8

I would like to draw some kind of wraped grid with a possible animation. I split my problem into two questions, the first one being more important than the second one. For the few mathematical formula below, I will use the symbols "$$" (recognized by LaTeX). I have no experience in making complicated pictures, and even less in making animations, with LaTeX.

  • My first goal is to draw a grid with an exponentially decreasing sine form : we can visualize the waveform of the surface of water after a perturbation (e.g. we throw a rock in a lake). Here a picture showing how I would like to draw the grid : "Rigid grid" I first thought to add the grid on the above surface by hand, but it would be really tough and surely not as good as a true grid. Furthermore, I do not see how to draw sine-like waves (starting from the black point and expanding like spherical waves) on the grid. Here's another picture showing a distorted green grid (found on the web) :"Curved spacetime"

    Question 1 : Is there a way to draw a grid oriented as in the first above picture and distorted by a given function $f$ as in the second above picture ?

To have a concrete example, we can choose $f(r,\theta)=\sin(\theta)\sum_{k=1}^{n}\exp(-a_{k}r)\cos(b_{k}r)r^{k}$ with $n$ a strictly positive integer, $a_{k}>0$ and $b_{k}$ some real numbers, $r>0$ a real number and $\theta$ an angle between $0$ and $2\pi$.

  • My second goal is "simply" to animate the expansion of the perturbation on the grid. I saw some codes in these beautiful examples : How to plot circular polarized electromagnetic wave, my first animate project times out. In the first case, I don't know hom to have the animation on the final PDF (I have some pictures at different times of the motion, one per page) ; in the second case, the LaTeX just can't compile the code!

    Question 2 : Once the distorted grid drawn, how to animate it on the final PDF ? Which pacakages are required for this ?

I will appreciate any help/suggestion.

  • Throwing a rock in a lake gives you Bessel functions, at a rough approximation for small amplitude waves. en.wikipedia.org/wiki/Bessel_function – Benjamin McKay May 12 '16 at 17:19
  • @BenjaminMcKay Yes you're right, I recognize that my sentence was misleading on this point : I wanted to give a simple example of perturbation propagation that everyone can imagine. The exponentially sine decay is not the mathematical solution obtained when one throws a rock in a lake, it is just what I want to see in the animation. Thanks anyway for your precision. – Nicolas May 12 '16 at 21:34
13
+100

Here is a solution using LuaLaTeX for two reasons:

  • there are many complex formula in this graph, so it's easier with a real programming language
  • there are a lot of trigonometric calculations, and for this Lua is faster than TeX

The LaTeX file:

\documentclass{minimal}

\usepackage[a4paper,top=20mm,bottom=20mm,left=15mm,right=15mm]{geometry}
\usepackage{tikz}
\usepackage{animate}

\begin{document}

\directlua{require("anim.lua");}
\begin{center}
    \begin{animateinline}[poster=first,controls,loop]{20}
        \multiframe{20}{rt=0+0.05}{
            \begin{tikzpicture}
                \useasboundingbox (-8.5,-5.4) rectangle (8.5,3.1);
                \directlua{plot_grid(8,4,0.3,\rt);}
            \end{tikzpicture}
        }
    \end{animateinline}
\end{center}


\end{document}

File anim.lua (in same directory):

ak,bk,omegak={0.6,0.8},{10,20},{2*math.pi,4*math.pi} -- list of coefs
zmax=2
function wave(r,theta,t)
    sum=0
    for k=1,#ak do
        sum=sum+math.exp(-ak[k]*r)*math.cos(bk[k]*r-omegak[k]*t)*r^k
    end
    return sum*math.sin(theta)
end
function color(z) -- color of facets
    if z>0 then if z<zmax then col="red!"..(100*z/zmax); else col="red"; end -- red color for positive wave values
    else if z>-zmax then col="blue!"..(-100*z/zmax); else col="blue"; end -- blue color for positive wave values
    end
    return col
