#!/bin/sh

""":"
exec python $0 ${1+"$@"}
"""

# ---------------------- HelloWaves.py ----------------------
#  
# This program demonstrates how to make an animation of the 
# wave equation. The user can specify the initial 
# conditions by dragging the graph.
# 
# For an extended version and explanation of the
# wave equation, see HelloWavesExt.py
#  

from Tkinter import *        # The Tk package
import Pmw                   # The Python MegaWidget package
import math                  # import the sin-function

master = Tk()                # build Tk-environment
npoints = 15                 # use 10 points on each curve

def mouseDrag(event):
    global idx
    
    u[idx] = g.yaxis_invtransform(event.y)
    g.element_configure("string", ydata=tuple(u))
    
def mouseDown(event):
    global idx
    
    g.element_bind("string", "<Motion>", mouseDrag)
    el = g.element_closest(event.x, event.y)
    idx  = el["index"]

def mouseUp(event):
    g.element_unbind("string", "<Motion>")
    
def run():
   global u, up, um, C
   
   g.element_configure("string", symbol="") 
   init()
   ntimesteps = 200  # the length of the animation
   
   for t in range(ntimesteps):
       for i in range(1, len(u)-1):
                  up[i] = 2*u[i] -um[i] + C*C*(u[i+1] - 2*u[i] + u[i-1])
                 
       um = u[:]
       u  = up[:]       
       g.element_configure("string", ydata=tuple(u))
                 
       master.after(10)           # wait 0.01 second
       master.update_idletasks()  # update screen
       
   g.element_configure("string", symbol="circle") 
   
               
def init():
    global u, up, um, C
    C = 0.8    
    # make special value for um (incorporating du/dt=0 at t=0):
    um = u[:]  # ensure that um is an array of correct length...
    for i in range(1, len(um)-1):
        um[i] = u[i] + 0.5*C*C*(u[i+1] - 2*u[i] + u[i-1])

    up = u[:]
        
if not Pmw.Blt.haveblt(master):     # Is Blt installed?
   print("BLT is not installed!")

else:
   vector_x = []   # x values (grid points used in the numerical scheme)
   u        = []   # u values (as computed by the wave equation)
   
   # make a default graph
   for x in range(npoints+1): 
      vector_x.append(x*0.1)
      if(x < 2.0*npoints/3):
          u.append(x/(2.0*npoints/3))
      else:        
          u.append(float(npoints-x)/(npoints/3))

   g = Pmw.Blt.Graph(master)                 # make a new graph area
   g.pack(expand=1, fill='both')

   curvename = 'string'                   
   g.line_create(curvename,               
                 xdata=tuple(vector_x),   
                 ydata=tuple(u),          
                 pixels=7,
                 smooth='natural')           # use spline smoothing
   
   g.element_bind("string", "<ButtonPress>",   mouseDown)
   g.element_bind("string", "<ButtonRelease>", mouseUp  )
   
   g.yaxis_configure(min=-1, max=1)
   g.configure(title='Hello world of waves', bufferelements=0)
   
   buttons = Pmw.ButtonBox(master, labelpos='n', label_text='Options')
   buttons.pack(fill='none', expand=0, padx=10, pady=10)

   buttons.add('Simulate',   command=run)
   buttons.add('Quit',       command=master.quit)

   master.mainloop()