diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..7182571 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7cc7bc1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +**/.idea diff --git a/MATLAB/Constants/B.m b/MATLAB/Constants/B.m deleted file mode 100644 index 97846aa..0000000 --- a/MATLAB/Constants/B.m +++ /dev/null @@ -1,4 +0,0 @@ -function [ v ] = B( ) -% constant in global notation -v = 5; -end diff --git a/MATLAB/Constants/C.m b/MATLAB/Constants/C.m deleted file mode 100644 index 5f983fe..0000000 --- a/MATLAB/Constants/C.m +++ /dev/null @@ -1,5 +0,0 @@ -function [ v ] = C( ) -% constant in global notation -v = 0; -end - diff --git a/MATLAB/Constants/E.m b/MATLAB/Constants/E.m deleted file mode 100644 index f208d5d..0000000 --- a/MATLAB/Constants/E.m +++ /dev/null @@ -1,5 +0,0 @@ -function [ v ] = E( ) -% constant in global notation -v = 2; -end - diff --git a/MATLAB/Constants/G.m b/MATLAB/Constants/G.m deleted file mode 100644 index 18f80a4..0000000 --- a/MATLAB/Constants/G.m +++ /dev/null @@ -1,5 +0,0 @@ -function [ v ] = G( ) -% gravitational constant -v = 9.81; -end - diff --git a/MATLAB/Constants/HUGE.m b/MATLAB/Constants/HUGE.m deleted file mode 100644 index 82038b5..0000000 --- a/MATLAB/Constants/HUGE.m +++ /dev/null @@ -1,5 +0,0 @@ -function [ v ] = HUGE( ) -% global constant -v = 1e+12; -end - diff --git a/MATLAB/Constants/N.m b/MATLAB/Constants/N.m deleted file mode 100644 index 1b90bb8..0000000 --- a/MATLAB/Constants/N.m +++ /dev/null @@ -1,5 +0,0 @@ -function [ v ] = N( ) -% constant in global notation -v = 4; -end - diff --git a/MATLAB/Constants/P.m b/MATLAB/Constants/P.m deleted file mode 100644 index 8fc0d5b..0000000 --- a/MATLAB/Constants/P.m +++ /dev/null @@ -1,4 +0,0 @@ -function [ v ] = P( ) -% constant in global notation -v = 7; -end \ No newline at end of file diff --git a/MATLAB/Constants/S.m b/MATLAB/Constants/S.m deleted file mode 100644 index 2037358..0000000 --- a/MATLAB/Constants/S.m +++ /dev/null @@ -1,5 +0,0 @@ -function [ v ] = S( ) -% constant in global notation -v = 3; -end - diff --git a/MATLAB/Constants/SOL.m b/MATLAB/Constants/SOL.m deleted file mode 100644 index d55fd70..0000000 --- a/MATLAB/Constants/SOL.m +++ /dev/null @@ -1,10 +0,0 @@ -%========================================================================== -function [s] = SOL( ) -%-------------------------------------------------------------------------- -% Function to specify the type of solver; 'i' or 'd' (iterative or direct). -%-------------------------------------------------------------------------- - -s = 'i'; % 'i' or 'd' - -end - diff --git a/MATLAB/Constants/T.m b/MATLAB/Constants/T.m deleted file mode 100644 index a662449..0000000 --- a/MATLAB/Constants/T.m +++ /dev/null @@ -1,4 +0,0 @@ -function [ v ] = T( ) -% constant in global notation -v = 6; -end \ No newline at end of file diff --git a/MATLAB/Constants/TINY.m b/MATLAB/Constants/TINY.m deleted file mode 100644 index cec5589..0000000 --- a/MATLAB/Constants/TINY.m +++ /dev/null @@ -1,5 +0,0 @@ -function [ v ] = TINY( ) -% global constant -v = 1e-12; -end - diff --git a/MATLAB/Constants/TOL.m b/MATLAB/Constants/TOL.m deleted file mode 100644 index 7008994..0000000 --- a/MATLAB/Constants/TOL.m +++ /dev/null @@ -1,12 +0,0 @@ -%========================================================================== -function [ t ] = TOL( ) -%-------------------------------------------------------------------------- -% This functions sets solver tolerances. -% -% It seems that results are too sensitive above 1E-4 -%-------------------------------------------------------------------------- - -t = 1E-8; - -end - diff --git a/MATLAB/Constants/W.m b/MATLAB/Constants/W.m deleted file mode 100644 index 6182aca..0000000 --- a/MATLAB/Constants/W.m +++ /dev/null @@ -1,5 +0,0 @@ -function [ v ] = W( ) -% constant in global notation -v = 1; -end - diff --git a/MATLAB/Constants/X.m b/MATLAB/Constants/X.m deleted file mode 100644 index 1710843..0000000 --- a/MATLAB/Constants/X.m +++ /dev/null @@ -1,5 +0,0 @@ -function [ v ] = X( ) -% constant in global notation -v = 1; -end - diff --git a/MATLAB/Constants/Y.m b/MATLAB/Constants/Y.m deleted file mode 100644 index ddd6e41..0000000 --- a/MATLAB/Constants/Y.m +++ /dev/null @@ -1,5 +0,0 @@ -function [ v ] = Y( ) -% constant in global notation -v = 2; -end - diff --git a/MATLAB/Constants/Z.m b/MATLAB/Constants/Z.m deleted file mode 100644 index d647a7e..0000000 --- a/MATLAB/Constants/Z.m +++ /dev/null @@ -1,5 +0,0 @@ -function [ v ] = Z( ) -% constant in global notation -v = 3; -end - diff --git a/MATLAB/Discretization/adj_n_bnds.m b/MATLAB/Discretization/adj_n_bnds.m deleted file mode 100644 index 2ee1dcd..0000000 --- a/MATLAB/Discretization/adj_n_bnds.m +++ /dev/null @@ -1,33 +0,0 @@ -%========================================================================== -function phi = adj_n_bnds(phi) -%-------------------------------------------------------------------------- -% Copies last domain cell values to Neumann boundary condition values. -%-------------------------------------------------------------------------- - -% These arrays will hold values true (1) in cells with boundary ... -% ... condition of Neumann type, and false (0) otherwise -if_w_n = ( phi.bnd(W).type(1,:,:) == 'n' ); % 1 if west is Neumann type -if_e_n = ( phi.bnd(E).type(1,:,:) == 'n' ); % 1 if east is Neumann type -if_s_n = ( phi.bnd(S).type(:,1,:) == 'n' ); % 1 if south is Neumann type -if_n_n = ( phi.bnd(N).type(:,1,:) == 'n' ); % 1 if north is Neumann type -if_b_n = ( phi.bnd(B).type(:,:,1) == 'n' ); % 1 if bottom is Neumann type -if_t_n = ( phi.bnd(T).type(:,:,1) == 'n' ); % 1 if top is Neumann type - -% In what follows, a linear combination of true (1) and false (0) -% will copy the values of variable phi to the boundaries. -phi.bnd(W).val(1,:,:) = phi.bnd(W).val(1,:,:) .* ( not(if_w_n) ) + ... - phi.val(1,:,:) .* if_w_n; -phi.bnd(E).val(1,:,:) = phi.bnd(E).val(1,:,:) .* ( not(if_e_n) ) + ... - phi.val(end,:,:) .* if_e_n; - -phi.bnd(S).val(:,1,:) = phi.bnd(S).val(:,1,:) .* ( not(if_s_n) ) + ... - phi.val(:,1,:) .* if_s_n; -phi.bnd(N).val(:,1,:) = phi.bnd(N).val(:,1,:) .* ( not(if_n_n) ) + ... - phi.val(:,end,:) .* if_n_n; - -phi.bnd(B).val(:,:,1) = phi.bnd(B).val(:,:,1) .* ( not(if_b_n) ) + ... - phi.val(:,:,1) .* if_b_n; -phi.bnd(T).val(:,:,1) = phi.bnd(T).val(:,:,1) .* ( not(if_t_n) ) + ... - phi.val(:,:,end) .* if_t_n; - -end \ No newline at end of file diff --git a/MATLAB/Discretization/adj_o_bnds.m b/MATLAB/Discretization/adj_o_bnds.m deleted file mode 100644 index 0947706..0000000 --- a/MATLAB/Discretization/adj_o_bnds.m +++ /dev/null @@ -1,277 +0,0 @@ -%========================================================================== -function [u, v, w] = adj_o_bnds(u, v, w, dx, dy, dz, dt) -%-------------------------------------------------------------------------- -% Computes values at the outlet boundary using the convective outlet. -%-------------------------------------------------------------------------- - -% Local variables used in this function -area_in = 0.0; % area of the inlet -area_out = 0.0; % area of the outlet -vol_in = 0.0; % inlet volume flux; positive for inflow -vol_out_1 = 0.0; % outlet volume flux; positive for outflow -vol_out_2 = 0.0; % outlet volume flux; positive for outflow - -verbatim = false; - -sx = dy .* dz; -sy = dx .* dz; -sz = dx .* dy; - -sx = sx(1,:,:); -sy = sy(:,1,:); -sz = sz(:,:,1); - -%------------------------------------------------------------------ -% Compute the volume flowing in (v_in), volume flowing out (v_out) -% as well as inlet and outlet areas (a_in, a_out) -%------------------------------------------------------------------ - -% Inlets: these arrays will hold values true (1) in cells ... -% with inlet boundary conditions, and false (0) otherwise -if_w_in = ( u.bnd(W).type(1,:,:) == 'd' & u.bnd(W).val(1,:,:) > +TINY ); -if_e_in = ( u.bnd(E).type(1,:,:) == 'd' & u.bnd(E).val(1,:,:) < -TINY ); -if_s_in = ( v.bnd(S).type(:,1,:) == 'd' & v.bnd(S).val(:,1,:) > +TINY ); -if_n_in = ( v.bnd(N).type(:,1,:) == 'd' & v.bnd(N).val(:,1,:) < -TINY ); -if_b_in = ( w.bnd(B).type(:,:,1) == 'd' & w.bnd(B).val(:,:,1) > +TINY ); -if_t_in = ( w.bnd(T).type(:,:,1) == 'd' & w.bnd(T).val(:,:,1) < -TINY ); - -% Using the arrays defined above, compute inlet surface area -area_in = area_in + sum( sum( if_w_in .* sx ) ); -area_in = area_in + sum( sum( if_e_in .* sx ) ); -area_in = area_in + sum( sum( if_s_in .* sy ) ); -area_in = area_in + sum( sum( if_n_in .* sy ) ); -area_in = area_in + sum( sum( if_b_in .* sz ) ); -area_in = area_in + sum( sum( if_t_in .* sz ) ); - -% If there is no inlet, nothing to do here any longer -if area_in < TINY - return; -end - -% Using the arrays defined above, compute inlet volume flux -vol_in = vol_in + sum(sum(if_w_in .* u.bnd(W).val(1,:,:) .* sx)); -vol_in = vol_in - sum(sum(if_e_in .* u.bnd(E).val(1,:,:) .* sx)); -vol_in = vol_in + sum(sum(if_s_in .* v.bnd(S).val(:,1,:) .* sy)); -vol_in = vol_in - sum(sum(if_n_in .* v.bnd(N).val(:,1,:) .* sy)); -vol_in = vol_in + sum(sum(if_b_in .* w.bnd(B).val(:,:,1) .* sz)); -vol_in = vol_in - sum(sum(if_t_in .* w.bnd(T).val(:,:,1) .* sz)); - -% Outlets: these arrays will hold values true (1) in cells ... -% with outlet boundary conditions, and false (0) otherwise -if_w_out_x = ( u.bnd(W).type(1,:,:) == 'o' ); -if_e_out_x = ( u.bnd(E).type(1,:,:) == 'o' ); -if_s_out_y = ( v.bnd(S).type(:,1,:) == 'o' ); -if_n_out_y = ( v.bnd(N).type(:,1,:) == 'o' ); -if_b_out_z = ( w.bnd(B).type(:,:,1) == 'o' ); -if_t_out_z = ( w.bnd(T).type(:,:,1) == 'o' ); -if_w_out_y = avg(v.pos, if_w_out_x) > 0.5; -if_w_out_z = avg(w.pos, if_w_out_x) > 0.5; -if_e_out_y = avg(v.pos, if_e_out_x) > 0.5; -if_e_out_z = avg(w.pos, if_e_out_x) > 0.5; -if_s_out_x = avg(u.pos, if_s_out_y) > 0.5; -if_s_out_z = avg(w.pos, if_s_out_y) > 0.5; -if_n_out_x = avg(u.pos, if_n_out_y) > 0.5; -if_n_out_z = avg(w.pos, if_n_out_y) > 0.5; -if_b_out_x = avg(u.pos, if_b_out_z) > 0.5; -if_b_out_y = avg(v.pos, if_b_out_z) > 0.5; -if_t_out_x = avg(u.pos, if_t_out_z) > 0.5; -if_t_out_y = avg(v.pos, if_t_out_z) > 0.5; - -% Using the arrays defined above, compute outlet surface area -area_out = area_out + sum( sum( if_w_out_x .* sx ) ); -area_out = area_out + sum( sum( if_e_out_x .* sx ) ); -area_out = area_out + sum( sum( if_s_out_y .* sy ) ); -area_out = area_out + sum( sum( if_n_out_y .* sy ) ); -area_out = area_out + sum( sum( if_b_out_z .* sz ) ); -area_out = area_out + sum( sum( if_t_out_z .* sz ) ); - -% Using the arrays defined above, compute outlet volume flux -vol_out_1 = vol_out_1 - sum(sum(if_w_out_x .* u.bnd(W).val(1,:,:) .* sx)); -vol_out_1 = vol_out_1 + sum(sum(if_e_out_x .* u.bnd(E).val(1,:,:) .* sx)); -vol_out_1 = vol_out_1 - sum(sum(if_s_out_y .* v.bnd(S).val(:,1,:) .* sy)); -vol_out_1 = vol_out_1 + sum(sum(if_n_out_y .* v.bnd(N).val(:,1,:) .* sy)); -vol_out_1 = vol_out_1 - sum(sum(if_b_out_z .* w.bnd(B).val(:,:,1) .* sz)); -vol_out_1 = vol_out_1 + sum(sum(if_t_out_z .* w.bnd(T).val(:,:,1) .* sz)); - -%--------------------------------- -% Check and calculate corrections -%--------------------------------- - -if (area_in == 0) - ub_in = 0; -else - ub_in = vol_in / area_in; -end - -if (area_out == 0) - ub_out = 0; -else - ub_out = vol_out_1 / area_out; -end - -%-------------------------------------------------- -% Bulk correction makes sense if nothing comes out -%-------------------------------------------------- -if(ub_out < TINY) - u_bulk_corr = ub_in * area_in / area_out; - - u.bnd(W).val(1,:,:) = u.bnd(W).val(1,:,:) .* not(if_w_out_x) ... - - u_bulk_corr .* if_w_out_x; - u.bnd(E).val(1,:,:) = u.bnd(E).val(1,:,:) .* not(if_e_out_x) ... - + u_bulk_corr .* if_e_out_x; - v.bnd(S).val(:,1,:) = v.bnd(S).val(:,1,:) .* not(if_s_out_y) ... - - u_bulk_corr .* if_s_out_y; - v.bnd(N).val(:,1,:) = v.bnd(N).val(:,1,:) .* not(if_n_out_y) ... - + u_bulk_corr .* if_n_out_y; - w.bnd(B).val(:,:,1) = w.bnd(B).val(:,:,1) .* not(if_b_out_z) ... - - u_bulk_corr .* if_b_out_z; - w.bnd(T).val(:,:,1) = w.bnd(T).val(:,:,1) .* not(if_t_out_z) ... - + u_bulk_corr .* if_t_out_z; - -%-------------------------------------------------------------- -% Correction outflow by applying convective boundary condition -%-------------------------------------------------------------- -else - du_dx_w = (u.val( 1,:,:) - u.bnd(W).val(1,:,:)) ./ dx( 1,:,:); - dv_dx_w = (v.val( 1,:,:) - v.bnd(W).val(1,:,:)) ./ avg(v.pos, dx( 1,:,:)); - dw_dx_w = (w.val( 1,:,:) - w.bnd(W).val(1,:,:)) ./ avg(w.pos, dx( 1,:,:)); - - du_dx_e = (u.val(end,:,:) - u.bnd(E).val(1,:,:)) ./ dx(end,:,:); - dv_dx_e = (v.val(end,:,:) - v.bnd(E).val(1,:,:)) ./ avg(v.pos, dx(end,:,:)); - dw_dx_e = (w.val(end,:,:) - w.bnd(E).val(1,:,:)) ./ avg(w.pos, dx(end,:,:)); - - du_dy_s = (u.val(:, 1,:) - u.bnd(S).val(:,1,:)) ./ avg(u.pos, dy(:, 1,:)); - dv_dy_s = (v.val(:, 1,:) - v.bnd(S).val(:,1,:)) ./ dy(:, 1,:); - dw_dy_s = (w.val(:, 1,:) - w.bnd(S).val(:,1,:)) ./ avg(w.pos, dy(:, 1,:)); - - du_dy_n = (u.val(:,end,:) - u.bnd(N).val(:,1,:)) ./ avg(u.pos, dy(:,end,:)); - dv_dy_n = (v.val(:,end,:) - v.bnd(N).val(:,1,:)) ./ dy(:,end,:); - dw_dy_n = (w.val(:,end,:) - w.bnd(N).val(:,1,:)) ./ avg(w.pos, dy(:,end,:)); - - du_dz_b = (u.val(:,:, 1) - u.bnd(B).val(:,:,1)) ./ avg(u.pos, dz(:,:, 1)); - dv_dz_b = (v.val(:,:, 1) - v.bnd(B).val(:,:,1)) ./ avg(v.pos, dz(:,:, 1)); - dw_dz_b = (w.val(:,:, 1) - w.bnd(B).val(:,:,1)) ./ dz(:,:, 1); - - du_dz_t = (u.val(:,:,end) - u.bnd(T).val(:,:,1)) ./ avg(u.pos, dz(:,:,end)); - dv_dz_t = (v.val(:,:,end) - v.bnd(T).val(:,:,1)) ./ avg(v.pos, dz(:,:,end)); - dw_dz_t = (w.val(:,:,end) - w.bnd(T).val(:,:,1)) ./ dz(:,:,end); - - u_bnd_w_corr = (u.bnd(W).val(1,:,:) + ub_out * dt * du_dx_w); - v_bnd_w_corr = (v.bnd(W).val(1,:,:) + ub_out * dt * dv_dx_w); - w_bnd_w_corr = (w.bnd(W).val(1,:,:) + ub_out * dt * dw_dx_w); - - u.bnd(W).val(1,:,:) = u.bnd(W).val(1,:,:) .* not(if_w_out_x) ... - + u_bnd_w_corr .* if_w_out_x; - v.bnd(W).val(1,:,:) = v.bnd(W).val(1,:,:) .* not(if_w_out_y) ... - + v_bnd_w_corr .* if_w_out_y; - w.bnd(W).val(1,:,:) = w.bnd(W).val(1,:,:) .* not(if_w_out_z) ... - + w_bnd_w_corr .* if_w_out_z; - - u_bnd_e_corr = (u.bnd(E).val(1,:,:) + ub_out * dt * du_dx_e); - v_bnd_e_corr = (v.bnd(E).val(1,:,:) + ub_out * dt * dv_dx_e); - w_bnd_e_corr = (w.bnd(E).val(1,:,:) + ub_out * dt * dw_dx_e); - - u.bnd(E).val(1,:,:) = u.bnd(E).val(1,:,:) .* not(if_e_out_x) ... - + u_bnd_e_corr .* if_e_out_x; - v.bnd(E).val(1,:,:) = v.bnd(E).val(1,:,:) .* not(if_e_out_y) ... - + v_bnd_e_corr .* if_e_out_y; - w.bnd(E).val(1,:,:) = w.bnd(E).val(1,:,:) .* not(if_e_out_z) ... - + w_bnd_e_corr .* if_e_out_z; - - u_bnd_s_corr = (u.bnd(S).val(:,1,:) + ub_out * dt * du_dy_s); - v_bnd_s_corr = (v.bnd(S).val(:,1,:) + ub_out * dt * dv_dy_s); - w_bnd_s_corr = (w.bnd(S).val(:,1,:) + ub_out * dt * dw_dy_s); - - u.bnd(S).val(:,1,:) = u.bnd(S).val(:,1,:) .* not(if_s_out_x) ... - + u_bnd_s_corr .* if_s_out_x; - v.bnd(S).val(:,1,:) = v.bnd(S).val(:,1,:) .* not(if_s_out_y) ... - + v_bnd_s_corr .* if_s_out_y; - w.bnd(S).val(:,1,:) = w.bnd(S).val(:,1,:) .* not(if_s_out_z) ... - + w_bnd_s_corr .* if_s_out_z; - - u_bnd_n_corr = (u.bnd(N).val(:,1,:) + ub_out * dt * du_dy_n); - v_bnd_n_corr = (v.bnd(N).val(:,1,:) + ub_out * dt * dv_dy_n); - w_bnd_n_corr = (w.bnd(N).val(:,1,:) + ub_out * dt * dw_dy_n); - - u.bnd(N).val(:,1,:) = u.bnd(N).val(:,1,:) .* not(if_n_out_x) ... - + u_bnd_n_corr .* if_n_out_x; - v.bnd(N).val(:,1,:) = v.bnd(N).val(:,1,:) .* not(if_n_out_y) ... - + v_bnd_n_corr .* if_n_out_y; - w.bnd(N).val(:,1,:) = w.bnd(N).val(:,1,:) .* not(if_n_out_z) ... - + w_bnd_n_corr .* if_n_out_z; - - u_bnd_b_corr = (u.bnd(B).val(:,:,1) + ub_out * dt * du_dz_b); - v_bnd_b_corr = (v.bnd(B).val(:,:,1) + ub_out * dt * dv_dz_b); - w_bnd_b_corr = (w.bnd(B).val(:,:,1) + ub_out * dt * dw_dz_b); - - u.bnd(B).val(:,:,1) = u.bnd(B).val(:,:,1) .* not(if_b_out_x) ... - + u_bnd_b_corr .* if_b_out_x; - v.bnd(B).val(:,:,1) = v.bnd(B).val(:,:,1) .* not(if_b_out_y) ... - + v_bnd_b_corr .* if_b_out_y; - w.bnd(B).val(:,:,1) = w.bnd(B).val(:,:,1) .* not(if_b_out_z) ... - + w_bnd_b_corr .* if_b_out_z; - - u_bnd_t_corr = (u.bnd(T).val(:,:,1) + ub_out *dt * du_dz_t); - v_bnd_t_corr = (v.bnd(T).val(:,:,1) + ub_out *dt * dv_dz_t); - w_bnd_t_corr = (w.bnd(T).val(:,:,1) + ub_out *dt * dw_dz_t); - - u.bnd(T).val(:,:,1) = u.bnd(T).val(:,:,1) .* not(if_t_out_x) ... - + u_bnd_t_corr .* if_t_out_x; - v.bnd(T).val(:,:,1) = v.bnd(T).val(:,:,1) .* not(if_t_out_y) ... - + v_bnd_t_corr .* if_t_out_y; - w.bnd(T).val(:,:,1) = w.bnd(T).val(:,:,1) .* not(if_t_out_z) ... - + w_bnd_t_corr .* if_t_out_z; -end - -if verbatim == true - disp( sprintf('+----------------------------+') ); - disp( sprintf('| ub_in = %12.5e |', ub_in ) ); - disp( sprintf('| a_in = %12.5e |', area_in ) ); - disp( sprintf('| v_in = %12.5e |', vol_in ) ); - disp( sprintf('| ub_out = %12.5e |', ub_out ) ); - disp( sprintf('| a_out = %12.5e |', area_out ) ); - disp( sprintf('| v_out_1 = %12.5e |', vol_out_1 ) ); -end - -%---------------------------------------------- -% Scaling correction to whatever you did above -% (bulk correction or convective outflow) -%---------------------------------------------- -vol_out_2 = 0.0; -vol_out_2 = vol_out_2 - sum(sum(if_w_out_x .* u.bnd(W).val(1,:,:) .* sx)); -vol_out_2 = vol_out_2 + sum(sum(if_e_out_x .* u.bnd(E).val(1,:,:) .* sx)); -vol_out_2 = vol_out_2 - sum(sum(if_s_out_y .* v.bnd(S).val(:,1,:) .* sy)); -vol_out_2 = vol_out_2 + sum(sum(if_n_out_y .* v.bnd(N).val(:,1,:) .* sy)); -vol_out_2 = vol_out_2 - sum(sum(if_b_out_z .* w.bnd(B).val(:,:,1) .* sz)); -vol_out_2 = vol_out_2 + sum(sum(if_t_out_z .* w.bnd(T).val(:,:,1) .* sz)); - -if(vol_out_2 > TINY) - factor = vol_in / vol_out_2; -else - factor = 1.0; -end - -if verbatim == true - disp( sprintf('+----------------------------+') ); - disp( sprintf('| v_out_2 = %12.5e |', vol_out_2 ) ); - disp( sprintf('| factor = %12.5e |', factor ) ); - disp( sprintf('+----------------------------+') ); -end - -%-------------------------------------- -% Correction to satisfy volume balance -%-------------------------------------- -u.bnd(W).val(1,:,:) = u.bnd(W).val(1,:,:) .* not(if_w_out_x) ... - + u.bnd(W).val(1,:,:) .* if_w_out_x * factor; -u.bnd(E).val(1,:,:) = u.bnd(E).val(1,:,:) .* not(if_e_out_x) ... - + u.bnd(E).val(1,:,:) .* if_e_out_x * factor; -v.bnd(S).val(:,1,:) = v.bnd(S).val(:,1,:) .* not(if_s_out_y) ... - + v.bnd(S).val(:,1,:) .* if_s_out_y * factor; -v.bnd(N).val(:,1,:) = v.bnd(N).val(:,1,:) .* not(if_n_out_y) ... - + v.bnd(N).val(:,1,:) .* if_n_out_y * factor; -w.bnd(B).val(:,:,1) = w.bnd(B).val(:,:,1) .* not(if_b_out_z) ... - + w.bnd(B).val(:,:,1) .* if_b_out_z * factor; -w.bnd(T).val(:,:,1) = w.bnd(T).val(:,:,1) .* not(if_t_out_z) ... - + w.bnd(T).val(:,:,1) .* if_t_out_z * factor; - -end \ No newline at end of file diff --git a/MATLAB/Discretization/advection.m b/MATLAB/Discretization/advection.m deleted file mode 100644 index 678b0a5..0000000 --- a/MATLAB/Discretization/advection.m +++ /dev/null @@ -1,269 +0,0 @@ -%========================================================================== -function [c] = advection(rho, phi, uf, vf, wf, dx, dy, dz, dt, lim_name) -%-------------------------------------------------------------------------- -% rho - advection coefficient -% phi - transported variable -% uf, vf, wf - staggered advection velocity components -% dx, dy, dz - cell size in x, y and z direction -% lim_name - limiter name -%-------------------------------------------------------------------------- - -[nx ny nz] = size(phi.val); - -pos = phi.pos; - -sx = dy .* dz; -sy = dx .* dz; -sz = dx .* dy; - -%------------------------------------------------- -% Specific for cell-centered transported variable -%------------------------------------------------- -if pos==C - - % Facial values of physical properties including boundary cells - rho_x_fac = cat(X, rho(1,:,:), avg(X, rho), rho(nx,:,:)); % nxp,ny, nz - rho_y_fac = cat(Y, rho(:,1,:), avg(Y, rho), rho(:,ny,:)); % nx, nyp,nz - rho_z_fac = cat(Z, rho(:,:,1), avg(Z, rho), rho(:,:,nz)); % nx, ny, nzp - - % Facial values of areas including boundary cells - a_x_fac = cat(X, sx(1,:,:), avg(X, sx), sx(nx,:,:)); - a_y_fac = cat(Y, sy(:,1,:), avg(Y, sy), sy(:,ny,:)); - a_z_fac = cat(Z, sz(:,:,1), avg(Z, sz), sz(:,:,nz)); - - del_x = avg(X, dx); - del_y = avg(Y, dy); - del_z = avg(Z, dz); - - % Facial values of velocities without boundary values - u_fac = uf.val; % nxm,ny, nz - v_fac = vf.val; % nx, nym,nz - w_fac = wf.val; % nx, ny, nzm - - % Boundary velocity values - u_bnd_W = uf.bnd(W).val; u_bnd_E = uf.bnd(E).val; - v_bnd_S = vf.bnd(S).val; v_bnd_N = vf.bnd(N).val; - w_bnd_B = wf.bnd(B).val; w_bnd_T = wf.bnd(T).val; -end - -%------------------------------------------------------------ -% Specific for transported variable staggered in x direction -%------------------------------------------------------------ -if pos==X - - % Facial values of physical properties including boundary cells - rho_x_fac = rho; % nx, ny, nz - rho_nod_y = avg(X, avg(Y, rho) ); % nxm,nym,nz - rho_y_fac = cat(Y, rho_nod_y(:, 1,:), ... % nxm,nyp,nz - rho_nod_y(:, :,:), ... - rho_nod_y(:,end,:)); - rho_nod_z = avg(X, avg(Z, rho) ); % nxm,ny,nzm - rho_z_fac = cat(Z, rho_nod_z(:,:, 1), ... % nxm,ny,nzp - rho_nod_z(:,:, :), ... - rho_nod_z(:,:,end)); - - % Facial values of areas including boundary cells - a_x_fac = sx; - a_y_fac = cat(Y, avg(X,sy(:,1,:)),avg(X, avg(Y, sy)),avg(X, sy(:,ny,:))); - a_z_fac = cat(Z, avg(X,sz(:,:,1)),avg(X, avg(Z, sz)),avg(X, sz(:,:,nz))); - - del_x = dx(2:end-1,:,:); - del_y = avg(X, avg(Y, dy)); - del_z = avg(X, avg(Z, dz)); - - % Facial values of velocities without boundary values - u_fac = avg(X, uf.val); % nxmm,ny, nz - v_fac = avg(X, vf.val); % nxm, nym,nz - w_fac = avg(X, wf.val); % nxm, ny, nzm - - % Boundary velocity values - u_bnd_W = uf.bnd(W).val; u_bnd_E = uf.bnd(E).val; - v_bnd_S = avg(X, vf.bnd(S).val); v_bnd_N = avg(X, vf.bnd(N).val); - w_bnd_B = avg(X, wf.bnd(B).val); w_bnd_T = avg(X, wf.bnd(T).val); -end - -%------------------------------------------------------------ -% Specific for transported variable staggered in y direction -%------------------------------------------------------------ -if pos==Y - - % Facial values of physical properties including boundary cells - rho_nod_x = avg(Y, avg(X, rho) ); % nxm,nym,nz - rho_x_fac = cat(X, rho_nod_x( 1,:,:), ... % nxp,nym,nz - rho_nod_x( :,:,:), ... - rho_nod_x(end,:,:)); - rho_y_fac = rho; % nx, ny, nz - rho_nod_z = avg(Y, avg(Z, rho) ); % nx, nym,nzm - rho_z_fac = cat(Z, rho_nod_z(:,:, 1), ... % nx, nym,nzp - rho_nod_z(:,:, :), ... - rho_nod_z(:,:,end)); - - % Facial values of areas including boundary cells - a_x_fac = cat(X, avg(Y, sx(1,:,:)),avg(Y, avg(X,sx)),avg(Y, sx(nx,:,:))); - a_y_fac = sy; - a_z_fac = cat(Z, avg(Y, sz(:,:,1)),avg(Y, avg(Z,sz)),avg(Y, sz(:,:,nz))); - - del_x = avg(Y, avg(X, dx)); - del_y = dy(:,2:end-1,:); - del_z = avg(Y, avg(Z, dz)); - - % Facial values of velocities without boundary values - u_fac = avg(Y, uf.val); % nxm,nym, nz - v_fac = avg(Y, vf.val); % nx, nymm,nz - w_fac = avg(Y, wf.val); % nx, nym, nzm - - % Facial values of velocities with boundary values - u_bnd_W = avg(Y, uf.bnd(W).val); u_bnd_E = avg(Y, uf.bnd(E).val); - v_bnd_S = vf.bnd(S).val; v_bnd_N = vf.bnd(N).val; - w_bnd_B = avg(Y, wf.bnd(B).val); w_bnd_T = avg(Y, wf.bnd(T).val); -end - -%------------------------------------------------------------ -% Specific for transported variable staggered in z direction -%------------------------------------------------------------ -if pos==Z - - % Facial values of physical properties including boundary cells - rho_nod_x = avg(Z, avg(X, rho) ); % nxm,ny, nzm - rho_x_fac = cat(X, rho_nod_x( 1,:,:), ... % nxp,ny, nzm - rho_nod_x( :,:,:), ... - rho_nod_x(end,:,:)); - rho_nod_y = avg(Z, avg(Y, rho) ); % nx, nym,nzm - rho_y_fac = cat(Y, rho_nod_y(:, 1,:), ... % nx, nyp,nzm - rho_nod_y(:, :,:), ... - rho_nod_y(:,end,:)); - rho_z_fac = rho; % nx, ny, nz - - % Facial values of areas including boundary cells - a_x_fac = cat(X, avg(Z, sx(1,:,:)),avg(Z, avg(X,sx)),avg(Z, sx(nx,:,:))); - a_y_fac = cat(Y, avg(Z, sy(:,1,:)),avg(Z, avg(Y,sy)),avg(Z, sy(:,ny,:))); - a_z_fac = sz; - - del_x = avg(Z, avg(X,dx)); - del_y = avg(Z, avg(Y,dy)); - del_z = dz(:,:,2:end-1); - - % Facial values of velocities without boundary values - u_fac = avg(Z, uf.val); % nxm,ny, nzm - v_fac = avg(Z, vf.val); % nx, nym, nzm - w_fac = avg(Z, wf.val); % nx, ny, nzmm - - % Facial values of velocities with boundary values - u_bnd_W = avg(Z, uf.bnd(W).val); u_bnd_E = avg(Z, uf.bnd(E).val); - v_bnd_S = avg(Z, vf.bnd(S).val); v_bnd_N = avg(Z, vf.bnd(N).val); - w_bnd_B = wf.bnd(B).val; w_bnd_T = wf.bnd(T).val; -end - -%------------------------------ -% Common part of the algorithm -%------------------------------ - -%------------------------------------------------------------ -% -% |-o-|-o-|-o-|-o-|-o-|-o-|-o-|-o-|-o-|-o-| -% 1 2 3 4 5 6 7 8 9 10 phi -% x---x---x---x---x---x---x---x---x -% 1 2 3 4 5 6 7 8 9 d_x initial -% 0---x---x---x---x---x---x---x---x---x---0 -% 1 2 3 4 5 6 7 8 9 10 11 d_x padded -% -%------------------------------------------------------------ - -% Compute consecutive differences (and avoid division by zero) -d_x = dif(X, phi.val); % nxm, ny, nz -d_x((d_x > -TINY) & (d_x <= 0.0)) = -TINY; -d_x((d_x >= 0.0) & (d_x < +TINY)) = +TINY; -d_x = cat(X, d_x(1,:,:), d_x, d_x(end,:,:)); - -d_y = dif(Y, phi.val); % nx, nym, nz -d_y((d_y > -TINY) & (d_y <= 0.0)) = -TINY; -d_y((d_y >= 0.0) & (d_y < +TINY)) = +TINY; -d_y = cat(Y, d_y(:,1,:), d_y, d_y(:,end,:)); - -d_z = dif(Z, phi.val); % nx, ny, nzm -d_z((d_z > -TINY) & (d_z < 0.0)) = -TINY; -d_z((d_z >= 0.0) & (d_z < +TINY)) = +TINY; -d_z = cat(Z, d_z(:,:,1), d_z, d_z(:,:,end)); - -% Ratio of consecutive gradients for positive and negative flow -r_x_we = d_x(2:end-1,:,:) ./ d_x(1:end-2,:,:); % nxm,ny, nz -r_x_ew = d_x(3:end, :,:) ./ d_x(2:end-1,:,:); % nxm,ny, nz - -r_y_sn = d_y(:,2:end-1,:) ./ d_y(:,1:end-2,:); % nx, nym,nz -r_y_ns = d_y(:,3:end, :) ./ d_y(:,2:end-1,:); % nx, nym,nz - -r_z_bt = d_z(:,:,2:end-1) ./ d_z(:,:,1:end-2); % nx, ny, nzm -r_z_tb = d_z(:,:,3:end ) ./ d_z(:,:,2:end-1); % nx, ny, nzm - -flow_we = u_fac >= 0; flow_ew = not(flow_we); -flow_sn = v_fac >= 0; flow_ns = not(flow_sn); -flow_bt = w_fac >= 0; flow_tb = not(flow_bt); - -r_x = r_x_we .* flow_we + r_x_ew .* flow_ew; -r_y = r_y_sn .* flow_sn + r_y_ns .* flow_ns; -r_z = r_z_bt .* flow_bt + r_z_tb .* flow_tb; - -% Apply a limiter -if( strcmp(lim_name, 'upwind') ) - psi_x = r_x * 0.0; % upwind - psi_y = r_y * 0.0; % upwind - psi_z = r_z * 0.0; % upwind -elseif( strcmp(lim_name, 'minmod') ) - psi_x = max (0.0, min(r_x, 1.0)); % minmod - psi_y = max (0.0, min(r_y, 1.0)); % minmod - psi_z = max (0.0, min(r_z, 1.0)); % minmod -elseif( strcmp(lim_name, 'superbee') ) - psi_x = max_of_3(0.0, min(2.0*r_x, 1.0), min(r_x, 2.0)); % superbee - psi_y = max_of_3(0.0, min(2.0*r_y, 1.0), min(r_y, 2.0)); % superbee - psi_z = max_of_3(0.0, min(2.0*r_z, 1.0), min(r_z, 2.0)); % superbee -elseif( strcmp(lim_name, 'smart') ) - psi_x = max(0.0, min_of_3(2.0*r_x, (0.25+0.75*r_x), 4.0)); % smart - psi_y = max(0.0, min_of_3(2.0*r_y, (0.25+0.75*r_y), 4.0)); % smart - psi_z = max(0.0, min_of_3(2.0*r_z, (0.25+0.75*r_z), 4.0)); % smart -elseif( strcmp(lim_name, 'koren') ) - psi_x = max(0.0, min_of_3(2.0*r_x, (2.0+r_x)/3.0, 2.0)); % koren - psi_y = max(0.0, min_of_3(2.0*r_y, (2.0+r_y)/3.0, 2.0)); % koren - psi_z = max(0.0, min_of_3(2.0*r_z, (2.0+r_z)/3.0, 2.0)); % koren -end - -flux_fac_lim_x = phi.val(1:end-1,:,:) .* u_fac .* flow_we ... - + phi.val(2:end, :,:) .* u_fac .* flow_ew ... - + 0.5 * abs(u_fac) .* (1 - abs(u_fac) * dt ./ del_x) ... - .* ( psi_x(:,:,:) .* d_x(1:nx-1,:,:) .* flow_we ... - + psi_x(:,:,:) .* d_x(2:nx, :,:) .* flow_ew ); - -flux_fac_lim_y = phi.val(:,1:end-1,:) .* v_fac .* flow_sn ... - + phi.val(:,2:end, :) .* v_fac .* flow_ns ... - + 0.5 * abs(v_fac) .* (1 - abs(v_fac) * dt ./ del_y) ... - .* ( psi_y(:,:,:) .* d_y(:,1:ny-1,:) .* flow_sn ... - + psi_y(:,:,:) .* d_y(:,2:ny, :) .* flow_ns ); - -flux_fac_lim_z = phi.val(:,:,1:end-1) .* w_fac .* flow_bt ... - + phi.val(:,:,2:end) .* w_fac .* flow_tb ... - + 0.5 * abs(w_fac) .* (1 - abs(w_fac) * dt ./ del_z) ... - .* ( psi_z(:,:,:) .* d_z(:,:,1:nz-1) .* flow_bt ... - + psi_z(:,:,:) .* d_z(:,:,2:nz) .* flow_tb ); - -% Pad with boundary values -flux_fac_lim_x = cat(X, phi.bnd(W).val .* u_bnd_W, ... - flux_fac_lim_x, ... - phi.bnd(E).val .* u_bnd_E); -flux_fac_lim_y = cat(Y, phi.bnd(S).val .* v_bnd_S, ... - flux_fac_lim_y, ... - phi.bnd(N).val .* v_bnd_N); -flux_fac_lim_z = cat(Z, phi.bnd(B).val .* w_bnd_B, ... - flux_fac_lim_z, ... - phi.bnd(T).val .* w_bnd_T); - -% Multiply with face areas -flux_fac_lim_x = rho_x_fac .* flux_fac_lim_x .* a_x_fac; -flux_fac_lim_y = rho_y_fac .* flux_fac_lim_y .* a_y_fac; -flux_fac_lim_z = rho_z_fac .* flux_fac_lim_z .* a_z_fac; - -% Sum contributions from all directions up -c = dif(X, flux_fac_lim_x) + ... - dif(Y, flux_fac_lim_y) + ... - dif(Z, flux_fac_lim_z); - -end - diff --git a/MATLAB/Discretization/calc_p.m b/MATLAB/Discretization/calc_p.m deleted file mode 100644 index f759cf9..0000000 --- a/MATLAB/Discretization/calc_p.m +++ /dev/null @@ -1,55 +0,0 @@ -%========================================================================== -function [p] = calc_p( p, ... - uf, vf, wf, ... - rho, ... - dt, dx, dy, dz, obst ) -%-------------------------------------------------------------------------- - -r_c = size( p.val ); n_c = prod( r_c ); % resolutions - -% Create linear system -[A_p, b_p] = create_matrix(p, ... % variable - zeros( r_c ), ... % inertial term - dt./rho, ... % diffusive coefficient - dx, dy, dz, ... % cell dimensions - obst, 'n'); ... % obstacles - -% Compute the source for the pressure -% Important: don't send "obst" as a parameter here, because you don't want -% to take it into account at this stage. After velocity corrections, yes! -b_p = vol_balance(uf, vf, wf, dx, dy, dz); - -disp( sprintf('maximum volume error before correction = %12.5e', ... - max(max(max(abs(b_p)))))); -disp( sprintf('volume imbalance before correction = %12.5e', ... - sum(sum(sum(b_p))))); - -% Solve pressure -if SOL == 'd' - p.val = reshape( A_p\(reshape(b_p, n_c, 1)), r_c ); -else - L = ichol(A_p); - p.val = reshape( bicgstab(A_p, reshape(b_p, n_c, 1), ... % A, b - TOL, ... % tolerance - n_c, ... % max iter - L, L', ... % preconditioner - reshape(p.val, n_c, 1)), ... % initial value - r_c); -end - -% Anchor it to values around zero (the absolute value of pressure -% correction can get really volatile. Although it is in prinicple not -% important for incompressible flows, it is ugly for post-processing. -p.val = p.val - mean(mean(mean(p.val))); - -% Set to zero in obstacle (it can get strange -% values during the iterative solution procedure) -if size(obst,1) ~= 0 - p.val = obst_zero_val(C, p.val, obst); -end - -% Finally adjust the boundary values -p = adj_n_bnds(p); - -end - diff --git a/MATLAB/Discretization/calc_t.m b/MATLAB/Discretization/calc_t.m deleted file mode 100644 index 75af328..0000000 --- a/MATLAB/Discretization/calc_t.m +++ /dev/null @@ -1,44 +0,0 @@ -%========================================================================== -function [t] = calc_t( t, ... - fu, fv, fw, ... - rho_cap, lambda, ... - dt, ts, dx, dy, dz, obst ) -%-------------------------------------------------------------------------- - -% Variable to keep the old time step -persistent ts_old; if isempty(ts_old) ts_old = 0; end - -% If you entered here first time in a time step, set the old value -if ts ~= ts_old - t.old = t.val; - ts_old = ts; -end - -r_c = size( t.val ); n_c = prod( r_c ); % resolutions - -[A_t, b_t] = create_matrix(t, ... % variable - rho_cap./dt, ... % innertial term - lambda, ... % diffusive coefficent - dx, dy, dz, ... % dimensions - obst); % obstacles - -% Advection terms for temperatures -c_t = advection(rho_cap, t, fu, fv, fw, dx, dy, dz, dt, 'smart'); - -% Innertial term for enthalpy -i_t = t.old .* rho_cap .* dx .* dy .* dz / dt; - -% The entire source term -f_t = b_t - c_t + i_t; - -% Solve temperature -if SOL == 'd' - t.val = reshape( A_t\(reshape(f_t, n_c, 1)), r_c ); -else - t.val = reshape( bicgstab(A_t, reshape(f_t, n_c, 1), TOL), r_c ); -end - -t = adj_n_bnds(t); - -end - diff --git a/MATLAB/Discretization/calc_uvw.m b/MATLAB/Discretization/calc_uvw.m deleted file mode 100644 index 828a9f7..0000000 --- a/MATLAB/Discretization/calc_uvw.m +++ /dev/null @@ -1,128 +0,0 @@ -%========================================================================== -function [u,v,w, uf,vf,wf] = ... - calc_uvw(u, v, w, ... % transported velocity (coll. or stag.) - uf, vf, wf, ... % advection velocity (staggered) - rho, mu, ... % physical properties - p_tot, ... % total pressure - e_x, e_y, e_z, ... % external forces in x, y and z direction - dt, ts, dx, dy, dz, obst ) -%-------------------------------------------------------------------------- - -% Variable to keep the old time step -persistent ts_old; if isempty(ts_old) ts_old = 0; end - -% If you entered here first time in a time step, set the old value -if ts ~= ts_old - u.old = u.val; - v.old = v.val; - w.old = w.val; - ts_old = ts; -end - -r_u = size( u.val ); n_u = prod( r_u ); % resolutions -r_v = size( v.val ); n_v = prod( r_v ); % resolutions -r_w = size( w.val ); n_w = prod( r_w ); % resolutions - -dv = dx .* dy .* dz; - -pos = u.pos; - -% Create linear systems -[A_u, b_u] = create_matrix(u, ... % variable - rho./dt, ... % inertial term - mu, ... % diffusive coefficient - dx, dy, dz, ... % dimensions - obst, 'd'); % obstacles - -[A_v, b_v] = create_matrix(v, ... % variable - rho./dt, ... % inertial term - mu, ... % diffusive coefficient - dx, dy, dz, ... % dimensions - obst, 'd'); % obstacles - -[A_w, b_w] = create_matrix(w, ... % variable - rho./dt, ... % inertial term - mu, ... % diffusive coefficient - dx, dy, dz, ... % dimensions - obst, 'd'); % obstacles - -% Advection terms for momentum -c_u = advection(rho, u, uf, vf, wf, dx, dy, dz, dt, 'superbee'); -c_v = advection(rho, v, uf, vf, wf, dx, dy, dz, dt, 'superbee'); -c_w = advection(rho, w, uf, vf, wf, dx, dy, dz, dt, 'superbee'); - -% Innertial term for momentum -i_u = u.old .* avg(u.pos, rho) .* avg(u.pos, dv) ./ dt; -i_v = v.old .* avg(v.pos, rho) .* avg(v.pos, dv) ./ dt; -i_w = w.old .* avg(w.pos, rho) .* avg(w.pos, dv) ./ dt; - -% Compute staggered pressure gradients -p_tot_x = dif(X, p_tot) ./ avg(X, dx); -p_tot_y = dif(Y, p_tot) ./ avg(Y, dy); -p_tot_z = dif(Z, p_tot) ./ avg(Z, dz); - -% Make pressure gradients cell-centered -if pos == C - p_tot_x = avg(X, cat(X, p_tot_x(1,:,:), p_tot_x, p_tot_x(end,:,:))); - p_tot_y = avg(Y, cat(Y, p_tot_y(:,1,:), p_tot_y, p_tot_y(:,end,:))); - p_tot_z = avg(Z, cat(Z, p_tot_z(:,:,1), p_tot_z, p_tot_z(:,:,end))); -end - -% Total pressure gradients -p_st_u = p_tot_x .* avg(u.pos, dv); -p_st_v = p_tot_y .* avg(v.pos, dv); -p_st_w = p_tot_z .* avg(w.pos, dv); - -% Full force terms for momentum equations -f_u = b_u - c_u + i_u - p_st_u + e_x .* avg(u.pos, dv); -f_v = b_v - c_v + i_v - p_st_v + e_y .* avg(v.pos, dv); -f_w = b_w - c_w + i_w - p_st_w + e_z .* avg(w.pos, dv); - -% Take care of obsts in the domian -if size(obst,1) ~= 0 - f_u = obst_zero_val(u.pos, f_u, obst); - f_v = obst_zero_val(v.pos, f_v, obst); - f_w = obst_zero_val(w.pos, f_w, obst); -end - -% Solve velocities -if SOL == 'd' - u.val = reshape( A_u\(reshape(f_u, n_u, 1)), r_u ); - v.val = reshape( A_v\(reshape(f_v, n_v, 1)), r_v ); - w.val = reshape( A_w\(reshape(f_w, n_w, 1)), r_w ); -else - u.val = reshape( bicgstab(A_u, reshape(f_u, n_u, 1), TOL), r_u ); - v.val = reshape( bicgstab(A_v, reshape(f_v, n_v, 1), TOL), r_v ); - w.val = reshape( bicgstab(A_w, reshape(f_w, n_w, 1), TOL), r_w ); -end - -% Update velocities in boundary cells -[u, v, w] = adj_o_bnds(u, v, w, dx, dy, dz, dt); - -% Update face velocities (also substract cell-centered pressure gradients -% and add staggered pressure gradients) -if pos == C - uf.val = avg(X,u.val + dt ./ rho .* ( p_tot_x )) ... - - dt ./ avg(X,rho) .* (dif(X,p_tot) ./ avg(X,dx)); - vf.val = avg(Y,v.val + dt ./ rho .* ( p_tot_y )) ... - - dt ./ avg(Y,rho) .* (dif(Y,p_tot) ./ avg(Y,dy)); - wf.val = avg(Z,w.val + dt ./ rho .* ( p_tot_z )) ... - - dt ./ avg(Z,rho) .* (dif(Z,p_tot) ./ avg(Z,dz)); - for j=1:6 - uf.bnd(j).val = u.bnd(j).val; - vf.bnd(j).val = v.bnd(j).val; - wf.bnd(j).val = w.bnd(j).val; - end -else - uf.val = u.val; uf.bnd = u.bnd; - vf.val = v.val; vf.bnd = v.bnd; - wf.val = w.val; wf.bnd = w.bnd; -end - -if size(obst,1) ~= 0 - uf.val = obst_zero_val(X, uf.val, obst); - vf.val = obst_zero_val(Y, vf.val, obst); - wf.val = obst_zero_val(Z, wf.val, obst); -end - -end \ No newline at end of file diff --git a/MATLAB/Discretization/cartesian_grid.m b/MATLAB/Discretization/cartesian_grid.m deleted file mode 100644 index 79796f1..0000000 --- a/MATLAB/Discretization/cartesian_grid.m +++ /dev/null @@ -1,20 +0,0 @@ -%========================================================================== -function [dx, dy, dz, nx, ny, nz] = cartesian_grid(xn, yn, zn) -%-------------------------------------------------------------------------- -% Spawns a 3D Cartesian grid from three arrays with node coordinates. -%-------------------------------------------------------------------------- - -dx = dif(xn); -dy = dif(yn); -dz = dif(zn); - -nx = max( size(dx) ); -ny = max( size(dy) ); -nz = max( size(dz) ); - -dx = repmat(reshape(dx, nx, 1, 1), 1, ny, nz); -dy = repmat(reshape(dy, 1, ny, 1), nx, 1, nz); -dz = repmat(reshape(dz, 1, 1, nz), nx, ny, 1); - -end - diff --git a/MATLAB/Discretization/cfl_max.m b/MATLAB/Discretization/cfl_max.m deleted file mode 100644 index 470ab9b..0000000 --- a/MATLAB/Discretization/cfl_max.m +++ /dev/null @@ -1,27 +0,0 @@ -%========================================================================== -function [cfl] = cfl_max( u, v, w, dt, dx, dy, dz ) -%-------------------------------------------------------------------------- -% Computes the maximum CFL number in a computational domain. -% -% u, v, w - velocity components, either collocated or staggered -% dt - time step -% dx, dy, dz - cell dimensions -%-------------------------------------------------------------------------- - -% Take velocity's position -pos = u.pos; - -% Mesh is cell-centered -if pos == C - cfl = dt * max([ max(max(max(abs(u.val)./dx))), - max(max(max(abs(v.val)./dy))), - max(max(max(abs(w.val)./dz))) ]); - -% Mesh is staggered -else - cfl = dt * max([ max(max(max(abs(u.val)./avg(X,dx)))), - max(max(max(abs(v.val)./avg(Y,dy)))), - max(max(max(abs(w.val)./avg(Z,dz)))) ]); -end - -end \ No newline at end of file diff --git a/MATLAB/Discretization/corr_uvw.m b/MATLAB/Discretization/corr_uvw.m deleted file mode 100644 index 639bcc6..0000000 --- a/MATLAB/Discretization/corr_uvw.m +++ /dev/null @@ -1,30 +0,0 @@ -%========================================================================== -function [u,v,w] = corr_uvw(u,v,w, p, rho, dt, dx,dy,dz, obst) -%-------------------------------------------------------------------------- - -% Compute pressure correction gradients -p_x = dif(X, p.val) ./ avg(X, dx); -p_y = dif(Y, p.val) ./ avg(Y, dy); -p_z = dif(Z, p.val) ./ avg(Z, dz); - -% Set to zero in obst -if size(obst,1) ~= 0 - p_x = obst_zero_val(X, p_x, obst); - p_y = obst_zero_val(Y, p_y, obst); - p_z = obst_zero_val(Z, p_z, obst); -end - -% Pad with boundary values by expanding from interior -% (This is done only for collocated formulation) -if u.pos == C - p_x = avg(X, cat(X, p_x(1,:,:), p_x, p_x(end,:,:))); - p_y = avg(Y, cat(Y, p_y(:,1,:), p_y, p_y(:,end,:))); - p_z = avg(Z, cat(Z, p_z(:,:,1), p_z, p_z(:,:,end))); -end - -% Correct the velocities -u.val = u.val - dt ./ avg(u.pos, rho) .* p_x; -v.val = v.val - dt ./ avg(v.pos, rho) .* p_y; -w.val = w.val - dt ./ avg(w.pos, rho) .* p_z; - -end \ No newline at end of file diff --git a/MATLAB/Discretization/create_matrix.m b/MATLAB/Discretization/create_matrix.m deleted file mode 100644 index 00d68c1..0000000 --- a/MATLAB/Discretization/create_matrix.m +++ /dev/null @@ -1,127 +0,0 @@ -%========================================================================== -function [A, b] = create_matrix(phi, in, mu, dx, dy, dz, obst, obc) -%-------------------------------------------------------------------------- -% pos - position of variable (C - central, -% X - staggered in x direction, -% Y - staggered in y direction, -% Z - staggered in z direction) -% in - innertial term -% mu - viscous coefficient -% dx, dy, dz - cell size in x, y and z directions -% obc - obstacles's boundary condition, ('n' - Neumann, -% 'd' - Dirichlet) -%-------------------------------------------------------------------------- - -%------------------------------- -% Create right hand side vector -%------------------------------- -[nx ny nz] = size(phi.val); - -b = zeros(nx, ny, nz); - -%------------------------------------ -% Create default matrix coefficients -%------------------------------------ -D = phi.pos; - -% Handle central coefficient due to innertia -c.P = avg(D, in) .* avg(D, dx.*dy.*dz); - -% Pre-compute geometrical quantities -sx = dy .* dz; -sy = dx .* dz; -sz = dx .* dy; - -% Compute default matrix coeffiecient values -c.W = cat(X, ... - avg(D,mu( 1,:,:)) .* avg(D,sx( 1,:,:)) ./ avg(D,(dx( 1,:,:))/2), ... - avg(D,avg(X, mu)) .* avg(D,avg(X, sx)) ./ avg(D,avg(X, dx))); -c.E = cat(X, ... - avg(D,avg(X, mu)) .* avg(D,avg(X, sx)) ./ avg(D,avg(X, dx)), ... - avg(D,mu(end,:,:)) .* avg(D,sx(end,:,:)) ./ avg(D,(dx(end,:,:)/2))); -c.S = cat(Y, ... - avg(D,mu(:, 1,:)) .* avg(D,sy(:, 1,:)) ./ avg(D,(dy(:, 1,:)/2)), ... - avg(D,avg(Y, mu)) .* avg(D,avg(Y, sy)) ./ avg(D,avg(Y, dy))); -c.N = cat(Y, ... - avg(D,avg(Y, mu)) .* avg(D,avg(Y, sy)) ./ avg(D,avg(Y, dy)), ... - avg(D,mu(:,end,:)) .* avg(D,sy(:,end,:)) ./ avg(D,(dy(:,end,:)/2))); -c.B = cat(Z, ... - avg(D,mu(:,:, 1)) .* avg(D,sz(:,:, 1)) ./ avg(D,(dz(:,:, 1)/2)), ... - avg(D,avg(Z, mu)) .* avg(D,avg(Z, sz)) ./ avg(D,avg(Z, dz))); -c.T = cat(Z, ... - avg(D,avg(Z, mu)) .* avg(D,avg(Z, sz)) ./ avg(D,avg(Z, dz)), ... - avg(D,mu(:,:,end)) .* avg(D,sz(:,:,end)) ./ avg(D,(dz(:,:,end)/2))); - -% Correct for staggered variables -if D == X - c.W = mu(1:end-1,:,:) .* sx(1:end-1,:,:) ./ dx(1:end-1,:,:); - c.E = mu(2:end, :,:) .* sx(2:end, :,:) ./ dx(2:end, :,:); -elseif D == Y - c.S = mu(:,1:end-1,:) .* sy(:,1:end-1,:) ./ dy(:,1:end-1,:); - c.N = mu(:,2:end, :) .* sy(:,2:end, :) ./ dy(:,2:end, :); -elseif D == Z - c.B = mu(:,:,1:end-1) .* sz(:,:,1:end-1) ./ dz(:,:,1:end-1); - c.T = mu(:,:,2:end ) .* sz(:,:,2:end ) ./ dz(:,:,2:end ); -end - -%----------------------------------------------------------------------- -% Zero them (correct them) for vanishing derivative boundary condition. -%----------------------------------------------------------------------- - -% The values defined here will be false (0) wherever there is no inlet. -if_w_d = ( phi.bnd(W).type(1,:,:) == 'd' ); -if_e_d = ( phi.bnd(E).type(1,:,:) == 'd' ); -if_s_d = ( phi.bnd(S).type(:,1,:) == 'd' ); -if_n_d = ( phi.bnd(N).type(:,1,:) == 'd' ); -if_b_d = ( phi.bnd(B).type(:,:,1) == 'd' ); -if_t_d = ( phi.bnd(T).type(:,:,1) == 'd' ); - -c.W( 1, :, :) = c.W( 1, :, :) .* if_w_d; -c.E(end, :, :) = c.E(end, :, :) .* if_e_d; -c.S( :, 1, :) = c.S( :, 1, :) .* if_s_d; -c.N( :,end, :) = c.N( :,end, :) .* if_n_d; -c.B( :, :, 1) = c.B( :, :, 1) .* if_b_d; -c.T( :, :,end) = c.T( :, :,end) .* if_t_d; - -%-------------------------------------------- -% Fill the source terms with boundary values -%-------------------------------------------- -b( 1, :, :) = b( 1, :, :) + c.W( 1, :, :).*phi.bnd(W).val(1,:,:); -b(end, :, :) = b(end, :, :) + c.E(end, :, :).*phi.bnd(E).val(1,:,:); -b( :, 1, :) = b( :, 1, :) + c.S( :, 1, :).*phi.bnd(S).val(:,1,:); -b( :,end, :) = b( :,end, :) + c.N( :,end, :).*phi.bnd(N).val(:,1,:); -b( :, :, 1) = b( :, :, 1) + c.B( :, :, 1).*phi.bnd(B).val(:,:,1); -b( :, :,end) = b( :, :,end) + c.T( :, :,end).*phi.bnd(T).val(:,:,1); - -%--------------------------------------- -% Correct system matrices for obstacles -%--------------------------------------- -if size(obst,1) ~= 0 - c = obst_mod_matrix(phi, c, obst, obc); -end - -%----------------------------------------------- -% Add all neighbours to the central matrix, -% and zero the coefficients towards boundaries -%----------------------------------------------- -c.P = c.P + c.W + c.E + c.S + c.N + c.B + c.T; - -c.W( 1, :, :) = 0; c.E(end, :, :) = 0; -c.S( :, 1, :) = 0; c.N( :,end, :) = 0; -c.B( :, :, 1) = 0; c.T( :, :,end) = 0; - -%---------------------- -% Create sparse matrix -%---------------------- -n = nx * ny * nz; - -c.P = reshape(c.P, n, 1); -c.W = reshape(c.W, n, 1); c.E = reshape(c.E, n, 1); -c.S = reshape(c.S, n, 1); c.N = reshape(c.N, n, 1); -c.B = reshape(c.B, n, 1); c.T = reshape(c.T, n, 1); - -A = spdiags( [-c.T -c.N -c.E c.P -c.W -c.S -c.B ], ... - [-nx*ny -nx -1 0 +1 +nx +nx*ny], ... - n, n); - -end \ No newline at end of file diff --git a/MATLAB/Discretization/create_unknown.m b/MATLAB/Discretization/create_unknown.m deleted file mode 100644 index 526d767..0000000 --- a/MATLAB/Discretization/create_unknown.m +++ /dev/null @@ -1,63 +0,0 @@ -%========================================================================== -function [phi] = create_unkonwn( name, pos, res, def_bc ) -%-------------------------------------------------------------------------- -% This function creates a new unkown; helping to shorten the main program. -%-------------------------------------------------------------------------- -% Input parameters are: -% -% name - string holding the name of the variable -% it should be used for post-processing -% pos - character specifying if the variable is cell centered (C), -% staggered in x direction (X) or in y direction (Y) -% res - vector specifying resolutions in x and y direction -% def_bc - character specifying if the default boundary condition is of -% dirichlet type ('d'), neumann type ('n') or outlet ('o') -%-------------------------------------------------------------------------- - -%--------------- -% Save the name -%--------------- -phi.name = name; - -%------------------ -% Set the position -%------------------ -if pos ~= C && pos ~= X && pos ~= Y && pos ~= Z - error('Variable must be defined at positions ' + ... - 'C, X, Y or Z'); -end -phi.pos = pos; - -%----------------------------- -% Dimension and initial value -%----------------------------- -phi.val = zeros(res); -phi.old = zeros(res); - -%--------------------------------- -% Set default boundary conditions -%--------------------------------- -if def_bc ~= 'd' && ... - def_bc ~= 'n' && ... - def_bc ~= 'o' - error('Variable must be defined with boundary conditions ' + ... - '''d'', ''n'' or ''o'''); -end -phi.bnd(W).type(1, 1:res(2), 1:res(3)) = def_bc; -phi.bnd(E).type(1, 1:res(2), 1:res(3)) = def_bc; -phi.bnd(S).type(1:res(1), 1, 1:res(3)) = def_bc; -phi.bnd(N).type(1:res(1), 1, 1:res(3)) = def_bc; -phi.bnd(B).type(1:res(1), 1:res(2), 1) = def_bc; -phi.bnd(T).type(1:res(1), 1:res(2), 1) = def_bc; - -phi.bnd(W).val(1, 1:res(2), 1:res(3)) = 0; -phi.bnd(E).val(1, 1:res(2), 1:res(3)) = 0; -phi.bnd(S).val(1:res(1), 1, 1:res(3)) = 0; -phi.bnd(N).val(1:res(1), 1, 1:res(3)) = 0; -phi.bnd(B).val(1:res(1), 1:res(2), 1) = 0; -phi.bnd(T).val(1:res(1), 1:res(2), 1) = 0; - -disp( sprintf('Created variable %s', name) ); - -end - diff --git a/MATLAB/Discretization/nodes.m b/MATLAB/Discretization/nodes.m deleted file mode 100644 index b3908aa..0000000 --- a/MATLAB/Discretization/nodes.m +++ /dev/null @@ -1,58 +0,0 @@ -%========================================================================== -function [x] = nodes(s, e, n, del_1, del_e) -%-------------------------------------------------------------------------- -% Creates node coordinates in one dimension -%-------------------------------------------------------------------------- - -%--------------------------------------------- -% -% Just a simple constant-spacing distribution -% -%--------------------------------------------- -if nargin == 3 - x = linspace(s, e, n+1); - -else -%------------------------------------------------------------------------ -% -% Grid distribution is determined from the following function: -% x = a + b y + c y^2 + d y^3 -% -% One should imagine this function as taking integer arguments. -% -% Boundary conditions: -% -% 1. x(1) = s => a + b + c + d = s -% -% 2. x(2) = s + del_1 => a + b*2 + c*4 + d*8 = s + del_1 -% -% 3. x(n) = e - del_e => a + b*n + c*n^2 + d*n^3 = e - del_e -% -% 4. x(n+1) = e => a + b*(n+1) + c*(n+1)^2 + d*(n+1)^3 = e -% -% => -% -% |1 1 1 1 | |a| |s | -% |1 2 4 8 | |b| |s+del_1| -% |1 n n^2 n^3 | |c| |e-del_e| -% |1 (n+1) (n+1)^2 (n+1)^3| |d| |e | -% -%------------------------------------------------------------------------ - A = [1 1 1 1; ... - 1 2 4 8; ... - 1 n n^2 n^3; ... - 1 (n+1) (n+1)^2 (n+1)^3]; - - f = [s; ... - s+del_1; ... - e-del_e; ... - e]; - - abcd = A \ f; - - for i=1:n+1 - x(i) = abcd(1) + abcd(2) * i + abcd(3) * i^2 + abcd(4) * i^3; - end - -end - diff --git a/MATLAB/Discretization/obst_mod_matrix.m b/MATLAB/Discretization/obst_mod_matrix.m deleted file mode 100644 index 9e963b3..0000000 --- a/MATLAB/Discretization/obst_mod_matrix.m +++ /dev/null @@ -1,147 +0,0 @@ -%========================================================================== -function [c] = obst_matrix(phi, c, obst, obc) -%-------------------------------------------------------------------------- -% Adjusts the system matrix for obstacles and cell centered varaibles -% (such as pressure) -% -% phi - variable -% c - coefficients in system matrix -% obst - obstacle array -% obc - obstacles's boundary condition, ('n' - Neumann, 'd' - Dirichlet) -%-------------------------------------------------------------------------- - -pos = phi.pos; - -%-------------------------- -% -% For collocated variables -% -%-------------------------- -if pos == C - - %------------------------------------ - % Neumann's boundary on the obstacle - %------------------------------------ - if obc == 'n' - - % Correct west and east - sol_x = dif(X, obst); % will be +1 east of obst, -1 west of obst - corr = 1 - (sol_x < 0); c.W(2:end, :,:) = c.W(2:end, :,:) .* corr; - corr = 1 - (sol_x > 0); c.E(1:end-1,:,:) = c.E(1:end-1,:,:) .* corr; - - % Correct south and north - sol_y = dif(Y, obst); % will be +1 north of obst, -1 south of obst - corr = 1 - (sol_y < 0); c.S(:,2:end, :) = c.S(:,2:end, :) .* corr; - corr = 1 - (sol_y > 0); c.N(:,1:end-1,:) = c.N(:,1:end-1,:) .* corr; - - % Correct bottom and top - sol_z = dif(Z, obst); % will be +1 north of obst, -1 south of obst - corr = 1 - (sol_z < 0); c.B(:,:,2:end ) = c.B(:,:,2:end ) .* corr; - corr = 1 - (sol_z > 0); c.T(:,:,1:end-1) = c.T(:,:,1:end-1) .* corr; - - %-------------------------------------- - % Dirichlet's boundary on the obstacle - %-------------------------------------- - elseif obc == 'd' - - % Set central coefficient to 1 in obst, unchanged elsewhere - c.P = c.P .* not(obst) + obst; - - % Set neighbour coefficients to zero in obst - c.W = c.W .* not(obst); - c.E = c.E .* not(obst); - c.S = c.S .* not(obst); - c.N = c.N .* not(obst); - c.B = c.B .* not(obst); - c.T = c.T .* not(obst); - - % Increase coefficients close to obst (makes sense for momentum) - sol_x = dif(X, obst); % will be +1 east of obst, -1 west of obst - corr = 1 + (sol_x > 0); c.E(1:end-1,:,:) = c.E(1:end-1,:,:) .* corr; - corr = 1 + (sol_x < 0); c.W(2:end, :,:) = c.W(2:end, :,:) .* corr; - - sol_y = dif(Y, obst); % will be +1 north of obst, -1 south of obst - corr = 1 + (sol_y > 0); c.N(:,1:end-1,:) = c.N(:,1:end-1,:) .* corr; - corr = 1 + (sol_y < 0); c.S(:,2:end, :) = c.S(:,2:end, :) .* corr; - - sol_z = dif(Z, obst); % will be +1 top of obst, -1 bottom of obst - corr = 1 + (sol_z > 0); c.T(:,:,1:end-1) = c.T(:,:,1:end-1) .* corr; - corr = 1 + (sol_z < 0); c.B(:,:,2:end ) = c.B(:,:,2:end ) .* corr; - end - -%------------------------- -% -% For staggered variables -% -%------------------------- -elseif pos==X - - % Set central coefficient to 1 in obst, unchanged elsewhere - obst_x = max(obst(1:end-1,:,:), obst(2:end,:,:)); - c.P = c.P .* not(obst_x) + obst_x; - - % Set neighbour coefficients to zero in obst - c.W = c.W .* not(obst_x); - c.E = c.E .* not(obst_x); - c.S = c.S .* not(obst_x); - c.N = c.N .* not(obst_x); - c.B = c.B .* not(obst_x); - c.T = c.T .* not(obst_x); - - % Increase coefficients close to obst (makes sense for momentum) - sol_y = dif(Y, obst_x); % will be +1 north of obst, -1 south of obst - corr = 1 + (sol_y > 0); c.N(:,1:end-1,:) = c.N(:,1:end-1,:) .* corr; - corr = 1 + (sol_y < 0); c.S(:,2:end, :) = c.S(:,2:end, :) .* corr; - - sol_z = dif(Z, obst_x); % will be +1 top of obst, -1 bottom of obst - corr = 1 + (sol_z > 0); c.T(:,:,1:end-1) = c.T(:,:,1:end-1) .* corr; - corr = 1 + (sol_z < 0); c.B(:,:,2:end ) = c.B(:,:,2:end ) .* corr; - -elseif pos==Y - - % Set central coefficient to 1 in obst, unchanged elsewhere - obst_y = max(obst(:,1:end-1,:), obst(:,2:end,:)); - c.P = c.P .* not(obst_y) + obst_y; - - % Set neighbour coefficients to zero in obst - c.W = c.W .* not(obst_y); - c.E = c.E .* not(obst_y); - c.S = c.S .* not(obst_y); - c.N = c.N .* not(obst_y); - c.B = c.B .* not(obst_y); - c.T = c.T .* not(obst_y); - - % Increase coefficients close to obst (makes sense for momentum) - sol_x = dif(X, obst_y); % will be +1 north of obst, -1 south of obst - corr = 1 + (sol_x > 0); c.E(1:end-1,:,:) = c.E(1:end-1,:,:) .* corr; - corr = 1 + (sol_x < 0); c.W(2:end, :,:) = c.W(2:end, :,:) .* corr; - - sol_z = dif(Z, obst_y); % will be +1 north of obst, -1 south of obst - corr = 1 + (sol_z > 0); c.T(:,:,1:end-1) = c.T(:,:,1:end-1) .* corr; - corr = 1 + (sol_z < 0); c.B(:,:,2:end ) = c.B(:,:,2:end ) .* corr; - -elseif pos==Z - - % Set central coefficient to 1 in obst, unchanged elsewhere - obst_z = max(obst(:,:,1:end-1), obst(:,:,2:end)); - c.P = c.P .* not(obst_z) + obst_z; - - % Set neighbour coefficients to zero in obst - c.W = c.W .* not(obst_z); - c.E = c.E .* not(obst_z); - c.S = c.S .* not(obst_z); - c.N = c.N .* not(obst_z); - c.B = c.B .* not(obst_z); - c.T = c.T .* not(obst_z); - - % Increase coefficients close to obst (makes sense for momentum) - sol_x = dif(X, obst_z); % will be +1 north of obst, -1 south of obst - corr = 1 + (sol_x > 0); c.E(1:end-1,:,:) = c.E(1:end-1,:,:) .* corr; - corr = 1 + (sol_x < 0); c.W(2:end, :,:) = c.W(2:end, :,:) .* corr; - - sol_y = dif(Y, obst_z); % will be +1 north of obst, -1 south of obst - corr = 1 + (sol_y > 0); c.N(:,1:end-1,:) = c.N(:,1:end-1,:) .* corr; - corr = 1 + (sol_y < 0); c.S(:,2:end, :) = c.S(:,2:end, :) .* corr; -end - -end \ No newline at end of file diff --git a/MATLAB/Discretization/obst_zero_val.m b/MATLAB/Discretization/obst_zero_val.m deleted file mode 100644 index b58ea62..0000000 --- a/MATLAB/Discretization/obst_zero_val.m +++ /dev/null @@ -1,27 +0,0 @@ -%========================================================================== -function [val] = obst_zero_source(pos, val, obst) -%-------------------------------------------------------------------------- -% Set value to zero inside obstacle. -% -% pos - position of the variable, C, X, Y or Z -% val - value to be zeroed in obstacle -% obst - matrix holding positions of obstacle -%-------------------------------------------------------------------------- - -if pos==C - val = val .* not(obst); - -elseif pos==X - obst_x = max(obst(1:end-1,:,:), obst(2:end,:,:)); - val = val .* not(obst_x); - -elseif pos==Y - obst_y = max(obst(:,1:end-1,:), obst(:,2:end,:)); - val = val .* not(obst_y); - -elseif pos==Z - obst_z = max(obst(:,:,1:end-1), obst(:,:,2:end)); - val = val .* not(obst_z); -end - -end \ No newline at end of file diff --git a/MATLAB/Discretization/vol_balance.m b/MATLAB/Discretization/vol_balance.m deleted file mode 100644 index 3d1675b..0000000 --- a/MATLAB/Discretization/vol_balance.m +++ /dev/null @@ -1,25 +0,0 @@ -%========================================================================== -function [src] = vol_balance(uf, vf, wf, dx, dy, dz, obst) -%-------------------------------------------------------------------------- -% Computes the volume balance, which is essentially a right hand side in -% the Poisson's equation for pressure. -% -% Note that "obst" is an optional parameter. If it is not sent, the source -% won't be zeroed inside the obstacle. That is important for calculation -% of pressure, see function "calc_p". -%-------------------------------------------------------------------------- - -% Compute it throughout the domain -src = - dif(X, cat(X, uf.bnd(W).val, uf.val, uf.bnd(E).val)).*dy.*dz ... - - dif(Y, cat(Y, vf.bnd(S).val, vf.val, vf.bnd(N).val)).*dx.*dz ... - - dif(Z, cat(Z, wf.bnd(B).val, wf.val, wf.bnd(T).val)).*dx.*dy; - -% Zero it inside obstacles, if obstacle is sent as parameter -if nargin == 7 - if size(obst,1) ~= 0 - src = obst_zero_val(C, src, obst); - end -end - -end - \ No newline at end of file diff --git a/MATLAB/InputOutput/disp_time_step.m b/MATLAB/InputOutput/disp_time_step.m deleted file mode 100644 index 89d410c..0000000 --- a/MATLAB/InputOutput/disp_time_step.m +++ /dev/null @@ -1,10 +0,0 @@ -function [] = disp_time_step( i ) - -disp( sprintf('+======================+') ); -disp( sprintf('| |') ); -disp( sprintf('| Time step = %6d |', i ) ); -disp( sprintf('| |') ); -disp( sprintf('+======================+') ); - -end - diff --git a/MATLAB/InputOutput/export_tecplot.m b/MATLAB/InputOutput/export_tecplot.m deleted file mode 100644 index 26210c0..0000000 --- a/MATLAB/InputOutput/export_tecplot.m +++ /dev/null @@ -1,110 +0,0 @@ -%========================================================================== -function export_tecplot(file_name, container, resolution, xn, yn, zn) -%-------------------------------------------------------------------------- - -nx = resolution(1); -ny = resolution(2); -nz = resolution(3); - -%-------------- -% write header -%-------------- -file_id = fopen(file_name, 'w'); -fprintf(file_id, 'title = "MatNaSt-FV Output"\n'); -fprintf(file_id, 'variables = "x" "y" "z" '); -for n=1:size(container.var, 2) - fprintf(file_id, '"%s" ', container.var(n).name); -end -fprintf(file_id, '\n'); -fprintf(file_id, 'zone i=%0.0d, j=%0.0d k=%0.0d\n', nx+1, ny+1, nz+1); -fprintf(file_id, 'datapacking=block\n'); -fprintf(file_id, 'varlocation=([%0.0d-%0.0d]=cellcentered)\n', ... - 4, size(container.var, 2) + 3); - -%------------------------ -% write node coordinates -%------------------------ -fprintf(file_id, '# x coordinates\n'); -c = 0; -for k=1:size(zn) - for j=1:size(yn) - for i=1:size(xn) - fprintf(file_id, '%12.5e ', xn(i)); - c = c + 1; - if mod(c,4)==0 - fprintf(file_id, '\n'); - end - end - end -end -fprintf(file_id, '\n'); - -fprintf(file_id, '# y-coordinates\n'); -c = 0; -for k=1:size(zn) - for j=1:size(yn) - for i=1:size(xn) - fprintf(file_id, '%12.5e ', yn(j)); - c = c + 1; - if mod(c,4)==0 - fprintf(file_id, '\n'); - end - end - end -end -fprintf(file_id, '\n'); - -fprintf(file_id, '# z-coordinates\n'); -c = 0; -for k=1:size(zn) - for j=1:size(yn) - for i=1:size(xn) - fprintf(file_id, '%12.5e ', zn(k)); - c = c + 1; - if mod(c,4)==0 - fprintf(file_id, '\n'); - end - end - end -end -fprintf(file_id, '\n'); - -%--------------------- -% write all variables -%--------------------- -for n=1:size(container.var, 2) - - % print a sub-header - fprintf(file_id, '# %s\n', container.var(n).name); - - % arrange the variables according to their positions - r = container.var(n); - values = r.val; - if container.var(n).pos == X - values = avg(X,cat(1, r.bnd(W).val, r.val, r.bnd(E).val)); - end - if container.var(n).pos == Y - values = avg(Y,cat(2, r.bnd(S).val, r.val, r.bnd(N).val)); - end - if container.var(n).pos == Z - values = avg(Z,cat(3, r.bnd(B).val, r.val, r.bnd(T).val)); - end - - % print to file - c = 0; - for k=1:nz - for j=1:ny - for i=1:nx - fprintf(file_id, '%12.5e ', values(i, j, k)); - c = c + 1; - if mod(c,4)==0 - fprintf(file_id, '\n'); - end - end - end - end -end - -fclose(file_id); - -end \ No newline at end of file diff --git a/MATLAB/Operators/avg.m b/MATLAB/Operators/avg.m deleted file mode 100644 index fa0b475..0000000 --- a/MATLAB/Operators/avg.m +++ /dev/null @@ -1,14 +0,0 @@ -%========================================================================== -function b = avg(d, a) - -if nargin == 1 - b = (d(2:end) + d(1:end-1))/2; -else - if d == X b = (a(2:end,:,:) + a(1:end-1,:,:))*0.5; - elseif d == Y b = (a(:,2:end,:) + a(:,1:end-1,:))*0.5; - elseif d == Z b = (a(:,:,2:end) + a(:,:,1:end-1))*0.5; - else b = a; - end -end - -end \ No newline at end of file diff --git a/MATLAB/Operators/dif.m b/MATLAB/Operators/dif.m deleted file mode 100644 index 89e2441..0000000 --- a/MATLAB/Operators/dif.m +++ /dev/null @@ -1,14 +0,0 @@ -%========================================================================== -function b = dif(d, a) - -if nargin == 1 - b = (d(2:end) - d(1:end-1)); -else - if d == X b = (a(2:end,:,:) - a(1:end-1,:,:)); - elseif d == Y b = (a(:,2:end,:) - a(:,1:end-1,:)); - elseif d == Z b = (a(:,:,2:end) - a(:,:,1:end-1)); - end -end - - -end \ No newline at end of file diff --git a/MATLAB/Operators/max_of_3.m b/MATLAB/Operators/max_of_3.m deleted file mode 100644 index 409a6fc..0000000 --- a/MATLAB/Operators/max_of_3.m +++ /dev/null @@ -1,7 +0,0 @@ -%========================================================================== -function d = max_of_3(a, b, c) - -d = max(a, max(b, c)); - -end - diff --git a/MATLAB/Operators/min_of_3.m b/MATLAB/Operators/min_of_3.m deleted file mode 100644 index 637e9ab..0000000 --- a/MATLAB/Operators/min_of_3.m +++ /dev/null @@ -1,6 +0,0 @@ -%========================================================================== -function d = min_of_3(a, b, c) - -d = min(a, min(b, c)); - -end diff --git a/MATLAB/Operators/par.m b/MATLAB/Operators/par.m deleted file mode 100644 index b41599a..0000000 --- a/MATLAB/Operators/par.m +++ /dev/null @@ -1,12 +0,0 @@ -%========================================================================== -function [ y ] = par( mean_val, n ) - -max_val = mean_val * 3/2; - -x = linspace(-1,1,n); - -y = (1-x.*x) * max_val; - - -end - diff --git a/MATLAB/Operators/vol.m b/MATLAB/Operators/vol.m deleted file mode 100644 index 908c8b7..0000000 --- a/MATLAB/Operators/vol.m +++ /dev/null @@ -1,16 +0,0 @@ -%========================================================================== -function [ dv ] = vol( dx, dy, dz ) -%-------------------------------------------------------------------------- -% Returns a 3D array of computational volumes -%-------------------------------------------------------------------------- - -nx = max( size(dx) ); -ny = max( size(dy) ); -nz = max( size(dz) ); - -dv = repmat(reshape(dx, nx, 1, 1), 1, ny, nz) ... - .* repmat(reshape(dy, 1, ny, 1), nx, 1, nz) ... - .* repmat(reshape(dz, 1, 1, nz), nx, ny, 1); - -end - diff --git a/MATLAB/PhysicalModels/air_properties.m b/MATLAB/PhysicalModels/air_properties.m deleted file mode 100644 index 74110d0..0000000 --- a/MATLAB/PhysicalModels/air_properties.m +++ /dev/null @@ -1,16 +0,0 @@ -%========================================================================== -function [ rho, mu, cp, lambda ] = air_properties( rx, ry, rz ) -%-------------------------------------------------------------------------- -% Returns physical properties of air in given ranges "rx", "ry" and "rz" -% -% For 60 deg from: -% http://www.engineeringtoolbox.com/air-properties-d_156.html -%-------------------------------------------------------------------------- - -rho (rx, ry, rz) = 1.067; % density [kg/m^3] -mu (rx, ry, rz) = 20.17E-06; % viscosity [Pa s] -cp (rx, ry, rz) = 1009; % thermal capacity [J/kg/K] -lambda(rx, ry, rz) = 0.0285; % thermal conductivity [W/m/K] - -end - diff --git a/MATLAB/PhysicalModels/water_properties.m b/MATLAB/PhysicalModels/water_properties.m deleted file mode 100644 index 396328c..0000000 --- a/MATLAB/PhysicalModels/water_properties.m +++ /dev/null @@ -1,16 +0,0 @@ -%========================================================================== -function [ rho, mu, cp, lambda ] = water_properties( rx, ry, rz ) -%-------------------------------------------------------------------------- -% Returns physical properties of water in given ranges "rx", "ry" and "rz" -% -% For 60 deg from: -% http://www.engineeringtoolbox.com/water-properties-d_1508.html -%-------------------------------------------------------------------------- - -rho (rx, ry, rz) = 983; % density [kg/m^3] -mu (rx, ry, rz) = 0.466E-3; % viscosity [Pa s] -cp (rx, ry, rz) = 4185; % thermal capacity [J/kg/K] -lambda(rx, ry, rz) = 0.654; % thermal conductivity [W/m/K] - -end - diff --git a/MATLAB/Tests/test_advection_rotational.m b/MATLAB/Tests/test_advection_rotational.m deleted file mode 100644 index 52bc3d8..0000000 --- a/MATLAB/Tests/test_advection_rotational.m +++ /dev/null @@ -1,150 +0,0 @@ -%========================================================================== -% Tests the rotation of a shape (defined in file shape.dat or in the script -% itself) using advection schemes implemented in the code. -% -% Name of the scheme to be used is set with the variable "NAME" -%-------------------------------------------------------------------------- -clear; - -NAME = 'superbee' - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution -xn = nodes(-1, 1, 120); -yn = nodes(-1, 1, 120); -zn = nodes( 0, 0.1, 4); - -% Cell dimensions -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - -% Resolution ranges -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% Set physical properties -prop.rho (1:nx, 1:ny, 1:nz) = 1.0e3; % density -prop.mu (1:nx, 1:ny, 1:nz) = 0.01; % viscosity -prop.lambda(1:nx, 1:ny, 1:nz) = 0.00000; % thermal conductivity -prop.cap (1:nx, 1:ny, 1:nz) = 1.0; % thermal capacity - -% Time-stepping parameters -dt = pi/600; % time steps -ndt = 300; % number of time steps - -% Create unknowns; names, positions, sizes and default boundary conditions -uf = create_unknown('face-u-vel', X, r.u, 'd'); -vf = create_unknown('face-v-vel', Y, r.v, 'd'); -wf = create_unknown('face-w-vel', Z, r.w, 'd'); -tc = create_unknown('temperature', C, r.c, 'd'); - -% Create rotational velocity field -for k=1:nz - for j=1:ny - for i=1:nx-1 - uf.val(i,j,k) = -yn(j+1); - end - end - for j=1:ny-1 - for i=1:nx - vf.val(i,j,k) = xn(i+1); - end - end -end - -% Initial and boundary conditions -SHAPE = ... -[ [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0]; ... - [0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0]; ... - [0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0]; ... - [0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0]; ... - [0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0]; ... - [0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0]; ... - [0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0] ]; -% load('shape.dat', 'shape', '-ascii') -[ni nj] = size(SHAPE); - -for k=1:nz - tx.val(nx/2-ni/2+1:nx/2+ni/2, 3*ny/4-ni/2+1 : 3*ny/4+ni/2, k) = SHAPE; - ty.val(nx/2-ni/2+1:nx/2+ni/2, 3*ny/4-ni/2+1 : 3*ny/4+ni/2, k) = SHAPE; - tc.val(nx/2-ni/2+1:nx/2+ni/2, 3*ny/4-ni/2+1 : 3*ny/4+ni/2, k) = SHAPE; -end - -obst = []; - -%----------- -% -% Time loop -% -%----------- -for ts=1:ndt - - disp_time_step( ts ); - - %--------------------- - % Collocated variable - %--------------------- - tc = calc_t(tc, uf, vf, wf, ... % variable and advection velocity - prop.rho, prop.mu, ... % physical properties - dt, ts, dx, dy, dz, obst); % numerical domain - - cfl = cfl_max( uf, vf, wf, dt, dx, dy, dz ); - disp( sprintf('cfl max = %5.3f', cfl ) ); - - %------ - % Plot - %------ - kp = 2; - up = avg(X, cat(X, uf.bnd(W).val, uf.val, uf.bnd(E).val)); - vp = avg(Y, cat(Y, vf.bnd(S).val, vf.val, vf.bnd(N).val)); - xp = avg(xn); - yp = avg(yn); - tp = tc.val(:,:,kp); - [cnt,hnd] = contourf(xp, yp, tp', linspace(-0.01,1.01,3)); - hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title(sprintf('Time step %d out of %d\nCFL = %5.3f\n', ts, ndt, cfl)) - drawnow; -end - diff --git a/MATLAB/Tests/test_advection_unidirectional.m b/MATLAB/Tests/test_advection_unidirectional.m deleted file mode 100644 index 6a79ef8..0000000 --- a/MATLAB/Tests/test_advection_unidirectional.m +++ /dev/null @@ -1,173 +0,0 @@ -%========================================================================== -% Program to test implementation of advection schemes in the code, using -% one-dimensoinal transport of a step function in X, Y or Z -% direction, either in positive or negative sense. -% -% The coordinate direction is specified with the local variable "TEST", -% which can be either X, Y or Z. -% -% Sense is specified with the variable "FLOW", which can assume values 'p' -% for positive, and 'n' for negative sense. -%-------------------------------------------------------------------------- -clear -clc; - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%--------------------- -% Set local constants -%--------------------- -test = [X, Y, Z]; TEST = test( ceil(rand*3) ); -flow = ['p','n']; FLOW = flow( ceil(rand*2) ); - -NAME = 'koren' -FLOW = 'n' -MIN = 10; -MAX = 20; - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution -if TEST == X - xn = nodes(0, 1, 200); - yn = nodes(0, 0.1, 4); - zn = nodes(0, 0.1, 4); - if FLOW == 'p' - u_bulk = +1.0; v_bulk = 0.0; w_bulk = 0.0; - elseif FLOW == 'n' - u_bulk = -1.0; v_bulk = 0.0; w_bulk = 0.0; - end -elseif TEST == Y - xn = nodes(0, 0.1, 4); - yn = nodes(0, 1, 200); - zn = nodes(0, 0.1, 4); - if FLOW == 'p' - u_bulk = 0.0; v_bulk = +1.0; w_bulk = 0.0; - elseif FLOW == 'n' - u_bulk = 0.0; v_bulk = -1.0; w_bulk = 0.0; - end -elseif TEST == Z - xn = nodes(0, 0.1, 4); - yn = nodes(0, 0.1, 4); - zn = nodes(0, 1, 200); - if FLOW == 'p' - u_bulk = 0.0; v_bulk = 0.0; w_bulk = +1.0; - elseif FLOW == 'n' - u_bulk = 0.0; v_bulk = 0.0; w_bulk = -1.0; - end -end - -% Cell dimensions -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - -% Resolution ranges -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% Set physical properties -rho (1:nx,1:ny,1:nz) = 1.0; -mu (1:nx,1:ny,1:nz) = 0.0; -lambda(1:nx,1:ny,1:nz) = 0.0; -cap (1:nx,1:ny,1:nz) = 1.0; - -% time-stepping parameters -dt = 0.002; % time step -ndt = 350; % number of time steps - -% create unknowns; names, positions and sizes -uf = create_unknown('face-u-vel', X, r.u, 'd'); -vf = create_unknown('face-v-vel', Y, r.v, 'd'); -wf = create_unknown('face-w-vel', Z, r.w, 'd'); -t = create_unknown('temperature', C, r.c, 'n'); - -% specify inital and boundary conditions -uf.val(:,:,:) = u_bulk; -vf.val(:,:,:) = v_bulk; -wf.val(:,:,:) = w_bulk; -for j=1:6 - uf.bnd(j).val(:,:,:) = u_bulk; - vf.bnd(j).val(:,:,:) = v_bulk; - wf.bnd(j).val(:,:,:) = w_bulk; -end - -t.val(:,:,:) = MIN; -for j=1:6 - t.bnd(j).val(:,:,:) = MIN; -end -if TEST == X t.val(nx/2-25:nx/2+25, :, :) = MAX; end -if TEST == Y t.val(:, ny/2-25:ny/2+25, :) = MAX; end -if TEST == Z t.val(:, :, nz/2-25:nz/2+25) = MAX; end - -obst = []; - -%========================================================================== -% -% Solution algorithm -% -%========================================================================== - -%----------- -% -% Time loop -% -%----------- -for ts=1:ndt - - disp_time_step( ts ); - - %------------------------ - % Temperature (enthalpy) - %------------------------ - t = calc_t(t, uf, vf, wf, ... % variable and adv. velocity - (rho.*cap), lambda, ... % physical properties - dt, ts, dx, dy, dz, obst); % numerical domain - -%========================================================================== -% -% Visualization -% -%========================================================================== - - %------ - % Plot - %------ - clf - xp = avg(xn); - yp = avg(yn); - zp = avg(zn); - if TEST == X - plot(xp, reshape( t.val(:,ny/2,nz/2), nx,1 ), 'r.-') - axis([-0.1 1.1 MIN*0.8 MAX*1.2]) - end - if TEST == Y - plot(yp, reshape( t.val(nx/2,:,nz/2), ny,1 ), 'g.-') - axis([-0.1 1.1 MIN*0.8 MAX*1.2]) - end - if TEST == Z - plot(zp, reshape( t.val(nx/2,ny/2,:), nz,1 ), 'b.-') - axis([-0.1 +1.1 MIN*0.8 MAX*1.2]) - end - title([sprintf('Transport with %s ', NAME), ... - sprintf('in %s direction, ', TEST), ... - sprintf('%s sense', FLOW)]); - drawnow - - cfl = cfl_max( uf, vf, wf, dt, dx, dy, dz ); - disp( sprintf('cfl max = %5.3f', cfl ) ); -end - - - diff --git a/MATLAB/Tests/test_disc.m b/MATLAB/Tests/test_disc.m deleted file mode 100644 index 0109d3c..0000000 --- a/MATLAB/Tests/test_disc.m +++ /dev/null @@ -1,165 +0,0 @@ -%========================================================================== -% -% -% -%-------------------------------------------------------------------------- -clear; - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution -xn = nodes(0, 0.1, 120); -yn = nodes(0, 0.1, 120); -zn = nodes(0, 0.003, 4); - -% Expand dx, dy and dz over whole domain -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - -% Resolution ranges -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% Set physical properties -[prop.rho, ... - prop.mu, ... - prop.cap, ... - prop.lambda] = air_properties(1:nx, 1:ny, 1:nz); - -% time-stepping parameters -dt = 0.0005; % time steps -ndt = 1000; % number of time steps - -% create unknowns; names, positions, sizes and default boundary conditions -uf = create_unknown('face-u-vel', X, r.u, 'd'); -vf = create_unknown('face-v-vel', Y, r.v, 'd'); -wf = create_unknown('face-w-vel', Z, r.w, 'd'); -p = create_unknown('pressure', C, r.c, 'n'); - -uf.bnd(B).type(:,:,1) = 'n'; -uf.bnd(T).type(:,:,1) = 'n'; -vf.bnd(B).type(:,:,1) = 'n'; -vf.bnd(T).type(:,:,1) = 'n'; -wf.bnd(B).type(:,:,1) = 'n'; -wf.bnd(T).type(:,:,1) = 'n'; - -p = adj_n_bnds(p); - -% Create a disc -obst = ones(r.c); -for k=1:nz - for j=1:ny - for i=1:nx - dist = sqrt( (j-ny/2)^2 + (i-nx/2)^2 ); - if dist < 0.52 * ny - obst(i,j,k) = 0; - end - end - end -end - -% Specify boundary conditions -for k=1:nz - uf.bnd(W).val (1, 3*ny/8+1:5*ny/8, k) = +avg(par(0.5,ny/4+1)); - uf.bnd(E).type(1, 3*ny/8+1:5*ny/8, k) = 'o'; - vf.bnd(S).type(3*nx/8+1:5*nx/8, 1, k) = 'o'; - vf.bnd(N).type(3*nx/8+1:5*nx/8, 1, k) = 'o'; -end - -%========================================================================== -% -% Solution algorithm -% -%========================================================================== - -%----------- -% -% Time loop -% -%----------- -for ts=1:ndt - - disp_time_step(ts); - - %---------- - % Momentum - %---------- - [uf, vf, wf, uf, vf, wf] = ... - calc_uvw(uf, vf, wf, uf, vf, wf, ... - prop.rho, prop.mu, ... - zeros(r.c), ... - zeros(r.u), zeros(r.v), zeros(r.w), ... - dt, ts, dx, dy, dz, obst); - - %---------- - % Pressure - %---------- - p = calc_p(p, uf, vf, wf, ... % variable and advection velocity - prop.rho, ... % density - dt, dx, dy, dz, obst); % numerical domain - - %--------------------- - % Velocity correction - %--------------------- - [uf,vf,wf] = corr_uvw(uf,vf,wf, p, prop.rho, dt, dx,dy,dz, obst); - - % Compute the source for pressure again to check mass error - err = vol_balance(uf,vf,wf, dx,dy,dz, obst); - disp( sprintf('maximum mass error after correction = %12.5e', ... - max(max(max(abs(err)))))); - - cfl = cfl_max( uf, vf, wf, dt, dx, dy, dz ); - disp( sprintf('cfl max = %5.3f', cfl ) ); - -%========================================================================== -% -% Visualisation -% -%========================================================================== - - %----------------------- - % Plot in Matlab format - %----------------------- - if mod(ts,10) == 0 - kp = 2; - xp = avg(xn); - yp = avg(yn); - up = avg(X, cat(X, uf.bnd(W).val, uf.val, uf.bnd(E).val)); - vp = avg(Y, cat(Y, vf.bnd(S).val, vf.val, vf.bnd(N).val)); - subplot(1,2,1) - [cnt,hnd] = contourf(xp,yp,p.val(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 4, 'k-'); - hold off; - axis equal - title([sprintf('Pressure correction at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - subplot(1,2,2) - [cnt,hnd] = contourf(xp, yp, sqrt([ up(:,:,kp)'.*up(:,:,kp)' ... - + vp(:,:,kp)'.*vp(:,:,kp)'])); - hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 4, 'k-'); - hold off; - axis equal - title([sprintf('Velocity magnitude at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - end -end diff --git a/MATLAB/Tests/test_inlet_outlet.m b/MATLAB/Tests/test_inlet_outlet.m deleted file mode 100644 index b4998c3..0000000 --- a/MATLAB/Tests/test_inlet_outlet.m +++ /dev/null @@ -1,258 +0,0 @@ -%========================================================================== -% This scripts tests inlet and outlet conditons at various places in -% computational domain. -% -% Computational domain is a simple box, and Reynolds number is rather -% small to avoid instabilities due to vortices getting out from the -% outlet. The script selects the case it will run randomply, from the -% 16 predefined cases. -%-------------------------------------------------------------------------- -clear; - -tests = [11:14,21:24,31:34,41:44]; -TEST = tests( ceil(rand*16) ); - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution -xn = nodes(0, 1, 160); -yn = nodes(0, 1, 160); -zn = nodes(0, 0.025, 4); - -% Expand dx, dy and dz over whole domain -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - -% Resolution ranges -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% set physical properties -[prop.rho, ... - prop.mu, ... - prop.cap, ... - prop.lambda] = air_properties(1:nx, 1:ny, 1:nz); - - -% time-stepping parameters -dt = 0.15; % time steps -ndt = 200; % number of time steps - -% create unknowns; names, positions, sizes and default boundary conditions -uf = create_unknown('face-u-vel', X, r.u, 'd'); -vf = create_unknown('face-v-vel', Y, r.v, 'd'); -wf = create_unknown('face-w-vel', Z, r.w, 'd'); -p = create_unknown('pressure', C, r.c, 'n'); - -uf.bnd(B).type(:,:,1) = 'n'; -uf.bnd(T).type(:,:,1) = 'n'; -vf.bnd(B).type(:,:,1) = 'n'; -vf.bnd(T).type(:,:,1) = 'n'; -wf.bnd(B).type(:,:,1) = 'n'; -wf.bnd(T).type(:,:,1) = 'n'; - -p = adj_n_bnds(p); - -% Create a cylindrical obstacle in the middle just for kicks -obst = zeros(r.c); -for k=1:nz - for j=1:ny - for i=1:nx - dist = sqrt( (j-ny/2)^2 + (i-nx/2)^2 ); - if dist < ny/4 - obst(i,j,k) = 1; - end - end - end -end - -% specify boundary conditions -if TEST == 11 - for k=1:nz - uf.bnd(W).val (1,ny/4+1:3*ny/4,k) = +avg(par(0.01,ny/2+1)); - uf.bnd(E).type(1,ny/4+1:3*ny/4,k) = 'o'; - end -elseif TEST == 12 % vertical mirror from 11 - for k=1:nz - uf.bnd(E).val (1,ny/4+1:3*ny/4,k) = -avg(par(0.01,ny/2+1)); - uf.bnd(W).type(1,ny/4+1:3*ny/4,k) = 'o'; - end -elseif TEST == 13 % rotate 11 - for k=1:nz - vf.bnd(S).val (nx/4+1:3*nx/4,1,k) = +avg(par(0.01,nx/2+1)); - vf.bnd(N).type(nx/4+1:3*nx/4,1,k) = 'o'; - end -elseif TEST == 14 % horizontal mirror 13 - for k=1:nz - vf.bnd(N).val (nx/4+1:3*nx/4,1,k) = -avg(par(0.01,nx/2+1)); - vf.bnd(S).type(nx/4+1:3*nx/4,1,k) = 'o'; - end -elseif TEST == 21 % 2 exits - for k=1:nz - uf.bnd(W).val (1, ny/4+1:3*ny/4,k) = +avg(par(0.01,ny/2+1)); - uf.bnd(E).type(1, 1:ny/4+1,k) = 'o'; - uf.bnd(E).type(1,3*ny/4+1:ny, k) = 'o'; - end -elseif TEST == 22 % vertical mirror 21 - for k=1:nz - uf.bnd(E).val (1, ny/4+1:3*ny/4,k) = -avg(par(0.01,ny/2+1)); - uf.bnd(W).type(1, 1:ny/4+1,k) = 'o'; - uf.bnd(W).type(1,3*ny/4+1:ny, k) = 'o'; - end -elseif TEST == 23 % rotated 21 - for k=1:nz - vf.bnd(S).val ( nx/4+1:3*nx/4,1,k) = +avg(par(0.01,nx/2+1)); - vf.bnd(N).type( 1:nx/4+1,1,k) = 'o'; - vf.bnd(N).type(3*nx/4+1:nx, 1,k) = 'o'; - end -elseif TEST == 24 % horizontal mirror of 23 - for k=1:nz - vf.bnd(N).val ( nx/4+1:3*nx/4,1,k) = -avg(par(0.01,nx/2+1)); - vf.bnd(S).type( 1:nx/4+1,1,k) = 'o'; - vf.bnd(S).type(3*nx/4+1:nx, 1,k) = 'o'; - end -elseif TEST == 31 % inlet and outlet at the same face - for k=1:nz - uf.bnd(W).val (1,3*ny/4+1:ny, k) = +avg(par(0.01,ny/4+1)); - uf.bnd(W).type(1, 1:ny/4,k) = 'o'; - end -elseif TEST == 32 % vertical mirror of 31 - for k=1:4 - uf.bnd(E).val (1,3*ny/4+1:ny, k) = -avg(par(0.01,ny/4+1)); - uf.bnd(E).type(1, 1:ny/4,k) = 'o'; - end -elseif TEST == 33 % rotated 31 - for k=1:4 - vf.bnd(S).val (3*nx/4+1:nx, 1,k) = +avg(par(0.01,nx/4+1)); - vf.bnd(S).type( 1:nx/4,1,k) = 'o'; - end -elseif TEST == 34 % horizontal mirror of 33 - for k=1:4 - vf.bnd(N).val (3*nx/4+1:nx, 1,k) = -avg(par(0.01,nx/4+1)); - vf.bnd(N).type( 1:nx/4,1,k) = 'o'; - end -elseif TEST == 41 % inlet and outlet at the same face, one more outlet - for k=1:4 - uf.bnd(W).val (1,3*ny/4+1:ny, k) = +avg(par(0.01,ny/4+1)); - uf.bnd(W).type(1, 1:ny/8,k) = 'o'; - uf.bnd(E).type(1, 1:ny/8,k) = 'o'; - end -elseif TEST == 42 % vertical mirror of 41 - for k=1:4 - uf.bnd(E).val (1,3*ny/4+1:ny, k) = -avg(par(0.01,ny/4+1)); - uf.bnd(E).type(1, 1:ny/8,k) = 'o'; - uf.bnd(W).type(1, 1:ny/8,k) = 'o'; - end -elseif TEST == 43 % rotated 41 - for k=1:4 - vf.bnd(S).val (3*nx/4+1:nx, 1,k) = +avg(par(0.01,nx/4+1)); - vf.bnd(S).type( 1:nx/8,1,k) = 'o'; - vf.bnd(N).type( 1:nx/8,1,k) = 'o'; - end -elseif TEST == 44 % horizontal mirror of 43 - for k=1:4 - vf.bnd(N).val (3*ny/4+1:nx, 1,k) = -avg(par(0.01,nx/4+1)); - vf.bnd(N).type( 1:nx/8,1,k) = 'o'; - vf.bnd(S).type( 1:nx/8,1,k) = 'o'; - end -end - -%========================================================================== -% -% Solution algorithm -% -%========================================================================== - -%----------- -% -% time loop -% -%----------- -for ts=1:ndt - - disp_time_step(ts); - - %---------- - % Momentum - %---------- - [uf, vf, wf, uf, vf, wf] = ... - calc_uvw(uf, vf, wf, uf, vf, wf, ... - prop.rho, prop.mu, ... - zeros( r.c ), ... - zeros( r.u ), zeros( r.v ), zeros( r.w ), ... - dt, ts, dx, dy, dz, obst); - - %---------- - % Pressure - %---------- - p = calc_p(p, uf, vf, wf, ... % variable and advection velocity - prop.rho, ... % density - dt, dx, dy, dz, obst); % numerical domain - - %--------------------- - % Velocity correction - %--------------------- - [uf, vf, wf] = corr_uvw(uf,vf,wf, p, prop.rho, dt, dx,dy,dz, obst); - - % Compute the source for pressure again to check mass error - err = vol_balance(uf,vf,wf, dx,dy,dz, obst); - disp( sprintf('maximum mass error after correction = %12.5e', ... - max(max(max(abs(err)))))); - - cfl = cfl_max( uf, vf, wf, dt, dx, dy, dz ); - disp( sprintf('cfl max = %5.3f', cfl ) ); - -%========================================================================== -% -% Visualisation -% -%========================================================================== - - %---------------- - % Plot in Matlab - %---------------- - if mod(ts,10) == 0 - kp = 2; - xp = avg(xn); - yp = avg(yn); - up = avg(X, cat(X, uf.bnd(W).val, uf.val, uf.bnd(E).val)); - vp = avg(Y, cat(Y, vf.bnd(S).val, vf.val, vf.bnd(N).val)); - subplot(1,2,1) - [cnt,hnd] = contourf(xp,yp,p.val(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 4, 'k-'); - hold off; - axis equal - title([sprintf('Test %2d: ', TEST), ... - sprintf('Pressure correction at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - subplot(1,2,2) - [cnt,hnd] = contourf(xp, yp, sqrt( [up(:,:,kp)'.*up(:,:,kp)' ... - + vp(:,:,kp)'.*vp(:,:,kp)'])); - hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 4, 'k-'); - hold off; - axis equal - title([sprintf('Test %2d: ', TEST), ... - sprintf('Velocity magnitude at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - end -end diff --git a/MATLAB/Tests/test_membrane.m b/MATLAB/Tests/test_membrane.m deleted file mode 100644 index ef66fbb..0000000 --- a/MATLAB/Tests/test_membrane.m +++ /dev/null @@ -1,279 +0,0 @@ -%========================================================================== -% Demonstrates the membrane for Kerstin. Two domains are computed -% independently, but linked through boundary conditions in an inner loop -% within each time step. This seems the most practical approach of all -% because the membrane model implementations are very obvious, at one -% place, in the main function. The convergence of the conditions at the -% membrane seems to be rather fast too. -%-------------------------------------------------------------------------- -clear -clc; - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%------------------ -% Phase indicators -%------------------ -AIR = 1 -H2O = 2 - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution for separate domains -x(AIR).nod = nodes(0, 0.1, 80); -y(AIR).nod = nodes(0, 0.01, 20); -z(AIR).nod = nodes(0, 0.1, 80); - -x(H2O).nod = x(AIR).nod; -y(H2O).nod = nodes(0.01, 0.03, 30); -z(H2O).nod = z(AIR).nod; - -% Expand dx, dy and dz over whole domain -for c=AIR:H2O - [del(c).x del(c).y del(c).z ... - ts(c).x ts(c).y ts(c).z] = cartesian_grid(x(c).nod,y(c).nod,z(c).nod); -end - -% Resolution ranges -for c=AIR:H2O - r(c).c = [ts(c).x ts(c).y ts(c).z ]; - r(c).u = [ts(c).x-1 ts(c).y ts(c).z ]; - r(c).v = [ts(c).x ts(c).y-1 ts(c).z ]; - r(c).w = [ts(c).x ts(c).y ts(c).z-1]; -end - -% Set physical properties for separate domains -[prop(AIR).rho, ... - prop(AIR).mu, ... - prop(AIR).cp, ... - prop(AIR).lambda] = air_properties( 1:ts(AIR).x, 1:ts(AIR).y, 1:ts(AIR).z ); - -[prop(H2O).rho, ... - prop(H2O).mu, ... - prop(H2O).cp, ... - prop(H2O).lambda] = water_properties( 1:ts(H2O).x, 1:ts(H2O).y, 1:ts(H2O).z ); - -% Time-stepping parameters -dt = 0.001; % time step -ndt = 200; % number of time steps - -% Create unknowns; names, positions, sizes and default boundary conditions -for c=AIR:H2O - u(c) = create_unknown('u-velocity', X, r(c).u, 'd'); - v(c) = create_unknown('v-velocity', Y, r(c).v, 'd'); - w(c) = create_unknown('w-velocity', Z, r(c).w, 'd'); - t(c) = create_unknown('temperature', C, r(c).c, 'n'); - p(c) = create_unknown('pressure', C, r(c).c, 'n'); - p_tot(c) = create_unknown('total-pressure', C, r(c).c, 'n'); -end - -% Specific boundary conditions -for k=1:ts(AIR).z - v(AIR).bnd(N).val(:,1,k)=-0.005; -end -u(AIR).bnd(E).type(1,:,:)='o'; -u(AIR).bnd(E).val (1,:,:)=0.1; - -for k=1:ts(H2O).z - u(H2O).bnd(W).val(1,:,k)=avg(par(0.1, ts(H2O).y+1)); -end -u(H2O).bnd(E).type(1,:,:)='o'; -u(H2O).bnd(E).val (1,:,:)=0.1; - -for c=AIR:H2O - u(c).bnd(B).type(:,:,1) = 'n'; - u(c).bnd(T).type(:,:,1) = 'n'; - v(c).bnd(B).type(:,:,1) = 'n'; - v(c).bnd(T).type(:,:,1) = 'n'; - w(c).bnd(B).type(:,:,1) = 'n'; - w(c).bnd(T).type(:,:,1) = 'n'; -end - -for c=1:H2O - p(c) = adj_n_bnds(p(c)); -end - -t(H2O).bnd(W).type(1,:,:) = 'd'; t(H2O).bnd(W).val (1,:,:) = 80; -t(AIR).bnd(S).type(:,1,:) = 'd'; t(AIR).bnd(S).val (:,1,:) = 60; -t(H2O).bnd(S).type(:,1,:) = 'd'; t(H2O).bnd(S).val (:,1,:) = 70; -t(AIR).bnd(N).type(:,1,:) = 'd'; t(AIR).bnd(N).val (:,1,:) = 70; - -t(H2O).val(:,:,:) = 70; -t(AIR).val(:,:,:) = 50; - -obst = []; - -%========================================================================== -% -% Solution algorithm -% -%========================================================================== - -%----------- -% -% Time loop -% -%----------- -for ts = 1:ndt - - disp_time_step(ts); - - %------------------------ - % Temperature (enthalpy) - %------------------------ - for c=AIR:H2O - t(c).old = t(c).val; - end - - % Initialize temperatures of the membrane - const = prop(H2O).lambda(:, 1,:) .* del(AIR).y(:,end,:) ... - ./ prop(AIR).lambda(:,end,:) ./ del(H2O).y(:, 1,:); - t_mem_old = (const.*t(H2O).val(:,1,:)+t(AIR).val(:,end,:)) ./ (1+const); - - while 1 - - for c=AIR:H2O - t(c) = calc_t(t(c), u(c),v(c),w(c), ... - prop(c).rho .* prop(c).cp, ... - prop(c).lambda, ... - dt, ts, del(c).x,del(c).y,del(c).z, obst); - end - - % Compute new temperature of the membrane - const = prop(H2O).lambda(:, 1,:) .* del(AIR).y(:,end,:) ... - ./ prop(AIR).lambda(:,end,:) ./ del(H2O).y(:, 1,:); - t_mem = (const.*t(H2O).val(:,1,:)+t(AIR).val(:,end,:)) ./ (1+const); - - % Update boundary conditions with membrane's temperature - t(H2O).bnd(S).val (:,1,:) = t_mem; - t(AIR).bnd(N).val (:,1,:) = t_mem; - - % Check if convergence has been reached - eps = max(max(abs(t_mem-t_mem_old))); - disp( sprintf('eps max = %5.3e', eps ) ); - if eps < TOL - break - end - - t_mem_old = t_mem; - end - - %---------- - % Momentum - %---------- - - for c=AIR:H2O - - % Gravity term for momentum - g_v = - G * avg(Y, prop(c).rho) * min(ts/100,1); - - [u(c),v(c),w(c)] = calc_uvw(u(c),v(c),w(c), u(c),v(c),w(c), ... - prop(c).rho, prop(c).mu, ... - p_tot(c).val, ... - zeros(r(c).u), g_v, zeros(r(c).w), ... - dt, ts, del(c).x,del(c).y,del(c).z, obst); - end - - %---------- - % Pressure - %---------- - for c=AIR:H2O - - p(c) = calc_p(p(c), u(c),v(c),w(c), ... - prop(c).rho, ... - dt, del(c).x,del(c).y,del(c).z, obst); - - p_tot(c).val = p_tot(c).val + p(c).val; - end - - %--------------------- - % Velocity correction - %--------------------- - for c=AIR:H2O - - [u(c),v(c),w(c)] = corr_uvw(u(c),v(c),w(c), p(c), ... - prop(c).rho, ... - dt, del(c).x,del(c).y,del(c).z, obst); - - % Compute the source for pressure again to check mass error - err = vol_balance(u(c),v(c),w(c), del(c).x,del(c).y,del(c).z, obst); - disp( sprintf('maximum mass error after correction = %12.5e', ... - max(max(max(abs(err)))))); - - cfl = cfl_max(u(c),v(c),w(c), dt, del(c).x,del(c).y,del(c).z); - disp( sprintf('cfl max = %5.3f', cfl ) ); - - end - -%========================================================================== -% -% Visualisation -% -%========================================================================== - - if mod(ts,20) == 0 - - %------------------------- - % Plot to Matlab's figure - %------------------------- - kp = 3; - - % Catenate coordinates - xp = avg(x(AIR).nod); - yp = cat(2, avg(y(AIR).nod), avg(y(H2O).nod)); - - for c=AIR:H2O - up(c).c = avg(X, cat(X, u(c).bnd(W).val, u(c).val, u(c).bnd(E).val)); - vp(c).c = avg(Y, cat(Y, v(c).bnd(S).val, v(c).val, v(c).bnd(N).val)); - end - - up_c = cat(2, up(AIR).c, up(H2O).c ); - vp_c = cat(2, vp(AIR).c, vp(H2O).c ); - - tp = cat(2, t(AIR).val, t(H2O).val); - pp = cat(2, p_tot(AIR).val, p_tot(H2O).val); - - subplot(2,1,1) - [cnt,hnd] = contourf(xp, yp, tp(:,:,kp)', linspace(49.999,80.001,10) ); - hold on; -% set(h,'ShowText','on','TextStep',get(h,'LevelStep')*2); - quiver(xp, yp, up_c(:,:,kp)', vp_c(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Temperature at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - subplot(2,1,2) - [cnt,hnd] = contourf(xp, yp, pp(:,:,kp)'); - hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up_c(:,:,kp)', vp_c(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Pressure correction at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - - %-------------------------- - % Export to Tecplot format - %-------------------------- -% container.var(1:4) = [u(AIR), v(AIR), w(AIR), p(AIR)]; -% file_name = sprintf('results-%6.6d.dat', n); -% export_tecplot(file_name, container, r(AIR).c, [dx(AIR) dy(AIR) dz(AIR)]); - - end -end - - diff --git a/MATLAB/Tests/test_obstacles_collocated.m b/MATLAB/Tests/test_obstacles_collocated.m deleted file mode 100644 index 64c4179..0000000 --- a/MATLAB/Tests/test_obstacles_collocated.m +++ /dev/null @@ -1,195 +0,0 @@ -%========================================================================== -% o ... scalars -% (n) - ... u velocities -% | ... v velocities -% +-------+-------+-------+-------+-------+ -% | | | | | | -% | o - o - o - o - o | j=ny -% | | | | | | -% +---|---+---|---+---|---+---|---+---|---+ j=nym -% | | | | | | -% | o - o - o - o - o | ... -% | | | | | | -% (w) +---|---+---|---+---|---+---|---+---|---+ j=2 (e) -% | | | | | | -% | o - o - o - o - o | j=2 -% | | | | | | -% +---|---+---|---+---|---+---|---+---|---+ j=1 (v-velocity) -% | | | | | | -% | o - o - o - o - o | j=1 (scalar cell) -% | | | | | | -% +-------+-------+-------+-------+-------+ -% y i=1 i=2 ... ... i=nx (scalar cells) -% ^ i=1 i=2 ... i=nxm (u-velocity cells) -% | -% +---> x (s) -% -%-------------------------------------------------------------------------- -clear; - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution -xn = nodes(0, 1, 256); -yn = nodes(0, 0.125, 32); -zn = nodes(0, 0.125, 4); - -% Expand dx, dy and dz over whole domain -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - -% Resolution ranges -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% Set physical properties -[rho, mu, cap, lambda] = air_properties(1:nx, 1:ny, 1:nz); - -% Time-stepping parameters -dt = 0.003; % time steps -ndt = 5000; % number of time steps - -% Create unknowns; names, positions, sizes and default boundary conditions -uc = create_unknown('u-velocity', C, r.c, 'd'); -vc = create_unknown('v-velocity', C, r.c, 'd'); -wc = create_unknown('w-velocity', C, r.c, 'd'); -uf = create_unknown('face-u-vel', X, r.u, 'd'); -vf = create_unknown('face-v-vel', Y, r.v, 'd'); -wf = create_unknown('face-w-vel', Z, r.w, 'd'); -p = create_unknown('pressure', C, r.c, 'n'); - -% Specify boundary conditions -for k=1:nz - uc.bnd(W).val(1,:,k)=avg(par(0.1, ny+1)); -end -uc.bnd(E).type(1,:,:) = 'o'; - -uc.bnd(B).type(:,:,1) = 'n'; -uc.bnd(T).type(:,:,1) = 'n'; -vc.bnd(B).type(:,:,1) = 'n'; -vc.bnd(T).type(:,:,1) = 'n'; -wc.bnd(B).type(:,:,1) = 'n'; -wc.bnd(T).type(:,:,1) = 'n'; - -p = adj_n_bnds(p); - -% Copy the values to face velocities -uf.val = avg(X, uc.val); uf.bnd = uc.bnd; -vf.val = avg(Y, vc.val); vf.bnd = vc.bnd; -wf.val = avg(Z, wc.val); wf.bnd = wc.bnd; - -% Create a slanted obstacle in the flow domain -obst = zeros(r.c); -for o=1:4 - for j=1:3*ny/4; - for i=nx/4+j:nx/4+3*ny/4; - for k=1:nz - obst(i,j,k) = 1; - end - end - end -end - -%----------- -% -% time loop -% -%----------- -for ts = 1:ndt - - disp_time_step(ts); - - %---------- - % Momentum - %---------- - [uc,vc,wc, uf,vf,wf] = calc_uvw(uc,vc,wc, uf,vf,wf, ... - rho, mu, ... - zeros(r.c), ... - zeros(r.c), zeros(r.c), zeros(r.c), ... - dt, ts, dx,dy,dz, obst); - - %---------- - % Pressure - %---------- - p = calc_p(p, uf,vf,wf, ... % variable and advection velocity - rho, ... % density - dt, dx, dy, dz, obst); % numerical domain - - %--------------------- - % Velocity correction - %--------------------- - - % Correct the cell centered velocites - [uc,vc,wc] = corr_uvw(uc,vc,wc, p, rho, dt, dx,dy,dz, obst); - - % Correct face velocities in staggered fashion - [uf,vf,wf] = corr_uvw(uf,vf,wf, p, rho, dt, dx,dy,dz, obst); - - % Compute the source for pressure again to check mass error - err = vol_balance(uf,vf,wf, dx,dy,dz, obst); - disp( sprintf('maximum mass error after correction = %12.5e', ... - max(max(max(abs(err)))))); - - cfl = cfl_max(uc,vc,wc, dt, dx,dy,dz); - disp( sprintf('cfl max = %5.3f', cfl ) ); - - %---------------- - % Plot in Matlab - %---------------- - if mod(ts,20) == 0 - kp = 2; - xp = avg(xn); - yp = avg(yn); - up = uc.val; - vp = vc.val; - - subplot(2,1,1) -% [cnt,hnd] = contourf(xp, yp, p.val(:,:,kp)'); hold on; - [cnt,hnd] = contourf(xp, yp, err(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Pressure correction at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - subplot(2,1,2) - [cnt,hnd] = contourf(xp, yp, sqrt( [up(:,:,kp)'.*up(:,:,kp)' ... - + vp(:,:,kp)'.*vp(:,:,kp)'])); - hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Velocity magnitude at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - end - - %-------------------------- - % Export to Tecplot format - %-------------------------- - if mod(ts,200) == 0 - container.var(1:4) = [uc vc wc p]; - file_name = sprintf('results-obstacles-collocated-%6.6d.dat', ts); - export_tecplot(file_name, container, r.c, xn, yn, zn); - end - -end - - diff --git a/MATLAB/Tests/test_obstacles_staggered.m b/MATLAB/Tests/test_obstacles_staggered.m deleted file mode 100644 index f6a1a35..0000000 --- a/MATLAB/Tests/test_obstacles_staggered.m +++ /dev/null @@ -1,179 +0,0 @@ -%========================================================================== -% o ... scalars -% (n) - ... u velocities -% | ... v velocities -% +-------+-------+-------+-------+-------+ -% | | | | | | -% | o - o - o - o - o | j=ny -% | | | | | | -% +---|---+---|---+---|---+---|---+---|---+ j=nym -% | | | | | | -% | o - o - o - o - o | ... -% | | | | | | -% (w) +---|---+---|---+---|---+---|---+---|---+ j=2 (e) -% | | | | | | -% | o - o - o - o - o | j=2 -% | | | | | | -% +---|---+---|---+---|---+---|---+---|---+ j=1 (v-velocity) -% | | | | | | -% | o - o - o - o - o | j=1 (scalar cell) -% | | | | | | -% +-------+-------+-------+-------+-------+ -% y i=1 i=2 ... ... i=nx (scalar cells) -% ^ i=1 i=2 ... i=nxm (u-velocity cells) -% | -% +---> x (s) -% -%-------------------------------------------------------------------------- -clear; - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution -xn = nodes(0, 1, 256); -yn = nodes(0, 0.125, 32); -zn = nodes(0, 0.125, 4); - -% Expand dx, dy and dz over whole domain -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - -% Resolution ranges -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% set physical properties -[rho, mu, cap, lambda] = air_properties(1:nx, 1:ny, 1:nz); - -% time-stepping parameters -dt = 0.003; % time steps -ndt = 5000; % number of time steps - -% create unknowns; names, positions, sizes and default boundary conditions -uf = create_unknown('u-velocity', X, r.u, 'd'); -vf = create_unknown('v-velocity', Y, r.v, 'd'); -wf = create_unknown('w-velocity', Z, r.w, 'd'); -p = create_unknown('pressure', C, r.c, 'n'); - -% specify boundary conditions -for k=1:nz - uf.bnd(W).val(1,:,k)=avg(par(0.1, ny+1)); -end -uf.bnd(E).type(1,:,:) = 'o'; - -uf.bnd(B).type(:,:,1) = 'n'; -uf.bnd(T).type(:,:,1) = 'n'; -vf.bnd(B).type(:,:,1) = 'n'; -vf.bnd(T).type(:,:,1) = 'n'; -wf.bnd(B).type(:,:,1) = 'n'; -wf.bnd(T).type(:,:,1) = 'n'; - -p = adj_n_bnds(p); - -obst = zeros( r.c ); -for o=1:4 - for j=1:3*ny/4; - for i=nx/4+j:nx/4+3*ny/4; - for k=1:nz - obst(i,j,k) = 1; - end - end - end -end - -%----------- -% -% Time loop -% -%----------- -for ts = 1:ndt - - disp_time_step(ts); - - %---------- - % Momentum - %---------- - [uf,vf,wf, uf,vf,wf] = calc_uvw(uf,vf,wf, uf,vf,wf, ... - rho, mu, ... - zeros(r.c), ... - zeros(r.u), zeros(r.v), zeros(r.w), ... - dt, ts, dx, dy, dz, obst); - - %---------- - % Pressure - %---------- - p = calc_p(p, uf, vf, wf, ... % variable and advection velocity - rho, ... % density - dt, dx, dy, dz, obst); % numerical domain - - %--------------------- - % Velocity correction - %--------------------- - [uf, vf, wf] = corr_uvw(uf, vf, wf, p, rho, dt, dx, dy, dz, obst); - - % Compute the source for pressure again to check mass error - err = vol_balance(uf,vf,wf, dx,dy,dz, obst); - disp( sprintf('maximum mass error after correction = %12.5e', ... - max(max(max(abs(err)))))); - - cfl = cfl_max( uf, vf, wf, dt, dx, dy, dz ); - disp( sprintf('cfl max = %5.3f', cfl ) ); - - %---------------- - % Plot in Matlab - %---------------- - if mod(ts,20) == 0 - k_plot = 2; - xp = avg(xn); - yp = avg(yn); - up = avg(X, cat(X, uf.bnd(W).val, uf.val, uf.bnd(E).val)); - vp = avg(Y, cat(Y, vf.bnd(S).val, vf.val, vf.bnd(N).val)); - - subplot(2,1,1) - [cnt,hnd] = contourf(xp,yp,p.val(:,:,k_plot)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,k_plot)', vp(:,:,k_plot)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Pressure correction at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - subplot(2,1,2) - [cnt,hnd] = contourf(xp, yp, sqrt([up(:,:,k_plot)'.*up(:,:,k_plot)' ... - + vp(:,:,k_plot)'.*vp(:,:,k_plot)'])); - hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,k_plot)', vp(:,:,k_plot)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Velocity magnitude at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - end - - %-------------------------- - % Export to Tecplot format - %-------------------------- - if mod(ts,200) == 0 - container.var(1:4) = [uf vf wf p]; - file_name = sprintf('results-obstacles-staggered-%6.6d.dat', ts); - export_tecplot(file_name, container, r.c, xn, yn, zn); - end - -end - diff --git a/MATLAB/Tests/test_obstacles_thinner.m b/MATLAB/Tests/test_obstacles_thinner.m deleted file mode 100644 index d6d8826..0000000 --- a/MATLAB/Tests/test_obstacles_thinner.m +++ /dev/null @@ -1,219 +0,0 @@ -%========================================================================== -% o ... scalars -% (n) - ... u velocities -% | ... v velocities -% +-------+-------+-------+-------+-------+ -% | | | | | | -% | o - o - o - o - o | j=ny -% | | | | | | -% +---|---+---|---+---|---+---|---+---|---+ j=nym -% | | | | | | -% | o - o - o - o - o | ... -% | | | | | | -% (w) +---|---+---|---+---|---+---|---+---|---+ j=2 (e) -% | | | | | | -% | o - o - o - o - o | j=2 -% | | | | | | -% +---|---+---|---+---|---+---|---+---|---+ j=1 (v-velocity) -% | | | | | | -% | o - o - o - o - o | j=1 (scalar cell) -% | | | | | | -% +-------+-------+-------+-------+-------+ -% y i=1 i=2 ... ... i=nx (scalar cells) -% ^ i=1 i=2 ... i=nxm (u-velocity cells) -% | -% +---> x (s) -% -%-------------------------------------------------------------------------- -clear; - -%------------------------------ -% set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%---------------- -% define problem -%---------------- - -% Set domain dimensions and grid resolution -xn = nodes(0, 1.25, 256); -yn = nodes(0, 0.125, 32); -zn = nodes(0, 0.125, 32); - -% Expand dx, dy and dz over whole domain -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - -% Resolution ranges -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% set physical properties -[rho, mu, cap, lambda] = air_properties(1:nx, 1:ny, 1:nz); - -% time-stepping parameters -dt = 0.005; % time steps -ndt = 2; % number of time steps - -% create unknowns; names, positions, sizes and default boundary conditions -uf = create_unknown('u-velocity', X, r.u, 'd'); -vf = create_unknown('v-velocity', Y, r.v, 'd'); -wf = create_unknown('w-velocity', Z, r.w, 'd'); -p = create_unknown('pressure', C, r.c, 'n'); -p_tot = zeros(r.c); - -% specify boundary conditions -for k=1:nz - uf.bnd(W).val(1,:,k)=avg(par(0.1, ny+1)); -end -uf.bnd(E).type(1,:,:) = 'o'; - -uf.bnd(B).type(:,:,1) = 'n'; -uf.bnd(T).type(:,:,1) = 'n'; -vf.bnd(B).type(:,:,1) = 'n'; -vf.bnd(T).type(:,:,1) = 'n'; -wf.bnd(B).type(:,:,1) = 'n'; -wf.bnd(T).type(:,:,1) = 'n'; - -p = adj_n_bnds(p); - -% create obstacles -th = 5; -block(1).im = 3*nx/16; % i minus -block(1).ip = block(1).im + th; % i plus -block(1).jm = 1; % j minus -block(1).jp = 3*ny/4; % j plus -block(1).km = 1; % k minus -block(1).kp = 3*ny/4; % k plus - -block(2).im = 5*nx/16; % i minus -block(2).ip = block(2).im + th; % i plus -block(2).jm = ny/4 + 1; % j minus -block(2).jp = ny; % j plus -block(2).km = ny/4 + 1; % k minus -block(2).kp = ny; % k plus - -block(3).im = 7*nx/16; % i minus -block(3).ip = block(3).im + th; % i plus -block(3).jm = 1; % j minus -block(3).jp = 3*ny/4; % j plus -block(3).km = 1; % k minus -block(3).kp = 3*ny/4; % k plus - -block(4).im = 9*nx/16; % i minus -block(4).ip = block(4).im + th; % i plus -block(4).jm = ny/4 + 1; % j minus -block(4).jp = ny; % j plus -block(4).km = ny/4 + 1; % k minus -block(4).kp = ny; % k plus - -obst = zeros(nx,ny,nz); -for o=1:4 - for i=block(o).im:block(o).ip - for j=block(o).jm:block(o).jp - for k=block(o).km:block(o).kp - obst(i,j,k) = 1; - end - end - end -end - -%----------- -% -% Time loop -% -%----------- -for ts = 1:ndt - - disp_time_step(ts); - - %---------- - % Momentum - %---------- - [uf,vf,wf, uf,vf,wf] = calc_uvw(uf,vf,wf, uf,vf,wf, ... - rho, mu, ... - p_tot, ... - zeros(r.u), zeros(r.v), zeros(r.w), ... - dt, ts, dx,dy,dz, obst); - - %---------- - % Pressure - %---------- - p = calc_p(p, uf,vf,wf, ... % variable and advection velocity - rho, ... % density - dt, dx,dy,dz, obst); % numerical domain - - p_tot = p_tot + p.val; - - %--------------------- - % Velocity correction - %--------------------- - [uf,vf,wf] = corr_uvw(uf,vf,wf, p, rho, dt, dx,dy,dz, obst); - - % Compute the source for pressure again to check mass error - err = vol_balance(uf,vf,wf, dx,dy,dz, obst); - disp( sprintf('maximum mass error after correction = %12.5e', ... - max(max(max(abs(err)))))); - - cfl = cfl_max( uf,vf,wf, dt, dx,dy,dz ); - disp( sprintf('cfl max = %5.3f', cfl ) ); - - %------ - % Plot - %------ - if mod(ts,10) == 0 - k_plot = 16; - xp = avg(xn); - yp = avg(yn); - up = avg(X, cat(X, uf.bnd(W).val, uf.val, uf.bnd(E).val)); - vp = avg(Y, cat(Y, vf.bnd(S).val, vf.val, vf.bnd(N).val)); - - subplot(3,1,1) - [cnt,hnd] = contourf(xp,yp,p.val(:,:,k_plot)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,k_plot)', vp(:,:,k_plot)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Pressure correction at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - subplot(3,1,2) - [cnt,hnd] = contourf(xp,yp,p_tot(:,:,k_plot)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,k_plot)', vp(:,:,k_plot)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Total pressure at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - subplot(3,1,3) - [cnt,hnd] = contourf(xp,yp,sqrt([up(:,:,k_plot)'.*up(:,:,k_plot)' ... - + vp(:,:,k_plot)'.*vp(:,:,k_plot)'])); - hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,k_plot)', vp(:,:,k_plot)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Velocity magnitude at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - end - - if mod(ts,100) == 0 - %-------------------------- - % Export to Tecplot format - %-------------------------- - container.var(1:4) = [uf vf wf p]; - file_name = sprintf('results-obstacles-%6.6d.dat', ts); - export_tecplot(file_name, container, r.c, xn, yn, zn); - end - -end - diff --git a/MATLAB/Tests/test_p_tot.m b/MATLAB/Tests/test_p_tot.m deleted file mode 100644 index b4104e1..0000000 --- a/MATLAB/Tests/test_p_tot.m +++ /dev/null @@ -1,176 +0,0 @@ -%========================================================================== -% Demonstrates the variation of projection algorythm which computes total -% pressure, as a sum of all pressure corrections. -% -% The total pressure being built up in this way counter-balances the -% gravity term in momentum equations. -% -% It seems that such an approach is important for bouyancy dominated flows. -% -% Gravity term is under-relaxed here, but it works even without it. -%-------------------------------------------------------------------------- -clear -clc; - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution -xn = nodes(0, 10, 80); -yn = nodes(0, 1, 20); -zn = nodes(0, 0.5, 5); - -% Expand dx, dy and dz over whole domain -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - -% Resolution ranges -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% Set physical properties -rho (1:nx,1:ny,1:nz) = 1.25; % density -mu (1:nx,1:ny,1:nz) = 0.1; % viscosity - -% Time-stepping parameters -dt = 0.1; % time step -ndt = 200; % number of time steps - -% Create unknowns; names, positions, sizes and default boundary conditions -uf = create_unknown('u-velocity', X, r.u, 'd'); -vf = create_unknown('v-velocity', Y, r.v, 'd'); -wf = create_unknown('w-velocity', Z, r.w, 'd'); -p = create_unknown('pressure', C, r.c, 'n'); -ptot = zeros( r.c ); - -% Specific boundary conditions -uf.bnd(W).type(1,:,:)='d'; -for k=1:nz - uf.bnd(W).val(1,:,k)=avg(par(0.1, ny+1)); -end -uf.bnd(E).type(1,:,:)='o'; -uf.bnd(E).val (1,:,:)=0.1; - -uf.bnd(B).type(:,:,1) = 'n'; -uf.bnd(T).type(:,:,1) = 'n'; -vf.bnd(B).type(:,:,1) = 'n'; -vf.bnd(T).type(:,:,1) = 'n'; -wf.bnd(B).type(:,:,1) = 'n'; -wf.bnd(T).type(:,:,1) = 'n'; - -p = adj_n_bnds(p); - -obst = []; - -%========================================================================== -% -% Solution algorithm -% -%========================================================================== - -%----------- -% -% Time loop -% -%----------- -for ts = 1:ndt - - disp_time_step(ts); - - %---------- - % Momentum - %---------- - - % Gravity term for momentum - g_v = - G * avg(Y, rho) * min(ts/100,1); - - [uf,vf,wf, uf,vf,wf] = calc_uvw(uf,vf,wf, uf,vf,wf, ... - rho, mu, ... - ptot, ... - zeros(r.u), g_v, zeros(r.w), ... - dt, ts, dx,dy,dz, obst); - - %---------- - % Pressure - %---------- - p = calc_p(p, uf,vf,wf, ... % variable and advection velocity - rho, ... % density - dt, dx,dy,dz, obst); % numerical domain - - ptot = ptot + p.val; - - %--------------------- - % Velocity correction - %--------------------- - [uf,vf,wf] = corr_uvw(uf,vf,wf, p, rho, dt, dx,dy,dz, obst); - - % Compute the source for pressure again to check mass error - err = vol_balance(uf,vf,wf, dx,dy,dz, obst); - disp( sprintf('maximum mass error after correction = %12.5e', ... - max(max(max(abs(err)))))); - - cfl = cfl_max(uf,vf,wf, dt, dx,dy,dz); - disp( sprintf('cfl max = %5.3f', cfl ) ); - -%========================================================================== -% -% Visualisation -% -%========================================================================== - - %------------------------- - % Plot to Matlab's figure - %------------------------- - if mod(ts,20) == 0 - kp = 3; - xp = avg(xn); - yp = avg(yn); - up = avg(X, cat(X, uf.bnd(W).val, uf.val, uf.bnd(E).val)); - vp = avg(Y, cat(Y, vf.bnd(S).val, vf.val, vf.bnd(N).val)); - subplot(2,1,1) - [cnt,hnd] = contourf(xp,yp,ptot(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Total pressureat time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - subplot(2,1,2) - [cnt,hnd] = contourf(xp,yp,p.val(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Pressure correction at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - end - - %-------------------------- - % Export to Tecplot format - %-------------------------- - if mod(ts,100) == 0 - - container.var(1:4) = [uf,vf,wf, p]; - file_name = sprintf('results-%6.6d.dat', ts); - export_tecplot(file_name, container, r.c, xn, yn, zn); - end - -end - - diff --git a/MATLAB/Tests/test_plumes_collocated.m b/MATLAB/Tests/test_plumes_collocated.m deleted file mode 100644 index 249343f..0000000 --- a/MATLAB/Tests/test_plumes_collocated.m +++ /dev/null @@ -1,210 +0,0 @@ -%========================================================================== -% This script is to reproduce two-dimensional mixed convection case, with -% the aim of testing the outflow boundary, particularly the "convective" -% boundary condition which allows eddies to leave the domain. -% -% There is also a staggered version of this script, called -% "demo_plums_collocated.m". It would be good to keep both version as -% similar as possible to each other, to test the differences between -% staggered and collocated arrangements always possible. -%-------------------------------------------------------------------------- -clear -clc; - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution -xn = nodes(0, 10, 300); xc = avg(xn); -yn = nodes(0, 1, 40, 1/500, 1/500); yc = avg(yn); -zn = nodes(0, 3, 3); zc = avg(zn); - -% Expand dx, dy and dz over whole domain -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - -% Resolution ranges -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% Set physical properties -prop.rho (1:nx,1:ny,1:nz) = 1; % density -prop.mu (1:nx,1:ny,1:nz) = 0.1; % viscosity -prop.lambda(1:nx,1:ny,1:nz) = 0.15; % thermal conductivity -prop.cap (1:nx,1:ny,1:nz) = 1.0; % thermal capacity - -% Time-stepping parameters -dt = 0.003; % time step -ndt = 1500; % number of time steps - -% Create unknowns; names, positions, sizes and default boundary conditions -uc = create_unknown('u-velocity', C, r.c, 'd'); -vc = create_unknown('v-velocity', C, r.c, 'd'); -wc = create_unknown('w-velocity', C, r.c, 'd'); -uf = create_unknown('face-u-vel', X, r.u, 'd'); -vf = create_unknown('face-v-vel', Y, r.v, 'd'); -wf = create_unknown('face-w-vel', Z, r.w, 'd'); -p = create_unknown('pressure', C, r.c, 'n'); -t = create_unknown('temperature', C, r.c, 'n'); - -% Specify boundary conditions -uc.bnd(W).type(1,:,:) = 'd'; -for k=1:nz - uc.bnd(W).val(1,:,k) = avg(par(1.0,ny+1)); -end -uc.bnd(E).type(1,:,:) = 'o'; uc.bnd(E).val(1,:,:) = 1.0; - -uc.bnd(B).type(:,:,1) = 'n'; -uc.bnd(T).type(:,:,1) = 'n'; -vc.bnd(B).type(:,:,1) = 'n'; -vc.bnd(T).type(:,:,1) = 'n'; -wc.bnd(B).type(:,:,1) = 'n'; -wc.bnd(T).type(:,:,1) = 'n'; - -t.bnd(W).type(1,:,:) = 'd'; -for k=1:nz - t.bnd(W).val(1,:,k) = 1.0-yc; -end -t.bnd(S).type(:,1,:) = 'd'; t.bnd(S).val(:,1,:) = +1.0; -t.bnd(N).type(:,1,:) = 'd'; t.bnd(N).val(:,1,:) = 0.0; - -t = adj_n_bnds(t); -p = adj_n_bnds(p); - -% Specify initial conditions -uc.val(:,:,:) = 0.01; -t.val(:,:,:) = 0; - -% Copy the values to face velocities -uf.val = avg(X, uc.val); uf.bnd = uc.bnd; -vf.val = avg(Y, vc.val); vf.bnd = vc.bnd; -wf.val = avg(Z, wc.val); wf.bnd = wc.bnd; - -obst = []; - -%========================================================================== -% -% Solution algorithm -% -%========================================================================== - -%----------- -% -% Time loop -% -%----------- -for ts=1:ndt - - disp_time_step( ts ); - - %------------------------ - % Temperature (enthalpy) - %------------------------ - t = calc_t(t, uf,vf,wf, ... % advection velocity - (prop.rho.*prop.cap), prop.lambda, ... % physical properties - dt, ts, dx,dy,dz, obst); % numerical domain - - %---------- - % Momentum - %---------- - - % Gravity term for momentum - g_v = 150.0 * t.val; - - [uc,vc,wc, uf,vf,wf] = calc_uvw(uc,vc,wc, uf,vf,wf, ... - prop.rho, prop.mu, ... - zeros( r.c ), ... - zeros( r.c ), g_v, zeros( r.c ), ... - dt, ts, dx,dy,dz, obst); - - %---------- - % Pressure - %---------- - p = calc_p(p, uf,vf,wf, ... % variable and advection velocity - prop.rho, ... % density - dt, dx,dy,dz, obst); % numerical domain - - %--------------------- - % Velocity correction - %--------------------- - - % Correct the cell centered velocites - [uc,vc,wc] = corr_uvw(uc,vc,wc, p, prop.rho, dt, dx,dy,dz, obst); - - % Correct face velocities in staggered fashion - [uf,vf,wf] = corr_uvw(uf,vf,wf, p, prop.rho, dt, dx,dy,dz, obst); - - % Compute the source for pressure again to check mass error - err = vol_balance(uf,vf,wf, dx,dy,dz, obst); - disp( sprintf('maximum mass error after correction = %12.5e', ... - max(max(max(abs(err)))))); - - cfl = cfl_max(uc,vc,wc, dt, dx,dy,dz); - disp( sprintf('cfl max = %5.3f', cfl ) ); - -%========================================================================== -% -% Visualization -% -%========================================================================== - - %------------------------- - % Plot in Matlab's figure - %------------------------- - if mod(ts,10) == 0 - - kp = 2; - xp = avg(xn); - yp = avg(yn); - up = uc.val; - vp = vc.val; - - subplot(2,1,1) - [cnt,hnd] = contourf(xp,yp, t.val(:,:,kp)', linspace(-0.0, 1.0, 11)); - hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 'k-'); - hold off; - axis equal - title([sprintf('Temperature at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - subplot(2,1,2) - [cnt,hnd] = contourf(xp, yp, p.val(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 'k-'); - hold off; - axis equal - title([sprintf('Pressure correction at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - end - - %-------------------------- - % Export to Tecplot format - %-------------------------- - if mod(ts,100) == 0 - - container.var(1:5) = [uc vc wc t p]; - file_name = sprintf('results-plumes-collocated-%6.6d.dat', ts); - export_tecplot(file_name, container, r.c, xn, yn, zn); - - end - -end - diff --git a/MATLAB/Tests/test_plumes_staggered.m b/MATLAB/Tests/test_plumes_staggered.m deleted file mode 100644 index ce589a4..0000000 --- a/MATLAB/Tests/test_plumes_staggered.m +++ /dev/null @@ -1,197 +0,0 @@ -%========================================================================== -% This script is to reproduce two-dimensional mixed convection case, with -% the aim of testing the outflow boundary, particularly the "convective" -% boundary condition which allows eddies to leave the domain. -% -% There is also a collocated version of this script, called -% "demo_plums_collocated.m". It would be good to keep both version as -% similar as possible to each other, to test the differences between -% staggered and collocated arrangements always possible. -%-------------------------------------------------------------------------- -clear -clc; - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution -xn = nodes(0, 10, 300); xc = avg(xn); -yn = nodes(0, 1, 40, 1/500, 1/500); yc = avg(yn); -zn = nodes(0, 3, 3); zc = avg(zn); - -% Expand dx, dy and dz over whole domain -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - -% Resolution ranges -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% Set physical properties -prop.rho (1:nx,1:ny,1:nz) = 1; % density -prop.mu (1:nx,1:ny,1:nz) = 0.1; % viscosity -prop.lambda(1:nx,1:ny,1:nz) = 0.15; % thermal conductivity -prop.cap (1:nx,1:ny,1:nz) = 1.0; % thermal capacity - -% Time-stepping parameters -dt = 0.003; % time step -ndt = 150; % number of time steps - -% Create unknowns; names, positions, sizes and default boundary conditions -uf = create_unknown('u-velocity', X, r.u, 'd'); -vf = create_unknown('v-velocity', Y, r.v, 'd'); -wf = create_unknown('w-velocity', Z, r.w, 'd'); -p = create_unknown('pressure', C, r.c, 'n'); -t = create_unknown('temperature', C, r.c, 'n'); - -% Specify boundary conditions -uf.bnd(W).type(1,:,:) = 'd'; -for k=1:nz - uf.bnd(W).val(1,:,k) = avg(par(1.0,ny+1)); -end -uf.bnd(E).type(1,:,:) = 'o'; uf.bnd(E).val(1,:,:) = 1.0; - -uf.bnd(B).type(:,:,1) = 'n'; -uf.bnd(T).type(:,:,1) = 'n'; -vf.bnd(B).type(:,:,1) = 'n'; -vf.bnd(T).type(:,:,1) = 'n'; -wf.bnd(B).type(:,:,1) = 'n'; -wf.bnd(T).type(:,:,1) = 'n'; - -t.bnd(W).type(1,:,:) = 'd'; -for k=1:nz - t.bnd(W).val(1,:,k) = 1.0-yc; -end -t.bnd(S).type(:,1,:) = 'd'; t.bnd(S).val(:,1,:) = +1.0; -t.bnd(N).type(:,1,:) = 'd'; t.bnd(N).val(:,1,:) = 0.0; - -t = adj_n_bnds(t); -p = adj_n_bnds(p); - -% Specify initial conditions -uf.val(:,:,:) = 1.0; -t.val(:,:,:) = 0; - -obst = []; - -%========================================================================== -% -% Solution algorithm -% -%========================================================================== - -%----------- -% -% Time loop -% -%----------- -for ts=1:ndt - - disp_time_step( ts ); - - %------------------------ - % Temperature (enthalpy) - %------------------------ - t = calc_t(t, uf,vf,wf, ... % advection velocity - (prop.rho.*prop.cap), prop.lambda, ... % physical properties - dt, ts, dx,dy,dz, obst); % numerical domain - - %---------- - % Momentum - %---------- - - % Gravity term for momentum - g_v = 150 * avg(Y, t.val); - - [uf,vf,wf, uf,vf,wf] = calc_uvw(uf,vf,wf, uf,vf,wf, ... - prop.rho, prop.mu, ... - zeros(r.c), ... - zeros(r.u), g_v, zeros(r.w), ... - dt, ts, dx,dy,dz, obst); - - %---------- - % Pressure - %---------- - p = calc_p(p, uf,vf,wf, ... % variable and advection velocity - prop.rho, ... % density - dt, dx,dy,dz, obst); % numerical domain - - %--------------------- - % Velocity correction - %--------------------- - [uf,vf,wf] = corr_uvw(uf,vf,wf, p, prop.rho, dt, dx,dy,dz, obst); - - % Compute the source for pressure again to check mass error - err = vol_balance(uf,vf,wf, dx,dy,dz, obst); - disp( sprintf('maximum mass error after correction = %12.5e', ... - max(max(max(abs(err)))))); - - cfl = cfl_max(uf,vf,wf, dt, dx,dy,dz); - disp( sprintf('cfl max = %5.3f', cfl ) ); - -%========================================================================== -% -% Visualisation -% -%========================================================================== - - %------------------------- - % Plot in Matlab's figure - %------------------------- - if mod(ts,10) == 0 - - kp = 2; - xp = avg(xn); - yp = avg(yn); - up = avg(X, cat(X, uf.bnd(W).val, uf.val, uf.bnd(E).val)); - vp = avg(Y, cat(Y, vf.bnd(S).val, vf.val, vf.bnd(N).val)); - - subplot(2,1,1) - [cnt,hnd] = contourf(xp, yp, t.val(:,:,kp)', linspace(-0.0, 1.0, 11)); - hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Temperature at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - subplot(2,1,2) - [cnt,hnd] = contourf(xp, yp, p.val(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Pressure correction at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - end - - %-------------------------- - % Export to Tecplot format - %-------------------------- - if mod(ts,100) == 0 - - container.var(1:5) = [uf vf wf t p]; - file_name = sprintf('results-plumes-staggered-%6.6d.dat', ts); - export_tecplot(file_name, container, r.c, xn, yn, zn); - - end - -end - diff --git a/MATLAB/Tests/test_stratification.m b/MATLAB/Tests/test_stratification.m deleted file mode 100644 index 31a46e9..0000000 --- a/MATLAB/Tests/test_stratification.m +++ /dev/null @@ -1,216 +0,0 @@ -%========================================================================== -% Solves flow in a channel with stable or unstable stratification. -% The type of stratification is set by parameter "STRATIFICATION" -% -% Uses non-Boussinesq model for buoyancy term; i.e. density depends on -% temperature. -% -% Gravity term is engaged gradually to avoid vortex at the outlet. -%-------------------------------------------------------------------------- -clear; - -%------------------------------------------------- -% Chose between stable or unstable stratification -%------------------------------------------------- -STRATIFICATION = 's'; % 's' or 'u' - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution -xn = nodes(0, 10, 80); xc = avg(xn); -yn = nodes(0, 1, 20); yc = avg(yn); -zn = nodes(0, 0.2, 5); zc = avg(zn); - -% Expand dx, dy and dz over whole domain -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - - -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% Set physical properties -rho (1:nx,1:ny,1:nz) = 1.25; % density -mu (1:nx,1:ny,1:nz) = 0.1; % viscosity -lambda(1:nx,1:ny,1:nz) = 0.001; % thermal conductivity -cap (1:nx,1:ny,1:nz) = 1.0; % thermal capacity - -% Time-stepping parameters -dt = 0.20; % time step -ndt = 500; % number of time steps - -% Create unknowns; names, positions and sizes -u = create_unknown('u-velocity', X, r.u, 'd'); -v = create_unknown('v-velocity', Y, r.v, 'd'); -w = create_unknown('w-velocity', Z, r.w, 'd'); -p = create_unknown('pressure', C, r.c, 'n'); -t = create_unknown('temperature', C, r.c, 'n'); -p_tot = zeros( r.c ); - -% Specify boundary conditions -u.bnd(W).type(1,:,:)='d'; -for k=1:nz - u.bnd(W).val(1,:,k)=avg(par(0.1, ny+1)); -end -u.bnd(E).type(1,:,:)='o'; -u.bnd(E).val (1,:,:)=0.1; - -u.bnd(B).type(:,:,1) = 'n'; -u.bnd(T).type(:,:,1) = 'n'; -v.bnd(B).type(:,:,1) = 'n'; -v.bnd(T).type(:,:,1) = 'n'; -w.bnd(B).type(:,:,1) = 'n'; -w.bnd(T).type(:,:,1) = 'n'; -t.bnd(B).type(:,:,1) = 'n'; -t.bnd(T).type(:,:,1) = 'n'; - -t.val(1:nx, 1:ny, 1:nz) = 70; -if STRATIFICATION == 'u' - dtemp = (60-80)/ny; - t.bnd(W).type(1,1:ny,1:nz) = 'd'; - for k=1:nz - t.bnd(W).val (1,1:ny,k) = linspace(60-dtemp/2,80+dtemp/2,ny); - end - t.bnd(S).type(1:nx,1,1:nz) = 'd'; - t.bnd(S).val (1:nx,1,1:nz) = 60.0; - t.bnd(N).type(1:nx,1,1:nz) = 'd'; - t.bnd(N).val (1:nx,1,1:nz) = 80.0; -elseif STRATIFICATION == 's' - dtemp = (80-60)/ny; - t.bnd(W).type(1,1:ny) = 'd'; - for k=1:nz - t.bnd(W).val(1,1:ny,k) = linspace(80-dtemp/2,60+dtemp/2,ny); - end - t.bnd(S).type(1:nx,1,1:nz) = 'd'; - t.bnd(S).val (1:nx,1,1:nz) = 80.0; - t.bnd(N).type(1:nx,1,1:nz) = 'd'; - t.bnd(N).val (1:nx,1,1:nz) = 60.0; -end -t.bnd(E).type(1,1:ny,1:nz) = 'n'; -t.bnd(E).val (1,1:ny,1:nz) = 70.0; - -t = adj_n_bnds(t); -p = adj_n_bnds(p); - -obst = []; - -%========================================================================== -% -% Solution algorithm -% -%========================================================================== - -%----------- -% -% Time loop -% -%----------- -for ts=1:ndt - - disp_time_step(ts); - - rho = 1.06 + (t.val - 60.0) * (0.99 - 1.06) / 20.0; - - %------------------------ - % Temperature (enthalpy) - %------------------------ - t = calc_t(t, u, v, w, ... % variable and advection velocity - (rho.*cap), lambda, ... % physical properties - dt, ts, dx, dy, dz, obst); % numerical domain - - %---------- - % Momentum - %---------- - - % Gravity term for momentum - g_v = - G * avg(Y, rho); - - [u, v, w] = calc_uvw(u, v, w, u, v, w, ... - rho, mu, ... - p_tot, ... - zeros(r.u), g_v, zeros(r.w), ... - dt, ts, dx, dy, dz, obst); - - %---------- - % Pressure - %---------- - p = calc_p(p, u, v, w, ... % variable and advection velocity - rho, ... % density - dt, dx, dy, dz, obst); % numerical domain - - p_tot = p_tot + p.val; - - %--------------------- - % Velocity correction - %--------------------- - [u, v, w] = corr_uvw(u, v, w, p, rho, dt, dx, dy, dz, obst); - - % Compute the source for pressure again to check mass error - err = vol_balance(u,v,w, dx,dy,dz, obst); - disp( sprintf('maximum mass error after correction = %12.5e', ... - max(max(max(abs(err)))))); - - cfl = cfl_max(u,v,w, dt, dx,dy,dz); - disp( sprintf('cfl max = %5.3f', cfl ) ); - -%========================================================================== -% -% Visualisation -% -%========================================================================== - - %------ - % Plot - %------ - if mod(ts,50) == 0 - k_plot = 3; - uc = avg(X, cat(X, u.bnd(W).val,u.val,u.bnd(E).val)); - vc = avg(Y, cat(Y, v.bnd(S).val,v.val,v.bnd(N).val)); - subplot(3,1,1) - [cnt,hnd] = contourf(xc, yc, t.val(:,:,k_plot)', ... - linspace(59.99,80.01,10)); - hold on; - quiver(xc, yc, uc(:,:,k_plot)', vc(:,:,k_plot)', 2, 'k-'); - hold off; - axis equal - title(sprintf('Temperature at time step %d out of %d\n', ts, ndt)) - subplot(3,1,2) - [cnt,hnd] = contourf(xc,yc,rho(:,:,k_plot)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xc, yc, uc(:,:,k_plot)', vc(:,:,k_plot)', 2, 'k-'); - hold off; - axis equal - title(sprintf('Density at time step %d out of %d\n', ts, ndt)) - subplot(3,1,3) - [cnt,hnd] = contourf(xc,yc,p_tot(:,:,k_plot)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xc, yc, uc(:,:,k_plot)', vc(:,:,k_plot)', 2, 'k-'); - hold off; - axis equal - title(sprintf('Total pressure at time step %d out of %d\n', ts, ndt)) - drawnow; - - %-------------------------- - % Export to Tecplot format - %-------------------------- - container.var(1:5) = [u v w t p]; - file_name = sprintf('results-stratification-staggered-%6.6d.dat', ts); - export_tecplot(file_name, container, r.c, xn, yn, zn); - - end -end - diff --git a/MATLAB/Tests/test_thermaly_driven_cavity_collocated.m b/MATLAB/Tests/test_thermaly_driven_cavity_collocated.m deleted file mode 100644 index a144976..0000000 --- a/MATLAB/Tests/test_thermaly_driven_cavity_collocated.m +++ /dev/null @@ -1,260 +0,0 @@ -%========================================================================== -% This program solves thermally driven cavity at Ra = 1.0e6, -% in dimensional and non-dimensional forms. -% -% Equations in dimensional form: -% -% D(rho u)/Dt = nabla(mu (nabla u)^T) - nabla p + g -% D(rho cp T)/Dt = nabla(lambda (nabla T)^T) -% -% Equations in non-dimensional form, for natural convection problems -% -% DU/Dt = nabla(1/sqrt(Gr) (nabla U)^T) - nabla P + theta -% D theta/Dt = nabla(1/(Pr*sqrt(Gr)) (nabla theta)^T) -% -%-------------------------------------------------------------------------- -% For thermally driven cavity, with properties of air at 60 deg: -% -% nu = 1.89035E-05; -% beta = 0.003; -% dT = 17.126; -% L = 0.1; -% Pr = 0.709; -% -% characteristic non-dimensional numbers are: -% Gr = 1.4105E+06 -% Ra = 1.0000E+06 -%-------------------------------------------------------------------------- -clear -clc; - -%---------------------------------------------------- -% Chose between dimensional or non-dimensional forms -%---------------------------------------------------- -FORM = 'n'; % 'd' or 'n' - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution -if FORM == 'd' - L = 0.1; -else - L = 1.0; -end -xn = nodes(0, L, 64, L/256, L/256); xc = avg(xn); -yn = nodes(0, L, 64, L/256, L/256); yc = avg(yn); -zn = nodes(0, L/10, 5); zc = avg(zn); - -% Expand dx, dy and dz over whole domain -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - -% Resolution ranges -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% set physical properties -if FORM == 'd' - [prop.rho, ... - prop.mu, ... - prop.cap, ... - prop.lambda] = air_properties(1:nx, 1:ny, 1:nz); -else - grashof = 1.4105E+06; - prandtl = 0.7058; - prop.rho (1:nx, 1:ny, 1:nz) = 1.0; - prop.mu (1:nx, 1:ny, 1:nz) = 1.0 / sqrt(grashof); - prop.cap (1:nx, 1:ny, 1:nz) = 1.0; - prop.lambda(1:nx, 1:ny, 1:nz) = 1.0 / (prandtl * sqrt(grashof)); -end - -% Time-stepping parameters -if FORM == 'd' - dt = 0.01; % time steps - ndt = 1000; % number of time steps -else - dt = 0.02; % time steps - ndt = 1000; % number of time steps -end - -% Create unknowns; names, positions, sizes and default boundary conditions -uc = create_unknown('u-velocity', C, r.c, 'd'); -vc = create_unknown('v-velocity', C, r.c, 'd'); -wc = create_unknown('w-velocity', C, r.c, 'd'); -uf = create_unknown('face-u-vel', X, r.u, 'd'); -vf = create_unknown('face-v-vel', Y, r.v, 'd'); -wf = create_unknown('face-w-vel', Z, r.w, 'd'); -p = create_unknown('pressure', C, r.c, 'n'); -t = create_unknown('temperature', C, r.c, 'n'); -p_tot = zeros(nx, ny, nz); - -if FORM == 'd' - t.val(:,:,:) = 60.0; - t.bnd(W).type(1,:,:) = 'd'; t.bnd(W).val(1,:,:) = 68.563; - t.bnd(E).type(1,:,:) = 'd'; t.bnd(E).val(1,:,:) = 51.437; - t.bnd(S).val (:,1,:) = 60.0; - t.bnd(N).val (:,1,:) = 60.0; -else - t.val(:,:,:) = 0.0; - t.bnd(W).type(1,:,:) = 'd'; t.bnd(W).val(1,:,:) = 0.5; - t.bnd(E).type(1,:,:) = 'd'; t.bnd(E).val(1,:,:) = -0.5; -end - -uc.bnd(B).type(:,:,1) = 'n'; -uc.bnd(T).type(:,:,1) = 'n'; -vc.bnd(B).type(:,:,1) = 'n'; -vc.bnd(T).type(:,:,1) = 'n'; -wc.bnd(B).type(:,:,1) = 'n'; -wc.bnd(T).type(:,:,1) = 'n'; - -t = adj_n_bnds(t); -p = adj_n_bnds(p); - -% Copy the values to face velocities -uf.val = avg(X,uc.val); uf.bnd = uc.bnd; -vf.val = avg(Y,vc.val); vf.bnd = vc.bnd; -wf.val = avg(Z,wc.val); wf.bnd = wc.bnd; - -obst = []; - -%========================================================================== -% -% Solution algorithm -% -%========================================================================== - -%----------- -% -% Time loop -% -%----------- -tic -for ts=1:ndt - - disp_time_step(ts); - - if FORM == 'd' - prop.rho = 1.127 + (t.val - 40.0) * (1.00 - 1.127) / 40.0; - end - - %------------------------ - % Temperature (enthalpy) - %------------------------ - t = calc_t(t, uf,vf,wf, ... % variable & velocity - (prop.rho.*prop.cap), prop.lambda, ... % physical properties - dt, ts, dx,dy,dz, obst); % numerical domain - - %---------- - % Momentum - %---------- - - % Gravity term for momentum - if FORM == 'd' - g_v = -G * prop.rho; - else - g_v = t.val; - end - - [uc,vc,wc, uf,vf,wf] = calc_uvw(uc,vc,wc, uf,vf,wf, ... - prop.rho, prop.mu, ... - p_tot, ... - zeros(r.c), g_v, zeros(r.c), ... - dt, ts, dx,dy,dz, obst); - - %---------- - % Pressure - %---------- - p = calc_p(p, uf,vf,wf, ... % pressure and advection velocity - prop.rho, ... % physical property - dt, dx,dy,dz, obst); % numerical domain - - p_tot = p_tot + p.val; - - %--------------------- - % Velocity correction - %--------------------- - - % Correct the cell centered velocites - [uc,vc,wc] = corr_uvw(uc,vc,wc, p, prop.rho, dt, dx,dy,dz, obst); - - % Correct face velocities in staggered fashion - [uf,vf,wf] = corr_uvw(uf,vf,wf, p, prop.rho, dt, dx,dy,dz, obst); - - % Compute the source for pressure again to check mass error - err = vol_balance(uf,vf,wf, dx,dy,dz, obst); - disp( sprintf('maximum mass error after correction = %12.5e', ... - max(max(max(abs(err)))))); - - cfl = cfl_max(uc,vc,wc, dt, dx,dy,dz); - disp( sprintf('cfl max = %5.3f', cfl ) ); - -%========================================================================== -% -% Visualization -% -%========================================================================== - - %------ - % Plot - %------ - if mod(ts,20) == 0 - kp = 3; - xp = avg(xn); - yp = avg(yn); - up = uc.val; - vp = vc.val; - - subplot(1,3,1) - [cnt,hnd] = contourf(xp,yp,t.val(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 'k-'); - hold off; - axis equal - title([sprintf('Temperature at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - subplot(1,3,2) - [cnt,hnd] = contourf(xp,yp,p.val(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Pressure correction at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - subplot(1,3,3) - [cnt,hnd] = contourf(xp,yp,p_tot(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Pressure at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - - %-------------------------- - % Export to Tecplot format - %-------------------------- - container.var(1:5) = [uc vc wc t p]; - file_name = sprintf('results-thermal-cavity-collocated-%6.6d.dat', ts); - export_tecplot(file_name, container, r.c, xn, yn, zn); - - end -end -toc - diff --git a/MATLAB/Tests/test_thermaly_driven_cavity_staggered.m b/MATLAB/Tests/test_thermaly_driven_cavity_staggered.m deleted file mode 100644 index 0e85500..0000000 --- a/MATLAB/Tests/test_thermaly_driven_cavity_staggered.m +++ /dev/null @@ -1,249 +0,0 @@ -%========================================================================== -% This program solves thermally driven cavity at Ra = 1.0e6, -% in dimensional and non-dimensional forms. -% -% Equations in dimensional form: -% -% D(rho u)/Dt = nabla(mu (nabla u)^T) - nabla p + g -% D(rho cp T)/Dt = nabla(lambda (nabla T)^T) -% -% Equations in non-dimensional form, for natural convection problems -% -% DU/Dt = nabla(1/sqrt(Gr) (nabla U)^T) - nabla P + theta -% D theta/Dt = nabla(1/(Pr*sqrt(Gr)) (nabla theta)^T) -% -%-------------------------------------------------------------------------- -% For thermally driven cavity, with properties of air at 60 deg: -% -% nu = 1.89035E-05; -% beta = 0.003; -% dT = 17.126; -% L = 0.1; -% Pr = 0.709; -% -% characteristic non-dimensional numbers are: -% Gr = 1.4105E+06 -% Ra = 1.0000E+06 -%-------------------------------------------------------------------------- -clear; - -%---------------------------------------------------- -% Chose between dimensional or non-dimensional forms -%---------------------------------------------------- -FORM = 'n'; % 'd' or 'n' - -%------------------------------ -% Set path to common functions -%------------------------------ -path(path, '../Constants'); -path(path, '../Discretization'); -path(path, '../InputOutput'); -path(path, '../Operators'); -path(path, '../PhysicalModels'); - -%========================================================================== -% -% Define problem -% -%========================================================================== - -% Set domain dimensions and grid resolution -if FORM == 'd' - L = 0.1; -else - L = 1.0; -end -xn = nodes(0, L, 64, L/256, L/256); xc = avg(xn); -yn = nodes(0, L, 64, L/256, L/256); yc = avg(yn); -zn = nodes(0, L/10, 5); zc = avg(zn); - -% Expand dx, dy and dz over whole domain -[dx dy dz nx ny nz] = cartesian_grid(xn, yn, zn); - -% Resolution ranges -r.c = [nx ny nz ]; -r.u = [nx-1 ny nz ]; -r.v = [nx ny-1 nz ]; -r.w = [nx ny nz-1]; - -% Set physical properties -if FORM == 'd' - [rho, mu, cap, lambda] = air_properties(1:nx, 1:ny, 1:nz); -else - grashof = 1.4105E+06; - prandtl = 0.7058; - rho (1:nx, 1:ny, 1:nz) = 1.0; - mu (1:nx, 1:ny, 1:nz) = 1.0 / sqrt(grashof); - cap (1:nx, 1:ny, 1:nz) = 1.0; - lambda(1:nx, 1:ny, 1:nz) = 1.0 / (prandtl * sqrt(grashof)); -end - -% Time-stepping parameters -if FORM == 'd' - dt = 0.01; % time steps - ndt = 333; % number of time steps -else - dt = 0.02; % time steps - ndt = 333; % number of time steps -end - -% Create unknowns; names, positions, sizes and default boundary conditions -uf = create_unknown('u-velocity', X, r.u, 'd'); -vf = create_unknown('v-velocity', Y, r.v, 'd'); -wf = create_unknown('w-velocity', Z, r.w, 'd'); -p = create_unknown('pressure', C, r.c, 'n'); -t = create_unknown('temperature', C, r.c, 'n'); -p_tot = zeros(nx, ny, nz); - -if FORM == 'd' - t.val(:,:,:) = 60.0; - t.bnd(W).type(1,:,:) = 'd'; t.bnd(W).val(1,:,:) = 68.563; - t.bnd(E).type(1,:,:) = 'd'; t.bnd(E).val(1,:,:) = 51.437; - t.bnd(S).val (:,1,:) = 60.0; - t.bnd(N).val (:,1,:) = 60.0; -else - t.val(:,:,:) = 0.0; - t.bnd(W).type(1,:,:) = 'd'; t.bnd(W).val(1,:,:) = 0.5; - t.bnd(E).type(1,:,:) = 'd'; t.bnd(E).val(1,:,:) = -0.5; -end - -uf.bnd(B).type(:,:,1) = 'n'; -uf.bnd(T).type(:,:,1) = 'n'; -vf.bnd(B).type(:,:,1) = 'n'; -vf.bnd(T).type(:,:,1) = 'n'; -wf.bnd(B).type(:,:,1) = 'n'; -wf.bnd(T).type(:,:,1) = 'n'; - -t = adj_n_bnds(t); -p = adj_n_bnds(p); - -obst = []; - -%========================================================================== -% -% Solution algorithm -% -%========================================================================== - -%----------- -% -% Time loop -% -%----------- -tic -for ts=1:ndt - - disp_time_step(ts); - - if FORM == 'd' - rho = 1.127 + (t.val - 40.0) * (1.00 - 1.127) / 40.0; - end - - %------------------------ - % Temperature (enthalpy) - %------------------------ - t = calc_t(t, uf,vf,wf, ... % variable and advection velocity - (rho.*cap), lambda, ... % physical properties - dt, ts, ... % time stepping, - dx,dy,dz, obst); % numerical domain - - %---------- - % Momentum - %---------- - - % Gravity term for momentum - if FORM == 'd' - g_v = -G * avg(Y,rho); - else - g_v = avg(Y,t.val); - end - - [uf,vf,wf, uf,vf,wf] = calc_uvw(uf,vf,wf, uf,vf,wf, ... - rho, mu, ... - p_tot, ... - zeros(r.u), g_v, zeros(r.w), ... - dt, ts, ... - dx,dy,dz, obst); - - %---------- - % Pressure - %---------- - p = calc_p(p, uf,vf,wf, ... % variable and advection velocity - rho, ... % density - dt, dx,dy,dz, obst); % numerical domain - - p_tot = p_tot + p.val; - - %--------------------- - % Velocity correction - %--------------------- - [uf,vf,wf] = corr_uvw(uf,vf,wf, p, rho, dt, dx,dy,dz, obst); - - % Compute the source for pressure again to check mass error - err = vol_balance(uf,vf,wf, dx,dy,dz, obst); - disp( sprintf('maximum mass error after correction = %12.5e', ... - max(max(max(abs(err)))))); - - cfl = cfl_max(uf,vf,wf, dt, dx,dy,dz); - disp( sprintf('cfl max = %5.3f', cfl ) ); - -%========================================================================== -% -% Visualization -% -%========================================================================== - - %------------------------- - % Plot in Matlab's figure - %------------------------- - if mod(ts,1) == 0 - kp = 3; - xp = avg(xn); - yp = avg(yn); - up = avg(X, cat(X, uf.bnd(W).val, uf.val, uf.bnd(E).val)); - vp = avg(Y, cat(Y, vf.bnd(S).val, vf.val, vf.bnd(N).val)); - - subplot(1,3,1) - [cnt,hnd] = contourf(xp, yp, t.val(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Temperature at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - subplot(1,3,2) - [cnt,hnd] = contourf(xp, yp, p.val(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Pressure correction at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - subplot(1,3,3) - [C,hnd] = contourf(xp, yp, p_tot(:,:,kp)'); hold on; - set(hnd,'ShowText','on','TextStep',get(hnd,'LevelStep')*2); - quiver(xp, yp, up(:,:,kp)', vp(:,:,kp)', 2, 'k-'); - hold off; - axis equal - title([sprintf('Pressure at time step %d ', ts), ... - sprintf('out of %d\n', ndt), ... - sprintf('CFL = %5.3f\n', cfl)]); - drawnow; - end - - %-------------------------- - % Export to Tecplot format - %-------------------------- - if mod(ts,100) == 0 - - container.var(1:5) = [uf vf wf t p]; - file_name = sprintf('results-thermal-cavity-staggered-%6.6d.dat', ts); - export_tecplot(file_name, container, r.c, xn, yn, zn); - - end - -end -toc - diff --git a/PYTHON/.DS_Store b/PYTHON/.DS_Store new file mode 100644 index 0000000..6df7619 Binary files /dev/null and b/PYTHON/.DS_Store differ diff --git a/PYTHON/Constants/all.py b/PYTHON/Constants/all.py deleted file mode 100644 index 492e163..0000000 --- a/PYTHON/Constants/all.py +++ /dev/null @@ -1,7 +0,0 @@ -# Constants -from Constants.boundary_conditions import * -from Constants.compass import * -from Constants.coordinates import * -from Constants.gravitational_constant import * -from Constants.solver import * -from Constants.tiny_and_huge import * \ No newline at end of file diff --git a/PYTHON/Constants/boundary_conditions.py b/PYTHON/Constants/boundary_conditions.py deleted file mode 100644 index 7605de1..0000000 --- a/PYTHON/Constants/boundary_conditions.py +++ /dev/null @@ -1,4 +0,0 @@ -# Boundary conditions -DIRICHLET = 10 -NEUMANN = 11 -OUTLET = 12 \ No newline at end of file diff --git a/PYTHON/Constants/coordinates.py b/PYTHON/Constants/coordinates.py deleted file mode 100644 index a383b52..0000000 --- a/PYTHON/Constants/coordinates.py +++ /dev/null @@ -1,4 +0,0 @@ -# Coordinate directions -X = 0 -Y = 1 -Z = 2 \ No newline at end of file diff --git a/PYTHON/Constants/gravitational_constant.py b/PYTHON/Constants/gravitational_constant.py deleted file mode 100644 index 53acf1d..0000000 --- a/PYTHON/Constants/gravitational_constant.py +++ /dev/null @@ -1,2 +0,0 @@ -# Gravitational constant -G = 9.81 \ No newline at end of file diff --git a/PYTHON/Constants/solver.py b/PYTHON/Constants/solver.py deleted file mode 100644 index 91a59f0..0000000 --- a/PYTHON/Constants/solver.py +++ /dev/null @@ -1,2 +0,0 @@ -# Solver tolerance -TOL = 1.0e-8 \ No newline at end of file diff --git a/PYTHON/Constants/tiny_and_huge.py b/PYTHON/Constants/tiny_and_huge.py deleted file mode 100644 index 39a28db..0000000 --- a/PYTHON/Constants/tiny_and_huge.py +++ /dev/null @@ -1,3 +0,0 @@ -# Tiny and huge -TINY = 1.0e-12 -HUGE = 1.0e+12 \ No newline at end of file diff --git a/PYTHON/Discretization/adj_n_bnds.py b/PYTHON/Discretization/adj_n_bnds.py deleted file mode 100644 index a1f9104..0000000 --- a/PYTHON/Discretization/adj_n_bnds.py +++ /dev/null @@ -1,39 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * - -#========================================================================== -def adj_n_bnds(phi): -#-------------------------------------------------------------------------- -# Copies last domain cell values to Neumann boundary condition values. -#-------------------------------------------------------------------------- - - # These arrays will hold values true (0) in cells with boundary ... - # ... condition of Neumann type, and false (0) otherwise - if_w_n = ( phi.bnd[W].typ[0,:,:] == NEUMANN ) # 1 if west is Neumann - if_e_n = ( phi.bnd[E].typ[0,:,:] == NEUMANN ) # 1 if east is Neumann - if_s_n = ( phi.bnd[S].typ[:,0,:] == NEUMANN ) # 1 if south is Neumann - if_n_n = ( phi.bnd[N].typ[:,0,:] == NEUMANN ) # 1 if north is Neumann - if_b_n = ( phi.bnd[B].typ[:,:,0] == NEUMANN ) # 1 if bottom is Neumann - if_t_n = ( phi.bnd[T].typ[:,:,0] == NEUMANN ) # 1 if top is Neumann - - # In what follows, a linear combination of true (0] and false (0) - # will copy the values of variable phi to the boundaries. - phi.bnd[W].val[0,:,:] = phi.bnd[W].val[0,:,:] * ( lnot(if_w_n) ) \ - + phi.val[0,:,:] * if_w_n - phi.bnd[E].val[0,:,:] = phi.bnd[E].val[0,:,:] * ( lnot(if_e_n) ) \ - + phi.val[-1,:,:] * if_e_n - - phi.bnd[S].val[:,0,:] = phi.bnd[S].val[:,0,:] * ( lnot(if_s_n) ) \ - + phi.val[:,0,:] * if_s_n - phi.bnd[N].val[:,0,:] = phi.bnd[N].val[:,0,:] * ( lnot(if_n_n) ) \ - + phi.val[:,-1,:] * if_n_n - - phi.bnd[B].val[:,:,0] = phi.bnd[B].val[:,:,0] * ( lnot(if_b_n) ) \ - + phi.val[:,:,0] * if_b_n - phi.bnd[T].val[:,:,0] = phi.bnd[T].val[:,:,0] * ( lnot(if_t_n) ) \ - + phi.val[:,:,-1] * if_t_n - - return # end of function diff --git a/PYTHON/Discretization/adj_o_bnds.py b/PYTHON/Discretization/adj_o_bnds.py deleted file mode 100644 index d704bb7..0000000 --- a/PYTHON/Discretization/adj_o_bnds.py +++ /dev/null @@ -1,284 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -#========================================================================== -def adj_o_bnds(uvw, dxyz, dt): -#-------------------------------------------------------------------------- - - # Unpack tuples - u, v, w = uvw - dx, dy, dz = dxyz - - # Local variables used in this function - area_in = 0.0 # area of the inlet - area_out = 0.0 # area of the outlet - vol_in = 0.0 # inlet volume flux; positive for inflow - vol_out_1 = 0.0 # outlet volume flux; positive for outflow - vol_out_2 = 0.0 # outlet volume flux; positive for outflow - - verbatim = False - - sx = dy * dz - sy = dx * dz - sz = dx * dy - - sx = sx[:1,:,:] - sy = sy[:,:1,:] - sz = sz[:,:,:1] - - #------------------------------------------------------------------ - # Compute the volume flowing in (v_in), volume flowing out (v_out) - # as well as inlet and outlet areas (a_in, a_out) - #------------------------------------------------------------------ - - # Inlets: these arrays will hold values true (1) in cells \ - # with inlet boundary conditions, and false (0) otherwise - if_w_in = (u.bnd[W].typ[:1,:,:]==DIRICHLET) & (u.bnd[W].val[:1,:,:]>+TINY) - if_e_in = (u.bnd[E].typ[:1,:,:]==DIRICHLET) & (u.bnd[E].val[:1,:,:]<-TINY) - if_s_in = (v.bnd[S].typ[:,:1,:]==DIRICHLET) & (v.bnd[S].val[:,:1,:]>+TINY) - if_n_in = (v.bnd[N].typ[:,:1,:]==DIRICHLET) & (v.bnd[N].val[:,:1,:]<-TINY) - if_b_in = (w.bnd[B].typ[:,:,:1]==DIRICHLET) & (w.bnd[B].val[:,:,:1]>+TINY) - if_t_in = (w.bnd[T].typ[:,:,:1]==DIRICHLET) & (w.bnd[T].val[:,:,:1]<-TINY) - - # Using the arrays defined above, compute inlet surface area - area_in += (if_w_in * sx).sum() - area_in += (if_e_in * sx).sum() - area_in += (if_s_in * sy).sum() - area_in += (if_n_in * sy).sum() - area_in += (if_b_in * sz).sum() - area_in += (if_t_in * sz).sum() - - # If there is no inlet, nothing to do here any longer - if area_in < TINY: - return u, v, w # one end of function - - # Using the arrays defined above, compute inlet volume flux - vol_in += (if_w_in * u.bnd[W].val[:1,:,:] * sx).sum() - vol_in -= (if_e_in * u.bnd[E].val[:1,:,:] * sx).sum() - vol_in += (if_s_in * v.bnd[S].val[:,:1,:] * sy).sum() - vol_in -= (if_n_in * v.bnd[N].val[:,:1,:] * sy).sum() - vol_in += (if_b_in * w.bnd[B].val[:,:,:1] * sz).sum() - vol_in -= (if_t_in * w.bnd[T].val[:,:,:1] * sz).sum() - - # Outlets: these arrays will hold values true (1) in cells ... - # with outlet boundary conditions, and false (0) otherwise - if_w_out_u = ( u.bnd[W].typ[:1,:,:] == OUTLET ) - if_w_out_v = avg(v.pos, if_w_out_u*1) > 0.5 - if_w_out_w = avg(w.pos, if_w_out_u*1) > 0.5 - - if_e_out_u = ( u.bnd[E].typ[:1,:,:] == OUTLET ) - if_e_out_v = avg(v.pos, if_e_out_u*1) > 0.5 - if_e_out_w = avg(w.pos, if_e_out_u*1) > 0.5 - - if_s_out_v = ( v.bnd[S].typ[:,:1,:] == OUTLET ) - if_s_out_u = avg(u.pos, if_s_out_v*1) > 0.5 - if_s_out_w = avg(w.pos, if_s_out_v*1) > 0.5 - - if_n_out_v = ( v.bnd[N].typ[:,:1,:] == OUTLET ) - if_n_out_u = avg(u.pos, if_n_out_v*1) > 0.5 - if_n_out_w = avg(w.pos, if_n_out_v*1) > 0.5 - - if_b_out_w = ( w.bnd[B].typ[:,:,:1] == OUTLET ) - if_b_out_u = avg(u.pos, if_b_out_w*1) > 0.5 - if_b_out_v = avg(v.pos, if_b_out_w*1) > 0.5 - - if_t_out_w = ( w.bnd[T].typ[:,:,:1] == OUTLET ) - if_t_out_u = avg(u.pos, if_t_out_w*1) > 0.5 - if_t_out_v = avg(v.pos, if_t_out_w*1) > 0.5 - - # Using the arrays defined above, compute outlet surface area - area_out += (if_w_out_u * sx).sum() - area_out += (if_e_out_u * sx).sum() - area_out += (if_s_out_v * sy).sum() - area_out += (if_n_out_v * sy).sum() - area_out += (if_b_out_w * sz).sum() - area_out += (if_t_out_w * sz).sum() - - # Using the arrays defined above, compute outlet volume flux - vol_out_1 -= (if_w_out_u * u.bnd[W].val[:1,:,:] * sx).sum() - vol_out_1 += (if_e_out_u * u.bnd[E].val[:1,:,:] * sx).sum() - vol_out_1 -= (if_s_out_v * v.bnd[S].val[:,:1,:] * sy).sum() - vol_out_1 += (if_n_out_v * v.bnd[N].val[:,:1,:] * sy).sum() - vol_out_1 -= (if_b_out_w * w.bnd[B].val[:,:,:1] * sz).sum() - vol_out_1 += (if_t_out_w * w.bnd[T].val[:,:,:1] * sz).sum() - - #--------------------------------- - # Check and calculate corrections - #--------------------------------- - - if (area_in == 0): - ub_in = 0 - else: - ub_in = vol_in / area_in - - if (area_out == 0): - ub_out = 0 - else: - ub_out = vol_out_1 / area_out - - #---------------------------------------------- - # If nothing comes out, make a bulk correction - #---------------------------------------------- - if(ub_out < TINY): - u_bulk_corr = ub_in * area_in / area_out - - u.bnd[W].val[:1,:,:] = u.bnd[W].val[:1,:,:] * lnot(if_w_out_u) \ - - u_bulk_corr * if_w_out_u - u.bnd[E].val[:1,:,:] = u.bnd[E].val[:1,:,:] * lnot(if_e_out_u) \ - + u_bulk_corr * if_e_out_u - v.bnd[S].val[:,:1,:] = v.bnd[S].val[:,:1,:] * lnot(if_s_out_v) \ - - u_bulk_corr * if_s_out_v - v.bnd[N].val[:,:1,:] = v.bnd[N].val[:,:1,:] * lnot(if_n_out_v) \ - + u_bulk_corr * if_n_out_v - w.bnd[B].val[:,:,:1] = w.bnd[B].val[:,:,:1] * lnot(if_b_out_w) \ - - u_bulk_corr * if_b_out_w - w.bnd[T].val[:,:,:1] = w.bnd[T].val[:,:,:1] * lnot(if_t_out_w) \ - + u_bulk_corr * if_t_out_w - - #-------------------------------------------------------------- - # Correction outflow by applying convective boundary condition - #-------------------------------------------------------------- - else: - du_dx_w = (u.val[ :1,:,:]-u.bnd[W].val[:1,:,:]) / dx[ :1,:,:] - dv_dx_w = (v.val[ :1,:,:]-v.bnd[W].val[:1,:,:]) / avg(v.pos, dx[ :1,:,:]) - dw_dx_w = (w.val[ :1,:,:]-w.bnd[W].val[:1,:,:]) / avg(w.pos, dx[ :1,:,:]) - - du_dx_e = (u.val[-1:,:,:]-u.bnd[E].val[:1,:,:]) / dx[-1:,:,:] - dv_dx_e = (v.val[-1:,:,:]-v.bnd[E].val[:1,:,:]) / avg(v.pos, dx[-1:,:,:]) - dw_dx_e = (w.val[-1:,:,:]-w.bnd[E].val[:1,:,:]) / avg(w.pos, dx[-1:,:,:]) - - du_dy_s = (u.val[:, :1,:]-u.bnd[S].val[:,:1,:]) / avg(u.pos, dy[:, :1,:]) - dv_dy_s = (v.val[:, :1,:]-v.bnd[S].val[:,:1,:]) / dy[:, :1,:] - dw_dy_s = (w.val[:, :1,:]-w.bnd[S].val[:,:1,:]) / avg(w.pos, dy[:, :1,:]) - - du_dy_n = (u.val[:,-1:,:]-u.bnd[N].val[:,:1,:]) / avg(u.pos, dy[:,-1:,:]) - dv_dy_n = (v.val[:,-1:,:]-v.bnd[N].val[:,:1,:]) / dy[:,-1:,:] - dw_dy_n = (w.val[:,-1:,:]-w.bnd[N].val[:,:1,:]) / avg(w.pos, dy[:,-1:,:]) - - du_dz_b = (u.val[:,:, :1]-u.bnd[B].val[:,:,:1]) / avg(u.pos, dz[:,:, :1]) - dv_dz_b = (v.val[:,:, :1]-v.bnd[B].val[:,:,:1]) / avg(v.pos, dz[:,:, :1]) - dw_dz_b = (w.val[:,:, :1]-w.bnd[B].val[:,:,:1]) / dz[:,:, :1] - - du_dz_t = (u.val[:,:,-1:]-u.bnd[T].val[:,:,:1]) / avg(u.pos, dz[:,:,-1:]) - dv_dz_t = (v.val[:,:,-1:]-v.bnd[T].val[:,:,:1]) / avg(v.pos, dz[:,:,-1:]) - dw_dz_t = (w.val[:,:,-1:]-w.bnd[T].val[:,:,:1]) / dz[:,:,-1:] - - u_bnd_w_corr = (u.bnd[W].val[:1,:,:] + ub_out * dt * du_dx_w) - v_bnd_w_corr = (v.bnd[W].val[:1,:,:] + ub_out * dt * dv_dx_w) - w_bnd_w_corr = (w.bnd[W].val[:1,:,:] + ub_out * dt * dw_dx_w) - - u.bnd[W].val[:1,:,:] = u.bnd[W].val[:1,:,:] * lnot(if_w_out_u) \ - + u_bnd_w_corr * if_w_out_u - v.bnd[W].val[:1,:,:] = v.bnd[W].val[:1,:,:] * lnot(if_w_out_v) \ - + v_bnd_w_corr * if_w_out_v - w.bnd[W].val[:1,:,:] = w.bnd[W].val[:1,:,:] * lnot(if_w_out_w) \ - + w_bnd_w_corr * if_w_out_w - - u_bnd_e_corr = (u.bnd[E].val[:1,:,:] + ub_out * dt * du_dx_e) - v_bnd_e_corr = (v.bnd[E].val[:1,:,:] + ub_out * dt * dv_dx_e) - w_bnd_e_corr = (w.bnd[E].val[:1,:,:] + ub_out * dt * dw_dx_e) - - u.bnd[E].val[:1,:,:] = u.bnd[E].val[:1,:,:] * lnot(if_e_out_u) \ - + u_bnd_e_corr * if_e_out_u - v.bnd[E].val[:1,:,:] = v.bnd[E].val[:1,:,:] * lnot(if_e_out_v) \ - + v_bnd_e_corr * if_e_out_v - w.bnd[E].val[:1,:,:] = w.bnd[E].val[:1,:,:] * lnot(if_e_out_w) \ - + w_bnd_e_corr * if_e_out_w - - u_bnd_s_corr = (u.bnd[S].val[:,:1,:] + ub_out * dt * du_dy_s) - v_bnd_s_corr = (v.bnd[S].val[:,:1,:] + ub_out * dt * dv_dy_s) - w_bnd_s_corr = (w.bnd[S].val[:,:1,:] + ub_out * dt * dw_dy_s) - - u.bnd[S].val[:,:1,:] = u.bnd[S].val[:,:1,:] * lnot(if_s_out_u) \ - + u_bnd_s_corr * if_s_out_u - v.bnd[S].val[:,:1,:] = v.bnd[S].val[:,:1,:] * lnot(if_s_out_v) \ - + v_bnd_s_corr * if_s_out_v - w.bnd[S].val[:,:1,:] = w.bnd[S].val[:,:1,:] * lnot(if_s_out_w) \ - + w_bnd_s_corr * if_s_out_w - - u_bnd_n_corr = (u.bnd[N].val[:,:1,:] + ub_out * dt * du_dy_n) - v_bnd_n_corr = (v.bnd[N].val[:,:1,:] + ub_out * dt * dv_dy_n) - w_bnd_n_corr = (w.bnd[N].val[:,:1,:] + ub_out * dt * dw_dy_n) - - u.bnd[N].val[:,:1,:] = u.bnd[N].val[:,:1,:] * lnot(if_n_out_u) \ - + u_bnd_n_corr * if_n_out_u - v.bnd[N].val[:,:1,:] = v.bnd[N].val[:,:1,:] * lnot(if_n_out_v) \ - + v_bnd_n_corr * if_n_out_v - w.bnd[N].val[:,:1,:] = w.bnd[N].val[:,:1,:] * lnot(if_n_out_w) \ - + w_bnd_n_corr * if_n_out_w - - u_bnd_b_corr = (u.bnd[B].val[:,:,:1] + ub_out * dt * du_dz_b) - v_bnd_b_corr = (v.bnd[B].val[:,:,:1] + ub_out * dt * dv_dz_b) - w_bnd_b_corr = (w.bnd[B].val[:,:,:1] + ub_out * dt * dw_dz_b) - - u.bnd[B].val[:,:,:1] = u.bnd[B].val[:,:,:1] * lnot(if_b_out_u) \ - + u_bnd_b_corr * if_b_out_u - v.bnd[B].val[:,:,:1] = v.bnd[B].val[:,:,:1] * lnot(if_b_out_v) \ - + v_bnd_b_corr * if_b_out_v - w.bnd[B].val[:,:,:1] = w.bnd[B].val[:,:,:1] * lnot(if_b_out_w) \ - + w_bnd_b_corr * if_b_out_w - - u_bnd_t_corr = (u.bnd[T].val[:,:,:1] + ub_out *dt * du_dz_t) - v_bnd_t_corr = (v.bnd[T].val[:,:,:1] + ub_out *dt * dv_dz_t) - w_bnd_t_corr = (w.bnd[T].val[:,:,:1] + ub_out *dt * dw_dz_t) - - u.bnd[T].val[:,:,:1] = u.bnd[T].val[:,:,:1] * lnot(if_t_out_u) \ - + u_bnd_t_corr * if_t_out_u - v.bnd[T].val[:,:,:1] = v.bnd[T].val[:,:,:1] * lnot(if_t_out_v) \ - + v_bnd_t_corr * if_t_out_v - w.bnd[T].val[:,:,:1] = w.bnd[T].val[:,:,:1] * lnot(if_t_out_w) \ - + w_bnd_t_corr * if_t_out_w - - if verbatim == True: - print('+----------------------------+' ) - print('| ub_in = %12.5e |' %ub_in ) - print('| a_in = %12.5e |' %area_in ) - print('| v_in = %12.5e |' %vol_in ) - print('| ub_out = %12.5e |' %ub_out ) - print('| a_out = %12.5e |' %area_out ) - print('| v_out_1 = %12.5e |' %vol_out_1) - - #---------------------------------------------- - # Scaling correction to whatever you did above - # (bulk correction or convective outflow) - #---------------------------------------------- - vol_out_2 = 0.0 - vol_out_2 -= (if_w_out_u * u.bnd[W].val[:1,:,:] * sx).sum() - vol_out_2 += (if_e_out_u * u.bnd[E].val[:1,:,:] * sx).sum() - vol_out_2 -= (if_s_out_v * v.bnd[S].val[:,:1,:] * sy).sum() - vol_out_2 += (if_n_out_v * v.bnd[N].val[:,:1,:] * sy).sum() - vol_out_2 -= (if_b_out_w * w.bnd[B].val[:,:,:1] * sz).sum() - vol_out_2 += (if_t_out_w * w.bnd[T].val[:,:,:1] * sz).sum() - - if vol_out_2 > TINY: - factor = vol_in / vol_out_2 - else: - factor = 1.0 - - if verbatim == True: - print('+----------------------------+') - print('| v_out_2 = %12.5e |' %vol_out_2) - print('| factor = %12.5e |' %factor ) - print('+----------------------------+') - - #-------------------------------------- - # Correction to satisfy volume balance - #-------------------------------------- - u.bnd[W].val[:1,:,:] = u.bnd[W].val[:1,:,:] * lnot(if_w_out_u) \ - + u.bnd[W].val[:1,:,:] * if_w_out_u * factor - u.bnd[E].val[:1,:,:] = u.bnd[E].val[:1,:,:] * lnot(if_e_out_u) \ - + u.bnd[E].val[:1,:,:] * if_e_out_u * factor - v.bnd[S].val[:,:1,:] = v.bnd[S].val[:,:1,:] * lnot(if_s_out_v) \ - + v.bnd[S].val[:,:1,:] * if_s_out_v * factor - v.bnd[N].val[:,:1,:] = v.bnd[N].val[:,:1,:] * lnot(if_n_out_v) \ - + v.bnd[N].val[:,:1,:] * if_n_out_v * factor - w.bnd[B].val[:,:,:1] = w.bnd[B].val[:,:,:1] * lnot(if_b_out_w) \ - + w.bnd[B].val[:,:,:1] * if_b_out_w * factor - w.bnd[T].val[:,:,:1] = w.bnd[T].val[:,:,:1] * lnot(if_t_out_w) \ - + w.bnd[T].val[:,:,:1] * if_t_out_w * factor - - return # another end of function diff --git a/PYTHON/Discretization/adj_o_bnds_new.py b/PYTHON/Discretization/adj_o_bnds_new.py deleted file mode 100644 index a160065..0000000 --- a/PYTHON/Discretization/adj_o_bnds_new.py +++ /dev/null @@ -1,284 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from constants.all import * -from operators.all import * - -#========================================================================== -def adj_o_bnds(uvw, dxyz, dt): -#-------------------------------------------------------------------------- - - # Unpack tuples - u, v, w = uvw - dx, dy, dz = dxyz - - # Local variables used in this function - area_in = 0.0 # area of the inlet - area_out = 0.0 # area of the outlet - vol_in = 0.0 # inlet volume flux; positive for inflow - vol_out_1 = 0.0 # outlet volume flux; positive for outflow - vol_out_2 = 0.0 # outlet volume flux; positive for outflow - - verbatim = False - - sx = dy * dz - sy = dx * dz - sz = dx * dy - - sx = sx[:1,:,:] - sy = sy[:,:1,:] - sz = sz[:,:,:1] - - #------------------------------------------------------------------ - # Compute the volume flowing in (v_in), volume flowing out (v_out) - # as well as inlet and outlet areas (a_in, a_out) - #------------------------------------------------------------------ - - # Inlets: these arrays will hold values true (1) in cells \ - # with inlet boundary conditions, and false (0) otherwise - if_w_in = (u.bnd[W].typ[:1,:,:]==DIRICHLET) & (u.bnd[W].val[:1,:,:]>+TINY) - if_e_in = (u.bnd[E].typ[:1,:,:]==DIRICHLET) & (u.bnd[E].val[:1,:,:]<-TINY) - if_s_in = (v.bnd[S].typ[:,:1,:]==DIRICHLET) & (v.bnd[S].val[:,:1,:]>+TINY) - if_n_in = (v.bnd[N].typ[:,:1,:]==DIRICHLET) & (v.bnd[N].val[:,:1,:]<-TINY) - if_b_in = (w.bnd[B].typ[:,:,:1]==DIRICHLET) & (w.bnd[B].val[:,:,:1]>+TINY) - if_t_in = (w.bnd[T].typ[:,:,:1]==DIRICHLET) & (w.bnd[T].val[:,:,:1]<-TINY) - - # Using the arrays defined above, compute inlet surface area - area_in = area_in + (if_w_in * sx).sum() - area_in = area_in + (if_e_in * sx).sum() - area_in = area_in + (if_s_in * sy).sum() - area_in = area_in + (if_n_in * sy).sum() - area_in = area_in + (if_b_in * sz).sum() - area_in = area_in + (if_t_in * sz).sum() - - # If there is no inlet, nothing to do here any longer - if area_in < TINY: - return u, v, w # one end of function - - # Using the arrays defined above, compute inlet volume flux - vol_in += (if_w_in * u.bnd[W].val[:1,:,:] * sx).sum() - vol_in -= (if_e_in * u.bnd[E].val[:1,:,:] * sx).sum() - vol_in += (if_s_in * v.bnd[S].val[:,:1,:] * sy).sum() - vol_in -= (if_n_in * v.bnd[N].val[:,:1,:] * sy).sum() - vol_in += (if_b_in * w.bnd[B].val[:,:,:1] * sz).sum() - vol_in -= (if_t_in * w.bnd[T].val[:,:,:1] * sz).sum() - - # Outlets: these arrays will hold values true (1) in cells ... - # with outlet boundary conditions, and false (0) otherwise - if_w_out_u = ( u.bnd[W].typ[:1,:,:] == OUTLET ) - if_w_out_v = avg(v.pos, if_w_out_u*1) > 0.5 - if_w_out_w = avg(w.pos, if_w_out_u*1) > 0.5 - - if_e_out_u = ( u.bnd[E].typ[:1,:,:] == OUTLET ) - if_e_out_v = avg(v.pos, if_e_out_u*1) > 0.5 - if_e_out_w = avg(w.pos, if_e_out_u*1) > 0.5 - - if_s_out_v = ( v.bnd[S].typ[:,:1,:] == OUTLET ) - if_s_out_u = avg(u.pos, if_s_out_v*1) > 0.5 - if_s_out_w = avg(w.pos, if_s_out_v*1) > 0.5 - - if_n_out_v = ( v.bnd[N].typ[:,:1,:] == OUTLET ) - if_n_out_u = avg(u.pos, if_n_out_v*1) > 0.5 - if_n_out_w = avg(w.pos, if_n_out_v*1) > 0.5 - - if_b_out_w = ( w.bnd[B].typ[:,:,:1] == OUTLET ) - if_b_out_u = avg(u.pos, if_b_out_w*1) > 0.5 - if_b_out_v = avg(v.pos, if_b_out_w*1) > 0.5 - - if_t_out_w = ( w.bnd[T].typ[:,:,:1] == OUTLET ) - if_t_out_u = avg(u.pos, if_t_out_w*1) > 0.5 - if_t_out_v = avg(v.pos, if_t_out_w*1) > 0.5 - - # Using the arrays defined above, compute outlet surface area - area_out += (if_w_out_u * sx).sum() - area_out += (if_e_out_u * sx).sum() - area_out += (if_s_out_v * sy).sum() - area_out += (if_n_out_v * sy).sum() - area_out += (if_b_out_w * sz).sum() - area_out += (if_t_out_w * sz).sum() - - # Using the arrays defined above, compute outlet volume flux - vol_out_1 -= (if_w_out_u * u.bnd[W].val[:1,:,:] * sx).sum() - vol_out_1 += (if_e_out_u * u.bnd[E].val[:1,:,:] * sx).sum() - vol_out_1 -= (if_s_out_v * v.bnd[S].val[:,:1,:] * sy).sum() - vol_out_1 += (if_n_out_v * v.bnd[N].val[:,:1,:] * sy).sum() - vol_out_1 -= (if_b_out_w * w.bnd[B].val[:,:,:1] * sz).sum() - vol_out_1 += (if_t_out_w * w.bnd[T].val[:,:,:1] * sz).sum() - - #--------------------------------- - # Check and calculate corrections - #--------------------------------- - - if (area_in == 0): - ub_in = 0 - else: - ub_in = vol_in / area_in - - if (area_out == 0): - ub_out = 0 - else: - ub_out = vol_out_1 / area_out - - #---------------------------------------------- - # If nothing comes out, make a bulk correction - #---------------------------------------------- - if(ub_out < TINY): - u_bulk_corr = ub_in * area_in / area_out - - u.bnd[W].val[:1,:,:] = u.bnd[W].val[:1,:,:] * lnot(if_w_out_u) \ - - u_bulk_corr * if_w_out_u - u.bnd[E].val[:1,:,:] = u.bnd[E].val[:1,:,:] * lnot(if_e_out_u) \ - + u_bulk_corr * if_e_out_u - v.bnd[S].val[:,:1,:] = v.bnd[S].val[:,:1,:] * lnot(if_s_out_v) \ - - u_bulk_corr * if_s_out_v - v.bnd[N].val[:,:1,:] = v.bnd[N].val[:,:1,:] * lnot(if_n_out_v) \ - + u_bulk_corr * if_n_out_v - w.bnd[B].val[:,:,:1] = w.bnd[B].val[:,:,:1] * lnot(if_b_out_w) \ - - u_bulk_corr * if_b_out_w - w.bnd[T].val[:,:,:1] = w.bnd[T].val[:,:,:1] * lnot(if_t_out_w) \ - + u_bulk_corr * if_t_out_w - - #-------------------------------------------------------------- - # Correction outflow by applying convective boundary condition - #-------------------------------------------------------------- - else: - du_dx_w = (u.val[ :1,:,:]-u.bnd[W].val[:1,:,:]) / dx[ :1,:,:] - dv_dx_w = (v.val[ :1,:,:]-v.bnd[W].val[:1,:,:]) / avg(v.pos, dx[ :1,:,:]) - dw_dx_w = (w.val[ :1,:,:]-w.bnd[W].val[:1,:,:]) / avg(w.pos, dx[ :1,:,:]) - - du_dx_e = (u.val[-1:,:,:]-u.bnd[E].val[:1,:,:]) / dx[-1:,:,:] - dv_dx_e = (v.val[-1:,:,:]-v.bnd[E].val[:1,:,:]) / avg(v.pos, dx[-1:,:,:]) - dw_dx_e = (w.val[-1:,:,:]-w.bnd[E].val[:1,:,:]) / avg(w.pos, dx[-1:,:,:]) - - du_dy_s = (u.val[:, :1,:]-u.bnd[S].val[:,:1,:]) / avg(u.pos, dy[:, :1,:]) - dv_dy_s = (v.val[:, :1,:]-v.bnd[S].val[:,:1,:]) / dy[:, :1,:] - dw_dy_s = (w.val[:, :1,:]-w.bnd[S].val[:,:1,:]) / avg(w.pos, dy[:, :1,:]) - - du_dy_n = (u.val[:,-1:,:]-u.bnd[N].val[:,:1,:]) / avg(u.pos, dy[:,-1:,:]) - dv_dy_n = (v.val[:,-1:,:]-v.bnd[N].val[:,:1,:]) / dy[:,-1:,:] - dw_dy_n = (w.val[:,-1:,:]-w.bnd[N].val[:,:1,:]) / avg(w.pos, dy[:,-1:,:]) - - du_dz_b = (u.val[:,:, :1]-u.bnd[B].val[:,:,:1]) / avg(u.pos, dz[:,:, :1]) - dv_dz_b = (v.val[:,:, :1]-v.bnd[B].val[:,:,:1]) / avg(v.pos, dz[:,:, :1]) - dw_dz_b = (w.val[:,:, :1]-w.bnd[B].val[:,:,:1]) / dz[:,:, :1] - - du_dz_t = (u.val[:,:,-1:]-u.bnd[T].val[:,:,:1]) / avg(u.pos, dz[:,:,-1:]) - dv_dz_t = (v.val[:,:,-1:]-v.bnd[T].val[:,:,:1]) / avg(v.pos, dz[:,:,-1:]) - dw_dz_t = (w.val[:,:,-1:]-w.bnd[T].val[:,:,:1]) / dz[:,:,-1:] - - u_bnd_w_corr = (u.bnd[W].val[:1,:,:] + ub_out * dt * du_dx_w) - v_bnd_w_corr = (v.bnd[W].val[:1,:,:] + ub_out * dt * dv_dx_w) - w_bnd_w_corr = (w.bnd[W].val[:1,:,:] + ub_out * dt * dw_dx_w) - - u.bnd[W].val[:1,:,:] = u.bnd[W].val[:1,:,:] * lnot(if_w_out_u) \ - + u_bnd_w_corr * if_w_out_u - v.bnd[W].val[:1,:,:] = v.bnd[W].val[:1,:,:] * lnot(if_w_out_v) \ - + v_bnd_w_corr * if_w_out_v - w.bnd[W].val[:1,:,:] = w.bnd[W].val[:1,:,:] * lnot(if_w_out_w) \ - + w_bnd_w_corr * if_w_out_w - - u_bnd_e_corr = (u.bnd[E].val[:1,:,:] + ub_out * dt * du_dx_e) - v_bnd_e_corr = (v.bnd[E].val[:1,:,:] + ub_out * dt * dv_dx_e) - w_bnd_e_corr = (w.bnd[E].val[:1,:,:] + ub_out * dt * dw_dx_e) - - u.bnd[E].val[:1,:,:] = u.bnd[E].val[:1,:,:] * lnot(if_e_out_u) \ - + u_bnd_e_corr * if_e_out_u - v.bnd[E].val[:1,:,:] = v.bnd[E].val[:1,:,:] * lnot(if_e_out_v) \ - + v_bnd_e_corr * if_e_out_v - w.bnd[E].val[:1,:,:] = w.bnd[E].val[:1,:,:] * lnot(if_e_out_w) \ - + w_bnd_e_corr * if_e_out_w - - u_bnd_s_corr = (u.bnd[S].val[:,:1,:] + ub_out * dt * du_dy_s) - v_bnd_s_corr = (v.bnd[S].val[:,:1,:] + ub_out * dt * dv_dy_s) - w_bnd_s_corr = (w.bnd[S].val[:,:1,:] + ub_out * dt * dw_dy_s) - - u.bnd[S].val[:,:1,:] = u.bnd[S].val[:,:1,:] * lnot(if_s_out_u) \ - + u_bnd_s_corr * if_s_out_u - v.bnd[S].val[:,:1,:] = v.bnd[S].val[:,:1,:] * lnot(if_s_out_v) \ - + v_bnd_s_corr * if_s_out_v - w.bnd[S].val[:,:1,:] = w.bnd[S].val[:,:1,:] * lnot(if_s_out_w) \ - + w_bnd_s_corr * if_s_out_w - - u_bnd_n_corr = (u.bnd[N].val[:,:1,:] + ub_out * dt * du_dy_n) - v_bnd_n_corr = (v.bnd[N].val[:,:1,:] + ub_out * dt * dv_dy_n) - w_bnd_n_corr = (w.bnd[N].val[:,:1,:] + ub_out * dt * dw_dy_n) - - u.bnd[N].val[:,:1,:] = u.bnd[N].val[:,:1,:] * lnot(if_n_out_u) \ - + u_bnd_n_corr * if_n_out_u - v.bnd[N].val[:,:1,:] = v.bnd[N].val[:,:1,:] * lnot(if_n_out_v) \ - + v_bnd_n_corr * if_n_out_v - w.bnd[N].val[:,:1,:] = w.bnd[N].val[:,:1,:] * lnot(if_n_out_w) \ - + w_bnd_n_corr * if_n_out_w - - u_bnd_b_corr = (u.bnd[B].val[:,:,:1] + ub_out * dt * du_dz_b) - v_bnd_b_corr = (v.bnd[B].val[:,:,:1] + ub_out * dt * dv_dz_b) - w_bnd_b_corr = (w.bnd[B].val[:,:,:1] + ub_out * dt * dw_dz_b) - - u.bnd[B].val[:,:,:1] = u.bnd[B].val[:,:,:1] * lnot(if_b_out_u) \ - + u_bnd_b_corr * if_b_out_u - v.bnd[B].val[:,:,:1] = v.bnd[B].val[:,:,:1] * lnot(if_b_out_v) \ - + v_bnd_b_corr * if_b_out_v - w.bnd[B].val[:,:,:1] = w.bnd[B].val[:,:,:1] * lnot(if_b_out_w) \ - + w_bnd_b_corr * if_b_out_w - - u_bnd_t_corr = (u.bnd[T].val[:,:,:1] + ub_out *dt * du_dz_t) - v_bnd_t_corr = (v.bnd[T].val[:,:,:1] + ub_out *dt * dv_dz_t) - w_bnd_t_corr = (w.bnd[T].val[:,:,:1] + ub_out *dt * dw_dz_t) - - u.bnd[T].val[:,:,:1] = u.bnd[T].val[:,:,:1] * lnot(if_t_out_u) \ - + u_bnd_t_corr * if_t_out_u - v.bnd[T].val[:,:,:1] = v.bnd[T].val[:,:,:1] * lnot(if_t_out_v) \ - + v_bnd_t_corr * if_t_out_v - w.bnd[T].val[:,:,:1] = w.bnd[T].val[:,:,:1] * lnot(if_t_out_w) \ - + w_bnd_t_corr * if_t_out_w - - if verbatim == True: - print('+----------------------------+' ) - print('| ub_in = %12.5e |' %ub_in ) - print('| a_in = %12.5e |' %area_in ) - print('| v_in = %12.5e |' %vol_in ) - print('| ub_out = %12.5e |' %ub_out ) - print('| a_out = %12.5e |' %area_out ) - print('| v_out_1 = %12.5e |' %vol_out_1) - - #---------------------------------------------- - # Scaling correction to whatever you did above - # (bulk correction or convective outflow) - #---------------------------------------------- - vol_out_2 = 0.0 - vol_out_2 -= (if_w_out_u * u.bnd[W].val[:1,:,:] * sx).sum() - vol_out_2 += (if_e_out_u * u.bnd[E].val[:1,:,:] * sx).sum() - vol_out_2 -= (if_s_out_v * v.bnd[S].val[:,:1,:] * sy).sum() - vol_out_2 += (if_n_out_v * v.bnd[N].val[:,:1,:] * sy).sum() - vol_out_2 -= (if_b_out_w * w.bnd[B].val[:,:,:1] * sz).sum() - vol_out_2 += (if_t_out_w * w.bnd[T].val[:,:,:1] * sz).sum() - - if vol_out_2 > TINY: - factor = vol_in / vol_out_2 - else: - factor = 1.0 - - if verbatim == True: - print('+----------------------------+') - print('| v_out_2 = %12.5e |' %vol_out_2) - print('| factor = %12.5e |' %factor ) - print('+----------------------------+') - - #-------------------------------------- - # Correction to satisfy volume balance - #-------------------------------------- - u.bnd[W].val[:1,:,:] = u.bnd[W].val[:1,:,:] * lnot(if_w_out_u) \ - + u.bnd[W].val[:1,:,:] * if_w_out_u * factor - u.bnd[E].val[:1,:,:] = u.bnd[E].val[:1,:,:] * lnot(if_e_out_u) \ - + u.bnd[E].val[:1,:,:] * if_e_out_u * factor - v.bnd[S].val[:,:1,:] = v.bnd[S].val[:,:1,:] * lnot(if_s_out_v) \ - + v.bnd[S].val[:,:1,:] * if_s_out_v * factor - v.bnd[N].val[:,:1,:] = v.bnd[N].val[:,:1,:] * lnot(if_n_out_v) \ - + v.bnd[N].val[:,:1,:] * if_n_out_v * factor - w.bnd[B].val[:,:,:1] = w.bnd[B].val[:,:,:1] * lnot(if_b_out_w) \ - + w.bnd[B].val[:,:,:1] * if_b_out_w * factor - w.bnd[T].val[:,:,:1] = w.bnd[T].val[:,:,:1] * lnot(if_t_out_w) \ - + w.bnd[T].val[:,:,:1] * if_t_out_w * factor - - return u, v, w # another end of function diff --git a/PYTHON/Discretization/advection.py b/PYTHON/Discretization/advection.py deleted file mode 100644 index b895317..0000000 --- a/PYTHON/Discretization/advection.py +++ /dev/null @@ -1,291 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -#========================================================================== -def advection(rho, phi, uvwf, dxyz, dt, lim_name): -#-------------------------------------------------------------------------- - - res = phi.val.shape - nx, ny, nz = res - - # Unpack tuples - uf, vf, wf = uvwf - dx, dy, dz = dxyz - - d = phi.pos - - # Pre-compute geometrical quantities - sx = dy * dz - sy = dx * dz - sz = dx * dy - - #------------------------------------------------- - # Specific for cell-centered transported variable - #------------------------------------------------- - if d == C: - - # Facial values of physical properties including boundary cells - rho_x_fac = cat(X, (rho[:1,:,:], avg(X, rho), rho[-1:,:,:])) # nxp,ny, nz - rho_y_fac = cat(Y, (rho[:,:1,:], avg(Y, rho), rho[:,-1:,:])) # nx, nyp,nz - rho_z_fac = cat(Z, (rho[:,:,:1], avg(Z, rho), rho[:,:,-1:])) # nx, ny, nzp - - # Facial values of areas including boundary cells - a_x_fac = cat(X, (sx[:1,:,:], avg(X, sx), sx[-1:,:,:])) - a_y_fac = cat(Y, (sy[:,:1,:], avg(Y, sy), sy[:,-1:,:])) - a_z_fac = cat(Z, (sz[:,:,:1], avg(Z, sz), sz[:,:,-1:])) - - del_x = avg(X, dx) - del_y = avg(Y, dy) - del_z = avg(Z, dz) - - # Facial values of velocities without boundary values - u_fac = uf.val # nxm,ny, nz - v_fac = vf.val # nx, nym,nz - w_fac = wf.val # nx, ny, nzm - - # Boundary velocity values - u_bnd_W = uf.bnd[W].val - u_bnd_E = uf.bnd[E].val - v_bnd_S = vf.bnd[S].val - v_bnd_N = vf.bnd[N].val - w_bnd_B = wf.bnd[B].val - w_bnd_T = wf.bnd[T].val - - #------------------------------------------------------------ - # Specific for transported variable staggered in x direction - #------------------------------------------------------------ - if d == X: - - # Facial values of physical properties including boundary cells - rho_x_fac = rho # nx, ny, nz - rho_nod_y = avg(X, avg(Y, rho) ) # nxm,nym,nz - rho_y_fac = cat(Y, (rho_nod_y[:, :1, :], \ - rho_nod_y[:, :, :], \ - rho_nod_y[:,-1:,:])) # nxm,nyp,nz - rho_nod_z = avg(X, avg(Z, rho) ) # nxm,ny,nzm - rho_z_fac = cat(Z, (rho_nod_z[:,:, :1], \ - rho_nod_z[:,:, :], \ - rho_nod_z[:,:,-1:])) # nxm,ny,nzp - - # Facial values of areas including boundary cells - a_x_fac = sx - a_y_fac = cat(Y, ( \ - avg(X,sy[:,:1,:]), avg(X,avg(Y,sy)), avg(X,sy[:,-1:,:]))) - a_z_fac = cat(Z, ( \ - avg(X,sz[:,:,:1]), avg(X,avg(Z,sz)), avg(X,sz[:,:,-1:]))) - - del_x = dx[1:-1,:,:] - del_y = avg(X, avg(Y, dy)) - del_z = avg(X, avg(Z, dz)) - - # Facial values of velocities without boundary values - u_fac = avg(X, uf.val) # nxmm,ny, nz - v_fac = avg(X, vf.val) # nxm, nym,nz - w_fac = avg(X, wf.val) # nxm, ny, nzm - - # Boundary velocity values - u_bnd_W = uf.bnd[W].val - u_bnd_E = uf.bnd[E].val - v_bnd_S = avg(X, vf.bnd[S].val) - v_bnd_N = avg(X, vf.bnd[N].val) - w_bnd_B = avg(X, wf.bnd[B].val) - w_bnd_T = avg(X, wf.bnd[T].val) - - #------------------------------------------------------------ - # Specific for transported variable staggered in y direction - #------------------------------------------------------------ - if d == Y: - - # Facial values of physical properties including boundary cells - rho_nod_x = avg(Y, avg(X, rho) ) # nxm,nym,nz - rho_x_fac = cat(X, (rho_nod_x[ :1,:,:], \ - rho_nod_x[ :,:,:], \ - rho_nod_x[-1:,:,:])) # nxp,nym,nz - rho_y_fac = rho # nx, ny, nz - rho_nod_z = avg(Y, avg(Z, rho) ) # nx, nym,nzm - rho_z_fac = cat(Z, (rho_nod_z[:,:, :1], \ - rho_nod_z[:,:, :], \ - rho_nod_z[:,:,-1:])) # nx, nym,nzp - - # Facial values of areas including boundary cells - a_x_fac = cat(X, ( \ - avg(Y, sx[:1,:,:]), \ - avg(Y, avg(X,sx)), \ - avg(Y, sx[-1:,:,:]))) - a_y_fac = sy - a_z_fac = cat(Z, ( \ - avg(Y, sz[:,:,:1]), \ - avg(Y, avg(Z,sz)), \ - avg(Y, sz[:,:,-1:]))) - - del_x = avg(Y, avg(X, dx)) - del_y = dy[:,1:-1,:] - del_z = avg(Y, avg(Z, dz)) - - # Facial values of velocities without boundary values - u_fac = avg(Y, uf.val) # nxm,nym, nz - v_fac = avg(Y, vf.val) # nx, nymm,nz - w_fac = avg(Y, wf.val) # nx, nym, nzm - - # Facial values of velocities with boundary values - u_bnd_W = avg(Y, uf.bnd[W].val) - u_bnd_E = avg(Y, uf.bnd[E].val) - v_bnd_S = vf.bnd[S].val - v_bnd_N = vf.bnd[N].val - w_bnd_B = avg(Y, wf.bnd[B].val) - w_bnd_T = avg(Y, wf.bnd[T].val) - - #------------------------------------------------------------ - # Specific for transported variable staggered in z direction - #------------------------------------------------------------ - if d == Z: - - # Facial values of physical properties including boundary cells - rho_nod_x = avg(Z, avg(X, rho) ) # nxm,ny, nzm - rho_x_fac = cat(X, (rho_nod_x[ :1,:,:], \ - rho_nod_x[ :,:,:], \ - rho_nod_x[-1:,:,:])) # nxp,ny, nzm - rho_nod_y = avg(Z, avg(Y, rho) ) # nx, nym,nzm - rho_y_fac = cat(Y, (rho_nod_y[:, :1,:], \ - rho_nod_y[:, :,:], \ - rho_nod_y[:,-1:,:])) # nx, nyp,nzm - rho_z_fac = rho # nx, ny, nz - - # Facial values of areas including boundary cells - a_x_fac = cat(X, ( \ - avg(Z, sx[:1,:,:]), \ - avg(Z, avg(X,sx)), \ - avg(Z, sx[-1:,:,:]))) - a_y_fac = cat(Y, ( \ - avg(Z, sy[:,:1,:]), \ - avg(Z, avg(Y,sy)), \ - avg(Z, sy[:,-1:,:]))) - a_z_fac = sz - - del_x = avg(Z, avg(X,dx)) - del_y = avg(Z, avg(Y,dy)) - del_z = dz[:,:,1:-1] - - # Facial values of velocities without boundary values - u_fac = avg(Z, uf.val) # nxm,ny, nzm - v_fac = avg(Z, vf.val) # nx, nym, nzm - w_fac = avg(Z, wf.val) # nx, ny, nzmm - - # Facial values of velocities with boundary values - u_bnd_W = avg(Z, uf.bnd[W].val) - u_bnd_E = avg(Z, uf.bnd[E].val) - v_bnd_S = avg(Z, vf.bnd[S].val) - v_bnd_N = avg(Z, vf.bnd[N].val) - w_bnd_B = wf.bnd[B].val - w_bnd_T = wf.bnd[T].val - - #------------------------------ - # Common part of the algorithm - #------------------------------ - - #------------------------------------------------------------ - # - # |-o-|-o-|-o-|-o-|-o-|-o-|-o-|-o-|-o-|-o-| - # 1 2 3 4 5 6 7 8 9 10 phi - # x---x---x---x---x---x---x---x---x - # 1 2 3 4 5 6 7 8 9 d_x initial - # 0---x---x---x---x---x---x---x---x---x---0 - # 1 2 3 4 5 6 7 8 9 10 11 d_x padded - # - #------------------------------------------------------------ - - # Compute consecutive differences (and avoid division by zero) - d_x = dif(X, phi.val) # nxm, ny, nz - d_x[(d_x > -TINY) & (d_x <= 0.0)] = -TINY - d_x[(d_x >= 0.0) & (d_x < +TINY)] = +TINY - d_x = cat(X, (d_x[:1,:,:], d_x, d_x[-1:,:,:])) # nxp, ny, nz - - d_y = dif(Y, phi.val) # nx, nym, nz - d_y[(d_y > -TINY) & (d_y <= 0.0)] = -TINY - d_y[(d_y >= 0.0) & (d_y < +TINY)] = +TINY - d_y = cat(Y, (d_y[:,:1,:], d_y, d_y[:,-1:,:])) # nx, nyp, nz - - d_z = dif(Z, phi.val) # nx, ny, nzm - d_z[(d_z > -TINY) & (d_z <= 0.0)] = -TINY - d_z[(d_z >= 0.0) & (d_z < +TINY)] = +TINY - d_z = cat(Z, (d_z[:,:,:1], d_z, d_z[:,:,-1:])) # nx, ny, nzp - - # Ratio of consecutive gradients for positive and negative flow - r_x_we = d_x[1:-1,:,:] / d_x[0:-2,:,:] # nxm,ny, nz - r_x_ew = d_x[2:, :,:] / d_x[1:-1,:,:] # nxm,ny, nz - r_y_sn = d_y[:,1:-1,:] / d_y[:,0:-2,:] # nx, nym,nz - r_y_ns = d_y[:,2:, :] / d_y[:,1:-1,:] # nx, nym,nz - r_z_bt = d_z[:,:,1:-1] / d_z[:,:,0:-2] # nx, ny, nzm - r_z_tb = d_z[:,:,2: ] / d_z[:,:,1:-1] # nx, ny, nzm - - flow_we = u_fac >= 0 - flow_ew = lnot(flow_we) - flow_sn = v_fac >= 0 - flow_ns = lnot(flow_sn) - flow_bt = w_fac >= 0 - flow_tb = lnot(flow_bt) - - r_x = r_x_we * flow_we + r_x_ew * flow_ew - r_y = r_y_sn * flow_sn + r_y_ns * flow_ns - r_z = r_z_bt * flow_bt + r_z_tb * flow_tb - - # Apply a limiter - if lim_name == 'upwind': - psi_x = r_x * 0.0 - psi_y = r_y * 0.0 - psi_z = r_z * 0.0 - elif lim_name == 'minmod': - psi_x = mx(zeros(r_x.shape), mn(r_x, ones(r_x.shape))) - psi_y = mx(zeros(r_y.shape), mn(r_y, ones(r_y.shape))) - psi_z = mx(zeros(r_z.shape), mn(r_z, ones(r_z.shape))) - elif lim_name == 'superbee': - psi_x = mx(zeros(r_x.shape), mn(2.*r_x, ones(r_x.shape)), mn(r_x, 2.)) - psi_y = mx(zeros(r_y.shape), mn(2.*r_y, ones(r_y.shape)), mn(r_y, 2.)) - psi_z = mx(zeros(r_z.shape), mn(2.*r_z, ones(r_z.shape)), mn(r_z, 2.)) - elif lim_name == 'koren': - psi_x = mx(zeros(r_x.shape), mn(2.*r_x, (2.+r_x)/3., 2.*ones(r_x.shape))) - psi_y = mx(zeros(r_y.shape), mn(2.*r_y, (2.+r_y)/3., 2.*ones(r_y.shape))) - psi_z = mx(zeros(r_z.shape), mn(2.*r_z, (2.+r_z)/3., 2.*ones(r_z.shape))) - - flux_fac_lim_x = phi.val[0:-1,:,:] * u_fac * flow_we \ - + phi.val[1:, :,:] * u_fac * flow_ew \ - + 0.5 * abs(u_fac) * (1 - abs(u_fac) * dt / del_x) \ - * ( psi_x[:,:,:] * d_x[0:nx-1,:,:] * flow_we \ - + psi_x[:,:,:] * d_x[1:nx, :,:] * flow_ew ) - flux_fac_lim_y = phi.val[:,0:-1,:] * v_fac * flow_sn \ - + phi.val[:,1: ,:] * v_fac * flow_ns \ - + 0.5 * abs(v_fac) * (1 - abs(v_fac) * dt / del_y) \ - * ( psi_y[:,:,:] * d_y[:,0:ny-1,:] * flow_sn \ - + psi_y[:,:,:] * d_y[:,1:ny, :] * flow_ns ) - flux_fac_lim_z = phi.val[:,:,0:-1] * w_fac * flow_bt \ - + phi.val[:,:,1: ] * w_fac * flow_tb \ - + 0.5 * abs(w_fac) * (1 - abs(w_fac) * dt / del_z) \ - * ( psi_z[:,:,:] * d_z[:,:,0:nz-1] * flow_bt \ - + psi_z[:,:,:] * d_z[:,:,1:nz ] * flow_tb ) - - # Pad with boundary values - flux_fac_lim_x = cat(X, (phi.bnd[W].val * u_bnd_W, \ - flux_fac_lim_x, \ - phi.bnd[E].val * u_bnd_E)) - flux_fac_lim_y = cat(Y, (phi.bnd[S].val * v_bnd_S, \ - flux_fac_lim_y, \ - phi.bnd[N].val * v_bnd_N)) - flux_fac_lim_z = cat(Z, (phi.bnd[B].val * w_bnd_B, \ - flux_fac_lim_z, \ - phi.bnd[T].val * w_bnd_T)) - - # Multiply with face areas - flux_fac_lim_x = rho_x_fac * flux_fac_lim_x * a_x_fac - flux_fac_lim_y = rho_y_fac * flux_fac_lim_y * a_y_fac - flux_fac_lim_z = rho_z_fac * flux_fac_lim_z * a_z_fac - - # Sum contributions from all directions up - c = dif(X, flux_fac_lim_x) + \ - dif(Y, flux_fac_lim_y) + \ - dif(Z, flux_fac_lim_z) - - return c # end of function \ No newline at end of file diff --git a/PYTHON/Discretization/all.py b/PYTHON/Discretization/all.py deleted file mode 100644 index a8bb80d..0000000 --- a/PYTHON/Discretization/all.py +++ /dev/null @@ -1,16 +0,0 @@ -# Discretization -from Discretization.adj_n_bnds import adj_n_bnds -from Discretization.adj_o_bnds import adj_o_bnds -from Discretization.advection import advection -from Discretization.calc_p import calc_p -from Discretization.calc_t import calc_t -from Discretization.calc_uvw import calc_uvw -from Discretization.cartesian_grid import cartesian_grid -from Discretization.cfl_max import cfl_max -from Discretization.corr_uvw import corr_uvw -from Discretization.create_matrix import create_matrix -from Discretization.create_unknown import create_unknown -from Discretization.nodes import nodes -from Discretization.obst_mod_matrix import obst_mod_matrix -from Discretization.obst_zero_val import obst_zero_val -from Discretization.vol_balance import vol_balance \ No newline at end of file diff --git a/PYTHON/Discretization/calc_p.py b/PYTHON/Discretization/calc_p.py deleted file mode 100644 index 941d5aa..0000000 --- a/PYTHON/Discretization/calc_p.py +++ /dev/null @@ -1,50 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -from Discretization.adj_n_bnds import adj_n_bnds -from Discretization.create_matrix import create_matrix -from Discretization.vol_balance import vol_balance -from Discretization.obst_zero_val import obst_zero_val - -#========================================================================== -def calc_p(p, uvwf, rho, dt, dxyz, obst ): -#-------------------------------------------------------------------------- - - # Fetch the resolution - rc = p.val.shape - - # Create linear system - A_p, b_p = create_matrix(p, zeros(rc), dt/rho, dxyz, obst, 'n') - - # Compute the source for the pressure. Important: don't send "obst" - # as a parameter here, because you don't want to take it into - # account at this stage. After velocity corrections, you should. - b_p = vol_balance(uvwf, dxyz, zeros(rc)) - - print('Maximum volume error before correction: %12.5e' % abs(b_p).max()) - print('Volume imbalance before correction : %12.5e' % b_p.sum()) - - # Solve for pressure - res = bicgstab( A_p, reshape(b_p, prod(rc)), tol=TOL ) - p.val[:] = reshape(res[0], rc) - - print("res[1] = ", res[1]) - - # Anchor it to values around zero (the absolute value of pressure - # correction can get really volatile. Although it is in prinicple not - # important for incompressible flows, it is ugly for post-processing. - p.val[:] = p.val[:] - p.val.mean() - - # Set to zero in obstacle (it can get strange - # values during the iterative solution procedure) - if obst.any() != 0: - p.val[:] = obst_zero_val(p.pos, p.val, obst) - - # Finally adjust the boundary values - p = adj_n_bnds(p); - - return # end of function \ No newline at end of file diff --git a/PYTHON/Discretization/calc_t.py b/PYTHON/Discretization/calc_t.py deleted file mode 100644 index 2c4b2a7..0000000 --- a/PYTHON/Discretization/calc_t.py +++ /dev/null @@ -1,40 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -from Discretization.adj_n_bnds import adj_n_bnds -from Discretization.advection import advection -from Discretization.create_matrix import create_matrix - -#========================================================================== -def calc_t(t, uvwf, rho_cap, kappa, dt, dxyz, obst): -#-------------------------------------------------------------------------- - - # Unpack tuple(s) - dx, dy, dz = dxyz - - # Fetch the resolution - rc = t.val.shape - - # Discretize the diffusive part - A_t, b_t = create_matrix(t, rho_cap/dt, kappa, dxyz, obst, 'n') - - # The advective fluxes - c_t = advection(rho_cap, t, uvwf, dxyz, dt, 'minmod') - - # Innertial term for enthalpy - i_t = t.old * rho_cap * dx*dy*dz / dt - - # The entire source term - f_t = b_t - c_t + i_t - - # Solve for temperature - res0 = bicgstab( A_t, reshape(f_t, prod(rc)), tol=TOL ) - t.val[:] = reshape(res0[0], rc) - - adj_n_bnds(t) - - return # end of function diff --git a/PYTHON/Discretization/calc_uvw.py b/PYTHON/Discretization/calc_uvw.py deleted file mode 100644 index f708e77..0000000 --- a/PYTHON/Discretization/calc_uvw.py +++ /dev/null @@ -1,124 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -from Discretization.adj_n_bnds import adj_n_bnds -from Discretization.adj_o_bnds import adj_o_bnds -from Discretization.advection import advection -from Discretization.create_matrix import create_matrix -from Discretization.obst_zero_val import obst_zero_val - -#========================================================================== -def calc_uvw(uvw, uvwf, rho, mu, p_tot, e_f, dt, dxyz, obst): -#-------------------------------------------------------------------------- - - # Unpack tuples - u, v, w = uvw - uf, vf, wf = uvwf - dx, dy, dz = dxyz - e_x, e_y, e_z = e_f - - # Fetch resolutions - ru = u.val.shape - rv = v.val.shape - rw = w.val.shape - - # Pre-compute geometrical quantities - dv = dx * dy * dz - - d = u.pos - - # Create linear systems - A_u, b_u = create_matrix(u, rho/dt, mu, dxyz, obst, 'd') - A_v, b_v = create_matrix(v, rho/dt, mu, dxyz, obst, 'd') - A_w, b_w = create_matrix(w, rho/dt, mu, dxyz, obst, 'd') - - # Advection terms for momentum - c_u = advection(rho, u, uvwf, dxyz, dt, 'superbee'); - c_v = advection(rho, v, uvwf, dxyz, dt, 'superbee'); - c_w = advection(rho, w, uvwf, dxyz, dt, 'superbee'); - - # Innertial term for momentum (this works for collocated and staggered) - i_u = u.old * avg(u.pos, rho) * avg(u.pos, dv) / dt - i_v = v.old * avg(v.pos, rho) * avg(v.pos, dv) / dt - i_w = w.old * avg(w.pos, rho) * avg(w.pos, dv) / dt - - # Compute staggered pressure gradients - p_tot_x = dif(X, p_tot) / avg(X, dx) - p_tot_y = dif(Y, p_tot) / avg(Y, dy) - p_tot_z = dif(Z, p_tot) / avg(Z, dz) - - # Make pressure gradients cell-centered - if d == C: - p_tot_x = avg(X, cat(X, (p_tot_x[:1,:,:], p_tot_x, p_tot_x[-1:,:,:]))) - p_tot_y = avg(Y, cat(Y, (p_tot_y[:,:1,:], p_tot_y, p_tot_y[:,-1:,:]))) - p_tot_z = avg(Z, cat(Z, (p_tot_z[:,:,:1], p_tot_z, p_tot_z[:,:,-1:]))) - - # Total pressure gradients (this works for collocated and staggered) - p_st_u = p_tot_x * avg(u.pos, dv) - p_st_v = p_tot_y * avg(v.pos, dv) - p_st_w = p_tot_z * avg(w.pos, dv) - - # Full force terms for momentum equations (collocated and staggered) - f_u = b_u - c_u + i_u - p_st_u + e_x * avg(u.pos, dv) - f_v = b_v - c_v + i_v - p_st_v + e_y * avg(v.pos, dv) - f_w = b_w - c_w + i_w - p_st_w + e_z * avg(w.pos, dv) - - # Take care of obsts in the domian - if obst.any() != 0: - f_u = obst_zero_val(u.pos, f_u, obst) - f_v = obst_zero_val(v.pos, f_v, obst) - f_w = obst_zero_val(w.pos, f_w, obst) - - # Solve for velocities - res0 = bicgstab( A_u, reshape(f_u, prod(ru)), tol=TOL ) - res1 = bicgstab( A_v, reshape(f_v, prod(rv)), tol=TOL ) - res2 = bicgstab( A_w, reshape(f_w, prod(rw)), tol=TOL ) - u.val[:] = reshape(res0[0], ru) - v.val[:] = reshape(res1[0], rv) - w.val[:] = reshape(res2[0], rw) - - # Update velocities in boundary cells - adj_o_bnds((u,v,w), (dx,dy,dz), dt) - - # Update face velocities (also substract cell-centered pressure gradients - # and add staggered pressure gradients) - if d == C: - uf.val[:] = avg(X,u.val + dt / rho * ( p_tot_x )) \ - - dt / avg(X,rho) * (dif(X,p_tot) / avg(X,dx)) - vf.val[:] = avg(Y,v.val + dt / rho * ( p_tot_y )) \ - - dt / avg(Y,rho) * (dif(Y,p_tot) / avg(Y,dy)) - wf.val[:] = avg(Z,w.val + dt / rho * ( p_tot_z )) \ - - dt / avg(Z,rho) * (dif(Z,p_tot) / avg(Z,dz)) - - for j in (W,E): - uf.bnd[j].val[:] = u.bnd[j].val[:] - vf.bnd[j].val[:] = avg(Y, v.bnd[j].val[:]) - wf.bnd[j].val[:] = avg(Z, w.bnd[j].val[:]) - for j in (S,N): - uf.bnd[j].val[:] = avg(X, u.bnd[j].val[:]) - vf.bnd[j].val[:] = v.bnd[j].val[:] - wf.bnd[j].val[:] = avg(Z, w.bnd[j].val[:]) - for j in (B,T): - uf.bnd[j].val[:] = avg(X, u.bnd[j].val[:]) - vf.bnd[j].val[:] = avg(Y, v.bnd[j].val[:]) - wf.bnd[j].val[:] = w.bnd[j].val[:] - - else: - uf.val[:] = u.val[:] - vf.val[:] = v.val[:] - wf.val[:] = w.val[:] - for j in (W,E,S,N,B,T): - uf.bnd[j].val[:] = u.bnd[j].val[:] - vf.bnd[j].val[:] = v.bnd[j].val[:] - wf.bnd[j].val[:] = w.bnd[j].val[:] - - if obst.any() != 0: - uf.val[:] = obst_zero_val(X, uf.val, obst) - vf.val[:] = obst_zero_val(Y, vf.val, obst) - wf.val[:] = obst_zero_val(Z, wf.val, obst) - - return # end of function diff --git a/PYTHON/Discretization/cartesian_grid.py b/PYTHON/Discretization/cartesian_grid.py deleted file mode 100644 index 0ff85fd..0000000 --- a/PYTHON/Discretization/cartesian_grid.py +++ /dev/null @@ -1,35 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -#========================================================================== -def cartesian_grid(xn, yn, zn): -#-------------------------------------------------------------------------- -# Spawns a 3D Cartesian grid from three arrays with node coordinates. -#-------------------------------------------------------------------------- - - # Compute cell resolutions - nx = len(xn)-1 - ny = len(yn)-1 - nz = len(zn)-1 - - # Create matrices for cell dimensions ... - dx = empty((nx,ny,nz)) - dy = empty((nx,ny,nz)) - dz = empty((nx,ny,nz)) - - # ... and fill them up! - dx[:] = dif(xn).reshape(nx,1,1) - dy[:] = dif(yn).reshape(1,ny,1) - dz[:] = dif(zn).reshape(1,1,nz) - - # Compute resolutions for cell-centered and all collocated variables - rc = nx, ny, nz - ru = nx-1, ny, nz - rv = nx, ny-1, nz - rw = nx, ny, nz-1 - - return nx,ny,nz, dx,dy,dz, rc,ru,rv,rw # end of function diff --git a/PYTHON/Discretization/cfl_max.py b/PYTHON/Discretization/cfl_max.py deleted file mode 100644 index 63b07e4..0000000 --- a/PYTHON/Discretization/cfl_max.py +++ /dev/null @@ -1,28 +0,0 @@ -# ScriNS modules -from Constants.all import * -from Operators.all import * - -#========================================================================== -def cfl_max(uvw, dt, dxyz): -#-------------------------------------------------------------------------- - - # Unpack received tuples - u, v, w = uvw - dx, dy, dz = dxyz - - # Take velocity's position - d = u.pos - - # Mesh is cell-centered - if d == C: - cfl = dt * max( abs(u.val/dx).max(), \ - abs(v.val/dy).max(), \ - abs(w.val/dz).max() ) - - # Mesh is staggered - else: - cfl = dt * max( abs(u.val/avg(X,dx)).max(), \ - abs(v.val/avg(Y,dy)).max(), \ - abs(w.val/avg(Z,dz)).max() ) - - return cfl \ No newline at end of file diff --git a/PYTHON/Discretization/corr_uvw.py b/PYTHON/Discretization/corr_uvw.py deleted file mode 100644 index 1fed45e..0000000 --- a/PYTHON/Discretization/corr_uvw.py +++ /dev/null @@ -1,40 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -from Discretization.obst_zero_val import obst_zero_val - -#========================================================================== -def corr_uvw(uvw, p, rho, dt, dxyz, obst): -#-------------------------------------------------------------------------- - - # Unpack received tuples - dx, dy, dz = dxyz - - # Compute pressure correction gradients - p_x = dif(X, p.val) / avg(X, dx) - p_y = dif(Y, p.val) / avg(Y, dy) - p_z = dif(Z, p.val) / avg(Z, dz) - - # Set to zero in obst - if obst.any() != 0: - p_x = obst_zero_val(X, p_x, obst) - p_y = obst_zero_val(Y, p_y, obst) - p_z = obst_zero_val(Z, p_z, obst) - - # Pad with boundary values by expanding from interior - # (This is done only for collocated formulation) - if uvw[X].pos == C: - p_x = avg(X, cat(X, (p_x[:1,:,:], p_x, p_x[-1:,:,:]))) - p_y = avg(Y, cat(Y, (p_y[:,:1,:], p_y, p_y[:,-1:,:]))) - p_z = avg(Z, cat(Z, (p_z[:,:,:1], p_z, p_z[:,:,-1:]))) - - # Correct the velocities - uvw[X].val[:] = uvw[X].val[:] - dt / avg(uvw[X].pos, rho) * p_x - uvw[Y].val[:] = uvw[Y].val[:] - dt / avg(uvw[Y].pos, rho) * p_y - uvw[Z].val[:] = uvw[Z].val[:] - dt / avg(uvw[Z].pos, rho) * p_z - - return # end of function \ No newline at end of file diff --git a/PYTHON/Discretization/create_matrix.py b/PYTHON/Discretization/create_matrix.py deleted file mode 100644 index 494fe8b..0000000 --- a/PYTHON/Discretization/create_matrix.py +++ /dev/null @@ -1,149 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -from Discretization.obst_mod_matrix import obst_mod_matrix - -#========================================================================== -def create_matrix(phi, inn, mu, dxyz, obst, obc): -#-------------------------------------------------------------------------- -# pos - position of variable (C - central, -# X - staggered in x direction, -# Y - staggered in y direction, -# Z - staggered in z direction) -# inn - innertial term -# mu - viscous coefficient -# dx, dy, dz - cell size in x, y and z directions -# obc - obstacles's boundary condition, ('n' - Neumann, -# 'd' - Dirichlet) -#-------------------------------------------------------------------------- - - # Unpack tuples - dx, dy, dz = dxyz - - res = phi.val.shape - - #------------------------------- - # Create right hand side vector - #------------------------------- - b = zeros(res) - - #------------------------------------ - # Create default matrix coefficients - #------------------------------------ - coefficients = namedtuple('matrix_diagonal', 'W E S N B T P') - c = coefficients(zeros(res), zeros(res), zeros(res), \ - zeros(res), zeros(res), zeros(res), \ - zeros(res)) - - d = phi.pos - - # Handle central coefficient due to innertia - c.P[:] = avg(d, inn) * avg(d, dx*dy*dz) - - # Pre-compute geometrical quantities - sx = dy * dz - sy = dx * dz - sz = dx * dy - - if d != X: - c.W[:] = cat(X, ( \ - avg(d,mu[ :1,:,:]) * avg(d,sx[ :1,:,:]) / avg(d,(dx[ :1,:,:])/2.0), \ - avg(d,avg(X, mu)) * avg(d,avg(X, sx)) / avg(d,avg(X, dx)) ) ) - - c.E[:] = cat(X, ( \ - avg(d,avg(X, mu)) * avg(d,avg(X, sx)) / avg(d,avg(X, dx)), \ - avg(d,mu[-1:,:,:]) * avg(d,sx[-1:,:,:]) / avg(d,(dx[-1:,:,:])/2.0) ) ) - - if d != Y: - c.S[:] = cat(Y, ( \ - avg(d,mu[:, :1,:]) * avg(d,sy[:, :1,:]) / avg(d,(dy[:, :1,:])/2.0), \ - avg(d,avg(Y, mu)) * avg(d,avg(Y, sy)) / avg(d,avg(Y, dy)) ) ) - - c.N[:] = cat(Y, ( \ - avg(d,avg(Y, mu)) * avg(d,avg(Y, sy)) / avg(d,avg(Y, dy)), \ - avg(d,mu[:,-1:,:]) * avg(d,sy[:,-1:,:]) / avg(d,(dy[:,-1:,:])/2.0) ) ) - - if d != Z: - c.B[:] = cat(Z, ( \ - avg(d,mu[:,:, :1]) * avg(d,sz[:,:, :1]) / avg(d,(dz[:,:, :1])/2.0), \ - avg(d,avg(Z, mu)) * avg(d,avg(Z, sz)) / avg(d,avg(Z, dz)) ) ) - - c.T[:] = cat(Z, ( \ - avg(d,avg(Z, mu)) * avg(d,avg(Z, sz)) / avg(d,avg(Z, dz)), \ - avg(d,mu[:,:,-1:]) * avg(d,sz[:,:,-1:]) / avg(d,(dz[:,:,-1:])/2.0) ) ) - - #--------------------------------- - # Correct for staggered variables - #--------------------------------- - if d == X: - c.W[:] = mu[0:-1,:,:] * sx[0:-1,:,:] / dx[0:-1,:,:] - c.E[:] = mu[1:, :,:] * sx[1:, :,:] / dx[1:, :,:] - elif d == Y: - c.S[:] = mu[:,0:-1,:] * sy[:,0:-1,:] / dy[:,0:-1,:] - c.N[:] = mu[:,1:, :] * sy[:,1:, :] / dy[:,1:, :] - elif d == Z: - c.B[:] = mu[:,:,0:-1] * sz[:,:,0:-1] / dz[:,:,0:-1] - c.T[:] = mu[:,:,1: ] * sz[:,:,1: ] / dz[:,:,1: ] - - #----------------------------------------------------------------------- - # Zero them (correct them) for vanishing derivative boundary condition. - #----------------------------------------------------------------------- - - # The values defined here will be false (numerical value 0) - # wherever there is or Neumann boundary condition. - c.W[ :1, :, :] *= ( phi.bnd[W].typ[:] == DIRICHLET ) - c.E[-1:, :, :] *= ( phi.bnd[E].typ[:] == DIRICHLET ) - c.S[ :, :1, :] *= ( phi.bnd[S].typ[:] == DIRICHLET ) - c.N[ :,-1:, :] *= ( phi.bnd[N].typ[:] == DIRICHLET ) - c.B[ :, :, :1] *= ( phi.bnd[B].typ[:] == DIRICHLET ) - c.T[ :, :,-1:] *= ( phi.bnd[T].typ[:] == DIRICHLET ) - - #-------------------------------------------- - # Fill the source terms with boundary values - #-------------------------------------------- - b[ :1, :, :] += c.W[ :1, :, :] * phi.bnd[W].val[:1,:,:] - b[-1:, :, :] += c.E[-1:, :, :] * phi.bnd[E].val[:1,:,:] - b[ :, :1, :] += c.S[ :, :1, :] * phi.bnd[S].val[:,:1,:] - b[ :,-1:, :] += c.N[ :,-1:, :] * phi.bnd[N].val[:,:1,:] - b[ :, :, :1] += c.B[ :, :, :1] * phi.bnd[B].val[:,:,:1] - b[ :, :,-1:] += c.T[ :, :,-1:] * phi.bnd[T].val[:,:,:1] - - #--------------------------------------- - # Correct system matrices for obstacles - #--------------------------------------- - if obst.any() != 0: - c = obst_mod_matrix(phi, c, obst, obc) - - #----------------------------------------------- - # Add all neighbours to the central matrix, - # and zero the coefficients towards boundaries - #----------------------------------------------- - c.P[:] += c.W[:] + c.E[:] + c.S[:] + c.N[:] + c.B[:] + c.T[:] - - c.W[ :1, :, :] = 0.0 - c.E[-1:, :, :] = 0.0 - c.S[ :, :1, :] = 0.0 - c.N[ :,-1:, :] = 0.0 - c.B[ :, :, :1] = 0.0 - c.T[ :, :,-1:] = 0.0 - - #---------------------- - # Create sparse matrix - #---------------------- - nx, ny, nz = res - n = nx * ny * nz - - data = array([reshape( c.P, n), \ - reshape(-c.W, n), reshape(-c.E, n), \ - reshape(-c.S, n), reshape(-c.N, n), \ - reshape(-c.B, n), reshape(-c.T, n)]) - - diag = array([0, +ny*nz, -ny*nz, +nz, -nz, +1, -1]) - - A = spdiags(data, diag, n, n) - - return A, b # end of function diff --git a/PYTHON/Discretization/create_unknown.py b/PYTHON/Discretization/create_unknown.py deleted file mode 100644 index 473288b..0000000 --- a/PYTHON/Discretization/create_unknown.py +++ /dev/null @@ -1,69 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -#========================================================================== -def create_unknown(name, pos, res, def_bc): -#-------------------------------------------------------------------------- -# This function creates a new unkown; helping to shorten the main program. -#-------------------------------------------------------------------------- -# Input parameters are: -# -# name - string holding the name of the variable -# it should be used for post-processing -# pos - character specifying if the variable is cell centered (C), -# staggered in x direction (X) or in y direction (Y) -# res - vector specifying resolutions in x and y direction -# def_bc - integer specifying if the default boundary condition is of -# dirichlet, neumann or outlet type -#-------------------------------------------------------------------------- - - # Fetch resolutions - nx, ny, nz = res - - # Create boundary tuple - key = namedtuple('key', 'typ val') - bnd = (key(ndarray(shape=(1,ny,nz), dtype=int), zeros((1,ny,nz))), \ - key(ndarray(shape=(1,ny,nz), dtype=int), zeros((1,ny,nz))), \ - key(ndarray(shape=(nx,1,nz), dtype=int), zeros((nx,1,nz))), \ - key(ndarray(shape=(nx,1,nz), dtype=int), zeros((nx,1,nz))), \ - key(ndarray(shape=(nx,ny,1), dtype=int), zeros((nx,ny,1))), \ - key(ndarray(shape=(nx,ny,1), dtype=int), zeros((nx,ny,1)))) - - # Create the unknown tuple - unk = namedtuple('unk', 'name pos val old bnd') - phi = unk(name, pos, zeros(res), zeros(res), bnd) - - #------------------ - # Set the position - #------------------ - if pos != C and pos != X and pos != Y and pos != Z: - print('Variable must be defined at positions C, X, Y or Z') - - #--------------------------------------------------- - # Set default boundary conditions, types and values - #--------------------------------------------------- - if def_bc != DIRICHLET and def_bc != NEUMANN and def_bc != OUTLET: - print('Variable must be defined with boundary conditions ', \ - 'DIRICHLET, NEUMANN or OUTLET!') - - phi.bnd[W].typ[0,:,:] = def_bc - phi.bnd[E].typ[0,:,:] = def_bc - phi.bnd[S].typ[:,0,:] = def_bc - phi.bnd[N].typ[:,0,:] = def_bc - phi.bnd[B].typ[:,:,0] = def_bc - phi.bnd[T].typ[:,:,0] = def_bc - - phi.bnd[W].val[0,:,:] = 0 - phi.bnd[E].val[0,:,:] = 0 - phi.bnd[S].val[:,0,:] = 0 - phi.bnd[N].val[:,0,:] = 0 - phi.bnd[B].val[:,:,0] = 0 - phi.bnd[T].val[:,:,0] = 0 - - print("Created variable ", name) - - return phi # end of function diff --git a/PYTHON/Discretization/nodes.py b/PYTHON/Discretization/nodes.py deleted file mode 100644 index c2327de..0000000 --- a/PYTHON/Discretization/nodes.py +++ /dev/null @@ -1,90 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -#========================================================================== -def nodes(*args): -#-------------------------------------------------------------------------- -# Creates node coordinates in one dimension -# -# Input arguments: -# s - starting coordinate -# e - end coordinate -# n - number of cells (number of nodes is greater than one than this) -# del_s - (optional) starting cell size -# del_e - (optional) ending cell size -#-------------------------------------------------------------------------- - - #--------------------------------------------- - # Just a simple constant-spacing distribution - #--------------------------------------------- - if len((args)) == 3: - s = args[0] - e = args[1] - n = args[2] - return linspace(s, e, n+1) - - #------------------------------------------------------------------------ - # Grid distribution is determined from the following function: - # x = a + b y + c y^2 + d y^3 - # - # One should imagine this function as taking integer arguments. - # - # Boundary conditions: - # - # x(0) = s => a = s - # x(1) = s + del_s => a + b + c + d = s + del_s - # x(n-1) = e - del_e => a + b*(n-1) + c*(n-1)^2 + d*(n-1)^3 = e - del_e - # x(n) = e => a + b*n + c*n^2 + d*n^3 = e - # - # It follows that: - # - # |1 0 0 0 | |a| |s | - # |1 1 1 1 | |b| |s+del_s| - # |1 n-1 (n-1)^2 (n-1)^3| |c| |e-del_e| - # |1 n n^2 n^3 | |d| |e | - #------------------------------------------------------------------------ - elif len((args)) == 5: - s = args[0] - e = args[1] - n = args[2] - del_s = args[3] - del_e = args[4] - - # Form the system matrix - A = matrix( [ [1, 0, 0, 0 ], \ - [1, 1, 1, 1 ], \ - [1, n-1, pow(n-1,2), pow(n-1,3)], \ - [1, n, pow(n, 2), pow(n, 3)] ] ) - - # Form the right hand side - f = array( [ s , \ - s + del_s, \ - e - del_e, \ - e ] ) - - # Solve for coefficients - abcd = solve(A, f) - - # Pre-allocate the array for coordinates ... - x = zeros(n+1); - - # ... and fill it up. - for i in range(0, n+1): - x[i] = abcd[0] \ - + abcd[1] * i \ - + abcd[2] * i*i \ - + abcd[3] * i*i*i - - return x - - #-------------------------- - # Some error message might - # be printed if number of - # arguments is wrong - #-------------------------- - - return # end of function \ No newline at end of file diff --git a/PYTHON/Discretization/obst_mod_matrix.py b/PYTHON/Discretization/obst_mod_matrix.py deleted file mode 100644 index 0787750..0000000 --- a/PYTHON/Discretization/obst_mod_matrix.py +++ /dev/null @@ -1,176 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -#========================================================================== -def obst_mod_matrix(phi, c, obst, obc): -#-------------------------------------------------------------------------- -# Adjusts the system matrix for obstacles and cell centered varaibles -# (such as pressure) -# -# phi - variable -# c - coefficients in system matrix -# obst - obstacle array -# obc - obstacles's boundary condition, ('n' - Neumann, 'd' - Dirichlet) -#-------------------------------------------------------------------------- - - pos = phi.pos - - #-------------------------- - # - # For collocated variables - # - #-------------------------- - if pos == C: - - #------------------------------------ - # Neumann's boundary on the obstacle - #------------------------------------ - if obc == 'n': - - # Correct west and east - sol_x = dif(X, obst) # will be +1 east of obst, -1 west of obst - corr = 1 - (sol_x < 0) - c.W[1:,:,:] = c.W[1:,:,:] * corr - corr = 1 - (sol_x > 0) - c.E[:-1,:,:] = c.E[:-1,:,:] * corr - - # Correct south and north - sol_y = dif(Y, obst) # will be +1 north of obst, -1 south of obst - corr = 1 - (sol_y < 0) - c.S[:,1:,:] = c.S[:,1:,:] * corr - corr = 1 - (sol_y > 0) - c.N[:,:-1,:] = c.N[:,:-1,:] * corr - - # Correct bottom and top - sol_z = dif(Z, obst) # will be +1 north of obst, -1 south of obst - corr = 1 - (sol_z < 0) - c.B[:,:,1:] = c.B[:,:,1:] * corr - corr = 1 - (sol_z > 0) - c.T[:,:,:-1] = c.T[:,:,:-1] * corr - - #-------------------------------------- - # Dirichlet's boundary on the obstacle - #-------------------------------------- - elif obc == 'd': - - # Set central coefficient to 1 in obst, unchanged elsewhere - c.P[:] = c.P[:] * lnot(obst) + obst - - # Set neighbour coefficients to zero in obst - c.W[:] = c.W[:] * lnot(obst) - c.E[:] = c.E[:] * lnot(obst) - c.S[:] = c.S[:] * lnot(obst) - c.N[:] = c.N[:] * lnot(obst) - c.B[:] = c.B[:] * lnot(obst) - c.T[:] = c.T[:] * lnot(obst) - - # Increase coefficients close to obst (makes sense for momentum) - sol_x = dif(X, obst) # will be +1 east of obst, -1 west of obst - corr = 1 + (sol_x > 0) - c.E[:-1,:,:] = c.E[:-1,:,:] * corr - corr = 1 + (sol_x < 0) - c.W[1:,:,:] = c.W[1:,:,:] * corr - - sol_y = dif(Y, obst) # will be +1 north of obst, -1 south of obst - corr = 1 + (sol_y > 0) - c.N[:,:-1,:] = c.N[:,:-1,:] * corr - corr = 1 + (sol_y < 0) - c.S[:,1:,:] = c.S[:,1:,:] * corr - - sol_z = dif(Z, obst) # will be +1 top of obst, -1 bottom of obst - corr = 1 + (sol_z > 0) - c.T[:,:,:-1] = c.T[:,:,:-1] * corr - corr = 1 + (sol_z < 0) - c.B[:,:,1:] = c.B[:,:,1:] * corr - - #------------------------- - # - # For staggered variables - # - #------------------------- - elif pos == X: - - # Set central coefficient to 1 in obst, unchanged elsewhere - obst_x = mx(obst[:-1,:,:], obst[1:,:,:]) - c.P[:] = c.P[:] * lnot(obst_x) + obst_x - - # Set neighbour coefficients to zero in obst - c.W[:] = c.W[:] * lnot(obst_x) - c.E[:] = c.E[:] * lnot(obst_x) - c.S[:] = c.S[:] * lnot(obst_x) - c.N[:] = c.N[:] * lnot(obst_x) - c.B[:] = c.B[:] * lnot(obst_x) - c.T[:] = c.T[:] * lnot(obst_x) - - # Increase coefficients close to obst (makes sense for momentum) - sol_y = dif(Y, obst_x) # will be +1 north of obst, -1 south of obst - corr = 1 + (sol_y > 0) - c.N[:,:-1,:] = c.N[:,:-1,:] * corr - corr = 1 + (sol_y < 0) - c.S[:,1:,:] = c.S[:,1:,:] * corr - - sol_z = dif(Z, obst_x) # will be +1 top of obst, -1 bottom of obst - corr = 1 + (sol_z > 0) - c.T[:,:,:-1] = c.T[:,:,:-1] * corr - corr = 1 + (sol_z < 0) - c.B[:,:,1:] = c.B[:,:,1:] * corr - - elif pos == Y: - - # Set central coefficient to 1 in obst, unchanged elsewhere - obst_y = mx(obst[:,:-1,:], obst[:,1:,:]) - c.P[:] = c.P[:] * lnot(obst_y) + obst_y - - # Set neighbour coefficients to zero in obst - c.W[:] = c.W[:] * lnot(obst_y) - c.E[:] = c.E[:] * lnot(obst_y) - c.S[:] = c.S[:] * lnot(obst_y) - c.N[:] = c.N[:] * lnot(obst_y) - c.B[:] = c.B[:] * lnot(obst_y) - c.T[:] = c.T[:] * lnot(obst_y) - - # Increase coefficients close to obst (makes sense for momentum) - sol_x = dif(X, obst_y) # will be +1 north of obst, -1 south of obst - corr = 1 + (sol_x > 0) - c.E[:-1,:,:] = c.E[:-1,:,:] * corr - corr = 1 + (sol_x < 0) - c.W[1:,:,:] = c.W[1:,:,:] * corr - - sol_z = dif(Z, obst_y) # will be +1 north of obst, -1 south of obst - corr = 1 + (sol_z > 0) - c.T[:,:,:-1] = c.T[:,:,:-1] * corr - corr = 1 + (sol_z < 0) - c.B[:,:,1:] = c.B[:,:,1:] * corr - - elif pos == Z: - - # Set central coefficient to 1 in obst, unchanged elsewhere - obst_z = mx(obst[:,:,:-1], obst[:,:,1:]) - c.P[:] = c.P[:] * lnot(obst_z) + obst_z - - # Set neighbour coefficients to zero in obst - c.W[:] = c.W[:] * lnot(obst_z) - c.E[:] = c.E[:] * lnot(obst_z) - c.S[:] = c.S[:] * lnot(obst_z) - c.N[:] = c.N[:] * lnot(obst_z) - c.B[:] = c.B[:] * lnot(obst_z) - c.T[:] = c.T[:] * lnot(obst_z) - - # Increase coefficients close to obst (makes sense for momentum) - sol_x = dif(X, obst_z) # will be +1 north of obst, -1 south of obst - corr = 1 + (sol_x > 0) - c.E[:-1,:,:] = c.E[:-1,:,:] * corr - corr = 1 + (sol_x < 0) - c.W[1:,:,:] = c.W[1:,:,:] * corr - - sol_y = dif(Y, obst_z) # will be +1 north of obst, -1 south of obst - corr = 1 + (sol_y > 0) - c.N[:,:-1,:] = c.N[:,:-1,:] * corr - corr = 1 + (sol_y < 0) - c.S[:,1:,:] = c.S[:,1:,:] * corr - - return c # end of function \ No newline at end of file diff --git a/PYTHON/Discretization/obst_zero_val.py b/PYTHON/Discretization/obst_zero_val.py deleted file mode 100644 index 166f2e0..0000000 --- a/PYTHON/Discretization/obst_zero_val.py +++ /dev/null @@ -1,33 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -#========================================================================== -def obst_zero_val(d, val, obst): -#-------------------------------------------------------------------------- -# Set value to zero inside obstacle. -# -# d - position of the variable, C, X, Y or Z -# val - value to be zeroed in obstacle -# obst - matrix holding positions of obstacle -#-------------------------------------------------------------------------- - - if d == C: - val = val * lnot(obst) - - elif d==X: - obst_x = mx(obst[:-1,:,:], obst[1:,:,:]) - val = val * lnot(obst_x) - - elif d==Y: - obst_y = mx(obst[:,:-1,:], obst[:,1:,:]) - val = val * lnot(obst_y) - - elif d==Z: - obst_z = mx(obst[:,:,:-1], obst[:,:,1:]) - val = val * lnot(obst_z) - - return val # end of function \ No newline at end of file diff --git a/PYTHON/Discretization/vol_balance.py b/PYTHON/Discretization/vol_balance.py deleted file mode 100644 index ce5a191..0000000 --- a/PYTHON/Discretization/vol_balance.py +++ /dev/null @@ -1,34 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -from Discretization.obst_zero_val import obst_zero_val - -#========================================================================== -def vol_balance(uvwf, dxyz, obst): -#-------------------------------------------------------------------------- -# Computes the volume balance, which is essentially a right hand side in -# the Poisson's equation for pressure. -# -# Note that "obst" is an optional parameter. If it is not sent, the source -# won't be zeroed inside the obstacle. That is important for calculation -# of pressure, see function "calc_p". -#-------------------------------------------------------------------------- - - # Unpack tuples - dx, dy, dz = dxyz - uf, vf, wf = uvwf - - # Compute it throughout the domain - src = - dif(X, cat(X, (uf.bnd[W].val, uf.val, uf.bnd[E].val)))*dy*dz \ - - dif(Y, cat(Y, (vf.bnd[S].val, vf.val, vf.bnd[N].val)))*dx*dz \ - - dif(Z, cat(Z, (wf.bnd[B].val, wf.val, wf.bnd[T].val)))*dx*dy - - # Zero it inside obstacles, if obstacle is sent as parameter - if obst.any() != 0: - src = obst_zero_val(C, src, obst) - - return src # end of function \ No newline at end of file diff --git a/PYTHON/Display/all.py b/PYTHON/Display/all.py deleted file mode 100644 index 044ed67..0000000 --- a/PYTHON/Display/all.py +++ /dev/null @@ -1,5 +0,0 @@ -# Printing functions -from Display.plot_isolines import plot_isolines -from Display.print_array import print_array -from Display.print_matrix import print_matrix -from Display.print_time_step import print_time_step \ No newline at end of file diff --git a/PYTHON/Display/plot_isolines.py b/PYTHON/Display/plot_isolines.py deleted file mode 100644 index 6d0ea66..0000000 --- a/PYTHON/Display/plot_isolines.py +++ /dev/null @@ -1,56 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -#-------------------------------------------------------------------------- -def plot_isolines(phi, uvw, xyzn, d): -#-------------------------------------------------------------------------- - - # Unpack tuples - u, v, w = uvw - xn, yn, zn = xyzn - - # Cell coordinates - xc = avg(xn) - yc = avg(yn) - zc = avg(zn) - - # Collocated velocity components - if u.pos == C: - uc = u.val - vc = v.val - wc = w.val - else: - uc = avg(X,cat(X,(u.bnd[W].val[:1,:,:], u.val, u.bnd[E].val[:1,:,:]))) - vc = avg(Y,cat(Y,(v.bnd[S].val[:,:1,:], v.val, v.bnd[N].val[:,:1,:]))) - wc = avg(Z,cat(Z,(w.bnd[B].val[:,:,:1], w.val, w.bnd[T].val[:,:,:1]))) - - # Pick coordinates for plotting (xp, yp) and values for plotting - if d == Y: - jp = floor(yc.size/2) - xp, yp = meshgrid(xc, zc) - zp = transpose(phi[:,jp,:], (1,0)) - up = transpose(uc [:,jp,:], (1,0)) - vp = transpose(wc [:,jp,:], (1,0)) - if d == Z: - kp = floor(zc.size/2) - xp, yp = meshgrid(xc, yc) - zp = transpose(phi[:,:,kp], (1,0)) - up = transpose(uc [:,:,kp], (1,0)) - vp = transpose(vc [:,:,kp], (1,0)) - - # Set levels and normalize the colors - levels = linspace( zp.min(), zp.max(), 11) - norm = cm.colors.Normalize( vmax=zp.max(), vmin=zp.min() ) - - plt.figure() - plt.gca(aspect='equal') - plt.contour(xp,yp,zp, levels, cmap=plt.cm.rainbow, norm=norm) - plt.quiver(xp,yp,up,vp) - plt.axis( [min(xn), max(xn), min(yn), max(yn)] ) - plt.show() - - return # end of function \ No newline at end of file diff --git a/PYTHON/Display/print_array.py b/PYTHON/Display/print_array.py deleted file mode 100644 index 29c5e98..0000000 --- a/PYTHON/Display/print_array.py +++ /dev/null @@ -1,17 +0,0 @@ -#========================================================================== -def print_array(*args): -#-------------------------------------------------------------------------- - - if len((args)) == 1: - a = args[0] - format = "%7.2f" - else: - a = args[0] - format = args[1] - - print('Array ['+('%d' %a.shape[0])+']') - rows = a.shape[0] - for i in range(0,rows): - print(format %a[i]) - - return # end of function \ No newline at end of file diff --git a/PYTHON/Display/print_matrix.py b/PYTHON/Display/print_matrix.py deleted file mode 100644 index 21803a5..0000000 --- a/PYTHON/Display/print_matrix.py +++ /dev/null @@ -1,22 +0,0 @@ -#========================================================================== -def print_matrix(*args): -#-------------------------------------------------------------------------- - - if len((args)) == 1: - a = args[0] - format = "%7.2f" - else: - a = args[0] - format = args[1] - - print('Matrix['+('%d' %a.shape[0])+']['+('%d' %a.shape[1])+']') - rows = a.shape[0] - cols = a.shape[1] - - for i in range(0,rows): - for j in range(0,cols): - print((format %a[i,j]), end='') - print('') - print('') - - return # end of function \ No newline at end of file diff --git a/PYTHON/Display/print_time_step.py b/PYTHON/Display/print_time_step.py deleted file mode 100644 index 6d70537..0000000 --- a/PYTHON/Display/print_time_step.py +++ /dev/null @@ -1,11 +0,0 @@ -#========================================================================== -def print_time_step(ts): -#-------------------------------------------------------------------------- - - print('+======================+') - print('| |') - print('| Time step = ' +'%6d' %ts + ' |') - print('| |') - print('+======================+') - - return # end of function \ No newline at end of file diff --git a/PYTHON/Operators/all.py b/PYTHON/Operators/all.py deleted file mode 100644 index e2aea6f..0000000 --- a/PYTHON/Operators/all.py +++ /dev/null @@ -1,5 +0,0 @@ -# Operators -from Operators.avg import avg -from Operators.cat import cat -from Operators.dif import dif -from Operators.par import par diff --git a/PYTHON/Operators/avg.py b/PYTHON/Operators/avg.py deleted file mode 100644 index c363ed2..0000000 --- a/PYTHON/Operators/avg.py +++ /dev/null @@ -1,31 +0,0 @@ -# ScriNS modules -from Constants.all import * - -#========================================================================== -def avg(*args): -#-------------------------------------------------------------------------- - - # Only one argument is sent - perform - # averaging of one-dimensional array - if len((args)) == 1: - a = args[0] - return (a[1:] + a[:-1]) * 0.5 - - # Two arguments are sent - perform averaging of a - # three-dimensional array, with a given direction - elif len((args)) == 2: - d = args[0] # direction - a = args[1] # array - - if d == X: - return (a[1:,:, : ] + a[:-1,:, : ]) * 0.5 - elif d == Y: - return (a[:, 1:,: ] + a[:, :-1,: ]) * 0.5 - elif d == Z: - return (a[:, :, 1:] + a[:, :, :-1]) * 0.5 - - # Some error message might - # be printed if number of - # arguments is wrong - - return a # end of function \ No newline at end of file diff --git a/PYTHON/Operators/cat.py b/PYTHON/Operators/cat.py deleted file mode 100644 index 964b5ad..0000000 --- a/PYTHON/Operators/cat.py +++ /dev/null @@ -1,13 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * - -#========================================================================== -def cat(d, tup): -#-------------------------------------------------------------------------- -# An interface to the standard NumPy's function concatenate -#-------------------------------------------------------------------------- - - return concatenate(tup, d) # end of function \ No newline at end of file diff --git a/PYTHON/Operators/dif.py b/PYTHON/Operators/dif.py deleted file mode 100644 index 4a7f6e3..0000000 --- a/PYTHON/Operators/dif.py +++ /dev/null @@ -1,31 +0,0 @@ -# ScriNS modules -from Constants.all import * - -#========================================================================== -def dif(*args): -#-------------------------------------------------------------------------- - - # Only one argument is sent - perform - # averaging of one-dimensional array - if len((args)) == 1: - a = args[0] - return (a[1:] - a[:-1]) - - # Two arguments are sent - perform averaging of a - # three-dimensional array, with a given direction - elif len((args)) == 2: - d = args[0] # direction - a = args[1] # array - - if d == X: - return (a[1:,:,:] - a[:-1,:,:]) - elif d == Y: - return (a[:,1:,:] - a[:,:-1,:]) - elif d == Z: - return (a[:,:,1:] - a[:,:,:-1]) - - # Some error message might - # be printed if number of - # arguments is wrong - - return # end of function \ No newline at end of file diff --git a/PYTHON/Operators/par.py b/PYTHON/Operators/par.py deleted file mode 100644 index 8bc156c..0000000 --- a/PYTHON/Operators/par.py +++ /dev/null @@ -1,41 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Display.all import * - -from Operators.all import avg - -#========================================================================== -def par(mean_val, x_nodes): -#-------------------------------------------------------------------------- -# A function to generate a parabolic profile over a set of cell centers, -# useful for specifying parabolic inlet velocity profiles. It expects -# nodal coordinates as input, but sends values at cell centers back. -# -# Input coordinates: |-----|-----|-----|-----|-----|-----|-----| -# Output values: o-----o-----o-----o-----o-----o-----o -# -# Input parameters -# -# mean_val - mean value the parabola will have -# x_nodes - nodal coordinatels -#-------------------------------------------------------------------------- - - # It is known that maximum of a parabola is 3/2 of its mean value - max_val = mean_val * 3/2 - - # Normalized x coordinates (from -1 to +1) - xn = copy(x_nodes) - - xn -= xn.min() - xn /= (xn.max()-xn.min()) - xn *= 2 - xn -= 1 - - xc = avg(xn) - - yc = (1.0-xc*xc) * max_val - - return yc # end of function \ No newline at end of file diff --git a/PYTHON/PhysicalModels/all.py b/PYTHON/PhysicalModels/all.py deleted file mode 100644 index 7ec691a..0000000 --- a/PYTHON/PhysicalModels/all.py +++ /dev/null @@ -1,3 +0,0 @@ -# Operators -from PhysicalModels.properties_for_air import properties_for_air -from PhysicalModels.properties_for_water import properties_for_water \ No newline at end of file diff --git a/PYTHON/PhysicalModels/properties_for_air.py b/PYTHON/PhysicalModels/properties_for_air.py deleted file mode 100644 index 493b685..0000000 --- a/PYTHON/PhysicalModels/properties_for_air.py +++ /dev/null @@ -1,23 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -#========================================================================== -def properties_for_air(rc): -#-------------------------------------------------------------------------- -# Returns physical properties of air for given resolution 'rc' -# -# For 60 deg from: -# http://www.engineeringtoolbox.com/air-properties-d_156.html -#-------------------------------------------------------------------------- - - # Create and fill matrice for all properties - rho = ones(rc) * 1.067 # density [kg/m^3] - mu = ones(rc) * 20.17E-06 # viscosity [Pa s] - cp = ones(rc) * 1009 # thermal capacity [J/kg/K] - kappa = ones(rc) * 0.0285 # thermal conductivity [W/m/K] - - return rho, mu, cp, kappa # end of function \ No newline at end of file diff --git a/PYTHON/PhysicalModels/properties_for_water.py b/PYTHON/PhysicalModels/properties_for_water.py deleted file mode 100644 index f8e1225..0000000 --- a/PYTHON/PhysicalModels/properties_for_water.py +++ /dev/null @@ -1,23 +0,0 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * - -#========================================================================== -def properties_for_water(rc): -#-------------------------------------------------------------------------- -# Returns physical properties for water for given resolution 'rc' -# -# For 60 deg from: -# http://www.engineeringtoolbox.com/water-properties-d_1508.html -#-------------------------------------------------------------------------- - - # Create and fill matrices for all properties - rho = ones(rc) * 983.0 # density [kg/m^3] - mu = ones(rc) * 0.466E-3 # viscosity [Pa s] - cp = ones(rc) * 4185 # thermal capacity [J/kg/K] - kappa = ones(rc) * 0.654 # thermal conductivity [W/m/K] - - return rho, mu, cp, kappa # end of function \ No newline at end of file diff --git a/PYTHON/scrins/.DS_Store b/PYTHON/scrins/.DS_Store new file mode 100644 index 0000000..164d549 Binary files /dev/null and b/PYTHON/scrins/.DS_Store differ diff --git a/PYTHON/scrins/__init__.py b/PYTHON/scrins/__init__.py new file mode 100755 index 0000000..e69de29 diff --git a/PYTHON/scrins/constants/__init__.py b/PYTHON/scrins/constants/__init__.py new file mode 100755 index 0000000..974e587 --- /dev/null +++ b/PYTHON/scrins/constants/__init__.py @@ -0,0 +1,2 @@ +_all_ = ["boundary_conditions", "compass", "coordinates", + "gravitational constant", "solver", "tiny_and_huge"] \ No newline at end of file diff --git a/PYTHON/scrins/constants/boundary_conditions.py b/PYTHON/scrins/constants/boundary_conditions.py new file mode 100755 index 0000000..379041a --- /dev/null +++ b/PYTHON/scrins/constants/boundary_conditions.py @@ -0,0 +1,6 @@ +""" +Boundary conditions. +""" +DIRICHLET = 10 +NEUMANN = 11 +OUTLET = 12 diff --git a/PYTHON/Constants/compass.py b/PYTHON/scrins/constants/compass.py old mode 100644 new mode 100755 similarity index 52% rename from PYTHON/Constants/compass.py rename to PYTHON/scrins/constants/compass.py index fa3d0ec..b72525d --- a/PYTHON/Constants/compass.py +++ b/PYTHON/scrins/constants/compass.py @@ -1,8 +1,10 @@ -# Compass notation -W = 0 -E = 1 -S = 2 -N = 3 -B = 4 -T = 5 -C = 6 \ No newline at end of file +""" +Compass notation. +""" +W = 0 +E = 1 +S = 2 +N = 3 +B = 4 +T = 5 +C = 6 diff --git a/PYTHON/scrins/constants/coordinates.py b/PYTHON/scrins/constants/coordinates.py new file mode 100755 index 0000000..7842be1 --- /dev/null +++ b/PYTHON/scrins/constants/coordinates.py @@ -0,0 +1,6 @@ +""" +Coordinate directions. +""" +X = 0 +Y = 1 +Z = 2 diff --git a/PYTHON/scrins/constants/gravitational_constant.py b/PYTHON/scrins/constants/gravitational_constant.py new file mode 100755 index 0000000..7d4c5b6 --- /dev/null +++ b/PYTHON/scrins/constants/gravitational_constant.py @@ -0,0 +1,4 @@ +""" +Gravitational constant. +""" +G = 9.81 diff --git a/PYTHON/scrins/constants/solver.py b/PYTHON/scrins/constants/solver.py new file mode 100755 index 0000000..ebf2bae --- /dev/null +++ b/PYTHON/scrins/constants/solver.py @@ -0,0 +1,4 @@ +""" +Solver tolerance. +""" +TOL = 1.0e-8 diff --git a/PYTHON/scrins/constants/tiny_and_huge.py b/PYTHON/scrins/constants/tiny_and_huge.py new file mode 100755 index 0000000..c7152a6 --- /dev/null +++ b/PYTHON/scrins/constants/tiny_and_huge.py @@ -0,0 +1,5 @@ +""" +Tiny and huge. +""" +TINY = 1.0e-12 +HUGE = 1.0e+12 diff --git a/PYTHON/scrins/discretization/.DS_Store b/PYTHON/scrins/discretization/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/PYTHON/scrins/discretization/.DS_Store differ diff --git a/PYTHON/scrins/discretization/__init__.py b/PYTHON/scrins/discretization/__init__.py new file mode 100755 index 0000000..a367012 --- /dev/null +++ b/PYTHON/scrins/discretization/__init__.py @@ -0,0 +1,6 @@ +_all_ = ["adj_n_bnds", "adj_o_bnds_new", "adj_o_bnds", + "adj_o_bnds_old", "advection", "calc_p", + "calc_t", "calc_uvw", "cartesian_grid", + "cfl_max", "corr_uvw", "create_matirx", + "create_unknown", "nodes", "obst_mod_matrix", + "obst_zero_val", "vol_balance"] \ No newline at end of file diff --git a/PYTHON/scrins/discretization/adj_n_bnds.py b/PYTHON/scrins/discretization/adj_n_bnds.py new file mode 100755 index 0000000..491b1c5 --- /dev/null +++ b/PYTHON/scrins/discretization/adj_n_bnds.py @@ -0,0 +1,41 @@ +""" +Adjust Neumann boundary conditions. +""" + +from scipy import logical_not as lnot +from scrins.constants.boundary_conditions import NEUMANN +from scrins.constants.compass import W, E, S, N, B, T + + +def adj_n_bnds(phi): + """ + Copies last domain cell values to Neumann boundary condition values. + :param phi: pressure TODO: why here phi and not p? + :return: None + """ + # These arrays will hold values true (0) in cells with boundary ... + # ... condition of Neumann type, and false (0) otherwise + + if_w_n = phi.bnd[W].typ[0, :, :] == NEUMANN # 1 if west is Neumann + if_e_n = phi.bnd[E].typ[0, :, :] == NEUMANN # 1 if east is Neumann + if_s_n = phi.bnd[S].typ[:, 0, :] == NEUMANN # 1 if south is Neumann + if_n_n = phi.bnd[N].typ[:, 0, :] == NEUMANN # 1 if north is Neumann + if_b_n = phi.bnd[B].typ[:, :, 0] == NEUMANN # 1 if bottom is Neumann + if_t_n = phi.bnd[T].typ[:, :, 0] == NEUMANN # 1 if top is Neumann + + # In what follows, a linear combination of true (0] and false (0) + # will copy the values of variable phi to the boundaries. + phi.bnd[W].val[0, :, :] = (phi.bnd[W].val[0, :, :] * lnot(if_w_n) + + phi.val[0, :, :] * if_w_n) + phi.bnd[E].val[0, :, :] = (phi.bnd[E].val[0, :, :] * lnot(if_e_n) + + phi.val[-1, :, :] * if_e_n) + + phi.bnd[S].val[:, 0, :] = (phi.bnd[S].val[:, 0, :] * lnot(if_s_n) + + phi.val[:, 0, :] * if_s_n) + phi.bnd[N].val[:, 0, :] = (phi.bnd[N].val[:, 0, :] * lnot(if_n_n) + + phi.val[:, -1, :] * if_n_n) + + phi.bnd[B].val[:, :, 0] = (phi.bnd[B].val[:, :, 0] * lnot(if_b_n) + + phi.val[:, :, 0] * if_b_n) + phi.bnd[T].val[:, :, 0] = (phi.bnd[T].val[:, :, 0] * lnot(if_t_n) + + phi.val[:, :, -1] * if_t_n) diff --git a/PYTHON/scrins/discretization/adj_o_bnds.py b/PYTHON/scrins/discretization/adj_o_bnds.py new file mode 100755 index 0000000..60e5250 --- /dev/null +++ b/PYTHON/scrins/discretization/adj_o_bnds.py @@ -0,0 +1,312 @@ +""" + +Update velocities in boundary cells +""" + +from scipy import logical_not as lnot +from scrins.constants.boundary_conditions import DIRICHLET, OUTLET +from scrins.constants.compass import W, E, S, N, B, T +from scrins.constants.tiny_and_huge import TINY +from scrins.operators.avg import avg + + +def adj_o_bnds(uvw, dxyz, dt): + """ + Update velocities in boundary cells + :param uvw: velocities u, v, w + :param dxyz: deltas of x, y, z coordinates + :param dt: time step + :return: + """ + + # pylint:disable=invalid-name,too-many-locals,too-many-statements + + # Unpack tuples + u, v, w = uvw + dx, dy, dz = dxyz + + # Local variables used in this function + area_in = 0.0 # area of the inlet + area_out = 0.0 # area of the outlet + vol_in = 0.0 # inlet volume flux; positive for inflow + vol_out_1 = 0.0 # outlet volume flux; positive for outflow + vol_out_2 = 0.0 # outlet volume flux; positive for outflow + + verbatim = False + + sx = dy * dz + sy = dx * dz + sz = dx * dy + + sx = sx[:1, :, :] + sy = sy[:, :1, :] + sz = sz[:, :, :1] + + # ----------------------------------------------------------------- + # Compute the volume flowing in (v_in), volume flowing out (v_out) + # as well as inlet and outlet areas (a_in, a_out) + # ----------------------------------------------------------------- + + # Inlets: these arrays will hold values true (1) in cells + # with inlet boundary conditions, and false (0) otherwise + if_w_in = (u.bnd[W].typ[:1, :, :] == DIRICHLET) & ( + u.bnd[W].val[:1, :, :] > +TINY) + if_e_in = (u.bnd[E].typ[:1, :, :] == DIRICHLET) & ( + u.bnd[E].val[:1, :, :] < -TINY) + if_s_in = (v.bnd[S].typ[:, :1, :] == DIRICHLET) & ( + v.bnd[S].val[:, :1, :] > +TINY) + if_n_in = (v.bnd[N].typ[:, :1, :] == DIRICHLET) & ( + v.bnd[N].val[:, :1, :] < -TINY) + if_b_in = (w.bnd[B].typ[:, :, :1] == DIRICHLET) & ( + w.bnd[B].val[:, :, :1] > +TINY) + if_t_in = (w.bnd[T].typ[:, :, :1] == DIRICHLET) & ( + w.bnd[T].val[:, :, :1] < -TINY) + + # Using the arrays defined above, compute inlet surface area + area_in += (if_w_in * sx).sum() + area_in += (if_e_in * sx).sum() + area_in += (if_s_in * sy).sum() + area_in += (if_n_in * sy).sum() + area_in += (if_b_in * sz).sum() + area_in += (if_t_in * sz).sum() + + # If there is no inlet, nothing to do here any longer + if area_in < TINY: + return u, v, w # one end of function + + # Using the arrays defined above, compute inlet volume flux + vol_in += (if_w_in * u.bnd[W].val[:1, :, :] * sx).sum() + vol_in -= (if_e_in * u.bnd[E].val[:1, :, :] * sx).sum() + vol_in += (if_s_in * v.bnd[S].val[:, :1, :] * sy).sum() + vol_in -= (if_n_in * v.bnd[N].val[:, :1, :] * sy).sum() + vol_in += (if_b_in * w.bnd[B].val[:, :, :1] * sz).sum() + vol_in -= (if_t_in * w.bnd[T].val[:, :, :1] * sz).sum() + + # Outlets: these arrays will hold values true (1) in cells ... + # with outlet boundary conditions, and false (0) otherwise + if_w_out_u = (u.bnd[W].typ[:1, :, :] == OUTLET) + if_w_out_v = avg(v.pos, if_w_out_u * 1) > 0.5 + if_w_out_w = avg(w.pos, if_w_out_u * 1) > 0.5 + + if_e_out_u = (u.bnd[E].typ[:1, :, :] == OUTLET) + if_e_out_v = avg(v.pos, if_e_out_u * 1) > 0.5 + if_e_out_w = avg(w.pos, if_e_out_u * 1) > 0.5 + + if_s_out_v = (v.bnd[S].typ[:, :1, :] == OUTLET) + if_s_out_u = avg(u.pos, if_s_out_v * 1) > 0.5 + if_s_out_w = avg(w.pos, if_s_out_v * 1) > 0.5 + + if_n_out_v = (v.bnd[N].typ[:, :1, :] == OUTLET) + if_n_out_u = avg(u.pos, if_n_out_v * 1) > 0.5 + if_n_out_w = avg(w.pos, if_n_out_v * 1) > 0.5 + + if_b_out_w = (w.bnd[B].typ[:, :, :1] == OUTLET) + if_b_out_u = avg(u.pos, if_b_out_w * 1) > 0.5 + if_b_out_v = avg(v.pos, if_b_out_w * 1) > 0.5 + + if_t_out_w = (w.bnd[T].typ[:, :, :1] == OUTLET) + if_t_out_u = avg(u.pos, if_t_out_w * 1) > 0.5 + if_t_out_v = avg(v.pos, if_t_out_w * 1) > 0.5 + + # Using the arrays defined above, compute outlet surface area + area_out += (if_w_out_u * sx).sum() + area_out += (if_e_out_u * sx).sum() + area_out += (if_s_out_v * sy).sum() + area_out += (if_n_out_v * sy).sum() + area_out += (if_b_out_w * sz).sum() + area_out += (if_t_out_w * sz).sum() + + # Using the arrays defined above, compute outlet volume flux + vol_out_1 -= (if_w_out_u * u.bnd[W].val[:1, :, :] * sx).sum() + vol_out_1 += (if_e_out_u * u.bnd[E].val[:1, :, :] * sx).sum() + vol_out_1 -= (if_s_out_v * v.bnd[S].val[:, :1, :] * sy).sum() + vol_out_1 += (if_n_out_v * v.bnd[N].val[:, :1, :] * sy).sum() + vol_out_1 -= (if_b_out_w * w.bnd[B].val[:, :, :1] * sz).sum() + vol_out_1 += (if_t_out_w * w.bnd[T].val[:, :, :1] * sz).sum() + + # -------------------------------- + # Check and calculate corrections + # -------------------------------- + + if area_in == 0: + ub_in = 0 + else: + ub_in = vol_in / area_in + + if area_out == 0: + ub_out = 0 + else: + ub_out = vol_out_1 / area_out + + # --------------------------------------------- + # If nothing comes out, make a bulk correction + # --------------------------------------------- + if ub_out < TINY: + u_bulk_corr = ub_in * area_in / area_out + + u.bnd[W].val[:1, :, :] = (u.bnd[W].val[:1, :, :] * lnot(if_w_out_u) + - u_bulk_corr * if_w_out_u) + u.bnd[E].val[:1, :, :] = (u.bnd[E].val[:1, :, :] * lnot(if_e_out_u) + + u_bulk_corr * if_e_out_u) + v.bnd[S].val[:, :1, :] = (v.bnd[S].val[:, :1, :] * lnot(if_s_out_v) + - u_bulk_corr * if_s_out_v) + v.bnd[N].val[:, :1, :] = (v.bnd[N].val[:, :1, :] * lnot(if_n_out_v) + + u_bulk_corr * if_n_out_v) + w.bnd[B].val[:, :, :1] = (w.bnd[B].val[:, :, :1] * lnot(if_b_out_w) + - u_bulk_corr * if_b_out_w) + w.bnd[T].val[:, :, :1] = (w.bnd[T].val[:, :, :1] * lnot(if_t_out_w) + + u_bulk_corr * if_t_out_w) + + # ------------------------------------------------------------- + # Correction outflow by applying convective boundary condition + # ------------------------------------------------------------- + else: + du_dx_w = (u.val[:1, :, :] - u.bnd[W].val[:1, :, :]) / dx[:1, :, :] + dv_dx_w = ((v.val[:1, :, :] - v.bnd[W].val[:1, :, :]) / + avg(v.pos, dx[:1, :, :])) + dw_dx_w = ((w.val[:1, :, :] - w.bnd[W].val[:1, :, :]) / + avg(w.pos, dx[:1, :, :])) + + du_dx_e = (u.val[-1:, :, :] - u.bnd[E].val[:1, :, :]) / dx[-1:, :, :] + dv_dx_e = ((v.val[-1:, :, :] - v.bnd[E].val[:1, :, :]) / + avg(v.pos, dx[-1:, :, :])) + dw_dx_e = ((w.val[-1:, :, :] - w.bnd[E].val[:1, :, :]) / + avg(w.pos, dx[-1:, :, :])) + + du_dy_s = ((u.val[:, :1, :] - u.bnd[S].val[:, :1, :]) / + avg(u.pos, dy[:, :1, :])) + dv_dy_s = (v.val[:, :1, :] - v.bnd[S].val[:, :1, :]) / dy[:, :1, :] + dw_dy_s = ((w.val[:, :1, :] - w.bnd[S].val[:, :1, :]) / + avg(w.pos, dy[:, :1, :])) + + du_dy_n = ((u.val[:, -1:, :] - u.bnd[N].val[:, :1, :]) / + avg(u.pos, dy[:, -1:, :])) + dv_dy_n = (v.val[:, -1:, :] - v.bnd[N].val[:, :1, :]) / dy[:, -1:, :] + dw_dy_n = ((w.val[:, -1:, :] - w.bnd[N].val[:, :1, :]) / + avg(w.pos, dy[:, -1:, :])) + + du_dz_b = ((u.val[:, :, :1] - u.bnd[B].val[:, :, :1]) / + avg(u.pos, dz[:, :, :1])) + dv_dz_b = ((v.val[:, :, :1] - v.bnd[B].val[:, :, :1]) / + avg(v.pos, dz[:, :, :1])) + dw_dz_b = (w.val[:, :, :1] - w.bnd[B].val[:, :, :1]) / dz[:, :, :1] + + du_dz_t = (((u.val[:, :, -1:] - u.bnd[T].val[:, :, :1]) / + avg(u.pos, dz[:, :, -1:]))) + dv_dz_t = ((v.val[:, :, -1:] - v.bnd[T].val[:, :, :1]) / + avg(v.pos, dz[:, :, -1:])) + dw_dz_t = (w.val[:, :, -1:] - w.bnd[T].val[:, :, :1]) / dz[:, :, -1:] + + u_bnd_w_corr = (u.bnd[W].val[:1, :, :] + ub_out * dt * du_dx_w) + v_bnd_w_corr = (v.bnd[W].val[:1, :, :] + ub_out * dt * dv_dx_w) + w_bnd_w_corr = (w.bnd[W].val[:1, :, :] + ub_out * dt * dw_dx_w) + + u.bnd[W].val[:1, :, :] = (u.bnd[W].val[:1, :, :] * lnot(if_w_out_u) + + u_bnd_w_corr * if_w_out_u) + v.bnd[W].val[:1, :, :] = (v.bnd[W].val[:1, :, :] * lnot(if_w_out_v) + + v_bnd_w_corr * if_w_out_v) + w.bnd[W].val[:1, :, :] = (w.bnd[W].val[:1, :, :] * lnot(if_w_out_w) + + w_bnd_w_corr * if_w_out_w) + + u_bnd_e_corr = (u.bnd[E].val[:1, :, :] + ub_out * dt * du_dx_e) + v_bnd_e_corr = (v.bnd[E].val[:1, :, :] + ub_out * dt * dv_dx_e) + w_bnd_e_corr = (w.bnd[E].val[:1, :, :] + ub_out * dt * dw_dx_e) + + u.bnd[E].val[:1, :, :] = (u.bnd[E].val[:1, :, :] * lnot(if_e_out_u) + + u_bnd_e_corr * if_e_out_u) + v.bnd[E].val[:1, :, :] = (v.bnd[E].val[:1, :, :] * lnot(if_e_out_v) + + v_bnd_e_corr * if_e_out_v) + w.bnd[E].val[:1, :, :] = (w.bnd[E].val[:1, :, :] * lnot(if_e_out_w) + + w_bnd_e_corr * if_e_out_w) + + u_bnd_s_corr = (u.bnd[S].val[:, :1, :] + ub_out * dt * du_dy_s) + v_bnd_s_corr = (v.bnd[S].val[:, :1, :] + ub_out * dt * dv_dy_s) + w_bnd_s_corr = (w.bnd[S].val[:, :1, :] + ub_out * dt * dw_dy_s) + + u.bnd[S].val[:, :1, :] = (u.bnd[S].val[:, :1, :] * lnot(if_s_out_u) + + u_bnd_s_corr * if_s_out_u) + v.bnd[S].val[:, :1, :] = (v.bnd[S].val[:, :1, :] * lnot(if_s_out_v) + + v_bnd_s_corr * if_s_out_v) + w.bnd[S].val[:, :1, :] = (w.bnd[S].val[:, :1, :] * lnot(if_s_out_w) + + w_bnd_s_corr * if_s_out_w) + + u_bnd_n_corr = (u.bnd[N].val[:, :1, :] + ub_out * dt * du_dy_n) + v_bnd_n_corr = (v.bnd[N].val[:, :1, :] + ub_out * dt * dv_dy_n) + w_bnd_n_corr = (w.bnd[N].val[:, :1, :] + ub_out * dt * dw_dy_n) + + u.bnd[N].val[:, :1, :] = (u.bnd[N].val[:, :1, :] * lnot(if_n_out_u) + + u_bnd_n_corr * if_n_out_u) + v.bnd[N].val[:, :1, :] = (v.bnd[N].val[:, :1, :] * lnot(if_n_out_v) + + v_bnd_n_corr * if_n_out_v) + w.bnd[N].val[:, :1, :] = (w.bnd[N].val[:, :1, :] * lnot(if_n_out_w) + + w_bnd_n_corr * if_n_out_w) + + u_bnd_b_corr = (u.bnd[B].val[:, :, :1] + ub_out * dt * du_dz_b) + v_bnd_b_corr = (v.bnd[B].val[:, :, :1] + ub_out * dt * dv_dz_b) + w_bnd_b_corr = (w.bnd[B].val[:, :, :1] + ub_out * dt * dw_dz_b) + + u.bnd[B].val[:, :, :1] = (u.bnd[B].val[:, :, :1] * lnot(if_b_out_u) + + u_bnd_b_corr * if_b_out_u) + v.bnd[B].val[:, :, :1] = (v.bnd[B].val[:, :, :1] * lnot(if_b_out_v) + + v_bnd_b_corr * if_b_out_v) + w.bnd[B].val[:, :, :1] = (w.bnd[B].val[:, :, :1] * lnot(if_b_out_w) + + w_bnd_b_corr * if_b_out_w) + + u_bnd_t_corr = (u.bnd[T].val[:, :, :1] + ub_out * dt * du_dz_t) + v_bnd_t_corr = (v.bnd[T].val[:, :, :1] + ub_out * dt * dv_dz_t) + w_bnd_t_corr = (w.bnd[T].val[:, :, :1] + ub_out * dt * dw_dz_t) + + u.bnd[T].val[:, :, :1] = (u.bnd[T].val[:, :, :1] * lnot(if_t_out_u) + + u_bnd_t_corr * if_t_out_u) + v.bnd[T].val[:, :, :1] = (v.bnd[T].val[:, :, :1] * lnot(if_t_out_v) + + v_bnd_t_corr * if_t_out_v) + w.bnd[T].val[:, :, :1] = (w.bnd[T].val[:, :, :1] * lnot(if_t_out_w) + + w_bnd_t_corr * if_t_out_w) + + if verbatim: + print('+----------------------------+') + print('| ub_in = %12.5e |' % ub_in) + print('| a_in = %12.5e |' % area_in) + print('| v_in = %12.5e |' % vol_in) + print('| ub_out = %12.5e |' % ub_out) + print('| a_out = %12.5e |' % area_out) + print('| v_out_1 = %12.5e |' % vol_out_1) + + # --------------------------------------------- + # Scaling correction to whatever you did above + # (bulk correction or convective outflow) + # --------------------------------------------- + vol_out_2 = 0.0 + vol_out_2 -= (if_w_out_u * u.bnd[W].val[:1, :, :] * sx).sum() + vol_out_2 += (if_e_out_u * u.bnd[E].val[:1, :, :] * sx).sum() + vol_out_2 -= (if_s_out_v * v.bnd[S].val[:, :1, :] * sy).sum() + vol_out_2 += (if_n_out_v * v.bnd[N].val[:, :1, :] * sy).sum() + vol_out_2 -= (if_b_out_w * w.bnd[B].val[:, :, :1] * sz).sum() + vol_out_2 += (if_t_out_w * w.bnd[T].val[:, :, :1] * sz).sum() + + if vol_out_2 > TINY: + factor = vol_in / vol_out_2 + else: + factor = 1.0 + + if verbatim: + print('+----------------------------+') + print('| v_out_2 = %12.5e |' % vol_out_2) + print('| factor = %12.5e |' % factor) + print('+----------------------------+') + + # ------------------------------------- + # Correction to satisfy volume balance + # ------------------------------------- + u.bnd[W].val[:1, :, :] = (u.bnd[W].val[:1, :, :] * lnot(if_w_out_u) + + u.bnd[W].val[:1, :, :] * if_w_out_u * factor) + u.bnd[E].val[:1, :, :] = (u.bnd[E].val[:1, :, :] * lnot(if_e_out_u) + + u.bnd[E].val[:1, :, :] * if_e_out_u * factor) + v.bnd[S].val[:, :1, :] = (v.bnd[S].val[:, :1, :] * lnot(if_s_out_v) + + v.bnd[S].val[:, :1, :] * if_s_out_v * factor) + v.bnd[N].val[:, :1, :] = (v.bnd[N].val[:, :1, :] * lnot(if_n_out_v) + + v.bnd[N].val[:, :1, :] * if_n_out_v * factor) + w.bnd[B].val[:, :, :1] = (w.bnd[B].val[:, :, :1] * lnot(if_b_out_w) + + w.bnd[B].val[:, :, :1] * if_b_out_w * factor) + w.bnd[T].val[:, :, :1] = (w.bnd[T].val[:, :, :1] * lnot(if_t_out_w) + + w.bnd[T].val[:, :, :1] * if_t_out_w * factor) diff --git a/PYTHON/scrins/discretization/adj_o_bnds_new.py b/PYTHON/scrins/discretization/adj_o_bnds_new.py new file mode 100755 index 0000000..8e8e6aa --- /dev/null +++ b/PYTHON/scrins/discretization/adj_o_bnds_new.py @@ -0,0 +1,306 @@ +""" +Docstring. +""" +from scipy import logical_not as lnot +from scrins.constants.boundary_conditions import DIRICHLET, OUTLET +from scrins.constants.compass import W, E, S, N, B, T +from scrins.constants.tiny_and_huge import TINY +from scrins.operators.avg import avg +#========================================================================== +def adj_o_bnds(uvw, dxyz, dt): +#-------------------------------------------------------------------------- + + """ + Docstring. + """ + # Unpack tuples + u, v, w = uvw + dx, dy, dz = dxyz + + # Local variables used in this function + area_in = 0.0 # area of the inlet + area_out = 0.0 # area of the outlet + vol_in = 0.0 # inlet volume flux; positive for inflow + vol_out_1 = 0.0 # outlet volume flux; positive for outflow + vol_out_2 = 0.0 # outlet volume flux; positive for outflow + + verbatim = False + + sx = dy * dz + sy = dx * dz + sz = dx * dy + + sx = sx[:1, :, :] + sy = sy[:, :1, :] + sz = sz[:, :, :1] + + # ------------------------------------------------------------------ + # Compute the volume flowing in (v_in), volume flowing out (v_out) + # as well as inlet and outlet areas (a_in, a_out) + # ------------------------------------------------------------------ + + # Inlets: these arrays will hold values true (1) in cells \ + # with inlet boundary conditions, and false (0) otherwise + if_w_in = (u.bnd[W].typ[:1, :, :] == DIRICHLET) & \ + (u.bnd[W].val[:1, :, :] > + TINY) + if_e_in = (u.bnd[E].typ[:1, :, :] == DIRICHLET) & \ + (u.bnd[E].val[:1, :, :] < - TINY) + if_s_in = (v.bnd[S].typ[:, :1, :] == DIRICHLET) & \ + (v.bnd[S].val[:, :1, :] > + TINY) + if_n_in = (v.bnd[N].typ[:, :1, :] == DIRICHLET) & \ + (v.bnd[N].val[:, :1, :] < - TINY) + if_b_in = (w.bnd[B].typ[:, :, :1] == DIRICHLET) & \ + (w.bnd[B].val[:, :, :1] > + TINY) + if_t_in = (w.bnd[T].typ[:, :, :1] == DIRICHLET) & \ + (w.bnd[T].val[:, :, :1] < - TINY) + + # Using the arrays defined above, compute inlet surface area + area_in = area_in + (if_w_in * sx).sum() + area_in = area_in + (if_e_in * sx).sum() + area_in = area_in + (if_s_in * sy).sum() + area_in = area_in + (if_n_in * sy).sum() + area_in = area_in + (if_b_in * sz).sum() + area_in = area_in + (if_t_in * sz).sum() + + # If there is no inlet, nothing to do here any longer + if area_in < TINY: + return u, v, w # one end of function + + # Using the arrays defined above, compute inlet volume flux + vol_in += (if_w_in * u.bnd[W].val[:1, :, :] * sx).sum() + vol_in -= (if_e_in * u.bnd[E].val[:1, :, :] * sx).sum() + vol_in += (if_s_in * v.bnd[S].val[:, :1, :] * sy).sum() + vol_in -= (if_n_in * v.bnd[N].val[:, :1, :] * sy).sum() + vol_in += (if_b_in * w.bnd[B].val[:, :, :1] * sz).sum() + vol_in -= (if_t_in * w.bnd[T].val[:, :, :1] * sz).sum() + + # Outlets: these arrays will hold values true (1) in cells ... + # with outlet boundary conditions, and false (0) otherwise + if_w_out_u = (u.bnd[W].typ[:1, :, :] == OUTLET) + if_w_out_v = avg(v.pos, if_w_out_u*1) > 0.5 + if_w_out_w = avg(w.pos, if_w_out_u*1) > 0.5 + + if_e_out_u = (u.bnd[E].typ[:1, :, :] == OUTLET) + if_e_out_v = avg(v.pos, if_e_out_u*1) > 0.5 + if_e_out_w = avg(w.pos, if_e_out_u*1) > 0.5 + + if_s_out_v = (v.bnd[S].typ[:, :1, :] == OUTLET) + if_s_out_u = avg(u.pos, if_s_out_v*1) > 0.5 + if_s_out_w = avg(w.pos, if_s_out_v*1) > 0.5 + + if_n_out_v = (v.bnd[N].typ[:, :1, :] == OUTLET) + if_n_out_u = avg(u.pos, if_n_out_v*1) > 0.5 + if_n_out_w = avg(w.pos, if_n_out_v*1) > 0.5 + + if_b_out_w = (w.bnd[B].typ[:, :, :1] == OUTLET) + if_b_out_u = avg(u.pos, if_b_out_w*1) > 0.5 + if_b_out_v = avg(v.pos, if_b_out_w*1) > 0.5 + + if_t_out_w = (w.bnd[T].typ[:, :, :1] == OUTLET) + if_t_out_u = avg(u.pos, if_t_out_w*1) > 0.5 + if_t_out_v = avg(v.pos, if_t_out_w*1) > 0.5 + + # Using the arrays defined above, compute outlet surface area + area_out += (if_w_out_u * sx).sum() + area_out += (if_e_out_u * sx).sum() + area_out += (if_s_out_v * sy).sum() + area_out += (if_n_out_v * sy).sum() + area_out += (if_b_out_w * sz).sum() + area_out += (if_t_out_w * sz).sum() + + # Using the arrays defined above, compute outlet volume flux + vol_out_1 -= (if_w_out_u * u.bnd[W].val[:1, :, :] * sx).sum() + vol_out_1 += (if_e_out_u * u.bnd[E].val[:1, :, :] * sx).sum() + vol_out_1 -= (if_s_out_v * v.bnd[S].val[:, :1, :] * sy).sum() + vol_out_1 += (if_n_out_v * v.bnd[N].val[:, :1, :] * sy).sum() + vol_out_1 -= (if_b_out_w * w.bnd[B].val[:, :, :1] * sz).sum() + vol_out_1 += (if_t_out_w * w.bnd[T].val[:, :, :1] * sz).sum() + + #--------------------------------- + # Check and calculate corrections + #--------------------------------- + + if area_in == 0: + ub_in = 0 + else: + ub_in = vol_in / area_in + + if area_out == 0: + ub_out = 0 + else: + ub_out = vol_out_1 / area_out + + #---------------------------------------------- + # If nothing comes out, make a bulk correction + #---------------------------------------------- + if ub_out < TINY: + u_bulk_corr = ub_in * area_in / area_out + + u.bnd[W].val[:1, :, :] = u.bnd[W].val[:1, :, :] * lnot(if_w_out_u) \ + - u_bulk_corr * if_w_out_u + u.bnd[E].val[:1, :, :] = u.bnd[E].val[:1, :, :] * lnot(if_e_out_u) \ + + u_bulk_corr * if_e_out_u + v.bnd[S].val[:, :1, :] = v.bnd[S].val[:, :1, :] * lnot(if_s_out_v) \ + - u_bulk_corr * if_s_out_v + v.bnd[N].val[:, :1, :] = v.bnd[N].val[:, :1, :] * lnot(if_n_out_v) \ + + u_bulk_corr * if_n_out_v + w.bnd[B].val[:, :, :1] = w.bnd[B].val[:, :, :1] * lnot(if_b_out_w) \ + - u_bulk_corr * if_b_out_w + w.bnd[T].val[:, :, :1] = w.bnd[T].val[:, :, :1] * lnot(if_t_out_w) \ + + u_bulk_corr * if_t_out_w + + #-------------------------------------------------------------- + # Correction outflow by applying convective boundary condition + #-------------------------------------------------------------- + else: + du_dx_w = (u.val[ :1, :, :]-u.bnd[W].val[:1, :, :]) / dx[ :1, :, :] + dv_dx_w = (v.val[ :1, :, :] \ + - v.bnd[W].val[:1, :, :]) / avg(v.pos, dx[ :1, :, :]) + dw_dx_w = (w.val[ :1, :, :] \ + - w.bnd[W].val[:1, :, :]) / avg(w.pos, dx[ :1, :, :]) + + du_dx_e = (u.val[-1:, :, :]-u.bnd[E].val[:1, :, :]) / dx[-1:, :, :] + dv_dx_e = (v.val[-1:, :, :]\ + - v.bnd[E].val[:1, :, :]) / avg(v.pos, dx[-1:, :, :]) + dw_dx_e = (w.val[-1:, :, :] \ + -w.bnd[E].val[:1, :, :]) / avg(w.pos, dx[-1:, :, :]) + + du_dy_s = (u.val[:, :1, :] \ + -u.bnd[S].val[:, :1, :]) / avg(u.pos, dy[:, :1, :]) + dv_dy_s = (v.val[:, :1, :]-v.bnd[S].val[:, :1, :]) / dy[:, :1, :] + dw_dy_s = (w.val[:, :1, :] \ + -w.bnd[S].val[:, :1, :]) / avg(w.pos, dy[:, :1, :]) + + du_dy_n = (u.val[:, -1:, :] \ + -u.bnd[N].val[:, :1, :]) / avg(u.pos, dy[:, -1:, :]) + dv_dy_n = (v.val[:, -1:, :]-v.bnd[N].val[:, :1, :]) / dy[:, -1:, :] + dw_dy_n = (w.val[:, -1:, :] \ + -w.bnd[N].val[:, :1, :]) / avg(w.pos, dy[:, -1:, :]) + + du_dz_b = (u.val[:, :, :1] \ + -u.bnd[B].val[:, :, :1]) / avg(u.pos, dz[:, :, :1]) + dv_dz_b = (v.val[:, :, :1] \ + -v.bnd[B].val[:, :, :1]) / avg(v.pos, dz[:, :, :1]) + dw_dz_b = (w.val[:, :, :1]-w.bnd[B].val[:, :, :1]) / dz[:, :, :1] + + du_dz_t = (u.val[:, :, -1:] \ + -u.bnd[T].val[:, :, :1]) / avg(u.pos, dz[:, :, -1:]) + dv_dz_t = (v.val[:, :, -1:] \ + -v.bnd[T].val[:, :, :1]) / avg(v.pos, dz[:, :, -1:]) + dw_dz_t = (w.val[:, :, -1:]-w.bnd[T].val[:, :, :1]) / dz[:, :, -1:] + + u_bnd_w_corr = (u.bnd[W].val[:1, :, :] + ub_out * dt * du_dx_w) + v_bnd_w_corr = (v.bnd[W].val[:1, :, :] + ub_out * dt * dv_dx_w) + w_bnd_w_corr = (w.bnd[W].val[:1, :, :] + ub_out * dt * dw_dx_w) + + u.bnd[W].val[:1, :, :] = u.bnd[W].val[:1, :, :] * lnot(if_w_out_u) \ + + u_bnd_w_corr * if_w_out_u + v.bnd[W].val[:1, :, :] = v.bnd[W].val[:1, :, :] * lnot(if_w_out_v) \ + + v_bnd_w_corr * if_w_out_v + w.bnd[W].val[:1, :, :] = w.bnd[W].val[:1, :, :] * lnot(if_w_out_w) \ + + w_bnd_w_corr * if_w_out_w + + u_bnd_e_corr = (u.bnd[E].val[:1, :, :] + ub_out * dt * du_dx_e) + v_bnd_e_corr = (v.bnd[E].val[:1, :, :] + ub_out * dt * dv_dx_e) + w_bnd_e_corr = (w.bnd[E].val[:1, :, :] + ub_out * dt * dw_dx_e) + + u.bnd[E].val[:1, :, :] = u.bnd[E].val[:1, :, :] * lnot(if_e_out_u) \ + + u_bnd_e_corr * if_e_out_ + v.bnd[E].val[:1, :, :] = v.bnd[E].val[:1, :, :] * lnot(if_e_out_v) \ + + v_bnd_e_corr * if_e_out_v + w.bnd[E].val[:1, :, :] = w.bnd[E].val[:1, :, :] * lnot(if_e_out_w) \ + + w_bnd_e_corr * if_e_out_w + + u_bnd_s_corr = (u.bnd[S].val[:, :1, :] + ub_out * dt * du_dy_s) + v_bnd_s_corr = (v.bnd[S].val[:, :1, :] + ub_out * dt * dv_dy_s) + w_bnd_s_corr = (w.bnd[S].val[:, :1, :] + ub_out * dt * dw_dy_s) + + u.bnd[S].val[:, :1, :] = u.bnd[S].val[:, :1, :] * lnot(if_s_out_u) \ + + u_bnd_s_corr * if_s_out_u + v.bnd[S].val[:, :1, :] = v.bnd[S].val[:, :1, :] * lnot(if_s_out_v) \ + + v_bnd_s_corr * if_s_out_v + w.bnd[S].val[:, :1, :] = w.bnd[S].val[:, :1, :] * lnot(if_s_out_w) \ + + w_bnd_s_corr * if_s_out_w + + u_bnd_n_corr = (u.bnd[N].val[:, :1, :] + ub_out * dt * du_dy_n) + v_bnd_n_corr = (v.bnd[N].val[:, :1, :] + ub_out * dt * dv_dy_n) + w_bnd_n_corr = (w.bnd[N].val[:, :1, :] + ub_out * dt * dw_dy_n) + + u.bnd[N].val[:, :1, :] = u.bnd[N].val[:, :1, :] * lnot(if_n_out_u) \ + + u_bnd_n_corr * if_n_out_u + v.bnd[N].val[:, :1, :] = v.bnd[N].val[:, :1, :] * lnot(if_n_out_v) \ + + v_bnd_n_corr * if_n_out_v + w.bnd[N].val[:, :1, :] = w.bnd[N].val[:, :1, :] * lnot(if_n_out_w) \ + + w_bnd_n_corr * if_n_out_w + + u_bnd_b_corr = (u.bnd[B].val[:, :, :1] + ub_out * dt * du_dz_b) + v_bnd_b_corr = (v.bnd[B].val[:, :, :1] + ub_out * dt * dv_dz_b) + w_bnd_b_corr = (w.bnd[B].val[:, :, :1] + ub_out * dt * dw_dz_b) + + u.bnd[B].val[:, :, :1] = u.bnd[B].val[:, :, :1] * lnot(if_b_out_u) \ + + u_bnd_b_corr * if_b_out_u + v.bnd[B].val[:, :, :1] = v.bnd[B].val[:, :, :1] * lnot(if_b_out_v) \ + + v_bnd_b_corr * if_b_out_v + w.bnd[B].val[:, :, :1] = w.bnd[B].val[:, :, :1] * lnot(if_b_out_w) \ + + w_bnd_b_corr * if_b_out_w + + u_bnd_t_corr = (u.bnd[T].val[:, :, :1] + ub_out *dt * du_dz_t) + v_bnd_t_corr = (v.bnd[T].val[:, :, :1] + ub_out *dt * dv_dz_t) + w_bnd_t_corr = (w.bnd[T].val[:, :, :1] + ub_out *dt * dw_dz_t) + + u.bnd[T].val[:, :, :1] = u.bnd[T].val[:, :, :1] * lnot(if_t_out_u) \ + + u_bnd_t_corr * if_t_out_u + v.bnd[T].val[:, :, :1] = v.bnd[T].val[:, :, :1] * lnot(if_t_out_v) \ + + v_bnd_t_corr * if_t_out_v + w.bnd[T].val[:, :, :1] = w.bnd[T].val[:, :, :1] * lnot(if_t_out_w) \ + + w_bnd_t_corr * if_t_out_w + + if verbatim == True: + print('+----------------------------+') + print('| ub_in = %12.5e |' %ub_in) + print('| a_in = %12.5e |' %area_in) + print('| v_in = %12.5e |' %vol_in) + print('| ub_out = %12.5e |' %ub_out) + print('| a_out = %12.5e |' %area_out) + print('| v_out_1 = %12.5e |' %vol_out_1) + + # ---------------------------------------------- + # Scaling correction to whatever you did above + # (bulk correction or convective outflow) + # ---------------------------------------------- + vol_out_2 = 0.0 + vol_out_2 -= (if_w_out_u * u.bnd[W].val[:1, :, :] * sx).sum() + vol_out_2 += (if_e_out_u * u.bnd[E].val[:1, :, :] * sx).sum() + vol_out_2 -= (if_s_out_v * v.bnd[S].val[:, :1, :] * sy).sum() + vol_out_2 += (if_n_out_v * v.bnd[N].val[:, :1, :] * sy).sum() + vol_out_2 -= (if_b_out_w * w.bnd[B].val[:, :, :1] * sz).sum() + vol_out_2 += (if_t_out_w * w.bnd[T].val[:, :, :1] * sz).sum() + + if vol_out_2 > TINY: + factor = vol_in / vol_out_2 + else: + factor = 1.0 + + if verbatim == True: + print('+----------------------------+') + print('| v_out_2 = %12.5e |' %vol_out_2) + print('| factor = %12.5e |' %factor) + print('+----------------------------+') + + # -------------------------------------- + # Correction to satisfy volume balance + # -------------------------------------- + u.bnd[W].val[:1, :, :] = u.bnd[W].val[:1, :, :] * lnot(if_w_out_u) \ + + u.bnd[W].val[:1, :, :] * if_w_out_u * factor + u.bnd[E].val[:1, :, :] = u.bnd[E].val[:1, :, :] * lnot(if_e_out_u) \ + + u.bnd[E].val[:1, :, :] * if_e_out_u * factor + v.bnd[S].val[:, :1, :] = v.bnd[S].val[:, :1, :] * lnot(if_s_out_v) \ + + v.bnd[S].val[:, :1, :] * if_s_out_v * factor + v.bnd[N].val[:, :1, :] = v.bnd[N].val[:, :1, :] * lnot(if_n_out_v) \ + + v.bnd[N].val[:, :1, :] * if_n_out_v * factor + w.bnd[B].val[:, :, :1] = w.bnd[B].val[:, :, :1] * lnot(if_b_out_w) \ + + w.bnd[B].val[:, :, :1] * if_b_out_w * factor + w.bnd[T].val[:, :, :1] = w.bnd[T].val[:, :, :1] * lnot(if_t_out_w) \ + + w.bnd[T].val[:, :, :1] * if_t_out_w * factor + + return u, v, w # another end of function diff --git a/PYTHON/Discretization/adj_o_bnds_old.py b/PYTHON/scrins/discretization/adj_o_bnds_old.py old mode 100644 new mode 100755 similarity index 97% rename from PYTHON/Discretization/adj_o_bnds_old.py rename to PYTHON/scrins/discretization/adj_o_bnds_old.py index c3c756e..0f59fde --- a/PYTHON/Discretization/adj_o_bnds_old.py +++ b/PYTHON/scrins/discretization/adj_o_bnds_old.py @@ -1,200 +1,200 @@ -# Standard Python modules -from standard import * - -# ScriNS modules -from constants.all import * - -#========================================================================== -def adj_o_bnds(uvw, dxyz, dt): -#-------------------------------------------------------------------------- - - # Unpack tuples - u, v, w = uvw - dx, dy, dz = dxyz - - # Local variables used in this function - area_in = 0.0 # area of the inlet - area_out = 0.0 # area of the outlet - vol_in = 0.0 # inlet volume flux; positive for inflow - vol_out_1 = 0.0 # outlet volume flux; positive for outflow - vol_out_2 = 0.0 # outlet volume flux; positive for outflow - - verbatim = True - - sx = dy * dz - sy = dx * dz - sz = dx * dy - - sx = sx[:1,:,:] - sy = sy[:,:1,:] - sz = sz[:,:,:1] - - #------------------------------------------------------------------ - # Compute the volume flowing in (v_in), volume flowing out (v_out) - # as well as inlet and outlet areas (a_in, a_out) - #------------------------------------------------------------------ - - if_w_in = (u.bnd[W].typ[:1,:,:] == DIRICHLET) \ - & (u.bnd[W].val[:1,:,:] > +TINY) - # Inlets: these arrays will hold values true (1) in cells \ - # with inlet boundary conditions, and false (0) otherwise - if_w_in = (u.bnd[W].typ[:1,:,:]==DIRICHLET) & (u.bnd[W].val[:1,:,:]>+TINY) - if_e_in = (u.bnd[E].typ[:1,:,:]==DIRICHLET) & (u.bnd[E].val[:1,:,:]<-TINY) - if_s_in = (v.bnd[S].typ[:,:1,:]==DIRICHLET) & (v.bnd[S].val[:,:1,:]>+TINY) - if_n_in = (v.bnd[N].typ[:,:1,:]==DIRICHLET) & (v.bnd[N].val[:,:1,:]<-TINY) - if_b_in = (w.bnd[B].typ[:,:,:1]==DIRICHLET) & (w.bnd[B].val[:,:,:1]>+TINY) - if_t_in = (w.bnd[T].typ[:,:,:1]==DIRICHLET) & (w.bnd[T].val[:,:,:1]<-TINY) - - # Using the arrays defined above, compute inlet surface area - area_in = area_in + (if_w_in * sx).sum() - area_in = area_in + (if_e_in * sx).sum() - area_in = area_in + (if_s_in * sy).sum() - area_in = area_in + (if_n_in * sy).sum() - area_in = area_in + (if_b_in * sz).sum() - area_in = area_in + (if_t_in * sz).sum() - - # If there is no inlet, nothing to do here any longer - if area_in < TINY: - return u, v, w # one end of function - - # Using the arrays defined above, compute inlet volume flux - vol_in = vol_in + (if_w_in * u.bnd[W].val[:1,:,:] * sx).sum() - vol_in = vol_in - (if_e_in * u.bnd[E].val[:1,:,:] * sx).sum() - vol_in = vol_in + (if_s_in * v.bnd[S].val[:,:1,:] * sy).sum() - vol_in = vol_in - (if_n_in * v.bnd[N].val[:,:1,:] * sy).sum() - vol_in = vol_in + (if_b_in * w.bnd[B].val[:,:,:1] * sz).sum() - vol_in = vol_in - (if_t_in * w.bnd[T].val[:,:,:1] * sz).sum() - - # Outlets: these arrays will hold values true (1) in cells ... - # with outlet boundary conditions, and false (0) otherwise - if_w_out = ( u.bnd[W].typ[:1,:,:] == OUTLET ) - if_e_out = ( u.bnd[E].typ[:1,:,:] == OUTLET ) - if_s_out = ( v.bnd[S].typ[:,:1,:] == OUTLET ) - if_n_out = ( v.bnd[N].typ[:,:1,:] == OUTLET ) - if_b_out = ( w.bnd[B].typ[:,:,:1] == OUTLET ) - if_t_out = ( w.bnd[T].typ[:,:,:1] == OUTLET ) - - # Using the arrays defined above, compute outlet surface area - area_out = area_out + (if_w_out * sx).sum() - area_out = area_out + (if_e_out * sx).sum() - area_out = area_out + (if_s_out * sy).sum() - area_out = area_out + (if_n_out * sy).sum() - area_out = area_out + (if_b_out * sz).sum() - area_out = area_out + (if_t_out * sz).sum() - - # Using the arrays defined above, compute outlet volume flux - vol_out_1 = vol_out_1 - (if_w_out * u.bnd[W].val[:1,:,:] * sx).sum() - vol_out_1 = vol_out_1 + (if_e_out * u.bnd[E].val[:1,:,:] * sx).sum() - vol_out_1 = vol_out_1 - (if_s_out * v.bnd[S].val[:,:1,:] * sy).sum() - vol_out_1 = vol_out_1 + (if_n_out * v.bnd[N].val[:,:1,:] * sy).sum() - vol_out_1 = vol_out_1 - (if_b_out * w.bnd[B].val[:,:,:1] * sz).sum() - vol_out_1 = vol_out_1 + (if_t_out * w.bnd[T].val[:,:,:1] * sz).sum() - - #--------------------------------- - # Check and calculate corrections - #--------------------------------- - - if (area_in == 0): - ub_in = 0 - else: - ub_in = vol_in / area_in - - if (area_out == 0): - ub_out = 0 - else: - ub_out = vol_out_1 / area_out - - bulk_corr = 0.0 # bulk correction to velocity - corr = 0.0 # switch between bulk correction and scaling - - if(ub_out < TINY): # bulk correction makes sense if nothing comes out - bulk_corr = ub_in * area_in / area_out - corr = 0.0 - else: # scaling factor makes sense if something comes out - bulk_corr = 0.0 - corr = 1.0 - - if verbatim == True: - print('+----------------------------+' ) - print('| ub_in = %12.5e |' %ub_in ) - print('| a_in = %12.5e |' %area_in ) - print('| v_in = %12.5e |' %vol_in ) - print('| ub_out = %12.5e |' %ub_out ) - print('| a_out = %12.5e |' %area_out ) - print('| v_out_1 = %12.5e |' %vol_out_1) - print('| bulk_corr = %12.5e |' %bulk_corr) - print('| corr = %12.5e |' %corr ) - - #-------------------------------------------------------------- - # Correction outflow by applying convective boundary condition - #-------------------------------------------------------------- - u_bnd_w_corr = - bulk_corr + corr * \ - (u.bnd[W].val[:1,:,:] + ub_out*dt*(u.val[:1,:,:]-u.bnd[W].val[:1,:,:])/dx[:1,:,:]) - u.bnd[W].val[:1,:,:] = u.bnd[W].val[:1,:,:] * lnot(if_w_out) \ - + u_bnd_w_corr * if_w_out - - u_bnd_e_corr = + bulk_corr + corr * \ - (u.bnd[E].val[:1,:,:] + ub_out*dt*(u.val[-1:,:,:]-u.bnd[E].val[:1,:,:])/dx[-1:,:,:]) - u.bnd[E].val[:1,:,:] = u.bnd[E].val[:1,:,:] * lnot(if_e_out) \ - + u_bnd_e_corr * if_e_out - - v_bnd_s_corr = - bulk_corr + corr * \ - (v.bnd[S].val[:,:1,:] + ub_out*dt*(v.val[:,:1,:]-v.bnd[S].val[:,:1,:])/dy[:,:1,:]) - v.bnd[S].val[:,:1,:] = v.bnd[S].val[:,:1,:] * lnot(if_s_out) \ - + v_bnd_s_corr * if_s_out - - v_bnd_n_corr = + bulk_corr + corr * \ - (v.bnd[N].val[:,:1,:] + ub_out*dt*(v.val[:,-1:,:]-v.bnd[N].val[:,:1,:])/dy[:,-1:,:]) - v.bnd[N].val[:,:1,:] = v.bnd[N].val[:,:1,:] * lnot(if_n_out) \ - + v_bnd_n_corr * if_n_out - - w_bnd_b_corr = - bulk_corr + corr * \ - (w.bnd[B].val[:,:,:1] + ub_out*dt*(w.val[:,:,:1]-w.bnd[B].val[:,:,:1])/dz[:,:,:1]) - w.bnd[B].val[:,:,:1] = w.bnd[B].val[:,:,:1] * lnot(if_b_out) \ - + w_bnd_b_corr * if_b_out - - w_bnd_t_corr = + bulk_corr + corr * \ - (w.bnd[T].val[:,:,:1] + ub_out*dt*(w.val[:,:,-1:]-w.bnd[T].val[:,:,:1])/dz[:,:,-1:]) - w.bnd[T].val[:,:,:1] = w.bnd[T].val[:,:,:1] * lnot(if_t_out) \ - + w_bnd_t_corr * if_t_out - - #---------------------------------------------- - # Scaling correction to whatever you did above - # (bulk correction or convective outflow) - #---------------------------------------------- - vol_out_2 = 0.0 - vol_out_2 = vol_out_2 - (if_w_out * u.bnd[W].val[:1,:,:] * sx).sum() - vol_out_2 = vol_out_2 + (if_e_out * u.bnd[E].val[:1,:,:] * sx).sum() - vol_out_2 = vol_out_2 - (if_s_out * v.bnd[S].val[:,:1,:] * sy).sum() - vol_out_2 = vol_out_2 + (if_n_out * v.bnd[N].val[:,:1,:] * sy).sum() - vol_out_2 = vol_out_2 - (if_b_out * w.bnd[B].val[:,:,:1] * sz).sum() - vol_out_2 = vol_out_2 + (if_t_out * w.bnd[T].val[:,:,:1] * sz).sum() - - if vol_out_2 > TINY: - factor = vol_in / vol_out_2 - else: - factor = 1.0 - - if verbatim == True: - print('+----------------------------+') - print('| v_out_2 = %12.5e |' %vol_out_2) - print('| factor = %12.5e |' %factor ) - print('+----------------------------+') - - #-------------------------------------- - # Correction to satisfy volume balance - #-------------------------------------- - u.bnd[W].val[:1,:,:] = u.bnd[W].val[:1,:,:] * lnot(if_w_out) \ - + u.bnd[W].val[:1,:,:] * if_w_out * factor - u.bnd[E].val[:1,:,:] = u.bnd[E].val[:1,:,:] * lnot(if_e_out) \ - + u.bnd[E].val[:1,:,:] * if_e_out * factor - v.bnd[S].val[:,:1,:] = v.bnd[S].val[:,:1,:] * lnot(if_s_out) \ - + v.bnd[S].val[:,:1,:] * if_s_out * factor - v.bnd[N].val[:,:1,:] = v.bnd[N].val[:,:1,:] * lnot(if_n_out) \ - + v.bnd[N].val[:,:1,:] * if_n_out * factor - w.bnd[B].val[:,:,:1] = w.bnd[B].val[:,:,:1] * lnot(if_b_out) \ - + w.bnd[B].val[:,:,:1] * if_b_out * factor - w.bnd[T].val[:,:,:1] = w.bnd[T].val[:,:,:1] * lnot(if_t_out) \ - + w.bnd[T].val[:,:,:1] * if_t_out * factor - - return u, v, w # another end of function +# Standard Python modules +from standard import * + +# ScriNS modules +from constants.all import * + +#========================================================================== +def adj_o_bnds(uvw, dxyz, dt): +#-------------------------------------------------------------------------- + + # Unpack tuples + u, v, w = uvw + dx, dy, dz = dxyz + + # Local variables used in this function + area_in = 0.0 # area of the inlet + area_out = 0.0 # area of the outlet + vol_in = 0.0 # inlet volume flux; positive for inflow + vol_out_1 = 0.0 # outlet volume flux; positive for outflow + vol_out_2 = 0.0 # outlet volume flux; positive for outflow + + verbatim = True + + sx = dy * dz + sy = dx * dz + sz = dx * dy + + sx = sx[:1,:,:] + sy = sy[:,:1,:] + sz = sz[:,:,:1] + + #------------------------------------------------------------------ + # Compute the volume flowing in (v_in), volume flowing out (v_out) + # as well as inlet and outlet areas (a_in, a_out) + #------------------------------------------------------------------ + + if_w_in = (u.bnd[W].typ[:1,:,:] == DIRICHLET) \ + & (u.bnd[W].val[:1,:,:] > +TINY) + # Inlets: these arrays will hold values true (1) in cells \ + # with inlet boundary conditions, and false (0) otherwise + if_w_in = (u.bnd[W].typ[:1,:,:]==DIRICHLET) & (u.bnd[W].val[:1,:,:]>+TINY) + if_e_in = (u.bnd[E].typ[:1,:,:]==DIRICHLET) & (u.bnd[E].val[:1,:,:]<-TINY) + if_s_in = (v.bnd[S].typ[:,:1,:]==DIRICHLET) & (v.bnd[S].val[:,:1,:]>+TINY) + if_n_in = (v.bnd[N].typ[:,:1,:]==DIRICHLET) & (v.bnd[N].val[:,:1,:]<-TINY) + if_b_in = (w.bnd[B].typ[:,:,:1]==DIRICHLET) & (w.bnd[B].val[:,:,:1]>+TINY) + if_t_in = (w.bnd[T].typ[:,:,:1]==DIRICHLET) & (w.bnd[T].val[:,:,:1]<-TINY) + + # Using the arrays defined above, compute inlet surface area + area_in = area_in + (if_w_in * sx).sum() + area_in = area_in + (if_e_in * sx).sum() + area_in = area_in + (if_s_in * sy).sum() + area_in = area_in + (if_n_in * sy).sum() + area_in = area_in + (if_b_in * sz).sum() + area_in = area_in + (if_t_in * sz).sum() + + # If there is no inlet, nothing to do here any longer + if area_in < TINY: + return u, v, w # one end of function + + # Using the arrays defined above, compute inlet volume flux + vol_in = vol_in + (if_w_in * u.bnd[W].val[:1,:,:] * sx).sum() + vol_in = vol_in - (if_e_in * u.bnd[E].val[:1,:,:] * sx).sum() + vol_in = vol_in + (if_s_in * v.bnd[S].val[:,:1,:] * sy).sum() + vol_in = vol_in - (if_n_in * v.bnd[N].val[:,:1,:] * sy).sum() + vol_in = vol_in + (if_b_in * w.bnd[B].val[:,:,:1] * sz).sum() + vol_in = vol_in - (if_t_in * w.bnd[T].val[:,:,:1] * sz).sum() + + # Outlets: these arrays will hold values true (1) in cells ... + # with outlet boundary conditions, and false (0) otherwise + if_w_out = ( u.bnd[W].typ[:1,:,:] == OUTLET ) + if_e_out = ( u.bnd[E].typ[:1,:,:] == OUTLET ) + if_s_out = ( v.bnd[S].typ[:,:1,:] == OUTLET ) + if_n_out = ( v.bnd[N].typ[:,:1,:] == OUTLET ) + if_b_out = ( w.bnd[B].typ[:,:,:1] == OUTLET ) + if_t_out = ( w.bnd[T].typ[:,:,:1] == OUTLET ) + + # Using the arrays defined above, compute outlet surface area + area_out = area_out + (if_w_out * sx).sum() + area_out = area_out + (if_e_out * sx).sum() + area_out = area_out + (if_s_out * sy).sum() + area_out = area_out + (if_n_out * sy).sum() + area_out = area_out + (if_b_out * sz).sum() + area_out = area_out + (if_t_out * sz).sum() + + # Using the arrays defined above, compute outlet volume flux + vol_out_1 = vol_out_1 - (if_w_out * u.bnd[W].val[:1,:,:] * sx).sum() + vol_out_1 = vol_out_1 + (if_e_out * u.bnd[E].val[:1,:,:] * sx).sum() + vol_out_1 = vol_out_1 - (if_s_out * v.bnd[S].val[:,:1,:] * sy).sum() + vol_out_1 = vol_out_1 + (if_n_out * v.bnd[N].val[:,:1,:] * sy).sum() + vol_out_1 = vol_out_1 - (if_b_out * w.bnd[B].val[:,:,:1] * sz).sum() + vol_out_1 = vol_out_1 + (if_t_out * w.bnd[T].val[:,:,:1] * sz).sum() + + #--------------------------------- + # Check and calculate corrections + #--------------------------------- + + if (area_in == 0): + ub_in = 0 + else: + ub_in = vol_in / area_in + + if (area_out == 0): + ub_out = 0 + else: + ub_out = vol_out_1 / area_out + + bulk_corr = 0.0 # bulk correction to velocity + corr = 0.0 # switch between bulk correction and scaling + + if(ub_out < TINY): # bulk correction makes sense if nothing comes out + bulk_corr = ub_in * area_in / area_out + corr = 0.0 + else: # scaling factor makes sense if something comes out + bulk_corr = 0.0 + corr = 1.0 + + if verbatim == True: + print('+----------------------------+' ) + print('| ub_in = %12.5e |' %ub_in ) + print('| a_in = %12.5e |' %area_in ) + print('| v_in = %12.5e |' %vol_in ) + print('| ub_out = %12.5e |' %ub_out ) + print('| a_out = %12.5e |' %area_out ) + print('| v_out_1 = %12.5e |' %vol_out_1) + print('| bulk_corr = %12.5e |' %bulk_corr) + print('| corr = %12.5e |' %corr ) + + #-------------------------------------------------------------- + # Correction outflow by applying convective boundary condition + #-------------------------------------------------------------- + u_bnd_w_corr = - bulk_corr + corr * \ + (u.bnd[W].val[:1,:,:] + ub_out*dt*(u.val[:1,:,:]-u.bnd[W].val[:1,:,:])/dx[:1,:,:]) + u.bnd[W].val[:1,:,:] = u.bnd[W].val[:1,:,:] * lnot(if_w_out) \ + + u_bnd_w_corr * if_w_out + + u_bnd_e_corr = + bulk_corr + corr * \ + (u.bnd[E].val[:1,:,:] + ub_out*dt*(u.val[-1:,:,:]-u.bnd[E].val[:1,:,:])/dx[-1:,:,:]) + u.bnd[E].val[:1,:,:] = u.bnd[E].val[:1,:,:] * lnot(if_e_out) \ + + u_bnd_e_corr * if_e_out + + v_bnd_s_corr = - bulk_corr + corr * \ + (v.bnd[S].val[:,:1,:] + ub_out*dt*(v.val[:,:1,:]-v.bnd[S].val[:,:1,:])/dy[:,:1,:]) + v.bnd[S].val[:,:1,:] = v.bnd[S].val[:,:1,:] * lnot(if_s_out) \ + + v_bnd_s_corr * if_s_out + + v_bnd_n_corr = + bulk_corr + corr * \ + (v.bnd[N].val[:,:1,:] + ub_out*dt*(v.val[:,-1:,:]-v.bnd[N].val[:,:1,:])/dy[:,-1:,:]) + v.bnd[N].val[:,:1,:] = v.bnd[N].val[:,:1,:] * lnot(if_n_out) \ + + v_bnd_n_corr * if_n_out + + w_bnd_b_corr = - bulk_corr + corr * \ + (w.bnd[B].val[:,:,:1] + ub_out*dt*(w.val[:,:,:1]-w.bnd[B].val[:,:,:1])/dz[:,:,:1]) + w.bnd[B].val[:,:,:1] = w.bnd[B].val[:,:,:1] * lnot(if_b_out) \ + + w_bnd_b_corr * if_b_out + + w_bnd_t_corr = + bulk_corr + corr * \ + (w.bnd[T].val[:,:,:1] + ub_out*dt*(w.val[:,:,-1:]-w.bnd[T].val[:,:,:1])/dz[:,:,-1:]) + w.bnd[T].val[:,:,:1] = w.bnd[T].val[:,:,:1] * lnot(if_t_out) \ + + w_bnd_t_corr * if_t_out + + #---------------------------------------------- + # Scaling correction to whatever you did above + # (bulk correction or convective outflow) + #---------------------------------------------- + vol_out_2 = 0.0 + vol_out_2 = vol_out_2 - (if_w_out * u.bnd[W].val[:1,:,:] * sx).sum() + vol_out_2 = vol_out_2 + (if_e_out * u.bnd[E].val[:1,:,:] * sx).sum() + vol_out_2 = vol_out_2 - (if_s_out * v.bnd[S].val[:,:1,:] * sy).sum() + vol_out_2 = vol_out_2 + (if_n_out * v.bnd[N].val[:,:1,:] * sy).sum() + vol_out_2 = vol_out_2 - (if_b_out * w.bnd[B].val[:,:,:1] * sz).sum() + vol_out_2 = vol_out_2 + (if_t_out * w.bnd[T].val[:,:,:1] * sz).sum() + + if vol_out_2 > TINY: + factor = vol_in / vol_out_2 + else: + factor = 1.0 + + if verbatim == True: + print('+----------------------------+') + print('| v_out_2 = %12.5e |' %vol_out_2) + print('| factor = %12.5e |' %factor ) + print('+----------------------------+') + + #-------------------------------------- + # Correction to satisfy volume balance + #-------------------------------------- + u.bnd[W].val[:1,:,:] = u.bnd[W].val[:1,:,:] * lnot(if_w_out) \ + + u.bnd[W].val[:1,:,:] * if_w_out * factor + u.bnd[E].val[:1,:,:] = u.bnd[E].val[:1,:,:] * lnot(if_e_out) \ + + u.bnd[E].val[:1,:,:] * if_e_out * factor + v.bnd[S].val[:,:1,:] = v.bnd[S].val[:,:1,:] * lnot(if_s_out) \ + + v.bnd[S].val[:,:1,:] * if_s_out * factor + v.bnd[N].val[:,:1,:] = v.bnd[N].val[:,:1,:] * lnot(if_n_out) \ + + v.bnd[N].val[:,:1,:] * if_n_out * factor + w.bnd[B].val[:,:,:1] = w.bnd[B].val[:,:,:1] * lnot(if_b_out) \ + + w.bnd[B].val[:,:,:1] * if_b_out * factor + w.bnd[T].val[:,:,:1] = w.bnd[T].val[:,:,:1] * lnot(if_t_out) \ + + w.bnd[T].val[:,:,:1] * if_t_out * factor + + return u, v, w # another end of function diff --git a/PYTHON/scrins/discretization/advection.py b/PYTHON/scrins/discretization/advection.py new file mode 100755 index 0000000..29a79f5 --- /dev/null +++ b/PYTHON/scrins/discretization/advection.py @@ -0,0 +1,307 @@ +""" +Comment. +""" +from numpy import ones, zeros + +from scipy import logical_not as lnot +from scipy import minimum as mn +from scipy import maximum as mx + + +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.constants.tiny_and_huge import TINY +from scrins.operators.avg import avg +from scrins.operators.cat import cat +from scrins.operators.dif import dif + +# ========================================================================== +def advection(rho, phi, uvwf, dxyz, dt, lim_name): + """ + Docstring. + """ + res = phi.val.shape + nx, ny, nz = res + + # Unpack tuples + uf, vf, wf = uvwf + dx, dy, dz = dxyz + + d = phi.pos + + # Pre-compute geometrical quantities + sx = dy * dz + sy = dx * dz + sz = dx * dy + + # ------------------------------------------------- + # Specific for cell-centered transported variable + # ------------------------------------------------- + if d == C: + + # Facial values of physical properties including boundary cells + rho_x_fac = cat(X, (rho[:1, :, :], avg(X, rho), rho[-1:, :, :])) # nxp,ny, nz + rho_y_fac = cat(Y, (rho[:, :1, :], avg(Y, rho), rho[:, -1:, :])) # nx, nyp,nz + rho_z_fac = cat(Z, (rho[:, :, :1], avg(Z, rho), rho[:, :, -1:])) # nx, ny, nzp + + # Facial values of areas including boundary cells + a_x_fac = cat(X, (sx[:1, :, :], avg(X, sx), sx[-1:, :, :])) + a_y_fac = cat(Y, (sy[:, :1, :], avg(Y, sy), sy[:, -1:, :])) + a_z_fac = cat(Z, (sz[:, :, :1], avg(Z, sz), sz[:, :, -1:])) + + del_x = avg(X, dx) + del_y = avg(Y, dy) + del_z = avg(Z, dz) + + # Facial values of velocities without boundary values + u_fac = uf.val # nxm,ny, nz + v_fac = vf.val # nx, nym,nz + w_fac = wf.val # nx, ny, nzm + + # Boundary velocity values + u_bnd_W = uf.bnd[W].val + u_bnd_E = uf.bnd[E].val + v_bnd_S = vf.bnd[S].val + v_bnd_N = vf.bnd[N].val + w_bnd_B = wf.bnd[B].val + w_bnd_T = wf.bnd[T].val + + # ------------------------------------------------------------ + # Specific for transported variable staggered in x direction + # ------------------------------------------------------------ + if d == X: + # Facial values of physical properties including boundary cells + rho_x_fac = rho # nx, ny, nz + rho_nod_y = avg(X, avg(Y, rho)) # nxm,nym,nz + rho_y_fac = cat(Y, (rho_nod_y[:, :1, :], \ + rho_nod_y[:, :, :], \ + rho_nod_y[:, -1:, :])) # nxm,nyp,nz + rho_nod_z = avg(X, avg(Z, rho)) # nxm,ny,nzm + rho_z_fac = cat(Z, (rho_nod_z[:, :, :1], \ + rho_nod_z[:, :, :], \ + rho_nod_z[:, :, -1:])) # nxm,ny,nzp + + # Facial values of areas including boundary cells + a_x_fac = sx + a_y_fac = cat(Y, ( \ + avg(X, sy[:, :1, :]),\ + avg(X, avg(Y, sy)), \ + avg(X, sy[:, -1:, :]))) + a_z_fac = cat(Z, ( \ + avg(X, sz[:, :, :1]), \ + avg(X, avg(Z, sz)), \ + avg(X, sz[:, :, -1:]))) + + del_x = dx[1:-1, :, :] + del_y = avg(X, avg(Y, dy)) + del_z = avg(X, avg(Z, dz)) + + # Facial values of velocities without boundary values + u_fac = avg(X, uf.val) # nxmm,ny, nz + v_fac = avg(X, vf.val) # nxm, nym,nz + w_fac = avg(X, wf.val) # nxm, ny, nzm + + # Boundary velocity values + u_bnd_W = uf.bnd[W].val + u_bnd_E = uf.bnd[E].val + v_bnd_S = avg(X, vf.bnd[S].val) + v_bnd_N = avg(X, vf.bnd[N].val) + w_bnd_B = avg(X, wf.bnd[B].val) + w_bnd_T = avg(X, wf.bnd[T].val) + + # ------------------------------------------------------------ + # Specific for transported variable staggered in y direction + # ------------------------------------------------------------ + if d == Y: + # Facial values of physical properties including boundary cells + rho_nod_x = avg(Y, avg(X, rho)) # nxm,nym,nz + rho_x_fac = cat(X, (rho_nod_x[:1, :, :], \ + rho_nod_x[:, :, :], \ + rho_nod_x[-1:, :, :])) # nxp,nym,nz + rho_y_fac = rho # nx, ny, nz + rho_nod_z = avg(Y, avg(Z, rho)) # nx, nym,nzm + rho_z_fac = cat(Z, (rho_nod_z[:, :, :1], \ + rho_nod_z[:, :, :], \ + rho_nod_z[:, :, -1:])) # nx, nym,nzp + + # Facial values of areas including boundary cells + a_x_fac = cat(X, ( \ + avg(Y, sx[:1, :, :]), \ + avg(Y, avg(X, sx)), \ + avg(Y, sx[-1:, :, :]))) + a_y_fac = sy + a_z_fac = cat(Z, ( \ + avg(Y, sz[:, :, :1]), \ + avg(Y, avg(Z, sz)), \ + avg(Y, sz[:, :, -1:]))) + + del_x = avg(Y, avg(X, dx)) + del_y = dy[:, 1:-1, :] + del_z = avg(Y, avg(Z, dz)) + + # Facial values of velocities without boundary values + u_fac = avg(Y, uf.val) # nxm,nym, nz + v_fac = avg(Y, vf.val) # nx, nymm,nz + w_fac = avg(Y, wf.val) # nx, nym, nzm + + # Facial values of velocities with boundary values + u_bnd_W = avg(Y, uf.bnd[W].val) + u_bnd_E = avg(Y, uf.bnd[E].val) + v_bnd_S = vf.bnd[S].val + v_bnd_N = vf.bnd[N].val + w_bnd_B = avg(Y, wf.bnd[B].val) + w_bnd_T = avg(Y, wf.bnd[T].val) + + # ------------------------------------------------------------ + # Specific for transported variable staggered in z direction + # ------------------------------------------------------------ + if d == Z: + + # Facial values of physical properties including boundary cells + rho_nod_x = avg(Z, avg(X, rho)) # nxm,ny, nzm + rho_x_fac = cat(X, (rho_nod_x[ :1, :, :], \ + rho_nod_x[ :, :, :], \ + rho_nod_x[-1:, :, :])) # nxp,ny, nzm + rho_nod_y = avg(Z, avg(Y, rho)) # nx, nym,nzm + rho_y_fac = cat(Y, (rho_nod_y[:, :1, :], \ + rho_nod_y[:, :, :], \ + rho_nod_y[:, -1:, :])) # nx, nyp,nzm + rho_z_fac = rho # nx, ny, nz + + # Facial values of areas including boundary cells + a_x_fac = cat(X, ( \ + avg(Z, sx[:1, :, :]), \ + avg(Z, avg(X, sx)), \ + avg(Z, sx[-1:, :, :]))) + a_y_fac = cat(Y, ( \ + avg(Z, sy[:, :1, :]), \ + avg(Z, avg(Y, sy)), \ + avg(Z, sy[:, -1:, :]))) + a_z_fac = sz + + del_x = avg(Z, avg(X, dx)) + del_y = avg(Z, avg(Y, dy)) + del_z = dz[:, :, 1:-1] + + # Facial values of velocities without boundary values + u_fac = avg(Z, uf.val) # nxm,ny, nzm + v_fac = avg(Z, vf.val) # nx, nym, nzm + w_fac = avg(Z, wf.val) # nx, ny, nzmm + + # Facial values of velocities with boundary values + u_bnd_W = avg(Z, uf.bnd[W].val) + u_bnd_E = avg(Z, uf.bnd[E].val) + v_bnd_S = avg(Z, vf.bnd[S].val) + v_bnd_N = avg(Z, vf.bnd[N].val) + w_bnd_B = wf.bnd[B].val + w_bnd_T = wf.bnd[T].val + + # ------------------------------ + # Common part of the algorithm + # ------------------------------ + + # ------------------------------------------------------------ + # + # |-o-|-o-|-o-|-o-|-o-|-o-|-o-|-o-|-o-|-o-| + # 1 2 3 4 5 6 7 8 9 10 phi + # x---x---x---x---x---x---x---x---x + # 1 2 3 4 5 6 7 8 9 d_x initial + # 0---x---x---x---x---x---x---x---x---x---0 + # 1 2 3 4 5 6 7 8 9 10 11 d_x padded + # + # ------------------------------------------------------------ + + # Compute consecutive differences (and avoid division by zero) + d_x = dif(X, phi.val) # nxm, ny, nz + d_x[(d_x > -TINY) & (d_x <= 0.0)] = -TINY + d_x[(d_x >= 0.0) & (d_x < +TINY)] = +TINY + d_x = cat(X, (d_x[:1, :, :], d_x, d_x[-1:, :, :])) # nxp, ny, nz + + d_y = dif(Y, phi.val) # nx, nym, nz + d_y[(d_y > -TINY) & (d_y <= 0.0)] = -TINY + d_y[(d_y >= 0.0) & (d_y < +TINY)] = +TINY + d_y = cat(Y, (d_y[:, :1, :], d_y, d_y[:, -1:, :])) # nx, nyp, nz + + d_z = dif(Z, phi.val) # nx, ny, nzm + d_z[(d_z > -TINY) & (d_z <= 0.0)] = -TINY + d_z[(d_z >= 0.0) & (d_z < +TINY)] = +TINY + d_z = cat(Z, (d_z[:, :, :1], d_z, d_z[:, :, -1:])) # nx, ny, nzp + + # Ratio of consecutive gradients for positive and negative flow + r_x_we = d_x[1:-1, :, :] / d_x[0:-2, :, :] # nxm,ny, nz + r_x_ew = d_x[2:, :, :] / d_x[1:-1, :, :] # nxm,ny, nz + r_y_sn = d_y[:, 1:-1, :] / d_y[:, 0:-2, :] # nx, nym,nz + r_y_ns = d_y[:, 2:, :] / d_y[:, 1:-1, :] # nx, nym,nz + r_z_bt = d_z[:, :, 1:-1] / d_z[:, :, 0:-2] # nx, ny, nzm + r_z_tb = d_z[:, :, 2: ] / d_z[:, :, 1:-1] # nx, ny, nzm + + flow_we = u_fac >= 0 + flow_ew = lnot(flow_we) + flow_sn = v_fac >= 0 + flow_ns = lnot(flow_sn) + flow_bt = w_fac >= 0 + flow_tb = lnot(flow_bt) + + r_x = r_x_we * flow_we + r_x_ew * flow_ew + r_y = r_y_sn * flow_sn + r_y_ns * flow_ns + r_z = r_z_bt * flow_bt + r_z_tb * flow_tb + + # Apply a limiter + if lim_name == 'upwind': + psi_x = r_x * 0.0 + psi_y = r_y * 0.0 + psi_z = r_z * 0.0 + elif lim_name == 'minmod': + psi_x = mx(zeros(r_x.shape), mn(r_x, ones(r_x.shape))) + psi_y = mx(zeros(r_y.shape), mn(r_y, ones(r_y.shape))) + psi_z = mx(zeros(r_z.shape), mn(r_z, ones(r_z.shape))) + elif lim_name == 'superbee': + psi_x = mx(zeros(r_x.shape), mn(2.*r_x, ones(r_x.shape)), mn(r_x, 2.)) + psi_y = mx(zeros(r_y.shape), mn(2.*r_y, ones(r_y.shape)), mn(r_y, 2.)) + psi_z = mx(zeros(r_z.shape), mn(2.*r_z, ones(r_z.shape)), mn(r_z, 2.)) + elif lim_name == 'koren': + psi_x = mx(zeros(r_x.shape), mn(2.*r_x, (2.+r_x)/3., \ + 2.*ones(r_x.shape))) + psi_y = mx(zeros(r_y.shape), mn(2.*r_y, (2.+r_y)/3., \ + 2.*ones(r_y.shape))) + psi_z = mx(zeros(r_z.shape), mn(2.*r_z, (2.+r_z)/3., \ + 2.*ones(r_z.shape))) + + flux_fac_lim_x = phi.val[0:-1, :, :] * u_fac * flow_we \ + + phi.val[1:, :, :] * u_fac * flow_ew \ + + 0.5 * abs(u_fac) * (1 - abs(u_fac) * dt / del_x) \ + * (psi_x[:, :, :] * d_x[0:nx-1, :, :] * flow_we \ + + psi_x[:, :, :] * d_x[1:nx, :, :] * flow_ew) + flux_fac_lim_y = phi.val[:, 0:-1, :] * v_fac * flow_sn \ + + phi.val[:, 1:, :] * v_fac * flow_ns \ + + 0.5 * abs(v_fac) * (1 - abs(v_fac) * dt / del_y) \ + * (psi_y[:, :, :] * d_y[:, 0:ny-1, :] * flow_sn \ + + psi_y[:, :, :] * d_y[:, 1:ny, :] * flow_ns) + flux_fac_lim_z = phi.val[:, :, 0:-1] * w_fac * flow_bt \ + + phi.val[:, :, 1: ] * w_fac * flow_tb \ + + 0.5 * abs(w_fac) * (1 - abs(w_fac) * dt / del_z) \ + * (psi_z[:, :, :] * d_z[:, :, 0:nz-1] * flow_bt \ + + psi_z[:, :, :] * d_z[:, :, 1:nz] * flow_tb) + + # Pad with boundary values + flux_fac_lim_x = cat(X, (phi.bnd[W].val * u_bnd_W, \ + flux_fac_lim_x, \ + phi.bnd[E].val * u_bnd_E)) + flux_fac_lim_y = cat(Y, (phi.bnd[S].val * v_bnd_S, \ + flux_fac_lim_y, \ + phi.bnd[N].val * v_bnd_N)) + flux_fac_lim_z = cat(Z, (phi.bnd[B].val * w_bnd_B, \ + flux_fac_lim_z, \ + phi.bnd[T].val * w_bnd_T)) + + # Multiply with face areas + flux_fac_lim_x = rho_x_fac * flux_fac_lim_x * a_x_fac + flux_fac_lim_y = rho_y_fac * flux_fac_lim_y * a_y_fac + flux_fac_lim_z = rho_z_fac * flux_fac_lim_z * a_z_fac + + # Sum contributions from all directions up + c = dif(X, flux_fac_lim_x) + \ + dif(Y, flux_fac_lim_y) + \ + dif(Z, flux_fac_lim_z) + + return c # end of function diff --git a/PYTHON/scrins/discretization/calc_p.py b/PYTHON/scrins/discretization/calc_p.py new file mode 100755 index 0000000..3e3417b --- /dev/null +++ b/PYTHON/scrins/discretization/calc_p.py @@ -0,0 +1,51 @@ +""" +Docstring. +""" +from numpy import reshape, prod, zeros +from scipy.sparse.linalg import bicgstab + +from scrins.discretization.adj_n_bnds import adj_n_bnds +from scrins.discretization.create_matrix import create_matrix +from scrins.discretization.vol_balance import vol_balance +from scrins.discretization.obst_zero_val import obst_zero_val +from scrins.constants.solver import TOL + +# ========================================================================== +def calc_p(p, uvwf, rho, dt, dxyz, obst): + """ + Calculating the Pressure. + """ + # ------------------------------------------------------------------------- + # Fetch the resolution + rc = p.val.shape + # Create linear system + A_p, b_p = create_matrix(p, zeros(rc), dt/rho, dxyz, obst, 'n') + + # Compute the source for the pressure. Important: don't send "obst" + # as a parameter here, because you don't want to take it into + # account at this stage. After velocity corrections, you should. + b_p = vol_balance(uvwf, dxyz, zeros(rc)) + + print('Maximum volume error before correction: %12.5e' % abs(b_p).max()) + print('Volume imbalance before correction : %12.5e' % b_p.sum()) + + # Solve for pressure + res = bicgstab(A_p, reshape(b_p, prod(rc)), tol=TOL) + p.val[:] = reshape(res[0], rc) + + print("res[1] = ", res[1]) + + # Anchor it to values around zero (the absolute value of pressure + # correction can get really volatile. Although it is in prinicple not + # important for incompressible flows, it is ugly for post-processing. + p.val[:] = p.val[:] - p.val.mean() + + # Set to zero in obstacle (it can get strange + # values during the iterative solution procedure) + if obst.any() != 0: + p.val[:] = obst_zero_val(p.pos, p.val, obst) + + # Finally adjust the boundary values + p = adj_n_bnds(p) + + return # end of function diff --git a/PYTHON/scrins/discretization/calc_t.py b/PYTHON/scrins/discretization/calc_t.py new file mode 100755 index 0000000..9a7fd28 --- /dev/null +++ b/PYTHON/scrins/discretization/calc_t.py @@ -0,0 +1,44 @@ +""" +Docstring. +""" +from numpy import reshape +from scipy.sparse.linalg import bicgstab +from scipy import prod + +from scrins.discretization.adj_n_bnds import adj_n_bnds +from scrins.discretization.advection import advection +from scrins.discretization.create_matrix import create_matrix +from scrins.constants.solver import TOL + +# ========================================================================== +def calc_t(t, uvwf, rho_cap, kappa, dt, dxyz, obst): +# -------------------------------------------------------------------------- + """ + Docstring. + """ + + # Unpack tuple(s) + dx, dy, dz = dxyz + + # Fetch the resolution + rc = t.val.shape + + # Discretize the diffusive part + A_t, b_t = create_matrix(t, rho_cap/dt, kappa, dxyz, obst, 'n') + + # The advective fluxes + c_t = advection(rho_cap, t, uvwf, dxyz, dt, 'minmod') + + # Innertial term for enthalpy + i_t = t.old * rho_cap * dx * dy* dz / dt + + # The entire source term + f_t = b_t - c_t + i_t + + # Solve for temperature + res0 = bicgstab(A_t, reshape(f_t, prod(rc)), tol=TOL) + t.val[:] = reshape(res0[0], rc) + + adj_n_bnds(t) + + return # end of function diff --git a/PYTHON/scrins/discretization/calc_uvw.py b/PYTHON/scrins/discretization/calc_uvw.py new file mode 100755 index 0000000..b0bd85e --- /dev/null +++ b/PYTHON/scrins/discretization/calc_uvw.py @@ -0,0 +1,150 @@ +""" +Calculate uvw +TODO: Write useful docstring +""" + +from numpy import reshape +from scipy import prod +from scipy.sparse.linalg import bicgstab + +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.constants.solver import TOL +from scrins.discretization.adj_o_bnds import adj_o_bnds +from scrins.discretization.advection import advection +from scrins.discretization.create_matrix import create_matrix +from scrins.discretization.obst_zero_val import obst_zero_val +from scrins.operators.avg import avg +from scrins.operators.cat import cat +from scrins.operators.dif import dif + + +def calc_uvw(uvw, uvwf, rho, mu, p_tot, e_f, dt, dxyz, obst): + """ + Calculate uvw + TODO: Write useful docstring + + :param uvw: + :param uvwf: + :param rho: + :param mu: + :param p_tot: + :param e_f: + :param dt: + :param dxyz: + :param obst: + :return: + """ + + # pylint: disable=invalid-name, too-many-locals, too-many-statements + + # Unpack tuples + u, v, w = uvw + uf, vf, wf = uvwf + dx, dy, dz = dxyz + e_x, e_y, e_z = e_f + + # Fetch resolutions + ru = u.val.shape + rv = v.val.shape + rw = w.val.shape + + # Pre-compute geometrical quantities + dv = dx * dy * dz + + d = u.pos + + # Create linear systems + A_u, b_u = create_matrix(u, rho / dt, mu, dxyz, obst, 'd') + A_v, b_v = create_matrix(v, rho / dt, mu, dxyz, obst, 'd') + A_w, b_w = create_matrix(w, rho / dt, mu, dxyz, obst, 'd') + + # Advection terms for momentum + c_u = advection(rho, u, uvwf, dxyz, dt, 'superbee') + c_v = advection(rho, v, uvwf, dxyz, dt, 'superbee') + c_w = advection(rho, w, uvwf, dxyz, dt, 'superbee') + + # Innertial term for momentum (this works for collocated and staggered) + i_u = u.old * avg(u.pos, rho) * avg(u.pos, dv) / dt + i_v = v.old * avg(v.pos, rho) * avg(v.pos, dv) / dt + i_w = w.old * avg(w.pos, rho) * avg(w.pos, dv) / dt + + # Compute staggered pressure gradients + p_tot_x = dif(X, p_tot) / avg(X, dx) + p_tot_y = dif(Y, p_tot) / avg(Y, dy) + p_tot_z = dif(Z, p_tot) / avg(Z, dz) + + # Make pressure gradients cell-centered + if d == C: + p_tot_x = avg(X, + cat(X, (p_tot_x[:1, :, :], p_tot_x, p_tot_x[-1:, :, :]))) + p_tot_y = avg(Y, + cat(Y, (p_tot_y[:, :1, :], p_tot_y, p_tot_y[:, -1:, :]))) + p_tot_z = avg(Z, + cat(Z, (p_tot_z[:, :, :1], p_tot_z, p_tot_z[:, :, -1:]))) + + # Total pressure gradients (this works for collocated and staggered) + p_st_u = p_tot_x * avg(u.pos, dv) + p_st_v = p_tot_y * avg(v.pos, dv) + p_st_w = p_tot_z * avg(w.pos, dv) + + # Full force terms for momentum equations (collocated and staggered) + f_u = b_u - c_u + i_u - p_st_u + e_x * avg(u.pos, dv) + f_v = b_v - c_v + i_v - p_st_v + e_y * avg(v.pos, dv) + f_w = b_w - c_w + i_w - p_st_w + e_z * avg(w.pos, dv) + + # Take care of obsts in the domian + if obst.any() != 0: + f_u = obst_zero_val(u.pos, f_u, obst) + f_v = obst_zero_val(v.pos, f_v, obst) + f_w = obst_zero_val(w.pos, f_w, obst) + + # Solve for velocities + res0 = bicgstab(A_u, reshape(f_u, prod(ru)), tol=TOL) + res1 = bicgstab(A_v, reshape(f_v, prod(rv)), tol=TOL) + res2 = bicgstab(A_w, reshape(f_w, prod(rw)), tol=TOL) + u.val[:] = reshape(res0[0], ru) + v.val[:] = reshape(res1[0], rv) + w.val[:] = reshape(res2[0], rw) + + # Update velocities in boundary cells + adj_o_bnds((u, v, w), (dx, dy, dz), dt) + + # Update face velocities (also substract cell-centered pressure gradients + # and add staggered pressure gradients) + if d == C: + uf.val[:] = (avg(X, u.val + dt / rho * (p_tot_x)) + - dt / avg(X, rho) * (dif(X, p_tot) / avg(X, dx))) + vf.val[:] = (avg(Y, v.val + dt / rho * (p_tot_y)) + - dt / avg(Y, rho) * (dif(Y, p_tot) / avg(Y, dy))) + wf.val[:] = (avg(Z, w.val + dt / rho * (p_tot_z)) + - dt / avg(Z, rho) * (dif(Z, p_tot) / avg(Z, dz))) + + for j in (W, E): + uf.bnd[j].val[:] = u.bnd[j].val[:] + vf.bnd[j].val[:] = avg(Y, v.bnd[j].val[:]) + wf.bnd[j].val[:] = avg(Z, w.bnd[j].val[:]) + for j in (S, N): + uf.bnd[j].val[:] = avg(X, u.bnd[j].val[:]) + vf.bnd[j].val[:] = v.bnd[j].val[:] + wf.bnd[j].val[:] = avg(Z, w.bnd[j].val[:]) + for j in (B, T): + uf.bnd[j].val[:] = avg(X, u.bnd[j].val[:]) + vf.bnd[j].val[:] = avg(Y, v.bnd[j].val[:]) + wf.bnd[j].val[:] = w.bnd[j].val[:] + + else: + uf.val[:] = u.val[:] + vf.val[:] = v.val[:] + wf.val[:] = w.val[:] + for j in (W, E, S, N, B, T): + uf.bnd[j].val[:] = u.bnd[j].val[:] + vf.bnd[j].val[:] = v.bnd[j].val[:] + wf.bnd[j].val[:] = w.bnd[j].val[:] + + if obst.any() != 0: + uf.val[:] = obst_zero_val(X, uf.val, obst) + vf.val[:] = obst_zero_val(Y, vf.val, obst) + wf.val[:] = obst_zero_val(Z, wf.val, obst) + + return # end of function diff --git a/PYTHON/scrins/discretization/cartesian_grid.py b/PYTHON/scrins/discretization/cartesian_grid.py new file mode 100755 index 0000000..a2dbd47 --- /dev/null +++ b/PYTHON/scrins/discretization/cartesian_grid.py @@ -0,0 +1,35 @@ +""" +Docstring. +""" +from numpy import empty +from scrins.operators.dif import dif + +#========================================================================== +def cartesian_grid(xn, yn, zn): + """ + Spawns a 3D Cartesian grid from three arrays with node coordinates. + """ + # Compute cell resolutions + nx = len(xn)-1 + ny = len(yn)-1 + nz = len(zn)-1 + + # Create matrices for cell dimensions ... + dx = empty((nx, ny, nz)) + dy = empty((nx, ny, nz)) + dz = empty((nx, ny, nz)) + + # ... and fill them up! + dx[:] = dif(xn).reshape(nx, 1, 1) + dy[:] = dif(yn).reshape(1, ny, 1) + dz[:] = dif(zn).reshape(1, 1, nz) + + # Compute resolutions for cell-centered and all collocated variables + rc = nx, ny, nz + ru = nx-1, ny, nz + rv = nx, ny-1, nz + rw = nx, ny, nz-1 + + return nx, ny, nz, \ + dx, dy, dz, \ + rc, ru, rv, rw # end of function diff --git a/PYTHON/scrins/discretization/cfl_max.py b/PYTHON/scrins/discretization/cfl_max.py new file mode 100755 index 0000000..39d5828 --- /dev/null +++ b/PYTHON/scrins/discretization/cfl_max.py @@ -0,0 +1,35 @@ +""" +CFL. +""" +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.operators.avg import avg + + +#========================================================================== +def cfl_max(uvw, dt, dxyz): +#-------------------------------------------------------------------------- + """ + Docstring. + """ + + # Unpack received tuples + u, v, w = uvw + dx, dy, dz = dxyz + + # Take velocity's position + d = u.pos + + # Mesh is cell-centered + if d == C: + cfl = dt * max(abs(u.val/dx).max(), \ + abs(v.val/dy).max(), \ + abs(w.val/dz).max()) + + # Mesh is staggered + else: + cfl = dt * max(abs(u.val/avg(X, dx)).max(), \ + abs(v.val/avg(Y, dy)).max(), \ + abs(w.val/avg(Z, dz)).max()) + + return cfl diff --git a/PYTHON/scrins/discretization/corr_uvw.py b/PYTHON/scrins/discretization/corr_uvw.py new file mode 100755 index 0000000..e523d28 --- /dev/null +++ b/PYTHON/scrins/discretization/corr_uvw.py @@ -0,0 +1,43 @@ +""" +Corrected uvw. +""" + +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.discretization.obst_zero_val import obst_zero_val +from scrins.operators.avg import avg +from scrins.operators.cat import cat +from scrins.operators.dif import dif + +# ========================================================================== +def corr_uvw(uvw, p, rho, dt, dxyz, obst): +# -------------------------------------------------------------------------- + """ + Docstring. + """ + # Unpack received tuples + dx, dy, dz = dxyz + # Compute pressure correction gradients + p_x = dif(X, p.val) / avg(X, dx) + p_y = dif(Y, p.val) / avg(Y, dy) + p_z = dif(Z, p.val) / avg(Z, dz) + + # Set to zero in obst + if obst.any() != 0: + p_x = obst_zero_val(X, p_x, obst) + p_y = obst_zero_val(Y, p_y, obst) + p_z = obst_zero_val(Z, p_z, obst) + + # Pad with boundary values by expanding from interior + # (This is done only for collocated formulation) + if uvw[X].pos == C: + p_x = avg(X, cat(X, (p_x[:1, :, :], p_x, p_x[-1:, :, :]))) + p_y = avg(Y, cat(Y, (p_y[:, :1, :], p_y, p_y[:, -1:, :]))) + p_z = avg(Z, cat(Z, (p_z[:, :, :1], p_z, p_z[:, :, -1:]))) + + # Correct the velocities + uvw[X].val[:] = uvw[X].val[:] - dt / avg(uvw[X].pos, rho) * p_x + uvw[Y].val[:] = uvw[Y].val[:] - dt / avg(uvw[Y].pos, rho) * p_y + uvw[Z].val[:] = uvw[Z].val[:] - dt / avg(uvw[Z].pos, rho) * p_z + + return # end of function diff --git a/PYTHON/scrins/discretization/create_matrix.py b/PYTHON/scrins/discretization/create_matrix.py new file mode 100755 index 0000000..669017f --- /dev/null +++ b/PYTHON/scrins/discretization/create_matrix.py @@ -0,0 +1,163 @@ +""" +Docstring. +""" +from collections import namedtuple + +from numpy import array, reshape, zeros +from scipy.sparse import spdiags + +from scrins.constants.boundary_conditions import DIRICHLET, NEUMANN +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.discretization.obst_mod_matrix import obst_mod_matrix +from scrins.operators.cat import cat +from scrins.operators.avg import avg + + +# ========================================================================== +def create_matrix(phi, inn, mu, dxyz, obst, obc): + + """ + pos - position of variable (C - central, + X - staggered in x direction, + Y - staggered in y direction, + Z - staggered in z direction) + inn - innertial term + mu - viscous coefficient + dx, dy, dz - cell size in x, y and z directions + obc - obstacles's boundary condition, ('n' - Neumann, + 'd' - Dirichlet) + ------------------------------------------------------------------------- + """ + # Unpack tuples + dx, dy, dz = dxyz + + res = phi.val.shape + + # ------------------------------- + # Create right hand side vector + # ------------------------------- + b = zeros(res) + + # ------------------------------------ + # Create default matrix coefficients + # ------------------------------------ + coefficients = namedtuple('matrix_diagonal', 'W E S N B T P') + c = coefficients(zeros(res), zeros(res), zeros(res), \ + zeros(res), zeros(res), zeros(res), \ + zeros(res)) + + d = phi.pos + + # Handle central coefficient due to innertia + c.P[:] = avg(d, inn) * avg(d, dx*dy*dz) + + # Pre-compute geometrical quantities + sx = dy * dz + sy = dx * dz + sz = dx * dy + + if d != X: + c.W[:] = cat(X, ( \ + avg(d, mu[:1, :, :]) \ + * avg(d, sx[:1, :, :]) / avg(d, (dx[:1, :, :])/2.0), \ + avg(d, avg(X, mu)) * avg(d, avg(X, sx)) / avg(d, avg(X, dx)))) + + c.E[:] = cat(X, ( \ + avg(d, avg(X, mu)) * avg(d, avg(X, sx)) / avg(d, avg(X, dx)), \ + avg(d, mu[-1:, :, :]) \ + * avg(d, sx[-1:, :, :])/ avg(d, (dx[-1:, :, :])/2.0))) + + if d != Y: + c.S[:] = cat(Y, ( \ + avg(d, mu[:, :1, :]) \ + * avg(d, sy[:, :1, :]) / avg(d, (dy[:, :1, :])/2.0), \ + avg(d, avg(Y, mu)) * avg(d, avg(Y, sy)) / avg(d, avg(Y, dy)))) + + c.N[:] = cat(Y, ( \ + avg(d, avg(Y, mu)) * avg(d, avg(Y, sy)) / avg(d, avg(Y, dy)), \ + avg(d, mu[:, -1:, :]) \ + * avg(d, sy[:, -1:, :]) / avg(d, (dy[:, -1:, :])/2.0))) + + if d != Z: + c.B[:] = cat(Z, ( \ + avg(d, mu[:, :, :1]) \ + * avg(d, sz[:, :, :1]) / avg(d, (dz[:, :, :1])/2.0), \ + avg(d, avg(Z, mu)) * avg(d, avg(Z, sz)) / avg(d, avg(Z, dz)))) + + c.T[:] = cat(Z, ( \ + avg(d, avg(Z, mu)) * avg(d, avg(Z, sz)) / avg(d, avg(Z, dz)), \ + avg(d, mu[:, :, -1:]) \ + * avg(d, sz[:, :, -1:]) / avg(d, (dz[:, :, -1:])/2.0))) + + # --------------------------------- + # Correct for staggered variables + # --------------------------------- + if d == X: + c.W[:] = mu[0:-1, :, :] * sx[0:-1, :, :] / dx[0:-1, :, :] + c.E[:] = mu[1:, :, :] * sx[1:, :, :] / dx[1:, :, :] + elif d == Y: + c.S[:] = mu[:, 0:-1, :] * sy[:, 0:-1, :] / dy[:, 0:-1, :] + c.N[:] = mu[:, 1:, :] * sy[:, 1:, :] / dy[:, 1:, :] + elif d == Z: + c.B[:] = mu[:, :, 0:-1] * sz[:, :, 0:-1] / dz[:, :, 0:-1] + c.T[:] = mu[:, :, 1: ] * sz[:, :, 1: ] / dz[:, :, 1: ] + + # ----------------------------------------------------------------------- + # Zero them (correct them) for vanishing derivative boundary condition. + # ----------------------------------------------------------------------- + + # The values defined here will be false (numerical value 0) + # wherever there is or Neumann boundary condition. + c.W[:1, :, :] *= (phi.bnd[W].typ[:] == DIRICHLET) + c.E[-1:, :, :] *= (phi.bnd[E].typ[:] == DIRICHLET) + c.S[:, :1, :] *= (phi.bnd[S].typ[:] == DIRICHLET) + c.N[:, -1:, :] *= (phi.bnd[N].typ[:] == DIRICHLET) + c.B[:, :, :1] *= (phi.bnd[B].typ[:] == DIRICHLET) + c.T[:, :, -1:] *= (phi.bnd[T].typ[:] == DIRICHLET) + + # -------------------------------------------- + # Fill the source terms with boundary values + # -------------------------------------------- + b[:1, :, :] += c.W[ :1, :, :] * phi.bnd[W].val[:1, :, :] + b[-1:, :, :] += c.E[-1:, :, :] * phi.bnd[E].val[:1, :, :] + b[:, :1, :] += c.S[ :, :1, :] * phi.bnd[S].val[:, :1, :] + b[:, -1:, :] += c.N[ :, -1:, :] * phi.bnd[N].val[:, :1, :] + b[:, :, :1] += c.B[ :, :, :1] * phi.bnd[B].val[:, :, :1] + b[:, :, -1:] += c.T[ :, :, -1:] * phi.bnd[T].val[:, :, :1] + + # --------------------------------------- + # Correct system matrices for obstacles + # --------------------------------------- + if obst.any() != 0: + c = obst_mod_matrix(phi, c, obst, obc) + + # ----------------------------------------------- + # Add all neighbours to the central matrix, + # and zero the coefficients towards boundaries + # ----------------------------------------------- + c.P[:] += c.W[:] + c.E[:] + c.S[:] + c.N[:] + c.B[:] + c.T[:] + + c.W[:1, :, :] = 0.0 + c.E[-1:, :, :] = 0.0 + c.S[:, :1, :] = 0.0 + c.N[:, -1:, :] = 0.0 + c.B[:, :, :1] = 0.0 + c.T[:, :, -1:] = 0.0 + + # ---------------------- + # Create sparse matrix + # ---------------------- + nx, ny, nz = res + n = nx * ny * nz + + data = array([reshape(c.P, n), \ + reshape(-c.W, n), reshape(-c.E, n), \ + reshape(-c.S, n), reshape(-c.N, n), \ + reshape(-c.B, n), reshape(-c.T, n)]) + + diag = array([0, +ny*nz, -ny*nz, +nz, -nz, +1, -1]) + + A = spdiags(data, diag, n, n) + + return A, b # end of function diff --git a/PYTHON/scrins/discretization/create_unknown.py b/PYTHON/scrins/discretization/create_unknown.py new file mode 100755 index 0000000..c69aaa9 --- /dev/null +++ b/PYTHON/scrins/discretization/create_unknown.py @@ -0,0 +1,72 @@ +""" +Docstring. +""" +from collections import namedtuple + +from numpy import ndarray, zeros + +from scrins.constants.boundary_conditions import DIRICHLET, NEUMANN, OUTLET +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C + +#========================================================================== +def create_unknown(name, pos, res, def_bc): + """ + -------------------------------------------------------------------------- + This function creates a new unkown; helping to shorten the main program. + -------------------------------------------------------------------------- + Input parameters are: + name - string holding the name of the variable + it should be used for post-processing + pos - character specifying if the variable is cell centered (C), + staggered in x direction (X) or in y direction (Y) + res - vector specifying resolutions in x and y direction + def_bc - integer specifying if the default boundary condition is of + dirichlet, neumann or outlet type + """ + # Fetch resolutions + nx, ny, nz = res + + # Create boundary tuple + key = namedtuple('key', 'typ val') + bnd = (key(ndarray(shape=(1, ny, nz), dtype=int), zeros((1, ny, nz))), \ + key(ndarray(shape=(1, ny, nz), dtype=int), zeros((1, ny, nz))), \ + key(ndarray(shape=(nx, 1, nz), dtype=int), zeros((nx, 1, nz))), \ + key(ndarray(shape=(nx, 1, nz), dtype=int), zeros((nx, 1, nz))), \ + key(ndarray(shape=(nx, ny, 1), dtype=int), zeros((nx, ny, 1))), \ + key(ndarray(shape=(nx, ny, 1), dtype=int), zeros((nx, ny, 1)))) + + # Create the unknown tuple + unk = namedtuple('unk', 'name pos val old bnd') + phi = unk(name, pos, zeros(res), zeros(res), bnd) + + # ------------------ + # Set the position + # ------------------ + if pos != C and pos != X and pos != Y and pos != Z: + print('Variable must be defined at positions C, X, Y or Z') + + # --------------------------------------------------- + # Set default boundary conditions, types and values + # --------------------------------------------------- + if def_bc != DIRICHLET and def_bc != NEUMANN and def_bc != OUTLET: + print('Variable must be defined with boundary conditions ', \ + 'DIRICHLET, NEUMANN or OUTLET!') + + phi.bnd[W].typ[0, :, :] = def_bc + phi.bnd[E].typ[0, :, :] = def_bc + phi.bnd[S].typ[:, 0, :] = def_bc + phi.bnd[N].typ[:, 0, :] = def_bc + phi.bnd[B].typ[:, :, 0] = def_bc + phi.bnd[T].typ[:, :, 0] = def_bc + + phi.bnd[W].val[0, :, :] = 0 + phi.bnd[E].val[0, :, :] = 0 + phi.bnd[S].val[:, 0, :] = 0 + phi.bnd[N].val[:, 0, :] = 0 + phi.bnd[B].val[:, :, 0] = 0 + phi.bnd[T].val[:, :, 0] = 0 + + print("Created variable ", name) + + return phi # end of function diff --git a/PYTHON/scrins/discretization/nodes.py b/PYTHON/scrins/discretization/nodes.py new file mode 100755 index 0000000..5cf7c40 --- /dev/null +++ b/PYTHON/scrins/discretization/nodes.py @@ -0,0 +1,93 @@ +""" +Docstring. +""" +from scipy import matrix, array, zeros, linspace +from scipy.linalg import solve + +# ScriNS modules +import scrins.constants +import scrins.operators + +#========================================================================== +def nodes(*args): + """ + Creates node coordinates in one dimension + + Input arguments: + s - starting coordinate + e - end coordinate + n - number of cells (number of nodes is greater than one than this) + del_s - (optional) starting cell size + del_e - (optional) ending cell size + """ + + # --------------------------------------------- + # Just a simple constant-spacing distribution + # --------------------------------------------- + if len((args)) == 3: + s = args[0] + e = args[1] + n = args[2] + return linspace(s, e, n+1) + + # ------------------------------------------------------------------------ + # Grid distribution is determined from the following function: + # x = a + b y + c y^2 + d y^3 + # + # One should imagine this function as taking integer arguments. + # + # Boundary conditions: + # + # x(0) = s => a = s + # x(1) = s + del_s => a + b + c + d = s + del_s + # x(n-1) = e - del_e => a + b*(n-1) + c*(n-1)^2 + d*(n-1)^3 = e - del_e + # x(n) = e => a + b*n + c*n^2 + d*n^3 = e + # + # It follows that: + # + # |1 0 0 0 | |a| |s | + # |1 1 1 1 | |b| |s+del_s| + # |1 n-1 (n-1)^2 (n-1)^3| |c| |e-del_e| + # |1 n n^2 n^3 | |d| |e | + #------------------------------------------------------------------------ + elif len((args)) == 5: + s = args[0] + e = args[1] + n = args[2] + del_s = args[3] + del_e = args[4] + + # Form the system matrix + A = matrix([[1, 0, 0, 0 ], \ + [1, 1, 1, 1 ], \ + [1, n-1, pow(n-1,2), pow(n-1,3)], \ + [1, n, pow(n, 2), pow(n, 3)]]) + + # Form the right hand side + f = array([ s, \ + s + del_s, \ + e - del_e, \ + e]) + + # Solve for coefficients + abcd = solve(A, f) + + # Pre-allocate the array for coordinates ... + x = zeros(n+1) + + # ... and fill it up. + for i in range(0, n+1): + x[i] = abcd[0] \ + + abcd[1] * i \ + + abcd[2] * i*i \ + + abcd[3] * i*i*i + + return x + + #-------------------------- + # Some error message might + # be printed if number of + # arguments is wrong + #-------------------------- + + return # end of function diff --git a/PYTHON/scrins/discretization/obst_mod_matrix.py b/PYTHON/scrins/discretization/obst_mod_matrix.py new file mode 100755 index 0000000..a259cc2 --- /dev/null +++ b/PYTHON/scrins/discretization/obst_mod_matrix.py @@ -0,0 +1,176 @@ + +""" +Docstring. +""" + +from scipy import logical_not as lnot +from scipy import maximum as mx + +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.operators.dif import dif + +#========================================================================== +def obst_mod_matrix(phi, c, obst, obc): + """ + Adjusts the system matrix for obstacles and cell centered varaibles + (such as pressure) + + phi - variable + c - coefficients in system matrix + obst - obstacle array + obc - obstacles's boundary condition, ('n' - Neumann, 'd' - Dirichlet) + """ + pos = phi.pos + #-------------------------- + # + # For collocated variables + # + #-------------------------- + if pos == C: + #------------------------------------ + # Neumann's boundary on the obstacle + #------------------------------------ + if obc == 'n': + + # Correct west and east + sol_x = dif(X, obst) # will be +1 east of obst, -1 west of obst + corr = 1 - (sol_x < 0) + c.W[1:, :, :] = c.W[1:, :, :] * corr + corr = 1 - (sol_x > 0) + c.E[:-1, :, :] = c.E[:-1, :, :] * corr + + # Correct south and north + sol_y = dif(Y, obst) # will be +1 north of obst, -1 south of obst + corr = 1 - (sol_y < 0) + c.S[:, 1:, :] = c.S[:, 1:, :] * corr + corr = 1 - (sol_y > 0) + c.N[:, :-1, :] = c.N[:, :-1, :] * corr + + # Correct bottom and top + sol_z = dif(Z, obst) # will be +1 north of obst, -1 south of obst + corr = 1 - (sol_z < 0) + c.B[:, :, 1:] = c.B[:, :, 1:] * corr + corr = 1 - (sol_z > 0) + c.T[:, :, :-1] = c.T[:, :, :-1] * corr + + #-------------------------------------- + # Dirichlet's boundary on the obstacle + #-------------------------------------- + elif obc == 'd': + # Set central coefficient to 1 in obst, unchanged elsewhere + c.P[:] = c.P[:] * lnot(obst) + obst + + # Set neighbour coefficients to zero in obst + c.W[:] = c.W[:] * lnot(obst) + c.E[:] = c.E[:] * lnot(obst) + c.S[:] = c.S[:] * lnot(obst) + c.N[:] = c.N[:] * lnot(obst) + c.B[:] = c.B[:] * lnot(obst) + c.T[:] = c.T[:] * lnot(obst) + + # Increase coefficients close to obst (makes sense for momentum) + sol_x = dif(X, obst) # will be +1 east of obst, -1 west of obst + corr = 1 + (sol_x > 0) + c.E[:-1, :, :] = c.E[:-1, :, :] * corr + corr = 1 + (sol_x < 0) + c.W[1:, :, :] = c.W[1:, :, :] * corr + + sol_y = dif(Y, obst) # will be +1 north of obst, -1 south of obst + corr = 1 + (sol_y > 0) + c.N[:, :-1, :] = c.N[:, :-1, :] * corr + corr = 1 + (sol_y < 0) + c.S[:, 1:, :] = c.S[:, 1:, :] * corr + + sol_z = dif(Z, obst) # will be +1 top of obst, -1 bottom of obst + corr = 1 + (sol_z > 0) + c.T[:, :, :-1] = c.T[:, :, :-1] * corr + corr = 1 + (sol_z < 0) + c.B[:, :, 1:] = c.B[:, :, 1:] * corr + + #------------------------- + # + # For staggered variables + # + #------------------------- + elif pos == X: + # Set central coefficient to 1 in obst, unchanged elsewhere + obst_x = mx(obst[:-1, :, :], obst[1:, :, :]) + c.P[:] = c.P[:] * lnot(obst_x) + obst_x + + # Set neighbour coefficients to zero in obst + c.W[:] = c.W[:] * lnot(obst_x) + c.E[:] = c.E[:] * lnot(obst_x) + c.S[:] = c.S[:] * lnot(obst_x) + c.N[:] = c.N[:] * lnot(obst_x) + c.B[:] = c.B[:] * lnot(obst_x) + c.T[:] = c.T[:] * lnot(obst_x) + + # Increase coefficients close to obst (makes sense for momentum) + sol_y = dif(Y, obst_x) # will be +1 north of obst,-1 south of obst + corr = 1 + (sol_y > 0) + c.N[:, :-1, :] = c.N[:, :-1, :] * corr + corr = 1 + (sol_y < 0) + c.S[:, 1:, :] = c.S[:, 1:, :] * corr + + sol_z = dif(Z, obst_x) # will be +1 top of obst, -1 bottom of obst + corr = 1 + (sol_z > 0) + c.T[:, :, :-1] = c.T[:, :, :-1] * corr + corr = 1 + (sol_z < 0) + c.B[:, :, 1:] = c.B[:, :, 1:] * corr + + elif pos == Y: + + # Set central coefficient to 1 in obst, unchanged elsewhere + obst_y = mx(obst[:, :-1, :], obst[:, 1:, :]) + c.P[:] = c.P[:] * lnot(obst_y) + obst_y + + # Set neighbour coefficients to zero in obst + c.W[:] = c.W[:] * lnot(obst_y) + c.E[:] = c.E[:] * lnot(obst_y) + c.S[:] = c.S[:] * lnot(obst_y) + c.N[:] = c.N[:] * lnot(obst_y) + c.B[:] = c.B[:] * lnot(obst_y) + c.T[:] = c.T[:] * lnot(obst_y) + + # Increase coefficients close to obst (makes sense for momentum) + sol_x = dif(X, obst_y) # will be +1 north of obst,-1 south of obst + corr = 1 + (sol_x > 0) + c.E[:-1, :, :] = c.E[:-1, :, :] * corr + corr = 1 + (sol_x < 0) + c.W[1:, :, :] = c.W[1:, :, :] * corr + + sol_z = dif(Z, obst_y) # will be +1 north of obst,-1 south of obst + corr = 1 + (sol_z > 0) + c.T[:, :, :-1] = c.T[:, :, :-1] * corr + corr = 1 + (sol_z < 0) + c.B[:, :, 1:] = c.B[:, :, 1:] * corr + + elif pos == Z: + + # Set central coefficient to 1 in obst, unchanged elsewhere + obst_z = mx(obst[:, :, :-1], obst[:, :, 1:]) + c.P[:] = c.P[:] * lnot(obst_z) + obst_z + + # Set neighbour coefficients to zero in obst + c.W[:] = c.W[:] * lnot(obst_z) + c.E[:] = c.E[:] * lnot(obst_z) + c.S[:] = c.S[:] * lnot(obst_z) + c.N[:] = c.N[:] * lnot(obst_z) + c.B[:] = c.B[:] * lnot(obst_z) + c.T[:] = c.T[:] * lnot(obst_z) + + # Increase coefficients close to obst (makes sense for momentum) + sol_x = dif(X, obst_z) # will be +1 north of obst,-1 south of obst + corr = 1 + (sol_x > 0) + c.E[:-1, :, :] = c.E[:-1, :, :] * corr + corr = 1 + (sol_x < 0) + c.W[1:, :, :] = c.W[1:, :, :] * corr + + sol_y = dif(Y, obst_z) # will be +1 north of obst,-1 south of obst + corr = 1 + (sol_y > 0) + c.N[:, :-1, :] = c.N[:, :-1, :] * corr + corr = 1 + (sol_y < 0) + c.S[:, 1:, :] = c.S[:, 1:, :] * corr + + return c # end of function diff --git a/PYTHON/scrins/discretization/obst_zero_val.py b/PYTHON/scrins/discretization/obst_zero_val.py new file mode 100755 index 0000000..d3feef7 --- /dev/null +++ b/PYTHON/scrins/discretization/obst_zero_val.py @@ -0,0 +1,36 @@ +""" +Docstring. +""" +from scipy import logical_not as lnot +from scipy import maximum as mx + +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import C + +# ========================================================================== +def obst_zero_val(d, val, obst): + + """ + Set value to zero inside obstacle. + + d - position of the variable, C, X, Y or Z + val - value to be zeroed in obstacle + obst - matrix holding positions of obstacle + """ + + if d == C: + val = val * lnot(obst) + + elif d == X: + obst_x = mx(obst[:-1, :, :], obst[1:, :, :]) + val = val * lnot(obst_x) + + elif d == Y: + obst_y = mx(obst[:, :-1, :], obst[:, 1:, :]) + val = val * lnot(obst_y) + + elif d == Z: + obst_z = mx(obst[:, :, :-1], obst[:, :, 1:]) + val = val * lnot(obst_z) + + return val # end of function diff --git a/PYTHON/scrins/discretization/vol_balance.py b/PYTHON/scrins/discretization/vol_balance.py new file mode 100755 index 0000000..46d695b --- /dev/null +++ b/PYTHON/scrins/discretization/vol_balance.py @@ -0,0 +1,35 @@ +""" +Comment. +""" + +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.discretization.obst_zero_val import obst_zero_val +from scrins.operators.cat import cat +from scrins.operators.dif import dif + +# ========================================================================== +def vol_balance(uvwf, dxyz, obst): + """ + Computes the volume balance, which is essentially a right hand side in + the Poisson's equation for pressure. + + Note that "obst" is an optional parameter. If it is not sent, the source + won't be zeroed inside the obstacle. That is important for calculation + of pressure, see function "calc_p". + + """ + # Unpack tuples + dx, dy, dz = dxyz + uf, vf, wf = uvwf + + # Compute it throughout the domain + src = - dif(X, cat(X, (uf.bnd[W].val, uf.val, uf.bnd[E].val)))*dy*dz \ + - dif(Y, cat(Y, (vf.bnd[S].val, vf.val, vf.bnd[N].val)))*dx*dz \ + - dif(Z, cat(Z, (wf.bnd[B].val, wf.val, wf.bnd[T].val)))*dx*dy + + # Zero it inside obstacles, if obstacle is sent as parameter + if obst.any() != 0: + src = obst_zero_val(C, src, obst) + + return src # end of function diff --git a/PYTHON/scrins/display/__init__.py b/PYTHON/scrins/display/__init__.py new file mode 100755 index 0000000..2500785 --- /dev/null +++ b/PYTHON/scrins/display/__init__.py @@ -0,0 +1,2 @@ +_all_ = ["plot_isoline", "plot_tecplot", "print_array", + "print_matrix", "print_time_step"] \ No newline at end of file diff --git a/PYTHON/scrins/display/plot_isolines.py b/PYTHON/scrins/display/plot_isolines.py new file mode 100755 index 0000000..d264e13 --- /dev/null +++ b/PYTHON/scrins/display/plot_isolines.py @@ -0,0 +1,73 @@ +""" +Plotting of Isolines. +""" +from math import floor + +from matplotlib import cm +from matplotlib import pyplot as plt +from numpy import linspace, meshgrid, transpose + +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.operators.avg import avg +from scrins.operators.cat import cat + +#-------------------------------------------------------------------------- +def plot_isolines(phi, uvw, xyzn, d): + """ + Docstring. + """ + + # Unpack tuples + u, v, w = uvw + xn, yn, zn = xyzn + + # Cell coordinates + xc = avg(xn) + yc = avg(yn) + zc = avg(zn) + + # Collocated velocity components + if u.pos == C: + uc = u.val + vc = v.val + wc = w.val + else: + uc = avg(X, cat(X, (u.bnd[W].val[:1, :, :], \ + u.val, \ + u.bnd[E].val[:1, :, :]))) + + vc = avg(Y, cat(Y, (v.bnd[S].val[:, :1, :], \ + v.val, \ + v.bnd[N].val[:, :1, :]))) + + wc = avg(Z, cat(Z, (w.bnd[B].val[:, :, :1], \ + w.val, \ + w.bnd[T].val[:, :, :1]))) + + # Pick coordinates for plotting (xp, yp) and values for plotting + if d == Y: + jp = floor(yc.size/2) + xp, yp = meshgrid(xc, zc) + zp = transpose(phi[:, jp, :], (1, 0)) + up = transpose(uc [:, jp, :], (1, 0)) + vp = transpose(wc [:, jp, :], (1, 0)) + if d == Z: + kp = floor(zc.size/2) + xp, yp = meshgrid(xc, yc) + zp = transpose(phi[:, :, kp], (1, 0)) + up = transpose(uc [:, :, kp], (1, 0)) + vp = transpose(vc [:, :, kp], (1, 0)) + + # Set levels and normalize the colors + levels = linspace(zp.min(), zp.max(), 11) + norm = cm.colors.Normalize(vmax=zp.max(), vmin=zp.min()) + + plt.figure() + plt.gca(aspect='equal') + plt.contour(xp, yp, zp, levels, cmap=plt.cm.rainbow, norm=norm) + plt.quiver(xp, yp, up, vp) + plt.axis([min(xn), max(xn), min(yn), max(yn)]) + plt.show() + + return # end of function diff --git a/PYTHON/scrins/display/plot_tecplot.py b/PYTHON/scrins/display/plot_tecplot.py new file mode 100644 index 0000000..b7e52da --- /dev/null +++ b/PYTHON/scrins/display/plot_tecplot.py @@ -0,0 +1,105 @@ +""" +Docstring. +Standard Python modules +""" + +# ScriNS modules +import scrins.constants +import scrins.operators + +#============================================================================== +def plot_tecplot(file_name, xyzn, variables): + """ + Exports results to Tecplot (TM) format. + """ + # Unpack tuples + xn, yn, zn = xyzn + + # Compute cell resolutions (remember: cell resolutions) + nx = len(xn)-1 + ny = len(yn)-1 + nz = len(zn)-1 + + file_id = open(file_name, 'w') + + #--------------------------- + # Write the file header out + #--------------------------- + file_id.write("# File header \n") + file_id.write("title=\"ScriNS Output\"\n") + file_id.write("variables=\"x\" \"y\" \"z\" ") + for v in variables: + file_id.write("\"%s\" " % v.name) + file_id.write("\n") + file_id.write("zone i=%d" % (nx+1) + " j=%d" % (ny+1) + " k=%d\n" % (nz+1)) + file_id.write("datapacking = block\n") + file_id.write("varlocation=([1-3]=nodal ") + file_id.write("[4-%d]=cellcentered)" % (3+len(variables))) + + #-------------------------------------------------------------------- + # Write the coordinates out (remember - those are nodal coordinates) + #-------------------------------------------------------------------- + file_id.write("\n# X coordinates\n") + c = 0 # column counter + for k in range(0, nz+1): + for j in range(0, ny+1): + for i in range(0, nx+1): + file_id.write("%12.5e " % xn[i]) + c = c + 1 + if c % 4 == 0: # go to new line after 4th column + file_id.write("\n") + + file_id.write("\n# Y coordinates\n") + c = 0 # column counter + for k in range(0, nz+1): + for j in range(0, ny+1): + for i in range(0, nx+1): + file_id.write("%12.5e " % yn[j]) + c = c + 1 + if c % 4 == 0: # go to new line after 4th column + file_id.write("\n") + + file_id.write("\n# Z coordinates\n") + c = 0 # column counter + for k in range(0, nz+1): + for j in range(0, ny+1): + for i in range(0, nx+1): + file_id.write("%12.5e " % zn[k]) + c = c + 1 + if c % 4 == 0: # go to new line after 4th column + file_id.write("\n") + + #------------------------- + # Write the variables out + #------------------------- + + # Average values to be written for staggered variables + for v in variables: + if v.pos == C: + val = v.val + elif v.pos == X: + val = avg(X, cat(X, (v.bnd[W].val[:1, :, :], \ + v.val, \ + v.bnd[E].val[:1, :, :]))) + elif v.pos == Y: + val = avg(Y, cat(Y, (v.bnd[S].val[:, :1, :], \ + v.val, \ + v.bnd[N].val[:, :1, :]))) + elif v.pos == Z: + val = avg(Z, cat(Z, (v.bnd[B].val[:, :, :1], \ + v.val, \ + v.bnd[T].val[:, :, :1]))) + + file_id.write("\n# %s \n" % v.name) + c = 0 + for k in range(0, nz): + for j in range(0, ny): + for i in range(0, nx): + file_id.write("%12.5e " % val[i, j, k]) + c = c + 1 + if c % 4 == 0: + file_id.write("\n") + + file_id.close() + + return # end of function diff --git a/PYTHON/scrins/display/print_array.py b/PYTHON/scrins/display/print_array.py new file mode 100755 index 0000000..92c51f2 --- /dev/null +++ b/PYTHON/scrins/display/print_array.py @@ -0,0 +1,22 @@ +""" +Script used to Visualise an Array. +""" +#========================================================================== +def print_array(*args): + """ + Docstring. + """ + + if len((args)) == 1: + a = args[0] + format = "%7.2f" + else: + a = args[0] + format = args[1] + + print('Array ['+('%d' %a.shape[0])+']') + rows = a.shape[0] + for i in range(0, rows): + print(format %a[i]) + + return # end of function diff --git a/PYTHON/scrins/display/print_matrix.py b/PYTHON/scrins/display/print_matrix.py new file mode 100755 index 0000000..34fb79b --- /dev/null +++ b/PYTHON/scrins/display/print_matrix.py @@ -0,0 +1,26 @@ +""" +Script used to visulaise a Matrix. +""" +#========================================================================== +def print_matrix(*args): + """ + Docstring. + """ + if len((args)) == 1: + a = args[0] + format = "%7.2f" + else: + a = args[0] + format = args[1] + + print('Matrix[' + ('%d' % a.shape[0]) + '][' + ('%d' % a.shape[1]) + ']') + rows = a.shape[0] + cols = a.shape[1] + + for i in range(0, rows): + for j in range(0, cols): + print((format % a[i, j]), end='') + print('') + print('') + + return # end of function diff --git a/PYTHON/scrins/display/print_time_step.py b/PYTHON/scrins/display/print_time_step.py new file mode 100755 index 0000000..da3adf8 --- /dev/null +++ b/PYTHON/scrins/display/print_time_step.py @@ -0,0 +1,15 @@ +""" +Script used to print Timestep. +""" +#========================================================================== +def print_time_step(ts): + """ + Docstring. + """ + print('+======================+') + print('| |') + print('| Time step = ' +'%6d' %ts + ' |') + print('| |') + print('+======================+') + + return # end of function diff --git a/PYTHON/scrins/operators/__init__.py b/PYTHON/scrins/operators/__init__.py new file mode 100755 index 0000000..99ef303 --- /dev/null +++ b/PYTHON/scrins/operators/__init__.py @@ -0,0 +1,2 @@ +_all_ = ["avg", "cat", "dif", + "par"] \ No newline at end of file diff --git a/PYTHON/scrins/operators/avg.py b/PYTHON/scrins/operators/avg.py new file mode 100755 index 0000000..10dd0a3 --- /dev/null +++ b/PYTHON/scrins/operators/avg.py @@ -0,0 +1,34 @@ +""" +Docstring. +""" +from scrins.constants.coordinates import X, Y, Z +#========================================================================== +def avg(*args): + """ + Docstring. + """ + + # Only one argument is sent - perform + # averaging of one-dimensional array + if len((args)) == 1: + a = args[0] + return (a[1:] + a[:-1]) * 0.5 + + # Two arguments are sent - perform averaging of a + # three-dimensional array, with a given direction + elif len((args)) == 2: + d = args[0] # direction + a = args[1] # array + + if d == X: + return (a[1:, :, : ] + a[:-1, :, :]) * 0.5 + elif d == Y: + return (a[:, 1:, : ] + a[:, :-1, :]) * 0.5 + elif d == Z: + return (a[:, :, 1:] + a[:, :, :-1]) * 0.5 + + # Some error message might + # be printed if number of + # arguments is wrong + + return a # end of function diff --git a/PYTHON/scrins/operators/cat.py b/PYTHON/scrins/operators/cat.py new file mode 100755 index 0000000..f2be599 --- /dev/null +++ b/PYTHON/scrins/operators/cat.py @@ -0,0 +1,12 @@ +""" +Docstring. +""" +from numpy import concatenate + +#========================================================================== +def cat(d, tup): + """ + An interface to the standard NumPy's function concatenate. + """ + + return concatenate(tup, d) # end of function diff --git a/PYTHON/scrins/operators/dif.py b/PYTHON/scrins/operators/dif.py new file mode 100755 index 0000000..11c9a66 --- /dev/null +++ b/PYTHON/scrins/operators/dif.py @@ -0,0 +1,35 @@ +""" +Docstring. +""" +from scrins.constants.coordinates import X, Y, Z + +# ========================================================================== +def dif(*args): + """ + Docstring. + """ + + # Only one argument is sent - perform + # averaging of one-dimensional array + if len((args)) == 1: + a = args[0] + return (a[1:] - a[:-1]) + + # Two arguments are sent - perform averaging of a + # three-dimensional array, with a given direction + elif len((args)) == 2: + d = args[0] # direction + a = args[1] # array + + if d == X: + return (a[1:, :, :] - a[:-1, :, :]) + elif d == Y: + return (a[:, 1:, :] - a[:, :-1, :]) + elif d == Z: + return (a[:, :, 1:] - a[:, :, :-1]) + + # Some error message might + # be printed if number of + # arguments is wrong + + return # end of function diff --git a/PYTHON/scrins/operators/par.py b/PYTHON/scrins/operators/par.py new file mode 100755 index 0000000..cbcae6d --- /dev/null +++ b/PYTHON/scrins/operators/par.py @@ -0,0 +1,39 @@ +""" +Docstring. +""" +from copy import copy +from scrins.operators.avg import avg + +# ========================================================================== +def par(mean_val, x_nodes): + """ + A function to generate a parabolic profile over a set of cell centers, + useful for specifying parabolic inlet velocity profiles. It expects + nodal coordinates as input, but sends values at cell centers back. + + Input coordinates: |-----|-----|-----|-----|-----|-----|-----| + Output values: o-----o-----o-----o-----o-----o-----o + + Input parameters + + mean_val - mean value the parabola will have + x_nodes - nodal coordinatels + ------------------------------------------------------------------------- + """ + + # It is known that maximum of a parabola is 3/2 of its mean value + max_val = mean_val * 3/2 + + # Normalized x coordinates (from -1 to +1) + xn = copy(x_nodes) + + xn -= xn.min() + xn /= (xn.max()-xn.min()) + xn *= 2 + xn -= 1 + + xc = avg(xn) + + yc = (1.0-xc*xc) * max_val + + return yc # end of function diff --git a/PYTHON/scrins/physical_models/__init__.py b/PYTHON/scrins/physical_models/__init__.py new file mode 100755 index 0000000..e105735 --- /dev/null +++ b/PYTHON/scrins/physical_models/__init__.py @@ -0,0 +1 @@ +_all_ = ["properties_for_air", "properties_for_water"] \ No newline at end of file diff --git a/PYTHON/scrins/physical_models/properties_for_air.py b/PYTHON/scrins/physical_models/properties_for_air.py new file mode 100755 index 0000000..66791fe --- /dev/null +++ b/PYTHON/scrins/physical_models/properties_for_air.py @@ -0,0 +1,23 @@ +""" +Standard Python modules. +""" +from numpy import ones + +#========================================================================== +def properties_for_air(rc): + """ + + Returns physical properties of air for given resolution 'rc' + + For 60 deg from: + http://www.engineeringtoolbox.com/air-properties-d_156.html + ------------------------------------------------------------------------- + """ + + # Create and fill matrice for all properties + rho = ones(rc) * 1.067 # density [kg/m^3] + mu = ones(rc) * 20.17E-06 # viscosity [Pa s] + cp = ones(rc) * 1009 # thermal capacity [J/kg/K] + kappa = ones(rc) * 0.0285 # thermal conductivity [W/m/K] + + return rho, mu, cp, kappa # end of function diff --git a/PYTHON/scrins/physical_models/properties_for_water.py b/PYTHON/scrins/physical_models/properties_for_water.py new file mode 100755 index 0000000..6522444 --- /dev/null +++ b/PYTHON/scrins/physical_models/properties_for_water.py @@ -0,0 +1,21 @@ +""" +Docstring. +""" +from numpy import ones + +#========================================================================== +def properties_for_water(rc): + """ + Returns physical properties for water for given resolution 'rc' + + For 60 deg from: + http://www.engineeringtoolbox.com/water-properties-d_1508.html + ------------------------------------------------------------------------- + """ + # Create and fill matrices for all properties + rho = ones(rc) * 983.0 # density [kg/m^3] + mu = ones(rc) * 0.466E-3 # viscosity [Pa s] + cp = ones(rc) * 4185 # thermal capacity [J/kg/K] + kappa = ones(rc) * 0.654 # thermal conductivity [W/m/K] + + return rho, mu, cp, kappa # end of function diff --git a/PYTHON/scrins/tests/.DS_Store b/PYTHON/scrins/tests/.DS_Store new file mode 100644 index 0000000..7e36780 Binary files /dev/null and b/PYTHON/scrins/tests/.DS_Store differ diff --git a/PYTHON/scrins/tests/__init__.py b/PYTHON/scrins/tests/__init__.py new file mode 100755 index 0000000..2247c38 --- /dev/null +++ b/PYTHON/scrins/tests/__init__.py @@ -0,0 +1,12 @@ +from . import (test_advection_1D, + test_inlet_outlet, + test_membrane_staggered, + test_obstacles_collocated, + test_obstacles_staggered, + test_obstacles_thinner_staggered, + test_p_tot_staggered, + test_stratification_staggered, + test_thermal_plumes_collocated, + test_thermal_plumes_staggered, + test_thermally_driven_cavity_collocated, + test_thermally_driven_cavity_staggered) \ No newline at end of file diff --git a/PYTHON/scrins/tests/test_all.py b/PYTHON/scrins/tests/test_all.py new file mode 100755 index 0000000..09ce308 --- /dev/null +++ b/PYTHON/scrins/tests/test_all.py @@ -0,0 +1,32 @@ +""" +Run all test +""" + +import timeit +import types + +from scrins import tests + +def main(): + """ + Docstring. + """ + + test_mods = [(name, obj) for name, obj in vars(tests).items() + if name.startswith('test_') and name != 'test_all' and + isinstance(obj, types.ModuleType)] + total_time = 0 + for name, test in test_mods: + + print('#' * 40) + print(name) + print('#' * 40) + start = timeit.default_timer() + test.main(show_plot=False) + duration = timeit.default_timer() - start + total_time += duration + print('run time {}: {:7.3f} s'.format(name, duration)) + print('total time: {:7.3f} s'.format(total_time)) + +if __name__ == '__main__': + main() diff --git a/PYTHON/scrins/tests/test_inlet_outlet.py b/PYTHON/scrins/tests/test_inlet_outlet.py new file mode 100755 index 0000000..f8c9c73 --- /dev/null +++ b/PYTHON/scrins/tests/test_inlet_outlet.py @@ -0,0 +1,251 @@ +#!/usr/bin/python + + +""" +This scripts tests inlet and outlet conditons at various places in +computational domain. + +Computational domain is a simple box, and Reynolds number is rather +small to avoid instabilities due to vortices getting out from the +outlet. The script selects the case it will run randomply, from the +16 predefined cases. +""" + +from math import floor, sqrt +from random import random + +from numpy import array, zeros + +from scrins.physical_models.properties_for_air import properties_for_air + +from scrins.constants.boundary_conditions import DIRICHLET, NEUMANN, OUTLET +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.display.plot_isolines import plot_isolines +from scrins.discretization.cartesian_grid import cartesian_grid +from scrins.discretization.nodes import nodes +from scrins.discretization.create_unknown import create_unknown +from scrins.discretization.cfl_max import cfl_max +from scrins.discretization.calc_p import calc_p +from scrins.discretization.calc_uvw import calc_uvw +from scrins.discretization.corr_uvw import corr_uvw +from scrins.discretization.vol_balance import vol_balance +from scrins.display.print_time_step import print_time_step +from scrins.operators.avg import avg +from scrins.operators.par import par + + +def main(show_plot=True): + """ + inlet example + :param show_plot: show plot or not + :return: None + """ + + #========================================================================== + # + # Define problem + # + #========================================================================== + + planes = ('XY', 'XZ', 'YZ') + tests = array([11, 12, 13, 14, \ + 21, 22, 23, 24, \ + 31, 32, 33, 34, \ + 41, 42, 43, 44]) + TEST = tests[floor(random()*16)] + PLANE = planes[floor(random()*3)] + + # Node coordinates + xn = nodes(0, 1, 160) + yn = nodes(0, 1, 160) + zn = nodes(0, 0.025, 4) + + # Cell coordinates + xc = avg(xn) + yc = avg(yn) + zc = avg(zn) + + # Cell dimensions + nx, ny, nz, \ + dx, dy, dz, \ + rc, ru, rv, rw = cartesian_grid(xn, yn, zn) + + # Set physical properties + rho, mu, cap, kappa = properties_for_air(rc) + + # Time-stepping parameters + dt = 0.15 # time step + ndt = 200 # number of time steps + + # Create unknowns names, positions and sizes + uf = create_unknown('face-u-vel', X, ru, DIRICHLET) + vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) + wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) + p = create_unknown('pressure', C, rc, NEUMANN) + + print(TEST) + + # Specify boundary conditions + if TEST == 11: + for k in range(0, nz): + uf.bnd[W].val[0, ny//4:3*ny//4, k] = +par(0.01, yn[ny//4:3*ny//4+1]) + uf.bnd[E].typ[0, ny//4:3*ny//4, k] = OUTLET + + elif TEST == 12: # vertical mirror from 11 + for k in range(0, nz): + uf.bnd[E].val[0, ny//4:3*ny//4, k] = -par(0.01, yn[ny//4:3*ny//4+1]) + uf.bnd[W].typ[0, ny//4:3*ny//4, k] = OUTLET + + elif TEST == 13: # rotate 11 + for k in range(0, nz): + vf.bnd[S].val[nx//4:3*nx//4, 0, k] = +par(0.01, xn[nx//4:3*nx//4+1]) + vf.bnd[N].typ[nx//4:3*nx//4, 0, k] = OUTLET + + elif TEST == 14: # horizontal mirror 13 + for k in range(0, nz): + vf.bnd[N].val[nx//4:3*nx//4, 0, k] = -par(0.01, xn[nx//4:3*nx//4+1]) + vf.bnd[S].typ[nx//4:3*nx//4, 0, k] = OUTLET + + elif TEST == 21: # 2 exits + for k in range(0, nz): + uf.bnd[W].val[0, ny//4:3*ny//4, k] = +par(0.01, yn[ny//4:3*ny//4+1]) + uf.bnd[E].typ[0, 0:ny//4, k] = OUTLET + uf.bnd[E].typ[0, 3*ny//4:ny, k] = OUTLET + + elif TEST == 22: # vertical mirror 21 + for k in range(0, nz): + uf.bnd[E].val[0, ny//4:3*ny//4, k] = -par(0.01, yn[ny//4:3*ny//4+1]) + uf.bnd[W].typ[0, 0:ny//4, k] = OUTLET + uf.bnd[W].typ[0, 3*ny//4:ny, k] = OUTLET + + elif TEST == 23: # rotated 21 + for k in range(0, nz): + vf.bnd[S].val[nx//4:3*nx//4, 0, k] = +par(0.01, xn[nx//4:3*nx//4+1]) + vf.bnd[N].typ[:nx//4, 0, k] = OUTLET + vf.bnd[N].typ[3*nx//4:nx, 0, k] = OUTLET + + elif TEST == 24: # horizontal mirror of 23 + for k in range(0, nz): + vf.bnd[N].val[nx//4:3*nx//4, 0, k] = -par(0.01, xn[nx//4:3*nx//4+1]) + vf.bnd[S].typ[:nx//4, 0, k] = OUTLET + vf.bnd[S].typ[3*nx//4:nx, 0, k] = OUTLET + + elif TEST == 31: # inlet and outlet at the same face + for k in range(0, nz): + uf.bnd[W].val[0, 3*ny//4:ny, k] = +par(0.01, yn[3*ny//4:ny+1]) + uf.bnd[W].typ[0, :ny//4, k] = OUTLET + + elif TEST == 32: # vertical mirror of 31 + for k in range(0, nz): + uf.bnd[E].val[0, 3*ny//4:ny, k] = -par(0.01, yn[3*ny//4:ny+1]) + uf.bnd[E].typ[0, 0:ny//4, k] = OUTLET + + elif TEST == 33: # rotated 31 + for k in range(0, nz): + vf.bnd[S].val[3*nx//4:nx, 0, k] = +par(0.01, xn[3*nx//4:nx+1]) + vf.bnd[S].typ[:nx//4, 0, k] = OUTLET + + elif TEST == 34: # horizontal mirror of 33 + for k in range(0, nz): + vf.bnd[N].val[3*nx//4:nx, 0, k] = -par(0.01, xn[3*nx//4:nx+1]) + vf.bnd[N].typ[:nx//4, 0, k] = OUTLET + + elif TEST == 41: # inlet and outlet at the same face, one more outlet + for k in range(0, nz): + uf.bnd[W].val[0, 3*ny//4:ny, k] = +par(0.01, yn[3*ny//4:ny+1]) + uf.bnd[W].typ[0, :ny//8, k] = OUTLET + uf.bnd[E].typ[0, :ny//8, k] = OUTLET + + elif TEST == 42: # vertical mirror of 41 + for k in range(0, nz): + uf.bnd[E].val[0, 3*ny//4:ny, k] = -par(0.01, yn[3*ny//4:ny+1]) + uf.bnd[E].typ[0, :ny//8, k] = OUTLET + uf.bnd[W].typ[0, :ny//8, k] = OUTLET + + elif TEST == 43: # rotated 41 + for k in range(0, nz): + vf.bnd[S].val[3*nx//4:nx, 0, k] = +par(0.01, xn[3*nx//4:nx+1]) + vf.bnd[S].typ[0:nx//8, 0, k] = OUTLET + vf.bnd[N].typ[0:nx//8, 0, k] = OUTLET + + elif TEST == 44: # horizontal mirror of 43 + for k in range(0, nz): + vf.bnd[N].val[3*ny//4:nx, 0, k] = -par(0.01, xn[3*nx//4:nx+1]) + vf.bnd[N].typ[:nx//8, 0, k] = OUTLET + vf.bnd[S].typ[:nx//8, 0, k] = OUTLET + + for j in (B, T): + uf.bnd[j].typ[:] = NEUMANN + vf.bnd[j].typ[:] = NEUMANN + wf.bnd[j].typ[:] = NEUMANN + + # Create a cylindrical obstacle in the middle just for kicks + obst = zeros(rc) + for k in range(0, nz): + for j in range(0, ny): + for i in range(0, nx): + dist = sqrt((j-ny/2+1)**2 + (i-nx/2+1)**2) + if dist < ny/4: + obst[i, j, k] = 1 + + # ========================================================================= + # + # Solution algorithm + # + # ========================================================================= + + # ----------- + # + # Time loop + # + # ----------- + for ts in range(1, ndt+1): + print_time_step(ts) + + # ------------------ + # Store old values + # ------------------ + uf.old[:] = uf.val[:] + vf.old[:] = vf.val[:] + wf.old[:] = wf.val[:] + + # ----------------------- + # Momentum conservation + # ----------------------- + ef = zeros(ru), zeros(rv), zeros(rw) + + calc_uvw((uf, vf, wf), (uf, vf, wf), rho, mu, + zeros(rc), ef, dt, (dx, dy, dz), obst) + + # ---------- + # Pressure + # ---------- + calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst) + + # --------------------- + # Velocity correction + # --------------------- + corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst) + + # Compute volume balance for checking + err = vol_balance((uf, vf, wf), (dx, dy, dz), obst) + print('Maximum volume error after correction: %12.5e' % abs(err).max()) + + # Check the CFL number too + cfl = cfl_max((uf, vf, wf), dt, (dx, dy, dz)) + print('Maximum CFL number: %12.5e' % cfl) + + # ========================================================================= + # + # Visualisation + # + # ========================================================================= + if show_plot: + if ts % 10 == 0: + plot_isolines(p.val, (uf, vf, wf), (xn, yn, zn), Z) + + +if __name__ == '__main__': + main() + \ No newline at end of file diff --git a/PYTHON/scrins/tests/test_obstacles_collocated.py b/PYTHON/scrins/tests/test_obstacles_collocated.py new file mode 100755 index 0000000..9ce7307 --- /dev/null +++ b/PYTHON/scrins/tests/test_obstacles_collocated.py @@ -0,0 +1,172 @@ +#!/usr/bin/python + +""" + o ... scalars + (n) - ... u velocities + | ... v velocities + +-------+-------+-------+-------+-------+ + | | | | | | + | o - o - o - o - o | j=ny + | | | | | | + +---|---+---|---+---|---+---|---+---|---+ j=nym + | | | | | | + | o - o - o - o - o | ... + | | | | | | + (w) +---|---+---|---+---|---+---|---+---|---+ j=2 (e) + | | | | | | + | o - o - o - o - o | j=2 + | | | | | | + +---|---+---|---+---|---+---|---+---|---+ j=1 (v-velocity) + | | | | | | + | o - o - o - o - o | j=1 (scalar cell) + | | | | | | + +-------+-------+-------+-------+-------+ + y i=1 i=2 ... ... i=nx (scalar cells) + ^ i=1 i=2 ... i=nxm (u-velocity cells) + | + +---> x (s) +""" + + +from numpy import zeros + +from scrins.physical_models.properties_for_air import properties_for_air +from scrins.constants.boundary_conditions import DIRICHLET, NEUMANN, OUTLET +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.display.plot_isolines import plot_isolines +from scrins.discretization.adj_n_bnds import adj_n_bnds +from scrins.discretization.cartesian_grid import cartesian_grid +from scrins.discretization.create_unknown import create_unknown +from scrins.discretization.cfl_max import cfl_max +from scrins.discretization.calc_p import calc_p +from scrins.discretization.calc_uvw import calc_uvw +from scrins.discretization.corr_uvw import corr_uvw +from scrins.discretization.nodes import nodes +from scrins.discretization.vol_balance import vol_balance +from scrins.display.print_time_step import print_time_step +from scrins.operators.avg import avg +from scrins.operators.par import par + + +def main(show_plot=True): + """ + Example for obstacles collocated + """ + # ========================================================================= + # + # Define problem + # + # ========================================================================= + + # Node coordinates + xn = nodes(0, 1, 256) + yn = nodes(0, 0.125, 32) + zn = nodes(0, 0.125, 4) + + # Cell coordinates + xc = avg(xn) + yc = avg(yn) + zc = avg(zn) + + # Cell dimensions + nx, ny, nz, \ + dx, dy, dz, \ + rc, ru, rv, rw = cartesian_grid(xn, yn, zn) + + # Set physical properties + rho, mu, cap, kappa = properties_for_air(rc) + + # Time-stepping parameters + dt = 0.002 # time step + ndt = 5000 # number of time steps + + # Create unknowns; names, positions and sizes + uc = create_unknown('cell-u-vel', C, rc, DIRICHLET) + vc = create_unknown('cell-v-vel', C, rc, DIRICHLET) + wc = create_unknown('cell-w-vel', C, rc, DIRICHLET) + uf = create_unknown('face-u-vel', X, ru, DIRICHLET) + vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) + wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) + p = create_unknown('pressure', C, rc, NEUMANN) + + # Specify boundary conditions + uc.bnd[W].typ[:1, :, :] = DIRICHLET + for k in range(0, nz): + uc.bnd[W].val[:1, :, k] = par(0.1, yn) + + uc.bnd[E].typ[:1, :, :] = OUTLET + + for j in (B, T): + uf.bnd[j].typ[:] = NEUMANN + vf.bnd[j].typ[:] = NEUMANN + wf.bnd[j].typ[:] = NEUMANN + + adj_n_bnds(p) + + obst = zeros(rc) + for j in range(0, 24): + for i in range(64+j, 64+24): + for k in range(0, nz): + obst[i, j, k] = 1 + + # ========================================================================= + # + # Solution algorithm + # + # ========================================================================= + + # ----------- + # + # Time loop + # + # ----------- + for ts in range(1, ndt+1): + + print_time_step(ts) + # ------------------ + # Store old values + # ------------------ + uc.old[:] = uc.val[:] + vc.old[:] = vc.val[:] + wc.old[:] = wc.val[:] + + # ----------------------- + # Momentum conservation + # ----------------------- + ef = zeros(rc), zeros(rc), zeros(rc) + + calc_uvw((uc, vc, wc), (uf, vf, wf), rho, mu, + zeros(rc), ef, dt, (dx, dy, dz), obst) + + # ---------- + # Pressure + # ---------- + calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst) + + # --------------------- + # Velocity correction + # --------------------- + corr_uvw((uc, vc, wc), p, rho, dt, (dx, dy, dz), obst) + corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst) + + # Compute volume balance for checking + err = vol_balance((uf, vf, wf), (dx, dy, dz), obst) + print('Maximum volume error after correction: %12.5e' % abs(err).max()) + + # Check the CFL number too + cfl = cfl_max((uc, vc, wc), dt, (dx, dy, dz)) + print('Maximum CFL number: %12.5e' % cfl) + + # ===================================================================== + # + # Visualisation + # + # ===================================================================== + if show_plot: + if ts % 20 == 0: + plot_isolines(p.val, (uc, vc, wc), (xn, yn, zn), Z) + + +if __name__ == '__main__': + main() diff --git a/PYTHON/scrins/tests/test_obstacles_staggered.py b/PYTHON/scrins/tests/test_obstacles_staggered.py new file mode 100755 index 0000000..b937586 --- /dev/null +++ b/PYTHON/scrins/tests/test_obstacles_staggered.py @@ -0,0 +1,169 @@ +#!/usr/bin/python + +""" + o ... scalars + (n) - ... u velocities + | ... v velocities + +-------+-------+-------+-------+-------+ + | | | | | | + | o - o - o - o - o | j=ny + | | | | | | + +---|---+---|---+---|---+---|---+---|---+ j=nym + | | | | | | + | o - o - o - o - o | ... + | | | | | | + (w) +---|---+---|---+---|---+---|---+---|---+ j=2 (e) + | | | | | | + | o - o - o - o - o | j=2 + | | | | | | + +---|---+---|---+---|---+---|---+---|---+ j=1 (v-velocity) + | | | | | | + | o - o - o - o - o | j=1 (scalar cell) + | | | | | | + +-------+-------+-------+-------+-------+ + y i=1 i=2 ... ... i=nx (scalar cells) +^ i=1 i=2 ... i=nxm (u-velocity cells) +| ++---> x (s) + + +""" + + +from numpy import array, zeros + +from scrins.physical_models.properties_for_air import properties_for_air +from scrins.constants.boundary_conditions import DIRICHLET, NEUMANN, OUTLET +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.display.plot_isolines import plot_isolines +from scrins.discretization.adj_n_bnds import adj_n_bnds +from scrins.discretization.cartesian_grid import cartesian_grid +from scrins.discretization.nodes import nodes +from scrins.discretization.create_unknown import create_unknown +from scrins.discretization.cfl_max import cfl_max +from scrins.discretization.calc_p import calc_p +from scrins.discretization.calc_uvw import calc_uvw +from scrins.discretization.corr_uvw import corr_uvw +from scrins.discretization.vol_balance import vol_balance +from scrins.display.print_time_step import print_time_step +from scrins.operators.avg import avg +from scrins.operators.par import par + + +def main(show_plot=True): + """Example + """ + #========================================================================== + # + # Define problem + # + #========================================================================== + + # Node coordinates + xn = nodes(0, 1, 256) + yn = nodes(0, 0.125, 32) + zn = nodes(0, 0.125, 4) + + # Cell coordinates + xc = avg(xn) + yc = avg(yn) + zc = avg(zn) + + # Cell dimensions + nx, ny, nz, \ + dx, dy, dz, \ + rc, ru, rv, rw = cartesian_grid(xn, yn, zn) + + # Set physical properties + rho, mu, cap, kappa = properties_for_air(rc) + + # Time-stepping parameters + dt = 0.002 # time step + ndt = 5000 # number of time steps + + # Create unknowns; names, positions and sizes + uf = create_unknown('face-u-vel', X, ru, DIRICHLET) + vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) + wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) + p = create_unknown('pressure', C, rc, NEUMANN) + + # Specify boundary conditions + uf.bnd[W].typ[:1, :, :] = DIRICHLET + for k in range(0, nz): + uf.bnd[W].val[:1, :, k] = par(0.1, yn) + + uf.bnd[E].typ[:1, :, :] = OUTLET + + for j in (B, T): + uf.bnd[j].typ[:] = NEUMANN + vf.bnd[j].typ[:] = NEUMANN + wf.bnd[j].typ[:] = NEUMANN + + adj_n_bnds(p) + + obst = zeros(rc) + for j in range(0, 24): + for i in range(64+j, 64+24): + for k in range(0, nz): + obst[i, j, k] = 1 + + # ========================================================================= + # + # Solution algorithm + # + # ========================================================================= + + # ----------- + # + # Time loop + # + # ----------- + for ts in range(1, ndt+1): + + print_time_step(ts) + + # ------------------ + # Store old values + # ------------------ + uf.old[:] = uf.val[:] + vf.old[:] = vf.val[:] + wf.old[:] = wf.val[:] + + # ----------------------- + # Momentum conservation + # ----------------------- + ef = zeros(ru), zeros(rv), zeros(rw) + + calc_uvw((uf, vf, wf), (uf, vf, wf), rho, mu, \ + zeros(rc), ef, dt, (dx, dy, dz), obst) + + # ---------- + # Pressure + # ---------- + calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst) + + # --------------------- + # Velocity correction + # --------------------- + corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst) + + # Compute volume balance for checking + err = vol_balance((uf, vf, wf), (dx, dy, dz), obst) + print('Maximum volume error after correction: %12.5e' % abs(err).max()) + + # Check the CFL number too + cfl = cfl_max((uf, vf, wf), dt, (dx, dy, dz)) + print('Maximum CFL number: %12.5e' % cfl) + + # ===================================================================== + # + # Visualisation + # + # ===================================================================== + if show_plot: + if ts % 20 == 0: + plot_isolines(p.val, (uf, vf, wf), (xn, yn, zn), Z) + +if __name__ == '__main__': + main() diff --git a/PYTHON/scrins/tests/test_obstacles_thinner_collocated.py b/PYTHON/scrins/tests/test_obstacles_thinner_collocated.py new file mode 100644 index 0000000..5821c8d --- /dev/null +++ b/PYTHON/scrins/tests/test_obstacles_thinner_collocated.py @@ -0,0 +1,219 @@ +#!/usr/bin/python + +""" + o ... scalars + (n) - ... u velocities + | ... v velocities + +-------+-------+-------+-------+-------+ + | | | | | | + | o - o - o - o - o | j=ny + | | | | | | + +---|---+---|---+---|---+---|---+---|---+ j=nym + | | | | | | + | o - o - o - o - o | ... + | | | | | | + (w) +---|---+---|---+---|---+---|---+---|---+ j=2 (e) + | | | | | | + | o - o - o - o - o | j=2 + | | | | | | + +---|---+---|---+---|---+---|---+---|---+ j=1 (v-velocity) + | | | | | | + | o - o - o - o - o | j=1 (scalar cell) + | | | | | | + +-------+-------+-------+-------+-------+ + y i=1 i=2 ... ... i=nx (scalar cells) +^ i=1 i=2 ... i=nxm (u-velocity cells) +| ++---> x (s) +""" +from math import floor +from numpy import outer, zeros + +from scrins.physical_models.properties_for_air import properties_for_air +from scrins.constants.boundary_conditions import DIRICHLET, NEUMANN, OUTLET +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.display.plot_isolines import plot_isolines +from scrins.discretization.adj_n_bnds import adj_n_bnds +from scrins.discretization.cartesian_grid import cartesian_grid +from scrins.discretization.nodes import nodes +from scrins.discretization.create_unknown import create_unknown +from scrins.discretization.cfl_max import cfl_max +from scrins.discretization.calc_p import calc_p +from scrins.discretization.calc_uvw import calc_uvw +from scrins.discretization.corr_uvw import corr_uvw +from scrins.discretization.vol_balance import vol_balance +from scrins.display.print_time_step import print_time_step +from scrins.operators.avg import avg +from scrins.operators.par import par + + +def main(show_plot=True): + """ + Docstring. + """ + + # ========================================================================= + # + # Define problem + # + # ========================================================================= + + # Node coordinates + xn = nodes(0, 1.25, 256) + yn = nodes(0, 0.125, 32) + zn = nodes(0, 0.125, 32) + + # Cell coordinates + xc = avg(xn) + yc = avg(yn) + zc = avg(zn) + + # Cell dimensions + nx, ny, nz, \ + dx, dy, dz, \ + rc, ru, rv, rw = cartesian_grid(xn, yn, zn) + + # Set physical properties + rho, mu, cap, kappa = properties_for_air(rc) + + # Time-stepping parameters + dt = 0.005 # time step + ndt = 2000 # number of time steps + + # Create unknowns; names, positions and sizes + uc = create_unknown('cell-u-vel', C, rc, DIRICHLET) + vc = create_unknown('cell-v-vel', C, rc, DIRICHLET) + wc = create_unknown('cell-w-vel', C, rc, DIRICHLET) + uf = create_unknown('face-u-vel', X, ru, DIRICHLET) + vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) + wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) + p = create_unknown('pressure', C, rc, NEUMANN) + + # Specify boundary conditions + uc.bnd[W].typ[:1, :, :] = DIRICHLET + uc.bnd[W].val[:1, :, :] = 0.1 * outer(par(1.0, yn), par(1.0, zn)) + + uc.bnd[E].typ[:1, :, :] = OUTLET + + for j in (B, T): + uc.bnd[j].typ[:] = NEUMANN + vc.bnd[j].typ[:] = NEUMANN + wc.bnd[j].typ[:] = NEUMANN + + adj_n_bnds(p) + + # Create obstacles + obst = zeros(rc) + + + + class key: + """ + Class Docstring. + """ + ip = -1 + im = -1 + jp = -1 + jm = -1 + kp = -1 + km = -1 + + block = (key(), key(), key(), key()) + + th = 5 + block[0].im = 3*nx/16 # i minus + block[0].ip = block[0].im + th # i plus + block[0].jm = 0 # j minus + block[0].jp = 3*ny/4 # j plus + block[0].km = 0 # k minus + block[0].kp = 3*ny/4 # k plus + + block[1].im = 5*nx/16 # i minus + block[1].ip = block[1].im + th # i plus + block[1].jm = ny/4 # j minus + block[1].jp = ny # j plus + block[1].km = ny/4 # k minus + block[1].kp = ny # k plus + + block[2].im = 7*nx/16 # i minus + block[2].ip = block[2].im + th # i plus + block[2].jm = 0 # j minus + block[2].jp = 3*ny/4 # j plus + block[2].km = 0 # k minus + block[2].kp = 3*ny/4 # k plus + + block[3].im = 9*nx/16 # i minus + block[3].ip = block[3].im + th # i plus + block[3].jm = ny/4 # j minus + block[3].jp = ny # j plus + block[3].km = ny/4 # k minus + block[3].kp = ny # k plus + + for o in range(0, 4): + for i in range(floor(block[o].im), floor(block[o].ip)): + for j in range(floor(block[o].jm), floor(block[o].jp)): + for k in range(floor(block[o].km), floor(block[o].kp)): + obst[i, j, k] = 1 + + # ========================================================================= + # + # Solution algorithm + # + # ========================================================================= + + # ----------- + # + # Time loop + # + # ----------- + for ts in range(1, ndt+1): + + print_time_step(ts) + + # ------------------ + # Store old values + # ------------------ + uc.old[:] = uc.val[:] + vc.old[:] = vc.val[:] + wc.old[:] = wc.val[:] + + # ----------------------- + # Momentum conservation + # ----------------------- + ef = zeros(rc), zeros(rc), zeros(rc) + + calc_uvw((uc, vc, wc), (uf, vf, wf), rho, mu, + zeros(rc), ef, dt, (dx, dy, dz), obst) + + # ---------- + # Pressure + # ---------- + calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst) + + # --------------------- + # Velocity correction + # --------------------- + corr_uvw((uc, vc, wc), p, rho, dt, (dx, dy, dz), obst) + corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst) + + # Compute volume balance for checking + err = vol_balance((uf, vf, wf), (dx, dy, dz), obst) + print('Maximum volume error after correction: %12.5e' % abs(err).max()) + + # Check the CFL number too + cfl = cfl_max((uc, vc, wc), dt, (dx, dy, dz)) + print('Maximum CFL number: %12.5e' % cfl) + + # ===================================================================== + # + # Visualisation + # + # ===================================================================== + if show_plot: + if ts % 20 == 0: + plot_isolines(p.val, (uc, vc, wc), (xn, yn, zn), Y) + plot_isolines(p.val, (uc, vc, wc), (xn, yn, zn), Z) + +if __name__ == '__main__': + main() diff --git a/PYTHON/scrins/tests/test_obstacles_thinner_staggered.py b/PYTHON/scrins/tests/test_obstacles_thinner_staggered.py new file mode 100755 index 0000000..be0d588 --- /dev/null +++ b/PYTHON/scrins/tests/test_obstacles_thinner_staggered.py @@ -0,0 +1,216 @@ +#!/usr/bin/python + +""" + o ... scalars + (n) - ... u velocities + | ... v velocities + +-------+-------+-------+-------+-------+ + | | | | | | + | o - o - o - o - o | j=ny + | | | | | | + +---|---+---|---+---|---+---|---+---|---+ j=nym + | | | | | | + | o - o - o - o - o | ... + | | | | | | + (w) +---|---+---|---+---|---+---|---+---|---+ j=2 (e) + | | | | | | + | o - o - o - o - o | j=2 + | | | | | | + +---|---+---|---+---|---+---|---+---|---+ j=1 (v-velocity) + | | | | | | + | o - o - o - o - o | j=1 (scalar cell) + | | | | | | + +-------+-------+-------+-------+-------+ + y i=1 i=2 ... ... i=nx (scalar cells) +^ i=1 i=2 ... i=nxm (u-velocity cells) +| ++---> x (s) +""" + +from math import floor + +from numpy import outer, zeros + +from scrins.physical_models.properties_for_air import properties_for_air +from scrins.constants.boundary_conditions import DIRICHLET, NEUMANN, OUTLET +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.display.plot_isolines import plot_isolines +from scrins.discretization.adj_n_bnds import adj_n_bnds +from scrins.discretization.cartesian_grid import cartesian_grid +from scrins.discretization.nodes import nodes +from scrins.discretization.create_unknown import create_unknown +from scrins.discretization.cfl_max import cfl_max +from scrins.discretization.calc_p import calc_p +from scrins.discretization.calc_uvw import calc_uvw +from scrins.discretization.corr_uvw import corr_uvw +from scrins.discretization.vol_balance import vol_balance +from scrins.display.print_time_step import print_time_step +from scrins.operators.avg import avg +from scrins.operators.par import par + +def main(show_plot=True): + """ + Example Docstring. + """ + + + # ========================================================================= + # + # Define problem + # + # ========================================================================= + + # Node coordinates + xn = nodes(0, 1.25, 256) + yn = nodes(0, 0.125, 32) + zn = nodes(0, 0.125, 32) + + # Cell coordinates + xc = avg(xn) + yc = avg(yn) + zc = avg(zn) + + # Cell dimensions + nx, ny, nz, \ + dx, dy, dz, \ + rc, ru, rv, rw = cartesian_grid(xn, yn, zn) + + # Set physical properties + rho, mu, cap, kappa = properties_for_air(rc) + + # Time-stepping parameters + dt = 0.005 # time step + ndt = 2000 # number of time steps + + # Create unknowns; names, positions and sizes + uf = create_unknown('face-u-vel', X, ru, DIRICHLET) + vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) + wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) + p = create_unknown('pressure', C, rc, NEUMANN) + + # Specify boundary conditions + uf.bnd[W].typ[:1, :, :] = DIRICHLET + uf.bnd[W].val[:1, :, :] = 0.1 * outer(par(1.0, yn), par(1.0, zn)) + + uf.bnd[E].typ[:1, :, :] = OUTLET + + for j in (B, T): + uf.bnd[j].typ[:] = NEUMANN + vf.bnd[j].typ[:] = NEUMANN + wf.bnd[j].typ[:] = NEUMANN + + adj_n_bnds(p) + + # Create obstacles + obst = zeros(rc) + + class key: + """ + Class Doctrsing. + """ + ip = -1 + im = -1 + jp = -1 + jm = -1 + kp = -1 + km = -1 + + block = (key(), key(), key(), key()) + + th = 5 + block[0].im = 3*nx/16 # i minus + block[0].ip = block[0].im + th # i plus + block[0].jm = 0 # j minus + block[0].jp = 3*ny/4 # j plus + block[0].km = 0 # k minus + block[0].kp = 3*ny/4 # k plus + + block[1].im = 5*nx/16 # i minus + block[1].ip = block[1].im + th # i plus + block[1].jm = ny/4 # j minus + block[1].jp = ny # j plus + block[1].km = ny/4 # k minus + block[1].kp = ny # k plus + + block[2].im = 7*nx/16 # i minus + block[2].ip = block[2].im + th # i plus + block[2].jm = 0 # j minus + block[2].jp = 3*ny/4 # j plus + block[2].km = 0 # k minus + block[2].kp = 3*ny/4 # k plus + + block[3].im = 9*nx/16 # i minus + block[3].ip = block[3].im + th # i plus + block[3].jm = ny/4 # j minus + block[3].jp = ny # j plus + block[3].km = ny/4 # k minus + block[3].kp = ny # k plus + + for o in range(0, 4): + for i in range(floor(block[o].im), floor(block[o].ip)): + for j in range(floor(block[o].jm), floor(block[o].jp)): + for k in range(floor(block[o].km), floor(block[o].kp)): + obst[i, j, k] = 1 + + # ========================================================================= + # + # Solution algorithm + # + # ========================================================================= + + # ----------- + # + # Time loop + # + # ----------- + for ts in range(1, ndt+1): + + print_time_step(ts) + + # ------------------ + # Store old values + # ------------------ + uf.old[:] = uf.val[:] + vf.old[:] = vf.val[:] + wf.old[:] = wf.val[:] + + # ----------------------- + # Momentum conservation + # ----------------------- + ef = zeros(ru), zeros(rv), zeros(rw) + + calc_uvw((uf, vf, wf), (uf, vf, wf), rho, mu, + zeros(rc), ef, dt, (dx, dy, dz), obst) + + # ---------- + # Pressure + # ---------- + calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst) + + # --------------------- + # Velocity correction + # --------------------- + corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst) + + # Compute volume balance for checking + err = vol_balance((uf, vf, wf), (dx, dy, dz), obst) + print('Maximum volume error after correction: %12.5e' % abs(err).max()) + + # Check the CFL number too + cfl = cfl_max((uf, vf, wf), dt, (dx, dy, dz)) + print('Maximum CFL number: %12.5e' % cfl) + + # ===================================================================== + # + # Visualisation + # + # ===================================================================== + if show_plot: + if ts % 20 == 0: + plot_isolines(p.val, (uf, vf, wf), (xn, yn, zn), Y) + plot_isolines(p.val, (uf, vf, wf), (xn, yn, zn), Z) + +if __name__ == '__main__': + main() + \ No newline at end of file diff --git a/PYTHON/scrins/tests/test_thermal_plumes_collocated.py b/PYTHON/scrins/tests/test_thermal_plumes_collocated.py new file mode 100755 index 0000000..d27004f --- /dev/null +++ b/PYTHON/scrins/tests/test_thermal_plumes_collocated.py @@ -0,0 +1,202 @@ +#!/usr/bin/python + +""" +This script is to reproduce two-dimensional mixed convection case, with +the aim of testing the outflow boundary, particularly the "convective" +boundary condition which allows eddies to leave the domain. + +There is also a staggered version of this script, called +"demo_plums_collocated.m". It would be good to keep both version as +similar as possible to each other, to test the differences between +staggered and collocated arrangements always possible. + +""" + +from numpy import zeros + + +#import scrins.constants +from scrins.constants.boundary_conditions import DIRICHLET, NEUMANN, OUTLET +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.display.plot_isolines import plot_isolines +from scrins.discretization.adj_n_bnds import adj_n_bnds +from scrins.discretization.cartesian_grid import cartesian_grid +from scrins.discretization.nodes import nodes +from scrins.discretization.create_unknown import create_unknown +from scrins.discretization.cfl_max import cfl_max +from scrins.discretization.calc_p import calc_p +from scrins.discretization.calc_t import calc_t +from scrins.discretization.calc_uvw import calc_uvw +from scrins.discretization.corr_uvw import corr_uvw +from scrins.discretization.vol_balance import vol_balance +from scrins.display.print_time_step import print_time_step +from scrins.operators.avg import avg +from scrins.operators.par import par + + +def main(show_plot=True): + """ + Docstring. + """ + # ========================================================================= + # + # Define problem + # + # ========================================================================= + + # Node coordinates + xn = nodes(0, 10, 300) + yn = nodes(0, 1, 40, 1 / 500, 1 / 500) + zn = nodes(0, 3, 3) + + # Cell coordinates + xc = avg(xn) + yc = avg(yn) + zc = avg(zn) + + # Cell dimensions + nx, ny, nz, \ + dx, dy, dz, \ + rc, ru, rv, rw = cartesian_grid(xn, yn, zn) + + # Set physical properties + rho = zeros(rc) + mu = zeros(rc) + kappa = zeros(rc) + cap = zeros(rc) + rho[:, :, :] = 1. + mu[:, :, :] = 0.1 + kappa[:, :, :] = 0.15 + cap[:, :, :] = 1.0 + + # Time-stepping parameters + dt = 0.003 # time step + ndt = 1500 # number of time steps + + # Create unknowns; names, positions and sizes + uc = create_unknown('cell-u-vel', C, rc, DIRICHLET) + vc = create_unknown('cell-v-vel', C, rc, DIRICHLET) + wc = create_unknown('cell-w-vel', C, rc, DIRICHLET) + uf = create_unknown('face-u-vel', X, ru, DIRICHLET) + vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) + wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) + t = create_unknown('temperature', C, rc, NEUMANN) + p = create_unknown('pressure', C, rc, NEUMANN) + + # Specify boundary conditions + uc.bnd[W].typ[:1, :, :] = DIRICHLET + for k in range(0, nz): + uc.bnd[W].val[:1, :, k] = par(1.0, yn) + + uc.bnd[E].typ[:1, :, :] = OUTLET + uc.bnd[E].val[:1, :, :] = 1.0 + + for j in (B, T): + uc.bnd[j].typ[:] = NEUMANN + vc.bnd[j].typ[:] = NEUMANN + wc.bnd[j].typ[:] = NEUMANN + + t.bnd[W].typ[:1, :, :] = DIRICHLET + for k in range(0, nz): + t.bnd[W].val[:1, :, k] = 1.0 - yc + + t.bnd[S].typ[:, :1, :] = DIRICHLET + t.bnd[S].val[:, :1, :] = +1.0 + t.bnd[N].typ[:, :1, :] = DIRICHLET + t.bnd[N].val[:, :1, :] = 0.0 + + adj_n_bnds(t) + adj_n_bnds(p) + + # Specify initial conditions + uc.val[:, :, :] = 1.0 + t.val[:, :, :] = 0 + + # Copy the values to face velocities + uf.val[:] = avg(X, uc.val) + vf.val[:] = avg(Y, vc.val) + wf.val[:] = avg(Z, wc.val) + for j in (W, E): + uf.bnd[j].val[:] = uc.bnd[j].val[:] + vf.bnd[j].val[:] = avg(Y, vc.bnd[j].val[:]) + wf.bnd[j].val[:] = avg(Z, wc.bnd[j].val[:]) + for j in (S, N): + uf.bnd[j].val[:] = avg(X, uc.bnd[j].val[:]) + vf.bnd[j].val[:] = vc.bnd[j].val[:] + wf.bnd[j].val[:] = avg(Z, wc.bnd[j].val[:]) + for j in (B, T): + uf.bnd[j].val[:] = avg(X, uc.bnd[j].val[:]) + vf.bnd[j].val[:] = avg(Y, vc.bnd[j].val[:]) + wf.bnd[j].val[:] = wc.bnd[j].val[:] + + obst = zeros(rc) + + # ========================================================================= + # + # Solution algorithm + # + # ========================================================================= + + # ----------- + # + # Time loop + # + # ----------- + for ts in range(1, ndt + 1): + + print_time_step(ts) + + # ------------------ + # Store old values + # ------------------ + t.old[:] = t.val[:] + uc.old[:] = uc.val[:] + vc.old[:] = vc.val[:] + wc.old[:] = wc.val[:] + + # ------------------------ + # Temperature (enthalpy) + # ------------------------ + calc_t(t, (uf, vf, wf), (rho * cap), kappa, dt, (dx, dy, dz), obst) + + # ----------------------- + # Momentum conservation + # ----------------------- + ef = zeros(rc), 150.0 * t.val, zeros(rc) + + calc_uvw((uc, vc, wc), (uf, vf, wf), rho, mu, \ + zeros(rc), ef, dt, (dx, dy, dz), obst) + + # ---------- + # Pressure + # ---------- + calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst) + + # --------------------- + # Velocity correction + # --------------------- + corr_uvw((uc, vc, wc), p, rho, dt, (dx, dy, dz), obst) + corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst) + + # Compute volume balance for checking + err = vol_balance((uf, vf, wf), (dx, dy, dz), obst) + print('Maximum volume error after correction: %12.5e' % abs(err).max()) + + # Check the CFL number too + cfl = cfl_max((uc, vc, wc), dt, (dx, dy, dz)) + print('Maximum CFL number: %12.5e' % cfl) + + # ===================================================================== + # + # Visualisation + # + # ===================================================================== + if show_plot: + if ts % 150 == 0: + plot_isolines(t.val, (uc, vc, wc), (xn, yn, zn), Z) + plot_isolines(p.val, (uc, vc, wc), (xn, yn, zn), Z) + + +if __name__ == '__main__': + main() diff --git a/PYTHON/scrins/tests/test_thermal_plumes_staggered.py b/PYTHON/scrins/tests/test_thermal_plumes_staggered.py new file mode 100755 index 0000000..4632b18 --- /dev/null +++ b/PYTHON/scrins/tests/test_thermal_plumes_staggered.py @@ -0,0 +1,176 @@ +#!/usr/bin/python + +""" +This script is to reproduce two-dimensional mixed convection case, with +the aim of testing the outflow boundary, particularly the "convective" +boundary condition which allows eddies to leave the domain. + +There is also a staggered version of this script, called +"demo_plums_collocated.m". It would be good to keep both version as +similar as possible to each other, to test the differences between +staggered and collocated arrangements always possible. +""" + +from numpy import zeros + +from scrins.constants.boundary_conditions import DIRICHLET, NEUMANN, OUTLET +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.display.plot_isolines import plot_isolines +from scrins.discretization.adj_n_bnds import adj_n_bnds +from scrins.discretization.cartesian_grid import cartesian_grid +from scrins.discretization.nodes import nodes +from scrins.discretization.create_unknown import create_unknown +from scrins.discretization.cfl_max import cfl_max +from scrins.discretization.calc_p import calc_p +from scrins.discretization.calc_t import calc_t +from scrins.discretization.calc_uvw import calc_uvw +from scrins.discretization.corr_uvw import corr_uvw +from scrins.discretization.vol_balance import vol_balance +from scrins.display.print_time_step import print_time_step +from scrins.operators.avg import avg +from scrins.operators.par import par + + +def main(show_plot=True): + """ + Docstring. + """ + + # ========================================================================= + # + # Define problem + # + # ========================================================================= + + # Node coordinates + xn = nodes(0, 10, 300) + yn = nodes(0, 1, 40, 1/500, 1/500) + zn = nodes(0, 3, 3) + + # Cell coordinates + xc = avg(xn) + yc = avg(yn) + zc = avg(zn) + + # Cell dimensions + nx, ny, nz, dx, dy, dz, rc, ru, rv, rw = cartesian_grid(xn, yn, zn) + + # Set physical properties + rho = zeros(rc) + mu = zeros(rc) + kappa = zeros(rc) + cap = zeros(rc) + rho[:, :, :] = 1. + mu[:, :, :] = 0.1 + kappa[:, :, :] = 0.15 + cap[:, :, :] = 1.0 + + # Time-stepping parameters + dt = 0.003 # time step + ndt = 1500 # number of time steps + + # Create unknowns; names, positions and sizes + uf = create_unknown('face-u-vel', X, ru, DIRICHLET) + vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) + wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) + t = create_unknown('temperature', C, rc, NEUMANN) + p = create_unknown('pressure', C, rc, NEUMANN) + + # Specify boundary conditions + uf.bnd[W].typ[:1, :, :] = DIRICHLET + for k in range(0, nz): + uf.bnd[W].val[:1, :, k] = par(1.0, yn) + + uf.bnd[E].typ[:1, :, :] = OUTLET + uf.bnd[E].val[:1, :, :] = 1.0 + + for j in (B, T): + uf.bnd[j].typ[:] = NEUMANN + vf.bnd[j].typ[:] = NEUMANN + wf.bnd[j].typ[:] = NEUMANN + + t.bnd[W].typ[:1, :, :] = DIRICHLET + for k in range(0, nz): + t.bnd[W].val[:1, :, k] = 1.0 - yc + + t.bnd[S].typ[:, :1, :] = DIRICHLET + t.bnd[S].val[:, :1, :] = +1.0 + t.bnd[N].typ[:, :1, :] = DIRICHLET + t.bnd[N].val[:, :1, :] = 0.0 + + adj_n_bnds(t) + adj_n_bnds(p) + + # Specify initial conditions + uf.val[:, :, :] = 1.0 + t.val[:, :, :] = 0 + + obst = zeros(rc) + + # ========================================================================= + # + # Solution algorithm + # + # ========================================================================= + + # ----------- + # + # Time loop + # + # ----------- + for ts in range(1, ndt+1): + + print_time_step(ts) + + # ------------------ + # Store old values + # ------------------ + t.old[:] = t.val[:] + uf.old[:] = uf.val[:] + vf.old[:] = vf.val[:] + wf.old[:] = wf.val[:] + + # ------------------------ + # Temperature (enthalpy) + # ------------------------ + calc_t(t, (uf, vf, wf), (rho * cap), kappa, dt, (dx, dy, dz), obst) + + # ----------------------- + # Momentum conservation + # ----------------------- + ef = zeros(ru), 150.0 * avg(Y, t.val), zeros(rw) + + calc_uvw((uf, vf, wf), (uf, vf, wf), rho, mu, \ + zeros(rc), ef, dt, (dx, dy, dz), obst) + + # ---------- + # Pressure + # ---------- + calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst) + + # --------------------- + # Velocity correction + # --------------------- + corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst) + + # Compute volume balance for checking + err = vol_balance((uf, vf, wf), (dx, dy, dz), obst) + print('Maximum volume error after correction: %12.5e' % abs(err).max()) + + # Check the CFL number too + cfl = cfl_max((uf, vf, wf), dt, (dx, dy, dz)) + print('Maximum CFL number: %12.5e' % cfl) + + # ===================================================================== + # + # Visualisation + # + # ===================================================================== + if show_plot: + if ts % 150 == 0: + plot_isolines(t.val, (uf, vf, wf), (xn, yn, zn), Z) + plot_isolines(p.val, (uf, vf, wf), (xn, yn, zn), Z) + +if __name__ == '__main__': + main() diff --git a/PYTHON/scrins/tests/test_thermally_driven_cavity_collocated.py b/PYTHON/scrins/tests/test_thermally_driven_cavity_collocated.py new file mode 100755 index 0000000..f8fc5c2 --- /dev/null +++ b/PYTHON/scrins/tests/test_thermally_driven_cavity_collocated.py @@ -0,0 +1,176 @@ +#!/usr/bin/python + +""" +This program solves thermally driven cavity at Ra = 1.0e6, +in dimensional and non-dimensional forms. + +Equations in dimensional form: + +D(rho u)/Dt = nabla(mu (nabla u)^T) - nabla p + g +D(rho cp T)/Dt = nabla(lambda (nabla T)^T) + +Equations in non-dimensional form, for natural convection problems + +DU/Dt = nabla(1/sqrt(Gr) (nabla U)^T) - nabla P + theta +D theta/Dt = nabla(1/(Pr*sqrt(Gr)) (nabla theta)^T) + +-------------------------------------------------------------------------- +For thermally driven cavity, with properties of air at 60 deg: + +nu = 1.89035E-05; +beta = 0.003; +dT = 17.126; +L = 0.1; +Pr = 0.709; + +characteristic non-dimensional numbers are: +Gr = 1.4105E+06 +Ra = 1.0000E+06 +""" + +from numpy import sqrt, zeros + +from scrins.constants.boundary_conditions import DIRICHLET, NEUMANN, OUTLET +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.display.plot_isolines import plot_isolines +from scrins.discretization.cartesian_grid import cartesian_grid +from scrins.discretization.nodes import nodes +from scrins.discretization.create_unknown import create_unknown +from scrins.discretization.cfl_max import cfl_max +from scrins.discretization.calc_p import calc_p +from scrins.discretization.calc_t import calc_t +from scrins.discretization.calc_uvw import calc_uvw +from scrins.discretization.corr_uvw import corr_uvw +from scrins.discretization.vol_balance import vol_balance +from scrins.display.print_time_step import print_time_step + + +def main(show_plot=True): + """ + Docstring. + """ + + + # ========================================================================= + # + # Define problem + # + # ========================================================================= + + xn = nodes(0, 1, 64, 1.0 / 256, 1.0 / 256) + yn = nodes(0, 1, 64, 1.0 / 256, 1.0 / 256) + zn = nodes(0, 0.1, 5) + + # Cell dimensions + nx, ny, nz, dx, dy, dz, rc, ru, rv, rw = cartesian_grid(xn, yn, zn) + + # Set physical properties + grashof = 1.4105E+06 + prandtl = 0.7058 + rho = zeros(rc) + mu = zeros(rc) + kappa = zeros(rc) + cap = zeros(rc) + rho[:, :, :] = 1.0 + mu[:, :, :] = 1.0 / sqrt(grashof) + kappa[:, :, :] = 1.0 / (prandtl * sqrt(grashof)) + cap[:, :, :] = 1.0 + + # Time-stepping parameters + dt = 0.02 # time step + ndt = 1000 # number of time steps + + # Create unknowns; names, positions and sizes + uc = create_unknown('cell-u-vel', C, rc, DIRICHLET) + vc = create_unknown('cell-v-vel', C, rc, DIRICHLET) + wc = create_unknown('cell-w-vel', C, rc, DIRICHLET) + uf = create_unknown('face-u-vel', X, ru, DIRICHLET) + vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) + wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) + t = create_unknown('temperature', C, rc, NEUMANN) + p = create_unknown('pressure', C, rc, NEUMANN) + p_tot = zeros(rc) + + # This is a new test + t.bnd[W].typ[:] = DIRICHLET + t.bnd[W].val[:] = -0.5 + + t.bnd[E].typ[:] = DIRICHLET + t.bnd[E].val[:] = +0.5 + + for j in (B, T): + uc.bnd[j].typ[:] = NEUMANN + vc.bnd[j].typ[:] = NEUMANN + wc.bnd[j].typ[:] = NEUMANN + + obst = zeros(rc) + + # ========================================================================= + # + # Solution algorithm + # + # ========================================================================= + + # ----------- + # + # Time loop + # + # ----------- + for ts in range(1, ndt + 1): + + print_time_step(ts) + + # ------------------ + # Store old values + # ------------------ + t.old[:] = t.val[:] + uc.old[:] = uc.val[:] + vc.old[:] = vc.val[:] + wc.old[:] = wc.val[:] + + # ------------------------ + # Temperature (enthalpy) + # ------------------------ + calc_t(t, (uf, vf, wf), (rho * cap), kappa, dt, (dx, dy, dz), obst) + + # ----------------------- + # Momentum conservation + # ----------------------- + ef = zeros(rc), t.val, zeros(rc) + + calc_uvw((uc, vc, wc), (uf, vf, wf), rho, mu, + p_tot, ef, dt, (dx, dy, dz), obst) + + # ---------- + # Pressure + # ---------- + calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst) + + p_tot = p_tot + p.val + + # --------------------- + # Velocity correction + # --------------------- + corr_uvw((uc, vc, wc), p, rho, dt, (dx, dy, dz), obst) + corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst) + + # Compute volume balance for checking + err = vol_balance((uf, vf, wf), (dx, dy, dz), obst) + print('Maximum volume error after correction: %12.5e' % abs(err).max()) + + # Check the CFL number too + cfl = cfl_max((uc, vc, wc), dt, (dx, dy, dz)) + print('Maximum CFL number: %12.5e' % cfl) + + # ===================================================================== + # + # Visualisation + # + # ===================================================================== + if show_plot: + if ts % 20 == 0: + plot_isolines(t.val, (uc, vc, wc), (xn, yn, zn), Z) + +if __name__ == '__main__': + main() diff --git a/PYTHON/scrins/tests/test_thermally_driven_cavity_staggered.py b/PYTHON/scrins/tests/test_thermally_driven_cavity_staggered.py new file mode 100755 index 0000000..6c7821b --- /dev/null +++ b/PYTHON/scrins/tests/test_thermally_driven_cavity_staggered.py @@ -0,0 +1,175 @@ +#!/usr/bin/python + +""" +This program solves thermally driven cavity at Ra = 1.0e6, +in dimensional and non-dimensional forms. + +Equations in dimensional form: + +D(rho u)/Dt = nabla(mu (nabla u)^T) - nabla p + g +D(rho cp T)/Dt = nabla(lambda (nabla T)^T) + +Equations in non-dimensional form, for natural convection problems + +DU/Dt = nabla(1/sqrt(Gr) (nabla U)^T) - nabla P + theta +D theta/Dt = nabla(1/(Pr*sqrt(Gr)) (nabla theta)^T) + +-------------------------------------------------------------------------- +For thermally driven cavity, with properties of air at 60 deg: + +nu = 1.89035E-05; +beta = 0.003; +dT = 17.126; +L = 0.1; +Pr = 0.709; + +characteristic non-dimensional numbers are: +Gr = 1.4105E+06 +Ra = 1.0000E+06 +""" + +from numpy import sqrt, zeros + +from scrins.constants.boundary_conditions import DIRICHLET, NEUMANN, OUTLET +from scrins.constants.coordinates import X, Y, Z +from scrins.constants.compass import W, E, S, N, B, T, C +from scrins.display.plot_isolines import plot_isolines +from scrins.discretization.adj_n_bnds import adj_n_bnds +from scrins.discretization.cartesian_grid import cartesian_grid +from scrins.discretization.nodes import nodes +from scrins.discretization.create_unknown import create_unknown +from scrins.discretization.cfl_max import cfl_max +from scrins.discretization.calc_p import calc_p +from scrins.discretization.calc_t import calc_t +from scrins.discretization.calc_uvw import calc_uvw +from scrins.discretization.corr_uvw import corr_uvw +from scrins.discretization.vol_balance import vol_balance +from scrins.display.print_time_step import print_time_step +from scrins.operators.avg import avg +from scrins.operators.par import par + + +def main(show_plot=True): + """ + Docstring. + """ + + + # ========================================================================= + # + # Define problem + # + # ========================================================================= + + xn = nodes(0, 1, 64, 1.0 / 256, 1.0 / 256) + yn = nodes(0, 1, 64, 1.0 / 256, 1.0 / 256) + zn = nodes(0, 0.1, 5) + + # Cell dimensions + nx, ny, nz, dx, dy, dz, rc, ru, rv, rw = cartesian_grid(xn, yn, zn) + + # Set physical properties + grashof = 1.4105E+06 + prandtl = 0.7058 + rho = zeros(rc) + mu = zeros(rc) + kappa = zeros(rc) + cap = zeros(rc) + rho[:, :, :] = 1.0 + mu[:, :, :] = 1.0 / sqrt(grashof) + kappa[:, :, :] = 1.0 / (prandtl * sqrt(grashof)) + cap[:, :, :] = 1.0 + + # Time-stepping parameters + dt = 0.02 # time step + ndt = 1000 # number of time steps + + # Create unknowns; names, positions and sizes + uf = create_unknown('face-u-vel', X, ru, DIRICHLET) + vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) + wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) + t = create_unknown('temperature', C, rc, NEUMANN) + p = create_unknown('pressure', C, rc, NEUMANN) + p_tot = zeros(rc) + + # This is a new test + t.bnd[W].typ[:] = DIRICHLET + t.bnd[W].val[:] = -0.5 + + t.bnd[E].typ[:] = DIRICHLET + t.bnd[E].val[:] = +0.5 + + for j in (B, T): + uf.bnd[j].typ[:] = NEUMANN + vf.bnd[j].typ[:] = NEUMANN + wf.bnd[j].typ[:] = NEUMANN + + obst = zeros(rc) + + # ========================================================================= + # + # Solution algorithm + # + # ========================================================================= + + # ----------- + # + # Time loop + # + # ----------- + for ts in range(1, ndt + 1): + + print_time_step(ts) + + # ------------------ + # Store old values + # ------------------ + t.old[:] = t.val[:] + uf.old[:] = uf.val[:] + vf.old[:] = vf.val[:] + wf.old[:] = wf.val[:] + + # ------------------------ + # Temperature (enthalpy) + # ------------------------ + calc_t(t, (uf, vf, wf), (rho * cap), kappa, dt, (dx, dy, dz), obst) + + # ----------------------- + # Momentum conservation + # ----------------------- + ef = zeros(ru), avg(Y, t.val), zeros(rw) + + calc_uvw((uf, vf, wf), (uf, vf, wf), rho, mu, \ + p_tot, ef, dt, (dx, dy, dz), obst) + + # ---------- + # Pressure + # ---------- + calc_p(p, (uf, vf, wf), rho, dt, (dx, dy, dz), obst) + + p_tot = p_tot + p.val + + # --------------------- + # Velocity correction + # --------------------- + corr_uvw((uf, vf, wf), p, rho, dt, (dx, dy, dz), obst) + + # Compute volume balance for checking + err = vol_balance((uf, vf, wf), (dx, dy, dz), obst) + print('Maximum volume error after correction: %12.5e' % abs(err).max()) + + # Check the CFL number too + cfl = cfl_max((uf, vf, wf), dt, (dx, dy, dz)) + print('Maximum CFL number: %12.5e' % cfl) + + # ===================================================================== + # + # Visualisation + # + # ===================================================================== + if show_plot: + if ts % 20 == 0: + plot_isolines(t.val, (uf, vf, wf), (xn, yn, zn), Z) + +if __name__ == '__main__': + main() diff --git a/PYTHON/standard.py b/PYTHON/standard.py deleted file mode 100644 index a8cc918..0000000 --- a/PYTHON/standard.py +++ /dev/null @@ -1,40 +0,0 @@ -# Standard modules used -from collections import namedtuple -from math import ceil, \ - floor, \ - factorial, \ - pi, \ - sqrt -from matplotlib import pyplot as plt -from matplotlib import cm -from random import random -from scipy import logical_not as lnot -from scipy import minimum as mn -from scipy import maximum as mx -from scipy import array, \ - append, \ - concatenate, \ - copy, \ - cos, \ - delete, \ - dot, \ - empty, \ - linspace, \ - log, \ - log2, \ - log10, \ - matrix, \ - meshgrid, \ - ndarray, \ - ones, \ - outer, \ - prod, \ - sin, \ - reshape, \ - tile, \ - transpose, \ - zeros -from scipy.linalg import solve -from scipy.sparse import spdiags -from scipy.sparse.linalg import bicgstab, \ - spsolve \ No newline at end of file diff --git a/PYTHON/test-advection-1D.py b/PYTHON/test-advection-1D.py deleted file mode 100644 index 2915025..0000000 --- a/PYTHON/test-advection-1D.py +++ /dev/null @@ -1,144 +0,0 @@ -#========================================================================== -# Program to test implementation of advection schemes in the code, using -# one-dimensoinal transport of a step function in X, Y or Z -# direction, either in positive or negative sense. -# -# The coordinate direction is specified with the local variable "TEST", -# which can be either X, Y or Z. -# -# Sense is specified with the variable "FLOW", which can assume values 'p' -# for positive, and 'n' for negative sense. -#-------------------------------------------------------------------------- - -#!/usr/bin/python - -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * -from Display.all import * -from Discretization.all import * - -#========================================================================== -# -# Define problem -# -#========================================================================== - -sens = -1, +1 -test = X, Y, Z -SENS = sens[ floor( random() * len(sens) ) ] -TEST = test[ floor( random() * len(test) ) ] -MIN = 10 -MAX = 20 - -uvw_bulk = SENS, 0.0, 0.0 -xn = nodes(0, 1, 200) -yn = nodes(0, 0.1, 4) -zn = nodes(0, 0.1, 4) -if TEST == Y: - uvw_bulk = 0.0, SENS, 0.0 - xn = nodes(0, 0.1, 4) - yn = nodes(0, 1, 200) - zn = nodes(0, 0.1, 4) -elif TEST == Z: - uvw_bulk = 0.0, 0.0, SENS - xn = nodes(0, 0.1, 4) - yn = nodes(0, 0.1, 4) - zn = nodes(0, 1, 200) - -# Set domain dimensions and grid resolution - -# Cell dimensions -nx,ny,nz, dx,dy,dz, rc,ru,rv,rw = cartesian_grid(xn,yn,zn) - -# Set physical properties -rho = zeros(rc) -mu = zeros(rc) -kappa = zeros(rc) -cap = zeros(rc) -rho [:,:,:] = 1.0 -mu [:,:,:] = 0.0 -kappa[:,:,:] = 0.0 -cap [:,:,:] = 1.0 - -# Time-stepping parameters -dt = 0.002; # time step -ndt = 350; # number of time steps - -# Create unknowns; names, positions and sizes -uf = create_unknown('face-u-vel', X, ru, DIRICHLET) -vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) -wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) -t = create_unknown('temperature', C, rc, NEUMANN) - -# Make a tuple with all velocity components -uvwf = uf, vf, wf - -# Specify inital and boundary conditions -t.val[:] = MIN -if TEST == X: - t.val[nx/2-25:nx/2+25,:,:] = MAX -elif TEST == Y: - t.val[:,ny/2-25:ny/2+25,:] = MAX -elif TEST == Z: - t.val[:,:,nz/2-25:nz/2+25] = MAX - -adj_n_bnds(t) - -# This is from the advection-1D case -for i in (X,Y,Z): - uvwf[i].val[:,:,:] = uvw_bulk[i] - for j in (W,E,S,N,B,T): - uvwf[i].bnd[j].val[:,:,:] = uvw_bulk[i] - -obst = zeros(rc) - -#========================================================================== -# -# Solution algorithm -# -#========================================================================== - -#----------- -# -# Time loop -# -#----------- -for ts in range(1,40): - - print_time_step(ts) - - #------------------ - # Store old values - #------------------ - t.old[:] = t.val[:] - - #------------------------ - # Temperature (enthalpy) - #------------------------ - calc_t(t, uvwf, (rho*cap), kappa, dt, (dx,dy,dz), obst) - -#========================================================================== -# -# Visualisation -# -#========================================================================== -from matplotlib import pyplot as plt - -st = 'ro' -xc = avg(xn) -vc = t.val[:,ny/2,nz/2] -if TEST == Y: - st = 'go' - xc = avg(yn) - vc = t.val[nx/2,:,nz/2] -elif TEST == Z: - st = 'bo' - xc = avg(zn) - vc = t.val[nx/2,ny/2,:] - -plt.plot(xc, vc, st) -plt.show() diff --git a/PYTHON/test-inlet-outlet.py b/PYTHON/test-inlet-outlet.py deleted file mode 100644 index 2198af1..0000000 --- a/PYTHON/test-inlet-outlet.py +++ /dev/null @@ -1,220 +0,0 @@ -#========================================================================== -# This scripts tests inlet and outlet conditons at various places in -# computational domain. -# -# Computational domain is a simple box, and Reynolds number is rather -# small to avoid instabilities due to vortices getting out from the -# outlet. The script selects the case it will run randomply, from the -# 16 predefined cases. -#-------------------------------------------------------------------------- - -#!/usr/bin/python - -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * -from Display.all import * -from Discretization.all import * -from PhysicalModels.all import properties_for_air - -#========================================================================== -# -# Define problem -# -#========================================================================== - -planes = ('XY', 'XZ', 'YZ') -tests = array([11,12,13,14, 21,22,23,24, 31,32,33,34, 41,42,43,44]) -TEST = tests[ floor(random()*16) ] -PLANE = planes[ floor(random()*3) ] - -# Node coordinates -xn = nodes(0, 1, 160) -yn = nodes(0, 1, 160) -zn = nodes(0, 0.025, 4) - -# Cell coordinates -xc = avg(xn) -yc = avg(yn) -zc = avg(zn) - -# Cell dimensions -nx,ny,nz, dx,dy,dz, rc,ru,rv,rw = cartesian_grid(xn,yn,zn) - -# Set physical properties -rho, mu, cap, kappa = properties_for_air(rc) - -# Time-stepping parameters -dt = 0.15 # time step -ndt = 200 # number of time steps - -# Create unknowns names, positions and sizes -uf = create_unknown('face-u-vel', X, ru, DIRICHLET) -vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) -wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) -p = create_unknown('pressure', C, rc, NEUMANN) - -print(TEST) - -# Specify boundary conditions -if TEST == 11: - for k in range(0,nz): - uf.bnd[W].val[0,ny/4:3*ny/4,k] = +par(0.01, yn[ny/4:3*ny/4+1]) - uf.bnd[E].typ[0,ny/4:3*ny/4,k] = OUTLET - -elif TEST == 12: # vertical mirror from 11 - for k in range(0,nz): - uf.bnd[E].val[0,ny/4:3*ny/4,k] = -par(0.01, yn[ny/4:3*ny/4+1]) - uf.bnd[W].typ[0,ny/4:3*ny/4,k] = OUTLET - -elif TEST == 13: # rotate 11 - for k in range(0,nz): - vf.bnd[S].val[nx/4:3*nx/4,0,k] = +par(0.01, xn[nx/4:3*nx/4+1]) - vf.bnd[N].typ[nx/4:3*nx/4,0,k] = OUTLET - -elif TEST == 14: # horizontal mirror 13 - for k in range(0,nz): - vf.bnd[N].val[nx/4:3*nx/4,0,k] = -par(0.01, xn[nx/4:3*nx/4+1]) - vf.bnd[S].typ[nx/4:3*nx/4,0,k] = OUTLET - -elif TEST == 21: # 2 exits - for k in range(0,nz): - uf.bnd[W].val[0, ny/4:3*ny/4,k] = +par(0.01, yn[ny/4:3*ny/4+1]) - uf.bnd[E].typ[0, 0:ny/4,k] = OUTLET - uf.bnd[E].typ[0,3*ny/4:ny, k] = OUTLET - -elif TEST == 22: # vertical mirror 21 - for k in range(0,nz): - uf.bnd[E].val[0, ny/4:3*ny/4,k] = -par(0.01, yn[ny/4:3*ny/4+1]) - uf.bnd[W].typ[0, 0:ny/4,k] = OUTLET - uf.bnd[W].typ[0,3*ny/4:ny, k] = OUTLET - -elif TEST == 23: # rotated 21 - for k in range(0,nz): - vf.bnd[S].val[ nx/4:3*nx/4,0,k] = +par(0.01, xn[nx/4:3*nx/4+1]) - vf.bnd[N].typ[ :nx/4,0,k] = OUTLET - vf.bnd[N].typ[3*nx/4:nx, 0,k] = OUTLET - -elif TEST == 24: # horizontal mirror of 23 - for k in range(0,nz): - vf.bnd[N].val[ nx/4:3*nx/4,0,k] = -par(0.01, xn[nx/4:3*nx/4+1]) - vf.bnd[S].typ[ :nx/4,0,k] = OUTLET - vf.bnd[S].typ[3*nx/4:nx, 0,k] = OUTLET - -elif TEST == 31: # inlet and outlet at the same face - for k in range(0,nz): - uf.bnd[W].val[0,3*ny/4:ny, k] = +par(0.01, yn[3*ny/4:ny+1]) - uf.bnd[W].typ[0, :ny/4,k] = OUTLET - -elif TEST == 32: # vertical mirror of 31 - for k in range(0,nz): - uf.bnd[E].val[0,3*ny/4:ny, k] = -par(0.01, yn[3*ny/4:ny+1]) - uf.bnd[E].typ[0, 0:ny/4,k] = OUTLET - -elif TEST == 33: # rotated 31 - for k in range(0,nz): - vf.bnd[S].val[3*nx/4:nx, 0,k] = +par(0.01, xn[3*nx/4:nx+1]) - vf.bnd[S].typ[ :nx/4,0,k] = OUTLET - -elif TEST == 34: # horizontal mirror of 33 - for k in range(0,nz): - vf.bnd[N].val[3*nx/4:nx, 0,k] = -par(0.01, xn[3*nx/4:nx+1]) - vf.bnd[N].typ[ :nx/4,0,k] = OUTLET - -elif TEST == 41: # inlet and outlet at the same face, one more outlet - for k in range(0,nz): - uf.bnd[W].val[0,3*ny/4:ny, k] = +par(0.01, yn[3*ny/4:ny+1]) - uf.bnd[W].typ[0, :ny/8,k] = OUTLET - uf.bnd[E].typ[0, :ny/8,k] = OUTLET - -elif TEST == 42: # vertical mirror of 41 - for k in range(0,nz): - uf.bnd[E].val[0,3*ny/4:ny, k] = -par(0.01, yn[3*ny/4:ny+1]) - uf.bnd[E].typ[0, :ny/8,k] = OUTLET - uf.bnd[W].typ[0, :ny/8,k] = OUTLET - -elif TEST == 43: # rotated 41 - for k in range(0,nz): - vf.bnd[S].val[3*nx/4:nx, 0,k] = +par(0.01, xn[3*nx/4:nx+1]) - vf.bnd[S].typ[ 0:nx/8,0,k] = OUTLET - vf.bnd[N].typ[ 0:nx/8,0,k] = OUTLET - -elif TEST == 44: # horizontal mirror of 43 - for k in range(0,nz): - vf.bnd[N].val[3*ny/4:nx, 0,k] = -par(0.01, xn[3*nx/4:nx+1]) - vf.bnd[N].typ[ :nx/8,0,k] = OUTLET - vf.bnd[S].typ[ :nx/8,0,k] = OUTLET - -for j in (B,T): - uf.bnd[j].typ[:] = NEUMANN - vf.bnd[j].typ[:] = NEUMANN - wf.bnd[j].typ[:] = NEUMANN - -# Create a cylindrical obstacle in the middle just for kicks -obst = zeros(rc) -for k in range(0,nz): - for j in range(0,ny): - for i in range(0,nx): - dist = sqrt( (j-ny/2+1)**2 + (i-nx/2+1)**2 ) - if dist < ny/4: - obst[i,j,k] = 1 - -#========================================================================== -# -# Solution algorithm -# -#========================================================================== - -#----------- -# -# Time loop -# -#----------- -for ts in range(1,ndt+1): - - print_time_step(ts) - - #------------------ - # Store old values - #------------------ - uf.old[:] = uf.val[:] - vf.old[:] = vf.val[:] - wf.old[:] = wf.val[:] - - #----------------------- - # Momentum conservation - #----------------------- - ef = zeros(ru), zeros(rv), zeros(rw) - - calc_uvw((uf,vf,wf), (uf,vf,wf), rho, mu, \ - zeros(rc), ef, dt, (dx,dy,dz), obst) - - #---------- - # Pressure - #---------- - calc_p(p, (uf,vf,wf), rho, dt, (dx,dy,dz), obst) - - #--------------------- - # Velocity correction - #--------------------- - corr_uvw((uf,vf,wf), p, rho, dt, (dx,dy,dz), obst) - - # Compute volume balance for checking - err = vol_balance((uf,vf,wf), (dx,dy,dz), obst) - print('Maximum volume error after correction: %12.5e' % abs(err).max()) - - # Check the CFL number too - cfl = cfl_max((uf,vf,wf), dt, (dx,dy,dz)) - print('Maximum CFL number: %12.5e' % cfl) - -#========================================================================== -# -# Visualisation -# -#========================================================================== - - if ts % 10 == 0: - plot_isolines(p.val, (uf,vf,wf), (xn,yn,zn), Z) diff --git a/PYTHON/test-membrane-staggered.py b/PYTHON/test-membrane-staggered.py deleted file mode 100644 index 0fb088e..0000000 --- a/PYTHON/test-membrane-staggered.py +++ /dev/null @@ -1,220 +0,0 @@ -#========================================================================== -# Demonstrates the membrane for Kerstin. Two domains are computed -# independently, but linked through boundary conditions in an inner loop -# within each time step. This seems the most practical approach of all -# because the membrane model implementations are very obvious, at one -# place, in the main function. The convergence of the conditions at the -# membrane seems to be rather fast too. -#-------------------------------------------------------------------------- - -#!/usr/bin/python - -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * -from Display.all import * -from Discretization.all import * -from PhysicalModels.all import * - -#========================================================================== -# -# Define problem -# -#========================================================================== - -AIR = 0 -H2O = 1 - -# Node coordinates for both domains -xn = (nodes(0, 0.1, 80), nodes(0, 0.1, 80)) -yn = (nodes(0, 0.01, 20), nodes(0.01, 0.03, 30)) -zn = (nodes(0, 0.1, 80), nodes(0, 0.1, 80)) - -# Cell coordinates -xc = (avg(xn[AIR]), avg(xn[H2O])) -yc = (avg(yn[AIR]), avg(yn[H2O])) -zc = (avg(zn[AIR]), avg(zn[H2O])) - -# Cell dimensions -cell = [cartesian_grid(xn[AIR],yn[AIR],zn[AIR]), \ - cartesian_grid(xn[H2O],yn[H2O],zn[H2O])] - -nx,ny,nz, dx,dy,dz = (cell[AIR][0], cell[H2O][0]), \ - (cell[AIR][1], cell[H2O][1]), \ - (cell[AIR][2], cell[H2O][2]), \ - (cell[AIR][3], cell[H2O][3]), \ - (cell[AIR][4], cell[H2O][4]), \ - (cell[AIR][5], cell[H2O][5]) -rc,ru,rv,rw = (cell[AIR][6], cell[H2O][6]), \ - (cell[AIR][7], cell[H2O][7]), \ - (cell[AIR][8], cell[H2O][8]), \ - (cell[AIR][9], cell[H2O][9]) - -# Set physical properties -prop = [properties_for_air(rc[AIR]), properties_for_water(rc[H2O])] -rho, mu, cap, kappa = (prop[AIR][0], prop[H2O][0]), \ - (prop[AIR][1], prop[H2O][1]), \ - (prop[AIR][2], prop[H2O][2]), \ - (prop[AIR][3], prop[H2O][3]) - -# Time-stepping parameters -dt = 0.004 # time step -ndt = 1000 # number of time steps - -# Create unknowns; names, positions and sizes -uf = [create_unknown('face-u-vel', X, ru[AIR], DIRICHLET), \ - create_unknown('face-u-vel', X, ru[H2O], DIRICHLET)] -vf = [create_unknown('face-v-vel', Y, rv[AIR], DIRICHLET), \ - create_unknown('face-v-vel', Y, rv[H2O], DIRICHLET)] -wf = [create_unknown('face-w-vel', Z, rw[AIR], DIRICHLET), \ - create_unknown('face-w-vel', Z, rw[H2O], DIRICHLET)] -p = [create_unknown('pressure', C, rc[AIR], NEUMANN), \ - create_unknown('pressure', C, rc[H2O], NEUMANN)] -t = [create_unknown('temperature', C, rc[AIR], NEUMANN), \ - create_unknown('temperature', C, rc[H2O], NEUMANN)] -p_tot = [zeros(rc[AIR]), zeros(rc[H2O])] - -# Specify boundary conditions -for k in range(0,nz[AIR]): - vf[AIR].bnd[N].val[:,:1,k]=-0.005 -uf[AIR].bnd[E].typ[:1,:,:] = OUTLET -uf[AIR].bnd[E].val[:1,:,:] = 0.1 - -for k in range(0,nz[H2O]): - uf[H2O].bnd[W].val[:1,:,k] = par(0.1, yn[H2O]) -uf[H2O].bnd[E].typ[:1,:,:] = OUTLET -uf[H2O].bnd[E].val[:1,:,:] = 0.1 - -for c in range(AIR,H2O): - for j in (B,T): - uf[c].bnd[j].typ[:] = NEUMANN - vf[c].bnd[j].typ[:] = NEUMANN - wf[c].bnd[j].typ[:] = NEUMANN - -t[AIR].bnd[S].typ[:,:1,:] = DIRICHLET -t[AIR].bnd[S].val[:,:1,:] = 60 -t[AIR].bnd[N].typ[:,:1,:] = DIRICHLET -t[AIR].bnd[N].val[:,:1,:] = 70 - -t[H2O].bnd[W].typ[:1,:,:] = DIRICHLET -t[H2O].bnd[W].val[:1,:,:] = 80 -t[H2O].bnd[S].typ[:,:1,:] = DIRICHLET -t[H2O].bnd[S].val[:,:1,:] = 70 - -t[AIR].val[:,:,:] = 50; -t[H2O].val[:,:,:] = 70; - -for c in (AIR,H2O): - adj_n_bnds(p[c]) - adj_n_bnds(t[c]) - -obst = [zeros(rc[AIR]), zeros(rc[H2O])] - -#========================================================================== -# -# Solution algorithm -# -#========================================================================== - -#----------- -# -# Time loop -# -#----------- -for ts in range(1,ndt+1): - - print_time_step(ts) - - #------------------ - # Store old values - #------------------ - for c in (AIR,H2O): - t[c].old[:] = t[c].val - uf[c].old[:] = uf[c].val - vf[c].old[:] = vf[c].val - wf[c].old[:] = wf[c].val - - #------------------------ - # Temperature (enthalpy) - #------------------------ - - # Compute old temperature of the membrane - const = kappa[H2O][:, :1,:] * dy[AIR][:,-1:,:] \ - / kappa[AIR][:,-1:,:] / dy[H2O][:, :1,:] - t_mem_old = (const * t[H2O].val[:,:1,:] + t[AIR].val[:,-1:,:]) \ - / (1+const) - - while True: - for c in (AIR,H2O): - calc_t(t[c], (uf[c],vf[c],wf[c]), (rho[c]*cap[c]), kappa[c], \ - dt, (dx[c],dy[c],dz[c]), obst[c]) - - # Compute new temperature of the membrane - const = kappa[H2O][:, :1,:] * dy[AIR][:,-1:,:] \ - / kappa[AIR][:,-1:,:] / dy[H2O][:, :1,:] - t_mem = (const * t[H2O].val[:,:1,:] + t[AIR].val[:,-1:,:]) \ - / (1+const) - - # Update boundary conditions with membrane's temperature - t[H2O].bnd[S].val[:,:1,:] = t_mem - t[AIR].bnd[N].val[:,:1,:] = t_mem - - # Check if convergence has been reached - eps = abs(t_mem-t_mem_old).max() - print('Maximum temperature error in the membrane = %5.3e' % eps) - if eps < 0.001: - break - - t_mem_old = t_mem - - #----------------------- - # Momentum conservation - #----------------------- - for c in (AIR,H2O): - g_v = -G * avg(Y, rho[c]) - - ef = zeros(ru[c]), g_v, zeros(rw[c]) - - calc_uvw((uf[c],vf[c],wf[c]), (uf[c],vf[c],wf[c]), rho[c], mu[c], \ - p_tot[c], ef, dt, (dx[c],dy[c],dz[c]), obst[c]) - - #---------- - # Pressure - #---------- - for c in (AIR,H2O): - calc_p(p[c], (uf[c],vf[c],wf[c]), rho[c], \ - dt, (dx[c],dy[c],dz[c]), obst[c]) - - p_tot[c] = p_tot[c] + p[c].val - - #--------------------- - # Velocity correction - #--------------------- - for c in (AIR,H2O): - corr_uvw((uf[c],vf[c],wf[c]), p[c], rho[c], \ - dt, (dx[c],dy[c],dz[c]), obst[c]) - - # Compute volume balance for checking - for c in (AIR,H2O): - err = vol_balance((uf[c],vf[c],wf[c]), \ - (dx[c],dy[c],dz[c]), obst[c]) - print('Maximum volume error after correction: %12.5e' % abs(err).max()) - - # Check the CFL number too - for c in (AIR,H2O): - cfl = cfl_max((uf[c],vf[c],wf[c]), dt, (dx[c],dy[c],dz[c])) - print('Maximum CFL number: %12.5e' % cfl) - -#========================================================================== -# -# Visualisation -# -#========================================================================== - - if ts % 100 == 0: - for c in (AIR,H2O): - plot_isolines(t[c].val, (uf[c],vf[c],wf[c]), (xn[c],yn[c],zn[c]), Z) - plot_isolines(p_tot[c], (uf[c],vf[c],wf[c]), (xn[c],yn[c],zn[c]), Z) diff --git a/PYTHON/test-obstacles-collocated.py b/PYTHON/test-obstacles-collocated.py deleted file mode 100644 index 2bc7c3e..0000000 --- a/PYTHON/test-obstacles-collocated.py +++ /dev/null @@ -1,152 +0,0 @@ -#========================================================================== -# o ... scalars -# (n) - ... u velocities -# | ... v velocities -# +-------+-------+-------+-------+-------+ -# | | | | | | -# | o - o - o - o - o | j=ny -# | | | | | | -# +---|---+---|---+---|---+---|---+---|---+ j=nym -# | | | | | | -# | o - o - o - o - o | ... -# | | | | | | -# (w) +---|---+---|---+---|---+---|---+---|---+ j=2 (e) -# | | | | | | -# | o - o - o - o - o | j=2 -# | | | | | | -# +---|---+---|---+---|---+---|---+---|---+ j=1 (v-velocity) -# | | | | | | -# | o - o - o - o - o | j=1 (scalar cell) -# | | | | | | -# +-------+-------+-------+-------+-------+ -# y i=1 i=2 ... ... i=nx (scalar cells) -# ^ i=1 i=2 ... i=nxm (u-velocity cells) -# | -# +---> x (s) -# -#-------------------------------------------------------------------------- - -#!/usr/bin/python - -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * -from Display.all import * -from Discretization.all import * -from PhysicalModels.all import * - -#========================================================================== -# -# Define problem -# -#========================================================================== - -# Node coordinates -xn = nodes(0, 1, 256) -yn = nodes(0, 0.125, 32) -zn = nodes(0, 0.125, 4) - -# Cell coordinates -xc = avg(xn) -yc = avg(yn) -zc = avg(zn) - -# Cell dimensions -nx,ny,nz, dx,dy,dz, rc,ru,rv,rw = cartesian_grid(xn,yn,zn) - -# Set physical properties -rho, mu, cap, kappa = properties_for_air(rc) - -# Time-stepping parameters -dt = 0.002 # time step -ndt = 5000 # number of time steps - -# Create unknowns; names, positions and sizes -uc = create_unknown('cell-u-vel', C, rc, DIRICHLET) -vc = create_unknown('cell-v-vel', C, rc, DIRICHLET) -wc = create_unknown('cell-w-vel', C, rc, DIRICHLET) -uf = create_unknown('face-u-vel', X, ru, DIRICHLET) -vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) -wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) -p = create_unknown('pressure', C, rc, NEUMANN) - -# Specify boundary conditions -uc.bnd[W].typ[:1,:,:] = DIRICHLET -for k in range(0,nz): - uc.bnd[W].val[:1,:,k] = par(0.1, yn) - -uc.bnd[E].typ[:1,:,:] = OUTLET - -for j in (B,T): - uf.bnd[j].typ[:] = NEUMANN - vf.bnd[j].typ[:] = NEUMANN - wf.bnd[j].typ[:] = NEUMANN - -adj_n_bnds(p) - -obst = zeros(rc) -for j in range(0, 24): - for i in range(64+j, 64+24): - for k in range(0,nz): - obst[i,j,k] = 1 - -#========================================================================== -# -# Solution algorithm -# -#========================================================================== - -#----------- -# -# Time loop -# -#----------- -for ts in range(1,ndt+1): - - print_time_step(ts) - - #------------------ - # Store old values - #------------------ - uc.old[:] = uc.val[:] - vc.old[:] = vc.val[:] - wc.old[:] = wc.val[:] - - #----------------------- - # Momentum conservation - #----------------------- - ef = zeros(rc), zeros(rc), zeros(rc) - - calc_uvw((uc,vc,wc), (uf,vf,wf), rho, mu, - zeros(rc), ef, dt, (dx,dy,dz), obst) - - #---------- - # Pressure - #---------- - calc_p(p, (uf,vf,wf), rho, dt, (dx,dy,dz), obst) - - #--------------------- - # Velocity correction - #--------------------- - corr_uvw((uc,vc,wc), p, rho, dt, (dx,dy,dz), obst) - corr_uvw((uf,vf,wf), p, rho, dt, (dx,dy,dz), obst) - - # Compute volume balance for checking - err = vol_balance((uf,vf,wf), (dx,dy,dz), obst) - print('Maximum volume error after correction: %12.5e' % abs(err).max()) - - # Check the CFL number too - cfl = cfl_max((uc,vc,wc), dt, (dx,dy,dz)) - print('Maximum CFL number: %12.5e' % cfl) - -#========================================================================== -# -# Visualisation -# -#========================================================================== - - if ts % 20 == 0: - plot_isolines(p.val, (uc,vc,wc), (xn,yn,zn), Z) diff --git a/PYTHON/test-obstacles-staggered.py b/PYTHON/test-obstacles-staggered.py deleted file mode 100644 index 187fea3..0000000 --- a/PYTHON/test-obstacles-staggered.py +++ /dev/null @@ -1,148 +0,0 @@ -#========================================================================== -# o ... scalars -# (n) - ... u velocities -# | ... v velocities -# +-------+-------+-------+-------+-------+ -# | | | | | | -# | o - o - o - o - o | j=ny -# | | | | | | -# +---|---+---|---+---|---+---|---+---|---+ j=nym -# | | | | | | -# | o - o - o - o - o | ... -# | | | | | | -# (w) +---|---+---|---+---|---+---|---+---|---+ j=2 (e) -# | | | | | | -# | o - o - o - o - o | j=2 -# | | | | | | -# +---|---+---|---+---|---+---|---+---|---+ j=1 (v-velocity) -# | | | | | | -# | o - o - o - o - o | j=1 (scalar cell) -# | | | | | | -# +-------+-------+-------+-------+-------+ -# y i=1 i=2 ... ... i=nx (scalar cells) -# ^ i=1 i=2 ... i=nxm (u-velocity cells) -# | -# +---> x (s) -# -#-------------------------------------------------------------------------- - -#!/usr/bin/python - -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * -from Display.all import * -from Discretization.all import * -from PhysicalModels.all import * - -#========================================================================== -# -# Define problem -# -#========================================================================== - -# Node coordinates -xn = nodes(0, 1, 256) -yn = nodes(0, 0.125, 32) -zn = nodes(0, 0.125, 4) - -# Cell coordinates -xc = avg(xn) -yc = avg(yn) -zc = avg(zn) - -# Cell dimensions -nx,ny,nz, dx,dy,dz, rc,ru,rv,rw = cartesian_grid(xn,yn,zn) - -# Set physical properties -rho, mu, cap, kappa = properties_for_air(rc) - -# Time-stepping parameters -dt = 0.002 # time step -ndt = 5000 # number of time steps - -# Create unknowns; names, positions and sizes -uf = create_unknown('face-u-vel', X, ru, DIRICHLET) -vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) -wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) -p = create_unknown('pressure', C, rc, NEUMANN) - -# Specify boundary conditions -uf.bnd[W].typ[:1,:,:] = DIRICHLET -for k in range(0,nz): - uf.bnd[W].val[:1,:,k] = par(0.1, yn) - -uf.bnd[E].typ[:1,:,:] = OUTLET - -for j in (B,T): - uf.bnd[j].typ[:] = NEUMANN - vf.bnd[j].typ[:] = NEUMANN - wf.bnd[j].typ[:] = NEUMANN - -adj_n_bnds(p) - -obst = zeros(rc) -for j in range(0, 24): - for i in range(64+j, 64+24): - for k in range(0,nz): - obst[i,j,k] = 1 - -#========================================================================== -# -# Solution algorithm -# -#========================================================================== - -#----------- -# -# Time loop -# -#----------- -for ts in range(1,ndt+1): - - print_time_step(ts) - - #------------------ - # Store old values - #------------------ - uf.old[:] = uf.val[:] - vf.old[:] = vf.val[:] - wf.old[:] = wf.val[:] - - #----------------------- - # Momentum conservation - #----------------------- - ef = zeros(ru), zeros(rv), zeros(rw) - - calc_uvw((uf,vf,wf), (uf,vf,wf), rho, mu, \ - zeros(rc), ef, dt, (dx,dy,dz), obst) - - #---------- - # Pressure - #---------- - calc_p(p, (uf,vf,wf), rho, dt, (dx,dy,dz), obst) - - #--------------------- - # Velocity correction - #--------------------- - corr_uvw((uf,vf,wf), p, rho, dt, (dx,dy,dz), obst) - - # Compute volume balance for checking - err = vol_balance((uf,vf,wf), (dx,dy,dz), obst) - print('Maximum volume error after correction: %12.5e' % abs(err).max()) - - # Check the CFL number too - cfl = cfl_max((uf,vf,wf), dt, (dx,dy,dz)) - print('Maximum CFL number: %12.5e' % cfl) - -#========================================================================== -# -# Visualisation -# -#========================================================================== - - if ts % 20 == 0: - plot_isolines(p.val, (uf,vf,wf), (xn,yn,zn), Z) diff --git a/PYTHON/test-obstacles-thinner-staggered.py b/PYTHON/test-obstacles-thinner-staggered.py deleted file mode 100644 index d01e048..0000000 --- a/PYTHON/test-obstacles-thinner-staggered.py +++ /dev/null @@ -1,190 +0,0 @@ -#========================================================================== -# o ... scalars -# (n) - ... u velocities -# | ... v velocities -# +-------+-------+-------+-------+-------+ -# | | | | | | -# | o - o - o - o - o | j=ny -# | | | | | | -# +---|---+---|---+---|---+---|---+---|---+ j=nym -# | | | | | | -# | o - o - o - o - o | ... -# | | | | | | -# (w) +---|---+---|---+---|---+---|---+---|---+ j=2 (e) -# | | | | | | -# | o - o - o - o - o | j=2 -# | | | | | | -# +---|---+---|---+---|---+---|---+---|---+ j=1 (v-velocity) -# | | | | | | -# | o - o - o - o - o | j=1 (scalar cell) -# | | | | | | -# +-------+-------+-------+-------+-------+ -# y i=1 i=2 ... ... i=nx (scalar cells) -# ^ i=1 i=2 ... i=nxm (u-velocity cells) -# | -# +---> x (s) -# -#-------------------------------------------------------------------------- - -#!/usr/bin/python - -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * -from Display.all import * -from Discretization.all import * -from PhysicalModels.all import * - -#========================================================================== -# -# Define problem -# -#========================================================================== - -# Node coordinates -xn = nodes(0, 1.25, 256) -yn = nodes(0, 0.125, 32) -zn = nodes(0, 0.125, 32) - -# Cell coordinates -xc = avg(xn) -yc = avg(yn) -zc = avg(zn) - -# Cell dimensions -nx,ny,nz, dx,dy,dz, rc,ru,rv,rw = cartesian_grid(xn,yn,zn) - -# Set physical properties -rho, mu, cap, kappa = properties_for_air(rc) - -# Time-stepping parameters -dt = 0.005 # time step -ndt = 2000 # number of time steps - -# Create unknowns; names, positions and sizes -uf = create_unknown('face-u-vel', X, ru, DIRICHLET) -vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) -wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) -p = create_unknown('pressure', C, rc, NEUMANN) - -# Specify boundary conditions -uf.bnd[W].typ[:1,:,:] = DIRICHLET -uf.bnd[W].val[:1,:,:] = 0.1 * outer( par(1.0, yn), par(1.0, zn) ) - -uf.bnd[E].typ[:1,:,:] = OUTLET - -for j in (B,T): - uf.bnd[j].typ[:] = NEUMANN - vf.bnd[j].typ[:] = NEUMANN - wf.bnd[j].typ[:] = NEUMANN - -adj_n_bnds(p) - -# Create obstacles -obst = zeros(rc) - -class key: - ip = -1 - im = -1 - jp = -1 - jm = -1 - kp = -1 - km = -1 - -block = (key(), key(), key(), key()); - -th = 5; -block[0].im = 3*nx/16 # i minus -block[0].ip = block[0].im + th # i plus -block[0].jm = 0 # j minus -block[0].jp = 3*ny/4 # j plus -block[0].km = 0 # k minus -block[0].kp = 3*ny/4 # k plus - -block[1].im = 5*nx/16 # i minus -block[1].ip = block[1].im + th # i plus -block[1].jm = ny/4 # j minus -block[1].jp = ny # j plus -block[1].km = ny/4 # k minus -block[1].kp = ny # k plus - -block[2].im = 7*nx/16 # i minus -block[2].ip = block[2].im + th # i plus -block[2].jm = 0 # j minus -block[2].jp = 3*ny/4 # j plus -block[2].km = 0 # k minus -block[2].kp = 3*ny/4 # k plus - -block[3].im = 9*nx/16 # i minus -block[3].ip = block[3].im + th # i plus -block[3].jm = ny/4 # j minus -block[3].jp = ny # j plus -block[3].km = ny/4 # k minus -block[3].kp = ny # k plus - -for o in range(0, 4): - for i in range(floor(block[o].im), floor(block[o].ip)): - for j in range(floor(block[o].jm), floor(block[o].jp)): - for k in range(floor(block[o].km), floor(block[o].kp)): - obst[i,j,k] = 1 - -#========================================================================== -# -# Solution algorithm -# -#========================================================================== - -#----------- -# -# Time loop -# -#----------- -for ts in range(1,ndt+1): - - print_time_step(ts) - - #------------------ - # Store old values - #------------------ - uf.old[:] = uf.val[:] - vf.old[:] = vf.val[:] - wf.old[:] = wf.val[:] - - #----------------------- - # Momentum conservation - #----------------------- - ef = zeros(ru), zeros(rv), zeros(rw) - - calc_uvw((uf,vf,wf), (uf,vf,wf), rho, mu, \ - zeros(rc), ef, dt, (dx,dy,dz), obst) - - #---------- - # Pressure - #---------- - calc_p(p, (uf,vf,wf), rho, dt, (dx,dy,dz), obst) - - #--------------------- - # Velocity correction - #--------------------- - corr_uvw((uf,vf,wf), p, rho, dt, (dx,dy,dz), obst) - - # Compute volume balance for checking - err = vol_balance((uf,vf,wf), (dx,dy,dz), obst) - print('Maximum volume error after correction: %12.5e' % abs(err).max()) - - # Check the CFL number too - cfl = cfl_max((uf,vf,wf), dt, (dx,dy,dz)) - print('Maximum CFL number: %12.5e' % cfl) - -#========================================================================== -# -# Visualisation -# -#========================================================================== - - if ts % 20 == 0: - plot_isolines(p.val, (uf,vf,wf), (xn,yn,zn), Y) - plot_isolines(p.val, (uf,vf,wf), (xn,yn,zn), Z) diff --git a/PYTHON/test-p-tot-staggered.py b/PYTHON/test-p-tot-staggered.py deleted file mode 100644 index ac90f11..0000000 --- a/PYTHON/test-p-tot-staggered.py +++ /dev/null @@ -1,139 +0,0 @@ -#========================================================================== -# Demonstrates the variation of projection algorythm which computes total -# pressure, as a sum of all pressure corrections. -# -# The total pressure being built up in this way counter-balances the -# gravity term in momentum equations. -# -# It seems that such an approach is important for bouyancy dominated flows. -# -# Gravity term is under-relaxed here, but it works even without it. -#-------------------------------------------------------------------------- - -#!/usr/bin/python - -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * -from Display.all import * -from Discretization.all import * -from PhysicalModels.all import * - -#========================================================================== -# -# Define problem -# -#========================================================================== - -# Node coordinates -xn = nodes(0, 10, 80) -yn = nodes(0, 1, 20) -zn = nodes(0, 0.5, 5) - -# Cell coordinates -xc = avg(xn) -yc = avg(yn) -zc = avg(zn) - -# Cell dimensions -nx,ny,nz, dx,dy,dz, rc,ru,rv,rw = cartesian_grid(xn,yn,zn) - -# Set physical properties -rho = zeros(rc) -mu = zeros(rc) -kappa = zeros(rc) -cap = zeros(rc) -rho [:] = 1.15 # density [kg/m^3] -mu [:] = 0.1 # viscosity [Pa s] - -# Time-stepping parameters -dt = 0.1 # time step -ndt = 200 # number of time steps - -# Create unknowns; names, positions and sizes -uf = create_unknown('face-u-vel', X, ru, DIRICHLET) -vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) -wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) -p = create_unknown('pressure', C, rc, NEUMANN) -p_tot = zeros(rc) - -# Specify boundary conditions -uf.bnd[W].typ[:1,:,:] = DIRICHLET -for k in range(0,nz): - uf.bnd[W].val[:1,:,k] = par(0.1, yn) - -uf.bnd[E].typ[:1,:,:] = OUTLET - -for j in (B,T): - uf.bnd[j].typ[:] = NEUMANN - vf.bnd[j].typ[:] = NEUMANN - wf.bnd[j].typ[:] = NEUMANN - -adj_n_bnds(p) - -obst = zeros(rc) - -#========================================================================== -# -# Solution algorithm -# -#========================================================================== - -#----------- -# -# Time loop -# -#----------- -for ts in range(1,ndt+1): - - print_time_step(ts) - - #------------------ - # Store old values - #------------------ - uf.old[:] = uf.val[:] - vf.old[:] = vf.val[:] - wf.old[:] = wf.val[:] - - #----------------------- - # Momentum conservation - #----------------------- - g_v = -G * avg(Y, rho) * min(ts/100,1) - - ef = zeros(ru), g_v, zeros(rw) - - calc_uvw((uf,vf,wf), (uf,vf,wf), rho, mu, \ - p_tot, ef, dt, (dx,dy,dz), obst) - - #---------- - # Pressure - #---------- - calc_p(p, (uf,vf,wf), rho, dt, (dx,dy,dz), obst) - - p_tot = p_tot + p.val - - #--------------------- - # Velocity correction - #--------------------- - corr_uvw((uf,vf,wf), p, rho, dt, (dx,dy,dz), obst) - - # Compute volume balance for checking - err = vol_balance((uf,vf,wf), (dx,dy,dz), obst) - print('Maximum volume error after correction: %12.5e' % abs(err).max()) - - # Check the CFL number too - cfl = cfl_max((uf,vf,wf), dt, (dx,dy,dz)) - print('Maximum CFL number: %12.5e' % cfl) - -#========================================================================== -# -# Visualisation -# -#========================================================================== - - if ts % 20 == 0: - plot_isolines(p_tot, (uf,vf,wf), (xn,yn,zn), Z) - plot_isolines(p.val, (uf,vf,wf), (xn,yn,zn), Z) \ No newline at end of file diff --git a/PYTHON/test-stratification-staggered.py b/PYTHON/test-stratification-staggered.py deleted file mode 100644 index f99b9c6..0000000 --- a/PYTHON/test-stratification-staggered.py +++ /dev/null @@ -1,176 +0,0 @@ -#========================================================================== -# Solves flow in a channel with stable or unstable stratification. -# The type of stratification is set by parameter "STRATIFICATION" -# -# Uses non-Boussinesq model for buoyancy term; i.e. density depends on -# temperature. -# -# Gravity term is engaged gradually to avoid vortex at the outlet. -#-------------------------------------------------------------------------- - -#!/usr/bin/python - -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * -from Display.all import * -from Discretization.all import * -from PhysicalModels.all import * - -#========================================================================== -# -# Define problem -# -#========================================================================== - -STRATIFICATION = 's' # 's' or 'u' - -# Node coordinates -xn = nodes(0, 10, 80) -yn = nodes(0, 1, 20) -zn = nodes(0, 0.5, 5) - -# Cell coordinates -xc = avg(xn) -yc = avg(yn) -zc = avg(zn) - -# Cell dimensions -nx,ny,nz, dx,dy,dz, rc,ru,rv,rw = cartesian_grid(xn,yn,zn) - -# Set physical properties -rho = zeros(rc) -mu = zeros(rc) -cap = zeros(rc) -kappa = zeros(rc) -rho [:] = 1.25 # density [kg/m^3] -mu [:] = 0.1 # viscosity [Pa s] -cap [:] = 1.0 # capacity [kg/m^3] -kappa [:] = 0.001 # thermal conductivity [W/mK] - -# Time-stepping parameters -dt = 0.2 # time step -ndt = 500 # number of time steps - -# Create unknowns; names, positions and sizes -uf = create_unknown('face-u-vel', X, ru, DIRICHLET) -vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) -wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) -p = create_unknown('pressure', C, rc, NEUMANN) -t = create_unknown('temperature', C, rc, NEUMANN) -p_tot = zeros(rc) - -# Specify boundary conditions -uf.bnd[W].typ[:1,:,:] = DIRICHLET -for k in range(0,nz): - uf.bnd[W].val[:1,:,k] = par(0.1, yn) - -uf.bnd[E].typ[:1,:,:] = OUTLET -uf.bnd[E].val[:1,:,:] = 0.1 - -for j in (B,T): - uf.bnd[j].typ[:] = NEUMANN - vf.bnd[j].typ[:] = NEUMANN - wf.bnd[j].typ[:] = NEUMANN - -t.val[:] = 70 -t.bnd[W].typ[:1,:,:] = DIRICHLET -t.bnd[S].typ[:,:1,:] = DIRICHLET -t.bnd[N].typ[:,:1,:] = DIRICHLET -t.bnd[E].val[:1,:,:] = 70 - -if STRATIFICATION == 'u': - dtemp = (60-80)/ny - for k in range(0,nz): - t.bnd[W].val[:1,:,k] = linspace(60-dtemp/2,80+dtemp/2,ny) - t.bnd[S].val[:,:1,:] = 60 - t.bnd[N].val[:,:1,:] = 80 - -elif STRATIFICATION == 's': - dtemp = (80-60)/ny - for k in range(0,nz): - t.bnd[W].val[:1,:,k] = linspace(80-dtemp/2,60+dtemp/2,ny) - t.bnd[S].val[:,:1,:] = 80 - t.bnd[N].val[:,:1,:] = 60 - -adj_n_bnds(p) -adj_n_bnds(t) - -obst = zeros(rc) - -#========================================================================== -# -# Solution algorithm -# -#========================================================================== - -#----------- -# -# Time loop -# -#----------- -for ts in range(1,ndt+1): - - print_time_step(ts) - - #------------------ - # Store old values - #------------------ - t.old[:] = t.val[:] - uf.old[:] = uf.val[:] - vf.old[:] = vf.val[:] - wf.old[:] = wf.val[:] - - #---------------------------- - # Update physical properties - #---------------------------- - rho[:] = 1.06 + (t.val[:] - 60.0) * (0.99 - 1.06) / 20.0 - - #------------------------ - # Temperature (enthalpy) - #------------------------ - calc_t(t, (uf,vf,wf), (rho*cap), kappa, dt, (dx,dy,dz), obst) - - #----------------------- - # Momentum conservation - #----------------------- - g_v = -G * avg(Y, rho) - - ef = zeros(ru), g_v, zeros(rw) - - calc_uvw((uf,vf,wf), (uf,vf,wf), rho, mu, \ - p_tot, ef, dt, (dx,dy,dz), obst) - - #---------- - # Pressure - #---------- - calc_p(p, (uf,vf,wf), rho, dt, (dx,dy,dz), obst) - - p_tot = p_tot + p.val - - #--------------------- - # Velocity correction - #--------------------- - corr_uvw((uf,vf,wf), p, rho, dt, (dx,dy,dz), obst) - - # Compute volume balance for checking - err = vol_balance((uf,vf,wf), (dx,dy,dz), obst) - print('Maximum volume error after correction: %12.5e' % abs(err).max()) - - # Check the CFL number too - cfl = cfl_max((uf,vf,wf), dt, (dx,dy,dz)) - print('Maximum CFL number: %12.5e' % cfl) - -#========================================================================== -# -# Visualisation -# -#========================================================================== - - if ts % 50 == 0: - plot_isolines(p_tot, (uf,vf,wf), (xn,yn,zn), Z) - plot_isolines(t.val, (uf,vf,wf), (xn,yn,zn), Z) - plot_isolines(rho, (uf,vf,wf), (xn,yn,zn), Z) diff --git a/PYTHON/test-thermal-plumes-collocated.py b/PYTHON/test-thermal-plumes-collocated.py deleted file mode 100644 index 6fd9a80..0000000 --- a/PYTHON/test-thermal-plumes-collocated.py +++ /dev/null @@ -1,178 +0,0 @@ -#========================================================================== -# This script is to reproduce two-dimensional mixed convection case, with -# the aim of testing the outflow boundary, particularly the "convective" -# boundary condition which allows eddies to leave the domain. -# -# There is also a staggered version of this script, called -# "demo_plums_collocated.m". It would be good to keep both version as -# similar as possible to each other, to test the differences between -# staggered and collocated arrangements always possible. -#-------------------------------------------------------------------------- - -#!/usr/bin/python - -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * -from Display.all import * -from Discretization.all import * -from PhysicalModels.all import * - -#========================================================================== -# -# Define problem -# -#========================================================================== - -# Node coordinates -xn = nodes(0, 10, 300) -yn = nodes(0, 1, 40, 1/500, 1/500) -zn = nodes(0, 3, 3) - -# Cell coordinates -xc = avg(xn) -yc = avg(yn) -zc = avg(zn) - -# Cell dimensions -nx,ny,nz, dx,dy,dz, rc,ru,rv,rw = cartesian_grid(xn,yn,zn) - -# Set physical properties -rho = zeros(rc) -mu = zeros(rc) -kappa = zeros(rc) -cap = zeros(rc) -rho [:,:,:] = 1. -mu [:,:,:] = 0.1 -kappa[:,:,:] = 0.15 -cap [:,:,:] = 1.0 - -# Time-stepping parameters -dt = 0.003 # time step -ndt = 1500 # number of time steps - -# Create unknowns; names, positions and sizes -uc = create_unknown('cell-u-vel', C, rc, DIRICHLET) -vc = create_unknown('cell-v-vel', C, rc, DIRICHLET) -wc = create_unknown('cell-w-vel', C, rc, DIRICHLET) -uf = create_unknown('face-u-vel', X, ru, DIRICHLET) -vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) -wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) -t = create_unknown('temperature', C, rc, NEUMANN) -p = create_unknown('pressure', C, rc, NEUMANN) - -# Specify boundary conditions -uc.bnd[W].typ[:1,:,:] = DIRICHLET -for k in range(0,nz): - uc.bnd[W].val[:1,:,k] = par(1.0, yn); - -uc.bnd[E].typ[:1,:,:] = OUTLET -uc.bnd[E].val[:1,:,:] = 1.0; - -for j in (B,T): - uc.bnd[j].typ[:] = NEUMANN - vc.bnd[j].typ[:] = NEUMANN - wc.bnd[j].typ[:] = NEUMANN - -t.bnd[W].typ[:1,:,:] = DIRICHLET -for k in range(0,nz): - t.bnd[W].val[:1,:,k] = 1.0-yc; - -t.bnd[S].typ[:,:1,:] = DIRICHLET -t.bnd[S].val[:,:1,:] = +1.0; -t.bnd[N].typ[:,:1,:] = DIRICHLET -t.bnd[N].val[:,:1,:] = 0.0 - -adj_n_bnds(t) -adj_n_bnds(p) - -# Specify initial conditions -uc.val[:,:,:] = 1.0 -t.val[:,:,:] = 0 - -# Copy the values to face velocities -uf.val[:] = avg(X, uc.val) -vf.val[:] = avg(Y, vc.val) -wf.val[:] = avg(Z, wc.val) -for j in (W,E): - uf.bnd[j].val[:] = uc.bnd[j].val[:] - vf.bnd[j].val[:] = avg(Y, vc.bnd[j].val[:]) - wf.bnd[j].val[:] = avg(Z, wc.bnd[j].val[:]) -for j in (S,N): - uf.bnd[j].val[:] = avg(X, uc.bnd[j].val[:]) - vf.bnd[j].val[:] = vc.bnd[j].val[:] - wf.bnd[j].val[:] = avg(Z, wc.bnd[j].val[:]) -for j in (B,T): - uf.bnd[j].val[:] = avg(X, uc.bnd[j].val[:]) - vf.bnd[j].val[:] = avg(Y, vc.bnd[j].val[:]) - wf.bnd[j].val[:] = wc.bnd[j].val[:] - -obst = zeros(rc) - -#========================================================================== -# -# Solution algorithm -# -#========================================================================== - -#----------- -# -# Time loop -# -#----------- -for ts in range(1,ndt+1): - - print_time_step(ts) - - #------------------ - # Store old values - #------------------ - t.old[:] = t.val[:] - uc.old[:] = uc.val[:] - vc.old[:] = vc.val[:] - wc.old[:] = wc.val[:] - - #------------------------ - # Temperature (enthalpy) - #------------------------ - calc_t(t, (uf,vf,wf), (rho*cap), kappa, dt, (dx,dy,dz), obst) - - #----------------------- - # Momentum conservation - #----------------------- - ef = zeros(rc), 150.0 * t.val, zeros(rc) - - calc_uvw((uc,vc,wc), (uf,vf,wf), rho, mu, \ - zeros(rc), ef, dt, (dx,dy,dz), obst) - - #---------- - # Pressure - #---------- - calc_p(p, (uf,vf,wf), rho, dt, (dx,dy,dz), obst) - - #--------------------- - # Velocity correction - #--------------------- - corr_uvw((uc,vc,wc), p, rho, dt, (dx,dy,dz), obst) - corr_uvw((uf,vf,wf), p, rho, dt, (dx,dy,dz), obst) - - # Compute volume balance for checking - err = vol_balance((uf,vf,wf), (dx,dy,dz), obst) - print('Maximum volume error after correction: %12.5e' % abs(err).max()) - - # Check the CFL number too - cfl = cfl_max((uc,vc,wc), dt, (dx,dy,dz)) - print('Maximum CFL number: %12.5e' % cfl) - -#========================================================================== -# -# Visualisation -# -#========================================================================== - - if ts % 150 == 0: - plot_isolines(t.val, (uc,vc,wc), (xn,yn,zn), Z) - plot_isolines(p.val, (uc,vc,wc), (xn,yn,zn), Z) diff --git a/PYTHON/test-thermal-plumes-staggered.py b/PYTHON/test-thermal-plumes-staggered.py deleted file mode 100644 index 2cb2502..0000000 --- a/PYTHON/test-thermal-plumes-staggered.py +++ /dev/null @@ -1,157 +0,0 @@ -#========================================================================== -# This script is to reproduce two-dimensional mixed convection case, with -# the aim of testing the outflow boundary, particularly the "convective" -# boundary condition which allows eddies to leave the domain. -# -# There is also a staggered version of this script, called -# "demo_plums_collocated.m". It would be good to keep both version as -# similar as possible to each other, to test the differences between -# staggered and collocated arrangements always possible. -#-------------------------------------------------------------------------- - -#!/usr/bin/python - -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * -from Display.all import * -from Discretization.all import * -from PhysicalModels.all import * - -#========================================================================== -# -# Define problem -# -#========================================================================== - -# Node coordinates -xn = nodes(0, 10, 300) -yn = nodes(0, 1, 40, 1/500, 1/500) -zn = nodes(0, 3, 3) - -# Cell coordinates -xc = avg(xn) -yc = avg(yn) -zc = avg(zn) - -# Cell dimensions -nx,ny,nz, dx,dy,dz, rc,ru,rv,rw = cartesian_grid(xn,yn,zn) - -# Set physical properties -rho = zeros(rc) -mu = zeros(rc) -kappa = zeros(rc) -cap = zeros(rc) -rho [:,:,:] = 1. -mu [:,:,:] = 0.1 -kappa[:,:,:] = 0.15 -cap [:,:,:] = 1.0 - -# Time-stepping parameters -dt = 0.003 # time step -ndt = 1500 # number of time steps - -# Create unknowns; names, positions and sizes -uf = create_unknown('face-u-vel', X, ru, DIRICHLET) -vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) -wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) -t = create_unknown('temperature', C, rc, NEUMANN) -p = create_unknown('pressure', C, rc, NEUMANN) - -# Specify boundary conditions -uf.bnd[W].typ[:1,:,:] = DIRICHLET -for k in range(0,nz): - uf.bnd[W].val[:1,:,k] = par(1.0, yn); - -uf.bnd[E].typ[:1,:,:] = OUTLET -uf.bnd[E].val[:1,:,:] = 1.0; - -for j in (B,T): - uf.bnd[j].typ[:] = NEUMANN - vf.bnd[j].typ[:] = NEUMANN - wf.bnd[j].typ[:] = NEUMANN - -t.bnd[W].typ[:1,:,:] = DIRICHLET -for k in range(0,nz): - t.bnd[W].val[:1,:,k] = 1.0-yc; - -t.bnd[S].typ[:,:1,:] = DIRICHLET -t.bnd[S].val[:,:1,:] = +1.0; -t.bnd[N].typ[:,:1,:] = DIRICHLET -t.bnd[N].val[:,:1,:] = 0.0 - -adj_n_bnds(t) -adj_n_bnds(p) - -# Specify initial conditions -uf.val[:,:,:] = 1.0 -t.val[:,:,:] = 0 - -obst = zeros(rc) - -#========================================================================== -# -# Solution algorithm -# -#========================================================================== - -#----------- -# -# Time loop -# -#----------- -for ts in range(1,ndt+1): - - print_time_step(ts) - - #------------------ - # Store old values - #------------------ - t.old[:] = t.val[:] - uf.old[:] = uf.val[:] - vf.old[:] = vf.val[:] - wf.old[:] = wf.val[:] - - #------------------------ - # Temperature (enthalpy) - #------------------------ - calc_t(t, (uf,vf,wf), (rho*cap), kappa, dt, (dx,dy,dz), obst) - - #----------------------- - # Momentum conservation - #----------------------- - ef = zeros(ru), 150.0 * avg(Y,t.val), zeros(rw) - - calc_uvw((uf,vf,wf), (uf,vf,wf), rho, mu, \ - zeros(rc), ef, dt, (dx,dy,dz), obst) - - #---------- - # Pressure - #---------- - calc_p(p, (uf,vf,wf), rho, dt, (dx,dy,dz), obst) - - #--------------------- - # Velocity correction - #--------------------- - corr_uvw((uf,vf,wf), p, rho, dt, (dx,dy,dz), obst) - - # Compute volume balance for checking - err = vol_balance((uf,vf,wf), (dx,dy,dz), obst) - print('Maximum volume error after correction: %12.5e' % abs(err).max()) - - # Check the CFL number too - cfl = cfl_max((uf,vf,wf), dt, (dx,dy,dz)) - print('Maximum CFL number: %12.5e' % cfl) - -#========================================================================== -# -# Visualisation -# -#========================================================================== - - if ts % 150 == 0: - plot_isolines(t.val, (uf,vf,wf), (xn,yn,zn), Z) - plot_isolines(p.val, (uf,vf,wf), (xn,yn,zn), Z) diff --git a/PYTHON/test-thermally-driven-cavity-collocated.py b/PYTHON/test-thermally-driven-cavity-collocated.py deleted file mode 100644 index c0d3b86..0000000 --- a/PYTHON/test-thermally-driven-cavity-collocated.py +++ /dev/null @@ -1,160 +0,0 @@ -#========================================================================== -# This program solves thermally driven cavity at Ra = 1.0e6, -# in dimensional and non-dimensional forms. -# -# Equations in dimensional form: -# -# D(rho u)/Dt = nabla(mu (nabla u)^T) - nabla p + g -# D(rho cp T)/Dt = nabla(lambda (nabla T)^T) -# -# Equations in non-dimensional form, for natural convection problems -# -# DU/Dt = nabla(1/sqrt(Gr) (nabla U)^T) - nabla P + theta -# D theta/Dt = nabla(1/(Pr*sqrt(Gr)) (nabla theta)^T) -# -#-------------------------------------------------------------------------- -# For thermally driven cavity, with properties of air at 60 deg: -# -# nu = 1.89035E-05; -# beta = 0.003; -# dT = 17.126; -# L = 0.1; -# Pr = 0.709; -# -# characteristic non-dimensional numbers are: -# Gr = 1.4105E+06 -# Ra = 1.0000E+06 -#-------------------------------------------------------------------------- - -#!/usr/bin/python - -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * -from Display.all import * -from Discretization.all import * -from PhysicalModels.all import * - -#========================================================================== -# -# Define problem -# -#========================================================================== - -xn = nodes(0, 1, 64, 1.0/256, 1.0/256) -yn = nodes(0, 1, 64, 1.0/256, 1.0/256) -zn = nodes(0, 0.1, 5) - -# Cell dimensions -nx,ny,nz, dx,dy,dz, rc,ru,rv,rw = cartesian_grid(xn,yn,zn) - -# Set physical properties -grashof = 1.4105E+06 -prandtl = 0.7058 -rho = zeros(rc) -mu = zeros(rc) -kappa = zeros(rc) -cap = zeros(rc) -rho [:,:,:] = 1.0 -mu [:,:,:] = 1.0 / sqrt(grashof) -kappa[:,:,:] = 1.0 / (prandtl * sqrt(grashof)) -cap [:,:,:] = 1.0 - -# Time-stepping parameters -dt = 0.02 # time step -ndt = 1000 # number of time steps - -# Create unknowns; names, positions and sizes -uc = create_unknown('cell-u-vel', C, rc, DIRICHLET) -vc = create_unknown('cell-v-vel', C, rc, DIRICHLET) -wc = create_unknown('cell-w-vel', C, rc, DIRICHLET) -uf = create_unknown('face-u-vel', X, ru, DIRICHLET) -vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) -wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) -t = create_unknown('temperature', C, rc, NEUMANN) -p = create_unknown('pressure', C, rc, NEUMANN) -p_tot = zeros(rc) - -# This is a new test -t.bnd[W].typ[:] = DIRICHLET -t.bnd[W].val[:] = -0.5 - -t.bnd[E].typ[:] = DIRICHLET -t.bnd[E].val[:] = +0.5 - -for j in (B,T): - uc.bnd[j].typ[:] = NEUMANN - vc.bnd[j].typ[:] = NEUMANN - wc.bnd[j].typ[:] = NEUMANN - -obst = zeros(rc) - -#========================================================================== -# -# Solution algorithm -# -#========================================================================== - -#----------- -# -# Time loop -# -#----------- -for ts in range(1,ndt+1): - - print_time_step(ts) - - #------------------ - # Store old values - #------------------ - t.old[:] = t.val[:] - uc.old[:] = uc.val[:] - vc.old[:] = vc.val[:] - wc.old[:] = wc.val[:] - - #------------------------ - # Temperature (enthalpy) - #------------------------ - calc_t(t, (uf,vf,wf), (rho*cap), kappa, dt, (dx,dy,dz), obst) - - #----------------------- - # Momentum conservation - #----------------------- - ef = zeros(rc), t.val, zeros(rc) - - calc_uvw((uc,vc,wc), (uf,vf,wf), rho, mu, - p_tot, ef, dt, (dx,dy,dz), obst) - - #---------- - # Pressure - #---------- - calc_p(p, (uf,vf,wf), rho, dt, (dx,dy,dz), obst) - - p_tot = p_tot + p.val - - #--------------------- - # Velocity correction - #--------------------- - corr_uvw((uc,vc,wc), p, rho, dt, (dx,dy,dz), obst) - corr_uvw((uf,vf,wf), p, rho, dt, (dx,dy,dz), obst) - - # Compute volume balance for checking - err = vol_balance((uf,vf,wf), (dx,dy,dz), obst) - print('Maximum volume error after correction: %12.5e' % abs(err).max()) - - # Check the CFL number too - cfl = cfl_max((uc,vc,wc), dt, (dx,dy,dz)) - print('Maximum CFL number: %12.5e' % cfl) - -#========================================================================== -# -# Visualisation -# -#========================================================================== - - if ts % 20 == 0: - plot_isolines(t.val, (uc,vc,wc), (xn,yn,zn), Z) - diff --git a/PYTHON/test-thermally-driven-cavity-staggered.py b/PYTHON/test-thermally-driven-cavity-staggered.py deleted file mode 100644 index 99f53b5..0000000 --- a/PYTHON/test-thermally-driven-cavity-staggered.py +++ /dev/null @@ -1,156 +0,0 @@ -#========================================================================== -# This program solves thermally driven cavity at Ra = 1.0e6, -# in dimensional and non-dimensional forms. -# -# Equations in dimensional form: -# -# D(rho u)/Dt = nabla(mu (nabla u)^T) - nabla p + g -# D(rho cp T)/Dt = nabla(lambda (nabla T)^T) -# -# Equations in non-dimensional form, for natural convection problems -# -# DU/Dt = nabla(1/sqrt(Gr) (nabla U)^T) - nabla P + theta -# D theta/Dt = nabla(1/(Pr*sqrt(Gr)) (nabla theta)^T) -# -#-------------------------------------------------------------------------- -# For thermally driven cavity, with properties of air at 60 deg: -# -# nu = 1.89035E-05; -# beta = 0.003; -# dT = 17.126; -# L = 0.1; -# Pr = 0.709; -# -# characteristic non-dimensional numbers are: -# Gr = 1.4105E+06 -# Ra = 1.0000E+06 -#-------------------------------------------------------------------------- - -#!/usr/bin/python - -# Standard Python modules -from standard import * - -# ScriNS modules -from Constants.all import * -from Operators.all import * -from Display.all import * -from Discretization.all import * -from PhysicalModels.all import * - -#========================================================================== -# -# Define problem -# -#========================================================================== - -xn = nodes(0, 1, 64, 1.0/256, 1.0/256) -yn = nodes(0, 1, 64, 1.0/256, 1.0/256) -zn = nodes(0, 0.1, 5) - -# Cell dimensions -nx,ny,nz, dx,dy,dz, rc,ru,rv,rw = cartesian_grid(xn,yn,zn) - -# Set physical properties -grashof = 1.4105E+06 -prandtl = 0.7058 -rho = zeros(rc) -mu = zeros(rc) -kappa = zeros(rc) -cap = zeros(rc) -rho [:,:,:] = 1.0 -mu [:,:,:] = 1.0 / sqrt(grashof) -kappa[:,:,:] = 1.0 / (prandtl * sqrt(grashof)) -cap [:,:,:] = 1.0 - -# Time-stepping parameters -dt = 0.02 # time step -ndt = 1000 # number of time steps - -# Create unknowns; names, positions and sizes -uf = create_unknown('face-u-vel', X, ru, DIRICHLET) -vf = create_unknown('face-v-vel', Y, rv, DIRICHLET) -wf = create_unknown('face-w-vel', Z, rw, DIRICHLET) -t = create_unknown('temperature', C, rc, NEUMANN) -p = create_unknown('pressure', C, rc, NEUMANN) -p_tot = zeros(rc) - -# This is a new test -t.bnd[W].typ[:] = DIRICHLET -t.bnd[W].val[:] = -0.5 - -t.bnd[E].typ[:] = DIRICHLET -t.bnd[E].val[:] = +0.5 - -for j in (B,T): - uf.bnd[j].typ[:] = NEUMANN - vf.bnd[j].typ[:] = NEUMANN - wf.bnd[j].typ[:] = NEUMANN - -obst = zeros(rc) - -#========================================================================== -# -# Solution algorithm -# -#========================================================================== - -#----------- -# -# Time loop -# -#----------- -for ts in range(1,ndt+1): - - print_time_step(ts) - - #------------------ - # Store old values - #------------------ - t.old[:] = t.val[:] - uf.old[:] = uf.val[:] - vf.old[:] = vf.val[:] - wf.old[:] = wf.val[:] - - #------------------------ - # Temperature (enthalpy) - #------------------------ - calc_t(t, (uf,vf,wf), (rho*cap), kappa, dt, (dx,dy,dz), obst) - - #----------------------- - # Momentum conservation - #----------------------- - ef = zeros(ru), avg(Y,t.val), zeros(rw) - - calc_uvw((uf,vf,wf), (uf,vf,wf), rho, mu, \ - p_tot, ef, dt, (dx,dy,dz), obst) - - #---------- - # Pressure - #---------- - calc_p(p, (uf,vf,wf), rho, dt, (dx,dy,dz), obst) - - p_tot = p_tot + p.val - - #--------------------- - # Velocity correction - #--------------------- - corr_uvw((uf,vf,wf), p, rho, dt, (dx,dy,dz), obst) - - # Compute volume balance for checking - err = vol_balance((uf,vf,wf), (dx,dy,dz), obst) - print('Maximum volume error after correction: %12.5e' % abs(err).max()) - - # Check the CFL number too - cfl = cfl_max((uf,vf,wf), dt, (dx,dy,dz)) - print('Maximum CFL number: %12.5e' % cfl) - -#========================================================================== -# -# Visualisation -# -#========================================================================== - - if ts % 20 == 0: - plot_isolines(t.val, (uf,vf,wf), (xn,yn,zn), Z) -