Chemical process flow sheets TikZ/PGF

Even after 5 years it still seems that there isn't a ready out of the box solution. So I decided to create my own. It's based on the TikZ circuit library and it allows the creation of new type of circuit diagram, based on the symbols and rules as described in the norm ISO 14617. I tried to keep the same structure and conventions as the 'circuit ee' library. At the current time it's still in the early development stages, and subject to regular changes. My goal is to create a package for CTAN. It is hosted on Github as PIDcircuitTikz.

The following file show the currently implemented symbols: example.pdf The manual can be found at: PIDcircuitTikZ.pdf

Example given below. The files pgflibraryshapes.gates.pid.ISO14617.code.tex, pgflibraryshapes.gates.pid.code.tex, tikzlibrarycircuits.pid.ISO14617.code.tex, tikzlibrarycircuits.pid.code.tex and draftdrawing.cls need to be installed in the same folder as the example.

\documentclass[a4paper, landscape, border=5mm, linewidth=0.25mm, linewidthborder=0.5mm]{draftdrawing}

\usetikzlibrary{calc}

\begin{document}

\title{Simple diagram}
\designedby{Jelle Spijker}
\checkedby{}
\approvedby{}
\draftnumber{A001}
\revision{A}
\remarks{some short remarks}
\logo{logo.png}
\scale{1:1}
\unit{mm}
\draftdate{\today}

