rbmatlab 0.10.01
|
00001 function flux = conv_flux(model,U,X,Y) 00002 %function flux = conv_flux(model,[U],[X],[Y]) 00003 % 00004 % function computing the convective flux of a convection problem. 00005 % flux consists of the fields 00006 % Fx, Fy and lambda, representing the x/y-coordinates of the 00007 % velocity in the edge midpoints and a CFL-bound. 00008 % lambda is only returned in affine_decomp_mode == 'none', as it 00009 % does not make sense otherwise. 00010 % lambda satisfies 00011 % lambda * sup_u n_jl * f'(u) <= 1 00012 % e.g. lambda := 1/sup|v(x,y)| in case of linear flux and u bounded by 1 00013 % only reasonable in affine_decomp_mode=='none', otherwise not returned. 00014 % 00015 % required fields of model: 00016 % name_flux: 'parabola', 'circular', etc. 00017 % t: real time value in case of time-dependent flux 00018 % 00019 % if name_flux == 'burgers_parabola' (reasonable domain [0,1]^2) 00020 % then a parabolic velocity field going to the right is used with 00021 % maximum velocity model.vmax and angle model.vrot_angle to 00022 % the x-axis. The computed flux then is v * u^model.flux_pdeg. The input 00023 % quantity U is assumed to be bounded by linfty-norm 1 00024 % 00025 % if name_flux == 'parabola' (reasonable domain [0,1]^2) 00026 % c : velocity of parabola-profile in model.yrange, constant in x-direction 00027 % 00028 % if name_flux == 'gdl' (reasonable domain [0,1e-3]x[0,0.25e-3]) 00029 % v_in_max : max velocity 00030 % a velocity profile is used, which is computed from an 00031 % elliptic problem: parabolic inflow profile on the left, 00032 % parabolic outflow on the right, noflow on bottom and middle 00033 % of top. Dirichlet values in pressure on two top domains 00034 % yield the velocity. 00035 % if name_flux == 'gdl2' (reasonable domain [0,1e-3]x[0,0.25e-3]) 00036 % lambda : factor for velocity computation: v = - lambda * grad(p) 00037 % a velocity field is used, which is computed from an 00038 % elliptic problem for the pressure by compute_pressure_gdl2 00039 % (some gdl-elements in a row, Neumann-0 and dirichlet 00040 % conditions between 4 and 1 for the pressure, linear 00041 % decreasing along the channel) 00042 % if name_flux == 'gdl_circ_par_mix' then a mixture of parabolic and 00043 % circular hand crafted velocity profile is used. 00044 % does not work good, produces singularities in fv simulation. 00045 % if name_flux == 'gdl_pgrad_and_parabola' then a mixture of a parabola 00046 % and a simulated pressure gradient is used. By this, 00047 % symmetric boundary conditions can be used 00048 % 00049 % Function supports affine decomposition, i.e. different operation modes 00050 % guided by optional field affine_decomp_mode in model. See also the 00051 % contents.txt for general explanation 00052 % 00053 % optional fields of model: 00054 % mu_names : names of fields to be regarded as parameters in vector mu 00055 % affine_decomp_mode: operation mode of the function 00056 % 'none' (default): no parameter dependence or decomposition is 00057 % performed. output is as described above. 00058 % 'components': For each output argument a cell array of output 00059 % arguments is returned representing the q-th component 00060 % independent of the parameters given in mu_names 00061 % 'coefficients': For each output argument a cell array of output 00062 % arguments is returned representing the q-th coefficient 00063 % dependent of the parameters given in mu_names 00064 % 00065 % in 'coefficient' mode, the parameters in brackets are empty 00066 00067 % Bernard Haasdonk 4.4.2006 00068 00069 flux = []; 00070 00071 % determine affine_decomposition_mode as integer 00072 %decomp_mode = get_affine_decomp_mode(model); 00073 decomp_mode = model.decomp_mode; 00074 % flag indicating whether the computation respected the decomposition 00075 respected_decomp_mode = 0; 00076 00077 %disp('halt in conv_flux') 00078 %keyboard; 00079 00080 % keep the following up-to-date with conv_flux_linearization!!! 00081 %linear_fluxes = {'gdl2','parabola','gdl_circ_par_mix','gdl',... 00082 % 'gdl_pgrad_and_parabola'}; 00083 00084 %if ismember(model.name_flux, linear_fluxes) 00085 % if fluxname is linear fluxes 00086 if model.flux_linear 00087 % evaluate linear flux 00088 lin_flux = conv_flux_linearization(model,U,X,Y); 00089 if decomp_mode == 0 % i.e. 'none' 00090 flux.lambda = lin_flux.lambda; 00091 if ~isempty(lin_flux.Vx) % otherwise size 0/0 => 0/1 !!!!! 00092 flux.Fx = lin_flux.Vx(:).* U(:); 00093 flux.Fy = lin_flux.Vy(:).* U(:); 00094 else 00095 flux.Fx = []; 00096 flux.Fy = []; 00097 end; 00098 elseif decomp_mode == 1 % i.e. 'components' 00099 flux = cell(size(lin_flux)); 00100 Q = length(lin_flux); 00101 for q = 1:Q 00102 % f.lambda = lin_flux{q}.lambda; 00103 f.Fx = lin_flux{q}.Vx(:).* U(:); 00104 f.Fy = lin_flux{q}.Vy(:).* U(:); 00105 flux{q} = f; 00106 end; 00107 elseif decomp_mode == 2 % i.e. 'coefficients' 00108 flux = lin_flux; % copy of coefficient vector from linear flux 00109 end; 00110 respected_decomp_mode = 1; 00111 else 00112 % if no linear flux, then select appropriate nonlinear flux 00113 switch model.name_flux 00114 case 'burgers_parabola' 00115 % i.e. a parabolic velocity field times u^2, which is rotated by 00116 % an arbitrary angle around the midpoint (0.5,0.5) 00117 % u is assumed to be bounded by 1, such that lambda can be 00118 % specified in advance 00119 00120 % NOTE: KEEP THIS DATA IMPLEMENTATION CONSISTENT WITH ITS DERIVATIVE 00121 % IN conv_flux_linearization !!! 00122 P = [X(:)'-0.5; Y(:)'-0.5]; 00123 Rinv = [cos(-model.vrot_angle), - sin(-model.vrot_angle); ... 00124 sin(-model.vrot_angle), cos(-model.vrot_angle) ]; 00125 RP = Rinv*P; % rotated coordinates as columns 00126 RP(1,:) = RP(1,:) + 0.5; 00127 RP(2,:) = RP(2,:) + 0.5; 00128 V = zeros(size(RP)); 00129 V(1,:) = (1- RP(2,:)) .* RP(2,:) * model.vmax * 4; 00130 V(2,:) = 0; 00131 RV = Rinv^(-1) * V; 00132 flux.Fx = RV(1,:)' .* U(:).^model.flux_pdeg; 00133 flux.Fy = RV(2,:)' .* U(:).^model.flux_pdeg; 00134 00135 umax = 1; 00136 i = find(abs(U)>1.5); 00137 if ~isempty(i) 00138 disp(['U not bounded by 1 as assumed by flux, lambda may be ',... 00139 'too large.']); 00140 end; 00141 flux.lambda = 1/ (model.vmax * 2 * umax^(model.flux_pdeg-1)); 00142 % NOTE: KEEP THIS DATA IMPLEMENTATION CONSISTENT WITH ITS DERIVATIVE 00143 % IN conv_flux_linearization !!! 00144 case 'burgers' 00145 % i.e. constant velocity v = (model.flux_vx, model.flux_vy) times u^pdeg 00146 % u is assumed to be bounded by 1, such that lambda can be 00147 % specified in advance 00148 Upower = real(U(:).^model.flux_pdeg); 00149 flux.Fx = model.flux_vx * ones(size(U(:))) .* Upower; 00150 flux.Fy = model.flux_vy * ones(size(U(:))) .* Upower; 00151 00152 umax = 1; 00153 i = find(abs(U)>1.5); 00154 if ~isempty(i) 00155 disp(['U not bounded by 1 as assumed by flux, lambda may be ',... 00156 'too large.']); 00157 end; 00158 vmax = sqrt(model.flux_vy^2 + model.flux_vx^2); 00159 flux.lambda = 1/ (vmax * 2 * umax^(model.flux_pdeg-1)); 00160 case 'richards' 00161 flux.Fx = zeros(size(U)); 00162 flux.Fy = zeros(size(U)); 00163 00164 p_mu = spline_select(model); 00165 [ breaks, coeffs, pieces, order ] = unmkpp(p_mu); 00166 p_mu_d = mkpp(breaks, coeffs(:,1:order-1) .* repmat([order-1:-1:1],pieces,1)); 00167 00168 00169 denom = 1 + ppval(p_mu, X); 00170 flux.Fx = - 0.001 * ppval(p_mu_d, X) ./ denom .* U'; 00171 flux.Fy = - 0.001 * ppval(p_mu_d, X).^2 .* Y ./ denom.^2 .* U'; 00172 flux.lambda = 1/ (max(max([flux.Fx, flux.Fy]))); 00173 00174 case 'none' 00175 flux.Fx = zeros(size(U)); 00176 flux.Fy = zeros(size(U)); 00177 % assumption: vmax = 1, umax = 1; 00178 vmax = 1; 00179 umax = 1; 00180 flux.lambda = 1/ (vmax * 2 * umax); 00181 00182 otherwise 00183 error('flux function unknown'); 00184 end; 00185 00186 end; 00187 00188 if decomp_mode>0 & respected_decomp_mode==0 00189 error('function does not support affine decomposition!'); 00190 end; 00191 00192 %| \docupdate