![]() |
FEATool Multiphysics
v1.17.5
Finite Element Analysis Toolbox
|
EX_NAVIERSTOKES6 Instationary laminar 2D flow around a cylinder (Re(t)<=100).
[ FEA, OUT ] = EX_NAVIERSTOKES3( VARARGIN ) 2D validation and CFD benchmark for instationary laminar incompressible flow around a cylinder (Reynolds number, Re(t) <= 100).
The maximum drag and lift coefficients (with corresponding incidence times), and pressure difference between the front and back of the cylinder at t = 8s are computed and compared with reference values [1].
[1] John V. Reference values for drag and lift of a two-dimensional time-dependent flow around a cylinder. International Journal for Numerical Methods in Fluids, 44:777-788, 2004.
Accepts the following property/value pairs.
Input Value/{Default} Description ----------------------------------------------------------------------------------- igrid scalar {2} Grid type: >0 regular (igrid refinements) <0 unstruc. grid (with hmax=|igrid|) dt scalar {0.02} Time step size instatbc boolean {true} Use instationary boundary conditions ischeme scalar {2} Time stepping scheme sf_u string {sflag2} Shape function for velocity sf_p string {sf_disc1} Shape function for pressure solver string {default} Solver selection default, openfoam, or su2 iplot logical false/{true} Plot and visualize solution . Output Value/(Size) Description ----------------------------------------------------------------------------------- fea struct Problem definition struct out struct Output struct
cOptDef = { 'igrid', 2; 'dt', 0.02; 'instatbc' true; 'ischeme' 2; 'sf_u', 'sflag2'; 'sf_p', 'sf_disc1'; 'solver', ''; 'iplot', true; 'tol', [0.01, 0.01, 0.1, 0.5, 0.2]; 'fid', 1 }; [got,opt] = parseopt(cOptDef,varargin{:}); if ( any(strcmpi(opt.solver,{'SU2'})) ) if ( ~isempty(opt.fid) ) warning('SU2 does not support intationary BCs.') end opt.instatbc = false; end if ( strcmpi(opt.solver,'OPENFOAM') && ~got.igrid ) opt.igrid = 3; end % Model parameters. rho = 1; % Density. miu = 0.001; % Molecular/dynamic viscosity. if ( opt.instatbc ) % t_c_d_max c_d_max t_c_l_max c_l_max dp_t8 ref_data = [3.93625, 2.950923849, 5.6925, 0.47834818, -0.11162153]; else % c_d_max c_l_max St dp_f2 ref_data = [3.23, 1.00, 0.3, 2.48]; if( ~got.tol ) opt.tol = 1; end end % Geometry. h = 0.41; % Height of rectangular domain. l = 2.2; % Length of rectangular domain. xc = 0.2; % x-coordinate of cylinder center. yc = 0.2; % y-coordinate of cylinder center. diam = 0.1; % Diameter of cylinder. fea.sdim = { 'x', 'y' }; R1 = gobj_rectangle( 0, l, 0, h, 'R1' ); C1 = gobj_circle( [xc, yc], diam/2, 'C1' ); fea.geom.objects = { R1, C1 }; fea = geom_apply_formula( fea, 'R1-C1' ); % Grid/mesh generation. if ( opt.igrid >= 1 ) fea.grid = l_cylbenchgrid_2d( opt.igrid ); else fea.grid = gridgen( fea, 'hmax', abs(opt.igrid), 'fid', opt.fid ); end % Boundary identification. dtol = sqrt(eps) * 1e3; ind_inflow = findbdr(fea, sprintf('x <= %.16g', dtol)); % Inflow boundary number. ind_outflow = findbdr(fea, sprintf('x >= (%.16g - %.16g)', l, dtol )); % Outflow boundary number. ind_cylinder = findbdr(fea, sprintf('sqrt((x-%.16g).^2+(y-%.16g).^2) <= %.16g', xc, yc, diam/2 + dtol)); % Cylinder boundary numbers. % Problem definition. fea = addphys( fea, @navierstokes ); fea.phys.ns.eqn.coef{1,end} = { rho }; fea.phys.ns.eqn.coef{2,end} = { miu }; if ( any(strcmpi(opt.solver,{'OPENFOAM','SU2'})) ) fea.phys.ns.sfun = { 'sflag1', 'sflag1', 'sflag1' }; else fea.phys.ns.sfun = { opt.sf_u, opt.sf_u, opt.sf_p }; end % Boundary condition definitions. fea.phys.ns.bdr.sel(ind_inflow) = 2; fea.phys.ns.bdr.sel(ind_outflow) = 4; if ( opt.instatbc ) s_inflow = '6*sin(pi*t/8)*(y*(0.41-y))/0.41^2'; else s_inflow = '6*(y*(0.41-y))/0.41^2'; end fea.phys.ns.bdr.coef{2,end}{1,ind_inflow} = s_inflow; % Call solver. fea = parsephys(fea); fea = parseprob(fea); % Check and parse problem struct. switch ( upper(opt.solver) ) case 'OPENFOAM' if ( opt.ischeme == 1 ) ddtSchemes = 'backward'; else ddtSchemes = 'CrankNicolson 0.9'; end fid = opt.fid; if ( ~got.fid ), fid = []; end [fea.sol.u,tlist] = openfoam( fea, 'application', 'pimpleFoam', 'maxCo', 1.0, 'ddtSchemes', ddtSchemes, ... 'deltaT', opt.dt, 'endTime', 8, 'nproc', 1, 'fid', fid, 'logfid', opt.fid ); fea.sol.u = fea.sol.u(:,tlist > 0); tlist = tlist(tlist > 0); case 'SU2' fid = opt.fid; if ( ~got.fid ), fid = []; end [fea.sol.u,tlist] = su2( fea, 'fid', fid, 'logfid', opt.fid, 'tstep', opt.dt, 'tmax', 8, 'ischeme', opt.ischeme, 'wrtfreq', floor(8/opt.dt/400) ); otherwise [fea.sol.u,tlist] = solvetime( fea, 'fid', opt.fid, 'tstep', opt.dt, 'tmax', 8, 'maxnit', 5, 'ischeme', opt.ischeme ); end % Benchmark quantities. [ c_d, c_l, dp ] = calc_bench_quants( fea, 1, ind_cylinder ); [c_d_max, i] = max( c_d ); t_c_d_max = tlist( i ); [c_l_max, i] = max( c_l ); t_c_l_max = tlist( i ); out.c_d = c_d; out.c_l = c_l; out.dp = dp; out.c_d_max = c_d_max; out.c_l_max = c_l_max; out.t_c_d_max = t_c_d_max; out.t_c_l_max = t_c_l_max; if ( opt.instatbc ) [~, i] = min(abs(tlist-8)); dp_t8 = dp(i); out.dp_t8 = dp_t8; comp_data = [ t_c_d_max c_d_max t_c_l_max c_l_max dp_t8 ]; out.err = abs(ref_data-comp_data)./abs(ref_data); out.pass = all( out.err < opt.tol ); else found = false; for j=i+1:length(c_l) if ( j==length(c_l) ) break end if ( j>1 && c_l(j) > c_l(j-1) && c_l(j) > c_l(j+1) ) found = true; c_l_max2 = c_l(j); t_c_l_max2 = tlist(j); break end end for j=i-1:-1:1 if ( j>1 && c_l(j) > c_l(j-1) && c_l(j) > c_l(j+1) ) found = true; c_l_max2 = c_l(j); t_c_l_max2 = tlist(j); break end end f = 1/(t_c_l_max2-t_c_l_max); St = 0.1*f/1.5; out.St = St; t_dp = t_c_l_max + 1/2/f; [~,j] = find( tlist > t_dp, 1 ); dp_f2 = dp(j-1) + (t_dp - tlist(j-1))/(tlist(j) - tlist(j-1)) * (dp(j)-dp(j-1)); out.dp_f2 = dp_f2; c_d(tlist < 0.5) = 0; [c_d_max, i] = max( c_d ); comp_data = [ c_d_max c_l_max St dp_f2 ]; out.err = abs(ref_data-comp_data)./abs(ref_data); out.pass = all( out.err([1,2,4]) < opt.tol ); end if ( ~isempty(opt.fid) ) fmtf = '%12.8f |'; fmts = '%12s |'; fmt = ['| ',repmat(fmtf,1,4+double(opt.instatbc)),'\n']; fmts = ['| ',repmat(fmts,1,4+double(opt.instatbc)),'\n']; fmtl = ['|------',repmat('-------------+',1,4+double(opt.instatbc))]; fmtl = [fmtl(1:end-1),'|\n']; fprintf( opt.fid, '\n\n' ); fprintf( opt.fid, fmtl ); if ( opt.instatbc ) fprintf( opt.fid, fmts, 't(cd_max)', 'cd_max', 't(cl_max)', 'cl_max', 'dp(t=8)' ); fprintf( opt.fid, fmtl ); fprintf( opt.fid, fmt, t_c_d_max, c_d_max, t_c_l_max, c_l_max, dp_t8 ); else fprintf( opt.fid, fmts, 'cd_max', 'cl_max', 'St', 'dp' ); fprintf( opt.fid, fmtl ); fprintf( opt.fid, fmt, c_d_max, c_l_max, St, dp_f2 ); end fprintf( opt.fid, fmtl ); fmt = ['| Ref. ',repmat(fmtf,1,4+double(opt.instatbc)),'\n']; fprintf( opt.fid, fmt, ref_data ); fprintf( opt.fid, fmtl ); fprintf( opt.fid, '\n\n' ); end % Postprocessing. if ( opt.iplot ) figure fea = parseprob( fea ); subplot(2,2,1) postplot( fea, 'surfexpr', 'sqrt(u^2+v^2)', 'arrowexpr', {'u' 'v'}, 'arrowcolor', 'k' ) title('Velocity field at t=8') ix = tlist > 1; if ( any(ix) ) tlist = tlist(ix); c_d = c_d(ix); c_l = c_l(ix); dp = dp(ix); end subplot(2,2,3) plot( tlist, c_d ) title('drag coefficient') subplot(2,2,4) plot( tlist, c_l ) title('lift coefficient') subplot(2,2,2) plot( tlist, dp ) title('pressure difference') end if ( ~nargout ) clear fea out end %