function varargout = Vibrating_String(varargin)
% VIBRATING_STRING M-file for Vibrating_String.fig
%      VIBRATING_STRING, by itself, creates a new VIBRATING_STRING or raises the existing
%      singleton*.
%
%      H = VIBRATING_STRING returns the handle to a new VIBRATING_STRING or the handle to
%      the existing singleton*.
%
% How to use the GUI:
%    - To start the GUI, place the cursor on the string, left-click
%    and drag to define an initial deflection, then release the left
%    mouse button. The initial velocity is automatically set to zero
%    and the string starts vibrating.
%    - Select the "Left TW" and/or "Right TW" check boxes to see the
%    corresponding left- and/or right-going waves.
%    - Select the "Superposition" check box to see the sum of the
%    left- and right- traveling waves that describe the deflection
%    of the string.
%    - The "Reset" button reinitializes the GUI.
%    
% Developed by Joceline Lega, Mathematics Department, University
% of Arizona, Spring 2007.
% 


% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
    'gui_Singleton',  gui_Singleton, ...
    'gui_OpeningFcn', @Vibrating_String_OpeningFcn, ...
    'gui_OutputFcn',  @Vibrating_String_OutputFcn, ...
    'gui_LayoutFcn',  [] , ...
    'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before Vibrating_String is made visible.
function Vibrating_String_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to Vibrating_String (see VARARGIN)

global x
global c L delta_t

% Choose default command line output for Vibrating_String
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes Vibrating_String wait for user response (see UIRESUME)
% uiwait(handles.figure1);
set(handles.figure1,'Name',' Vibrating String');
axes(handles.axes1)
x=0:0.01:1;
c=1;
L=1;
delta_t = 0.05;

% Flat string
plot(x,zeros(size(x)),'r-','LineWidth',2)
ylim([-1 1])
hold on
plot([0 1 1 0 0],[-1 -1 1 1 -1],'-k')
axis off
hold off

axes(handles.axes2)
bar(0:10,zeros(11))
xlim([-0.5 10.5])
ylim([0 1])
title('Modes 0 through 10')
ylabel('Amplitude')

axes(handles.axes3)
hold on
plot([0 0],[-1 1],'--k')
plot([1 1],[-1 1],'--k')
plot([-1 2 2 -1 -1],[-1 -1 1 1 -1],'-k')
axis off

% Initial conditions
initial(hObject,eventdata,handles)

% Time-evolution of the coefficients
evolve(hObject,eventdata,handles)


% --- Outputs from this function are returned to the command line.
function varargout = Vibrating_String_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


function initial(hObject,eventdata,handles)

global x
global c L delta_t
global modes k n
global f

axes(handles.axes1)
waitforbuttonpress
point1 = get(gca,'CurrentPoint');    % button down detected
finalRect = rbbox;                   % return figure units
point2 = get(gca,'CurrentPoint');    % button up detected
x1=point2(1,1);
y1=point2(1,2);
xx=[0 x1 1];
yy=[0 y1 0];
yyy=interp1(xx,yy,x,'pchip');        % interpolate between selected point
% and end points
plot(x,yyy,'r-','LineWidth',2)
ylim([-1 1])
axis off
hold on
plot([0 1 1 0 0],[-1 -1 1 1 -1],'-k')
hold off

% Half-range sine expansion of yyy
n=size(x,2)-1;
y(1:n-1)=-yyy(n:-1:2);
y(n:2*n)=yyy(1:n+1);
z=fft(y,2*n);
k=1:n-1;
u=z(1:n+1);
v=-z(2:n).*exp(-2*pi*i*k/n);
u(n+2:2*n)=v(n-1:-1:1);
% max(abs(u-z))
modes(1:n+1)=i*z(1:n+1)/n.*exp(-pi*i*(n-1)/n*[0 k n]);
axes(handles.axes2)
bar(0:10,abs(modes(1:11)))
xlim([-0.5 10.5])
ylim([0 1])
title('Modes 0 through 10')
ylabel('Amplitude')

