function masspring(action) % solution of the IVP % m y'' + gamma y' + k y = F * cos(omega * t - phi) % y(t0) = y0 % y'(t0) = yp0 global ui uj plt param ax sys color uu tt uk tk if nargin==0 close all; action = 'init'; end if strcmp(action,'init') pos = get(0,'ScreenSize'); pos = round([pos(1)+pos(3)/10 pos(2)+pos(4)/10 8*pos(3)/10 8*pos(4)/10]); pos=round(0.6*pos); fntsize = round(pos(4)/40); color.a = [.9 1 .8]; color.b = [.1 .7 .6]; color.c = [.7 .1 .6]; figure(1); set(1,'DefaultUicontrolUnits','normalized', ... 'DefaultUicontrolFontSize',fntsize, ... 'DefaultUicontrolFontName','helvetica', ... 'DefaultUicontrolFontWeight','bold', ... 'DefaultAxesFontName','helvetica', ... 'Color','white', ... 'Position',pos, ... 'NumberTitle','off', ... 'ResizeFcn','masspring(''resize'')', ... 'Name','Mass-Spring System', ... 'DoubleBuffer','on', ... 'BackingStore','off') uicontrol('Style','frame', ... 'Position',[.1 .88 .8 .09], ... 'BackgroundColor',color.a); ui = zeros(16,1); uj = zeros(15,1); ui(1) = uicontrol('Style','edit', ... 'Position',[.15 0.90 .05 .05], ... 'BackgroundColor','white', ... 'HorizontalAlignment','left', ... 'String',1, ... 'Callback','masspring(''setparam'')'); ui(2) = uicontrol('Style','edit', ... 'Position',[.27 0.90 .05 .05], ... 'BackgroundColor','white', ... 'HorizontalAlignment','left', ... 'String',0, ... 'Callback','masspring(''set'')'); ui(3) = uicontrol('Style','edit', ... 'Position',[.39 0.90 .05 .05], ... 'BackgroundColor','white', ... 'HorizontalAlignment','left', ... 'String',1, ... 'Callback','masspring(''set'')'); ui(4) = uicontrol('Style','edit', ... 'Position',[.51 0.90 .05 .05], ... 'BackgroundColor','white', ... 'HorizontalAlignment','left', ... 'String',0, ... 'Callback','masspring(''set'')'); ui(5) = uicontrol('Style','edit', ... 'Position',[.63 0.90 .05 .05], ... 'BackgroundColor','white', ... 'HorizontalAlignment','left', ... 'String',0, ... 'Callback','masspring(''set'')'); ui(6) = uicontrol('Style','edit', ... 'Position',[.75 0.90 .05 .05], ... 'BackgroundColor','white', ... 'HorizontalAlignment','left', ... 'String',0, ... 'Callback','masspring(''set'')'); uj(1) = uicontrol('Style','text', ... 'Position',[.20 0.91 .07 .04], ... 'BackgroundColor',color.a, ... 'HorizontalAlignment','center', ... 'FontWeight','bold', ... 'String','y'''' + '); uj(2) = uicontrol('Style','text', ... 'Position',[.32 0.91 .07 .04], ... 'BackgroundColor',color.a, ... 'HorizontalAlignment','center', ... 'FontWeight','bold', ... 'String','y'' + '); uj(3) = uicontrol('Style','text', ... 'Position',[.44 0.91 .07 .04], ... 'BackgroundColor',color.a, ... 'HorizontalAlignment','center', ... 'FontWeight','bold', ... 'String','y = '); uj(4) = uicontrol('Style','text', ... 'Position',[.56 0.91 .07 .04], ... 'BackgroundColor',color.a, ... 'HorizontalAlignment','center', ... 'FontWeight','bold', ... 'String','cos('); uj(5) = uicontrol('Style','text', ... 'Position',[.68 0.91 .07 .04], ... 'BackgroundColor',color.a, ... 'HorizontalAlignment','center', ... 'FontWeight','bold', ... 'String','t - '); uj(6) = uicontrol('Style','text', ... 'Position',[.80 0.91 .02 .04], ... 'BackgroundColor',color.a, ... 'HorizontalAlignment','center', ... 'FontWeight','bold', ... 'String',')'); uj(7) = uicontrol('Style','text', ... 'Position',[.0 0.83 .15 .04], ... 'BackgroundColor','white', ... 'HorizontalAlignment','right', ... 'FontWeight','bold', ... 'String','initial time:'); uj(8) = uicontrol('Style','text', ... 'Position',[.2 0.83 .15 .04], ... 'BackgroundColor','white', ... 'HorizontalAlignment','right', ... 'FontWeight','bold', ... 'String','final time:'); uj(9) = uicontrol('Style','text', ... 'Position',[.45 0.83 .20 .04], ... 'BackgroundColor','white', ... 'HorizontalAlignment','right', ... 'FontWeight','bold', ... 'String','initial position:'); uj(10) = uicontrol('Style','text', ... 'Position',[.70 0.83 .20 .04], ... 'BackgroundColor','white', ... 'HorizontalAlignment','right', ... 'FontWeight','bold', ... 'String','initial velocity:'); ui(7) = uicontrol('Style','edit', ... 'Position',[.15 0.82 .03 .05], ... 'BackgroundColor','white', ... 'HorizontalAlignment','center', ... 'Enable','inactive', ... 'String',0, ... 'Callback','masspring(''set'')'); ui(8) = uicontrol('Style','edit', ... 'Position',[.35 0.82 .07 .05], ... 'BackgroundColor','white', ... 'HorizontalAlignment','center', ... 'String',10, ... 'Callback','masspring(''set'')'); ui(9) = uicontrol('Style','edit', ... 'Position',[.65 0.82 .07 .05], ... 'BackgroundColor','white', ... 'HorizontalAlignment','left', ... 'String',0, ... 'Callback','masspring(''set'')'); ui(10) = uicontrol('Style','edit', ... 'Position',[.90 0.82 .07 .05], ... 'BackgroundColor','white', ... 'HorizontalAlignment','left', ... 'String',0, ... 'Callback','masspring(''set'')'); ui(12) = uicontrol('Style','text', ... 'Position',[.0 .8 .70 .02], ... 'ForegroundColor','red', ... 'BackgroundColor','white', ... 'HorizontalAlignment','left', ... 'FontWeight','bold'); uj(11) = uicontrol('Style','push', ... 'Position',[0 0.75 .10 .05], ... 'BackgroundColor',color.b, ... 'ForegroundColor','white', ... 'FontWeight','bold', ... 'HorizontalAlignment','center', ... 'String','RESET', ... 'Callback','masspring(''reset'')'); ui(11) = uicontrol('Style','push', ... 'Position',[.10 0.75 .1 .05], ... 'BackgroundColor',color.b, ... 'ForegroundColor','white', ... 'FontWeight','bold', ... 'HorizontalAlignment','center', ... 'String','SOLVE', ... 'UserData',0, ... 'Callback','masspring(''solve'')'); uj(12) = uicontrol('Style','text', ... 'Position',[.20 .75 .15 .04], ... 'ForegroundColor',color.c, ... 'BackgroundColor','white', ... 'HorizontalAlignment','right', ... 'FontWeight','bold', ... 'String','parameter:'); ui(13) = uicontrol('Style','popupmenu', ... 'Position',[.35 0.75 .2 .05], ... 'BackgroundColor',color.c, ... 'ForegroundColor','white', ... 'String','mass|damping|spring constant|force|frequency|phase|initial position|initial velocity', ... 'Value',5, ... 'UserData',[[0 1];[0 5];[0 100];[0 1];[0 9];[0 3.2];[-20 20];[-80 80]], ... 'HorizontalAlignment','left', ... 'Callback','masspring(''setparam'')'); ui(14) = uicontrol('Style','edit', ... 'Position',[.55 0.75 .05 .05], ... 'BackgroundColor','white', ... 'HorizontalAlignment','center', ... 'String','0', ... 'Enable','inactive'); ui(16) = uicontrol('Style','slider', ... 'Position',[.6 .75 .2 .05], ... 'ForegroundColor','red', ... 'BackgroundColor','white', ... 'Min',0, ... 'Max',1, ... 'SliderStep',[.01 .1], ... 'Callback','masspring(''parameter'')'); ui(15) = uicontrol('Style','edit', ... 'Position',[.8 0.75 .05 .05], ... 'BackgroundColor','white', ... 'HorizontalAlignment','center', ... 'String','20', ... 'Enable','inactive'); uj(13) = uicontrol('Style','push', ... 'Position',[.9 0.75 .05 .05], ... 'BackgroundColor',color.b, ... 'ForegroundColor','white', ... 'FontWeight','bold', ... 'Interruptible','on', ... 'HorizontalAlignment','center', ... 'String','>', ... 'UserData',0, ... 'Callback','masspring(''play'')'); uj(14) = uicontrol('Style','push', ... 'Position',[.95 0.75 .05 .05], ... 'BackgroundColor',color.b, ... 'ForegroundColor','white', ... 'FontWeight','bold', ... 'HorizontalAlignment','center', ... 'String','||', ... 'Callback','masspring(''stop'')'); ax(1) = axes( ... 'Position',[0.07 0.09 .43 .66], ... 'Box','on', ... 'DrawMode','fast', ... 'FontName','helvetica', ... 'FontSize',fntsize); plt(1) = plot([NaN],[NaN],'r','LineWidth',2); xlabel('time'); ylabel('y(t)'); hold on plt(2) = plot([NaN],[NaN],'b','LineWidth',2); plt(3) = plot([NaN],[NaN],'.b','MarkerSize',20, ... 'Visible','off'); hold off uj(15) = uicontrol('Style','push', ... 'Position',[0 0 .15 .05], ... 'BackgroundColor',color.b, ... 'ForegroundColor','white', ... 'FontWeight','bold', ... 'HorizontalAlignment','center', ... 'String','hold on', ... 'UserData',0, ... 'Callback','masspring(''hold'')'); uj(16) = uicontrol('Style','text', ... 'Position',[0.8 0.5 .15 .05], ... 'BackgroundColor','yellow', ... 'ForegroundColor','blue', ... 'FontWeight','bold', ... 'HorizontalAlignment','center'); uj(17) = uicontrol('Style','push', ... 'Position',[0.85 0 .15 .05], ... 'BackgroundColor',color.b, ... 'ForegroundColor','white', ... 'FontWeight','bold', ... 'HorizontalAlignment','center', ... 'String','Close', ... 'Callback','close(1)'); uj(18) = uicontrol('Style','text', ... 'Position',[0.8 0.3 .15 .18], ... 'BackgroundColor','white', ... 'ForegroundColor','red', ... 'FontWeight','bold', ... 'HorizontalAlignment','center', ... 'Visible','off', ... 'String','SYSTEM BLOWS UP!!'); ax(2) = axes( ... 'Position',[.5 0 .5 .75], ... 'DrawMode','fast', ... 'XLim',[0 1], ... 'YLim',[0 1]); sys(1) = fill([0 1 1 0],[.9 .9 1 1],[.8 .8 .8]); hold on plot([0 .1 .1 .1 .2 .2 .2 .3 .3 .3 ... .4 .4 .4 .5 .5 .5 .6 .6 .6 .7 ... .7 .7 .8 .8 .8 .9 .9 .9 1], ... [.95 .95 1 .95 .95 .9 .95 .95 1 .95 ... .95 .9 .95 .95 1 .95 .95 .9 .95 .95 ... 1 .95 .95 .9 .95 .95 1 .95 .95]) sys(2) = fill([.1 .1 .5 .5],[.9 0 0 .9],'cyan'); sys(3) = fill([.25 .35 .35 .25],[.65 .65 .85 .85]/2,'blue'); set([sys(1) sys(2) sys(3)],'EdgeColor','black', ... 'EraseMode','none','LineWidth',2); sys(4) = plot([NaN],[NaN],'Linewidth',1); axis([0 1 0 1]) axis off hold off masspring('setparam'); masspring('solve'); elseif strcmp(action,'setmass') var = 0:pi/20:40*pi; x = .3+.02*cos(var); s = (0.475-uk/100)/var(length(var)); y = .9-s*var; if min(y)<0.1 | max(y)>.9 set(uj(18),'Visible','on'); masspring('stop') end set(sys(4),'XData',x,'YData',y); y = y(length(y)); set(sys(3),'YData',[y-.1 y-.1 y y]); set(uj(16),'String',['t = ' num2str(tk,'%4.2f')]) elseif strcmp(action,'play') set(uj(13),'UserData',1); kk = 1; set(plt(3),'Visible','on'); while get(uj(13),'UserData') tf = str2num(get(ui(8),'String')); uk = uu(kk); tk = tt(kk); set(plt(3),'XData',tk,'YData',uk); masspring('setmass'); if strcmp(get(uj(18),'Visible'),'on') pause(3) set(uj(18),'Visible','off'); break end if kk==length(uu) kk = 1; pause(2) else kk = min(length(uu),kk+ceil(100/tf)); pause(tf/10000) end end elseif strcmp(action,'stop') set(uj(13),'UserData',0); set(plt(3),'Visible','off'); elseif strcmp(action,'hold') val = get(uj(15),'UserData'); if val set(ax(1),'YLimMode','auto') set(uj(15),'String','hold on'); else set(ax(1),'YLimMode','manual') set(uj(15),'String','hold off'); end set(uj(15),'UserData',1-val) elseif strcmp(action,'resize') pos = get(1,'Position'); fntsize = round(pos(4)/40); for kk = 1:size(uj,1) set(uj(kk),'FontSize',fntsize) end for kk = 1:size(ui,1) set(ui(kk),'FontSize',fntsize) end set(ax(1),'FontSize',fntsize); axes(ax(1)) xlabel('time'); ylabel('y(t)'); elseif strcmp(action,'parameter') index = [1 2 3 4 5 6 9 10]; kk = get(ui(13),'Value'); set(ui(index(kk)),'String',get(ui(16),'Value')) for kk = index set(ui(kk),'BackgroundColor','white','ForegroundColor','black'); end masspring('solve') elseif strcmp(action,'setparam') index = [1 2 3 4 5 6 9 10]; for kk = index set(ui(kk),'BackgroundColor','white','ForegroundColor','black'); end kk = get(ui(13),'Value'); set(ui(index(kk)),'ForegroundColor',color.c); range = get(ui(13),'UserData'); string = get(ui(index(kk)),'String'); val = str2num(string); if isempty(val) val = 0; end val = max(range(kk,1),min(range(kk,2),val)); set(ui(16),'Value',val); set(ui(16),'Min',range(kk,1),'Max',range(kk,2)) set(ui(14),'String',num2str(range(kk,1))) set(ui(15),'String',num2str(range(kk,2))) %if get(ui(1),'Value')==0, set(ui(1),'Value',1); end %if get(ui(3),'Value')==0, set(ui(3),'Value',1); end elseif strcmp(action,'reset') for kk = 1:10 set(ui(kk),'String',num2str(param(kk))); end elseif strcmp(action,'solve') % check if values are ok set(ui(11),'UserData',0); for kk = 1:10; string = get(ui(kk),'String'); value = str2num(string); if isempty(value) if isempty(deblank(string)) set(ui(kk),'String','0'); set(ui(kk),'BackgroundColor','white'); param(kk) = 0; else set(ui(kk),'BackgroundColor','red'); set(ui(11),'UserData',1); end else set(ui(kk),'BackgroundColor','white'); param(kk) = value; end end if get(ui(11),'UserData') set(ui(12),'String','Reset the values in the red boxes and solve again'); else set(ui(12),'String',''); m = param(1); gamma = param(2); k = param(3); F = param(4); omega = param(5); phi = param(6); tf = param(8); u0 = param(9); up0 = param(10); t = 0:tf/1000:tf; delta = gamma^2-4*m*k; a = k-m*omega^2; b = gamma*omega; det = norm([a b],2)^2; r1 = (-gamma+sqrt(delta))/(2*m); r2 = (-gamma-sqrt(delta))/(2*m); if det~=0 c1 = F*(a*cos(phi)-b*sin(phi))/det; c2 = F*(b*cos(phi)+a*sin(phi))/det; b1 = u0-c1; b2 = up0-c2*omega; else coef = F/(2*m*omega); c1 = -coef*sin(phi)*t; c2 = coef*cos(phi)*t; b1 = u0; b2 = up0-coef*sin(phi); end if delta~=0 c3 = (b1*r2-b2)/(r2-r1); c4 = (b2-b1*r1)/(r2-r1); else c3 = b1; c4 = (b2-r1*b1-c2*omega)*t; end u = c1.*cos(omega*t)+c2.*sin(omega*t) ... +c3*exp(r1*t)+c4.*exp(r2*t); set(plt(1),'XData',t,'YData',u) end uk = u(1); tk = t(1); tt = t; uu = u; masspring('setmass') end