An Introduction to visulaization of Physical system
DISCLAIMER: The “Animate a Cycloid” topic is developed step by step. There is a some repeatation of large code blocks. So it may seems to be lengthy but it is actually not!
Visualizing a system by plotting a graph is always of great interest for practising professionals in any stream. But the advancement of technology now allows us more than just plotting. Nowadays “Just plotting” is an old fashion. Either it is teaching or presenting an idea in front of the audience, or just for self-learning, it is always a good idea to animate the system somehow. Or you may just want to plot a time-varying graph. Here I’ll discuss techniques and tricks for the same.
GNUPlot is simple, elegant and great for First and Fast
learning. Although there are several packages/software, some are too advanced, we will be using good old GNUPlot. My personal believe (fortunately, many people agree to that) is that if you can learn one such package, the skill is transferable. So you can go on learning as per your preference.
I believe, most of you is already equipped with Lagrangian and Hamiltonian formalism. So the idea is to show the technique to produce GIFs(Graphics Interchange Format) and then to show how to simulate a simple system when the Lagrangian(or Hamiltonian) of the system is given a priori. After the second half, the reader must be able to animate simple systems of their choice. In a later post, I’ll also show how to do animation from a data file. That will give you a wing to use GNUPlot with any other programming language. Although GNUPlot terminal can be linked to other programming languages, let’s don’t make thing complicated with that technical jargon. Now it’s enough of hunky-junky. Let’s get into the topic with the so-called ‘hello-world GNUPlot script for the animation.
Unlike writing command directly in the terminal, we can create a simple text file listing all the commands. Save it with an extension ‘.gnu’(say, cos.gnu). Then from the terminal just type gnuplot cos.gnu
and hit Enter
. The file may contain the following
reset
set term qt
set xrange[-2*pi:2*pi]
set yrange[-1.5:1.5]
plot cos(x)
reread #optional
Sometimes it is convenient to put the
reread
statement at the end line. It’ll keep the plotting window open. For some system, it may not be required for ordinary plotting. However, if you’re usingreread
, then keep in your mind that closing the plot window will not do the job, it’ll pop up again. Rather you would like to executeCtrl+C
in the terminal to stop the execution and close the plotting window. *Alternativel, for static plots, one may use--persists
argument in the command line, likegnuplot cos.gnu --persists
Now let’s have a train of sine wave
reset
set term qt
set nokey #Optional
set title 'Sine wave train'
set xrange[-2*pi:2*pi]
set yrange[-1.5:1.5]
func(x, w, t) = sin(x + w*t)
do for[loopNo=1:100]{
plot func(x, 0.5, loopNo)
}
reread
Output in your screen is too fast, isn’t it? No problem we will fix it later. Have some patience! :P
Notice that we’ve used the plot
command within the loop. And that’s the trick, you’re just plotting the same thing over and over again for different instances(here loopNo) and you get the animation like output. There are various method to save this animation. We will discuss those from time to time in the various examples.
set nokey
(As I’ve done in the above script). It’ll disable legend.plot
line one can directly use plot sin(x + 0.5*i)
, but the notion of function will be useful in the next example, so I thought it’ll be nice to introduce beforehand. In case you haven’t seen this before, it is just a black-box kind of thing, where you define the function with the specific arguments(in this case, x, w, t). Whenever required, you just call that function with the specific arguments. That’s it!Now, we’ll look into a better picture, a better animation!
We will build this script step by step! In the end, we will see a stunning animated cycloid just like the above GIF.
The idea is to trace a particular point of a moving circle. So, first thing first. We will need a circle. For that, we will consider the parametric setup.
#setting up the enviorment
reset
set term qt
set nokey
set paramteric
s= 4 # radius of the circle
plot s*cos(t), s*sin(t)
# in the parametric enviorment, the parameter is predefined as 't' by GNUPlot itself
reread #you must be executing Ctrl+C in the terminal to stop the execution.
You may see an elongated/squeezed circle in the output. You can get rid of this by scaling the size. But for that, you must specify the xrange
and yrange
. Then you can calculate the ratio. But if you’re lazy enough like me, you might want a better solution. The trick is to set the ratio to be -1. In that case, GNUPlot will do the job for you. So just add another line to the above script set size ratio -1
.
cirX
and cirY
with three arguments, the “intrinsic parameter”(that ‘t’, you may change the variable for function since it’s a dummy one, there shouldn’t be a problem. I’ll call it par
here. ), the radius of the circle and the instances(loop number).
cirX(r, i, par) = r*i + r*cos(par)
# the term r*i is added due to the fact, as time passes, circle will be rotated by an angle 'i'(say),
# so the linear distance traveled by the circle is radius*angle(=r*i)
cirY(r, i, par)= r + r*sin(par) # Although we are not using 'i' here(since y co-ordinate of the centre is not changing),
# so you may not want to mention it.
# The additional r term is because I wanted that the circle must be moving on the y=0 line.
# If you are okay with the circle is moving along y=-r line, then you need not to add that term.
px(r, i)
and py(r, i)
px(r, i) = r*i + r*cos(i)
py(r, i) = r + r*sin(i)
# Here we haven't pass the generic parameter 'par', because we are concerned about a particular point only,
# which is located at an angle 'i'
sin
and cos
are defined to take an angle in radians as the argument, we must convert the angle into radian. After plugging everything here discussed, we have the following script:
# setting up the enviorment
reset
set term qt
set size ratio -1
set nokey
set xrange[-pi:7*pi]
# set maximum range greater than 2*pi*r*number_of_rotation
set yrange[0:5]
# must be grater than radius of circle
# If you do not want to uplift the cirY by the radius,
# then you must extend the yrange to the negative axis.
set parametric
# setting up the function
cirX(r, i, par) = r*i + r*cos(par)
cirY(r, i, par)= r + r*sin(par)
px(r, i) = r*i + r*cos(i)
py(r, i) = r + r*sin(i)
# Defining the radius and coversion factor
s = 2
conv = pi/180
#multiplication by 2 emphasize the fact we will have 2 full rotation
do for[deg=0:360*2]{
rad = deg*conv
# plotting the circle for each instances
# If you haven't pass three argument, you must pass only s and t through cirY!
# Here the 't' is really the 'intrinsic parameter of the GNUPlot
plot cirX(s, rad, t), cirY(s, rad, t)
# plot an arrow with nohead(actually the radius)
# Notice that, we plot the arrow from s*rad (linear distance traversed by the circle.)
set arrow 1 nohead from s*rad, s to px(s, rad), py(s,rad) lc rgb 'red'
# The circle object is a point on a circle
set object 2 circle at px(s, rad), py(s, rad) fc rgb 'red' size 0.05 fs solid front
# 1 and 2 number is the identifier of the arrow and the circle respectively
}
reread
If you inspect the output closely, the point is rotating anti-clockwise but the advancement of the circle in the positive direction. To change the direction, just subtract the angle by 2*pi from cirX and cirY function. Another point is that the rotation starts from the line y=radius line. I wanted to start the rotation from y=0, so I’ll change the phase by pi/2.
Here we will set
gif animate
type terminal and an output file with a .gif extension.gif animate
usually take a long time(strictly speaking, depends upon the computational complexity of the problem and the number of frame/instance you are producing) to produce the output file. So you may need to wait for a while.
The output will be very much similar to the above one. You may like to use this website to speed up or reduce the size of GIF, or maybe you want to convert the GIF into a video!
If you’re having any difficulty, you can always contact me. But it’ll be better if you do comment below this post. Since community learning is the best thing that one can have!
The only thing I’m asking in return, please share your feedback, either by email/social-media or comment here.
These tips may not seem to be clear unless you really start to work on the problem. Only then you’ll understand what I’m talking about.
array array_name=[element1, element2, element3....]
To access the elements you may use array_name[index]. In GNUPlot the index starts from 1.
You may want to use a nested loop while plotting different instances.
THIS IS, MAYBE, OPTIONAL: If you’re using a nested loop, make sure you plot all the circles using a single plot
command before you start an inner loop to plot the different radius vector and trajectory corresponding to those vectors. For my machine, GNUPlot was unable to take that huge load of plotting the circles from an inner loop. So I was generating an output with blinking circles.
To keep the track of trajectory of the corresponding radius vectors, use the identifier in the following form: (angle+j)**j [Here j stands for different circles like 1, 2, 3- can be identified as the index of the inner loop] so that the identifier is varied widely for different objects. Then it’ll be easier for GNUPlot to keep track of the various different object.
Here I’ve uploaded the solution ;)