% Extend grid for left-right traveling waves
f=[0 y y y y]/2;

pause(0.05)


function evolve(hObject,eventdata,handles)

global x
global c L delta_t
global modes k n
global f

for p = 1:200
    t = p*delta_t;
    % Time-evolution of modes
    modes_t=modes.*cos(c*[0 k n]*pi/L*t);
    axes(handles.axes2)
    bar(0:10,abs(modes_t(1:11)))
    xlim([-0.5 10.5])
    ylim([0 1])
    title('Modes 0 through 10')
    ylabel('Amplitude')
    % Reconstruction of string shape
    z_t(1:n+1)=-i*modes_t(1:n+1)*n.*exp(pi*i*(n-1)/n*[0 k n]);
    v=-z_t(2:n).*exp(-2*pi*i*k/n);
    z_t(n+2:2*n)=v(n-1:-1:1);
    y_t=ifft(z_t,2*n);
    axes(handles.axes1)
    plot(x,real(y_t(n:2*n)),'r-','LineWidth',2)
    ylim([-1 1])
    hold on
    plot([0 1 1 0 0],[-1 -1 1 1 -1],'-k')
    axis off
    hold off
    % Left and right traveling waves
    axes(handles.axes3)
    x1=floor((c*t-2*floor((c*t+1)/2)+1)/0.01)+1;
    x2=floor((-c*t-2*floor((-c*t+1)/2)+1)/0.01)+1;
    if get(handles.checkbox1,'Value')==1
        plot(-1:0.01:2, f(x1:x1+3*n),'LineWidth',2)
        ylim([-1 1])
        xlim([-1 2])
        hold on
        plot([0 0],[-1 1],'--k')
        plot([1 1],[-1 1],'--k')
        plot([-1 2 2 -1 -1],[-1 -1 1 1 -1],'-k')
    end
    if get(handles.checkbox2,'Value')==1
        plot(-1:0.01:2,f(x2:x2+3*n),'k-','LineWidth',2)
        ylim([-1 1])
        xlim([-1 2])
        hold on
        plot([0 0],[-1 1],'--k')
        plot([1 1],[-1 1],'--k')
        plot([-1 2 2 -1 -1],[-1 -1 1 1 -1],'-k')
    end
    if get(handles.checkbox3,'Value')==1
        plot(x,f(x1:x1+n)+f(x2:x2+n),'r-','LineWidth',2)
        ylim([-1 1])
        xlim([-1 2])
        hold on
        plot([0 0],[-1 1],'--k')
        plot([1 1],[-1 1],'--k')
        plot([-1 2 2 -1 -1],[-1 -1 1 1 -1],'-k')
    end
    axis off
    hold off
    % Pause to see plots
    pause(0.05)
end


% --- Executes on button press in pushbutton1.
function pushbutton1_Callback(hObject, eventdata, handles)
% hObject    handle to pushbutton1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

global x

% Flat string
axes(handles.axes1)
plot(x,zeros(size(x)),'r-','LineWidth',2)
ylim([-1 1])
axis off

axes(handles.axes2)
bar(0:10,zeros(11))
xlim([-0.5 10.5])
ylim([0 1])
title('Modes 0 through 10')

axes(handles.axes3)
cla
axis off

% Initial conditions
initial(hObject,eventdata,handles)

% Time-evolution of the coefficients
evolve(hObject,eventdata,handles)



% --- Executes on button press in checkbox1.
function checkbox1_Callback(hObject, eventdata, handles)
% hObject    handle to checkbox1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of checkbox1


% --- Executes on button press in checkbox2.
function checkbox2_Callback(hObject, eventdata, handles)
% hObject    handle to checkbox2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of checkbox2


% --- Executes on button press in checkbox3.
function checkbox3_Callback(hObject, eventdata, handles)
% hObject    handle to checkbox3 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of checkbox3


