# pgfplots: Plot inverse function (function of y)

I am trying to plot the Ramberg-Osgood-relationship for a specific material with pgfplots. The relationship describes the stress-strain-curve, that is the stress as a function of the strain. The relationship itself is defined as the strain as a function of the stress:

strain(stress)=stress/modulus+0.002*(stress/yield stress)^n


I already found a thread which describes plotting inverse functions, so plot x as a function of y.

However, everything I tried results in an error, either Dimension too large by TikZ, Illegal unit of measure with fpu as in this thread or the wrong function with gnuplot.

Here are the MWE's for the things I tried:

• Plain pgfplots:

\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{siunitx}

\pgfplotsset{compat=1.10}

\begin{document}

\pgfplotsset{stressstrainset/.style={%
axis lines=center,
xlabel={$\varepsilon$ $\left[\si{\percent}\right]$},
ylabel={$\sigma$ $\left[\si{\MPa}\right]$},
restrict x to domain=0:15,
restrict y to domain=0:775,
xmin=0.0, xmax=  15,
ymin=0.0, ymax= 775,
samples=100,
}}

\begin{tikzpicture}
\pgfmathsetmacro\modulus{72400}
\pgfmathsetmacro\yield{325}
\begin{axis}[stressstrainset]
\end{axis}
\end{tikzpicture}

\end{document}


Results in:

! Dimension too large.
\relax
l.21 \pgfmathsetmacro\modulus{72400}

• pgfplots with fpu:

\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{siunitx}

\pgfplotsset{compat=1.10}

\begin{document}

\pgfplotsset{stressstrainset/.style={%
axis lines=center,
xlabel={$\varepsilon$ $\left[\si{\percent}\right]$},
ylabel={$\sigma$ $\left[\si{\MPa}\right]$},
restrict x to domain=0:15,
restrict y to domain=0:775,
xmin=0.0, xmax=  15,
ymin=0.0, ymax= 775,
samples=100,
}}

\begin{tikzpicture}
\pgfkeys{/pgf/fpu=true}
\pgfmathsetmacro\modulus{72400}
\pgfkeys{/pgf/fpu=false}
\pgfmathsetmacro\yield{325}
\begin{axis}[stressstrainset]
\end{axis}
\end{tikzpicture}

\end{document}


Results in:

! Illegal unit of measure (pt inserted).

• pgfplots with gnuplot:

\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{siunitx}

\pgfplotsset{compat=1.10}

\begin{document}

\pgfplotsset{stressstrainset/.style={%
axis lines=center,
xlabel={$\varepsilon$ $\left[\si{\percent}\right]$},
ylabel={$\sigma$ $\left[\si{\MPa}\right]$},
restrict x to domain=0:15,
restrict y to domain=0:775,
xmin=0.0, xmax=  15,
ymin=0.0, ymax= 775,
samples=100,
}}

\begin{tikzpicture}
\begin{axis}[stressstrainset]
\addplot gnuplot [raw gnuplot,id=nfive, mark=none, draw=black]{
set xrange  [0:15];
modulus = 72400;
yield   = 325;
h(x)=(x/modulus+0.002*(x/yield)^15);
plot h(x),x
};
\end{axis}
\end{tikzpicture}

\end{document}


Gives me a result which is obviously wrong.

## Edit

I also tried using GPa as unit for the stress, but I would like to set up the chart in the MPa-System since the rest of my document uses it.

\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{siunitx}

\pgfplotsset{compat=1.10}

\begin{document}

\pgfplotsset{stressstrainset/.style={%
axis lines=center,
xlabel={$\varepsilon$ $\left[-\right]$},
ylabel={$\sigma$ $\left[\si{\GPa}\right]$},
restrict x to domain=0:0.15,
restrict y to domain=0:0.775,
xmin=0.0, xmax=  0.15,
ymin=0.0, ymax= 0.775,
samples=1000,
}}

\begin{tikzpicture}
\pgfmathsetmacro\modulus{72.400}
\pgfmathsetmacro\yield{0.325}
\begin{axis}[stressstrainset]
\end{axis}
\end{tikzpicture}

\end{document}


## Edit2

Thanks to @Christian's answer, there is a running version of the chart. However, I found out, that I need to define the strains, thus the x-axis, not in percent, but in the actual decimal value in order to obtain the correct graph.

\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{siunitx}

\pgfplotsset{compat=1.10}

\begin{document}

\pgfplotsset{stressstrainset/.style={%
axis lines=center,
xlabel={$\varepsilon$ $\left[-\right]$},
ylabel={$\sigma$ $\left[\si{\MPa}\right]$},
domain=0:775,
xmin=0.0, xmax= 0.15,
ymin=0.0, ymax= 775,
samples=100,
}}

\begin{tikzpicture}
\def\modulus{72400}
\def\yield{325}
\begin{axis}[stressstrainset]
\end{axis}
\end{tikzpicture}


Now again, there is the problem that I do get the error

! Dimension too large.


for the second addplot, but only if the exponent is >10. Is the value getting too small?

Can someone please explain how I can set up this chart correctly?

• One possible problem with first and second example is that the calculations should not exceed ±16383.99999 (\modulus{72400} seems to be a direct violation of this rule). This limitation, if I'm not so wrong, is inherited from TeX. Mar 19, 2014 at 16:10
• thx @Pouya, that is why I tried the workaround with fpu Mar 19, 2014 at 16:21
• The easiest partial answer is to switch your stress axis to units of GPa, and scale all stress numbers down by a factor of 1000. You'll probably need to increase your samples from 100 to 1000 as well. Working on how to change the y axis labels back to units of MPa, but haven't finished that yet. Mar 19, 2014 at 16:41
• you could also try avoiding having 72400 in memory at once by using x/72400=x/72.4/1000 Mar 19, 2014 at 16:45
• Fixed the GPa to MPa problem now. Mar 19, 2014 at 16:52

