3

I've cobbled together some code I've found to draw slope fields for my class. It does the job rather well, except for the following DE, and others, specifically, in this case: the resultant output clearly shows field lines with slope zero, which shouldn't be the case.

Any suggestions? I've appended the code:

\documentclass[border=5pt,tikz]{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{gnuplottex}

\begin{document}        
    \begin{tikzpicture}
    [declare function={f(\x,\y)=(3*(\x^2)+2)/(2*\y);},scale=2.0]

        %limits
        \def\xmax{3} \def\xmin{-3}
        \def\ymax{3} \def\ymin{-3}
        \def\nx{11}
        \def\ny{11}

        %slope field
        \pgfmathsetmacro{\hx}{(\xmax-\xmin)/\nx}
        \pgfmathsetmacro{\hy}{(\ymax-\ymin)/\ny}
        \foreach \i in {0,...,\nx}
        \foreach \j in {0,...,\ny}{
        \pgfmathsetmacro{\yprime}{f({\xmin+\i*\hx},{\ymin+\j*\hy})}
        \draw[blue,shift={({\xmin+\i*\hx},{\ymin+\j*\hy})}] 
        (0,0)--($(0,0)!1mm!(.1,.1*\yprime)$);
        }

        %axes
        \draw[->] (\xmin-.5,0)--(\xmax+.5,0) node[below right] {{$x$}};
        \draw[->] (0,\ymin-.5)--(0,\ymax+.5) node[above left] {{$y$}};


        \draw (current bounding box.north) node[above]
        %label
        {Slope field of \quad $\displaystyle \frac{dy}{dx}=\frac{3x^2+2}{2y}$.};
        \end{tikzpicture}

\end{document}
  • 3
    As always on this site you are much much more likely to get help if you provide a full minimal example instead of just a sniplet like this. Please provide something that is self contained, that others can copy and test without having to add anything. – daleif Aug 28 '19 at 13:21
  • Done. Thanks for the tip. – Lino Vari Aug 28 '19 at 13:31
  • BTW are you even using gnuplottex in this example? It is probably also a better idea to use pgfplots as it will make all the axis for you automatically. Perhaps it even has a build in function to do what you are looking for. – daleif Aug 28 '19 at 13:58
  • 1
    You need to say [declare function={f(\x,\y)=(3*\x*\x+2)/(2*\y);} since \x^2 is not the square of \x, see https://tex.stackexchange.com/q/5400 or https://tex.stackexchange.com/q/469747. Rather, for negative \x this is -abs(\x)^2, i.e. negative, which is why the "slope" can become zero. (I also have problems seeing how your axis description is correct. You have a function f(\x,\y). You plot lines from a given (x,y) to (x+0.1,y+0.1*f(x,y). How are these the slope lines? Shouldn't you compute the gradient for that?) –  Aug 28 '19 at 16:08
  • I do use gnuplottex to plot a solution to the DE, I've left that code out since it's not the focus of my concern. The solutions are typically implicit functions which gnuplottex handles easily. The purpose of the original question was to find out how TikZ handles function inputs;, the code seems to draw the slope field lines and I'm still trying to work that out. As to axes, once I refine the code I'll clean it up, I'm still experimenting. – Lino Vari Aug 29 '19 at 10:04

1 Answers1

2

The singular line y=0 causes some error "Dimension too large" when you change the value of \ny. To overcome, we can clip outside a vicinity of that singular zone, and locally redefine the value \ymax or \ymin accordingly. Just for highlight singular zone, I put different color (magenta) in the vicinity of y=0.

This solution is manualy done, and may not apply for complex singular sets, for example ones given by implicit functions. That situation may need the power of Asymptote.

enter image description here

\documentclass[border=5mm,tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}        
\begin{tikzpicture}
[declare function={f(\x,\y)=(3*\x*\x+2)/(2*\y);}]

% global limits
\def\xmax{3} \def\xmin{-3}
\def\ymax{3} \def\ymin{-3}
\def\nx{30}  \def\ny{12}

% axes
\draw[->,gray] (\xmin-.5,0)--(\xmax+.5,0) node[below right,black] {$x$};
\draw[->,gray] (0,\ymin-.5)--(0,\ymax+.5) node[above left,black] {$y$};

% the above half-plane 
\begin{scope}
\clip (\xmin-.2,.2) rectangle (\xmax+.2,\ymax+.2);
\def\ymin{.2} % locally redefined ymax (inside this scope only)
\pgfmathsetmacro{\hx}{(\xmax-\xmin)/\nx}
\pgfmathsetmacro{\hy}{(\ymax-\ymin)/\ny}
\foreach \i in {0,...,\nx}
\foreach \j in {0,...,\ny}
{
\pgfmathsetmacro{\yprime}{f({\xmin+\i*\hx},{\ymin+\j*\hy})}
\draw[blue,shift={({\xmin+\i*\hx},{\ymin+\j*\hy})}] 
(0,0)--($(0,0)!1.5mm!(.1,.1*\yprime)$);
}
\end{scope}

% the below half-plane
\begin{scope}
\clip (\xmin-.2,-.2) rectangle (\xmax+.2,\ymin-.2);
\def\ymax{-.2} % locally redefined ymax (inside this scope only)
\pgfmathsetmacro{\hx}{(\xmax-\xmin)/\nx}
\pgfmathsetmacro{\hy}{(\ymax-\ymin)/\ny}
\foreach \i in {0,...,\nx}
\foreach \j in {0,...,\ny}
{
\pgfmathsetmacro{\yprime}{f({\xmin+\i*\hx},{\ymin+\j*\hy})}
\draw[blue,shift={({\xmin+\i*\hx},{\ymin+\j*\hy})}] 
(0,0)--($(0,0)!1.5mm!(.1,.1*\yprime)$);
}
\end{scope}

% vicinity of singular line y=0
\begin{scope}
\clip (\xmin-.2,.2) rectangle (\xmax+.2,-.2);
\pgfmathsetmacro{\hx}{(\xmax-\xmin)/\nx}
\foreach \i in {0,...,\nx}
\draw[magenta]  (\xmin+\i*\hx,0)--+(-90:1mm)--+(90:1mm);
\end{scope}

\draw (current bounding box.north) node[above]
{The slope field of \quad $\displaystyle \frac{dy}{dx}=\frac{3x^2+2}{2y}$};
\end{tikzpicture}
\end{document}
Black Mild
  • 17,569
  • The dimension too large errors were avoided in the OP's example since they chose odd values for \nx and \ny, for which \y never becomes 0. The main improvement here is that you replaced \x^2 by \x*\x, such that the numerator really stays positive. –  Aug 28 '19 at 23:06
  • the way of correct writing \x*\x you have mentioned above. In the code, I just say we can do (no matter the value of \ny) for a differential equations like f(\x,\y)=(3*\x*\x+2)/(2*\y-\x*\x) by clip to a vicinity of singular set y=(x^2)/2. – Black Mild Aug 29 '19 at 01:40
  • Maybeclip reversed helpful – Black Mild Aug 29 '19 at 01:43
  • You suggest I use Asymptote, which I'm keen to do, although, I haven't yet found an easy lead-in into it. Any suggestions? I can't read French by the way! – Lino Vari Aug 29 '19 at 10:06