📄 pdegui.m
字号:
function pdegui(action)%PDEGUI Demonstrate solution of model partial differential equations.% PDEGUI demonstrates the finite difference solution of model problems% involving Laplace's operator:% del^2_U = partial^2_U/partial_x^2 + partial^2_U/partial_y^2.%% The PDEs are:% Poisson equation, del^2_U = f, f = -1.% Heat equation, partial_U/dt = del^2_U - f.% Wave equation, partial^2_U/partial_t^2 = del^2_U.% Eigenvalue equation, del^2_U + lambda U = 0.%% The regions are: % Square.% L-shaped.% H-shaped.% Disc.% Annulus.% Heart.% An pair of "isospectral" drums with the same eigenvalues.%% The boundary values are u = 0 outside the region. The initial values for% the heat and wave equations are impulses at random points in the region.% You can vary the grid spacing, h. Decreasing h increases accuracy,% but also increases memory requirements and computation time.% For the heat equation, you can set sigma = delta_t/h^2.% For the wave equation, you can set sigma = delta_t^2/h^2.% If sigma is too large, the time-stepping methods are unstable.% For the eigenvalue problem, you can set the eigenvalue index.if nargin == 0 Initialize_GUI action = 'restart';enddrawnowif isequal(action,'restart') | ... isequal(action,'h+') | isequal(action,'h-') % Find the buttons regionobj = findobj('tag','region'); regionstr = get(regionobj,'string'); region = regionstr{get(regionobj,'value')}; eqnobj = findobj('tag','eqn'); eqn = get(eqnobj,'value'); hobj = findobj('tag','h'); sigind = findobj('tag','sigind'); indxobj = findobj('tag','indx'); sigmaobj = findobj('tag','sigma'); plusobj = findobj('tag','plus'); minusobj = findobj('tag','minus'); stopobj = findobj('string','stop'); % Set button visibility switch eqn case {1,5} % Poisson, Grid set([sigind,indxobj,sigmaobj,plusobj,minusobj,stopobj],'vis','off'); case 2 % Heat set(sigind,'vis','on','string','sigma ='); set(indxobj,'vis','off'); set(sigmaobj,'vis','on','string','0.250','userdata',0.250); set([plusobj,minusobj,stopobj],'vis','on'); case 3 % Wave set(sigind,'vis','on','string','sigma ='); set(indxobj,'vis','off'); set(sigmaobj,'vis','on','string','0.500','userdata',0.500); set([plusobj,minusobj,stopobj],'vis','on'); case 4 % Eigenvalue set(sigind,'vis','on','string','index ='); set([sigmaobj,stopobj],'vis','off'); set([indxobj,plusobj,minusobj],'vis','on'); end % Adjust h h = str2num(get(hobj,'string')); if isequal(action,'h+') h = 1/round(1/h+3); set(hobj,'string',sprintf('1/%.0f',1/h)) elseif isequal(action,'h-') & (h < 1/3) h = 1/round(1/h-3); set(hobj,'string',sprintf('1/%.0f',1/h)) end % Generate the mesh [x,y] = meshgrid(-1:h:1); [xv,yv,scale] = vertices(region); [in,on] = inregion(x,y,xv,yv); if isequal(region,'Annulus') in = in - inregion(x,y,xv/2,yv/2); xv = [xv NaN xv/2]; yv = [yv NaN yv/2]; end p = find(in-on); G = zeros(size(x)); G(p) = 1:length(p); % Generate the discrete Laplacian. A = -delsq(G); n = size(A,1) % Initialize the solution t = 0; lambda = []; switch eqn case {2,3} % Heat, Wave p = find(G>0); n = length(p); q = ceil(n*rand); x0 = x(p(q)); y0 = y(p(q)); r = (x(p)-x0).^2 + (y(p)-y0).^2; if eqn == 2, c = 1; else c = 1/6; end u = c*exp(-5*r); v = zeros(n,1); otherwise u = []; v = []; end % Save everything in figure's userdata. data.eqn = eqn; data.G = G; data.A = A; data.x = x; data.y = y; data.h = h; data.n = n; data.u = u; data.v = v; data.t = t; data.lambda = lambda; data.xv = xv; data.yv = yv; data.scale = scale; set(gcf,'userdata',data);else % Adjust sigma or index. eqn = get(findobj('tag','eqn'),'value'); if eqn == 4 indxobj = findobj('tag','indx'); indx = str2num(get(indxobj,'string')); if isequal(action,'+') indx = indx + 1; elseif isequal(action,'-') indx = max(1,indx - 1); end set(indxobj,'string',int2str(indx)); else sigmaobj = findobj('tag','sigma'); sigma = str2num(get(sigmaobj,'string')); if isequal(action,'+') sigma = sigma + .001; elseif isequal(action,'-') sigma = sigma - .001; end set(sigmaobj,'string',sprintf('%6.3f',sigma)); endend% Retrieve parameters data = get(gcf,'userdata');A = data.A; u = data.u; v = data.v; t = data.t; scale = data.scale;n = data.n; h = data.h; x = data.x; y = data.y; G = data.G;xv = data.xv; yv = data.yv;% Begin main loopstopobj = findobj('string','stop');closeobj = findobj('string','close');set(stopobj,'userdata',0)set(closeobj,'vis','off')while get(stopobj,'userdata') == 0 switch eqn case 1 % Solve sparse linear system Au = f with f = -1, % scaled so that max(abs(u)) = 1. f = -h^2*scale*ones(n,1); u = A\f; set(stopobj,'userdata',1) case 2 % One step for heat equation sigmaobj = findobj('tag','sigma'); sigma = str2num(get(sigmaobj,'string')); f = -h^2*scale*ones(n,1); t = t + sigma*h^2; u = u + sigma*(A*u - f); data.t = t; data.u = u; case 3 % One step for wave equation sigmaobj = findobj('tag','sigma'); sigma = str2num(get(sigmaobj,'string')); t = t + sqrt(sigma)*h; w = u; u = 2*u - v + sigma*A*u; v = w; data.t = t; data.u = u; data.v = v; case 4 % Some eigenvalues already computed; maybe need more. indxobj = findobj('tag','indx'); indx = str2num(get(indxobj,'string')); if indx >= n indx = n-1; set(indxobj,'string',num2str(n-1)) end while indx > length(data.lambda) k = min(length(data.lambda)+10,n-1); [u,lambda] = eigswatch(-(1/h^2)*A,k); data.lambda = lambda; data.u = u; end lambda = data.lambda(indx); u = data.u(:,indx); u = u/u(min(find(abs(u(:))==max(abs(u(:)))))); set(stopobj,'userdata',1) case 5 % Show grid, no computation u = ones(n,1); set(stopobj,'userdata',1) end % Map the solution onto the grid and display it. U = zeros(size(x)); p = find(G>0); U(p) = u; U(U>1) = 1; U(U<-1) = -1; set(gcf,'renderer','painters') if eqn < 5 contourf(x,y,U,-1:1/8:1) else ms = max(4,min(14,ceil(100*h))); plot(x(p),y(p),'.','markersize',ms,'color',[0 2/3 0]) end line(xv,yv,'color','black') set(gca,'color',get(gcf,'color'),'xtick',[],'ytick',[]) axis square caxis([-1 1]) switch eqn case {2,3} xlabel(sprintf('t = %9.4f',t)); case 4 xlabel(sprintf('lambda(%2d) = %9.4f',indx,lambda)) case 5 xlabel(sprintf('n = %.0f',n)); otherwise end drawnow set(gcf,'userdata',data)endset(stopobj,'vis','off')set(closeobj,'vis','on')% ------------------------------------------------------------------------function Initialize_GUIclf resetset(gcf,'doublebuffer','on','menubar','none', ... 'numbertitle','off','name','PDE gui','userdata',1);set(gca,'pos',[.11 .11 .6 .815])uicontrol( ... 'tag','region', ... 'style','list', ... 'units','normal', ... 'position',[.75 .55 .23 .35], ... 'string',{'Square','L','H','Disc','Annulus', ... 'Heart','Drum1','Drum2'}, ... 'fontsize',12, ... 'value',1, ... 'callback','pdegui(''restart'')')uicontrol( ... 'tag','eqn', ... 'style','list', ... 'units','normal', ... 'position',[.75 .30 .23 .22], ... 'string',{'Poisson','Heat','Wave','Eigenvalue','Grid'}, ... 'fontsize',12, ... 'value',1, ... 'callback','pdegui(''restart'')')uicontrol( ... 'style','text', ... 'units','normal', ... 'position',[.75 .22 .10 .06], ... 'background',get(gcf,'color'), ... 'string',' h = ', ... 'fontsize',12)uicontrol( ... 'tag','h', ... 'style','edit', ... 'units','normal', ... 'position',[.85 .22 .08 .06], ... 'string','1/24', ... 'backgroundcolor',[1 1 1], ... 'fontsize',12, ... 'callback','pdegui(''restart'')')uicontrol( ... 'tag','hminus', ... 'style','pushbutton', ... 'units','normal', ... 'position',[.93 .22 .03 .03], ... 'string','-', ... 'fontsize',12, ... 'callback','pdegui(''h-'')')uicontrol( ... 'tag','hplus', ... 'style','pushbutton', ... 'units','normal', ... 'position',[.93 .25 .03 .03], ... 'string','+', ... 'fontsize',12, ... 'callback','pdegui(''h+'')')uicontrol( ... 'tag','sigind', ... 'style','text', ... 'units','normal', ... 'position',[.75 .14 .10 .06], ... 'background',get(gcf,'color'), ... 'string','', ... 'fontsize',12)uicontrol( ... 'tag','indx', ... 'style','edit', ... 'units','normal', ... 'position',[.85 .14 .08 .06], ... 'string','1', ... 'userdata',1, ... 'backgroundcolor',[1 1 1], ... 'fontsize',12, ... 'callback','pdegui(''indx'')')uicontrol( ... 'tag','sigma', ... 'style','edit', ... 'units','normal', ... 'position',[.85 .14 .08 .06], ... 'string','0.250', ... 'userdata',0.250, ... 'backgroundcolor',[1 1 1], ... 'fontsize',12);uicontrol( ... 'tag','minus', ... 'style','pushbutton', ... 'units','normal', ... 'position',[.93 .14 .03 .03], ... 'string','-', ... 'fontsize',12, ... 'callback','pdegui(''-'')')uicontrol( ... 'tag','plus', ... 'style','pushbutton', ... 'units','normal', ... 'position',[.93 .17 .03 .03], ... 'string','+', ... 'fontsize',12, ... 'callback','pdegui(''+'')')uicontrol( ... 'style','pushbutton', ... 'units','normal', ... 'position',[.80 .05 .12 .06], ... 'string','stop', ... 'fontsize',12, ... 'userdata',0, ... 'callback','set(findobj(''string'',''stop''),''userdata'',1)');uicontrol( ... 'style','toggle', ... 'units','normal', ... 'position',[.80 .05 .12 .06], ... 'string','close', ... 'fontsize',12, ... 'userdata',0, ... 'callback','close(gcf)');% ------------------------------------------------------------------------function [u,lambda] = eigswatch(A,k)% [u,lambda] = eigswatch(A,k)% Modify pointer and text while computing k smallest% eigenvalues and eigenvectors of sparse matrix A.ps = get(gcf,'pointer');set(gcf,'pointer','watch')sigind = findobj('tag','sigind');str = get(sigind,'string');set(sigind,'string','computing')drawnowopts.disp = 0;[u,lambda] = eigs(A,k,0,opts);[lambda,p] = sort(diag(lambda));u = u(:,p);set(sigind,'string',str)set(gcf,'pointer',ps)% ------------------------------------------------------------------------function [xv,yv,scale] = vertices(region)% (xv,yv) = vertices of where region% scale = max(U) where del^2 U = -1 in region.switch region case 'Square' xv = [-1 1 1 -1 -1]; yv = [-1 -1 1 1 -1]; scale = 3.394; case 'L' xv = [0 1 1 -1 -1 0 0]; yv = [0 0 1 1 -1 -1 0]; scale = 6.702; case 'H' xv = [0 1 1 2 2 1 1 -1 -1 -2 -2 -1 -1 0]/2; yv = [1 1 2 2 -2 -2 -1 -1 -2 -2 2 2 1 1]/2; scale = 8.387; case 'Disc' z = exp(2*pi*i*(0:128)/128); xv = real(z); yv = imag(z); scale = 3.960; case 'Annulus' z = exp(2*pi*i*(0:128)/128); xv = real(z); yv = imag(z); scale = 30.12; case 'Heart' t = 0:pi/64:pi; xv = sin(t); yv = sin(t)-2*cos(t)/3; xv = [-fliplr(xv) xv]; yv = [fliplr(yv) yv]-1/3; scale = 8.926; case 'Drum1' xv = [-3 -3 1 1 3 1 -1 -1 -3]/3; yv = [-3 -1 3 1 1 -1 -1 -3 -3]/3; scale = 14.96; case 'Drum2' xv = [-1 -3 -3 1 1 3 1 -1 -1]/3; yv = [-3 -1 1 1 3 1 -1 -1 -3]/3; scale = 15.35;end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -