function phi = fvm_soln_SS_bdry_nodes( X_edges, Z_edges, X_P, Z_P, K_P, ...
                             S_C, S_P, phi_u, q_d, q_e, q_w )
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%  find steady-state phi(x,z), given heat sources S and conductivity K_P.
%%  Uses Patankar Control Volume method.
%%
%%  Boundary Conditions:
%%  vector phi_u is fixed value of phi on upper boundary
%%  vector q_w   is fixed flux on west boundary
%%  vector q_e   is fixed flux on east boundary
%%  vector q_d   is fixed flux on down boundary
%%
%% My treatment of Boundary Conditions differs from Patankar
%%  I impose all boundary conditions on edges of regular control volumes
%%  This means that I don't have to use half-volumes.
%%  On the other hand, the boundary values of phi do not appear 
%%  as an explicit part of my solution 
%%  but (they can be easily recovered later)
%%
%%  THIS CODE USES PATANKAR HALF-VOLUMES
%%
%%  a_P = coefficient of phi_P at point P = (i,j)
%%  a_E = coefficient of phi_E at point east of (i,j)
%%  a_W, a_U, a_D for points 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
%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%
% get Finite-Volume dimensions
% ------------------------------
%  NOTE: if using variable-size volumes, I need to be more careful here!
%  I could carry matrices containing 
%   dX_P, dX_E, dX_W, dx_e, dx_w, 
%   dZ_P, dZ_U, dZ_D, dz_u, dz_d, etc
  %%    [nz,nx] = size( X_P );
    %%   dx = X_edges(1,2) - X_edges(1,1);  
    %%   dz = Z_edges(2,1) - Z_edges(1,1);
  %%     dx = X_P(1,2) - X_P(1,1);  
  %%     dz = Z_P(2,1) - Z_P(1,1);
%

%  get dX, dZ - spacings between volume edges
%  -------------------------------------------
       dX = diff(X_edges')';
       dZ = diff(Z_edges);
%

%  get dX_E, dx_W, dZ_U, dZ_D - 
%          - distances to adjacent volume centers
%  -----------------------------------------------
       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 ];
%
       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 = ones(size(X_P)) - (X_edges(:,2:end) - X_P)./ dX_e;
%
       f_w = ones(size(X_P)) - (X_P - X_edges(:,1:(end-1)) )./ dX_w;
%
       f_u = ones(size(Z_P)) - (Z_P - Z_edges(1:(end-1),: ))./ dZ_u;
%
       f_d = ones(size(Z_P)) - (Z_edges(2:end,: ) - Z_P)./ dZ_d;
%



% 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
% ------------------------------------------------------
    K_E   =  [ K_P(:,2:end) K_P(:, end) ];
    K_W   =  [ K_P(:,1) K_P(:,1:end-1) ];
    K_U   =  [ K_P(1,:)' K_P(1:end-1,:)' ]';
    K_D   =  [ K_P(2:end,:)' K_P(end,:)' ]';
%
%
% set up interface conductivity matrices
%   (These expressions need to be modified when dx and dz
%    are not uniform)
% --------------------------------------
 %%   K_e =  2 * ( K_P .* K_E ) ./( K_P + K_E );
 %%   K_w =  2 * ( K_P .* K_W ) ./( K_P + K_W );
 %%   K_u =  2 * ( K_P .* K_U ) ./( K_P + K_U );
 %%   K_d =  2 * ( K_P .* K_D ) ./( K_P + K_D );
%
    K_e =  1./ ( (1 - f_e)./K_P + f_e./K_E );
    K_w =  1./ ( (1 - f_w)./K_P + f_w./K_W );
    K_u =  1./ ( (1 - f_u)./K_P + f_u./K_U );
    K_d =  1./ ( (1 - f_d)./K_P + f_d./K_D );
%
%
% set up coefficients at adjacent points
% ---------------------------------------
    a_E = (K_e ./ dX_e).* dZ;
    a_W = (K_w ./ dX_w).* dZ;
    a_U = (K_u ./ dZ_u).* dX;
    a_D = (K_d ./ dZ_d).* dX;

         
