Compare commits

..

No commits in common. "e91c70880bc67ae9871e14e3049e8c1f0b445746" and "ded3617fc69cbaf9874797c3ad08f2323bcfecdd" have entirely different histories.

16 changed files with 151 additions and 4065 deletions

View File

@ -18,17 +18,17 @@ composition and element sizes on fixed size pages without manual intervention
is a hard problem that LaTeX is very capable of.
## Example outputs
The following documents are generated by [tests/test_rendering_example1_doc.py](tests/test_rendering_example1_doc.py):
The following documents are generated by [tests/test_rendering_example_doc.py](tests/test_rendering_example_doc.py):
- HTML: [test_html_render1.html](https://html-preview.github.io/?url=https://github.com/Nonannet/pyladoc/blob/main/tests/out/test_html_render1.html)
- PDF: [test_latex_render1.pdf](https://raw.githubusercontent.com/Nonannet/pyladoc/refs/heads/main/tests/out/test_latex_render1.pdf)
- HTML: [test_html_render.html](https://html-preview.github.io/?url=https://github.com/Nonannet/pyladoc/blob/main/tests/out/test_html_render.html)
- PDF: [test_latex_render.pdf](https://raw.githubusercontent.com/Nonannet/pyladoc/refs/heads/main/tests/out/test_LaTeX_render.pdf)
### Supported primitives
### Sported primitives
- Text (can be Markdown or HTML formatted)
- Headings
- Tables (Pandas, Markdown or HTML)
- Matplotlib figures
- LaTeX equations (Block or inline)
- LaTeX equations
- Named references for figures, tables and equation
### Key Features
@ -53,21 +53,12 @@ It is easy to use as the following example code shows:
```python
import pyladoc
import pandas as pd
doc = pyladoc.DocumentWriter()
doc.add_markdown("""
# Example
This is inline LaTeX: $$\\lambda$$
This is a LaTeX block with a number:
$$
\\label{eq:test1}
\\lambda_{\text{mix}} = \\sum_{i=1}^{n} \\frac{x_i \\lambda_i}{\\sum_{j=1}^{n} x_j \\Phi_{ij}}
$$
This is an example table. The table @table:pandas_example shows some random data.
This is an example. The @table:pandas_example shows some random data.
""")
some_data = {
@ -76,10 +67,9 @@ some_data = {
'Row3': ['12 g/km', '> 150 g/km', '110 g/km']
}
df = pd.DataFrame(some_data)
doc.add_table(df, 'This is a pandas example table', 'pandas_example')
dw.add_table(df, 'This is a pandas example table', 'pandas_example')
html_code = doc.to_html()
print(html_code)
doc.to_pdf('test.pdf')
```

View File

@ -1,6 +1,6 @@
[project]
name = "pyladoc"
version = "1.1.0"
version = "1.0.0"
authors = [
{ name="Nicolas Kruse", email="nicolas.kruse@nonan.net" },
]
@ -13,7 +13,8 @@ classifiers = [
"Operating System :: OS Independent",
]
dependencies = [
"markdown>=3.3.0"
"markdown>=3.3.0",
"beautifulsoup4>=4.9.1"
]
[project.optional-dependencies]
@ -40,6 +41,7 @@ where = ["src"]
[tool.setuptools.package-data]
pyladoc = ["templates/*"]
[tool.mypy]
files = ["src"]
strict = true

View File

@ -6,8 +6,7 @@ import re
import io
from . import latex
import pkgutil
from html.parser import HTMLParser
from io import StringIO
HTML_OUTPUT = 0
LATEX_OUTPUT = 1
@ -54,8 +53,23 @@ def _get_pkgutil_string(path: str) -> str:
def _markdown_to_html(text: str) -> str:
prep_text = re.sub(r'\u00A0', ' ', text) # non-breaking space
html_text = markdown.markdown(prep_text, extensions=['tables', 'fenced_code', 'def_list', 'abbr', 'sane_lists'])
return html_text
html = markdown.markdown(prep_text, extensions=['tables', 'fenced_code', 'def_list', 'abbr', 'sane_lists'])
return html.replace('<hr />', '<hr>')
def escape_html(text: str) -> str:
"""
Escapes special HTML characters in a given string.
Args:
text: The text to escape
Returns:
Escaped text save for inserting into HTML code
"""
ret = re.sub(r'\u00A0', '&nbsp;', text) # non-breaking space
ret = html.escape(ret)
return ' '.join(ret.strip().splitlines())
def _clean_svg(svg_text: str) -> str:
@ -126,21 +140,6 @@ def _save_figure(fig: Figure, buff: io.BytesIO, figure_format: FFormat, font_fam
fig.set_size_inches(old_size, None, False)
def escape_html(text: str) -> str:
"""
Escapes special HTML characters in a given string.
Args:
text: The text to escape
Returns:
Escaped text save for inserting into HTML code
"""
ret = re.sub(r'\u00A0', '&nbsp;', text) # non-breaking space
ret = html.escape(ret)
return ' '.join(ret.strip().splitlines())
def figure_to_string(fig: Figure,
figure_format: FFormat = 'svg',
font_family: str | None = None,
@ -187,7 +186,7 @@ def figure_to_string(fig: Figure,
def latex_to_figure(latex_code: str) -> Figure:
assert Figure, 'Matplotlib is required for rendering LaTeX expressions for HTML output.' # type:ignore[truthy-function]
assert Figure, 'Matplotlib is required for rendering LaTex expressions for HTML output.' # type:ignore[truthy-function]
fig, ax = plt.subplots()
ax.set_xticks([])
ax.set_yticks([])
@ -285,9 +284,6 @@ class DocumentWriter():
A class to create a document for exporting to HTML or LaTeX.
"""
def __init__(self) -> None:
"""
Initializes the DocumentWriter instance.
"""
self._doc: list[list[Callable[[], str]]] = []
self._fields: dict[str, DocumentWriter] = dict()
self._base64_svgs: bool = False
@ -306,105 +302,6 @@ class DocumentWriter():
self._item_count[ref_type] = current_index
return caption_prefix.format(current_index)
def _equation_embedding_reescaping(self, text: str) -> str:
"""
Convert $$-escaping of LaTeX blocks and inline expressions
to a HTML-style format: <latex>...</latex>.
"""
block_pattern = re.compile(
r'(^|\n)\s*\$\$\s*\n' # start delimiter on a line on its own
r'(?P<content>.*?)' # capture block content non-greedily
r'\n\s*\$\$\s*(\n|$)', # end delimiter on a line on its own
re.DOTALL | re.MULTILINE
)
def block_repl(match: re.Match[str]) -> str:
content = match.group("content").strip()
latex_label: str = ''
label_pattern = re.compile(r'^\\label\{([^}]+)\}\s*\n?')
label_match = label_pattern.match(content)
if label_match:
latex_label = label_match.group(1)
# Remove the label command from the content.
content = content[label_match.end():].lstrip()
if latex_label and ':' in latex_label:
parts = latex_label.split(':')
ref_type = parts[0]
ref_id = parts[1]
caption = self._add_item(ref_id, ref_type, '({})')
return (f'\n<latex type="block" ref_type="{ref_type}"'
f' ref_id="{ref_id}" caption="{caption}">{content}</latex>\n')
else:
return f'\n<latex type="block">{content}</latex>\n'
result = block_pattern.sub(block_repl, text)
inline_pattern = re.compile(r'\$\$(.+?)\$\$')
def inline_repl(match: re.Match[str]) -> str:
content = match.group(1)
return f'<latex>{content}</latex>'
return inline_pattern.sub(inline_repl, result)
def _get_equation_html(self, latex_equation: str, caption: str, block: bool = False) -> str:
fig = latex_to_figure(latex_equation)
if block:
ret = ('<div class="equation-container">'
'<div class="equation">%s</div>'
'<div class="equation-number">%s</div></div>') % (
figure_to_string(fig, self._figure_format, base64=self._base64_svgs),
caption)
else:
ret = '<span class="inline-equation">' + figure_to_string(fig, self._figure_format, base64=self._base64_svgs) + '</span>'
plt.close(fig)
return ret
def _html_post_processing(self, html_code: str) -> str:
"""
"""
class HTMLPostProcessor(HTMLParser):
def __init__(self, document_writer: 'DocumentWriter') -> None:
super().__init__()
self.modified_html = StringIO()
self.in_latex: bool = False
self.eq_caption: str = ''
self.block: bool = False
self.dw = document_writer
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
if tag == 'hr':
self.modified_html.write(f"<{tag}>")
elif tag == 'latex':
self.in_latex = True
attr_dict = {k: v if v else '' for k, v in attrs}
self.eq_caption = attr_dict.get('caption', '')
self.block = attr_dict.get('type') == 'block'
elif not self.in_latex:
tag_text = self.get_starttag_text()
if tag_text:
self.modified_html.write(tag_text)
def handle_data(self, data: str) -> None:
if self.in_latex:
self.modified_html.write(
self.dw._get_equation_html(data, self.eq_caption, self.block))
else:
self.modified_html.write(data)
def handle_endtag(self, tag: str) -> None:
if tag == 'latex':
self.in_latex = False
else:
self.modified_html.write(f"</{tag}>")
parser = HTMLPostProcessor(self)
parser.feed(html_code)
return parser.modified_html.getvalue()
def new_field(self, name: str) -> 'DocumentWriter':
new_dwr = _create_document_writer()
self._fields[name] = new_dwr
@ -416,28 +313,14 @@ class DocumentWriter():
def add_diagram(self, fig: Figure, caption: str = '', ref_id: str = '',
prefix_pattern: str = 'Figure {}: ', ref_type: str = 'fig',
centered: bool = True) -> None:
"""
Adds a diagram to the document.
Args:
fig: The figure to add (matplotlib figure)
caption: The caption for the figure
ref_id: If provided, the figure can be referenced by this string
prefix_pattern: A custom string for the caption prefix, {} will
be replaced by the figure number
ref_type: The type of reference. Each type (e.g., 'fig', 'table')
has an individual numbering
centered: Whether to center the figure in LaTeX output
"""
caption_prefix = self._add_item(ref_id, ref_type, prefix_pattern)
def render_to_html() -> str:
caption_prefix = self._add_item(ref_id, ref_type, prefix_pattern)
return '<div class="figure">%s%s</div>' % (
figure_to_string(fig, self._figure_format, base64=self._base64_svgs, scale=self._fig_scale),
'<br>' + caption_prefix + escape_html(caption) if caption else '')
def render_to_latex() -> str:
self._add_item(ref_id, ref_type, prefix_pattern)
return '\\begin{figure}%s\n%s\n\\caption{%s}\n%s\\end{figure}' % (
'\n\\centering' if centered else '',
figure_to_string(fig, 'pgf', self._font_family, scale=self._fig_scale),
@ -448,41 +331,26 @@ class DocumentWriter():
def add_table(self, table: Table, caption: str = '', ref_id: str = '',
prefix_pattern: str = 'Table {}: ', ref_type: str = 'table', centered: bool = True) -> None:
"""
Adds a table to the document.
Args:
table: The table to add (pandas DataFrame or Styler)
caption: The caption for the table
ref_id: If provided, the table can be referenced by this string
prefix_pattern: A custom string for the caption prefix, {} will
be replaced by the table number
ref_type: The type of reference. Each type (e.g., 'fig', 'table')
has an individual numbering
centered: Whether to center the table in LaTeX output
"""
assert Table and isinstance(table, Table), 'Table has to be a pandas DataFrame oder DataFrame Styler'
caption_prefix = self._add_item(ref_id, ref_type, prefix_pattern)
styler = table if isinstance(table, Styler) else getattr(table, 'style', None)
assert isinstance(styler, Styler), 'Jinja2 package is required for rendering tables'
def render_to_html() -> str:
caption_prefix = self._add_item(ref_id, ref_type, prefix_pattern)
html_string = styler.to_html(table_uuid=ref_id, caption=caption_prefix + escape_html(caption))
return re.sub(r'<style.*?>.*?</style>', '', html_string, flags=re.DOTALL)
def render_to_latex() -> str:
self._add_item(ref_id, ref_type, prefix_pattern)
ref_label = latex.normalize_label_text(ref_type + ':' + ref_id)
if self._table_renderer == 'pandas':
return styler.to_latex(
label=ref_label,
label=latex.normalize_label_text(ref_type + ':' + ref_id),
hrules=True,
convert_css=True,
siunitx=True,
caption=latex.escape_text(caption),
position_float='centering' if centered else None)
else:
return latex.render_pandas_styler_table(styler, caption, ref_label, centered)
return latex.render_pandas_styler_table(styler, caption, ref_type + ':' + ref_id, centered)
self._doc.append([render_to_html, render_to_latex])
@ -579,14 +447,21 @@ class DocumentWriter():
ref_id: If provided, the equation is displayed with
a number and can be referenced by the ref_id
"""
caption = self._add_item(ref_id, ref_type, '({})')
def render_to_html() -> str:
caption = self._add_item(ref_id, ref_type, '({})')
return self._get_equation_html(latex_equation, caption)
fig = latex_to_figure(latex_equation)
return ('<div class="equation-container"><div class="equation">%s</div>'
'<div class="equation-number">%s</div></div>') % (
figure_to_string(fig, self._figure_format, base64=self._base64_svgs),
caption)
def render_to_latex() -> str:
self._add_item(ref_id, ref_type, '')
return latex.get_equation_code(latex_equation, ref_type, ref_id)
if ref_id:
return '\\begin{equation}\\label{%s:%s}%s\\end{equation}' % (
ref_type, ref_id, latex_equation)
else:
return '\\[%s\\]' % latex_equation
self._doc.append([render_to_html, render_to_latex])
@ -601,16 +476,14 @@ class DocumentWriter():
norm_text = _normalize_text_indent(str(text))
def render_to_html() -> str:
html = self._html_post_processing(_markdown_to_html(self._equation_embedding_reescaping(norm_text)))
html = _markdown_to_html(norm_text)
if section_class:
return '<div class="' + section_class + '">' + html + '</div>'
else:
return html
def render_to_latex() -> str:
html = _markdown_to_html(
self._equation_embedding_reescaping(norm_text))
return latex.from_html(html)
return latex.from_html(render_to_html())
self._doc.append([render_to_html, render_to_latex])
@ -672,7 +545,7 @@ class DocumentWriter():
If no path is provided a default template is used.
Returns:
True if the PDF file was successfully created
True if the PDF was successfully created
"""
latex_code = inject_to_template(self.to_latex(font_family, table_renderer),
latex_template_path,

View File

@ -1,5 +1,6 @@
import bs4
from html.parser import HTMLParser
from typing import Generator, Any
from typing import Iterator, Generator, Any
from pandas.io.formats.style import Styler
import re
import os
@ -15,8 +16,8 @@ def basic_formatter(value: Any) -> str:
def to_ascii(text: str) -> str:
"""
Replaces/escapes often used unicode characters in LaTeX code or text
with its LaTeX ascii equivalents.
Replaces/escapes often used unicode characters in latex code or text
with its LaTex ascii equivalents.
Args:
text: The text to convert.
@ -82,25 +83,6 @@ def escape_text(text: str) -> str:
return ''.join(ret)
def get_equation_code(equation: str, ref_id: str, ref_type: str, block: bool = False) -> str:
"""
Converts an equation string to LaTeX code.
Args:
equation: The LaTeX equation string.
ref_id: The reference ID for the equation.
ref_type: The type of reference (e.g., 'eq', 'fig', etc.).
"""
if block:
if ref_id:
return '\\begin{equation}\\label{%s:%s}%s\\end{equation}' % (
normalize_label_text(ref_type), normalize_label_text(ref_id), equation)
else:
return '\\[%s\\]' % equation
else:
return '\\(%s\\)' % equation
def render_pandas_styler_table(df_style: Styler, caption: str = '', label: str = '', centering: bool = True) -> str:
"""
Converts a pandas Styler object to LaTeX table.
@ -150,6 +132,63 @@ def render_pandas_styler_table(df_style: Styler, caption: str = '', label: str =
return ''.join(str_list)
def from_html_old(html_code: str) -> str:
"""
Converts HTML code to LaTeX code.
Args:
html_code: The HTML code to convert.
Returns:
The LaTeX code.
"""
root = bs4.BeautifulSoup(html_code, 'html.parser')
html_to_latex = {
'strong': ('\\textbf{', '}'),
'b': ('\\textbf{', '}'),
'em': ('\\emph{', '}'),
'i': ('\\emph{', '}'),
'p': ('', '\n\n'),
'h1': ('\\section{', '}'),
'h2': ('\\subsection{', '}'),
'h3': ('\\subsubsection{', '}'),
'ul': ('\\begin{itemize}', '\\end{itemize}'),
'ol': ('\\begin{enumerate}', '\\end{enumerate}'),
'li': ('\\item ', ''),
'latex_eq': ('\\[', '\\]'),
}
def handle_table(table: bs4.element.Tag) -> str:
rows = table.find_all('tr')
latex_table: str = ''
for row in rows:
assert isinstance(row, bs4.element.Tag), 'HTML table not valid'
cells = row.find_all(['th', 'td'])
if not latex_table:
latex_table = "\\begin{tabular}{|" + "|".join(['l'] * len(cells)) + "|}\\toprule\n"
else:
latex_table += " & ".join(escape_text(cell.get_text(strip=True)) for cell in cells) + " \\\\\n"
latex_table += "\\bottomrule\n\\end{tabular}"
return latex_table
def parse_node(element: bs4.element.Tag) -> Iterator[str]:
prefix, post = html_to_latex.get(element.name, ('', ''))
yield prefix
for c in element.children:
if isinstance(c, bs4.element.Tag):
if c.name == 'table':
yield handle_table(c)
else:
yield from parse_node(c)
else:
yield escape_text(c.text)
yield post
return ''.join(parse_node(root))
def from_html(html_code: str) -> str:
"""
Converts HTML code to LaTeX code using HTMLParser.
@ -182,11 +221,8 @@ def from_html(html_code: str) -> str:
self.column_alignment = ''
self.midrule_flag = False
self.header_flag = False
self.attr_dict: dict[str, str] = {}
self.equation_flag = False
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
self.attr_dict = {k: v if v else '' for k, v in attrs}
if tag in html_to_latex:
prefix, _ = html_to_latex[tag]
self.latex_code.append(prefix)
@ -198,18 +234,15 @@ def from_html(html_code: str) -> str:
elif tag == 'tr':
self.column_alignment = ''
elif tag in ['th', 'td']:
if 'right' in self.attr_dict.get('style', ''):
style = [v for k, v in attrs if k == 'style']
if style and style[0] and 'right' in style[0]:
self.column_alignment += 'r'
else:
self.column_alignment += 'l'
elif tag == 'a':
href = self.attr_dict.get('href')
href = [v for k, v in attrs if k == 'href']
assert href, 'Link href attribute is missing'
self.latex_code.append(f"\\href{{{href}}}{{")
elif tag == 'hr':
self.latex_code.append("\n\n\\noindent\\rule[0.5ex]{\\linewidth}{1pt}\n\n")
elif tag == 'latex':
self.equation_flag = True
self.latex_code.append(f"\\href{{{href[0]}}}{{")
def handle_endtag(self, tag: str) -> None:
if tag in html_to_latex:
@ -233,16 +266,9 @@ def from_html(html_code: str) -> str:
self.latex_code.append(" & ")
elif tag == 'a':
self.latex_code.append("}")
elif tag == 'latex':
self.equation_flag = False
def handle_data(self, data: str) -> None:
if self.equation_flag:
block = self.attr_dict.get('type') == 'block'
ref_id = self.attr_dict.get('ref_id', '')
ref_type = self.attr_dict.get('ref_type', 'eq')
self.latex_code.append(get_equation_code(data, ref_id, ref_type, block))
elif data.strip():
if data.strip():
self.latex_code.append(escape_text(data))
parser = LaTeXHTMLParser()

View File

@ -43,17 +43,13 @@
text-align: center;
}
.equation svg {
div svg {
margin-left: -5%;
max-width: 110%;
height: auto;
object-fit: contain;
}
.inline-equation svg {
vertical-align: middle;
}
.equation-container {
display: flex;
justify-content: space-between;

View File

@ -43,17 +43,13 @@
text-align: center;
}
.equation svg {
div svg {
margin-left: -5%;
max-width: 110%;
height: auto;
object-fit: contain;
}
.inline-equation svg {
vertical-align: middle;
}
.equation-container {
display: flex;
justify-content: space-between;
@ -196,9 +192,9 @@
</tr>
</tbody>
</table>
<hr></hr>
<hr>
<h1>Equations</h1>
<p>This line represents a reference to the equation 1.</p><span class="inline-equation"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="102.120397pt" height="34.4322pt" viewBox="0 0 102.120397 34.4322" xmlns="http://www.w3.org/2000/svg" version="1.1">
<p>This line represents a reference to the equation 1.</p><div class="equation-container"><div class="equation"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="102.120397pt" height="34.4322pt" viewBox="0 0 102.120397 34.4322" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<style type="text/css">*{stroke-linejoin: round; stroke-linecap: butt}</style>
@ -474,7 +470,7 @@ z
</g>
</g>
</svg>
</span><div class="figure"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="460.8pt" height="345.6pt" viewBox="0 0 460.8 345.6" xmlns="http://www.w3.org/2000/svg" version="1.1">
</div><div class="equation-number">(1)</div></div><div class="figure"><svg xmlns:xlink="http://www.w3.org/1999/xlink" width="460.8pt" height="345.6pt" viewBox="0 0 460.8 345.6" xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<style type="text/css">*{stroke-linejoin: round; stroke-linecap: butt}</style>
@ -503,7 +499,7 @@ L 142.181053 307.584
L 142.181053 206.208
L 73.832727 206.208
z
" clip-path="url(#p8886bfdb0f)" style="fill: #d62728"/>
" clip-path="url(#p69260dc8d6)" style="fill: #d62728"/>
</g>
<g id="patch_4">
<path d="M 159.268134 307.584
@ -511,7 +507,7 @@ L 227.616459 307.584
L 227.616459 54.144
L 159.268134 54.144
z
" clip-path="url(#p8886bfdb0f)" style="fill: #1f77b4"/>
" clip-path="url(#p69260dc8d6)" style="fill: #1f77b4"/>
</g>
<g id="patch_5">
<path d="M 244.703541 307.584
@ -519,7 +515,7 @@ L 313.051866 307.584
L 313.051866 231.552
L 244.703541 231.552
z
" clip-path="url(#p8886bfdb0f)" style="fill: #d62728"/>
" clip-path="url(#p69260dc8d6)" style="fill: #d62728"/>
</g>
<g id="patch_6">
<path d="M 330.138947 307.584
@ -527,18 +523,18 @@ L 398.487273 307.584
L 398.487273 168.192
L 330.138947 168.192
z
" clip-path="url(#p8886bfdb0f)" style="fill: #ff7f0e"/>
" clip-path="url(#p69260dc8d6)" style="fill: #ff7f0e"/>
</g>
<g id="matplotlib.axis_1">
<g id="xtick_1">
<g id="line2d_1">
<defs>
<path id="m5bc4660a75" d="M 0 0
<path id="m0a989fc6c9" d="M 0 0
L 0 3.5
" style="stroke: #000000; stroke-width: 0.8"/>
</defs>
<g>
<use xlink:href="#m5bc4660a75" x="108.00689" y="307.584" style="stroke: #000000; stroke-width: 0.8"/>
<use xlink:href="#m0a989fc6c9" x="108.00689" y="307.584" style="stroke: #000000; stroke-width: 0.8"/>
</g>
</g>
<g id="text_1">
@ -648,7 +644,7 @@ z
<g id="xtick_2">
<g id="line2d_2">
<g>
<use xlink:href="#m5bc4660a75" x="193.442297" y="307.584" style="stroke: #000000; stroke-width: 0.8"/>
<use xlink:href="#m0a989fc6c9" x="193.442297" y="307.584" style="stroke: #000000; stroke-width: 0.8"/>
</g>
</g>
<g id="text_2">
@ -753,7 +749,7 @@ z
<g id="xtick_3">
<g id="line2d_3">
<g>
<use xlink:href="#m5bc4660a75" x="278.877703" y="307.584" style="stroke: #000000; stroke-width: 0.8"/>
<use xlink:href="#m0a989fc6c9" x="278.877703" y="307.584" style="stroke: #000000; stroke-width: 0.8"/>
</g>
</g>
<g id="text_3">
@ -813,7 +809,7 @@ z
<g id="xtick_4">
<g id="line2d_4">
<g>
<use xlink:href="#m5bc4660a75" x="364.31311" y="307.584" style="stroke: #000000; stroke-width: 0.8"/>
<use xlink:href="#m0a989fc6c9" x="364.31311" y="307.584" style="stroke: #000000; stroke-width: 0.8"/>
</g>
</g>
<g id="text_4">
@ -909,12 +905,12 @@ z
<g id="ytick_1">
<g id="line2d_5">
<defs>
<path id="mb5327dd54d" d="M 0 0
<path id="m9bab964a69" d="M 0 0
L -3.5 0
" style="stroke: #000000; stroke-width: 0.8"/>
</defs>
<g>
<use xlink:href="#mb5327dd54d" x="57.6" y="307.584" style="stroke: #000000; stroke-width: 0.8"/>
<use xlink:href="#m9bab964a69" x="57.6" y="307.584" style="stroke: #000000; stroke-width: 0.8"/>
</g>
</g>
<g id="text_5">
@ -950,7 +946,7 @@ z
<g id="ytick_2">
<g id="line2d_6">
<g>
<use xlink:href="#mb5327dd54d" x="57.6" y="256.896" style="stroke: #000000; stroke-width: 0.8"/>
<use xlink:href="#m9bab964a69" x="57.6" y="256.896" style="stroke: #000000; stroke-width: 0.8"/>
</g>
</g>
<g id="text_6">
@ -990,7 +986,7 @@ z
<g id="ytick_3">
<g id="line2d_7">
<g>
<use xlink:href="#mb5327dd54d" x="57.6" y="206.208" style="stroke: #000000; stroke-width: 0.8"/>
<use xlink:href="#m9bab964a69" x="57.6" y="206.208" style="stroke: #000000; stroke-width: 0.8"/>
</g>
</g>
<g id="text_7">
@ -1025,7 +1021,7 @@ z
<g id="ytick_4">
<g id="line2d_8">
<g>
<use xlink:href="#mb5327dd54d" x="57.6" y="155.52" style="stroke: #000000; stroke-width: 0.8"/>
<use xlink:href="#m9bab964a69" x="57.6" y="155.52" style="stroke: #000000; stroke-width: 0.8"/>
</g>
</g>
<g id="text_8">
@ -1071,7 +1067,7 @@ z
<g id="ytick_5">
<g id="line2d_9">
<g>
<use xlink:href="#mb5327dd54d" x="57.6" y="104.832" style="stroke: #000000; stroke-width: 0.8"/>
<use xlink:href="#m9bab964a69" x="57.6" y="104.832" style="stroke: #000000; stroke-width: 0.8"/>
</g>
</g>
<g id="text_9">
@ -1126,7 +1122,7 @@ z
<g id="ytick_6">
<g id="line2d_10">
<g>
<use xlink:href="#mb5327dd54d" x="57.6" y="54.144" style="stroke: #000000; stroke-width: 0.8"/>
<use xlink:href="#m9bab964a69" x="57.6" y="54.144" style="stroke: #000000; stroke-width: 0.8"/>
</g>
</g>
<g id="text_10">
@ -1457,7 +1453,7 @@ z
</g>
</g>
<defs>
<clipPath id="p8886bfdb0f">
<clipPath id="p69260dc8d6">
<rect x="57.6" y="41.472" width="357.12" height="266.112"/>
</clipPath>
</defs>

File diff suppressed because it is too large Load Diff

View File

@ -1,613 +0,0 @@
\section{Thermal Conductivity of Mixtures}
The determination of the thermal conductivity of gas mixtures is a central aspect of modeling
transport phenomena, particularly in high-temperature and high-pressure processes. Among the
most established approaches is the empirical equation introduced by Wassiljewa, which was
subsequently refined by Mason and Saxena to improve its applicability to multicomponent systems.
This model offers a reliable means of estimating the thermal conductivity of gas mixtures based
on the properties of the pure components and their molar interactions.
The thermal conductivity of a gas mixture, denoted by \(\lambda_{\text{mix}}\), can expressed as
shown in equation \ref{eq:lambda-mixture}.
\begin{equation}\label{eq:lambda-mixture}\lambda_{ ext{mix}} = \sum_{i=1}^{n} \frac{x_i \lambda_i}{\sum_{j=1}^{n} x_j \Phi_{ij}}\end{equation}
In this equation, \(x_i\) represents the molar fraction of component \(i\) within the mixture,
while \(\lambda_i\) denotes the thermal conductivity of the pure substance \(i\). The denominator
contains the interaction parameter \(\Phi_{ij}\), which describes the influence of component
\(j\) on the transport properties of component \(i\).
The interaction parameter \(\Phi_{ij}\) is given by the relation shown in equation \ref{eq:interaction-parameter}.
\begin{equation}\label{eq:interaction-parameter}\Phi_{ij} = \frac{1}{\sqrt{8}} \left(1 + \frac{M_i}{M_j} \right)^{-1/2} \left[ 1 + \left( \frac{\lambda_i}{\lambda_j} \right)^{1/2} \left( \frac{M_j}{M_i} \right)^{1/4} \right]^2\end{equation}
Here, \(M_i\) and \(M_j\) are the molar masses of the components \(i\) and \(j\), respectively.
Molar masses and thermal conductivity of the pure substances are listed in table \ref{table:gas-probs}.
The structure of this expression illustrates the nonlinear dependence of the interaction term on
both the molar mass ratio and the square root of the conductivity ratio of the involved species.
\begin{table}
\centering
\caption{Properties of some gases}
\label{table:gas-probs}
\begin{tabular}{lSS}
\toprule
\text{Gas} & \text{Molar mass in g/mol} & \text{Thermal conductivity in W/m/K} \\
\midrule
H2 & 2.016 & 0.1805 \\
O2 & 32.00 & 0.0263 \\
N2 & 28.02 & 0.0258 \\
CO2 & 44.01 & 0.0166 \\
CH4 & 16.04 & 0.0341 \\
Ar & 39.95 & 0.0177 \\
He & 4.0026 & 0.1513 \\
\bottomrule
\end{tabular}
\end{table}This formulation acknowledges that the transport properties of a gas mixture are not a simple
linear combination of the individual conductivities. Rather, they are governed by intermolecular
interactions, which affect the energy exchange and diffusion behavior of each component. These
interactions are particularly significant at elevated pressures or in cases where the gas components
exhibit widely differing molecular masses or transport properties.
The equation proposed by Wassiljewa and refined by Mason and Saxena assumes that binary interactions
dominate the behavior of the mixture, while higher-order (three-body or more) interactions are
neglected. It also presumes that the gases approximate ideal behavior, although in practical
applications, moderate deviations from ideality are tolerated without significant loss of accuracy.
In figure \ref{fig:mixture} the resulting thermal conductivity of an H2/CO2-mixture is shown.
\begin{figure}
\centering
\begingroup%
\makeatletter%
\begin{pgfpicture}%
\pgfpathrectangle{\pgfpointorigin}{\pgfqpoint{6.400000in}{4.800000in}}%
\pgfusepath{use as bounding box, clip}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetmiterjoin%
\definecolor{currentfill}{rgb}{1.000000,1.000000,1.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.000000pt}%
\definecolor{currentstroke}{rgb}{1.000000,1.000000,1.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfpathmoveto{\pgfqpoint{0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{6.400000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{6.400000in}{4.800000in}}%
\pgfpathlineto{\pgfqpoint{0.000000in}{4.800000in}}%
\pgfpathlineto{\pgfqpoint{0.000000in}{0.000000in}}%
\pgfpathclose%
\pgfusepath{fill}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetmiterjoin%
\definecolor{currentfill}{rgb}{1.000000,1.000000,1.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.000000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetstrokeopacity{0.000000}%
\pgfsetdash{}{0pt}%
\pgfpathmoveto{\pgfqpoint{0.800000in}{0.528000in}}%
\pgfpathlineto{\pgfqpoint{5.760000in}{0.528000in}}%
\pgfpathlineto{\pgfqpoint{5.760000in}{4.224000in}}%
\pgfpathlineto{\pgfqpoint{0.800000in}{4.224000in}}%
\pgfpathlineto{\pgfqpoint{0.800000in}{0.528000in}}%
\pgfpathclose%
\pgfusepath{fill}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{0.000000in}{-0.048611in}}{\pgfqpoint{0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{0.000000in}{-0.048611in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{1.025455in}{0.528000in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=1.025455in,y=0.430778in,,top]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}0}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{0.000000in}{-0.048611in}}{\pgfqpoint{0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{0.000000in}{-0.048611in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{1.927273in}{0.528000in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=1.927273in,y=0.430778in,,top]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}20}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{0.000000in}{-0.048611in}}{\pgfqpoint{0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{0.000000in}{-0.048611in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{2.829091in}{0.528000in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=2.829091in,y=0.430778in,,top]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}40}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{0.000000in}{-0.048611in}}{\pgfqpoint{0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{0.000000in}{-0.048611in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{3.730909in}{0.528000in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=3.730909in,y=0.430778in,,top]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}60}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{0.000000in}{-0.048611in}}{\pgfqpoint{0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{0.000000in}{-0.048611in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{4.632727in}{0.528000in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=4.632727in,y=0.430778in,,top]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}80}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{0.000000in}{-0.048611in}}{\pgfqpoint{0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{0.000000in}{-0.048611in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{5.534545in}{0.528000in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=5.534545in,y=0.430778in,,top]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}100}}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=3.280000in,y=0.240809in,,top]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}H2 molar fraction / %}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{-0.048611in}{0.000000in}}{\pgfqpoint{-0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{-0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{-0.048611in}{0.000000in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{0.800000in}{0.868203in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=0.305168in, y=0.815441in, left, base]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}0.025}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{-0.048611in}{0.000000in}}{\pgfqpoint{-0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{-0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{-0.048611in}{0.000000in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{0.800000in}{1.380710in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=0.305168in, y=1.327949in, left, base]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}0.050}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{-0.048611in}{0.000000in}}{\pgfqpoint{-0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{-0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{-0.048611in}{0.000000in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{0.800000in}{1.893218in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=0.305168in, y=1.840456in, left, base]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}0.075}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{-0.048611in}{0.000000in}}{\pgfqpoint{-0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{-0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{-0.048611in}{0.000000in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{0.800000in}{2.405725in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=0.305168in, y=2.352964in, left, base]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}0.100}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{-0.048611in}{0.000000in}}{\pgfqpoint{-0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{-0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{-0.048611in}{0.000000in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{0.800000in}{2.918233in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=0.305168in, y=2.865472in, left, base]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}0.125}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{-0.048611in}{0.000000in}}{\pgfqpoint{-0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{-0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{-0.048611in}{0.000000in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{0.800000in}{3.430741in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=0.305168in, y=3.377979in, left, base]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}0.150}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetbuttcap%
\pgfsetroundjoin%
\definecolor{currentfill}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetfillcolor{currentfill}%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfsys@defobject{currentmarker}{\pgfqpoint{-0.048611in}{0.000000in}}{\pgfqpoint{-0.000000in}{0.000000in}}{%
\pgfpathmoveto{\pgfqpoint{-0.000000in}{0.000000in}}%
\pgfpathlineto{\pgfqpoint{-0.048611in}{0.000000in}}%
\pgfusepath{stroke,fill}%
}%
\begin{pgfscope}%
\pgfsys@transformshift{0.800000in}{3.943248in}%
\pgfsys@useobject{currentmarker}{}%
\end{pgfscope}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=0.305168in, y=3.890487in, left, base]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}0.175}}%
\end{pgfscope}%
\begin{pgfscope}%
\definecolor{textcolor}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{textcolor}%
\pgfsetfillcolor{textcolor}%
\pgftext[x=0.249612in,y=2.376000in,,bottom,rotate=90.000000]{\color{textcolor}{\sffamily\fontsize{10.000000}{12.000000}\selectfont\catcode`\^=\active\def^{\ifmmode\sp\else\^{}\fi}\catcode`\%=\active\def%{\%}Thermal Conductivity / (W/m·K)}}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfpathrectangle{\pgfqpoint{0.800000in}{0.528000in}}{\pgfqpoint{4.960000in}{3.696000in}}%
\pgfusepath{clip}%
\pgfsetrectcap%
\pgfsetroundjoin%
\pgfsetlinewidth{1.505625pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfpathmoveto{\pgfqpoint{1.025455in}{0.696000in}}%
\pgfpathlineto{\pgfqpoint{1.071001in}{0.697319in}}%
\pgfpathlineto{\pgfqpoint{1.116547in}{0.698664in}}%
\pgfpathlineto{\pgfqpoint{1.162094in}{0.700036in}}%
\pgfpathlineto{\pgfqpoint{1.207640in}{0.701436in}}%
\pgfpathlineto{\pgfqpoint{1.253186in}{0.702865in}}%
\pgfpathlineto{\pgfqpoint{1.298733in}{0.704324in}}%
\pgfpathlineto{\pgfqpoint{1.344279in}{0.705814in}}%
\pgfpathlineto{\pgfqpoint{1.389826in}{0.707335in}}%
\pgfpathlineto{\pgfqpoint{1.435372in}{0.708889in}}%
\pgfpathlineto{\pgfqpoint{1.480918in}{0.710476in}}%
\pgfpathlineto{\pgfqpoint{1.526465in}{0.712098in}}%
\pgfpathlineto{\pgfqpoint{1.572011in}{0.713757in}}%
\pgfpathlineto{\pgfqpoint{1.617557in}{0.715452in}}%
\pgfpathlineto{\pgfqpoint{1.663104in}{0.717186in}}%
\pgfpathlineto{\pgfqpoint{1.708650in}{0.718960in}}%
\pgfpathlineto{\pgfqpoint{1.754197in}{0.720775in}}%
\pgfpathlineto{\pgfqpoint{1.799743in}{0.722632in}}%
\pgfpathlineto{\pgfqpoint{1.845289in}{0.724534in}}%
\pgfpathlineto{\pgfqpoint{1.890836in}{0.726482in}}%
\pgfpathlineto{\pgfqpoint{1.936382in}{0.728476in}}%
\pgfpathlineto{\pgfqpoint{1.981928in}{0.730520in}}%
\pgfpathlineto{\pgfqpoint{2.027475in}{0.732615in}}%
\pgfpathlineto{\pgfqpoint{2.073021in}{0.734763in}}%
\pgfpathlineto{\pgfqpoint{2.118567in}{0.736966in}}%
\pgfpathlineto{\pgfqpoint{2.164114in}{0.739226in}}%
\pgfpathlineto{\pgfqpoint{2.209660in}{0.741545in}}%
\pgfpathlineto{\pgfqpoint{2.255207in}{0.743926in}}%
\pgfpathlineto{\pgfqpoint{2.300753in}{0.746371in}}%
\pgfpathlineto{\pgfqpoint{2.346299in}{0.748883in}}%
\pgfpathlineto{\pgfqpoint{2.391846in}{0.751464in}}%
\pgfpathlineto{\pgfqpoint{2.437392in}{0.754118in}}%
\pgfpathlineto{\pgfqpoint{2.482938in}{0.756847in}}%
\pgfpathlineto{\pgfqpoint{2.528485in}{0.759656in}}%
\pgfpathlineto{\pgfqpoint{2.574031in}{0.762546in}}%
\pgfpathlineto{\pgfqpoint{2.619578in}{0.765523in}}%
\pgfpathlineto{\pgfqpoint{2.665124in}{0.768589in}}%
\pgfpathlineto{\pgfqpoint{2.710670in}{0.771749in}}%
\pgfpathlineto{\pgfqpoint{2.756217in}{0.775008in}}%
\pgfpathlineto{\pgfqpoint{2.801763in}{0.778370in}}%
\pgfpathlineto{\pgfqpoint{2.847309in}{0.781840in}}%
\pgfpathlineto{\pgfqpoint{2.892856in}{0.785423in}}%
\pgfpathlineto{\pgfqpoint{2.938402in}{0.789124in}}%
\pgfpathlineto{\pgfqpoint{2.983949in}{0.792951in}}%
\pgfpathlineto{\pgfqpoint{3.029495in}{0.796909in}}%
\pgfpathlineto{\pgfqpoint{3.075041in}{0.801005in}}%
\pgfpathlineto{\pgfqpoint{3.120588in}{0.805247in}}%
\pgfpathlineto{\pgfqpoint{3.166134in}{0.809642in}}%
\pgfpathlineto{\pgfqpoint{3.211680in}{0.814198in}}%
\pgfpathlineto{\pgfqpoint{3.257227in}{0.818926in}}%
\pgfpathlineto{\pgfqpoint{3.302773in}{0.823834in}}%
\pgfpathlineto{\pgfqpoint{3.348320in}{0.828933in}}%
\pgfpathlineto{\pgfqpoint{3.393866in}{0.834235in}}%
\pgfpathlineto{\pgfqpoint{3.439412in}{0.839752in}}%
\pgfpathlineto{\pgfqpoint{3.484959in}{0.845496in}}%
\pgfpathlineto{\pgfqpoint{3.530505in}{0.851484in}}%
\pgfpathlineto{\pgfqpoint{3.576051in}{0.857729in}}%
\pgfpathlineto{\pgfqpoint{3.621598in}{0.864249in}}%
\pgfpathlineto{\pgfqpoint{3.667144in}{0.871063in}}%
\pgfpathlineto{\pgfqpoint{3.712691in}{0.878191in}}%
\pgfpathlineto{\pgfqpoint{3.758237in}{0.885655in}}%
\pgfpathlineto{\pgfqpoint{3.803783in}{0.893479in}}%
\pgfpathlineto{\pgfqpoint{3.849330in}{0.901690in}}%
\pgfpathlineto{\pgfqpoint{3.894876in}{0.910317in}}%
\pgfpathlineto{\pgfqpoint{3.940422in}{0.919392in}}%
\pgfpathlineto{\pgfqpoint{3.985969in}{0.928951in}}%
\pgfpathlineto{\pgfqpoint{4.031515in}{0.939034in}}%
\pgfpathlineto{\pgfqpoint{4.077062in}{0.949685in}}%
\pgfpathlineto{\pgfqpoint{4.122608in}{0.960953in}}%
\pgfpathlineto{\pgfqpoint{4.168154in}{0.972893in}}%
\pgfpathlineto{\pgfqpoint{4.213701in}{0.985566in}}%
\pgfpathlineto{\pgfqpoint{4.259247in}{0.999042in}}%
\pgfpathlineto{\pgfqpoint{4.304793in}{1.013399in}}%
\pgfpathlineto{\pgfqpoint{4.350340in}{1.028727in}}%
\pgfpathlineto{\pgfqpoint{4.395886in}{1.045125in}}%
\pgfpathlineto{\pgfqpoint{4.441433in}{1.062710in}}%
\pgfpathlineto{\pgfqpoint{4.486979in}{1.081614in}}%
\pgfpathlineto{\pgfqpoint{4.532525in}{1.101991in}}%
\pgfpathlineto{\pgfqpoint{4.578072in}{1.124018in}}%
\pgfpathlineto{\pgfqpoint{4.623618in}{1.147903in}}%
\pgfpathlineto{\pgfqpoint{4.669164in}{1.173889in}}%
\pgfpathlineto{\pgfqpoint{4.714711in}{1.202263in}}%
\pgfpathlineto{\pgfqpoint{4.760257in}{1.233369in}}%
\pgfpathlineto{\pgfqpoint{4.805803in}{1.267615in}}%
\pgfpathlineto{\pgfqpoint{4.851350in}{1.305499in}}%
\pgfpathlineto{\pgfqpoint{4.896896in}{1.347625in}}%
\pgfpathlineto{\pgfqpoint{4.942443in}{1.394741in}}%
\pgfpathlineto{\pgfqpoint{4.987989in}{1.447778in}}%
\pgfpathlineto{\pgfqpoint{5.033535in}{1.507912in}}%
\pgfpathlineto{\pgfqpoint{5.079082in}{1.576651in}}%
\pgfpathlineto{\pgfqpoint{5.124628in}{1.655955in}}%
\pgfpathlineto{\pgfqpoint{5.170174in}{1.748426in}}%
\pgfpathlineto{\pgfqpoint{5.215721in}{1.857582in}}%
\pgfpathlineto{\pgfqpoint{5.261267in}{1.988306in}}%
\pgfpathlineto{\pgfqpoint{5.306814in}{2.147564in}}%
\pgfpathlineto{\pgfqpoint{5.352360in}{2.345643in}}%
\pgfpathlineto{\pgfqpoint{5.397906in}{2.598377in}}%
\pgfpathlineto{\pgfqpoint{5.443453in}{2.931436in}}%
\pgfpathlineto{\pgfqpoint{5.488999in}{3.389276in}}%
\pgfpathlineto{\pgfqpoint{5.534545in}{4.056000in}}%
\pgfusepath{stroke}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetrectcap%
\pgfsetmiterjoin%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfpathmoveto{\pgfqpoint{0.800000in}{0.528000in}}%
\pgfpathlineto{\pgfqpoint{0.800000in}{4.224000in}}%
\pgfusepath{stroke}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetrectcap%
\pgfsetmiterjoin%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfpathmoveto{\pgfqpoint{5.760000in}{0.528000in}}%
\pgfpathlineto{\pgfqpoint{5.760000in}{4.224000in}}%
\pgfusepath{stroke}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetrectcap%
\pgfsetmiterjoin%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfpathmoveto{\pgfqpoint{0.800000in}{0.528000in}}%
\pgfpathlineto{\pgfqpoint{5.760000in}{0.528000in}}%
\pgfusepath{stroke}%
\end{pgfscope}%
\begin{pgfscope}%
\pgfsetrectcap%
\pgfsetmiterjoin%
\pgfsetlinewidth{0.803000pt}%
\definecolor{currentstroke}{rgb}{0.000000,0.000000,0.000000}%
\pgfsetstrokecolor{currentstroke}%
\pgfsetdash{}{0pt}%
\pgfpathmoveto{\pgfqpoint{0.800000in}{4.224000in}}%
\pgfpathlineto{\pgfqpoint{5.760000in}{4.224000in}}%
\pgfusepath{stroke}%
\end{pgfscope}%
\end{pgfpicture}%
\makeatother%
\endgroup%
\caption{Thermal Conductivity of H2/CO2 mixtures}
\label{fig:mixture}
\end{figure}In engineering practice, the accurate determination of \(\lambda_{\text{mix}}\) is essential
for the prediction of heat transfer in systems such as membrane modules, chemical reactors, and
combustion chambers. In the context of membrane-based gas separation, for instance, the thermal
conductivity of the gas mixture influences the local temperature distribution, which in turn affects
both the permeation behavior and the structural stability of the membrane.
It is important to note that the calculated mixture conductivity reflects only the gas phase
behavior. In porous systems such as carbon membranes, additional effects must be considered.
These include the solid-phase thermal conduction through the membrane matrix, radiative transport
in pore channels at high temperatures, and transport in the Knudsen regime for narrow pores.
To account for these complexities, models based on effective medium theory, such as those of
Maxwell-Eucken or Bruggeman, are frequently employed. These models combine the conductivities of
individual phases (gas and solid) with geometrical factors that reflect the morphology of the
porous structure.
\noindent\rule[0.5ex]{\linewidth}{1pt}
Expanded by more or less sensible AI jabbering; based on: \href{https://doi.org/10.14279/depositonce-7390}{doi:10.14279/depositonce-7390}

Binary file not shown.

View File

@ -2,4 +2,4 @@
<p>Umlaute: ÖÄÜ öäü</p>
<p>Other: ß, €, @, $, %, ~, µ</p>
<p>Units: m³, cm²</p>
<p>Controll characters: <, >, ", ', &, |, /, \</p>
<p>Controll characters: &lt;, &gt;, ", ', &amp;, |, /, \</p>

View File

@ -2,7 +2,7 @@
unconditional branch instruction—often simply called the
“B” instruction—and how its 26bit immediate field (imm26)
is laid out and later relocated during linking.</p>
<hr></hr>
<hr>
<h2>Instruction Layout</h2>
<p>The unconditional branch in AArch64 is encoded in a 32bit
instruction. Its layout is as follows:</p>
@ -40,5 +40,5 @@ the full register width (typically 64 bits).</li>
</li>
<li>With a 26bit signed field thats effectively 28 bits
after the shift, the branch can cover a range
of approximately ±128 MB from the current instruction.</li>
of approximately ±128&nbsp;MB from the current instruction.</li>
</ul>

View File

@ -1,62 +0,0 @@
import pyladoc
def test_latex_embedding2():
test_input = pyladoc._normalize_text_indent("""
In this equation, $$x_i$$ represents the molar fraction of component $$i$$ within the mixture,
while $$\\lambda_i$$ denotes the thermal conductivity of the pure substance $$i$$. The denominator
contains the interaction parameter $$\\Phi_{ij}$$, which describes the influence of component
$$j$$ on the transport properties of component $$i$$.
The interaction parameter $$\\Phi_{ij}$$ is given by the relation shown in @eq:ExampleFormula2.
$$
\\label{eq:ExampleFormula2}
\\Phi_{ij} = \\frac{1}{\\sqrt{8}} \\left(1 + \\frac{M_i}{M_j} \\right)^{-1/2} \\left[ 1 + \\left( \\frac{\\lambda_i}{\\lambda_j} \\right)^{1/2} \\left( \\frac{M_j}{M_i} \\right)^{1/4} \\right]^2
$$
""")
expected_output = pyladoc._normalize_text_indent(r"""
In this equation, <latex>x_i</latex> represents the molar fraction of component <latex>i</latex> within the mixture,
while <latex>\lambda_i</latex> denotes the thermal conductivity of the pure substance <latex>i</latex>. The denominator
contains the interaction parameter <latex>\Phi_{ij}</latex>, which describes the influence of component
<latex>j</latex> on the transport properties of component <latex>i</latex>.
The interaction parameter <latex>\Phi_{ij}</latex> is given by the relation shown in @eq:ExampleFormula2.
<latex type="block" ref_type="eq" ref_id="ExampleFormula2" caption="(1)">\Phi_{ij} = \frac{1}{\sqrt{8}} \left(1 + \frac{M_i}{M_j} \right)^{-1/2} \left[ 1 + \left( \frac{\lambda_i}{\lambda_j} \right)^{1/2} \left( \frac{M_j}{M_i} \right)^{1/4} \right]^2</latex>
""")
dummy = pyladoc.DocumentWriter()
result_string = dummy._equation_embedding_reescaping(test_input)
print(result_string)
assert result_string == expected_output
def test_latex_embedding():
test_input = pyladoc._normalize_text_indent(r"""
# Test
$$
\label{eq:ExampleFormula2}
\Phi_{ij} = \frac{1}{\sqrt{8}}
$$
This $$i$$ is inline LaTeX.
""")
expected_output = pyladoc._normalize_text_indent(r"""
# Test
<latex type="block" ref_type="eq" ref_id="ExampleFormula2" caption="(1)">\Phi_{ij} = \frac{1}{\sqrt{8}}</latex>
This <latex>i</latex> is inline LaTeX.
""")
dummy = pyladoc.DocumentWriter()
result_string = dummy._equation_embedding_reescaping(test_input)
print(result_string)
assert result_string == expected_output
final_html = dummy._html_post_processing(pyladoc._markdown_to_html(result_string))
print('-- final_html --')
print(final_html)
assert '<h1>' in final_html and '<svg ' in final_html and '<div class="equation-number">' in final_html

View File

@ -1,31 +0,0 @@
import pyladoc
import pandas as pd
def test_readme_example():
doc = pyladoc.DocumentWriter()
doc.add_markdown("""
# Example
This is inline LaTeX: $$\\lambda$$
This is a LaTeX block with a number:
$$
\\label{eq:test1}
\\lambda_{\text{mix}} = \\sum_{i=1}^{n} \\frac{x_i \\lambda_i}{\\sum_{j=1}^{n} x_j \\Phi_{ij}}
$$
This is an example table. The table @table:pandas_example shows some random data.
""")
some_data = {
'Row1': ["Line1", "Line2", "Line3"],
'Row2': [120, 100, 110],
'Row3': ['12 g/km', '> 150 g/km', '110 g/km']
}
df = pd.DataFrame(some_data)
doc.add_table(df, 'This is a pandas example table', 'pandas_example')
html_code = doc.to_html()
print(html_code)
assert '<table' in html_code

View File

@ -1,176 +0,0 @@
import pyladoc
import matplotlib.pyplot as plt
import pandas as pd
import document_validation
import numpy as np
VALIDATE_HTML_CODE_ONLINE = False
WRITE_RESULT_FILES = True
def mason_saxena_k_mixture(x_h2):
"""
Calculate the thermal conductivity of a H2/CO2 gas mixture using the Mason and Saxena mixing rule.
The mixture thermal conductivity is computed as:
k_mix = Σ_i [ X_i * k_i / (Σ_j X_j * φ_ij) ]
with:
φ_ij = 1/8 * (1 + M_i/M_j)^(-0.5) * [ 1 + ( (k_i/k_j)**0.5 * (M_j/M_i)**0.25 ) ]^2
Parameters:
x_h2 (float or array-like): Mole fraction of H2 (from 0 to 1). The CO2 mole fraction is 1 - x_h2.
Returns:
float or array-like: Thermal conductivity of the mixture in W/m·K.
"""
# Pure gas properties (at room temperature, approx.)
k_h2 = 0.1805 # Thermal conductivity of H2 in W/mK
k_co2 = 0.0166 # Thermal conductivity of CO2 in W/mK
M_h2 = 2.016 # Molar mass of H2 in g/mol
M_co2 = 44.01 # Molar mass of CO2 in g/mol
# Define the phi_ij function according to Mason and Saxena.
def phi(k_i, k_j, M_i, M_j):
return (1 / np.sqrt(8)) * (1 + M_i / M_j) ** (-0.5) * (1 + ((k_i / k_j) ** 0.5 * (M_j / M_i) ** 0.25))**2
# Compute phi terms for the two species.
# For i = j the phi terms should be 1.
phi_h2_h2 = phi(k_h2, k_h2, M_h2, M_h2) # Should be 1
phi_h2_co2 = phi(k_h2, k_co2, M_h2, M_co2)
phi_co2_h2 = phi(k_co2, k_h2, M_co2, M_h2)
phi_co2_co2 = phi(k_co2, k_co2, M_co2, M_co2) # Should be 1
# Ensure we can perform vectorized operations.
x_h2 = np.array(x_h2)
x_co2 = 1 - x_h2
# Use the Mason-Saxena mixing rule:
# k_mix = X_H2 * k_H2 / (X_H2*φ_H2_H2 + X_CO2*φ_H2_CO2) +
# X_CO2 * k_CO2 / (X_CO2*φ_CO2_CO2 + X_H2*φ_CO2_H2)
k_mix = (x_h2 * k_h2 / (x_h2 * phi_h2_h2 + x_co2 * phi_h2_co2)) + \
(x_co2 * k_co2 / (x_co2 * phi_co2_co2 + x_h2 * phi_co2_h2))
return k_mix
def make_document():
doc = pyladoc.DocumentWriter()
doc.add_markdown("""
# Thermal Conductivity of Mixtures
The determination of the thermal conductivity of gas mixtures is a central aspect of modeling
transport phenomena, particularly in high-temperature and high-pressure processes. Among the
most established approaches is the empirical equation introduced by Wassiljewa, which was
subsequently refined by Mason and Saxena to improve its applicability to multicomponent systems.
This model offers a reliable means of estimating the thermal conductivity of gas mixtures based
on the properties of the pure components and their molar interactions.
The thermal conductivity of a gas mixture, denoted by $$\\lambda_{\\text{mix}}$$, can expressed as
shown in equation @eq:lambda_mixture.
$$
\\label{eq:lambda_mixture}
\\lambda_{\text{mix}} = \\sum_{i=1}^{n} \\frac{x_i \\lambda_i}{\\sum_{j=1}^{n} x_j \\Phi_{ij}}
$$
In this equation, $$x_i$$ represents the molar fraction of component $$i$$ within the mixture,
while $$\\lambda_i$$ denotes the thermal conductivity of the pure substance $$i$$. The denominator
contains the interaction parameter $$\\Phi_{ij}$$, which describes the influence of component
$$j$$ on the transport properties of component $$i$$.
The interaction parameter $$\\Phi_{ij}$$ is given by the relation shown in equation @eq:interaction_parameter.
$$
\\label{eq:interaction_parameter}
\\Phi_{ij} = \\frac{1}{\\sqrt{8}} \\left(1 + \\frac{M_i}{M_j} \\right)^{-1/2} \\left[ 1 + \\left( \\frac{\\lambda_i}{\\lambda_j} \\right)^{1/2} \\left( \\frac{M_j}{M_i} \\right)^{1/4} \\right]^2
$$
Here, $$M_i$$ and $$M_j$$ are the molar masses of the components $$i$$ and $$j$$, respectively.
Molar masses and thermal conductivity of the pure substances are listed in table @table:gas_probs.
The structure of this expression illustrates the nonlinear dependence of the interaction term on
both the molar mass ratio and the square root of the conductivity ratio of the involved species.
""")
# Table
data = {
"Gas": ["H2", "O2", "N2", "CO2", "CH4", "Ar", "He"],
"Molar mass in g/mol": ["2.016", "32.00", "28.02", "44.01", "16.04", "39.95", "4.0026"],
"Thermal conductivity in W/m/K": ["0.1805", "0.0263", "0.0258", "0.0166", "0.0341", "0.0177", "0.1513"]
}
df = pd.DataFrame(data)
doc.add_table(df.style.hide(axis="index"), 'Properties of some gases', 'gas_probs')
doc.add_markdown("""
This formulation acknowledges that the transport properties of a gas mixture are not a simple
linear combination of the individual conductivities. Rather, they are governed by intermolecular
interactions, which affect the energy exchange and diffusion behavior of each component. These
interactions are particularly significant at elevated pressures or in cases where the gas components
exhibit widely differing molecular masses or transport properties.
The equation proposed by Wassiljewa and refined by Mason and Saxena assumes that binary interactions
dominate the behavior of the mixture, while higher-order (three-body or more) interactions are
neglected. It also presumes that the gases approximate ideal behavior, although in practical
applications, moderate deviations from ideality are tolerated without significant loss of accuracy.
In figure @fig:mixture the resulting thermal conductivity of an H2/CO2-mixture is shown.""")
# Figure
x_h2_values = np.linspace(0, 1, 100)
k_mixture_values = mason_saxena_k_mixture(x_h2_values)
fig, ax = plt.subplots()
ax.set_xlabel("H2 molar fraction / %")
ax.set_ylabel("Thermal Conductivity / (W/m·K)")
ax.plot(x_h2_values * 100, k_mixture_values, color='black')
doc.add_diagram(fig, 'Thermal Conductivity of H2/CO2 mixtures', 'mixture')
doc.add_markdown("""
In engineering practice, the accurate determination of $$\\lambda_{\\text{mix}}$$ is essential
for the prediction of heat transfer in systems such as membrane modules, chemical reactors, and
combustion chambers. In the context of membrane-based gas separation, for instance, the thermal
conductivity of the gas mixture influences the local temperature distribution, which in turn affects
both the permeation behavior and the structural stability of the membrane.
It is important to note that the calculated mixture conductivity reflects only the gas phase
behavior. In porous systems such as carbon membranes, additional effects must be considered.
These include the solid-phase thermal conduction through the membrane matrix, radiative transport
in pore channels at high temperatures, and transport in the Knudsen regime for narrow pores.
To account for these complexities, models based on effective medium theory, such as those of
Maxwell-Eucken or Bruggeman, are frequently employed. These models combine the conductivities of
individual phases (gas and solid) with geometrical factors that reflect the morphology of the
porous structure.
---
Expanded by more or less sensible AI jabbering; based on: [doi:10.14279/depositonce-7390](https://doi.org/10.14279/depositonce-7390)
""")
return doc
def test_html_render():
doc = make_document()
html_code = doc.to_html()
document_validation.validate_html(html_code, VALIDATE_HTML_CODE_ONLINE)
if WRITE_RESULT_FILES:
with open('tests/out/test_html_render1.html', 'w', encoding='utf-8') as f:
f.write(pyladoc.inject_to_template(html_code, internal_template='templates/test_template.html'))
def test_latex_render():
doc = make_document()
if WRITE_RESULT_FILES:
with open('tests/out/test_html_render1.tex', 'w', encoding='utf-8') as f:
f.write(doc.to_latex())
assert doc.to_pdf('tests/out/test_latex_render1.pdf', font_family='serif')
if __name__ == '__main__':
test_html_render()
test_latex_render()

View File

@ -8,9 +8,9 @@ WRITE_RESULT_FILES = True
def make_document():
doc = pyladoc.DocumentWriter()
dw = pyladoc.DocumentWriter()
doc.add_markdown("""
dw.add_markdown("""
# Special characters
ö ä ü Ö Ä Ü ß @
@ -50,7 +50,7 @@ def make_document():
This line represents a reference to the equation @eq:test1.
""")
doc.add_equation(r'y = a + b * \sum_{i=0}^{\infty} a_i x^i', 'test1')
dw.add_equation(r'y = a + b * \sum_{i=0}^{\infty} a_i x^i', 'test1')
# Figure
fig, ax = plt.subplots()
@ -65,7 +65,7 @@ def make_document():
ax.set_title('Fruit supply by kind and color')
ax.legend(title='Fruit color')
doc.add_diagram(fig, 'Bar chart with individual bar colors')
dw.add_diagram(fig, 'Bar chart with individual bar colors')
# Table
mydataset = {
@ -79,9 +79,9 @@ def make_document():
}
df = pd.DataFrame(mydataset)
doc.add_table(df.style.hide(axis="index"), 'This is a example table', 'example1')
dw.add_table(df.style.hide(axis="index"), 'This is a example table', 'example1')
return doc
return dw
def test_html_render():
@ -91,7 +91,7 @@ def test_html_render():
document_validation.validate_html(html_code, VALIDATE_HTML_CODE_ONLINE)
if WRITE_RESULT_FILES:
with open('tests/out/test_html_render2.html', 'w', encoding='utf-8') as f:
with open('tests/out/test_html_render.html', 'w', encoding='utf-8') as f:
f.write(pyladoc.inject_to_template(html_code, internal_template='templates/test_template.html'))
@ -100,7 +100,7 @@ def test_latex_render():
# print(doc.to_latex())
assert doc.to_pdf('tests/out/test_latex_render2.pdf', font_family='serif')
assert doc.to_pdf('tests/out/test_latex_render.pdf', font_family='serif')
if __name__ == '__main__':