# Drawing lines between 2 intersections of a function given the y-value (Morse potential)

I have to draw lines (vibrational energy lines) in a Morse potential curve.

Let me explain it with a more general example :

If I have a parabola x², I want to draw lines in it given a set of y values, for instance (1; 0.5; 0.7; 0.8; 0.85; 0.875). How can I draw these lines up to the intersection? For example, how can I find the x values to draw the first line from (-1,1) up to (1,1)?

My intention is to draw a figure like this

• If you add a MWE of what you've done, it's so much appealing to us for provide a fast and good answer. Dec 30, 2013 at 23:14

Updated

## Method 1: using intersections library

Here's an approach that uses pgfplots to plot the actual Morse potential. It uses \pgfmathdeclarefunction to define a potential function V and another function that calculates the energy of the nth bound state, then uses the tikz library intersections to calculate the intersection of an undrawn horizontal line at this height with the Morse potential. Finally, it draws the horizontal line from one intersection to the next. See pgfplots: using path names created with foreach in pgfplotsextra for info on naming paths within pgfplotsinvokeforeach.

\documentclass{standalone}
\usepackage{pgfplots}
\usetikzlibrary{intersections}

\begin{document}

%%%%%%% Define Potential Function %%%%%%%
\pgfmathsetmacro{\De}{10}
\pgfmathsetmacro{\re}{1}
\pgfmathsetmacro{\a}{1}
\pgfmathdeclarefunction{V}{1}{%
\pgfmathparse{%
\De*((1-exp(-\a*(#1-\re)))^2-1)
}%
}
%%%%%%% Energy Levels %%%%%%%
% energies are given as multiples of \hbar \omega_0 with
% \omega_0 = \a*sqrt(2*\De/\m), where m is the (reduced) mass of the diatomic molecule
% \De above is really \De/(\hbar*\omega)
\pgfmathdeclarefunction{energy}{1}{%
\pgfmathparse{%
-\De+(#1+0.5) - (#1+0.5)^2/(4*\De)
}%
}

\begin{tikzpicture}
\begin{axis}[axis lines = middle,smooth,xlabel = $r/r_e$, ylabel =$E/\hbar \omega_0$, minor tick num =1, grid=none, no markers, every axis x label/.style={ at={(ticklabel* cs:1.05)}, anchor=west},
every axis y label/.style={at={(ticklabel* cs:1.05)},anchor=south},domain=0:10, enlargelimits = true,scale=1.5]
\addplot +[thick, samples=50, name path global=MorseCurve] {V(x)};
\pgfplotsinvokeforeach{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17}{
\path [name path global=HelperLine-#1] (axis cs: 0,{energy(#1)}) -- (axis cs: 10, {energy(#1)});
\draw[name intersections={of=MorseCurve and HelperLine-#1}] (intersection-1) -- (intersection-2);
}

\end{axis}
\end{tikzpicture}

\end{document}


## Method 2: analytical form of the intersections

Uses the analytical form of the intersections, which is fairly easy to calculate. This is my original post, except I changed \edefs to pgfplotsinvokeforeach.

\documentclass{standalone}
\usepackage{pgfplots}

\begin{document}

%%%%%%% Define Potential Function %%%%%%%
\pgfmathsetmacro{\De}{10}
\pgfmathsetmacro{\re}{1}
\pgfmathsetmacro{\a}{1}
\pgfmathdeclarefunction{V}{1}{%
\pgfmathparse{%
\De*((1-exp(-\a*(#1-\re)))^2-1)
}%
}
%%%%%%% Energy Levels %%%%%%%
% energies are given as multiples of \hbar \omega_0 with
% \omega_0 = \a*sqrt(2*\De/\m), where m is the (reduced) mass of the diatomic molecule
% \De above is really \De/(\hbar*\omega)
\pgfmathdeclarefunction{energy}{1}{%
\pgfmathparse{%
-\De+(#1+0.5) - (#1+0.5)^2/(4*\De)
}%
}
%Upper limit on classical bound state of a given energy
\pgfmathdeclarefunction{rmax}{1}{%
\pgfmathparse{%
(\a*\re+ln( - (\De+sqrt(\De*(#1+\De)))/#1 ) )/\a
}%
}
%Lower limit on classical bound state of a given energy
\pgfmathdeclarefunction{rmin}{1}{%
\pgfmathparse{%
(\a*\re+ln( (-\De+sqrt(\De*(#1+\De)))/#1 ) )/\a
}%
}

\begin{tikzpicture}
\begin{axis}[axis lines = middle,smooth,xlabel = $r/r_e$, ylabel =$E/\hbar \omega_0$, minor tick num =1, grid=none, no markers, every axis x label/.style={ at={(ticklabel* cs:1.05)}, anchor=west},
every axis y label/.style={at={(ticklabel* cs:1.05)},anchor=south},domain=0:10, enlargelimits = true,scale=1.5]
% \foreach inside axis environment was tricky, see https://tex.stackexchange.com/questions/17638/pgfplots-foreach-equivalent-to-tikzs-with-multiple-variables-separated-by-a-sla/17817#17817
\pgfplotsinvokeforeach{0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17}{
\draw (axis cs: {rmin( energy(#1) )},{energy(#1)}) -- (axis cs: {rmax(energy(#1))},{energy(#1)});
}
\node[style ={ align=center}] at (axis cs: 7,14) {Morse potential: \\ $V(r) = D_e \left( [1-e^{-a(r-r_e)}]^2-1 \right)$ };
\node[style ={ align=center}] at (axis cs: 7,7) {Energy levels: \\ $E_n = -D_e + \hbar \omega_0 (n+1/2) + \frac{[\hbar \omega_0 (n+1/2)]^2}{4 D_e}$ \\ with $\omega_0 = a \sqrt{2 D_e/m}$ };
\end{axis}
\end{tikzpicture}

\end{document}


With TikZ, without drawing an explicit Morse-potential and with clipping. (The upper blue curve is not really an excited state, but rather a curve that looks alike)

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
\draw[->] (-0.3,0) -- node[sloped,below] {Bond length} (6,0);
\draw[->] (0,-0.3) -- node[sloped,above] {Enery wavenumbers} (0,5);
\begin{scope}
\draw[blue,thick] plot[smooth,domain=0.5:2.5] (\x,{0.2*exp(-20*(\x-1.5)^2)+1)});
\coordinate (a) at (1.2,1);
\draw[clip] plot[smooth,tension=0.7] coordinates {(0.5,4) (1,0.1) (3,1.5) (5,2)};
\foreach \i in {1,2,3,...,6} {
\draw (0,{2-2/(2*\i)}) -- (5,{2-2/(2*\i)});
}
\end{scope}
\begin{scope}[shift={(0.5,2.5)}]
\draw[blue,thick] plot[smooth,domain=0.5:2.5] (\x,{0.4*cos(5.5*pi*(\x-1.5) r)^2*sin((\x-1.5) r)^2+1.5});
\coordinate (b) at (0.7,1.5);
\path[clip] (0,0) rectangle (5,2);
\draw[clip] plot[smooth,tension=0.7] coordinates {(0.5,4) (1,0.1) (3,1.5) (5,2)};
\foreach \i in {1,2,3,...,6} {
\draw (0,{2-2/(2*\i)}) -- (5,{2-2/(2*\i)});
}
\end{scope}
\draw[red,->] (a) -- (b);
\end{tikzpicture}
\end{document}


• Thank you for your answer! How can you do this with an explicit Morse-potential ( I use \addplot[] expression{...} in the axis environment, so all my figures are the same in my article). Dec 31, 2013 at 14:34
• Clipping detected... Dec 31, 2013 at 16:02
• @Dries_VB you can precompute your Morse curve in a file where every line is on the format "x_value y_value" and then replace \draw[clip] plot[smooth,tension=0.7] by \draw[clip] plot file{filename}, or even \draw[clip] plot function{<gnuplot formula>}. See §19.2 of the pgfmanual Dec 31, 2013 at 17:23
• @StiffJokes You detected my wording flaw :-) Dec 31, 2013 at 18:33
• I see....... :-) Dec 31, 2013 at 18:34

With PSTricks.

\documentclass[pstricks,border=12pt]{standalone}

\usepackage{pst-plot}
\psset
{
algebraic,
plotpoints=100,
}

\def\f{(x+1)*(x-2)*(x-2.5)-1}

\begin{document}
\begin{pspicture}(-1,-2)(5,6)
\psaxes[linecolor=gray,ticksize=4pt 0]{->}(0,0)(-1,-4)(4.5,5.5)[$x$,0][$y$,90]
\begin{psclip}
{
\pscustom[linestyle=none]
{
\psplot{-1}{3.4}{\f}
\psline(-1,0|*3.4 {\f})
\closepath
}
}
\foreach \y in {.5,.7,.8,1,2,3}{\psline(0,\y)(4.5,\y)}% important percent sign
\end{psclip}
\psplot[linecolor=blue]{-1}{3.4}{\f}
\end{pspicture}
\end{document}