7.8 SubroutinesSubroutines are similar to mathematical functions (see Section 4.3), and once defined, can be used anywhere in algebraic expressions, just as functions can be. However, instead of being defined by a single algebraic expression, whenever a subroutine is evaluated, a block of Pyxplot commands of arbitrary length is executed. This gives much greater flexibility for implementing complex algorithms. Subroutines are defined using the following syntax: subroutine <name>(<variable1>,...) { ... return <value> } Where name is the name of the subroutine, variable1 is an argument taken by the subroutine, and the value passed to the return statement is the value returned to the caller. Once the return statement is reached, execution of the subroutine is terminated. The following two examples would produce entirely equivalent results: f(x,y) = x*sin(y) subroutine f(x,y) { return x*sin(y) } In either case, the function/subroutine could be evaluated by typing: print f(1,pi/2) If a subroutine ends without any value being returned using the return statement, then a value of zero is returned. Subroutines may serve one of two purposes. In many cases they are used to implement complicated mathematical functions for which no simple algebraic expression may be given. Secondly, they may be used to repetitively execute a set of commands whenever they are required. In the latter case, the subroutine may not have a return value, but may merely be used as a mechanism for encapsulating a block of commands. In this case, the call command may be used to execute a subroutine, discarding any return value which it may produce, as in the example: pyxplot> subroutine f(x,y) { print "%s - %s = %s"%(x,y,x-y) ; } Example: An image of a Newton fractal Newton fractals are formed by iterating the equation
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() If ![]() ![]() ![]() ![]() set numerics complex set unit angle nodimensionless root1 = exp(i*unit( 0*deg)) root2 = exp(i*unit(120*deg)) root3 = exp(i*unit(240*deg)) tolerance = 1e-2 subroutine newtonFractal(x,y) { global iter z = x+i*y iter = 0 while (1) { z = z - (z**3-1)/(3*z**2) if abs(z-root1) ![]() if abs(z-root2) ![]() if abs(z-root3) ![]() iter = iter + 1 } } # Plot Newton fractal set size square set key below set xrange [-1.5:1.5] set yrange [-1.5:1.5] set sample grid 250x250 set colmap hsb(c1*0.667,0.8+0.2*c2,1.0-0.8*c2) set nocolkey set log c2 plot newtonFractal(x,y):iter+2 with colormap ![]() Example: The dynamics of the simple pendulum The equation of motion for a pendulum bob may be derived from the rotational analogue to Newton’s Second Law, ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]()
A more exact solution requires integration of the second-order differential equation of motion including the ![]()
where ![]() ![]() Below, we produce a plot of Equations () and (). The horizontal axis is demarcated in units of the dimensionless period of the pendulum to eliminate ![]() ![]() ![]() set unit angle nodimensionless theta_approx(a,t) = a*sin(2*pi*t) theta_exact (a,t) = 2*asin(sin(a/2)*jacobi_sn(2*pi*t,sin(a/2))) set unit of angle degrees set key below set xlabel r’Time / $ ![]() set ylabel r’$ ![]() omega = unit(30*deg) plot [0:4] theta_approx(omega,x) title ’Approximate solution’, ![]() theta_exact (omega,x) title ’Exact solution’ ![]() As is apparent, at this amplitude, the exact solution begins to deviate noticeably from the small-angle solution within 2–3 swings of the pendulum. We now seek to quantify more precisely how long the two solutions take to diverge by defining a subroutine to compute how long ![]() ![]() ![]() ![]() subroutine pendulumDivergenceTime(omega, deviation) { for t=0 to 20 step 0.05 { approx = theta_approx(omega,t) exact = theta_exact (omega,t) if (abs(approx-exact) ![]() } return t } set key top right set xlabel r’Amplitude of swing’ set ylabel r’Time / $ ![]() set samples 40 plot [unit(5*deg):unit(30*deg)][0:19] ![]() pendulumDivergenceTime(x,unit(20*deg)) title r"$20 ![]() ![]() ![]() pendulumDivergenceTime(x,unit(10*deg)) title r"$10 ![]() ![]() ![]() pendulumDivergenceTime(x,unit( 5*deg)) title r"$ 5 ![]() ![]() ![]()
|