function ss3d(action) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ss3d.m % % Plot the trajectory of the 3D Swingin Spring. % % Written by Peter Lynch (Peter.Lynch@met.ie ) % % Adapted from MATLAB demonstration program % lorenz, written for Expo by Ned Gulley, 6-21-93. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Set the initial conditions. x0 = 0.01; xdot0 = 0.00; y0 = 0.00; ydot0 = 0.02; zprime0 = 0.1; zdot0 = 0.00; % Change to alternative initial conditions as required. % These ones give a nice six-pointed star for the projection. x0 = 0.04; xdot0 = 0.00; y0 = 0.00; ydot0 = 0.034272; zprime0 = 0.08; zdot0 = 0.00; % Change scale to alter character of the motion. skale = 1.00; yinit1=x0*skale; yinit2=xdot0*skale; yinit3=y0*skale; yinit4=ydot0*skale; yinit5=-1+zprime0*skale; yinit6=zdot0*skale; yinit = [ yinit1 yinit2 yinit3 yinit4 yinit5 yinit6 ]; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Information regarding the play status will be held in % the axis user data according to the following table: play= 1; stop=-1; if nargin<1, action='initialize'; end; if strcmp(action,'initialize'), oldFigNumber=watchon; figNumber=figure( ... 'Name','Swingin Spring', ... 'NumberTitle','off', ... 'Color',[0.15 0.15 0.30], ... 'Visible','off'); axes( ... 'Units','normalized', ... 'Position',[0.10 0.10 0.7 0.85], ... 'Visible','off'); text(0,0,'Press the "Start" button to see the Swingin Spring', ... 'HorizontalAlignment','center'); axis([-1 1 -1 1]); %=================================== % Information for all buttons labelColor=[0.8 0.8 1.0]; yInitPos=0.90; xPos=0.85; btnLen=0.10; btnWid=0.10; % Spacing between the button and the next command's label spacing=0.05; %==================================== % The CONSOLE frame frmBorder=0.02; yPos=0.05-frmBorder; frmPos=[xPos-frmBorder yPos btnLen+2*frmBorder 0.9+2*frmBorder]; h=uicontrol( ... 'Style','frame', ... 'Units','normalized', ... 'Position',frmPos, ... 'BackgroundColor',[0.70 0.70 0.80]); %==================================== % The START button btnNumber=1; yPos=0.90-(btnNumber-1)*(btnWid+spacing); labelStr='Start'; cmdStr='start'; callbackStr='ss3d(''start'');'; % Generic button information btnPos=[xPos yPos-spacing btnLen btnWid]; startHndl=uicontrol( ... 'Style','pushbutton', ... 'BackGroundColor','b', ... 'Units','normalized', ... 'Position',btnPos, ... 'String',labelStr, ... 'Interruptible','yes', ... 'Callback',callbackStr); %==================================== % The STOP button btnNumber=2; yPos=0.90-(btnNumber-1)*(btnWid+spacing); labelStr='Stop'; % Setting userdata to -1 (=stop) will stop the program. callbackStr='set(gca,''Userdata'',-1)'; % Generic button information btnPos=[xPos yPos-spacing btnLen btnWid]; stopHndl=uicontrol( ... 'Style','pushbutton', ... 'Units','normalized', ... 'Position',btnPos, ... 'Enable','off', ... 'String',labelStr, ... 'Callback',callbackStr); %==================================== % The INFO button labelStr='Info'; callbackStr='ss3d(''info'')'; infoHndl=uicontrol( ... 'Style','push', ... 'Units','normalized', ... 'position',[xPos 0.20 btnLen 0.10], ... 'string',labelStr, ... 'call',callbackStr); %==================================== % The CLOSE button labelStr='Close'; callbackStr='close(gcf)'; closeHndl=uicontrol( ... 'Style','push', ... 'Units','normalized', ... 'position',[xPos 0.05 btnLen 0.10], ... 'string',labelStr, ... 'call',callbackStr); % Uncover the figure hndlList=[startHndl stopHndl infoHndl closeHndl]; set(figNumber,'Visible','on', ... 'UserData',hndlList); watchoff(oldFigNumber); figure(figNumber); elseif strcmp(action,'start'), axHndl=gca; figNumber=gcf; hndlList=get(figNumber,'UserData'); startHndl=hndlList(1); stopHndl=hndlList(2); infoHndl=hndlList(3); closeHndl=hndlList(4); set([startHndl closeHndl infoHndl],'Enable','off'); set(stopHndl,'Enable','on'); % ====== Start of Integration set(figNumber,'Backingstore','off'); % The graphics axis limits are set to values known % to contain the solution. XLimn=-0.2*skale; XLimx=+0.2*skale; YLimn=-0.2*skale; YLimx=+0.2*skale; ZLimn=-1+(1-1.3)*skale; ZLimx=-1+(1-0.9)*skale; tickx=linspace(XLimn,XLimx,5); ticky=linspace(YLimn,YLimx,5); tickz=linspace(ZLimn,ZLimx,5); set(axHndl, ... 'XLim',[XLimn XLimx],'YLim',[YLimn YLimx],'ZLim',[ZLimn ZLimx], ... 'XColor','b','YColor','b','ZColor','b', ... 'Userdata',play, ... 'XTick',tickx,'YTick',ticky,'ZTick',tickz, ... 'Drawmode','fast', ... 'Visible','on', ... 'NextPlot','add', ... 'Userdata',play, ... 'View',[-30,30] ); %%% 'View',[-37.5,30]); xlabel('X'); ylabel('Y'); zlabel('Z'); grid on % Values of the physical spring parameters. m = 1; %%% mass on spring g = pi^2; %%% gravity k = 4*pi^2; %%% stiffness l = 1; %%% length at equilibrium. epssq=(m*g)/(k*l); epsilon=sqrt(epssq); l_0=(1-epssq)*l; omega_R = sqrt(g/l); omega_Z = sqrt(k/m); tau_R = 2*pi/omega_R; tau_Z = 2*pi/omega_Z; % The orbit ranges (regularly or chaotically) back and forth around % the stable equilibrium point. It is bounded, but not periodic and % not convergent. The numerical integration, and the display of the % evolving solution, are handled by the method of ODE23P (inline). t0=0; tfinal=1000; pow = 1/3; tol = 0.0001; %%% reduced by factor of 10. t = t0; hmax = (tfinal - t)/5; hmin = (tfinal - t)/200000; h = (tfinal - t)/100; y = yinit(:); tau = tol * max(norm(y,'inf'),1); % Save L steps and plot like a comet tail. L = 50; Y = y*ones(1,L); cla; head = line( ... 'color','r', ... 'linestyle','.', ... 'Markersize',50, ... 'erase','xor', ... 'xdata',y(1),'ydata',y(3),'zdata',y(5)); cord = line( ... 'color','r', ... 'linestyle','-', ... 'linewidth',2.0, ... 'erase','xor', ... 'xdata',[0;y(1)],'ydata',[0;y(3)],'zdata',[0;y(5)]); body = line( ... 'color','g', ... 'linestyle','-', ... 'erase','none', ... 'xdata',[],'ydata',[],'zdata',[]); tail=line( ... 'color','m', ... 'linestyle','-', ... 'erase','none', ... 'xdata',[],'ydata',[],'zdata',[]); base = line( ... 'color','y', ... 'linestyle','-', ... 'erase','none', ... 'xdata',[],'ydata',[],'zdata',[]); % The main loop while (get(axHndl,'Userdata')==play) & (h >= hmin) if t + h > tfinal, h = tfinal - t; end % Compute the slopes %%%%%%%%% FunFcn='sprroc'; % s1 = (feval(FunFcn, t, y))'; yy = y; r=sqrt(yy(1)^2+yy(3)^2+yy(5)^2); fac=omega_Z^2*(r-l_0)/r; ydot(1) = yy(2); ydot(2) = - fac*yy(1); ydot(3) = yy(4); ydot(4) = - fac*yy(3); ydot(5) = yy(6); ydot(6) = - fac*yy(5) - g; s1 = ydot'; % s2 = (feval(FunFcn, t+h, y+h*s1))'; yy = y+h*s1; r=sqrt(yy(1)^2+yy(3)^2+yy(5)^2); fac=omega_Z^2*(r-l_0)/r; ydot(1) = yy(2); ydot(2) = - fac*yy(1); ydot(3) = yy(4); ydot(4) = - fac*yy(3); ydot(5) = yy(6); ydot(6) = - fac*yy(5) - g; s2 = ydot'; % s3 = (feval(FunFcn, t+h/2, y+h*(s1+s2)/4))'; yy = y+h*(s1+s2)/4; r=sqrt(yy(1)^2+yy(3)^2+yy(5)^2); fac=omega_Z^2*(r-l_0)/r; ydot(1) = yy(2); ydot(2) = - fac*yy(1); ydot(3) = yy(4); ydot(4) = - fac*yy(3); ydot(5) = yy(6); ydot(6) = - fac*yy(5) - g; s3 = ydot'; % Estimate the error and the acceptable error delta = norm(h*(s1 - 2*s3 + s2)/3,'inf'); tau = tol*max(norm(y,'inf'),1.0); % Update the solution only if the error is acceptable ts = t; ys = y; if delta <= tau t = t + h; y = y + h*(s1 + 4*s3 + s2)/6; % Update the plot Y = [y Y(:,1:L-1)]; zbase=ZLimn; set(head,'xdata',Y(1,1),'ydata',Y(3,1),'zdata',Y(5,1)) set(cord,'xdata',[0;Y(1,1)],'ydata',[0;Y(3,1)],'zdata',[0;Y(5,1)]) set(body,'xdata',Y(1,1:2),'ydata',Y(3,1:2),'zdata',Y(5,1:2)) set(tail,'xdata',Y(1,L-1:L),'ydata',Y(3,L-1:L),'zdata',Y(5,L-1:L)) set(base,'xdata',Y(1,1:2),'ydata',Y(3,1:2),'zdata',[zbase,zbase]) drawnow; end % Update the step size if delta ~= 0.0 h = min(hmax, 0.9*h*(tau/delta)^pow); end end; % Main loop ... % ====== End of Program set([startHndl closeHndl infoHndl],'Enable','on'); set(stopHndl,'Enable','off'); elseif strcmp(action,'info'); ttlStr='Swingin Spring Info'; hlpStr= ... [' ' ' This program animates the integration of the ' ' six coupled nonlinear differential equations ' ' that determine the motion of the elastic ' ' pendulum, more colloquially called the ' ' "Swingin Spring" ' ' As the integration proceeds you will see a ' ' point moving around in a curious orbit in ' ' 3-D space. The red blob is the pendulum bob. ' ' The green streak shows the recent track. ' ' The magenta shows the complete 3D trajectory. ' ' The yellow is a projection of the motion on ' ' a horizontal plane. ' ' ' ' The initial conditions are in the array yinit.' ' They can easily be changed by changing the ' ' values x0, y0, z0, xdot0, ydot0,zdot0 or the ' ' value of the parameter "skale", defined ' ' near the top of the program. For small values ' ' of skale the motion is quasi-regular. For ' ' large values it is chaotic. ' ' [ for references, see publications in ' ' http://www.maths.tcd.ie/~plynch ] ' ' ' ' File name: ss3d.m ']; helpfun(ttlStr,hlpStr); end; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%