Plan B as per tohecz: I'm a security engineer at Facebook and this is my fault.

Properties of water and steam (IAPWS-SF95 formulation), enthalpy-entropy diagram, actually used by our students (and colleagues, from time to time).

Compiled with lualatex for memory reasons. I'll not post the code here, as it is quite a lot and wouldn't work on other computers anyway. That, of course, has a reason: The IAPWS-SF95 is not really easy to handle, so I wrote programs in C++ that output tables for the properties at a certain pressure, temperature, etc. This might have been possible with luatex, but I'm not really experienced in lua. I've added the tex code below.

The latex code reads in a table of iso lines that must be generated first, then calls the external binaries with appropriate command line arguments and reads back the resulting iso line tables. That takes about 45 minutes on a decent desktop PC, so I added an option not to regenerate all the data. Cosmetic runs now take only a few minutes.

Overview:

A close-up near the critical point:

You can see that some lines with constant steam quality (x) are cut off near the critical point, otherwise they would be to close to each other.

Some labels:

Extra labels or extended labels as you can see them above are also specified in the table that is read in first. Major and minor iso lines have different strength. The grid is quiet, gray. All glyphs have some white padding around them. I don't like the white spots appearing near the intersections of some lines, I haven't yet mastered that art (they are also present in the printed diagram, but not as prominent as on screen).

The layout is for A2 paper, I'm thinking about making an A0 version that starts at lower enthalpy/entropy. It would have a large empty area at the lower right that I'd fill with some table for looking up exact values.

Holding the real printed diagram in my hands with a real gray grid was really great. An older version of this diagram existed at our institute before, but we ran out of prints and it contained some wrong values. That was my motivation to create this one.

Thanks to tex sx - many of the tikz / pgfplots / pgfplotstable tricks I used in this diagram are actually yours!

EDIT: OK, as so many others have also posted their code I thought I'd just post mine as well, but without the C++ part.

mollier.tex (main file):

%\listfiles \documentclass{article} \usepackage[a2paper,landscape,margin=0.9cm]{geometry} \usepackage[latin1]{luainputenc} \usepackage[T1]{fontenc} \usepackage{sfmath} \usepackage{icomma} % german decimal separator in math mode \usepackage[ngerman]{babel} \usepackage[locale=DE]{siunitx} \usepackage[outline]{contour} \contourlength{0.5pt} \usepackage{color} \usepackage{tikz,pgfplots,pgfplotstable} \usetikzlibrary{intersections,calc} % \pgfplotsset{compat=1.5} \usepackage{etoolbox} % \usepackage{hyperref} % plotted entropy range \edef\smin{4000} \edef\smax{9200} \pgfmathsetmacro{\dsa}{500} % major tick size \pgfmathsetmacro{\dsb}{100} % intermediate tick size \pgfmathsetmacro{\dsc}{10} % minor tick size % plotted enthalpy range \edef\hmin{2000} \edef\hmax{3900} \pgfmathsetmacro{\dha}{500} % major tick size \pgfmathsetmacro{\dhl}{100} % label ticks size \pgfmathsetmacro{\dhb}{50} % intermediate tick size \pgfmathsetmacro{\dhc}{5} % minor tick size % min, critical, max pressure, critical temperature \edef\pmin{700} \edef\pCrit{22064000} \edef\pmax{10000e5} \edef\tCrit{373.946} % default number of points per plotted line \edef

