rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
conv_flux.m
1 function flux = conv_flux(model,U,X,Y)
2 %function flux = conv_flux(model,[U],[X],[Y])
3 %
4 % function computing the convective flux of a convection problem.
5 % flux consists of the fields
6 % Fx, Fy and lambda, representing the x/y-coordinates of the
7 % velocity in the edge midpoints and a CFL-bound.
8 % lambda is only returned in affine_decomp_mode == 'none', as it
9 % does not make sense otherwise.
10 % lambda satisfies
11 % lambda * sup_u n_jl * f'(u) <= 1
12 % e.g. lambda := 1/sup|v(x,y)| in case of linear flux and u bounded by 1
13 % only reasonable in affine_decomp_mode=='none', otherwise not returned.
14 %
15 % required fields of model:
16 % name_flux: 'parabola', 'circular', etc.
17 % t: real time value in case of time-dependent flux
18 %
19 % if name_flux == 'burgers_parabola' (reasonable domain [0,1]^2)
20 % then a parabolic velocity field going to the right is used with
21 % maximum velocity model.vmax and angle model.vrot_angle to
22 % the x-axis. The computed flux then is v * u^model.flux_pdeg. The input
23 % quantity U is assumed to be bounded by linfty-norm 1
24 %
25 % if name_flux == 'parabola' (reasonable domain [0,1]^2)
26 % c : velocity of parabola-profile in model.yrange, constant in x-direction
27 %
28 % if name_flux == 'gdl' (reasonable domain [0,1e-3]x[0,0.25e-3])
29 % v_in_max : max velocity
30 % a velocity profile is used, which is computed from an
31 % elliptic problem: parabolic inflow profile on the left,
32 % parabolic outflow on the right, noflow on bottom and middle
33 % of top. Dirichlet values in pressure on two top domains
34 % yield the velocity.
35 % if name_flux == 'gdl2' (reasonable domain [0,1e-3]x[0,0.25e-3])
36 % lambda : factor for velocity computation: v = - lambda * grad(p)
37 % a velocity field is used, which is computed from an
38 % elliptic problem for the pressure by compute_pressure_gdl2
39 % (some gdl-elements in a row, Neumann-0 and dirichlet
40 % conditions between 4 and 1 for the pressure, linear
41 % decreasing along the channel)
42 % if name_flux == 'gdl_circ_par_mix' then a mixture of parabolic and
43 % circular hand crafted velocity profile is used.
44 % does not work good, produces singularities in fv simulation.
45 % if name_flux == 'gdl_pgrad_and_parabola' then a mixture of a parabola
46 % and a simulated pressure gradient is used. By this,
47 % symmetric boundary conditions can be used
48 %
49 % Function supports affine decomposition, i.e. different operation modes
50 % guided by optional field affine_decomp_mode in model. See also the
51 % contents.txt for general explanation
52 %
53 % optional fields of model:
54 % mu_names : names of fields to be regarded as parameters in vector mu
55 % affine_decomp_mode: operation mode of the function
56 % 'none' (default): no parameter dependence or decomposition is
57 % performed. output is as described above.
58 % 'components': For each output argument a cell array of output
59 % arguments is returned representing the q-th component
60 % independent of the parameters given in mu_names
61 % 'coefficients': For each output argument a cell array of output
62 % arguments is returned representing the q-th coefficient
63 % dependent of the parameters given in mu_names
64 %
65 % in 'coefficient' mode, the parameters in brackets are empty
66 
67 % Bernard Haasdonk 4.4.2006
68 
69 flux = [];
70 
71 % determine affine_decomposition_mode as integer
72 %decomp_mode = get_affine_decomp_mode(model);
73 decomp_mode = model.decomp_mode;
74 % flag indicating whether the computation respected the decomposition
75 respected_decomp_mode = 0;
76 
77 %disp('halt in conv_flux')
78 %keyboard;
79 
80 % keep the following up-to-date with conv_flux_linearization!!!
81 %linear_fluxes = {'gdl2','parabola','gdl_circ_par_mix','gdl',...
82 % 'gdl_pgrad_and_parabola'};
83 
84 %if ismember(model.name_flux, linear_fluxes)
85 % if fluxname is linear fluxes
86 if model.flux_linear
87  % evaluate linear flux
88  lin_flux = conv_flux_linearization(model,U,X,Y);
89  if decomp_mode == 0 % i.e. 'none'
90  flux.lambda = lin_flux.lambda;
91  if ~isempty(lin_flux.Vx) % otherwise size 0/0 => 0/1 !!!!!
92  flux.Fx = lin_flux.Vx(:).* U(:);
93  flux.Fy = lin_flux.Vy(:).* U(:);
94  else
95  flux.Fx = [];
96  flux.Fy = [];
97  end;
98  elseif decomp_mode == 1 % i.e. 'components'
99  flux = cell(size(lin_flux));
100  Q = length(lin_flux);
101  for q = 1:Q
102 % f.lambda = lin_flux{q}.lambda;
103  f.Fx = lin_flux{q}.Vx(:).* U(:);
104  f.Fy = lin_flux{q}.Vy(:).* U(:);
105  flux{q} = f;
106  end;
107  elseif decomp_mode == 2 % i.e. 'coefficients'
108  flux = lin_flux; % copy of coefficient vector from linear flux
109  end;
110  respected_decomp_mode = 1;
111 else
112  % if no linear flux, then select appropriate nonlinear flux
113  switch model.name_flux
114  case 'burgers_parabola'
115  % i.e. a parabolic velocity field times u^2, which is rotated by
116  % an arbitrary angle around the midpoint (0.5,0.5)
117  % u is assumed to be bounded by 1, such that lambda can be
118  % specified in advance
119 
120  % NOTE: KEEP THIS DATA IMPLEMENTATION CONSISTENT WITH ITS DERIVATIVE
121  % IN conv_flux_linearization !!!
122  P = [X(:)'-0.5; Y(:)'-0.5];
123  Rinv = [cos(-model.vrot_angle), - sin(-model.vrot_angle); ...
124  sin(-model.vrot_angle), cos(-model.vrot_angle) ];
125  RP = Rinv*P; % rotated coordinates as columns
126  RP(1,:) = RP(1,:) + 0.5;
127  RP(2,:) = RP(2,:) + 0.5;
128  V = zeros(size(RP));
129  V(1,:) = (1- RP(2,:)) .* RP(2,:) * model.vmax * 4;
130  V(2,:) = 0;
131  RV = Rinv^(-1) * V;
132  flux.Fx = RV(1,:)' .* U(:).^model.flux_pdeg;
133  flux.Fy = RV(2,:)' .* U(:).^model.flux_pdeg;
134 
135  umax = 1;
136  i = find(abs(U)>1.5);
137  if ~isempty(i)
138  disp(['U not bounded by 1 as assumed by flux, lambda may be ',...
139  'too large.']);
140  end;
141  flux.lambda = 1/ (model.vmax * 2 * umax^(model.flux_pdeg-1));
142  % NOTE: KEEP THIS DATA IMPLEMENTATION CONSISTENT WITH ITS DERIVATIVE
143  % IN conv_flux_linearization !!!
144  case 'burgers'
145  % i.e. constant velocity v = (model.flux_vx, model.flux_vy) times u^pdeg
146  % u is assumed to be bounded by 1, such that lambda can be
147  % specified in advance
148  Upower = real(U(:).^model.flux_pdeg);
149  flux.Fx = model.flux_vx * ones(size(U(:))) .* Upower;
150  flux.Fy = model.flux_vy * ones(size(U(:))) .* Upower;
151 
152  umax = 1;
153  i = find(abs(U)>1.5);
154  if ~isempty(i)
155  disp(['U not bounded by 1 as assumed by flux, lambda may be ',...
156  'too large.']);
157  end;
158  vmax = sqrt(model.flux_vy^2 + model.flux_vx^2);
159  flux.lambda = 1/ (vmax * 2 * umax^(model.flux_pdeg-1));
160  case 'richards'
161  flux.Fx = zeros(size(U));
162  flux.Fy = zeros(size(U));
163 
164  p_mu = spline_select(model);
165  [ breaks, coeffs, pieces, order ] = unmkpp(p_mu);
166  p_mu_d = mkpp(breaks, coeffs(:,1:order-1) .* repmat([order-1:-1:1],pieces,1));
167 
168 
169  denom = 1 + ppval(p_mu, X);
170  flux.Fx = - 0.001 * ppval(p_mu_d, X) ./ denom .* U';
171  flux.Fy = - 0.001 * ppval(p_mu_d, X).^2 .* Y ./ denom.^2 .* U';
172  flux.lambda = 1/ (max(max([flux.Fx, flux.Fy])));
173 
174  case 'none'
175  flux.Fx = zeros(size(U));
176  flux.Fy = zeros(size(U));
177  % assumption: vmax = 1, umax = 1;
178  vmax = 1;
179  umax = 1;
180  flux.lambda = 1/ (vmax * 2 * umax);
181 
182  otherwise
183  error('flux function unknown');
184  end;
185 
186 end;
187 
188 if decomp_mode>0 & respected_decomp_mode==0
189  error('function does not support affine decomposition!');
190 end;
191 
192 %| \docupdate