Q: How to compute a streamfunction?
© Kirill Pankratov, Ph. D. (kirill@plume.mit.edu)u = d(phi)/dx, v = d(phi)/dy for potential flows, u = -d(psi)/dy, v = d(psi)/dx for solenoidal flows.These potentials are computed by integrating the velocities given by matrices u, v using Simpson rule summation. To do this the routine "cumsimp" is added. This routine is actually of much more general application, than the "flowfun" - is is general cumulative integrator - a little bit similar to "cumsum" but much more accurate (for continuous functions) and starting from zero. I think MATLAB should have had something like this long ago it would be useful for anybody dealing with continuous fields. See HELP for additional information.
e = 2; g = 1; [x,y] = meshgrid(0:20,0:15); % This makes regular grid u = e*x-g*y; % Linear velocity field v = g*x-e*y; [phi,psi] = flowfun(u,v); % Here comes the potential and streamfun. contour(phi,20,'--r') % Contours of potential hold on contour(psi,20,'-g') % Contours of streamfunction quiver(u,v,'w') % Now superimpose the velocity field % Now see the meaning of these potentials? If you want the streamfunction only, use psi = flowfun(u,v,'-') (or psi = flowfun(u,v,'psi') or psi = flowfun(u,v,'stream') ).I would appreciate any comments and suggestions about these routines. Regards, Kirill.
================================== save as flowfun.m ========= function [phi,psi] = flowfun(u,v,flag) % FLOWFUN Computes the potential PHI and the streamfunction PSI % of a 2-dimensional flow defined by the matrices of velocity % components U and V, so that % % d(PHI) d(PSI) d(PHI) d(PSI) % u = ----- - ----- , v = ----- + ----- % dx dy dx dy % % For a potential (irrotational) flow PSI = 0, and the laplacian % of PSI is equal to the divergence of the velocity field. % A non-divergent flow can be described by the streamfunction % alone, and the laplacian of the streamfunction is equal to % vorticity (curl) of the velocity field. % The stepsizes dx and dy are assumed to equal unity. % [PHI,PSI] = FLOWFUN(U,V), or in a complex form % [PHI,PSI] = FLOWFUN(U+iV) % returns matrices PHI and PSI of the same sizes as U and V, % containing potential and streamfunction given by velocity % components U, V. % Because these potentials are defined up to the integration % constant their absolute values are such that % PHI(1,1) = PSI(1,1) = 0. % If only streamfunction is needed, the flag can be used: % PSI = FLOWFUN(U,V,FLAG), where FLAG can be a string: % '-', 'psi', 'streamfunction' (abbreviations allowed). % For the potential the FLAG can be '+', 'phi', 'potential'. % Uses command CUMSIMP (Simpson rule summation). % Kirill K. Pankratov, March 7, 1994. % Check input arguments ............................................. issu=0; issv=0; isflag=0; % For input checking isphi = 1; ispsi = 1; % Is phi and psi to be computed if nargin==1, issu = isstr(u); end if nargin==2, issv = isstr(v); end if nargin==1&~issu, v=imag(u); end if issv, flag = v; v = imag(u); isflag = 1; end if nargin==0|issu % Not enough input arguments disp([10 ' Error: function must have input arguments:'... 10 ' matrivces U and V (or complex matrix W = U+iV)' 10 ]) return end if any(size(u)~=size(v)) % Disparate sizes disp([10 ' Error: matrices U and V must be of equal size' 10]) return end if nargin==3, isflag=1; end u = real(u); % Check the flag string . . . . . . . . Dcn = str2mat('+','potential','phi'); Dcn = str2mat(Dcn,'-','streamfunction','psi'); if isflag lmin = min(size(flag,2),size(Dcn,2)); flag = flag(1,1:lmin); A = flag(ones(size(Dcn,1),1),1:lmin)==Dcn(:,1:lmin); if lmin>1, coinc = sum(A'); else, coinc = A'; end fnd = find(coinc==lmin); if fnd~=[], if fnd<4, ispsi=0; else, isphi=0; end, end end phi = []; % Create output psi = []; lx = size(u,2); % Size of the velocity matrices ly = size(u,1); % Now the main computations ......................................... % Integrate velocity fields to get potential and streamfunction % Use Simpson rule summation (function CUMSIMP) % Compute potential PHI (potential, non-rotating part) if isphi cx = cumsimp(u(1,:)); % Compute x-integration constant cy = cumsimp(v(:,1)); % Compute y-integration constant phi = cumsimp(v)+cx(ones(ly,1),:); phi = (phi+cumsimp(u')'+cy(:,ones(1,lx)))/2; end % Compute streamfunction PSI (solenoidal part) if ispsi cx = cumsimp(v(1,:)); % Compute x-integration constant cy = cumsimp(u(:,1)); % Compute y-integration constant psi = -cumsimp(u)+cx(ones(ly,1),:); psi = (psi+cumsimp(v')'-cy(:,ones(1,lx)))/2; end % Rename output if need only PSI if ~isphi&ispsi&nargout==1, phi = psi; end =========================== end flowfun.m ====================== ============================ save as cumsimp.m ================= function f = cumsimp(y) % F = CUMSIMP(Y) Simpson-rule column-wise cumulative summation. % Numerical approximation of a function F(x) such that % Y(X) = dF/dX. Each column of the input matrix Y represents % the value of the integrand Y(X) at equally spaced points % X = 0,1,...size(Y,1). % The output is a matrix F of the same size as Y. % The first row of F is equal to zero and each following row % is the approximation of the integral of each column of matrix % Y up to the givem row. % CUMSIMP assumes continuity of each column of the function Y(X) % and uses Simpson rule summation. % Similar to the command F = CUMSUM(Y), exept for zero first % row and more accurate summation (under the assumption of % continuous integrand Y(X)). % % See also CUMSUM, SUM, TRAPZ, QUAD % Kirill K. Pankratov, March 7, 1994. % 3-points interpolation coefficients to midpoints. % Second-order polynomial (parabolic) interpolation coefficients % from Xbasis = [0 1 2] to Xint = [.5 1.5] c1 = 3/8; c2 = 6/8; c3 = -1/8; % Determine the size of the input and make column if vector ist = 0; % If to be transposed lv = size(y,1); if lv==1, ist = 1; y = y(:); lv = length(y); end f = zeros(size(y)); % If only 2 elements in columns - simple sum divided by 2 if lv==2 f(2,:) = (y(1,:)+y(2))/2; if ist, f = f'; end % Transpose output if necessary return end % If more than two elements in columns - Simpson summation num = 1:lv-2; % Interpolate values of Y to all midpoints f(num+1,:) = c1*y(num,:)+c2*y(num+1,:)+c3*y(num+2,:); f(num+2,:) = f(num+2,:)+c3*y(num,:)+c2*y(num+1,:)+c1*y(num+2,:); f(2,:) = f(2,:)*2; f(lv,:) = f(lv,:)*2; % Now Simpson (1,4,1) rule f(2:lv,:) = 2*f(2:lv,:)+y(1:lv-1,:)+y(2:lv,:); f = cumsum(f)/6; % Cumulative sum, 6 - denom. from the Simpson rule if ist, f = f'; end % Transpose output if necessary ============================= end cumsimp.m =================