function varargout = Spline_GUI(varargin) % SPLINE_GUI Application M-file for Spline_GUI.fig % FIG = SPLINE_GUI launch Spline_GUI GUI. % SPLINE_GUI('callback_name', ...) invoke the named callback. % Last Modified by GUIDE v2.5 21-Sep-2004 14:42:24 if nargin == 0 % LAUNCH GUI fig = openfig(mfilename,'reuse'); % Generate a structure of handles to pass to callbacks, and store it. handles = guihandles(fig); handles.indexfcn=1; handles.indexbc=1; handles.subdivisions=4; handles.const_a=0; handles.const_b=1; handles.problem_data = [handles.indexfcn, handles.subdivisions,... handles.const_a, handles.const_b,handles.indexbc]; guidata(fig, handles) if nargout > 0 varargout{1} = fig; end elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK try if (nargout) [varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard else feval(varargin{:}); % FEVAL switchyard end catch disp(lasterr); end end %| ABOUT CALLBACKS: %| GUIDE automatically appends subfunction prototypes to this file, and %| sets objects' callback properties to call them through the FEVAL %| switchyard above. This comment describes that mechanism. %| %| Each callback subfunction declaration has the following form: %| (H, EVENTDATA, HANDLES, VARARGIN) %| %| The subfunction name is composed using the object's Tag and the %| callback type separated by '_', e.g. 'slider2_Callback', %| 'figure1_CloseRequestFcn', 'axis1_ButtondownFcn'. %| %| H is the callback object's handle (obtained using GCBO). %| %| EVENTDATA is empty, but reserved for future use. %| %| HANDLES is a structure containing handles of components in GUI using %| tags as fieldnames, e.g. handles.figure1, handles.slider2. This %| structure is created at GUI startup using GUIHANDLES and stored in %| the figure's application data using GUIDATA. A copy of the structure %| is passed to each callback. You can store additional information in %| this structure at GUI startup, and you can change the structure %| during callbacks. Call guidata(hObject, handles) after changing your %| copy to replace the stored original so that subsequent callbacks see %| the updates. Type "help guihandles" and "help guidata" for more %| information. %| %| VARARGIN contains any extra arguments you have passed to the %| callback. Specify the extra arguments by editing the callback %| property in the inspector. By default, GUIDE sets the property to: %| ('', gcbo, [], guidata(gcbo)) %| Add any extra arguments after the last argument, before the final %| closing parenthesis. % -------------------------------------------------------------------- function varargout = popup_fcn_menu_Callback(hObject, eventdata, handles, varargin) indexfcn = get(hObject,'Value'); handles.indexfcn = indexfcn; handles.problem_data = [handles.indexfcn, handles.subdivisions,... handles.const_a, handles.const_b,handles.indexbc]; guidata(hObject,handles); % Save the handles structure after adding data % -------------------------------------------------------------------- function varargout = SelectSubdiv_Callback(hObject, eventdata, handles, varargin) subdiv = eval(get(handles.SelectSubdiv,'string')); handles.subdivisions = subdiv; handles.problem_data = [handles.indexfcn, handles.subdivisions,... handles.const_a, handles.const_b,handles.indexbc]; guidata(hObject,handles); % Save the handles structure after adding data % -------------------------------------------------------------------- function varargout = LeftHand_Callback(hObject, eventdata, handles, varargin) const_a = eval(get(handles.LeftHand,'string')); handles.const_a = const_a; handles.problem_data = [handles.indexfcn, handles.subdivisions,... handles.const_a, handles.const_b,handles.indexbc]; guidata(hObject,handles); % Save the handles structure after adding data % -------------------------------------------------------------------- function varargout = RightHand_Callback(hObject, eventdata, handles, varargin) const_b = eval(get(handles.RightHand,'string')); handles.const_b = const_b; handles.problem_data = [handles.indexfcn, handles.subdivisions,... handles.const_a, handles.const_b,handles.indexbc]; guidata(hObject,handles); % Save the handles structure after adding data % -------------------------------------------------------------------- function varargout = ErrorOutput_Callback(hObject, eventdata, handles, varargin) % -------------------------------------------------------------------- function varargout = CalculatePushbutton_Callback(hObject, eventdata, handles, varargin) prob_data = handles.problem_data; indexfcn = prob_data(1); subdiv=prob_data(2); a = prob_data(3); b = prob_data(4); indexbc = prob_data(5); stepsize = (b-a)/subdiv; nodes = a:stepsize:b; x_eval = a:(b-a)/(20*subdiv):b; % Calculate interpolating spline function. Evaluate it % and the true function at the points given in x_eval. [y_eval,true] = fcn(x_eval,prob_data); max_y = max([max(y_eval),max(true)]); min_y = min([min(y_eval),min(true)]); delta_y = (max_y - min_y)/10; delta_x = (b-a)/10; % Graph f(x) vs. P(x) axes(handles.axes1) cla axis([a-delta_x,b+delta_x,min_y-delta_y,max_y+delta_y]) hold on plot(x_eval,true,x_eval,y_eval,'r:') h_step=(b-a)/subdiv; x=a:h_step:b; y=f(x,indexfcn); plot(x,y,'.','MarkerSize',10) legend('Original fcn','Interpolant',0) hold off error = true-y_eval; max_y = max(error); min_y = min(error); delta_y = (max_y - min_y)/10; % Graph error in P(x) axes(handles.axes2) cla axis([a-delta_x,b+delta_x,min_y-delta_y,max_y+delta_y]) hold on plot(x_eval,error) plot([a-delta_x b+delta_x/2],[0 0],'k') text(b+.6*delta_x,0,'\itx') hold off max_error = max(abs(true-y_eval)); StringData=sprintf('Maximum Absolute Error = %12.3e',max_error); set(handles.ErrorOutput,'string',StringData) guidata(hObject,handles); % -------------------------------------------------------------------- function varargout = Menu_file_Callback(hObject, eventdata, handles, varargin) if isempty(get(handles.axes1,'Children')) set(handles.Submenu_save_axes1,'Enable','off') set(handles.Submenu_save_axes2,'Enable','off') else set(handles.Submenu_save_axes1,'Enable','on') set(handles.Submenu_save_axes2,'Enable','on') end % -------------------------------------------------------------------- function varargout = Submenu_save_axes1_Callback(hObject, eventdata, handles, varargin) h_invisible = figure('visible','off'); hax = copyobj(handles.axes1,h_invisible); set(hax,'units',get(0,'defaultaxesunits'),'position',get(0,'defaultaxesposition')) print(h_invisible,'-depsc','spline') close(h_invisible); disp('The graph is stored under the name "spline.eps"') % -------------------------------------------------------------------- function varargout = Submenu_save_axes2_Callback(hObject, eventdata, handles, varargin) h_invisible = figure('visible','off'); hax = copyobj(handles.axes2,h_invisible); set(hax,'units',get(0,'defaultaxesunits'),'position',get(0,'defaultaxesposition')) print(h_invisible,'-depsc','spline_error') close(h_invisible); disp('The graph is stored under the name "spline_error.eps"') % -------------------------------------------------------------------- function varargout = Submenu_close_Callback(hObject, eventdata, handles, varargin) delete(handles.figure1) % -------------------------------------------------------------------- % --- Executes on selection change in BoundaryCondition. function BoundaryCondition_Callback(hObject, eventdata, handles) % hObject handle to BoundaryCondition (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) % Hints: contents = get(hObject,'String') returns BoundaryCondition contents as cell array % contents{get(hObject,'Value')} returns selected item from BoundaryCondition indexbc = get(hObject,'Value'); handles.indexbc = indexbc; handles.problem_data = [handles.indexfcn, handles.subdivisions,... handles.const_a, handles.const_b,handles.indexbc]; guidata(hObject,handles); % Save the handles structure after adding data % -------------------------------------------------------------------- % --- Executes during object creation, after setting all properties. function BoundaryCondition_CreateFcn(hObject, eventdata, handles) % hObject handle to BoundaryCondition (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles empty - handles not created until after all CreateFcns called % Hint: popupmenu controls usually have a white background on Windows. % See ISPC and COMPUTER. if ispc set(hObject,'BackgroundColor','white'); else set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor')); end % -------------------------------------------------------------------- function [y_eval,true] = fcn(x_eval,prob_data) indexfcn = prob_data(1); subdiv=prob_data(2); a = prob_data(3); b = prob_data(4); indexbc = prob_data(5); true = f(x_eval,indexfcn); % Construct data for interpolating spline. stepsize=(b-a)/subdiv; x=a:stepsize:b; y=f(x,indexfcn); switch indexbc case 1 % natural boundary conditions y_eval = spline_natural(x,y,x_eval,a,b,stepsize,subdiv); case 2 % clamped boundary conditions y_eval = spline_clamped(x,y,x_eval,a,b,stepsize,subdiv,indexfcn); case 3 % not-a-knot boundary conditions y_eval = spline(x,y,x_eval); case 4 % not-a-knot boundary conditions, with first and last % subintervals halved. x = [a,a+stepsize/2,x(2:subdiv),b-stepsize/2,b]; y = [y(1),f(a+stepsize/2,indexfcn),y(2:subdiv),f(b-stepsize/2,indexfcn),y(subdiv+1)]; y_eval = spline(x,y,x_eval); end % -------------------------------------------------------------------- function y_eval = spline_natural(x,y,x_eval,a,b,stepsize,subdiv) % x and y have length n = subdiv+1. n = subdiv+1; % Set up the tridiagonal linear system for obtaining the second derivative % values associated with the natural cubic interpolating spline for the % data given in x and y. Then solve using tridiag. avec = zeros(n,1); avec(2:n-1) = (stepsize/6)*ones(n-2,1); cvec = avec; bvec = ones(n,1); bvec(2:n-1) = (2*stepsize/3)*bvec(2:n-1); rhs = zeros(n,1); rhs(2:n-1) = (y(3:n)-2*y(2:n-1)+y(1:n-2))/stepsize; [mvec, alpha, beta, ier] = tridiag(avec,bvec,cvec,rhs,n,0); y_eval = spline_evaluate(x,y,a,b,subdiv,stepsize,x_eval,mvec); % -------------------------------------------------------------------- function y_eval = spline_clamped(x,y,x_eval,a,b,stepsize,subdiv,indexfcn) % x and y have length n = subdiv+1. n = subdiv+1; % Obtain derivative values at endpoints. dy = df([a,b],indexfcn); % Set up the tridiagonal linear system for obtaining the second derivative % values associated with the natural cubic interpolating spline for the % data given in x and y. Then solve using tridiag. avec = zeros(n,1); avec(2:n) = (stepsize/6)*ones(n-1,1); cvec = zeros(n,1); cvec(1:n-1) = (stepsize/6)*ones(n-1,1); bvec = ones(n,1); bvec(2:n-1) = (2*stepsize/3)*bvec(2:n-1); bvec(1) = stepsize/3; bvec(n) = stepsize/3; rhs = zeros(n,1); rhs(2:n-1) = (y(3:n)-2*y(2:n-1)+y(1:n-2))/stepsize; rhs(1) = (y(2)-y(1))/stepsize - dy(1); rhs(n) = dy(2) - (y(n)-y(n-1))/stepsize; [mvec, alpha, beta, ier] = tridiag(avec,bvec,cvec,rhs,n,0); y_eval = spline_evaluate(x,y,a,b,subdiv,stepsize,x_eval,mvec); % -------------------------------------------------------------------- function y_eval = spline_evaluate(x,y,a,b,subdiv,stepsize,x_eval,mvec); nx = length(x_eval); for i=1:nx t = x_eval(i); j = 1 + floor((t-a)/stepsize + 2*eps); if j == subdiv+1 j = subdiv; end term1 = (mvec(j)*(x(j+1)-t).^3+mvec(j+1)*(t-x(j)).^3)/(6*stepsize); term2 = (y(j)*(x(j+1)-t)+y(j+1)*(t-x(j)))/stepsize; term3 = (stepsize/6)*(mvec(j)*(x(j+1)-t)+mvec(j+1)*(t-x(j))); y_eval(i) = term1 + term2 - term3; end % -------------------------------------------------------------------- function f_value=f(x,indexfcn) switch indexfcn case 1 % f(x) = exp(x) f_value = exp(x); case 2 % f(x) = cos x f_value = cos(x); case 3 % f(x) = arctan x f_value = atan(x); case 4 % f(x) = 1/(1+x^2) f_value = 1./(1+x.^2); case 5 % f(x) = log x f_value = log(x); case 6 % f(x) = tan x f_value = tan(x); case 7 % f(x) = exp(-x^2) f_value = exp(-x.^2); case 8 % f(x) = 1/(2+cos(x)) f_value = 1 ./(2+cos(x)); case 9 % f(x) = sqrt(abs(x)) f_value = sqrt(abs(x)); end % -------------------------------------------------------------------- function df_value=df(x,indexfcn) switch indexfcn case 1 % f(x) = exp(x) df_value = exp(x); case 2 % f(x) = cos x df_value = -sin(x); case 3 % f(x) = arctan x df_value = 1./(1+x.^2); case 4 % f(x) = 1/(1+x^2) df_value = -2*x./(1+x.^2).^2; case 5 % f(x) = log x df_value = 1./x; case 6 % f(x) = tan x sec_x = 1./cos(x); df_value = sec_x.^2; case 7 % f(x) = exp(-x^2) df_value = -2*x.*exp(-x.^2); case 8 % f(x) = 1/(2+cos(x)) df_value = sin(x)./(2+cos(x)).^2; case 9 % f(x) = sqrt(abs(x)) df_value = sign(x)./sqrt(abs(x)); end % -------------------------------------------------------------------- function [x, alpha, beta, ier] = tridiag(a,b,c,f,n,iflag) % function [x, alpha, beta, ier] = tridiag(a,b,c,f,n,iflag) % % Solve a tridiagonal linear system M*x=f % % INPUT: % The order of the linear system is given in n. % The subdiagonal, diagonal, and superdiagonal of M are given % by the arrays a,b,c, respectively. More precisely, % M(i,i-1) = a(i), i=2,...,n % M(i,i) = b(i), i=1,...,n % M(i,i+1) = c(i), i=1,...,n-1 % iflag=0 means that the original matrix M is given as specified above. % iflag=1 means that the LU factorization of M is already known and is % stored in a,b,c. This will have been accomplished by a previous call % to this routine. In that case, the vectors alpha and beta should % have been substituted for a and b in the calling sequence. % % OUTPUT: % Upon exit, the LU factorization of M is already known and is stored % in alpha,beta,c. The solution x is given as well. % ier=0 means the program was completed satisfactorily. % ier=1 means that a zero pivot element was encountered and the % solution process was abandoned. a(1) = 0; if iflag == 0 % Compute LU factorization of matrix M. for j=2:n if b(j-1) == 0 ier = 1; return end a(j) = a(j)/b(j-1); b(j) = b(j) - a(j)*c(j-1); end if b(n) == 0 ier = 1; return end end % Compute solution x to M*x = f. % Do forward substitution to solve lower triangular system. for j=2:n f(j) = f(j) - a(j)*f(j-1); end % Do backward substitution to solve upper triangular system. f(n) = f(n)/b(n); for j=n-1:-1:1 f(j) = (f(j) - c(j)*f(j+1))/b(j); end % Set output variables. ier = 0; x = f; alpha = a; beta = b; % -------------------------------------------------------------------- function Help_GUI_Callback(hObject, eventdata, handles) % hObject handle to Help_GUI (see GCBO) % eventdata reserved - to be defined in a future version of MATLAB % handles structure with handles and user data (see GUIDATA) Spline_GUI_Help;