Samples{500} \input{createTicks} \tikzset{minor grid style/.style={ultra thin,color=black!50}} \tikzset{intermediate grid style/.style={thin,color=black!50}} \tikzset{major grid style/.style={thin,color=black!50}} \tikzset{hidden plot/.style={draw=none}} \pgfplotsset{minor p plot/.style={black,very thin}} \pgfplotsset{major p plot/.style={black,semithick}} \pgfplotsset{minor T plot/.style={smooth,magenta,very thin}} \pgfplotsset{major T plot/.style={smooth,magenta,semithick}} \pgfplotsset{minor x plot/.style={smooth,black,very thin}} \pgfplotsset{major x plot/.style={smooth,black,semithick}} \tikzset{p plot label/.style={inner sep=1pt,outer sep=0pt,above=1pt,anchor=base,sloped,font={\footnotesize}}} \tikzset{t plot label/.style={inner sep=1pt,outer sep=0pt,above=1pt,anchor=base,sloped,font={\footnotesize}}} \tikzset{x plot label/.style={inner sep=1pt,outer sep=0pt,above=1pt,anchor=base,sloped,font={\footnotesize}}} \pgfplotstableset{input filter/.style={y expr=\thisrow{h}/1e3}} \sisetup{detect-all=true,parse-numbers=false} \pgfkeys{/pgf/number format/.cd,set thousands separator={},set decimal separator={,}} \pgfplotsset{mollier axis/.style={ xmin=\smin,xmax=\smax,width=52cm, ymin=\hmin,ymax=\hmax,height=38cm, scale only axis, major tick length={0pt}, minor tick length={0pt}, grid=none, xtick=\sLabelTicks, xticklabel={\pgfmathparse{\tick/1e3}

um{\pgfmathprintnumber{\pgfmathresult}}}, ytick=\hLabelTicks, yticklabel={\pgfmathparse{\tick}\pgfmathprintnumber{\pgfmathresult}}, }}

ewbool{createPTables}

ewbool{createTTables}

ewbool{createXTables} \setbool{createPTables}{false} \setbool{createTTables}{false} \setbool{createXTables}{false} \begin{document} \thispagestyle{empty} \input{createTables}

oindent\centering \begin{tikzpicture} \begin{axis}[mollier axis, axis x line*=top, axis y line*=right, ] \end{axis} \begin{axis}[mollier axis, xlabel={\textsf{spezifische Entropie $s$ in \si[per-mode=fraction]{\kilo\joule\per\kilogram\per\kelvin}}}, ylabel={\textsf{spezifische Enthalpie $h$ in \si[per-mode=fraction]{\kilo\joule\per\kilogram}}}, ] \input{drawGrid} % plots % plots are drawn using external data files created by createTables.tex % the data files don't need to be recreated in each run. \input{plotp} \input{plotT} \input{plotx} % labels % labels are placed by creating a path between 2 points on a plot (using intersections) % and then adding a node between these points. \input{placePLabels} \input{placeTLabels} \input{placeXLabels} % mark critical point % the critical point is at the end of the x=1 plot (or x=0) \filldraw (coord-x1000m-end) circle(2pt) node[ p plot label,right=2pt,font={\sffamily\footnotesize} ] {\contour{white}{K.P.}}; % title/info box \draw (rel axis cs:1,0) node[ draw=black,fill=white,above left=1em,align=left,font={\sffamily\footnotesize} ] { \begin{minipage}{7.3cm} \includegraphics[width=\textwidth,keepaspectratio]{Logo_mit_TUHH_deu_weiss.pdf}\\[1\baselineskip] \Huge Mollier $h$,$s$-Diagramm\\[2pt] \LARGE für Wasser, nach IAPWS-95 [1]\\[0.5\baselineskip] \large Christoph Redecker\\ Institut für Thermofluiddynamik\\ TU Hamburg-Harburg \end{minipage} }; % frame \draw[major grid style] (axis cs:\smin,\hmin) rectangle (axis cs: \smax,\hmax); \end{axis} % IAPWS reference \draw (current axis.below south east) node[outer sep=0pt,inner sep=0pt,left] { \footnotesize\sffamily \begin{minipage}{12.2cm} \begin{itemize} \item[{[1]}] IAPWS, \textit{Revised Release on the IAPWS Formulation 1995 for the Thermodynamic Properties of Ordinary Water Substance for General and Scientific Use} (2009). \texttt{http://www.iapws.org}. \end{itemize} \end{minipage} }; \draw (current axis.below south west) node[outer sep=0pt,inner sep=0pt,right] { \footnotesize\sffamily v 1.2, 23.\,10.\,2012 }; \end{tikzpicture} \end{document}

createTicks.tex :

