# Arrows on the graph of a function with Tikz

I would be glad if you could help me with a problem in Tikz. I want to draw a diagram for a paper about epidemiological systems (as illustrated below) and have two issues (the more important one regarding arrows).

1. I want to draw 3 arrows on the graph which point to the left to show the movement (which basically starts at S = 1). I tried to implement this based on this answer (Add arrows to a smooth tikz function), but I can't get 3 arrows and I have no idea how to change the direction.

2. I need a lot of samples (2000) to draw the graph completely. If I use fewer samples, the graph just stops. Do have an idea how to improve this?

\documentclass[tikz,border=2mm]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{arrows.meta,positioning}
\usetikzlibrary{decorations.markings}
\tikzset{
set arrow inside/.code={\pgfqkeys{/tikz/arrow inside}{#1}},
set arrow inside={end/.initial=>, opt/.initial=},
/pgf/decoration/Mark/.style={
mark/.expanded=at position #1 with
{
\noexpand\arrow[\pgfkeysvalueof{/tikz/arrow inside/opt}]{\pgfkeysvalueof{/tikz/arrow inside/end}}
}
},
arrow inside/.style 2 args={
set arrow inside={#1},
post*emphasized text*action={
decorate,decoration={
markings,Mark/.list={#2}
}
}
},
}

\begin{document}
\begin{tikzpicture}[>=latex]
\begin{axis}[
axis x line=center,
axis y line=center,
xmin=0, xmax=1.1,
ymin=0, ymax=1.1,
xtick={0,1},
ytick={0,1},
hide obscured x ticks=false,
extra x ticks={0.33},
extra x tick labels={$\frac{\gamma}{\beta}$},
extra y ticks={0.3},
extra y tick labels={$I_{\text{max}}$},
xlabel=$S$, ylabel=$I$,
xlabel style={right},
ylabel style={above},
scale=1.2
]

\draw[dashed] (axis cs: 0.33,1) -- (axis cs: 0.33,0) node[pos=1, below] {$\frac{\gamma}{\beta}$};
\draw[dashed] (axis cs: 0,0.3) -- (axis cs: 1,0.3);

\addplot[samples=2000, red, smooth] {1 + (1/3) * ln(x) - x} [arrow inside={end=stealth,opt={red,scale=2}}{0.25,0.50.75}];
%\addplot[samples=1500, green, smooth] {1 + (1/6) * ln(x) - x} [arrow inside={end=stealth,opt={green,scale=1.5}}{0.25,0.50.75}];
\node[label={45:{$(S^*,I_{\text{max}})$}}, circle, fill, inner sep=1pt] at (axis cs: 0.33,0.3) {};
\end{axis}
\end{tikzpicture}
\end{document}


Welcome! As for 2, I added a domain to avoid invalid points in which logarithms of negative numbers or zero get taken, and, as for 1, fixed the arrow positions. Unfortunately for smooth plots decorations.markings easily gives rise to dimension too large errors, so one has to remove smooth, but given the still moderately large number of samples the result looks still good and is hardly distinguishable from the smooth version.

\documentclass[tikz,border=2mm]{standalone}
\usepackage{amsmath}
\usepackage{pgfplots}
\pgfplotsset{compat=1.17}
\usetikzlibrary{arrows.meta,positioning}
\usetikzlibrary{decorations.markings}
\tikzset{
set arrow inside/.code={\pgfqkeys{/tikz/arrow inside}{#1}},
set arrow inside={end/.initial=>, opt/.initial=},
/pgf/decoration/Mark/.style={
mark/.expanded=at position #1 with
{
\noexpand\arrow[\pgfkeysvalueof{/tikz/arrow inside/opt}]{\pgfkeysvalueof{/tikz/arrow inside/end}}
}
},
arrow inside/.style 2 args={
set arrow inside={#1},
postaction={
decorate,decoration={
markings,Mark/.list={#2}
}
}
},
}

\begin{document}
\begin{tikzpicture}[>=latex]
\begin{axis}[
axis x line=center,
axis y line=center,
xmin=0, xmax=1.1,
ymin=0, ymax=1.1,
xtick={0,1},
ytick={0,1},
hide obscured x ticks=false,
extra x ticks={0.33},
extra x tick labels={$\frac{\gamma}{\beta}$},
extra y ticks={0.3},
extra y tick labels={$I_{\text{max}}$},
xlabel=$S$, ylabel=$I$,
xlabel style={right},
ylabel style={above},
scale=1.2
]

\draw[dashed] (axis cs: 0.33,1) -- (axis cs: 0.33,0) node[pos=1, below] {$\frac{\gamma}{\beta}$};
\draw[dashed] (axis cs: 0,0.3) -- (axis cs: 1,0.3);

arrow inside={end=stealth,opt={red,scale=2}}{0.25,0.5,0.75}]
{1 + (1/3) * ln(x) - x}
;
arrow inside={end=stealth,opt={green!70!black,scale=1.5}}{0.25,0.5,0.75}] {1 + (1/6) * ln(x) - x} ;
\node[label={45:{$(S^*,I_{\text{max}})$}}, circle, fill, inner sep=1pt]
at (axis cs: 0.33,0.3) {};
\end{axis}
\end{tikzpicture}
\end{document}


One can avoid the dimension too large errors and use smooth plots if one tells TikZ to use fpu for computing reciprocals.

\documentclass[tikz,border=2mm]{standalone}
\usepackage{amsmath}
\usepackage{pgfplots}
\pgfplotsset{compat=1.17}
\usetikzlibrary{arrows.meta,positioning}
\usetikzlibrary{decorations.markings}
\tikzset{
set arrow inside/.code={\pgfqkeys{/tikz/arrow inside}{#1}},
set arrow inside={end/.initial=>, opt/.initial=},
/pgf/decoration/Mark/.style={
mark/.expanded=at position #1 with
{
\noexpand\arrow[\pgfkeysvalueof{/tikz/arrow inside/opt}]{\pgfkeysvalueof{/tikz/arrow inside/end}}
}
},
arrow inside/.style 2 args={
set arrow inside={#1},
postaction={
decorate,decoration={
markings,Mark/.list={#2}
}
}
},
}

\makeatletter
\tikzset{use fpu reciprocal/.code={%
\def\pgfmathreciprocal@##1{%
\begingroup
\pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}%
\pgfmathparse{1/##1}%
\pgfmath@smuggleone\pgfmathresult
\endgroup
}}}%
\makeatother

\begin{document}
\begin{tikzpicture}[>=latex]
\begin{axis}[
axis x line=center,
axis y line=center,
xmin=0, xmax=1.1,
ymin=0, ymax=1.1,
xtick={0,1},
ytick={0,1},
hide obscured x ticks=false,
extra x ticks={0.33},
extra x tick labels={$\frac{\gamma}{\beta}$},
extra y ticks={0.3},
extra y tick labels={$I_{\text{max}}$},
xlabel=$S$, ylabel=$I$,
xlabel style={right},
ylabel style={above},
scale=1.2
]

\draw[dashed] (axis cs: 0.33,1) -- (axis cs: 0.33,0) node[pos=1, below] {$\frac{\gamma}{\beta}$};
\draw[dashed] (axis cs: 0,0.3) -- (axis cs: 1,0.3);

\begin{scope}[use fpu reciprocal,>=stealth]
arrow inside={end={<},opt={red,scale=2}}{0.25,0.5,0.75}]
{1 + (1/3) * ln(x) - x}
;
\node[label={45:{$(S^*,I_{\text{max}})$}}, circle, fill, inner sep=1pt]

• @thomjan You can either add a reversed key (see pgfmanual v3.1.5 p. 198) or just use the < symbol. I added reversed arrows to the second code but the same construction will work for the first one (provided you drop smooth there, of course). – user194703 Apr 23 at 17:47
• To be clear, in the first example you can use something like \addplot[samples=101, red,domain=0.05:1, arrow inside={end={Stealth[reversed,red,scale=1.5]}}{0.25,0.5,0.75}] {1 + (1/3) * ln(x) - x};. – user194703 Apr 23 at 17:52