end
function plot_grid(width,height,shrink,t)
    local gridx,gridy={},{}
    local Nr,Nt=20,10
    local zscale=1
    for i=0,Nr do
        local r=i/Nr
        gridx[i]={}
        gridy[i]={}
        for j=-Nt,Nt do
            local theta=math.pi*j/Nt
            local z=wave(r,theta,t)
            local factor=1-shrink*math.cos(theta)
            local x=r*width*factor*math.sin(theta)
            local y=r*height*factor*math.cos(theta)+z*zscale*factor
            gridx[i][j]=x
            gridy[i][j]=y
        end
    end

    -- grid faces, from top to bottom
    for j=0,Nt-1 do
        local theta=math.pi*j/Nt
        local start,stop,step=0,Nr-1,1
        if theta<math.pi/2 then start,stop,step=Nr-1,0,-1; end
        for i=start,stop,step do
            local r=i/Nr
            -- print facet at (r,theta)
            tex.print("\\filldraw[fill="..color(wave(r,theta,t)).."] ("..gridx[i][j]..","..gridy[i][j]..") -- ("..gridx[i+1][j]..","..gridy[i+1][j]..") -- ("..gridx[i+1][j+1]..","..gridy[i+1][j+1]..") -- ("..gridx[i][j+1]..","..gridy[i][j+1]..") -- cycle;")
            -- print facet at (r,-theta)
            tex.print("\\filldraw[fill="..color(wave(r,-theta,t)).."] ("..gridx[i][-j]..","..gridy[i][-j]..") -- ("..gridx[i+1][-j]..","..gridy[i+1][-j]..") -- ("..gridx[i+1][-j-1]..","..gridy[i+1][-j-1]..") -- ("..gridx[i][-j-1]..","..gridy[i][-j-1]..") -- cycle;")

        end
    end
end

You can compile it twice with lualatex and then open it with Acrobat Reader (the only reader that shows animations). The result is: enter image description here


Explanations:

First of all, a little word about LuaLaTeX. It's like another LaTeX engine, but you can add Lua code inside. Lua is a simple scripting language, with functions, loops and conditional statements like others. Lua chunks are included for example in directlua{...} statements. When LuaLaTeX compiles the files, the directlua{...} are executed and replaced by their output; which is LaTeX code; for example, here the line \directlua{plot_grid(8,4,0.3,\rt);} is replaced by

\filldraw[fill=blue!-0] (0,2.66) -- (0,2.8) -- (-1.7667936522486,2.8044534789179) -- (-1.6784539696362,2.6194714601329) -- cycle;
\filldraw[fill=blue!0] (0,2.52) -- (0,2.66) -- (1.6784539696362,2.5462786901229) -- (1.5901142870238,2.3797166001964) -- cycle;
\filldraw[fill=blue!-0] (0,2.52) -- (0,2.66) -- (-1.6784539696362,2.6194714601329) -- (-1.5901142870238,2.5141519632038) -- cycle;
....

that is, Tikz commands. Then a pure LaTeX document is generated and compiled as another LaTeX document.

As a summary: LuaLaTeX documents are normal LaTeX ones, but with some Lua chunks that generates many LaTeX code in place of you.

Then as to the files, commencing with the LaTeX one: it's very simple; \animateinline defines an animation with 20 frames and looping, and \multiframe iterates time (real variable \rt) from 0 with step 0.05, and do this 20 times, so that \rt will have values: 0,0.05,0.10,...,0.95. Then we define a tikzpicture with a bounding box (thanks to AlexG) and call Lua plot_grid function which will generate all the graph.

The anim.lua file begins with global variables definitions: 3 arrays of coefficients corresponding to the sum you've proposed for the wave. You can add more coefs, but the 3 arrays must have same length. Then zmax is for coloring, we will see that further.

Function wave is used to compute the wave value at r,θ coordinates and t time. It computes a sum using the coefficients (this part I think is difficult in pure LaTeX) and returns the result.

Function color is for coloring the facets, we will use it later. If z>zmax the color is red; if 0 < z < zmax the color is partially red; and the same with blue for negative values.

Function plot_grid has two part. First, it calculates the cordinates of each node of the grid. It creates two empty arrays, and defines the numbers Nr and Nt of points. In the loops, you can see that r will go from 0 to 1 with Nr intervals, and theta from -π to +π with 2 Nt intervals. Then for each (r,θ) pairs it proceeds as follow:

  • compute the perspective factor. Normally the grid would show from -width to +width and -height to +height. But in your question you wanted some perspective, that is the grid on the top is smaller than on the bottom. Here I introduce parameter shrink which has this meaning: on the top, the grid size is multiplied by 1-shrink and on the bottom it is multiplied by 1+shrink.
  • compute the x and y position. The factor is used to multiply the width and height of the grid, and in y we add the amplitude of the wave (z) multipliez by a scaling factor which you can modify.
  • store the results in the arrays

