rbmatlab 0.10.01
datafunc/conv_flux.m
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 
All Classes Namespaces Files Functions Variables