\gdef\sMajorTicks{} { \pgfmathsetmacro{\ticks}{floor((\smax - \smin)/\dsa)+1} \def\tickSep{} \foreach

in {1,...,\ticks}% { \pgfmathsetmacro{\s}{\smin + (

-1)*\dsa}% \xdef\sMajorTicks{\sMajorTicks\tickSep\s} \xdef\tickSep{, } } } \let\sLabelTicks\sMajorTicks \gdef\sInterTicks{} { \pgfmathsetmacro{\ticks}{floor((\smax - \smin)/\dsb)+1} \def\tickSep{} \foreach

in {1,...,\ticks}% { \pgfmathsetmacro{\s}{\smin + (

-1)*\dsb}% \xdef\sInterTicks{\sInterTicks\tickSep\s} \xdef\tickSep{, } } } \gdef\sMinorTicks{} { \pgfmathsetmacro{\ticks}{floor((\smax - \smin)/\dsc)+1} \def\tickSep{} \foreach

in {1,...,\ticks}% { \pgfmathsetmacro{\s}{\smin + (

-1)*\dsc}% \xdef\sMinorTicks{\sMinorTicks\tickSep\s} \xdef\tickSep{, } } } \gdef\hMajorTicks{} { \pgfmathsetmacro{\ticks}{floor((\hmax - \hmin)/\dha)+1} \def\tickSep{} \foreach

in {1,...,\ticks}% { \pgfmathsetmacro{\h}{\hmin + (

-1)*\dha}% \xdef\hMajorTicks{\hMajorTicks\tickSep\h} \xdef\tickSep{, } } } \gdef\hInterTicks{} { \pgfmathsetmacro{\ticks}{floor((\hmax - \hmin)/\dhb)+1} \def\tickSep{} \foreach

in {1,...,\ticks}% { \pgfmathsetmacro{\h}{\hmin + (

-1)*\dhb}% \xdef\hInterTicks{\hInterTicks\tickSep\h} \xdef\tickSep{, } } } \gdef\hMinorTicks{} { \pgfmathsetmacro{\ticks}{floor((\hmax - \hmin)/\dhc)+1} \def\tickSep{} \foreach

in {1,...,\ticks}% { \pgfmathsetmacro{\h}{\hmin + (

-1)*\dhc}% \xdef\hMinorTicks{\hMinorTicks\tickSep\h} \xdef\tickSep{, } } } \gdef\hLabelTicks{} { \pgfmathsetmacro{\ticks}{floor((\hmax - \hmin)/\dhl)+1} \def\tickSep{} \foreach

in {1,...,\ticks}% { \pgfmathsetmacro{\h}{\hmin + (

-1)*\dhl}% \xdef\hLabelTicks{\hLabelTicks\tickSep\h} \xdef\tickSep{, } } }

createTables.tex

