function phi = fvm_soln_SS_adv_diff( X_edges, Z_edges, X_P, Z_P, Gamma_P, ... rho, S_C, S_P, bc_u, bc_d, bc_e, bc_w ) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% find steady-state phi(x,z), for combined advection and diffusion %% with given heat sources S and conductivity Gamma_P. %% %% div( rho u phi) = div( K grad(phi) ) + S %% %% Uses Patankar Finite Volume method. %% %% IF upwind = 0, (in global block) %% THIS CODE INCLUDES ADVECTIVE FLUX WITH CENTERED DIFFERENCE %% (NO UPWINDING SCHEME) %% *** DON'T USE THIS AT HOME FOR SERIOUS WORK!! *** %% %% IF upwind = 1, %% THIS CODE INCLUDES ADVECTIVE FLUX WITH PATANKAR POWER-LAW SCHEME %% %% %% EXTERNALLY SPECIFIED VELOCITY MUST SATISFY CONTINUITY, %% i.e. IS A CONSTANT IN 1-D %% %% Boundary Conditions: %% vector bc_u = phi_u set value of phi on upper boundary %% vector bc_d = phi_d set value of phi on lower boundary %% vector bc_w = dphi_dx_w set gradient on west boundary %% vector bc_e = dphi_dx_e set gradient on east boundary %% %% %% THIS CODE APPLIES FLUX BOUNDARY CONDITIONS ON VOLUME INTERFACES %% on East and West %% APPLIES FIXED VALUE BOUNDARY CONDITIONS ON VOLUME CENTERS %% in Up and Down %% %% a_P = coefficient of phi_P at point P = (i,j) %% a_E = coefficient of phi_E at point east of (i,j) %% a_E, a_W, a_U, a_D for points East, West, Up, Down %% %% System of equations to be solved for phi %% %% big_A * phi = rhs %% %% big_A = matrix with coefficients a_E etc, modified to include BC %% phi = unknown values in Control-volumes %% rhs = right-hand-side column vector containing sources and BC terms %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % global upwind Peclet % % get Finite-Volume dimensions % ------------------------------ [nz_P, nx_P] = size(X_P); % get dX, dZ - spacings between volume edges % ------------------------------------------- dX = diff(X_edges')'; dZ = diff(Z_edges); % % reduce dimensions in vertical, where boundaries are at nodes dX = dX(1:end-1,:); % get dX_E, dx_W, dZ_U, dZ_D - % - distances to adjacent volume centers % ----------------------------------------------- % if( size(X_P,2) == 1) dX_e = ones( size(X_P) ); dX_w = ones( size(X_P) ); else dX_e = diff(X_P')'; % add dummy row at eastern edge to maintain size [nx, nz] dX_e = [ dX_e dX_e(:,end) ]; % dX_w = diff(X_P')'; % add dummy row at western edge to maintain size [nx, nz] dX_w = [ dX_w(:,1) dX_w ]; end % dZ_u = diff(Z_P); % add dummy row at top edge to maintain size [nx, nz] dZ_u = [ dZ_u(1,:)' dZ_u' ]'; % dZ_d = diff(Z_P); % add dummy row at bottom edge to maintain size [nx, nz] dZ_d = [ dZ_d' dZ_d(end,:)' ]'; % % get f_e, f_w, f_u, f_d % - fractional distances to volume interfaces % --------------------------------------------------- f_e = 1 - (X_edges(1,2:end) - X_P(1,:))./ dX_e(1,:); f_e = repmat( f_e, nz_P, 1 ); f_w = 1 - (X_P(1,:) - X_edges(1,1:(end-1)) ) ./ dX_w(1,:); f_w = repmat( f_w, nz_P, 1 ); f_u = 1 - (Z_P(:,1) - Z_edges(1:(end-1),1 ))./ dZ_u(:,1); f_u = repmat( f_u, 1, nx_P ); % f_d = 1 - (Z_edges(2:end,1 ) - Z_P(:,1) )./ dZ_d(:,1); f_d = repmat( f_d, 1, nx_P ); % % set up b matrix - includes constant part of source matrix S % S = S_C + S_P * phi_P (units are W m^-3) % ---------------------------------------------------------- b = S_C.* dX.* dZ; % % % set up matrices for conductivities in adjacent volumes % ------------------------------------------------------ Gamma_E = [ Gamma_P(:,2:end) Gamma_P(:, end) ]; Gamma_W = [ Gamma_P(:,1) Gamma_P(:,1:end-1) ]; Gamma_U = [ Gamma_P(1,:)' Gamma_P(1:end-1,:)' ]'; Gamma_D = [ Gamma_P(2:end,:)' Gamma_P(end,:)' ]'; % % % set up interface conductivity matrices % -------------------------------------- Gamma_e = 1./ ( (1 - f_e)./Gamma_P + f_e./Gamma_E ); Gamma_w = 1./ ( (1 - f_w)./Gamma_P + f_w./Gamma_W ); Gamma_u = 1./ ( (1 - f_u)./Gamma_P + f_u./Gamma_U ); Gamma_d = 1./ ( (1 - f_d)./Gamma_P + f_d./Gamma_D ); % % % advection %%%%%%%%%%%%%%%%% % set up uniform velocity for 1-D u_0 = 0; % m s^-1 w_0 = 2; % m s^-1 % u_velo = repmat( u_0, size(X_P) ); w_velo = repmat( w_0, size(X_P) ); % % set up velocities at interfaces %% (this is quick and dirty because velocity is uniform) %% In a real problem, you would call a subroutine that %% provided u velocities on the east-west interfaces, %% and w velocities on the Up-Down interfaces % ------------------------------------------------------ u_e = u_velo; u_w = u_velo; w_u = w_velo; w_d = w_velo; % % set up Flow and Diffusion coefficients % --------------------------------------- D_e = (Gamma_e ./ dX_e).* dZ; D_w = (Gamma_w ./ dX_w).* dZ; D_u = (Gamma_u ./ dZ_u).* dX; D_d = (Gamma_d ./ dZ_d).* dX; % F_e = ( rho.* u_e ).* dZ; F_w = ( rho.* u_w ).* dZ; F_u = ( rho.* w_u ).* dX; F_d = ( rho.* w_d ).* dX; % % set up Peclet numbers % ---------------------- P_e = F_e./ D_e; P_w = F_w./ D_w; P_u = F_u./ D_u; P_d = F_d./ D_d; % % set up coefficients at adjacent points % --------------------------------------- if(upwind == 0 ) a_E = ( Gamma_e ./ dX_e - rho.* u_e/2 ).* dZ; a_W = ( Gamma_w ./ dX_w + rho.* u_w/2 ).* dZ; a_U = ( Gamma_u ./ dZ_u + rho.* w_u/2 ).* dX; a_D = ( Gamma_d ./ dZ_d - rho.* w_d/2 ).* dX; % else % a_E = D_e .* A( P_e ) + F_upwind( -F_e ); a_W = D_w .* A( P_w ) + F_upwind( F_w ); a_U = D_u .* A( P_u ) + F_upwind( F_u ); a_D = D_d .* A( P_d ) + F_upwind( -F_d ); % end % set up coefficient at central point P (incl source dependent on phi) % -------------------------------------------------------------------- a_P = a_E + a_W + a_U + a_D - S_P.* dX.* dZ; % % % set Boundary Conditions %%%%%%%%%%%%%%%%%%%%%%%%%%% % phi_u = bc_u; phi_d = bc_d; dphi_dx_e = bc_e; dphi_dx_w = bc_w; % specified gradient boundaries % ------------------------------ % East boundary (dphi/dx = dphi_dx_e) % use dphi/dx = (phi_E - phi_P)/dx % i.e. phi_E = phi_P + dx * dphi_dx_e a_P(:,end) = a_P(:,end) - a_E(:,end); b(:,end) = b(:,end) + a_E(:,end).* dX_e(:,end).* dphi_dx_e; a_E(:,end) = 0; % West boundary (dphi/dx = dphi_dx_w) % use dphi/dx = (phi_P - phi_W)/dx % i.e. phi_W = phi_P - dx * dphi_dx_w a_P(:,1) = a_P(:,1) - a_W(:,1); b(:,1) = b(:,1) - a_W(:,1).* dX_w(:,1).* dphi_dx_w ; a_W(:,1) = 0; % % % specified phi = phi_u on upper boundary % ------------------------------------------- a_P(1,:) = 1; b(1,:) = phi_u; a_U(1,:) = 0; a_D(1,:) = 0; a_E(1,:) = 0; a_W(1,:) = 0; % % specified phi = phi_d on lower boundary % ------------------------------------------- a_P(end,:) = 1; b(end,:) = phi_d; a_D(end,:) = 0; a_U(end,:) = 0; a_E(end,:) = 0; a_W(end,:) = 0; % %%%%%%%%%%%%%% % % Now call matrix solver %%%%%%%%%%%%%%%%%%%%%%%%%%%% phi = solver( a_E, a_W, a_U, a_D, a_P, b ); % % %%Peclet = ( rho(1,1) * w(1,1) * dz_u(1,1) ) / Gamma_P(1,1) Peclet = P_u(1,1); % %