% 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
%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Specified phi
%  -------------
%   Boundary type #1 - boundaries on faces of regular finite volumes
%                      x_B = (x_U + x_P)/2
%                      -------------------
%    To eliminate phi_U from the equations
%           use   phi_u = (phi_U + phi_P)/2, 
%           i.e.  phi_U = 2 phi_u - phi_P
%    set a_U = 0 and move phi_U contribution onto b and a_P
%%  ** NOTE THAT this formulation assumes that Z_u is 
%%     at midpoint between Z_P and Z_U ** 
   %%      a_P(1,:) = a_P(1,:) + a_U(1,:); 
   %%      b(1,:) = b(1,:) + 2*phi_u .* a_U(1,:);
   %%      a_U(1,:) = 0;           % to make P independent of volume
                                   % at bottom of previous column
%
%   Boundary type #2 - boundaries are at solution points X_P (Patankar)
%    Set boundary point coefficient to unity, b to specified value
%    zero out coefficients on neighboring points
%
%
%  Specified phi gradient
%  ----------------------
%
%


%  specified flux boundaries
%  ---------------------------
%  
%   Boundary type #1 - Ed's design
%        boundaries on faces of regular finite volumes
%          e.g. on East boundary  x_B = (x_E + x_P)/2
%   ----------------------------------------------------
%     use  q_e = - K_e * (T_E - T_P)/dD_e   (flux toward E) 
%     i.e.  T_E = T_P - dx * (q_e/K_e) to eliminate T_E
     %%    a_P(:,end) = a_P(:,end) - a_E(:,end); 
%
     %%    b(:,end) = b(:,end) - dx * (q_e./K_e(:,end)) .* a_E(:,end);
     %%    a_E(:,end) = 0;
%
%   Boundary type #2 - recommended by Patankar (p. 50) 
%        boundaries are at solution points X_B = X_P
%   ------------------------------------------------
%
%
%
%   Upper boundary - specified phi = phi_u 
%   ========================================
         a_P(1,:) = 1; 
         b(1,:) = phi_u;
         a_U(1,:) = 0; 
         a_E(1,:) = 0;
         a_W(1,:) = 0;
         a_D(1,:) = 0;
%
%

%   East boundary - outward flux  (x is positive outward)
%   =====================================================
   %  remove a_E from a_P
         a_P(:,end) = a_P(:,end) - a_E(:,end); 
%
   %  include specified boundary flux q_e in b
%         Boundary type #1 - boundaries on faces of regular finite volumes
     %%        b(:,end) = b(:,end) - dx * (q_e./K_e(:,end)) .* a_E(:,end);
%         Boundary type #2 - recommended by Patankar (p. 50) 
             b(:,end) = b(:,end) - q_e.* dZ(:,end);
%
   %  eliminate fictitious East point (outside domain)
         a_E(:,end) = 0;
%

%   West boundary - zero inward flux (x is positive inward)
%   =======================================================
   %  remove a_W from a_P
         a_P(:,1) = a_P(:,1) - a_W(:,1); 
%
   %  include specified boundary flux q_w in b
%         Boundary type #1 - boundaries on faces of regular finite volumes
    %%         b(:,1) = b(:,1) + dx * (q_w./K_w(:,1)) .* a_W(:,1);
%         Boundary type #2 - boundaries are at solution points X_P (Patankar)
             b(:,end) = b(:,end) + q_w.* dZ(:,end);
%
   %  eliminate fictitious West point (outside domain)
         a_W(:,1) = 0;
%


%   Bottom - geothermal flux
%   ========================  
   %  remove a_D from a_P
         a_P(end,:) = a_P(end,:) - a_D(end,:);
%
   %  include specified boundary flux q_d in b
%         Boundary type #1 - boundaries on faces of regular finite volumes
    %%         b(end,:) = b(end,:) - dz * (q_d./K_d(end,:)) .* a_D(end,:);
%         Boundary type #2 - boundaries are at solution points X_P (Patankar)
             b(end,:) = b(end,:) - q_d.* dX(end,:);
%
   %  eliminate fictitious Down point (outside domain)
         a_D(end,:) = 0;
%

%
%    Now call implicit solver
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        phi = solver( a_E, a_W, a_U, a_D, a_P, b );
%
%
%
%
