4

I'm using PGFPlots to graph some functions, and I'm facing the following problem: I need to plot the following function f over this interval:

function I need to plot and interval of plotting

It can be verified that in the left point of the interval, f has a value of 1. Nonetheless, when I plot f I get this result (the red and teal lines are for my guidance):

first graph of function

As you can see, the value of f in the left point is not plotted. I used the default samples to plot (25) and I count only 24 points. The problem is worse later, because I have to plot atan(f(x)), and this causes two errors:

Missing number, treated as zero. ...\x^(1-\ga)-\km)/(\co*\x^(1-\ga)+\km)))))};
Illegal unit of measure (pt inserted). ...\x^(1-\ga)-\km)/(\co*\x^(1-\ga)+\km)))))};

How can I fix this? I realized that plotting from the left point plus a little number fixes this, but nothing more. I provide a MWE to plot f. Thank you very much in advance.

\documentclass{article}

\usepackage{pgfplots}
\pgfplotsset{compat=1.14} % this is to avoid a backwards compatibility warning

\begin{document}
\thispagestyle{empty}

\begin{tikzpicture}% function

\pgfmathsetmacro{\T}{1};
\pgfmathsetmacro{\co}{1};
\pgfmathsetmacro{\km}{4};
\pgfmathsetmacro{\ga}{0.1};

\pgfmathsetmacro{\la}{((\km/\co)^(1/(1-\ga))};
\pgfmathsetmacro{\lb}{((sqrt(5)-1)*\km/\co)^(1/(1-\ga))};

\begin{axis}[domain=\la:\lb]
\addplot {sqrt( (2*sqrt( \km*\co*\x^(1-\ga)*(\co*\x^(1-\ga)-\km)/(\co*\x^(1-\ga)+\km) )+\km)/(\co*\x^(1-\ga)-2*sqrt( \km*\co*\x^(1-\ga)*(\co*\x^(1-\ga)-\km)/(\co*\x^(1-\ga)+\km))))};
\addplot[color=teal] coordinates {(\la,{rad(atan(1))})(\lb,{rad(atan(1))})};
\addplot[color=red] coordinates {(\la,0.8)(\la,1.85)};
\addplot[color=red] coordinates {(\lb,0.8)(\lb,1.85)};
\end{axis}
\end{tikzpicture}

\end{document}

EDIT: I've just realized that, although my LaTeX editor throws the aforementioned errors when atan() or rad(atan()) is added, it still generates a .pdf. By ploting this

\addplot {rad(atan(sqrt( (2*sqrt( \km*\co*\x^(1-\ga)*(\co*\x^(1-\ga)-\km)/(\co*\x^(1-\ga)+\km) )+\km)/(\co*\x^(1-\ga)-2*sqrt( \km*\co*\x^(1-\ga)*(\co*\x^(1-\ga)-\km)/(\co*\x^(1-\ga)+\km))))))};

the result is this

plot of the arctan (in radians) of the function mentioned before

4

As Symbol 1 already stated in the comment below the question you can either use a small offset for the lower bound to "correct" the inaccuracy TeX's/Lua's calculation or you can use unequal sampling.

I present both solutions

  • adding an offset for the linear spacing solution using TeX and Lua as calculation engine and
  • using unequal spacing for the Lua solution.

I added markers to the solutions so you can see the difference. When you uncomment the line no markers you will notice that the unequal spacing solution shows a little better result when sticking to 25 samples.

For more details on how the solution works, please have a look at the comments in the code.

\documentclass[border=5pt]{standalone}
\usepackage{pgfplots}
    \pgfplotsset{
        compat=1.12,
        /pgf/declare function={
            % declare constants
            k = 4;
            alpha = 1;
            gamma = 0.1;
            % declare help function
            b(\x) = (alpha*\x^(1-gamma) - k)/(alpha*\x^(1-gamma) + k);
            % declare the main function
            f(\x) = sqrt( (2*sqrt( k*alpha*\x^(1-gamma) * b(\x) ) + k)/
                          (alpha*\x^(1-gamma) - 2*sqrt( k*alpha*\x^(1-gamma)*b(\x)))
                        );
            % declare an small amount to compensate for TeX's/Lua's inaccuracy
            infi = 1e-3;        % for linear spacing
%            infi = 0;           % for non-linear spacing
            % calculate the lower and upper boundaries (the domain values)
            llb = (k/alpha)^(1/(1-gamma));
            lb = llb + infi;
            ub = ((sqrt(5)-1)*k/alpha)^(1/(1-gamma));
            %
            % -----------------------------------------------------------------
            %%% nonlinear spacing: <https://stackoverflow.com/a/39140096/5776000>
            % "non-linearity factor"
            a = 5.0;
            % function to use for the nonlinear spacing
            Y(\x) = exp(a*\x);
            % rescale to former limits
            X(\x) = (Y(\x) - Y(lb))/(Y(ub) - Y(lb)) * (ub - lb) + lb;
        },
    }
\begin{document}
\begin{tikzpicture}
        \pgfmathsetmacro{\co}{1};
        \pgfmathsetmacro{\km}{4};
        \pgfmathsetmacro{\ga}{0.1};

            % "infinitesimal" small amount (for TeX)
            \pgfmathsetmacro{\infinitesimal}{1e-3}
        \pgfmathsetmacro{\la}{(\km/\co)^(1/(1-\ga)) + \infinitesimal};
        \pgfmathsetmacro{\lb}{((sqrt(5)-1)*\km/\co)^(1/(1-\ga))};

        \pgfmathsetmacro{\LA}{lb};
        \pgfmathsetmacro{\LB}{ub};
    \begin{axis}[
        ymin=1,
        domain=\la:\lb,
        smooth,
%        no markers,
    ]
%        % using TeX for calculation
%        \addplot {sqrt( (2*sqrt( \km*\co*\x^(1-\ga)*(\co*\x^(1-\ga)-\km)/(\co*\x^(1-\ga)+\km) )+\km)/(\co*\x^(1-\ga)-2*sqrt( \km*\co*\x^(1-\ga)*(\co*\x^(1-\ga)-\km)/(\co*\x^(1-\ga)+\km))))};
        % using Lua for calculation
        % (see section 6.3.1 in the PGFPlots manual)
        \addplot+ [thick,mark=square,domain=\LA:\LB] {f(x)};
        \addplot+ [mark=triangle,domain=\LA:\LB] ({X(x)},{f(X(x))});

        \addplot [color=teal]  coordinates {(\la,{rad(atan(1))})(\lb,{rad(atan(1))})};
        \addplot [color=green] coordinates {(\la,0.8)(\la,1.85)};
        \addplot [color=green] coordinates {(\lb,0.8)(\lb,1.85)};
    \end{axis}
\end{tikzpicture}
\end{document}

image showing the result of above code

|improve this answer|||||
  • Thank you very much for this solution! I've marked it as accepted. – Ignacio Correa Jun 8 '17 at 15:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.