As already explained in some comment, \pgfmathsetmacro{72400} is unsupported by PGF (in fact, my system accepts it without problems - apparently something has changed in PGF CVS).

Nevertheless, you do not need \pgfmathsetmacro just to declare a constant; it is much simpler to write \def\MACRO{<constant>} (or use \newcommand\MACRO{<constant>} which should be the same).

Then you need to assign a domain. The key(s) restrict * to domain are no definition how to sample points; they can be used to exclude already sampled points from the region of interest. In your case, you would define domain=775 and omit the restrict * to domain.

Finally, math expressions in parametric plots need extra curly braces if they contain other round braces. In other words, use ({x/\modulus+0.002*(x/\yield)^15},x) to avoid confusion with the round braces (TeX cannot automatically balance them, it can only balance curly braces).

Taking this together, I arrive at the following modification of your first plot:

\documentclass{standalone}
\usepackage{pgfplots}

\pgfplotsset{compat=1.10}

\begin{document}

\pgfplotsset{stressstrainset/.style={%
axis lines=center,
xlabel={$\varepsilon$},
ylabel={$\sigma$},
%restrict x to domain=0:15,
domain=0:775,
xmin=0.0, xmax=  15,
ymin=0.0, ymax= 775,
samples=100,
}}

\begin{tikzpicture}
\def\modulus{72400}
\def\yield{325}
\begin{axis}[stressstrainset]
\end{axis}
\end{tikzpicture}

\end{document}


• Thanks, that looks good. However, I found out, that I have to define my x-axis (strains) not in percent but in the actual decimal value to obtain the correct chart. This results in another Dimensions too large-Error. I updated my questions accordingly. Mar 20, 2014 at 8:29
• The dimensions too large errors happen if and only if the axis limits (xmin and friends) show a much smaller portion than the data range. In order to fix these items, you need to add restrict x to domain=0:0.3 or something like that. The precise value does not matter, it is just required that the difference between data range and axis range is "reasonably small". Perhaps I should implement automatic support for this case... Mar 20, 2014 at 22:33
• Thanks a lot. I'll try that as soon as the construction workers turn the power back on in my office. An automatic check would be helpful I guess. Mar 21, 2014 at 10:23

Here's what worked for me on TeX Live 2013:

\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{siunitx}

\begin{document}

\pgfplotsset{stressstrainset/.style={%
axis lines=center,
xlabel={$\varepsilon$ $\left[\si{\percent}\right]$},
ylabel={$\sigma$ $\left[\si{\MPa}\right]$},
restrict x to domain=0:15,
restrict y to domain=0:0.775, % GPa
xmin=0.0, xmax=  15,
ymin=0.0, ymax= 0.775, % GPa
samples=1000,
%scaled y ticks=false,
yticklabels={0, 0, 200, 400, 600} % MPa
}}

\begin{tikzpicture}
\pgfmathsetmacro\modulus{72.400} % GPa
\pgfmathsetmacro\yield{0.325} % GPa
\begin{axis}[stressstrainset]
\end{axis}
\end{tikzpicture}

\end{document}


(Partly solved.) I have drawn almost perfect straight line without significant y-intercept change! Even those values look suspiciously...

Well, I don't know exactly how to set the parameters for this particular task, but I wasn't limited in calculations as Lua was on the run. It might be useful to know this way for similar tasks in a long run. Lua can be even improved by the BigNum and BigRat libraries, http://oss.digirati.com.br/luabignum/. I was inspired by this article, http://www.unirioja.es/cu/jvarona/downloads/numerical-methods-luatex.pdf, to try this task regardless the results. As an exercise I also listed the coordinates as an immediate feedback if the results are what they should be.

%! lualatex inverse.tex
\documentclass[a4paper]{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.10}
\usepackage{siunitx}
\usepackage{luacode}
\parindent=0pt
\pagestyle{empty}

\begin{document}
\def\myxmin{0}
\def\myxmax{15}
\def\mysamples{100}
\def\mymodulus{72400} % /1000?
\def\myyield{325} % /1000?

\pgfplotsset{stressstrainset/.style={%
axis lines=center,
xlabel={Strain $\varepsilon$ $\left[\si{\percent}\right]$},
ylabel={Stress $\sigma$ $\left[\si{\MPa}\right]$},
restrict x to domain=0:\myxmax,
restrict y to domain=0:775, % /1000?
xmin=\myxmin, xmax=\myxmax,
ymin=0.0, ymax=775, % /1000?
samples=\mysamples,
}}

\begin{luacode*}
-- Round me...
-- http://lua-users.org/wiki/SimpleRound
function round(num, idp)
local mult=10^(idp or 0)
return math.floor(num*mult+0.5)/mult
end

-- Compute me...
function computeme(xmin,xmax,samples,modulus,yield)
local step=(xmax-xmin)/(samples-1)
local x=xmin
local y
local mystring=""
tex.sprint("\\begin{tikzpicture}")
tex.sprint("\\begin{axis}[stressstrainset])")
for i=1,samples do
y=1000000*(x/modulus+0.002*(x/yield)^15)
mystring=mystring.."("..round(x,2)..","..round(y,2)..") "
x=x+step
end
tex.sprint(mystring) -- values in the graph
tex.sprint("};")
tex.sprint("\\end{axis}")
tex.sprint("\\end{tikzpicture}\\par")
tex.sprint(mystring) -- paper
end
\end{luacode*}

% Draw and show me...
\directlua{computeme(\myxmin, \myxmax, \mysamples, \mymodulus, \myyield)}
\end{document}