├── README.md
├── StokesFlowSimulation_Tutorial.pdf
├── images
├── flowfield_3D.png
├── flowfield_combo_fig.png
└── flowfield_streamfunction.png
└── scripts
├── bem_2d_functions
├── calcUV_BEM_2D.m
├── calc_Amat_BEM_2D.m
├── calc_PS_2D.m
├── calc_PSmat_BEM_2D.m
├── calc_SLDL_2D.m
└── generateBC_BEM_2D.m
├── bem_3d_functions
├── calc_Amat_BEM_3D.m
├── calc_PS_3D.m
├── calc_PSmat_BEM_3D.m
├── calc_SLDL_3D.m
├── calc_singint.m
├── generateBC_BEM_3D.m
├── grid2tri.m
└── trigrid_com_norm.m
├── doit_sim_BEM_2D.m
├── doit_sim_BEM_3D.m
├── doit_sim_MFS_2D.m
├── mfs_2d_functions
├── calcPPsi_MFS_2D.m
├── calcUV_MFS_2D.m
├── calc_Amat_MFS_2D.m
└── generateBC_MFS_2D.m
└── shared_functions
├── InteriorPts_2D.m
├── InteriorPts_3D.m
├── edge3d
├── edgedetect.asv
├── edgedetect.m
├── example.m
├── license.txt
├── plotsurface.m
└── segment.m
├── quiver3D_pub
├── ColorSpec_LongName_to_RGBvalue.m
├── ColorSpec_ShortName_to_RGBvalue.m
├── arrow3D.m
├── demoQuiver3D.m
├── helix.m
├── html
│ ├── demoQuiver3D.html
│ ├── demoQuiver3D.png
│ ├── demoQuiver3D_01.png
│ ├── demoQuiver3D_02.png
│ ├── demoQuiver3D_03.png
│ ├── demoQuiver3D_04.png
│ └── demoQuiver3D_05.png
├── quiver3D.m
└── rotatePoints.m
├── quiverc.m
├── solve_mixedBC.m
├── vis2Dfield_quiver.m
├── vis2Dfield_streamline.m
└── vis3Dfield_cube.m
/README.md:
--------------------------------------------------------------------------------
1 | # Stokes-Flow-Simulation
2 | Stokes-Flow-Simulation is a Matlab implementation of boundary element method (BEM) and method of fundamental solutions (MFS) for simulation of Stokes flow based on traction and velocity boundary conditions.
3 |
4 |
5 |
6 | This repository contains an implementation of numerical simulations of low Reynold's number flow (Stokes flow). The work was done as part of my doctoral thesis at Yale University [1]. There are three possible types of simulations that can be performed with the code:
7 |
8 |
[X, Y] = meshgrid(0:3:9, 0:3:9); 133 | Z = ones(size(X)); 134 | U = zeros(size(X)); 135 | V = U; 136 | W = ones(size(X))*8; 137 | posArray = [X(:),Y(:),Z(:)]; 138 | magnitudeArray = [U(:),V(:),W(:)]; 139 | quiverHandle = quiver3D(posArray, magnitudeArray, 'r'); 140 | 141 | hold on; 142 | axis equal; 143 | grid on; 144 | xlabel('X'); ylabel('Y'); zlabel('Z'); 145 | view(20,30); 146 |
lighting phong; 147 | camlight head; 148 |
numArrows = size(posArray,1); 149 | arrowColors = zeros(numArrows, 3); 150 | Rstream = (0:1/(numArrows-1):1)'; 151 | arrowColors(:,1) = Rstream; 152 | delete(quiverHandle); 153 | colorQuiverHandle = quiver3D(posArray, magnitudeArray, arrowColors); 154 |
delete(colorQuiverHandle); 155 | colorQuiverHandle = quiver3D(posArray, magnitudeArray, arrowColors, 0.9); 156 |
radius = 7; height = 1; numRotations = 2; numPoints = 25; arrowScale = 0.8; 157 | [posArray1, magnitudeArray1] = helix(radius, height, numRotations, numPoints, arrowScale); 158 | arrowColors1 = zeros(numPoints, 3); 159 | BlackToWhite = (0:1/(numPoints-1):1); 160 | WhiteToBlack = (1:-1/(numPoints-1):0); 161 | arrowColors1(:,1) = WhiteToBlack'; 162 | arrowColors1(:,2) = BlackToWhite'; 163 | 164 | radius = 2; height = 0.66; numRotations = 3; 165 | [posArray2, magnitudeArray2] = helix(radius, height, numRotations, numPoints, arrowScale); 166 | arrowColors2 = zeros(numPoints, 3); 167 | arrowColors2(:,3) = BlackToWhite'; 168 | 169 | delete(colorQuiverHandle); 170 | quiver3D(posArray1, magnitudeArray1, arrowColors1, 0.6); 171 | quiver3D(posArray2, magnitudeArray2, arrowColors2, 0.6); 172 | axis equal; 173 | grid on; 174 | xlabel('X'); ylabel('Y'); zlabel('Z'); 175 | view(20,10); 176 | axis tight; 177 | camlight head; 178 | lighting phong; 179 |
Author: Shawn Arseneau
181 |Created: September 15, 2006
182 | 184 | 294 | 295 | -------------------------------------------------------------------------------- /scripts/shared_functions/quiver3D_pub/html/demoQuiver3D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brendanhuang/Stokes-Flow-Simulation/a552e2e249106ff4ea8e60f31a3bad035e9c4d59/scripts/shared_functions/quiver3D_pub/html/demoQuiver3D.png -------------------------------------------------------------------------------- /scripts/shared_functions/quiver3D_pub/html/demoQuiver3D_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brendanhuang/Stokes-Flow-Simulation/a552e2e249106ff4ea8e60f31a3bad035e9c4d59/scripts/shared_functions/quiver3D_pub/html/demoQuiver3D_01.png -------------------------------------------------------------------------------- /scripts/shared_functions/quiver3D_pub/html/demoQuiver3D_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brendanhuang/Stokes-Flow-Simulation/a552e2e249106ff4ea8e60f31a3bad035e9c4d59/scripts/shared_functions/quiver3D_pub/html/demoQuiver3D_02.png -------------------------------------------------------------------------------- /scripts/shared_functions/quiver3D_pub/html/demoQuiver3D_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brendanhuang/Stokes-Flow-Simulation/a552e2e249106ff4ea8e60f31a3bad035e9c4d59/scripts/shared_functions/quiver3D_pub/html/demoQuiver3D_03.png -------------------------------------------------------------------------------- /scripts/shared_functions/quiver3D_pub/html/demoQuiver3D_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brendanhuang/Stokes-Flow-Simulation/a552e2e249106ff4ea8e60f31a3bad035e9c4d59/scripts/shared_functions/quiver3D_pub/html/demoQuiver3D_04.png -------------------------------------------------------------------------------- /scripts/shared_functions/quiver3D_pub/html/demoQuiver3D_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brendanhuang/Stokes-Flow-Simulation/a552e2e249106ff4ea8e60f31a3bad035e9c4d59/scripts/shared_functions/quiver3D_pub/html/demoQuiver3D_05.png -------------------------------------------------------------------------------- /scripts/shared_functions/quiver3D_pub/quiver3D.m: -------------------------------------------------------------------------------- 1 | function qHandle = quiver3D(posArray, magnitudeArray, arrowColors, stemRatio) 2 | 3 | % qHandle = quiver3D(posArray, magnitudeArray, arrowColors, stemRatio) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | % 5 | % Given the posArray (position array) [x1,y1,z1; x2,y2,z2; ...] and 6 | % their relative magnitudes along the x,y,z-axes using magnitudeArray [dx1,dy1,dz1; dx2,dy2,dz2; ...], 7 | % with optional color and stem ratios, output a quiver of arrows. 8 | % 9 | % arrowColors - conforms to 'ColorSpec.' For example, 'r','red',[1 0 0] will all plot a quiver with all arrows as red. 10 | % This can also be in the form of Nx3 where 'N' is the number of arrows, and each column corresponds to the R,G,B values 11 | % stemRatio - ratio of the arrowhead (cone) to the arrowstem (cylinder) [default = 0.75]. For example, setting this value to 0.94 will 12 | % produce arrows with arrowstems 94% of the length and short, 6% cones as arrowheads 13 | % 14 | % Example: 15 | % [X,Y] = meshgrid(1:5, -2:2); 16 | % Z = zeros(size(X)); 17 | % posArray = [X(:),Y(:),Z(:)]; 18 | % 19 | % magnitudeArray = zeros(size(posArray)); 20 | % magnitudeArray(:,1) = 1; 21 | % quiver3D(posArray, magnitudeArray, 'g', 0.6); 22 | % 23 | % 24 | % Forms: 25 | % quiver3D(posArray, magnitudeArray) - plot a quiver of three-dimensional arrows with default color black 26 | % 27 | % quiver3D(posArray, magnitudeArray, arrowColors) 28 | % 29 | % quiver3D(..., arrowColors, stemRatio) - ratio of the arrowhead (cone) to the arrowstem (cylinder) [default = 0.75] 30 | % 31 | % Author: Shawn Arseneau 32 | % Created: September 14, 2006 33 | % Updated: September 18, 2006 34 | % 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | qHandle = []; 37 | 38 | %% ------------------------------------------------------------Initial verification of input parameters 39 | if nargin<2 || nargin>4 40 | error('Invalid number of input arguments. help quiver3D for details'); 41 | end 42 | 43 | numArrows = size(posArray,1); 44 | if numArrows ~= size(magnitudeArray,1) 45 | error('Position and magnitude inputs do not agree. help quiver3D for details'); 46 | end 47 | 48 | %% ----------------------------------------------------------------------------------Default parameters 49 | if nargin<4 50 | stemRatio = 0.75; 51 | end 52 | 53 | if nargin<3 54 | arrowColors = zeros(numArrows, 3); 55 | else 56 | [arrowRow, arrowCol] = size(arrowColors); 57 | 58 | if arrowRow==1 59 | if ischar(arrowColors) %--------------------------------------- in ShortName or LongName color format 60 | if arrowCol==1 61 | RGBvalue = ColorSpec_ShortName_to_RGBvalue(arrowColors); 62 | else 63 | RGBvalue = ColorSpec_LongName_to_RGBvalue(arrowColors); 64 | end 65 | else 66 | if arrowCol~=3 67 | error('arrowColors in RGBvalue must be of the form 1x3'); 68 | end 69 | RGBvalue = arrowColors; 70 | end 71 | arrowColors = []; 72 | arrowColors(1:numArrows,1) = RGBvalue(1); 73 | arrowColors(1:numArrows,2) = RGBvalue(2); 74 | arrowColors(1:numArrows,3) = RGBvalue(3); 75 | 76 | elseif arrowRow~=numArrows 77 | error('arrowColors in RGBvalue must be of the form Nx3'); 78 | end 79 | end 80 | 81 | 82 | %% ---------------------------------------------------------------Loop through all arrows and plot in 3D 83 | hold on; 84 | for i=1:numArrows 85 | qHandle(i,:) = arrow3D(posArray(i,:), magnitudeArray(i,:), arrowColors(i,:), stemRatio); 86 | end 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /scripts/shared_functions/quiver3D_pub/rotatePoints.m: -------------------------------------------------------------------------------- 1 | function rotatedData = rotatePoints(alignmentVector, originalData) 2 | 3 | % rotatedData = rotatePoints(alignmentVector, originalData) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | % 5 | % Rotate the 'originalData' in the form of Nx2 or Nx3 about the origin by aligning the x-axis with the alignment vector 6 | % 7 | % Rdata = rotatePoints([1,2,-1], [Xpts(:), Ypts(:), Zpts(:)]) - rotate the (X,Y,Z)pts in 3D with respect to the vector [1,2,-1] 8 | % 9 | % Rotating using spherical components can be done by first converting using [dX,dY,dZ] = cart2sph(theta, phi, rho); alignmentVector = [dX,dY,dZ]; 10 | % 11 | % Example: 12 | % %% Rotate the point [3,4,-7] with respect to the following: 13 | % %%%% Original associated vector is always [1,0,0] 14 | % %%%% Calculate the appropriate rotation requested with respect to the x-axis. For example, if only a rotation about the z-axis is 15 | % %%%% sought, alignmentVector = [2,1,0] %% Note that the z-component is zero 16 | % rotData = rotatePoints(alignmentVector, [3,4,-7]); 17 | % 18 | % Author: Shawn Arseneau 19 | % Created: Feb.2, 2006 20 | % 21 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 22 | 23 | alignmentDim = numel(alignmentVector); 24 | DOF = size(originalData,2); %---- DOF = Degrees of Freedom (i.e. 2 for two dimensional and 3 for three dimensional data) 25 | 26 | if alignmentDim~=DOF 27 | error('Alignment vector does not agree with originalData dimensions'); 28 | end 29 | if DOF<2 || DOF>3 30 | error('rotatePoints only does rotation in two or three dimensions'); 31 | end 32 | 33 | 34 | if DOF==2 % 2D rotation... 35 | [rad_theta, rho] = cart2pol(alignmentVector(1), alignmentVector(2)); 36 | deg_theta = -1 * rad_theta * (180/pi); 37 | ctheta = cosd(deg_theta); stheta = sind(deg_theta); 38 | 39 | Rmatrix = [ctheta, -1.*stheta;... 40 | stheta, ctheta]; 41 | rotatedData = originalData*Rmatrix; 42 | 43 | else % 3D rotation... 44 | [rad_theta, rad_phi, rho] = cart2sph(alignmentVector(1), alignmentVector(2), alignmentVector(3)); 45 | rad_theta = rad_theta * -1; 46 | deg_theta = rad_theta * (180/pi); 47 | deg_phi = rad_phi * (180/pi); 48 | ctheta = cosd(deg_theta); stheta = sind(deg_theta); 49 | Rz = [ctheta, -1.*stheta, 0;... 50 | stheta, ctheta, 0;... 51 | 0, 0, 1]; %% First rotate as per theta around the Z axis 52 | rotatedData = originalData*Rz; 53 | 54 | [rotX, rotY, rotZ] = sph2cart(-1* (rad_theta+(pi/2)), 0, 1); %% Second rotation corresponding to phi 55 | rotationAxis = [rotX, rotY, rotZ]; 56 | u = rotationAxis(:)/norm(rotationAxis); %% Code extract from rotate.m from MATLAB 57 | cosPhi = cosd(deg_phi); 58 | sinPhi = sind(deg_phi); 59 | invCosPhi = 1 - cosPhi; 60 | x = u(1); 61 | y = u(2); 62 | z = u(3); 63 | Rmatrix = [cosPhi+x^2*invCosPhi x*y*invCosPhi-z*sinPhi x*z*invCosPhi+y*sinPhi; ... 64 | x*y*invCosPhi+z*sinPhi cosPhi+y^2*invCosPhi y*z*invCosPhi-x*sinPhi; ... 65 | x*z*invCosPhi-y*sinPhi y*z*invCosPhi+x*sinPhi cosPhi+z^2*invCosPhi]'; 66 | 67 | rotatedData = rotatedData*Rmatrix; 68 | end 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /scripts/shared_functions/quiverc.m: -------------------------------------------------------------------------------- 1 | function hh = quiverc(varargin) 2 | % Modified version of Quiver to plots velocity vectors as arrows 3 | % with components (u,v) at the points (x,y) using the current colormap 4 | 5 | % Bertrand Dano 3-3-03 6 | % Extended by Stephan Jonas 9/14/12 7 | % Copyright 1984-2002 The MathWorks, Inc. 8 | 9 | %QUIVERC Quiver color plot. 10 | % QUIVERC(X,Y,U,V) plots velocity vectors as arrows with components (u,v) 11 | % at the points (x,y). The matrices X,Y,U,V must all be the same size 12 | % and contain corresponding position and velocity components (X and Y 13 | % can also be vectors to specify a uniform grid). QUIVER automatically 14 | % scales the arrows to fit within the grid. 15 | % 16 | % QUIVERC(U,V) plots velocity vectors at equally spaced points in 17 | % the x-y plane. 18 | 19 | % QUIVERC(U,V,C) plots velocity vectors at equally spaced points in 20 | % the x-y plane colorcoded with the colors givin in C. 21 | % 22 | % QUIVERC(U,V,S), QUIVERC(U,V,C,S), QUIVER(X,Y,U,V,S) or QUIVER(X,Y,U,V,C, S) automatically scales the 23 | % arrows to fit within the grid and then stretches them by S. Use 24 | % S=0 to plot the arrows without the automatic scaling. 25 | % 26 | % QUIVERC(...,LINESPEC) uses the plot linestyle specified for 27 | % the velocity vectors. Any marker in LINESPEC is drawn at the base 28 | % instead of an arrow on the tip. Use a marker of '.' to specify 29 | % no marker at all. See PLOT for other possibilities. 30 | % 31 | % QUIVERC(...,'filled') fills any markers specified. 32 | % 33 | % H = QUIVERC(...) returns a vector of line handles. 34 | % 35 | % Example: 36 | % [x,y] = meshgrid(-2:.2:2,-1:.15:1); 37 | % z = x .* exp(-x.^2 - y.^2); [px,py] = gradient(z,.2,.15); 38 | % contour(x,y,z), hold on 39 | % quiverc(x,y,px,py), hold off, axis image 40 | % 41 | % See also FEATHER, QUIVER3, PLOT. 42 | % Clay M. Thompson 3-3-94 43 | % Copyright 1984-2002 The MathWorks, Inc. 44 | % $Revision: 5.21 $ $Date: 2002/06/05 20:05:16 $ 45 | %------------------------------------------------------------- 46 | 47 | set(gca, 'color', 'blue'); 48 | % Arrow head parameters 49 | alpha = 0.33; % Size of arrow head relative to the length of the vector 50 | beta = 0.23; % Width of the base of the arrow head relative to the length 51 | autoscale = 1; % Autoscale if ~= 0 then scale by this. 52 | plotarrows = 1; % Plot arrows 53 | sym = ''; 54 | 55 | filled = 0; 56 | ls = '-'; 57 | ms = ''; 58 | col = ''; 59 | lw=2; 60 | 61 | nin = nargin; 62 | % Parse the string inputs 63 | while isstr(varargin{nin}), 64 | vv = varargin{nin}; 65 | if ~isempty(vv) & strcmp(lower(vv(1)),'f') 66 | filled = 1; 67 | nin = nin-1; 68 | else 69 | [l,c,m,msg] = colstyle(vv); 70 | if ~isempty(msg), 71 | error(sprintf('Unknown option "%s".',vv)); 72 | end 73 | if ~isempty(l), ls = l; end 74 | if ~isempty(c), col = c; end 75 | if ~isempty(m), ms = m; plotarrows = 0; end 76 | if isequal(m,'.'), ms = ''; end % Don't plot '.' 77 | nin = nin-1; 78 | end 79 | end 80 | 81 | 82 | error(nargchk(2,6,nin)); 83 | if length(varargin{nin})==1 % quiver(u,v,s) or quiver(x,y,u,v,s) 84 | autoscale = varargin{nin}; 85 | nin = nin-1; 86 | end 87 | 88 | % Check numeric input arguments 89 | if nin<4 % quiver(u,v), quiver(u,v,c) or quiver(u,v,c,s) 90 | [msg,x,y,u,v] = xyzchk(varargin{1:2}); 91 | else 92 | [msg,x,y,u,v] = xyzchk(varargin{1:4}); 93 | end 94 | if ~isempty(msg), error(msg); end 95 | 96 | % Scalar expand u,v 97 | if numel(u)==1, u = u(ones(size(x))); end 98 | if numel(v)==1, v = v(ones(size(u))); end 99 | 100 | if autoscale, 101 | % Base autoscale value on average spacing in the x and y 102 | % directions. Estimate number of points in each direction as 103 | % either the size of the input arrays or the effective square 104 | % spacing if x and y are vectors. 105 | if min(size(x))==1, n=sqrt(numel(x)); m=n; else [m,n]=size(x); end 106 | delx = diff([min(x(:)) max(x(:))])/n; 107 | dely = diff([min(y(:)) max(y(:))])/m; 108 | len = sqrt((u.^2 + v.^2)/(delx.^2 + dely.^2)); 109 | autoscale = autoscale*0.9 / max(len(:)); 110 | u = u*autoscale; v = v*autoscale; 111 | end 112 | 113 | %---------------------------------------------- 114 | % Define colormap 115 | if nin==3 || nin==5 116 | vr = varargin{nin}; 117 | else 118 | vr=sqrt(u.^2+v.^2); 119 | end 120 | vrn=round(vr/max(vr(:))*64); 121 | %CC=colormap; 122 | %CC=parula(64); 123 | CC=jet(128); 124 | CC=CC(65:end,:); 125 | %CC=flipud(CC(1:64,:)); 126 | %CC=hot(64); 127 | ax = newplot; 128 | next = lower(get(ax,'NextPlot')); 129 | hold_state = ishold; 130 | 131 | %---------------------------------------------- 132 | % Make velocity vectors and plot them 133 | 134 | x = x(:).';y = y(:).'; 135 | u = u(:).';v = v(:).'; 136 | vrn=vrn(:).'; 137 | uu = [x;x+u;repmat(NaN,size(u))]; 138 | vv = [y;y+v;repmat(NaN,size(u))]; 139 | vrn1= [vrn;repmat(NaN,size(u));repmat(NaN,size(u))]; 140 | 141 | uui=uu(:); vvi=vv(:); vrn1=vrn1(:); imax=size(uui); 142 | hold on 143 | for i= 1:3:imax-1 144 | ii=int8(round(vrn1(i))); 145 | if ii==0; ii=1; end 146 | c1= CC(ii,1); c2= CC(ii,2); c3= CC(ii,3); 147 | plot(uui(i:i+1),vvi(i:i+1),'linewidth',lw,'color',[c1 c2 c3]); 148 | end 149 | 150 | %---------------------------------------------- 151 | % Make arrow heads and plot them 152 | if plotarrows, 153 | 154 | hu = [x+u-alpha*(u+beta*(v+eps));x+u; ... 155 | x+u-alpha*(u-beta*(v+eps));repmat(NaN,size(u))]; 156 | hv = [y+v-alpha*(v-beta*(u+eps));y+v; ... 157 | y+v-alpha*(v+beta*(u+eps));repmat(NaN,size(v))]; 158 | vrn2= [vrn;vrn;vrn;vrn]; 159 | 160 | uui=hu(:); vvi=hv(:); vrn2=vrn2(:); imax=size(uui); 161 | 162 | for i= 1:imax-1 163 | ii=int8(round(vrn2(i))); 164 | if ii==0; ii=1; end 165 | c1= CC(ii,1); c2= CC(ii,2); c3= CC(ii,3); 166 | plot(uui(i:i+1),vvi(i:i+1),'linewidth',lw,'color',[c1 c2 c3]); 167 | end 168 | 169 | else 170 | h2 = []; 171 | end 172 | %---------------------------------------------- 173 | 174 | if ~isempty(ms), % Plot marker on base 175 | hu = x; hv = y; 176 | hold on 177 | h3 = plot(hu(:),hv(:),[col ms]); 178 | if filled, set(h3,'markerfacecolor',get(h1,'color')); end 179 | else 180 | h3 = []; 181 | end 182 | 183 | if ~hold_state, hold off, view(2); set(ax,'NextPlot',next); end 184 | 185 | if nargout>0, hh = [h1;h2;h3]; end 186 | set(gca,'XTick',[]) 187 | set(gca,'YTick',[]) 188 | 189 | %set(gca, 'color', [0 0 0],'Xcolor','w','Ycolor','w'); 190 | %set(gcf, 'color', [0 0 0]); 191 | %set(gcf, 'InvertHardCopy', 'off'); 192 | -------------------------------------------------------------------------------- /scripts/shared_functions/solve_mixedBC.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % 3 | % Stokes-Flow-Simulation by Brendan Huang 4 | % Script: solve_mixedBC 5 | % 6 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7 | % 8 | % MIT License 9 | % 10 | % Copyright (c) 2015 Brendan K. Huang 11 | % 12 | % Permission is hereby granted, free of charge, to any person obtaining a copy 13 | % of this software and associated documentation files (the "Software"), to deal 14 | % in the Software without restriction, including without limitation the rights 15 | % to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | % copies of the Software, and to permit persons to whom the Software is 17 | % furnished to do so, subject to the following conditions: 18 | % 19 | % The above copyright notice and this permission notice shall be included in all 20 | % copies or substantial portions of the Software. 21 | % 22 | % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | % IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | % FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | % AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | % LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | % OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | % SOFTWARE. 29 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 | % 31 | % Description: This function solves the equation u = G f + T u 32 | % where u is the flow on the boundary, f is the traction on the boundary, G 33 | % is the single layer potential, and T is the double layer potential. Some 34 | % elements of both u and f may be known, while others are unknown. 35 | % The solution is done by collecting all the known coeeficients in one vector and 36 | % all the unknown coefficients in another vector (swapping traction and boundary conditions 37 | % using the matlab deal function, inverting the equation, and then swaping the 38 | % solved for traction and boundary conditions back in. 39 | % 40 | % Inputs: 41 | % BCtotal - known velocity / traction values on boundary, all dimensions (2D 42 | % or 3D) in a single column 43 | % alpha - index specifying which boundary element is traction versus velocity 44 | % SLmat - single layer potential 45 | % DLmat - double layer potential 46 | % visc - viscosity 47 | % dimen - 2D vs. 3D 48 | % 49 | % Outputs: 50 | % u0 velocity values of boundary, all dimensions in a single column 51 | % f0 traction values on boundaries, all dimensions in a single column 52 | % bcu, bcv, [bcw] - u0 split into proper dimensions 53 | % fx, fy, [fz] - f0 split into proper dimensions 54 | % We have a variable out structure depending on the number of dimensions 55 | % For 2D for example, bcu, bcv, fx, and fy are nout 1 - 4 56 | 57 | function [u0,f0,nout1,nout2,nout3,nout4,nout5,nout6] = solve_mixedBC(SLmat,DLmat,BCtotal,visc,alpha,dimen) 58 | 59 | % We start by multiplying our single and double layer potential matrices by 60 | % the proper coefficients 61 | switch dimen 62 | case '2D' 63 | A=1/(2*pi*visc)*SLmat; 64 | B=(1/(2*pi)*DLmat-eye(size(DLmat))); 65 | case '3D' 66 | A=1/(4*pi*visc)*SLmat; 67 | B=(1/(4*pi)*DLmat-eye(size(DLmat))); 68 | end 69 | % Our Boundary Condition vector BCtotal is a long vector that contains 70 | % either values of u or f. Whether the value is u or f is determined by the 71 | % alpha vector. Here, if a boundary condition is a traction one (f), then 72 | % we swap the single and double layer potentials for that element 73 | [A(:,alpha),B(:,alpha)]=deal(-B(:,alpha),-A(:,alpha)); 74 | 75 | % may want to A\B this in the future 76 | f0=inv(A)*B*BCtotal; 77 | u0=BCtotal; 78 | 79 | % f0 is our now solved for coefficients. Most are traction, but the 80 | % elements in BC total that were traction need to be swapped back 81 | [u0(alpha),f0(alpha)]=deal(f0(alpha),u0(alpha)); 82 | 83 | % Split u0 and f0 into respective x,y, [z] dimensions 84 | switch dimen 85 | case '2D' 86 | n1=numel(u0)/2; 87 | nout1=u0(1:n1); 88 | nout2=u0(n1+1:end); 89 | nout3=f0(1:n1); 90 | nout4=f0(n1+1:end); 91 | case '3D' 92 | n1=numel(u0)/3; 93 | nout1=u0(1:n1); 94 | nout2=u0(n1+1:2*n1); 95 | nout3=u0(2*n1+1:end); 96 | nout4=f0(1:n1); 97 | nout5=f0(n1+1:2*n1); 98 | nout6=f0(2*n1+1:end); 99 | end 100 | end -------------------------------------------------------------------------------- /scripts/shared_functions/vis2Dfield_quiver.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % 3 | % Stokes-Flow-Simulation by Brendan Huang 4 | % Script: vis2Dfield_quiver 5 | % 6 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7 | % 8 | % MIT License 9 | % 10 | % Copyright (c) 2015 Brendan K. Huang 11 | % 12 | % Permission is hereby granted, free of charge, to any person obtaining a copy 13 | % of this software and associated documentation files (the "Software"), to deal 14 | % in the Software without restriction, including without limitation the rights 15 | % to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | % copies of the Software, and to permit persons to whom the Software is 17 | % furnished to do so, subject to the following conditions: 18 | % 19 | % The above copyright notice and this permission notice shall be included in all 20 | % copies or substantial portions of the Software. 21 | % 22 | % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | % IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | % FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | % AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | % LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | % OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | % SOFTWARE. 29 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 | % 31 | % Description: This function plots the flow field simulated in 32 | % two-dimensions by the Stokes-Flow-Simulation. It additionally plots the 33 | % boundary points and the flow on the boundary. Square represent stationary 34 | % points on the boundary 35 | % 36 | % 37 | % 38 | % Inputs: 39 | % x, y: x and y coordinates of interior points 40 | % u, v: flow vector of interior points 41 | % xbc, ybc: x and y coordinates of boundary elements 42 | % ubc, vbc: flow vector of boundary elements 43 | % fignum: optional to specify numbering of Matlab figure 44 | % 45 | 46 | function vis2Dfield_quiver(x,y,u,v,xbc,ybc,ubc,vbc,fignum) 47 | 48 | if nargin<9 49 | fignum=1; 50 | end 51 | 52 | % Find elements where there is flow on the boundary 53 | ind1=bitor(ubc~=0,vbc~=0); 54 | if numel(ubc(ind1))>10 55 | % for visualization sake, we don't plot the flow at every boundary point if 56 | % we have more than 10. We'll use our function reducemat to downsample our 57 | % points 58 | % ds is downsample factor 59 | ds=floor(numel(ubc(ind1))/10); 60 | 61 | % leftover is how many values we omit at the end 62 | leftover=mod(numel(ubc(ind1)),ds); 63 | unz=reducemat(ubc(ind1),ds,leftover); 64 | vnz=reducemat(vbc(ind1),ds,leftover); 65 | xnz=reducemat(xbc(ind1),ds,leftover); 66 | ynz=reducemat(ybc(ind1),ds,leftover); 67 | else 68 | unz=ubc(ind1); 69 | vnz=vbc(ind1); 70 | xnz=xbc(ind1); 71 | ynz=ybc(ind1); 72 | end 73 | 74 | % Find the boundaries of domain 75 | x1=min(x(:)); 76 | x2=max(x(:)); 77 | y1=min(y(:)); 78 | y2=max(y(:)); 79 | xl=x2-x1; 80 | yl=y2-y1; 81 | 82 | % set color of boundary points 83 | boundarycolor=[0 0 0]/255; 84 | figure(fignum); 85 | 86 | % call the color quiver function 87 | quiverc(x(:),y(:),u(:),v(:));hold on; 88 | 89 | % plot the boundaries 90 | plot(xbc(~ind1),ybc(~ind1),'s','MarkerEdgeColor',boundarycolor,'LineWidth',1.5); 91 | axis([x1-0.1*xl, x2+0.1*xl, y1-0.1*yl, y2+0.1*yl]); 92 | 93 | % quiver the moving portion of the boundary 94 | g1=quiver(xnz,ynz,unz,vnz,0.2,'Linewidth',1.5); 95 | set(g1, 'Color',boundarycolor); 96 | hold off; 97 | end 98 | 99 | % reducemat a function to downsample the quiver field if there are too many 100 | % points on the boundary 101 | function zz=reducemat(mat1,ds,leftover) 102 | a2=mat1(1:end-leftover); 103 | a3=mat1(end-leftover:end); 104 | a2=squeeze(mean(reshape(a2,ds,[]),1)); 105 | a3=mean(a3); 106 | zz=[a2,a3]; 107 | end -------------------------------------------------------------------------------- /scripts/shared_functions/vis2Dfield_streamline.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % 3 | % Stokes-Flow-Simulation by Brendan Huang 4 | % Script: vis2Dfield_streamline 5 | % 6 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7 | % 8 | % MIT License 9 | % 10 | % Copyright (c) 2015 Brendan K. Huang 11 | % 12 | % Permission is hereby granted, free of charge, to any person obtaining a copy 13 | % of this software and associated documentation files (the "Software"), to deal 14 | % in the Software without restriction, including without limitation the rights 15 | % to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | % copies of the Software, and to permit persons to whom the Software is 17 | % furnished to do so, subject to the following conditions: 18 | % 19 | % The above copyright notice and this permission notice shall be included in all 20 | % copies or substantial portions of the Software. 21 | % 22 | % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | % IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | % FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | % AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | % LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | % OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | % SOFTWARE. 29 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 | % 31 | % Description: This function plots the streamfunction simulated in 32 | % two-dimensions by the Stokes-Flow-Simulation. Lines represent contours 33 | % of the streamfunction, which are known as streamlines. It additionally plots 34 | % the boundary points and the flow on the boundary. Square represent stationary 35 | % points on the boundary. 36 | % 37 | % 38 | % 39 | % Inputs: 40 | % x, y: x and y coordinates of interior points 41 | % psi: streamfunction 42 | % xbc, ybc: x and y coordinates of boundary elements 43 | % ubc, vbc: flow vector of boundary elements 44 | % fignum: optional to specify numbering of Matlab figure 45 | 46 | function vis2Dfield_streamline(x,y,psi,xbc,ybc,ubc,vbc,fignum) 47 | 48 | if nargin < 8 49 | fignum=1; 50 | end 51 | 52 | % Find elements where there is flow on the boundary 53 | 54 | ind1=bitor(ubc~=0,vbc~=0); 55 | % for visualization sake, we don't plot the flow at every boundary point if 56 | % we have more than 10. We'll use our function reducemat to downsample our 57 | % points 58 | if numel(ubc(ind1))>10 59 | ds=floor(numel(ubc(ind1))/10); % ds is downsample factor 60 | leftover=mod(numel(ubc(ind1)),ds); % leftover is how many values we omit at the end 61 | unz=reducemat(ubc(ind1),ds,leftover); 62 | vnz=reducemat(vbc(ind1),ds,leftover); 63 | xnz=reducemat(xbc(ind1),ds,leftover); 64 | ynz=reducemat(ybc(ind1),ds,leftover); 65 | else 66 | unz=ubc(ind1); 67 | vnz=vbc(ind1); 68 | xnz=xbc(ind1); 69 | ynz=ybc(ind1); 70 | end 71 | 72 | 73 | % Find the boundaries of domain 74 | x1=min(x(:)); 75 | x2=max(x(:)); 76 | y1=min(y(:)); 77 | y2=max(y(:)); 78 | xl=x2-x1; 79 | yl=y2-y1; 80 | 81 | % set color of boundary points 82 | boundarycolor=[0 0 0]/255; 83 | figure(fignum); 84 | %quiverc(imresize(x,0.3),imresize(y,0.3),imresize(u,0.3),imresize(v,0.3));hold on; 85 | %gg2=parula(64); 86 | contour(x,y,psi,'Linewidth',3); 87 | set(gca,'XTick',[]) 88 | set(gca,'YTick',[]) 89 | hold on; 90 | 91 | plot(xbc(~ind1),ybc(~ind1),'s','MarkerEdgeColor',boundarycolor,'LineWidth',1.5); 92 | axis([x1-0.1*xl, x2+0.1*xl, y1-0.1*yl, y2+0.1*yl]); 93 | 94 | 95 | % quiver the moving portion of the boundary 96 | g1=quiver(xnz,ynz,unz,vnz,0.2,'Linewidth',1.5); 97 | set(g1, 'Color',boundarycolor); 98 | hold off; 99 | end 100 | 101 | % reducemat a function to downsample the quiver field if there are too many 102 | % points on the boundary 103 | function zz=reducemat(mat1,ds,leftover) 104 | a2=mat1(1:end-leftover); 105 | a3=mat1(end-leftover:end); 106 | a2=squeeze(mean(reshape(a2,ds,[]),1)); 107 | a3=mean(a3); 108 | zz=[a2,a3]; 109 | end -------------------------------------------------------------------------------- /scripts/shared_functions/vis3Dfield_cube.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % 3 | % Stokes-Flow-Simulation by Brendan Huang 4 | % Script: vis3Dfield_cube 5 | % 6 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7 | % 8 | % MIT License 9 | % 10 | % Copyright (c) 2015 Brendan K. Huang 11 | % 12 | % Permission is hereby granted, free of charge, to any person obtaining a copy 13 | % of this software and associated documentation files (the "Software"), to deal 14 | % in the Software without restriction, including without limitation the rights 15 | % to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | % copies of the Software, and to permit persons to whom the Software is 17 | % furnished to do so, subject to the following conditions: 18 | % 19 | % The above copyright notice and this permission notice shall be included in all 20 | % copies or substantial portions of the Software. 21 | % 22 | % THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | % IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | % FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | % AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | % LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | % OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | % SOFTWARE. 29 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 | % 31 | % Description: This function plots the flow field simulated in 32 | % three-dimensions by the Stokes-Flow-Simulation. It additionally plots the 33 | % boundaries elements of the surface, and shades the portion 34 | % of the bottom surface that is moving. A 2D quiver plot is generated on 35 | % the moving surface to indicate the magnitude and direction of flow 36 | % 37 | % 38 | % 39 | % Inputs: 40 | % x, y, z: x and y coordinates of interior points 41 | % u, v, w: flow vector of interior points 42 | % bcx, bcy, bcz: x, y, z coordinates of boundary elements 43 | % bcu, bcv, bcw, vbc: flow vector of boundary elements 44 | % vertpts, elemverts: vertices and indices of triangles to plot of cube 45 | % surface 46 | % 47 | % Note, this script calls the 'plotsurface' function from: 48 | % https://www.mathworks.com/matlabcentral/fileexchange/46260-3d-differential-canny-edge-detector 49 | % 50 | % as well as the 'quiver3D' function from: 51 | % https://www.mathworks.com/matlabcentral/fileexchange/12285-3d-quiver-with-volumized-arrows 52 | % 53 | % Original source code for these functions can be downloaded at Mathworks 54 | % file exchange, but have also been included with this function under 55 | % licensing terms. 56 | % 57 | function vis3Dfield_cube(corner1,corner2,x,y,z,u,v,w,bcx,bcy,bcz,bcu,bcv,bcw,vertpts,elemvert) 58 | 59 | % calculate some geometric properties of where the flow is calculated 60 | xmin=corner1(1); 61 | ymin=corner1(2); 62 | zmin=corner1(3); 63 | xmax=corner2(1); 64 | ymax=corner2(2); 65 | zmax=corner2(3); 66 | 67 | cubevert=[xmin,ymin,zmin;xmin,ymin,zmax;xmin,ymax,zmin;xmin,ymax,zmax;... 68 | xmax,ymin,zmin;xmax,ymin,zmax;xmax,ymax,zmin;xmax,ymax,zmax]; 69 | cubevert1=[cubevert(1,:);cubevert(2,:);cubevert(4,:);cubevert(3,:);cubevert(1,:); ... 70 | cubevert(5,:);cubevert(6,:);cubevert(8,:);cubevert(7,:);cubevert(5,:)]; 71 | cubevert2=[cubevert(1,:);cubevert(5,:);cubevert(6,:);cubevert(2,:)]; 72 | cubevert3=[cubevert(3,:);cubevert(7,:);cubevert(8,:);cubevert(4,:)]; 73 | 74 | 75 | bctot_ordered=sqrt(bcu.^2+bcv.^2+bcw.^2); 76 | bcnonzero=bctot_ordered~=0; 77 | bcxnz=bcx(bcnonzero); 78 | bcynz=bcy(bcnonzero); 79 | bcunz=bcu(bcnonzero); 80 | bcvnz=bcv(bcnonzero); 81 | 82 | % bcz and bcw here are not used because we are doing a 2D quiver plot on 83 | % the bottom surface. 84 | 85 | % here we put the vertices and faces in a structure that is called by the 86 | % plotsurface function 87 | wallstl=struct('faces',elemvert,'vertices',vertpts); 88 | 89 | % we can specify the color of the moving portion of the wall 90 | coloring1=ones(size(elemvert,1),1)*0.5; 91 | coloring1(bctot_ordered(:,1)~=0)=3; 92 | 93 | % here we put all our positional information into a long array 94 | posarray=[x(:), y(:), z(:)]; 95 | 96 | % here we calculate our speed so we can use the max to normalize our arrows 97 | speedarray=sqrt(u(:).^2+v(:).^2+w(:).^2); 98 | 99 | % if we just want to display the direction of the arrows without encoding 100 | % total speed in the size, we can use normalize all speeds 101 | % magarray=[u(:)./speedarray, v(:)./speedarray, w(:)./speedarray]; 102 | 103 | % Here, we set the magnitudes of the arrow size to be proprotional to the 104 | % total speed 105 | magarray=[u(:), v(:), w(:)]/3; 106 | 107 | % Here we will also encode speed with color 108 | dc=dopplerColors(64); 109 | colarray=dc(floor(speedarray/max(speedarray(:))*32)+32,:); 110 | n1=norm(corner1-corner2); 111 | 112 | figure(30); 113 | % call the plot surface function to plot the boundary elements 114 | plotsurface(wallstl,coloring1,0.2);hold on; 115 | % plot the edges of the cube for clarity 116 | plot3(cubevert1(:,1),cubevert1(:,2),cubevert1(:,3),... 117 | cubevert2(:,1),cubevert2(:,2),cubevert2(:,3),... 118 | cubevert3(:,1),cubevert3(:,2),cubevert3(:,3),'Linewidth',3,'Color',[0,0,0]) 119 | 120 | % call the quiver3D function 121 | quiver3D(posarray,magarray/max(speedarray(:))*n1,colarray); 122 | 123 | % plot the 2D quiver field of the moving surface 124 | quiver(bcxnz,bcynz,bcunz,bcvnz);axis off; 125 | hold off; 126 | camlight('headlight') 127 | 128 | % Depending on your computer, you may have issues with this rendering. You 129 | % can also try to not set this renderer, try 'zbuffer' (deprecated), or try 130 | % 'painters' 131 | set(gcf,'Renderer','opengl'); 132 | drawnow; --------------------------------------------------------------------------------