When this is done, we can draw the facets, from top to bottom beacause of perspective. That's the second loop. We begin with θ close to 0, which are the farther facets. The start,stop,step lines are for perspective also: if -π/2<θ<π/2 then we should draw the big radius first and go to the center, in other cases we should go from center to border. Then comes the heart of that: tex.print allows to print output which will be replaced in the LaTeX document. Here it is a simple \filldraw Tikz command; string concatenation is .. in Lua. You can remark also that we draw simultaneously (r,θ) and (r,-θ) facets.

Concluding remark: The first time I tried LuaLaTeX I was afraid, but since then I've become found of it. When you do scientific graphs or simulations, it's really useful. With Lua in my LaTeX documents, I can draw complex plots, draw implicit plots, solve ODE, integrate functions, and then do entire simulations in my LaTeX document. It's necessary to learn a new (simple) programming language, but the power of Lua+LaTeX is awesome!

  • Thanks for your answer. If I understand correctly, I need to download LuaLaTeX to use your code ? then I use two distinct documents (but in the same directory), one for The LaTex file and one another for File? – Nicolas May 12 '16 at 10:49
  • Yes. LuaLaTeX is usually installed with TeXlive. Here I have put the Lua program in another document, but it is possible to embed the Lua code in the LaTeX document with begin{luacode*}...\end{luacode*} – JPG May 12 '16 at 10:51
  • Ok! Before I test it, can you tell me if there is any difference between LaTeX and LuaLaTeX when I want to write a (mathematical) document ? – Nicolas May 12 '16 at 10:59
  • No, it's only that you can use Lua programming language inside (and also Unidoce characters). – JPG May 12 '16 at 11:01
  • 2
    In the animated PDF, the plot jumps somewhat due to different bounding box sizes of the animation frames. This can be remedied by adding a common bbox: \begin{tikzpicture}\useasboundingbox (-8.5,-5.4) rectangle (8.5,3.1);...\end{tikzpicture} – AlexG May 12 '16 at 13:22
1

You can start with the following code...

Ensure, that each picture is in a own environment...

\PassOptionsToPackage{pst,dvipsnames,table,svgnames,xcdraw,showerrors}{xcolor}
\documentclass[multi,crop,pstricks,border=0.15cm]{standalone}

\standaloneenv{my}

\usepackage[T1]{fontenc} % Use 8-bit encoding that has 256 glyphs
\usepackage[ansinew]{inputenc} % Uses the utf8 input encoding
\usepackage{graphics}


\usepackage{xcolor}
\usepackage{pst-perspective}
\usepackage{auto-pst-pdf}


\begin{document}

\begin{my}
\begin{pspicture}[showgrid=false](3,2)(11,6)
% \psgrid
\rput(7,4){\psCircleTS[fillstyle=solid,fillcolor=blue,opacity=0.5]{2}}
\rput(7,4){\psCircleTS[fillstyle=solid,fillcolor=blue,opacity=0.5]{2.5}}
\rput(7,4){\psCircleTS[fillstyle=solid,fillcolor=blue,opacity=0.5]{3.0}}
\rput(7,4){\psCircleTS[fillstyle=solid,fillcolor=blue,opacity=0.5]{3.5}}
\end{pspicture}
\end{my}


\end{document}

For sure a lot of more work is to do, most likely you need some more pstricks packages... and it is recommended, to use \usepackage{xsavebox} to decrease filesize if you use repeated eps figures...

You can compile with pdflatex or latex - dvips - ps2pdf.

enter image description here

  • Thanks for your post. It is indeed the waves expansion profile that I look for, but there is no grid and decreasing sine waves as we go away from the central point. Any idea for this ? – Nicolas May 12 '16 at 10:29
  • It was only 5 Minutes of work to produce this. But I am very sure, that Herbert Voss can do similar things like the answer above. – Peter Ebelsberger May 12 '16 at 13:08

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.