\pgfplotstableset{create on use/pBar/.style={create col/expr={\thisrow{p}*1e-5}}} \pgfplotstableset{create on use/pMPa/.style={create col/expr={\thisrow{p}*1e-6}}} \pgfplotstableset{create on use/xVal/.style={create col/expr={\thisrow{x}*1e-3}}} \pgfplotstableread[col sep=semicolon, columns/p/.style={string type}, columns/style/.style={string type}, columns/label/.style={string type}, columns/cmdoptions/.style={string type} ]{pTable.tab}{\pTable} \pgfplotstableread[col sep=semicolon, columns/t/.style={string type}, columns/style/.style={string type}, columns/label/.style={string type}, columns/cmdoptions/.style={string type} ]{tTable.tab}{\tTable} \pgfplotstableread[col sep=semicolon, columns/x/.style={string type}, columns/style/.style={string type}, columns/label/.style={string type}, columns/cmdoptions/.style={string type} ]{xTable.tab}{\xTable} %************************************************ \ifbool{createPTables}{% \pgfplotstablegetrowsof{\pTable} \foreach \i[evaluate=\i as \row using int(\i-1)] in {1,...,\pgfplotsretval}% {% \pgfplotstablegetelem{\row}{p}\of\pTable% \edef\p{\pgfplotsretval}% \pgfplotstablegetelem{\row}{cmdoptions}\of\pTable% \edef\cmdoptions{\pgfplotsretval}% \edef\shellcmd{../isobar/bin/Debug/isobar\space% --p=\p\space% --s=[\smin:\smax]\space% --h=[\hmin e3:\hmax e3]\space% % number of amples is set per plot in pTables.tab --snap\space% \cmdoptions\space% > ./data/p\p Pa.dat}% \immediate\write18{\shellcmd}% }% }% {} % end of \ifbool{createPTables} % %************************************************ \ifbool{createTTables}{% \pgfplotstablegetrowsof{\tTable} \foreach \i[evaluate=\i as \row using int(\i-1)] in {1,...,\pgfplotsretval}% {% \pgfplotstablegetelem{\row}{t}\of\tTable% \edef\t{\pgfplotsretval}% \pgfplotstablegetelem{\row}{cmdoptions}\of\tTable% \edef\cmdoptions{\pgfplotsretval}% \edef\shellcmd{../isotherm/bin/Debug/isotherm\space% --t=\t\space% --s=[\smin:\smax]\space% --h=[\hmin:\hmax]\space% --snap\space% \cmdoptions\space% > ./data/t\t C.dat}% \immediate\write18{\shellcmd}% }% }% {} % end of \ifbool{createTTables} % %************************************************ \ifbool{createXTables}{% \pgfplotstablegetrowsof{\xTable} \foreach \i[evaluate=\i as \row using int(\i-1)] in {1,...,\pgfplotsretval}% {% \pgfplotstablegetelem{\row}{x}\of\xTable% \edef\x{\pgfplotsretval}% \pgfplotstablegetelem{\row}{cmdoptions}\of\xTable% \edef\cmdoptions{\pgfplotsretval}% \edef\shellcmd{../isox/bin/Debug/isox\space% --x=\x e-3\space% --s=[\smin:\smax]\space% --h=[\hmin:\hmax]\space% --p=[\pmin:\pCrit]\space% --samples=100\space%

Samples\space% \cmdoptions\space% > ./data/x\x e-3.dat}% \immediate\write18{\shellcmd}% }% }% {} % end of \ifbool{createTTables}

The file pTable.tab read in by the above file starts with this header and first entry:

p;style;label;cmdoptions 700;major p plot;normal;--samples=100 --t=[1:50]

This specifies that the 700 Pa plot is a major p plot, with a normal label. The binary for creating the isobar table is called with extra options to get 100 samples and limit the the temperature range to 1...50 °C (that helps solving the state equations).

drawGrid.tex :

% draw minor x grid lines \foreach \s in \sMinorTicks { \edef\temp{

oexpand\draw[minor grid style](axis cs:\s,\hmin) -- (axis cs:\s,\hmax);} \temp } % draw minor y grid lines \foreach \h in \hMinorTicks { \edef\temp{

oexpand\draw[minor grid style](axis cs:\smin,\h) -- (axis cs:\smax,\h);} \temp } % draw intermediate x grid lines \foreach \s in \sInterTicks { \edef\temp{

oexpand\draw[intermediate grid style](axis cs:\s,\hmin) -- (axis cs:\s,\hmax);} \temp } % draw intermediate y grid lines \foreach \h in \hInterTicks { \edef\temp{

oexpand\draw[intermediate grid style](axis cs:\smin,\h) -- (axis cs:\smax,\h);} \temp } % draw major x grid lines \foreach \s in \sMajorTicks% { \edef\temp{

oexpand\draw[major grid style](axis cs:\s,\hmin) -- (axis cs:\s,\hmax);} \temp } % draw major y grid lines \foreach \h in \hMajorTicks { \edef\temp{

oexpand\draw[major grid style](axis cs:\smin,\h) -- (axis cs:\smax,\h);} \temp }

plotp.tex : (creates the pressure plots, other plot files are similar and omitted here)

\pgfplotstablegetrowsof{\pTable} \foreach \i[evaluate=\i as \row using int(\i-1)] in {1,...,\pgfplotsretval} { \pgfplotstablegetelem{\row}{p}\of\pTable \edef\p{\pgfplotsretval} \pgfplotstablegetelem{\row}{style}\of\pTable \edef\style{\pgfplotsretval} \edef\temp{

oexpand\addplot[name path global=plot-p\p Pa,\style] table[x=s,input filter] {./data/p\p Pa.dat};} \temp }

placePLabels.tex :