2

I am trying to generate this image:

Vector potential

I have not yet tried an approach to this, but there does not appear to be anything similar to this on TEXample.net . Can anyone direct me to a start? (i.e. I envisage no problems in generating this along a 1D line - the difficulty is in wrapping the line around).

Equivalently for a square potential, the desired output is:

enter image description here

Sid
  • 1,806

1 Answers1

4

Is it possible to draw this with TikZ? Yes, but IMHO only thanks to this fantastic answer by Max. Let's keep our fingers crossed that his great routines will make it to a package some time (soon). Until this happens, however, one has to copy the preamble from his great answer. (Notice that I also copy a part that is not used at this version of the answer, which concerns "deforming" texts such that you get a 3D feel. I like these macros too much to kick them out. ;-)

\documentclass[tikz,border=3.14mm]{standalone}
\usepackage{tikz-3dplot}
\usepgfmodule{nonlineartransformations}
\usetikzlibrary{calc}
% Max magic
\makeatletter 
% the first part is not in use here
\def\tikz@scan@transform@one@point#1{%
  \tikz@scan@one@point\pgf@process#1%
  \pgf@pos@transform{\pgf@x}{\pgf@y}}
\tikzset{%
  grid source opposite corners/.code args={#1and#2}{%
   \pgfextract@process\tikz@transform@source@southwest{%
     \tikz@scan@transform@one@point{#1}}%
   \pgfextract@process\tikz@transform@source@northeast{%
     \tikz@scan@transform@one@point{#2}}%
  },
  grid target corners/.code args={#1--#2--#3--#4}{%
   \pgfextract@process\tikz@transform@target@southwest{%
     \tikz@scan@transform@one@point{#1}}%
   \pgfextract@process\tikz@transform@target@southeast{%
     \tikz@scan@transform@one@point{#2}}%
   \pgfextract@process\tikz@transform@target@northeast{%
     \tikz@scan@transform@one@point{#3}}%
   \pgfextract@process\tikz@transform@target@northwest{%
     \tikz@scan@transform@one@point{#4}}%
  }
}

\def\tikzgridtransform{%
  \pgfextract@process\tikz@current@point{}%
  \pgf@process{%
    \pgfpointdiff{\tikz@transform@source@southwest}%
      {\tikz@transform@source@northeast}%
  }%
  \pgf@xc=\pgf@x\pgf@yc=\pgf@y%
  \pgf@process{%
    \pgfpointdiff{\tikz@transform@source@southwest}{\tikz@current@point}%
  }%
  \pgfmathparse{\pgf@x/\pgf@xc}\let\tikz@tx=\pgfmathresult%
  \pgfmathparse{\pgf@y/\pgf@yc}\let\tikz@ty=\pgfmathresult%
  %
  \pgfpointlineattime{\tikz@ty}{%
    \pgfpointlineattime{\tikz@tx}{\tikz@transform@target@southwest}%
      {\tikz@transform@target@southeast}}{%
    \pgfpointlineattime{\tikz@tx}{\tikz@transform@target@northwest}%
      {\tikz@transform@target@northeast}}%
}

% Initialize H matrix for perspective view
\pgfmathsetmacro\H@tpp@aa{1}\pgfmathsetmacro\H@tpp@ab{0}\pgfmathsetmacro\H@tpp@ac{0}%\pgfmathsetmacro\H@tpp@ad{0}
\pgfmathsetmacro\H@tpp@ba{0}\pgfmathsetmacro\H@tpp@bb{1}\pgfmathsetmacro\H@tpp@bc{0}%\pgfmathsetmacro\H@tpp@bd{0}
\pgfmathsetmacro\H@tpp@ca{0}\pgfmathsetmacro\H@tpp@cb{0}\pgfmathsetmacro\H@tpp@cc{1}%\pgfmathsetmacro\H@tpp@cd{0}
\pgfmathsetmacro\H@tpp@da{0}\pgfmathsetmacro\H@tpp@db{0}\pgfmathsetmacro\H@tpp@dc{0}%\pgfmathsetmacro\H@tpp@dd{1}

%Initialize H matrix for main rotation
\pgfmathsetmacro\H@rot@aa{1}\pgfmathsetmacro\H@rot@ab{0}\pgfmathsetmacro\H@rot@ac{0}%\pgfmathsetmacro\H@rot@ad{0}
\pgfmathsetmacro\H@rot@ba{0}\pgfmathsetmacro\H@rot@bb{1}\pgfmathsetmacro\H@rot@bc{0}%\pgfmathsetmacro\H@rot@bd{0}
\pgfmathsetmacro\H@rot@ca{0}\pgfmathsetmacro\H@rot@cb{0}\pgfmathsetmacro\H@rot@cc{1}%\pgfmathsetmacro\H@rot@cd{0}
%\pgfmathsetmacro\H@rot@da{0}\pgfmathsetmacro\H@rot@db{0}\pgfmathsetmacro\H@rot@dc{0}\pgfmathsetmacro\H@rot@dd{1}

\pgfkeys{
    /three point perspective/.cd,
        p/.code args={(#1,#2,#3)}{
            \pgfmathparse{int(round(#1))}
            \ifnum\pgfmathresult=0\else
                \pgfmathsetmacro\H@tpp@ba{#2/#1}
                \pgfmathsetmacro\H@tpp@ca{#3/#1}
                \pgfmathsetmacro\H@tpp@da{ 1/#1}
                \coordinate (vp-p) at (#1,#2,#3);
            \fi
        },
        q/.code args={(#1,#2,#3)}{
            \pgfmathparse{int(round(#2))}
            \ifnum\pgfmathresult=0\else
                \pgfmathsetmacro\H@tpp@ab{#1/#2}
                \pgfmathsetmacro\H@tpp@cb{#3/#2}
                \pgfmathsetmacro\H@tpp@db{ 1/#2}
                \coordinate (vp-q) at (#1,#2,#3);
            \fi
        },
        r/.code args={(#1,#2,#3)}{
            \pgfmathparse{int(round(#3))}
            \ifnum\pgfmathresult=0\else
                \pgfmathsetmacro\H@tpp@ac{#1/#3}
                \pgfmathsetmacro\H@tpp@bc{#2/#3}
                \pgfmathsetmacro\H@tpp@dc{ 1/#3}
                \coordinate (vp-r) at (#1,#2,#3);
            \fi
        },
        coordinate/.code args={#1,#2,#3}{
           \pgfmathsetmacro\tpp@x{#1} %<- Max' fix
            \pgfmathsetmacro\tpp@y{#2}
            \pgfmathsetmacro\tpp@z{#3}
        },
}

\tikzset{
    view/.code 2 args={
        \pgfmathsetmacro\rot@main@theta{#1}
        \pgfmathsetmacro\rot@main@phi{#2}
        % Row 1
        \pgfmathsetmacro\H@rot@aa{cos(\rot@main@phi)}
        \pgfmathsetmacro\H@rot@ab{sin(\rot@main@phi)}
        \pgfmathsetmacro\H@rot@ac{0}
        % Row 2
        \pgfmathsetmacro\H@rot@ba{-cos(\rot@main@theta)*sin(\rot@main@phi)}
        \pgfmathsetmacro\H@rot@bb{cos(\rot@main@phi)*cos(\rot@main@theta)}
        \pgfmathsetmacro\H@rot@bc{sin(\rot@main@theta)}
        % Row 3
        \pgfmathsetmacro\H@m@ca{sin(\rot@main@phi)*sin(\rot@main@theta)}
        \pgfmathsetmacro\H@m@cb{-cos(\rot@main@phi)*sin(\rot@main@theta)}
        \pgfmathsetmacro\H@m@cc{cos(\rot@main@theta)}
        % Set vector values
        \pgfmathsetmacro\vec@x@x{\H@rot@aa}
        \pgfmathsetmacro\vec@y@x{\H@rot@ab}
        \pgfmathsetmacro\vec@z@x{\H@rot@ac}
        \pgfmathsetmacro\vec@x@y{\H@rot@ba}
        \pgfmathsetmacro\vec@y@y{\H@rot@bb}
        \pgfmathsetmacro\vec@z@y{\H@rot@bc}
        % Set pgf vectors
        \pgfsetxvec{\pgfpoint{\vec@x@x cm}{\vec@x@y cm}}
        \pgfsetyvec{\pgfpoint{\vec@y@x cm}{\vec@y@y cm}}
        \pgfsetzvec{\pgfpoint{\vec@z@x cm}{\vec@z@y cm}}
    },
}

\tikzset{
    perspective/.code={\pgfkeys{/three point perspective/.cd,#1}},
    perspective/.default={p={(15,0,0)},q={(0,15,0)},r={(0,0,50)}},
}

\tikzdeclarecoordinatesystem{three point perspective}{
    \pgfkeys{/three point perspective/.cd,coordinate={#1}}
    \pgfmathsetmacro\temp@p@w{\H@tpp@da*\tpp@x + \H@tpp@db*\tpp@y + \H@tpp@dc*\tpp@z + 1}
    \pgfmathsetmacro\temp@p@x{(\H@tpp@aa*\tpp@x + \H@tpp@ab*\tpp@y + \H@tpp@ac*\tpp@z)/\temp@p@w}
    \pgfmathsetmacro\temp@p@y{(\H@tpp@ba*\tpp@x + \H@tpp@bb*\tpp@y + \H@tpp@bc*\tpp@z)/\temp@p@w}
    \pgfmathsetmacro\temp@p@z{(\H@tpp@ca*\tpp@x + \H@tpp@cb*\tpp@y + \H@tpp@cc*\tpp@z)/\temp@p@w}
    \pgfpointxyz{\temp@p@x}{\temp@p@y}{\temp@p@z}
}
\tikzaliascoordinatesystem{tpp}{three point perspective}

\makeatother


\begin{document}
\tdplotsetmaincoords{80}{-20}
\begin{tikzpicture}[scale=pi,%tdplot_main_coords
  view={\tdplotmaintheta}{\tdplotmainphi},
            perspective={
                p = {(5,0,0.5)},
                q = {(0,4,0.5)},
            },
  declare function={potential(\x)=-0.0314*pow(abs(\x),2);}          
  ]
  \draw[thick] plot[variable=\x,domain=0:360,samples=37,smooth] 
  (tpp cs:{cos(\x)},{sin(\x)},0);
  \pgfmathsetmacro{\Nion}{40}
  \pgfmathsetmacro{\Dist}{360/\Nion}
  \pgfmathsetmacro{\xmin}{1}
  \pgfmathsetmacro{\xmax}{\Dist-\xmin}
  \draw[-latex] (tpp cs:0,-1,0) -- (tpp cs:0,-1,{1.2*potential(\xmin-\Dist/2)})
  node[right]{$V$};
  \draw[-latex] plot[variable=\x,domain=0:\Dist,samples={\Dist+1},smooth] 
  (tpp  cs:{cos(-90+\x)},{sin(-90+\x)},{-0.2*potential(\xmin-\Dist/2)});
  \node[anchor=south] at (tpp  cs:{cos(-90+\Dist/2)},{sin(-90+\Dist/2)},{-0.22*potential(\xmin-\Dist/2)})
  {$x$};
  \foreach \index in {1,...,\Nion}
   {\draw plot[variable=\x,domain=\xmin:\xmax,samples={\Dist+1},smooth] 
  (tpp
  cs:{cos(\x+\index*\Dist)},{sin(\x+\index*\Dist)},{potential(\x-\Dist/2)});
  \fill let \p1=($(tpp cs:{cos(\index*\Dist)},{sin(\index*\Dist)},2)-
  (tpp cs:{cos(\index*\Dist)},{sin(\index*\Dist)},0)$),\n1={veclen(\x1,\y1)}
  in
  (tpp cs:{cos(\index*\Dist)},{sin(\index*\Dist)},0) circle(\n1*0.01pt);
    }
\end{tikzpicture}
\end{document}

enter image description here

  1. What the perspective key precisely does, is explained very well in Max' great answer, which deserves IMHO many more upvotes. Note, however, that if you change the radius of the circle too much, then you may also want to increase the coordinates of the perspective points p and q in order to avoid division by zero problems.
  2. The potential is defined in declare function={potential(\x)=-0.0314*pow(abs(\x),2);}.
  3. The number of ions is set by \pgfmathsetmacro{\Nion}{40}.
  4. Since in your upper screen shot there is a gap, I added a parameter controlling the width of the gap: \pgfmathsetmacro{\xmin}{1}. This means that the gap is 2*\xmin=2 degrees wide.

If you keep the above preamble but change the document to become (note that I also load the backgrounds library now)

\usetikzlibrary{backgrounds}
\begin{document}
\tdplotsetmaincoords{80}{-20}
\begin{tikzpicture}[scale=pi,%tdplot_main_coords
      view={\tdplotmaintheta}{\tdplotmainphi},
                perspective={
                    p = {(5,0,0.5)},
                    q = {(0,4,0.5)},
                },
      declare function={potential(\x)=ifthenelse(abs(\x)<\Dist/4,0,-0.6);}          
      ]
      \draw[thick] plot[variable=\x,domain=0:360,samples=37,smooth] 
      (tpp cs:{cos(\x)},{sin(\x)},0);
      \pgfmathsetmacro{\Nion}{40}
      \pgfmathsetmacro{\Dist}{360/\Nion}
      \pgfmathsetmacro{\xmin}{0}
      \pgfmathsetmacro{\xmax}{\Dist-\xmin}
      \draw[-latex] (tpp cs:0,-1,0) -- (tpp cs:0,-1,{1.2*potential(\xmin-\Dist/2)})
      node[right]{$V$};
      \draw[-latex] plot[variable=\x,domain=0:\Dist,samples={\Dist+1},smooth] 
      (tpp  cs:{cos(-90+\x)},{sin(-90+\x)},{-0.2*potential(\xmin-\Dist/2)});
      \node[anchor=south] at (tpp  cs:{cos(-90+\Dist/2)},{sin(-90+\Dist/2)},{-0.22*potential(\xmin-\Dist/2)})
      {$x$};
      \foreach \index in {1,...,\Nion}
       {\begin{scope}[on background layer]
       \draw[thick,blue] plot[variable=\x,domain=\xmin:\xmax,samples={29}] 
      (tpp
      cs:{cos(\x+\index*\Dist)},{sin(\x+\index*\Dist)},{potential(\x-\Dist/2)});
      \end{scope}
      \fill let \p1=($(tpp cs:{cos(\index*\Dist)},{sin(\index*\Dist)},2)-
  (tpp cs:{cos(\index*\Dist)},{sin(\index*\Dist)},0)$),\n1={veclen(\x1,\y1)}
  in
  (tpp cs:{cos(\index*\Dist)},{sin(\index*\Dist)},0) circle(\n1*0.01pt);
        }
    \end{tikzpicture}
\end{document}

enter image description here

(The potential lines are not precisely vertical here, but almost and become more vertical if you increase the sample. You can change this y replacing the plot by an appropriate combination of lines, please let me know if you need assistance for this.)

UPDATE: Made the diameters of the ions also dependent on the distance to enhance the 3D effect.

  • Absolutely brilliant! The potentials should just be quadratic, so what you have is already great. Just some things: 1) How can you increase the number of 'particles' along the ring? 2) How can you equivalently change the quadratic potentials for rectangular potentials (width half of the particle separations)?, 3) The labels and axes would be nice to have. – Sid Sep 24 '18 at 19:03
  • i'm just interested to see how the output looks at the number of particles is changed up to say 40. 2) I'll update the question to show what I mean. – Sid Sep 24 '18 at 19:49
  • @Sid Thanks but I disagree. I am only using Max' code. Please make this comment to him (and also don't forget to upvote his really great answer. ;-) –  Sep 24 '18 at 20:47
  • 1
    I already did based on your initial answer! – Sid Sep 24 '18 at 22:18