function output = dfield(action,input1,input2,input3) % DFIELD is an interactive tool for studying single first order % differential equations. When DFIELD is executed, a DFIELD Setup % window is opened. The user may enter the differential % equation and specify a display window using the interactive % controls in the Setup window. % % When the Proceed button is pressed on the Setup window, the DF % Display window is opened. At first this window displays a % direction line field for the differential equation. When the % mouse button is depressed in the DFIELD Display window, the % solution to the differential equation with that initial % condition is calculated and plotted. % % Other options are available in the Options menu. These are % fairly self explanatory. The Settings option allows the user % to change several parameters. Included here are the % possibilities of using a vector field instead of the default % line field, and of changing the number of field points computed % and displayed. % Copywright (c) 1993 - 95 by John C. Polking, Rice University % Last modified: January 30, 1995 if nargin <1 action ='initialize'; end if strcmp(action,'initialize') % First we make sure that there is no other copy of DFIELD % running, since this causes problems. figs = get(0,'children'); for (figno = 1:length(figs)) nn = get(figs(figno),'name'); if (length(nn) >1) if (findstr(nn,'DFIELD')~=[]) error('Only one copy of DFIELD can be open at one time.') end end end % Initiate several parameters. NumbFPts = 20; % The number of field points plotted in each direction. Arrflag=1; % The default is a vector field. magn = 1.25; % The expansion factor in each direction % for the compute window. steps = 20; % Then minimum number of compute stepss across % the Display window. tol = 1e-4; % The relative error tolerance. itlim = 1000; % After this many iterations, the computation of % a solution stops. settings = [Arrflag,NumbFPts,magn,steps,itlim,tol]; % The default differential equation, and Display window. Xname = ' x'; Tname = ' t'; derivstr = ' x^2 - t'; WINvect=[-3 10 -4 4]; % Build the Setup window. texth =20; % Height of text boxes. varw = 80; % Length of variable boxes. equalw =30; % Length of equals. eqlength = 300; % Length of right hand sides. left =30; % Left margin. separation = texth+3; % Separation between boxes. equationbot = 7.5*separation;; eqlabelbot = equationbot + 2.5*separation; xbot = equationbot + 1.5*separation; % Bottom of x equation. tbot = equationbot; % Bottom of t equation. defigwidth =2*left + varw+equalw+eqlength; % Width of the figure. defigureheight = 12*separation; % Height of the figure. defigurebot = 20; % Bottom of the figure. dfset = figure('pos',[20 defigurebot defigwidth defigureheight],... 'resize','off','name','DFIELD Setup','numb','off',... 'visible','off'); figure(dfset) lablen =160; eqlableft = (defigwidth-lablen)/2; frame(1) = uicontrol('style','frame',... 'pos',[left-5,equationbot-5,defigwidth-2*left+10,3.5*separation+10],... 'visible','off'); tname = [ 'sh = get(gcf,''user'');'... 'sm = get(sh(1),''user'');'... 'eq = sh(3:8);'... 'wind =sh(9:17);'... 'Tname=get(eq(6),''string'');'... 'set(wind(2),''string'',[''The min value of '',Tname,'' = '']);'... 'set(wind(4),''string'',[''The max value of '',Tname,'' = '']);'... 'sm = str2mat(Tname,sm(2:3,:));'... 'set(sh(1),''user'',sm);'... 'set(sh(3),''user'',0);']; % Set's the flag to compute anew. xname=[ 'sh = get(gcf,''user'');'... 'sm = get(sh(1),''user'');'... 'eq = sh(3:8);'... 'wind =sh(9:17);'... 'Xname=get(eq(2),''string'');'... 'set(wind(6),''string'',[''The min value of '',Xname,'' = '']);'... 'set(wind(8),''string'',[''The max value of '',Xname,'' = '']);'... 'sm = str2mat(sm(1,:),Xname,sm(3,:));'... 'set(sh(1),''user'',sm);'... 'set(sh(3),''user'',0);']; xder =[ 'sh = get(gcf,''user'');'... 'sm = get(sh(1),''user'');'... 'eq=sh(3:8);'... 'derivstr = get(eq(4),''string'');'... 'sm = str2mat(sm(1:2,:),derivstr);'... 'set(sh(1),''user'',sm);'... 'set(sh(3),''user'',0);']; eq(1)=uicontrol('style','text',... 'pos',[left eqlabelbot defigwidth-2*left texth],... 'horizon','center',... 'string','The differential equation.','visible','off'); eq(2)=uicontrol('pos',[left xbot varw texth],'style','edit',... 'horizon','right','string',Xname,... 'call',xname,'visible','off'); eq(3) = uicontrol('style','text','pos',[left+varw xbot equalw texth],... 'horizon','center','string',''' = ','visible','off'); eq(4)=uicontrol('pos',[left+varw + equalw xbot eqlength texth],... 'string',derivstr,'horizon','left','style','edit',... 'call',xder,'visible','off'); eq(5)=uicontrol('pos',[left tbot 200 texth],'style','text',... 'horizon','right','string','The independent variable is ',... 'visible','off'); eq(6)=uicontrol('pos',[left+200 tbot varw texth],... 'string',Tname,... 'horizon','right','style','edit','call',tname,... 'visible','off'); winstrlen = (defigwidth - 2*left)/2 -50; winbot = 2*separation; winleft = left+(winstrlen +50 -120)/2; wframe=[left-5,winbot+separation-5,... defigwidth-2*left+10,3*separation+10]; w1 = [ 'sh = get(gcf,''user'');'... 'wind =sh(9:17);'... 'sh(21)=str2num(get(wind(3),''string''));'... 'set(gcf,''user'',sh);']; w2 = [ 'sh = get(gcf,''user'');'... 'wind =sh(9:17);'... 'sh(22)=str2num(get(wind(5),''string''));'... 'set(gcf,''user'',sh);']; w3 = [ 'sh = get(gcf,''user'');'... 'wind =sh(9:17);'... 'sh(23)=str2num(get(wind(7),''string''));'... 'set(gcf,''user'',sh);']; w4 = [ 'sh = get(gcf,''user'');'... 'wind =sh(9:17);'... 'sh(24)=str2num(get(wind(9),''string''));'... 'set(gcf,''user'',sh);']; frame(2) = uicontrol('style','frame','pos',wframe,'visible','off'); wind(1)=uicontrol('style','text',... 'pos',[left winbot+3*separation defigwidth - 2*left texth],... 'horizon','center','string','The display window.','visible','off'); wind(2) = uicontrol('style','text',... 'pos',[left winbot+2*separation winstrlen texth],... 'horizon','right','string',['The min value of ',Tname,' = '],... 'visible','off'); wind(3) = uicontrol('style','edit',... 'pos',[left+winstrlen winbot+2*separation 50 texth],... 'string',num2str(WINvect(1)),... 'call',w1,'visible','off'); wind(4) = uicontrol('style','text',... 'pos',[left winbot+separation winstrlen texth],... 'horizon','right','string',['The max value of ',Tname,' = '],... 'visible','off'); wind(5) = uicontrol('style','edit',... 'pos',[left+winstrlen winbot+separation 50 texth],... 'string',num2str(WINvect(2)),... 'call',w2,'visible','off'); wind(6) = uicontrol('style','text',... 'pos',[left+winstrlen+50 winbot+2*separation winstrlen texth],... 'horizon','right','string',['The min value of ',Xname,' = '],... 'visible','off'); wind(7) = uicontrol('style','edit',... 'pos',[left+2*winstrlen+50 winbot+2*separation 50 texth],... 'string',num2str(WINvect(3)),... 'call',w3,'visible','off'); wind(8) = uicontrol('style','text',... 'pos',[left+winstrlen+50 winbot+separation winstrlen texth],... 'horizon','right','string',['The max value of ',Xname,' = '],... 'visible','off'); wind(9) = uicontrol('style','edit',... 'pos',[left+2*winstrlen+50 winbot+separation 50 texth],... 'string',num2str(WINvect(4)),... 'call',w4,'visible','off'); butt(1) = uicontrol('style','push',... 'pos',[(defigwidth/4-35),separation,70,texth],... 'string','Quit','call','dfield(''quit'')','visible','off'); butt(2) = uicontrol('style','push',... 'pos',[(defigwidth/2-35),separation,70,texth],... 'string','Revert','call','dfield(''revert'')','visible','off'); butt(3) = uicontrol('style','push',... 'pos',[(3*defigwidth/4-35),separation,70,texth],... 'string','Proceed','call','dfield(''proceed'')','visible','off'); % Record the handles in the User Data of the Set Up figure. sh = [frame,eq,wind,butt,WINvect,WINvect,settings]; set(gcf,'user',sh); set(gcf,'pos',[20 defigurebot defigwidth defigureheight],'vis','on'); set(get(gcf,'child'),'vis','on'); % Record the important information in the User Data of % varous controls. sm = str2mat(Tname,Xname,derivstr); set(frame(1),'user',sm); set(frame(2),'user',sm); % This is long term memory. set(sh(3),'user',0); elseif strcmp(action,'proceed') % Proceed connects Setup with the Display window. dfset = gcf; sh = get(dfset,'user'); flag = get (sh(3),'user'); % flag = 0, if this is the first time through for this equation, % but flag = 1 if only the window dimensions have been changed. if (flag == 1) WINvect = sh(21:24); sh(25:28) = WINvect; set(dfset,'user',sh); dfdisp = 0; figs = get(0,'children'); for (kk = 1:length(figs)) if (strcmp(get(figs(kk),'name'),'DFIELD Display')) dfdisp = figs(kk); end end dh = get(dfdisp,'user'); dh(15:18) = WINvect; set(dfdisp,'user',dh); dfield('dirfield'); else set(sh(3),'user',1); set(dfset,'user',sh); dfield('display'); end elseif strcmp(action,'revert') % Revert allows the user to change all settings in theSetup window to % what they were before changes have been made. sh = get(gcf,'user'); frame=sh(1:2); eq=sh(3:8); wind =sh(9:17); sm = get(sh(2),'user'); Tname = deblank(sm(1,:)); Xname = deblank(sm(2,:)); derivstr = deblank(sm(3,:)); WINvect = sh(25:28); set(sh(1),'user',sm); set(eq(2),'string',Xname); set(wind(2),'string',['The min value of ',Tname,' = ']); set(wind(4),'string',['The max value of ',Tname,' = ']); set(eq(6),'string',Tname); set(wind(6),'string',['The min value of ',Xname,' = ']); set(wind(8),'string',['The max value of ',Xname,' = ']); set(eq(4),'string',derivstr); set(wind(3),'string',num2str(WINvect(1))); set(wind(5),'string',num2str(WINvect(2))); set(wind(7),'string',num2str(WINvect(3))); set(wind(9),'string',num2str(WINvect(4))); sh(21:24) = WINvect; set(gcf,'user',sh); elseif strcmp(action,'display') % Display takes the information from the Setup window and initializes % the Display window if it already exists. If the Display window does % not exist, it builds one. dfset = gcf; % Find DFIELD Display if it exists. figs = get(0,'children'); dfdisp = 0; for (figno = 1:length(figs)) if (strcmp(get(figs(figno),'name'),'DFIELD Display')) dfdisp = figs(figno); figure(dfdisp); dh = get(dfdisp,'user'); dfdispa = dh(14); axes(dfdispa); cla notice = dh(2:3); set(notice(1),'string','Computing the field elements.'); set(notice(2),'string',''); end end % Get the information from DFIELD Setup. sh = get(dfset,'user'); settings = sh(29:34); WINvect = sh(21:24); sm = get(sh(1),'user'); set(sh(2),'user',sm); % Resets long term storage. Tname = deblank(sm(1,:)); Xname = deblank(sm(2,:)); derivstr = deblank(sm(3,:)); Labstr = [Xname,''' = ',derivstr]; sh(25:28) = WINvect; set(gcf,'user',sh); % If DFIELD Display exists, update it. If it does not build it. if (dfdisp) dh(15:18) = WINvect; set(dfdisp,'user',dh); dm = get(dh(1),'user'); FFFCCNNN = deblank(dm(3,:)); dm = str2mat(Tname,Xname,FFFCCNNN,Labstr); set(dh(1),'user',dm); else dfdisp = figure('name','DFIELD Display','numb','off',... 'visible','off'); figure(dfdisp); Arrflag = settings(1); % Set up the bulletin window. nframe = uicontrol('style','frame','units','normal',... 'pos',[.1 0 .78 .09],'visible','off'); notice(1)=uicontrol('style','text','pos',[.12 .045 .74 .04],... 'units','normal','horiz','left',... 'string','Computing the field elements.','visible','off'); notice(2)=uicontrol('style','text','pos',[.12 .005 .74 .04],... 'units','normal','horiz','left','string','',... 'visible','off'); % drawnow % Set up the buttons and the menu. dbutt(1) = uicontrol('style','push','units','normal','pos',... [0.895 0.17 0.09 0.06],'string','Quit',... 'call','dfield(''quit'')','visible','off'); dbutt(2) = uicontrol('style','push','units','normal','pos',... [0.895 0.86 0.09 0.06],'string','Replot','call',... 'dfield(''refresh'')','visible','off','value',1); dbutt(3) = uicontrol('style','push','units','normal','pos',... [0.895 0.515 0.09 0.06],'string','Print',... 'call','dfield(''print'')','visible','off'); v = version; if (findstr('tudent', v)) v = 4.2; else v = str2num(v(1:3)); end dbutt(4) = v; menu(1) = uimenu('label','DFIELD Options','visible','off'); menukey = uimenu(menu(1),'label','Keyboard input.','call',... 'dfield(''kbd'')'); mesev = uimenu(menu(1),'label','Plot several solutions.',... 'call','dfield(''several'')'); menu(2) = uimenu(menu(1),'label','Zoom in.','call',... 'dfield(''zoomin'')','separator','on'); menu(4) = uimenu(menu(1),'label','Erase all solutions.',... 'call','dfield(''dall'')','separator','on'); menu(5) = uimenu(menu(1),'label','Delete a graphics object.',... 'call','dfield(''delete'')'); menutext = uimenu(menu(1),'label','Enter text on the Display Window.',... 'call','dfield(''text'')'); meset = uimenu(menu(1),'label','Settings.',... 'call','dfield(''settings'')','separator','on'); menu(6) = uimenu(menu(1),'label','Make the Display Window inactive.',... 'call','dfield(''hotcold'')','separator','on'); if (v > 4.0) menu(3) = uimenu(menu(1),'label','Replot solutions later.',... 'call','dfield(''replot'')','separator','on'); else menu(3) = 0; end set(dfdisp,'visible','on'); set([nframe, notice, dbutt([1 3]),menu(1)],'visible','on'); % if (dbutt(4) < 4.1) % set(menu(3),'visible','off'); % end drawnow dfdispa=axes('position',[.1 .17 .78 .75],... 'next','add','box','on',... 'xgrid','on','ygrid','on'); set(gcf,'WindowButtonDownFcn','dfield(''down'')'); % Save the numbers: % dh(1) nframe % dh(2:3) notice % dh(4:7) dbutt (dbutt(4) = version of MATLAB) % dh(8:13) menu % dh(14) ddispa % dh(15:18) WINvect % dh(19:24) settings % dh(25) RFLAG dh = [nframe,notice,dbutt,menu,dfdispa,WINvect,settings]; set(dfdisp,'user',dh); dm = str2mat(Tname,Xname,' ',Labstr); set(dh(1),'user',dm); end % We have to make the derivative string array smart. l = length(derivstr); for (k=fliplr(find((derivstr=='^')|(derivstr=='*')|(derivstr=='/')))) derivstr = [derivstr(1:k-1) '.' derivstr(k:l)]; l = l+1; end % If an old function m-file exists delete it, and then build a new one. if (exist(FFFCCNNN)==2) delete([FFFCCNNN,'.m']);end tee = clock; tee = ceil(tee(6)*100); FFFCCNNN=['dftp',num2str(tee)]; fcnstr = ['function YyYypr = ',FFFCCNNN,'(TtTt,YyYy)\n\n']; varstr = [Tname,' = TtTt;', Xname,' = YyYy;\n\n']; lenstr = ['l = length(YyYy);\n']; derstr1 = ['YyYypr = ', derivstr,';\n']; derstr2 = ['if (length(YyYypr) < l) YyYypr = YyYypr*ones(1,l);end\n']; dff = fopen([FFFCCNNN,'.m'],'w'); fprintf(dff,fcnstr); fprintf(dff,varstr); fprintf(dff,lenstr); fprintf(dff,derstr1); fprintf(dff,derstr2); fclose(dff); % Initialize important information as user data. dm = str2mat(dm(1:2,:),FFFCCNNN,dm(4,:)); set(dh(1),'user',dm); % The strings. set(dh(3),'user',[]); % Handles to solution curves. set(dh(8),'user',[]); % Data for solution curves which are % still plotted with no erase mode, % and must be replotted at some point. set(dh(12),'user',[]); % Handles for the direction and vector fields. set(dfdispa,'user',[]); % Handles for the ends of orbits plotted with % no erasemode. These must be deleted at % some point. dfield('dirfield'); elseif strcmp(action,'replot') % This is the callback for the Replot button. This is only visible if % the version of MATLAB is 4.1 or greater. In this case "enable" is % defined, so we need not check further. dh = get(gcf,'user'); menu = dh(8:13); dbutt = dh(4:7); RFLAG = strcmp(get(menu(3),'label'),'Replot solutions immediately.'); set(dh(5),'value',RFLAG); if RFLAG set(menu(3),'label','Replot solutions later.'); set(dbutt(2),'visible','off'); else set(menu(3),'label','Replot solutions immediately.'); set(dbutt(2),'visible','on'); end dfield('refresh'); elseif strcmp(action,'hotcold') % 'hotcold' is the callback for the menu selection that makes the % Display Window active or inactive. dfdisp = gcf; dh = get(dfdisp,'user'); notice = dh(2:3); mehc = dh(13); if (findstr(get(mehc,'label'),'inactive')) set(dfdisp,'WindowButtonDownFcn',' '); set(mehc,'label','Make the Display Window active.'); set(notice(1),'string','The Display Window is not active.'); set(notice(2),'string',' '); else set(dfdisp,'WindowButtonDownFcn','dfield(''down'')'); set(mehc,'label','Make the Display Window inactive.'); set(notice(1),'string','Ready.'); set(notice(2),'string',' '); end dfield('refresh'); elseif strcmp(action,'dirfield') % 'dirfield' computes and plots the field elements. This is the entry % point both from 'display' and from later commands that require the % recomputation of the field elements. % Find DFIELD Display and get the user data. figs = get(0,'children'); dfdisp = 0; for (figno = 1:length(figs)) if (strcmp(get(figs(figno),'name'),'DFIELD Display')) dfdisp = figs(figno); end end dh = get(dfdisp,'user'); dm = get(dh(1),'user'); Tname = deblank(dm(1,:)); Xname = deblank(dm(2,:)); FFFCCNNN = deblank(dm(3,:)); Labstr = deblank(dm(4,:)); notice = dh(2:3); dfdispa = dh(14); WINvect = dh(15:18); settings = dh(19:24); set(notice(1),'string','Computing the field elements.'); set(notice(2),'string',''); Tmin = WINvect(1); Tmax = WINvect(2); Xmin = WINvect(3); Xmax = WINvect(4); N = settings(2); deltat=(Tmax - Tmin)/(N-1); deltax=(Xmax - Xmin)/(N-1); % Set up the display window. Dtint=[Tmin-deltat,Tmax+deltat]; Dxint=[Xmin-deltax,Xmax+deltax]; % Set up the original mesh. TTTg=Tmin + deltat*[0:N-1]; XXXg=Xmin + deltax*[0:N-1]; [Tt,Xx]=meshgrid(TTTg,XXXg); % Calculate the line and vector fields. Xx=Xx(:);Tt=Tt(:); Ww = feval(FFFCCNNN,Tt',Xx'); Vv = ones(size(Ww)) + Ww*sqrt(-1); Vv = Vv.'; set(notice(1),'string','Computing the graphic elements.'); set(notice(2),'string',''); Arrflag = settings(1); N = settings(2); deltat = (WINvect(2) - WINvect(1))/(N-1); deltax = (WINvect(4) - WINvect(3))/(N-1); mgrid = Tt+Xx.*sqrt(-1); % mgrid = mgrid(:); zz=Vv.'; sc = min(deltat,deltax); arrow=[-1,1].'; zzz=sign(zz); scale = sqrt((real(zzz)/deltat).^2+(imag(zzz)/deltax).^2); ww = (zzz == 0); scale = scale + ww; aa1 = 0.3*arrow*(zzz./scale)+ones(size(arrow))*(mgrid.'); [r,c] = size(aa1); aa1 = [aa1;NaN*ones(1,c)]; aa1 = aa1(:); arrow = [0,1,.7,1,.7].' + [0,0,.25,0,-.25].' * sqrt(-1); zz=sign(zz).*((abs(zz)).^(1/3)); scale = 0.9*sc./max(max(abs(zz))); aa2 = scale*arrow*zz +ones(size(arrow))*(mgrid.'); [r,c] = size(aa2); aa2 = [aa2;NaN*ones(1,c)]; aa2 = aa2(:); axes(dfdispa); arrh = get(dh(12),'user'); % Delete the old field data. if (arrh ~= []) delete(arrh); end % We plot both the line field and the vector field. Then we % control which is seen by manipulating the visibility. if (Arrflag ==1) arrh(1) = plot(real(aa1),imag(aa1),'-c','visible','on'); arrh(2) = plot(real(aa2),imag(aa2),'-c','visible','off'); elseif (Arrflag == 2) arrh(1) = plot(real(aa1),imag(aa1),'-c','visible','off'); arrh(2) = plot(real(aa2),imag(aa2),'-c','visible','on'); else arrh(1) = plot(real(aa1),imag(aa1),'-c','visible','off'); arrh(2) = plot(real(aa2),imag(aa2),'-c','visible','off'); end set(dh(12),'user',arrh); % Save the handles for later use. title(Labstr); xlabel(Tname);ylabel(Xname); set(notice(1),'string','Ready.'); set(notice(2),'string',''); axis([Dtint,Dxint]); dfield('refresh'); elseif strcmp(action,'down') % 'down' is the Window Button Down call. It starts the computation of % solutions from a click of the mouse. dh = get(gcf,'user'); notice = dh(2:3); initpt = get(gca,'currentpoint'); initpt = initpt(1,[1,2]); dfield('solution',initpt); RFLAG = get(dh(5),'value'); if RFLAG dfield('refresh'); end set(notice(1),'string','Ready.') set(notice(2),'string',' '); elseif strcmp(action,'several') % 'several' allows the user to pick several initial points at once. % This is not needed in X-windows, but it is on the Macintosh. dh = get(gcf,'user'); notice = dh(2:3); RFLAG = get(dh(5),'value'); set(notice(1),'string','Pick initial points with the mouse.') set(notice(2),'string','Enter "Return" when finished.'); [X,Y]=ginput; NN = length(X); set(notice(1),'string','Working.') set(notice(2),'string',''); for k = 1:NN initpt = [X(k),Y(k)]; dfield('solution',initpt); end if RFLAG dfield('refresh') end set(notice(1),'string','Ready.') set(notice(2),'string',' '); elseif strcmp(action,'solution') % 'solution' affects the computation and (erasemode == none) plotting of % solutions. It also stores the data as appropriate. dh = get(gcf,'user'); dm = get(dh(1),'user'); notice = dh(2:3); RFLAG = get(dh(5),'value'); if (RFLAG == 0) if (strcmp(get(dh(5),'enable'),'off')) set(dh(5),'enable','on'); end end initpt = input1; FFFCCNNN = deblank(dm(3,:));; dfdispa = dh(14); settings = dh(19:24); ptstr = [' (',num2str(initpt(1)), ', ', num2str(initpt(2)), ').']; set(notice(1),'string',... ['Working on the forward trajectory from',ptstr]) Dxint = get(dfdispa,'xlim'); Dyint = get(dfdispa,'ylim'); htemp = get(dfdispa,'user'); window = [Dxint, Dyint]; magn = settings(3); steps = settings(4); itlim = settings(5); tol = settings(6); [tp,xp] = dfsolve(FFFCCNNN,initpt,window,magn,1.0,steps,tol,itlim); hnew = get(dfdispa,'children'); hnew = hnew(1); htemp = [htemp;hnew]; % Save the handles of the orbit ends. set(notice(1),'string',... ['Working on the backward trajectory from',ptstr]) [tm,xm] = dfsolve(FFFCCNNN,initpt,window,magn,-1.0,steps,tol,itlim); hnew = get(dfdispa,'children'); hnew = hnew(1); htemp = [htemp;hnew]; % Save the handles of the orbit ends. % Store the trajectory. xm = flipud([tm,xm]); x=[xm;[tp,xp]]; newtraj = get(dh(8),'user'); [mm,nn] = size(newtraj); if (nn == 0) newtraj = x; else % In this case we have to make sure the % trajectories fit in the same matrix. l = size(x,1); if (l < mm) x=[x;ones(mm-l,1)*x(l,:)]; elseif (mm < l) newtraj = [newtraj;ones(l-mm,1)*newtraj(mm,:)]; end newtraj=[newtraj,x]; end set(dh(8),'user',newtraj); set(notice(2),'string','Ready.'); set(dfdispa,'user',htemp); % Save the handles of the orbit ends. elseif strcmp(action,'kcompute') % 'kcompute' is the call back for the Compute button on the DFIELD Keyboard figure. errmsg1 = 'Enter initial values for both variables.'; errmsg2 = 'You must start DFIELD from the beginning.'; kh = get(gcf,'user'); initpt = [str2num(get(kh(2),'string')),str2num(get(kh(4),'string'))]; if (length(initpt) ~= 2) error(errmsg1); end figs = get(0,'children'); dfdisp = 0; for (figno = 1:length(figs)); if (strcmp(get(figs(figno),'name'),'DFIELD Display')) dfdisp = figs(figno); end end if (dfdisp == 0) error(errmsg2); else figure(dfdisp); dfield('solution',initpt); dh = get(dfdisp,'user'); notice = dh(2:3); RFLAG = get(dh(5),'value'); if RFLAG dfield('refresh'); end set(notice(1),'string','Ready.'); set(notice(2),'string',''); end elseif strcmp(action,'kbd') % 'kbd' is the callback for the Keyboard Input menu selection. It % sets up the DFIELD Keyboard figure which allows accurate input of % initial values using the keyboard. dh = get(gcf,'user'); dm = get(dh(1),'user'); Tname = deblank(dm(1,:)); Xname = deblank(dm(2,:)); txtl = 200;txth = 22; dfkbd = figure('pos',[30 200 (txtl+102) (9*txth)],... 'resize','off','name','DFIELD Keyboard input','numb','off'); figure(dfkbd) KBD(1) = uicontrol('style','text','pos',[1 7*txth txtl txth],... 'horiz','right','string',['The initial value of ',Tname,' = ']); KBD(2) = uicontrol('style','edit','pos',[txtl+1 7*txth 100 txth],... 'string','','call',''); KBD(3) = uicontrol('style','text','pos',[1 5*txth txtl txth],... 'horiz','right',... 'string',['The initial value of ',Xname,' = ']); KBD(4) = uicontrol('style','edit','pos',[txtl+1 5*txth 100 txth],... 'string',''); KBD(5) = uicontrol('style','push',... 'pos',[(txtl+102)/2-35 3*txth 70 txth],... 'string','Compute','call','dfield(''kcompute'')'); KBD(6) = uicontrol('style','push',... 'pos',[(txtl+102)/2-35,txth,70,txth],... 'string','Close','call','close'); set(dfkbd,'user',KBD); elseif strcmp(action,'zoomin') % 'zoomin' is the callback for the Zoomin menu item. It allows the % user to pick a new display rectangle by clicking and dragging the mouse. % % This codes works with RBBOX. Until they get it working on the Macintosh % we will replace it by the older code. % % set(gcf,'WindowButtonDownFcn','dfield(''zoom'')',... % 'WindowButtonUpFcn','1;','inter','yes'); % set(gca,'inter','yes'); % dh = get(gcf,'user'); % notice = dh(2:3); % % set(notice(1),'string','Pick a new display rectangle by dragging the mouse.'); % set(notice(2),'string',''); % %elseif strcmp(action,'zoom') % % dh = get(gcf,'user'); % notice = dh(2:3); % q1 = get(gcf,'currentpoint'); % p1 = get(gca,'currentpoint'); % rbbox([q1 0 0],q1); % p2 = get(gca,'currentpoint'); % a = [p1(1,1:2);p2(1,1:2)]; % a = [min(a);max(a)];a=a(:); % WINvect = a'; % % The following code is the old code. To be replaced by the above % when RBBOX works. % set(gcf,'WindowButtonDownFcn',''); dh = get(gcf,'user'); notice = dh(2:3); set(notice(1),'string','Pick out two opposite corners with the mouse.'); set(notice(2),'string',''); [x1,y1]=ginput(2); WINvect = [min(x1), max(x1), min(y1), max(y1)]; % The following code is valid in both cases. dh(15:18) = WINvect; set(gcf,'user',dh); figure(gcf); axes(gca); set(gcf,'WindowButtonDownFcn','dfield(''down'')',... 'WindowButtonUpFcn',''); dfield('dirfield'); dfset = 0; figs = get(0,'children'); for ( figno = 1:length(figs) ) if(strcmp(get(figs(figno),'name'),'DFIELD Setup')) dfset = figs(figno); end end if (dfset) sh = get(dfset,'user'); wind = sh(9:17); set(wind(3),'string',num2str(WINvect(1))); set(wind(5),'string',num2str(WINvect(2))); set(wind(7),'string',num2str(WINvect(3))); set(wind(9),'string',num2str(WINvect(4))); sh(21:24) = WINvect; sh(25:28) = WINvect; set(dfset,'user',sh); end elseif strcmp(action,'dall') % 'dall' is the callback for the Erase all solutions option. dh = get(gcf,'user'); notice = dh(2:3); set(notice(1),'string','Erasing all trajectories.'); set(notice(2),'string',''); dfdispa = dh(14); newtraj = get(dh(8),'user'); trajh = get(dh(3),'user'); axes(dfdispa); htemp = get(dfdispa,'user'); if (htemp~=[]) set(htemp,'erase','normal'); delete(htemp); % This deletes the orbit ends. end set(dfdispa,'user',[]); delete(trajh); set(dh(3),'user',[]); set(dh(8),'user',[]); if (dh(7) > 4.0) set(dh(5),'enable','off'); end % set(dh(5),'visible','off'); set(notice(1),'string','Ready.'); set(notice(2),'string',''); elseif strcmp(action,'settings') % 'settings' is the call back for the Settings menu option. It sets % up the DFIELD Settings window, which allows the user to interactively % change several parameters that govern the behaviour of the program. dh = get(gcf,'user'); settings = dh(19:24); Arrflag = settings(1); rval1 = ~(Arrflag -1); rval2 = (~(Arrflag -2))*2; rval3 = (~(Arrflag -3))*3; txtl = 350;txth = 18; figwidth = txtl+104; pbwidth = 80; framewidth = 3*pbwidth+2*8+2*10; frleft = (figwidth - framewidth)/2; frbot = 13*txth-5; frpos = [frleft frbot framewidth (txth+10)]; dfsettings = figure('pos',[150 50 figwidth (15*txth)],... 'resize','off','name','DFIELD Settings','numb','off'); figure(dfsettings) setframe = uicontrol('style','frame','pos',frpos); rad(1) = uicontrol('style','radio','pos',[(frleft+8) 13*txth 80 txth],... 'string','Lines','value',rval1); rad(2) = uicontrol('style','radio','pos',[(frleft+pbwidth+18) 13*txth 80 txth],... 'string','Arrows','value',rval2,'max',2); rad(3) = uicontrol('style','radio','pos',[frleft+2*pbwidth+28 13*txth 80 txth],... 'string','None','value',rval3,'max',3); for i=1:3 set(rad(i),'user',rad(:,[1:(i-1),(i+1):3])); end callrad = [ 'me = get(gcf,''currentobject'');',... 'kk = get(me,''max'');',... 'set(get(me,''user''),''value'',0),',... 'set(me,''value'',kk),',... 'data = get(gcf,''user'');',... 'data(1) = kk;'... 'set(gcf,''user'',data);']; set(rad,'call',callrad); call1 = [ 'me = get(gcf,''currentobject'');',... 'kk = floor(str2num(get(me,''string'')));',... '[m,N] = computer;'... 'if (N <= 8192),',... ' N = 32;',... 'else,',... ' N = 50;',... 'end,',... 'kk = min([N,max([5,kk])]);'... 'set(me,''string'',num2str(kk));'... 'data = get(gcf,''user'');',... 'data(2) = kk;',... 'set(gcf,''user'',data);']; settext(1) = uicontrol('style','text','pos',[3 11*txth txtl txth],... 'horiz','left','string','Number of field points per row and column: '); setedit(1) = uicontrol('style','edit','pos',[3+txtl 11*txth 100 txth],... 'string',num2str(settings(2)),'call',call1); settext(2) = uicontrol('style','text','pos',[3 9*txth txtl txth],... 'horiz','left','string','Relative size of calculation window: '); kk = 1+2*settings(3); call2 =[ 'data = get(gcf,''user'');',... 'ss = get(data(8),''string'');',... 'data(3) = max(0,(str2num(ss)-1)/2);',... 'set(data(8),''string'',ss);',... 'set(gcf,''user'',data);']; setedit(2) = uicontrol('style','edit','pos',[3+txtl 9*txth 100 txth],... 'string',num2str(kk),'call',call2); settext(3) = uicontrol('style','text','pos',[3 7*txth txtl txth],... 'horiz','left','string','Minimum number of plot steps across the window: '); call3 =[ 'data = get(gcf,''user'');',... 'ss = max(round(str2num(get(data(9),''string''))),0);',... 'data(4) = ss;',... 'set(data(9),''string'',num2str(ss));',... 'set(gcf,''user'',data);']; setedit(3) = uicontrol('style','edit','pos',[3+txtl 7*txth 100 txth],... 'string',num2str(settings(4)),'call',call3); settext(4) = uicontrol('style','text','pos',[3 5*txth txtl txth],... 'horiz','left','string','Maximum number of iterations per solution: '); call4 =[ 'data = get(gcf,''user'');',... 'data(5) = round(str2num(get(data(10),''string'')));',... 'set(data(10),''string'',num2str(data(5)));',... 'set(gcf,''user'',data);']; setedit(4) = uicontrol('style','edit','pos',[3+txtl 5*txth 100 txth],... 'string',num2str(settings(5)),'call',call4); settext(5) = uicontrol('style','text','pos',[3 3*txth txtl txth],... 'horiz','left','string','Relative error tolerance: '); call5 =[ 'data = get(gcf,''user'');',... 'data(6) = str2num(get(data(11),''string''));',... 'set(data(11),''string'',num2str(data(6)));',... 'set(gcf,''user'',data);']; setedit(5) = uicontrol('style','edit','pos',[3+txtl 3*txth 100 txth],... 'string',num2str(settings(6)),'call',call5); bwidth = 130; spacing = (figwidth-2*bwidth-6)/3; setbutt(1) = uicontrol('style','push','pos',[3+spacing,txth,bwidth,txth],... 'string','Cancel','call','close'); setbutt(2) = uicontrol('style','push','pos',[3+2*spacing+bwidth,txth,bwidth,txth],... 'string','Change settings','call','dfield(''setchange'')'); set(dfsettings,'user',[settings,setedit]); elseif strcmp(action,'setchange') % 'setchange' is the callback for the Change button on the DFIELD Settings window. flag = 0; data = get(gcf,'user'); settings = data(1:6); dfdisp = 0; figs = get(0,'children'); for (figno = 1:length(figs)); if (strcmp(get(figs(figno),'name'),'DFIELD Display')), dfdisp = figs(figno); end end if (dfdisp == 0) error('You must start DFIELD from the beginning.'); else dh = get(dfdisp,'user'); if settings(2)~=dh(20) flag = 1; elseif settings(1)~=dh(19) flag = 2; end dh(19:24) = settings; set(dfdisp,'user',dh); end dfset = 0; for (figno = 1:length(figs)); if (strcmp(get(figs(figno),'name'),'DFIELD Setup')) dfset = figs(figno); end end if (dfset == 0) error('You must start DFIELD from the beginning.'); else sh = get(dfset,'user'); sh(29:34) = settings; set(dfset,'user',sh); end close if flag == 1 dfield('dirfield'); elseif flag == 2 Arrflag = settings(1); arrh = get(dh(12),'user'); ll = length(arrh)/2; if (Arrflag == 1) set(arrh(1:ll),'visible','on'); set(arrh(ll+1:2*ll),'visible','off'); elseif (Arrflag == 2) set(arrh(1:ll),'visible','off'); set(arrh(ll+1:2*ll),'visible','on'); else set(arrh(1:ll),'visible','of'); set(arrh(ll+1:2*ll),'visible','off'); end dfield('refresh'); end elseif strcmp(action,'delete') % 'delete' is the callback for the Delete a graphics object selection % on the menu. oldcall = get(gcf,'WindowButtonDownFcn'); set(gcf,'WindowButtonDownFcn',''); dh = get(gcf,'user'); dm = get(dh(1),'user'); arrh = get(dh(12),'user'); v1 = get(arrh(1),'visible'); v2 = get(arrh(2),'visible'); set(arrh,'visible','off'); dfield('refresh') trjh = get(dh(3),'user'); notice = dh(2:3); set(notice(1),'string','Select a graphics object with the mouse.'); set(notice(2),'string',''); ginput(1); objh = get(gcf,'currentobject'); hc = [gcf gca dh(1:14)] - objh; if ( all(hc) ) ah = find(trjh == objh); if (ah ~= []) trjh = [trjh(1:ah-1);trjh(ah+1:length(trjh))]; set(dh(3),'user',trjh); end delete(objh); set(notice(1),'string','Ready.'); set(notice(2),'string',' ') else set(notice(1),'string','The selected object cannot be deleted.'); set(notice(2),'string','Ready.') end set(arrh(1),'visible',v1); set(arrh(2),'visible',v2); set(gcf,'WindowButtonDownFcn',oldcall); elseif strcmp(action,'refresh') % 'refresh' is the callback for the Update the Display Window % selection from the menu. It deletes the ends of orbits which % have been plotted using erasemode none, and it replots those % solutions so that they become children of the the display % window axes. dfdisp = 0; figs = get(0,'children'); for (figno = 1:length(figs)) if (strcmp(get(figs(figno),'name'),'DFIELD Display')) dfdisp = figs(figno); end end dh = get(dfdisp,'user'); dm = get(dh(1),'user'); dfdispa = dh(14); newtraj = get(dh(8),'user'); trajh = get(dh(3),'user'); axes(dfdispa); htemp = get(dfdispa,'user'); if (htemp~=[]) set(htemp,'erase','normal'); delete(htemp); % This deletes the orbit ends. end set(dfdispa,'user',[]); trjno = size(newtraj,2)/2; evens = [1:trjno]*2; odds = evens -1; newh = line(newtraj(:,odds),newtraj(:,evens),'linestyle','-','color','y'); trajh = [trajh;newh(:)]; drawnow set(dh(8),'user',[]); set(dh(3),'user',trajh); if (dh(7) > 4.0) set(dh(5),'enable','off'); end % set(dh(5),'visible','off'); elseif strcmp(action,'text') dh = get(gcf,'user'); notice = dh(2:3); set(notice(1),'string','Enter the text into the Command Window.'); set(notice(2),'string',' '); oldcall = get(gcf,'WindowButtonDownFcn'); set(gcf,'WindowButtonDownFcn',''); txtstr = input('Enter the text here. > ','s'); set(notice(1),'string','Choose the location of the text.'); gtext(txtstr); dfield('refresh'); set(gcf,'WindowButtonDownFcn',oldcall); set(notice(1),'string','Ready.'); elseif strcmp(action,'print') % 'print' is the callback of the Print button. It first calls % 'refresh', so that all orbit information is part of the axes, % and then it uses the standard MATLAB print command to print % the axes. dh = get(gcf,'user'); dm = get(dh(1),'user'); notice = dh(2:3); set(notice(1),'string','Preparing to print the DFIELD Display Window.'); set(notice(2),'string','Please be patient.'); dfdispa = dh(14); dfield('refresh') set(notice(1),'string','Printing the DFIELD Display Window.'); print set(notice(1),'string','Ready.'); set(notice(2),'string',''); elseif strcmp(action,'quit') % 'quit' is the callback of the Quit buttons on teh DFIELD Setup and DFIELD % Display windows. It provides for an orderly exit, deleting all % associated windows and the function m-file. figs = get(0,'children'); dfdisp = 0; for (figno = 1:length(figs)) nn = get(figs(figno),'name'); if (length(nn) > 1) if (strcmp(nn,'DFIELD Display')) dfdisp = figs(figno); dh = get(dfdisp,'user'); dm = get(dh(1),'user'); FFFCCNNN = deblank(dm(3,:)); if (exist(FFFCCNNN)==2) delete([FFFCCNNN,'.m']);end close(dfdisp) elseif (findstr(nn,'DFIELD')~=[]) close(figs(figno)) end end end end