\begin{tikzdraft}[every info/.style={font=\tiny}, node distance=2]
 \node[fan={name=F1,info=\( F_{1} \)}, rotate=180] at (-7,5) {};
 \node[damper={name=D1,info=above left:\( D_{1} \), adjustable}, right=of F1] {};
 \node[tank={info=\(S_{1}\), name=S1, with={bag filter element}{-0.25}{0}{rotate=90}}, below=of F1] {};
 \node[regenerative pre-heater={name=H1, info=\( H_{1} \)}, anchor=input in] at ($(D1)+(1.5,0)$) {};
 \node[branch={name=B1}] at (D1 |- S1) {};
 \node[damper={name=D2,info'=above left:\( D_{2} \)}, adjustable] at ($(B1)+(0.75,0)$) {};
 \node[tank={info=\( S_{2} \), name=S2, with={filter element}{0}{0}{rotate=90}}] at ($(H1.output in)+(1.5,0)$) {};
 \node[measurement point={name=M1}] at (D2 -| S2) {};
 \node[branch={name=B2}] at ($(M1)-(0.75,0)$) {};
 \node[straight tube heat exchanger={name=H2, info=\( H_{2} \)}, anchor=input] at ($(M1)+(0.75,0)$) {};
 \node[tank={name=W1, info=\( W_{1} \), with={spray nozzle}{0}{-0.5}{rotate=180}}] at ($(H2.output)+(1.5,0)$) {};
 \node[measurement point={name=M2}] at ($(W1)+(0.75,0)$) {};
 \node[tank={name=H3, info=above right:\( H_{3} \), with={heating coil}{0}{0}}] at ($(M2)+(1,0)$) {};
 \node[three way valve={globe, name=V1, info=below left:\( V_{1} \), rotate=270}] at ($(H3-heating coil.south)-(0,1)$) {};
 \node[fan={name=F2,info'=\( F_{2} \)}] at ($(H3)+(5,0)$) {};
 \node[measurement point={name=M3}] at ($(F2)+(0.75,0)$) {};
 \node[branch={name=B3}] at ($(W1.south |- V1)-(0.25,0)$) {};
 \node[boiler={name=H4, info=\( H_{4} \),with={fired type}{0}{-0.5}}] at ($(V1)-(-1,1.5)$) {};
 \node[pump={displacement, name=P1, info=\( P_{1} \), rotate=180}] at ($(H4.output)+(1,0)$) {};
 \node[tank={name=T1, with={heating coil}{0}{0}, with={measurement point}{0.75}{0.75}, info=below:\( T_{1} \)}] at ($(P1)+(1.5,0)$) {};
 \node[valve={name=V3, info'=\( V_{3} \)}] at (T1 -| F2) {};
 \node[branch={name=B4}] at (V1 |- H4.input) {};
 \node[angled valve={globe, safety function, name=V2, info=left:\( V_{2} \)}] at (B4 -| M2) {};
 \node[spring={info=\( p>\SI{10}{\bar} \)}, at={V2.center}{0.5}] {};

 \node[reference={name=TO1, info=right:{to aula}}] at ($(M3)+(1,0)$) {};
 \node[reference={name=TO2, rotate=180, info=left:{from aula}}] at (S2 -| TO1) {};
 \node[reference={name=TO3, info=left:{from outside}}, left=of S1] {};
 \node[reference={name=TO4, rotate=90, info=right:{to outside}}] at ($(TO3 |- F1)+(0,1.5)$) {};
 \node[reference={name=TO5, rotate=-90, info=right:{to atm}}] at ($(V2)-(0,1.5)$) {};
 \node[reference={name=TO6, rotate=-90, info=right:{to water}}] at (TO5 -| B3) {};
 \node[reference={name=TO7, rotate=180, info=left:{from water}}] at (V3 -| TO1) {};

 \draw (H1.input in) to [flow direction] (D1);
 \draw (D1) to [flow direction] (F1);
 \draw (D1) to [flow direction] (B1);
 \draw (S1) to [flow direction] (B1);
 \draw (B1) to (D2);
 \draw (D2) to [flow direction] (\currentcoordinate |- H1.input out) to (H1.input out);
 \draw (S2) to [flow direction] (H1.output in);
 \draw (D2) to [flow direction] (B2);
 \draw (B2) to (M1);
 \draw (H1.output out) to (H1.output out -| B2) to [flow direction] (B2);
 \draw (M1) to (H2.input);
 \draw (H2.output) to [flow direction] (W1);
 \draw (W1.south -| B3) to (B3);
 \draw (H2.south) to ++ (0,-0.5) to [flow direction] (B3) to [flow direction=near end] (TO6);
 \draw (W1) to (M2) to (H3);
 \draw (V1) to (H3-heating coil.south);
 \draw (V1) to [flow direction] (V1 -| W1-spray nozzle) to (W1-spray nozzle);
 \draw (H3) to [flow direction] (F2);
 \draw (F2) to (M3);
 \draw (H4.input) to (B4) to [flow direction] (V1);
 \draw (B4) to (V2) to [flow direction] (TO5);
 \draw (H3-heating coil) to (H3-heating coil |- H2.refrigerant out) to [flow direction] (\currentcoordinate -| T1-heating coil) to ($(\currentcoordinate |- F2)+(0,0.125)$);
 \draw (T1-heating coil) to [flow direction'] ($(\currentcoordinate |- F2)-(0,0.125)$);
 \draw (TO7) [flow direction] to (V3) to (T1) to [measurement point={name=M4}] (P1) to [measurement point={name=M5}] (H4.output);
 \draw (M3) to (TO1);
 \draw (TO2) to [flow direction] (S2);
 \draw (TO3) to [flow direction] (S1);
 \draw (F1) to [flow direction] (F1 -| TO4) to (TO4);

 \node[measurement device={central control room, name=MD1}, measure=PT, at={M1.north}{}] {};
 \node[measurement device={central control room, name=MD2}, measure=MT, anchor=west] at (MD1.east) {};
 \node[measurement device={central control room, name=MD3}, measure=TT, at={M2.north}{}] {};
 \node[measurement device={central control room, name=MD4}, measure=MT, anchor=west] at (MD3.east) {};
 \node[measurement device={central control room,  name=MD5}, measure=FT, at={M3.north}{}] {};
 \node[measurement device={name=MD6}, measure=LS, at={V3.center}{1.5}] {};
 \node[measurement device={local control room, name=MD7}, measure=PT, at={M4}{1.6}] {};
 \node[measurement device={local control room, name=MD8}, measure=TT, anchor=west]  at (MD7.east) {};
 \node[measurement device={local control room, name=MD9}, measure=PT, at={M5}{1.6}] {};
 \node[measurement device={local control room, name=MD10}, measure=TT, anchor=west] at (MD9.east) {};

 \node[automatic operation, at={D1.north}{}] {\tiny M};
 \node[automatic operation, at={D2.south}{3}{rotate around=180:(D2.south), rotate=180}]  {\tiny M};
 \node[automatic operation, at={V1.center}{}{rotate around=270:(V1.center)}] {\tiny M};
 \node[automatic operation, at={P1.south}{0.15}] {};
 \node[automatic operation, at={F1.south}{}] {};
 \node[automatic operation, at={F2}{}] {};

 \draw[dashed] (MD6) to [flow direction'] (MD6 -| T1-measurement point) to (T1-measurement point);

\end{tikzdraft}
\end{document}

enter image description here

Note: The Tikz library can also be used without the draftdrawing.cls, which only purpose is to create a drafting sheet.

Help, tips and contributions are greatly appreciated.


I came across this looking for something else http://www.texample.net/tikz/examples/area/electrical-engineering/

Edit: Code for a Tikz valve is available from a link at http://old.nabble.com/Overflow-when-designing-a-shape-to31589669.html#a31589669 but from the webpage it seems the author had some problems with this, so some work may be required.

You may be able to modify some of the basic elements of these flow chart like diagrams without too much trouble.


I have the same problem, here is my partial solution for a flowsheet that I need to reproduce. I know it's completely unfinished, but I hope this will help you. It only has 2 equipments and doesn't has any control loop or valve, but as you can see in the code, the images are loaded as external file so you can add more. I also know that you can draw a circle with tikz but I'm a newbie and I want to make it as simple as I can. Feel free to change anything.

\documentclass{standalone}

\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{intersections}
\usepackage{tkz-euclide}
\usetkzobj{all}
%with these two packages you can write accents and similar directly
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

\begin{document}

\def\radius{2.mm} 

\begin{tikzpicture}
\node[inner sep=0pt] (Absorbedor) at (0,0)
    {\includegraphics[width=.1\textwidth]{filled_tower.png}};
\node[inner sep=0pt] (Flash) at (5,-6) 
    {\includegraphics[width=.1\textwidth]{unfilled_tower.png}};
\node[inner sep=0pt] (Divisor) at (5,-10)
    {\includegraphics[width=.1\textwidth]{circle.png}};
\node[left] at (Absorbedor.west) {Absorbedor};

\draw[->,very thick, name path=line 1] (Absorbedor.south) |- (Flash.west);  
\draw[->,very thick] (Flash.south) -- (Divisor.north);  
\draw[-,very thick] (Divisor.west) -- (3,-10);
\draw[->,name path=line 2, opacity=0] (3,-10) |- (Absorbedor.east);         %this line is going to be replaced

% find intersection of first and second line
\path [name intersections={of = line 1 and line 2}];
\coordinate (S)  at (intersection-1);

% path a circle around this intersection for the arc
\path[name path=circle] (S) circle(\radius);

% find intersections of second line and circle
\path [name intersections={of = circle and line 2}];
\coordinate (I1)  at (intersection-1);
\coordinate (I2)  at (intersection-2);

% draw normal line segments
\draw[very thick] (3, -10) -- (I2);
\draw[->,  very thick] (I1) |- (Absorbedor.east);

% draw arc at intersection
\tkzDrawArc[color=black, very thick](S,I1)(I2);

\draw[->,very thick] (-2,-2.55) node[align=right, left] {Alimentación\\$CO_2$\\$H_2S$\\I} -- ($(Absorbedor.south west)+(0,13mm)$) node[midway, above] {1};

\draw[<-,very thick] (-2,4) node[align=right, left] {$CO_2$\\I} -| ($(Absorbedor.north west)+(0.3,-0.9 mm)$) node[near start, above] {2};

\end{tikzpicture}

\end{document}

enter image description here