rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
fv_num_conv_flux_engquist_osher.m
Go to the documentation of this file.
1 function num_flux = fv_num_conv_flux_engquist_osher(model,model_data,U,NU_ind)
2 %function num_flux = fv_num_conv_flux_engquist_osher(model,model_data,U,NU_ind)
3 % Function computing a numerical convective Engquist-Osher
4 % flux matrix.
5 %
6 % Engquist-Osher-Flux in 2D:
7 % ``g_{jl}(u,v) = |e_{jl}| \cdot (c^+_{jl}(u) + c^-_{jl}(v))``
8 % with
9 % ``c^+_{jl}(u) = c_{jl}(0) + \int_0^u \max(c_{jl}'(s),0) ds``
10 % ``c^-_{jl}(u) = \int_0^u \min(c_{jl}'(s),0) ds``
11 % ``c_{jl}(u) = f(u) \cdot n_{jl}``
12 %
13 % if we assume, that
14 % -# `f'(u)\cdot n` does not change sign on `[0,u]` and
15 % -# `f(0) = 0`
16 % then
17 % this simplifies to
18 % ``c^+_{jl}(u) = \left\{\begin{array}{rl}
19 % f(u)\cdot n_{jl} & \mbox{if }f'(u)\cdot n_{jl} > 0 \\
20 % 0 & \mbox{otherwise}
21 % \end{array}\right.``
22 % ``c^-_{jl}(v) = \left\{\begin{array}{rl}
23 % f(v)\cdot n_{jl} & \mbox{if }f'(v)\cdot n_{jl} < 0 \\
24 % 0 & \mbox{otherwise}.
25 % \end{array}\right.``
26 %
27 % Dirichlet-boundary treatment is performed, but
28 % Neumann-values are set to 'nan'. They must be performed by
29 % the calling function.
30 %
31 % fields of num_flux:
32 % Lg: lipschitz constant satisfying
33 % ``|g_{ij}(w,v) - g_{ij}(w',v')| \leq Lg |S_{ij}| ( |w'-w| + |v'-v| ).``
34 % G: the matrix of numerical flux values across the edges.
35 % boundary treatment is performed as follows:
36 % - in dirichlet-boundary points, the
37 % neighbour-values are simply set to this value and
38 % the flux is computed.
39 % - Neumann-treatment is not performed here
40 % .
41 %
42 % We assume for the convective flux function:
43 % -# `f'(u)\cdot n` does not change sign on interval `(u,0)`
44 % -# `f(0) = 0`
45 %
46 % Additionally, a velocity function must be available in order to
47 % compute the derivative of the convection term.
48 %
49 
50 % Bernard Haasdonk 10.4.2006
51 
52  grid = model_data.grid;
53 
54  if ~isempty(model.flux_quad_degree)
55  model.flux_quad_degree = 1;
56  end;
57 
58  num_flux = [];
59  num_flux.G = nan* ones(size(grid.NBI));
60 
61  % determine index sets of boundary types
62  real_NB_ind = find(grid.NBI>0);
63  NBIind = grid.NBI(real_NB_ind);
64  INBind = grid.INB(real_NB_ind);
65  % NB_real_ind comprises comprises some kind of inverse cell-neighbour
66  % relation that leads back to the original cell from where we started
67  % Falls
68  % [i,j]=ind2sub(size(grid.NBI),NB_real_NB_ind(sub2ind(size(grid.NBI),k,l)))
69  % dann ist
70  % grid.NBI(i,j) == k
71  NB_real_NB_ind = sub2ind(size(grid.NBI),NBIind,INBind);
72 
73  dir_NB_ind = find(grid.NBI == -1);
74 
75  % matrix with the neighbouring function values
76  % UNB = nan * ones(size(grid.NBI));
77  % UNB(real_NB_ind) = U(grid.NBI(real_NB_ind));
78  UU = repmat(U,1,size(grid.NBI,2));
79 
80  %%%%%%%%%%%%%%%%%%% convective numerical flux: Engquist Osher %%%%%%%%%%%%%%
81 
82  if model.flux_linear && model.divclean_mode>0
83  error('divergence cleaning not implemented for engquist-osher!')
84  end;
85 
86  % evaluate flux matrix
87  % FxNB and FyNB and UNB are computed, where possible:
88  % both are valid in real_NB_ind
89 
90  % matrix evaluating the flux by quadratures over all edges
91  [flux_mat, lambda] = fv_conv_flux_matrix(model,model_data,U);
92 
93  % matrix with flux values, the neighbour values U(j) inserted
94  % values must be reflected across all edges
95  % i.e. GNB(i,j) = flux.G(NBI(i,j),INB(i,j))
96  % take care of boundary-indices!!
97  FxNB = nan * ones([grid.nelements,grid.nneigh]);
98  FyNB = nan * ones([grid.nelements,grid.nneigh]);
99  %[i,j] = ind2sub(size(flux_mat.G),NB_real_NB_ind);
100  [i,j] = ind2sub([grid.nelements, grid.nneigh],NB_real_NB_ind);
101  Fx = reshape(flux_mat(1,:,:),size(FxNB));
102  Fy = reshape(flux_mat(2,:,:),size(FxNB));
103  FxNB(real_NB_ind) = Fx(NB_real_NB_ind);
104  FyNB(real_NB_ind) = Fy(NB_real_NB_ind);
105 
106 
107  % evaluate flux matrix derivative (average over edges)
108  flux_derivative_mat = fv_conv_flux_linearization_matrix(model,model_data,U);
109  % produced fields: Vx, Vy
110 
111  % matrix with flux values, the neighbour values U(j) inserted
112  % values must be reflected across all edges
113  % i.e. GNB(i,j) = flux.G(NBI(i,j),INB(i,j))
114  % take care of boundary-indices!!
115  VxNB = nan * ones(size(flux_derivative_mat.Vx));
116  % [i.j] = ind2sub(size(flux_mat.G),real_NB_ind);
117  VxNB(real_NB_ind) = flux_derivative_mat.Vx(NB_real_NB_ind);
118 
119  VyNB = nan * ones(size(flux_derivative_mat.Vy));
120  % [i.j] = ind2sub(size(flux_mat.G),real_NB_ind);
121  VyNB(real_NB_ind) = flux_derivative_mat.Vy(NB_real_NB_ind);
122 
123  if ~isempty(dir_NB_ind>0)
124  % ordinary flux evaluation by quadratures
125  % Fdir = conv_flux(model, Udir, Xdir, Ydir);
126  Xdir = grid.ECX(dir_NB_ind);
127  Ydir = grid.ECY(dir_NB_ind);
128  Udir = model.dirichlet_values_ptr([Xdir,Ydir],model);
129  [elids, edgeids] = ind2sub(size(grid.VI),dir_NB_ind);
130  PP = edge_quad_points(grid,elids,edgeids,model.flux_quad_degree);
131 
132  ff = model.conv_flux_ptr(PP,...
133  repmat(Udir(:),model.flux_quad_degree,1), ...
134  model );
135  Fdir.Fx = edge_quad_eval_mean(grid,elids,edgeids,...
136  model.flux_quad_degree,ff(:,1));
137  Fdir.Fy = edge_quad_eval_mean(grid,elids,edgeids,...
138  model.flux_quad_degree,ff(:,2));
139 
140  ff_lin = model.conv_flux_derivative_ptr(PP,...
141  repmat(Udir(:),model.flux_quad_degree, 1), ...
142  model);
143  Fdir_derivative.Vx = edge_quad_eval_mean(grid,elids,edgeids,...
144  model.flux_quad_degree,...
145  ff_lin(:,1));
146  Fdir_derivative.Vy = edge_quad_eval_mean(grid,elids,edgeids,...
147  model.flux_quad_degree,...
148  ff_lin(:,2));
149 
150  FxNB(dir_NB_ind) = Fdir.Fx(:);
151  FyNB(dir_NB_ind) = Fdir.Fy(:);
152  VxNB(dir_NB_ind) = Fdir_derivative.Vx(:);
153  VyNB(dir_NB_ind) = Fdir_derivative.Vy(:);
154 
155  end;
156 
157  % the following nicely maintains nan in Neumann-boundary edges
158  c_jl_u_deri = (grid.NX.* flux_derivative_mat.Vx + ...
159  grid.NY.* flux_derivative_mat.Vy);
160  I_c_jl_u_deri_pos = find (c_jl_u_deri > 0);
161  I_c_jl_u_deri_nonpos = c_jl_u_deri <= 0;
162 
163  c_jl_v_deri = (grid.NX.* VxNB + grid.NY.* VyNB);
164  I_c_jl_v_deri_neg = find(c_jl_v_deri < 0);
165  I_c_jl_v_deri_nonneg = c_jl_v_deri >= 0;
166 
167  c_jl_u_plus = nan * ones(size(grid.NBI)); % matrix of Nans
168  c_jl_u_plus(I_c_jl_u_deri_pos) = ...
169  grid.NX(I_c_jl_u_deri_pos).* Fx(I_c_jl_u_deri_pos) + ...
170  grid.NY(I_c_jl_u_deri_pos).* Fy(I_c_jl_u_deri_pos);
171  c_jl_u_plus(I_c_jl_u_deri_nonpos) = 0;
172 
173  c_jl_v_minus = nan * ones(size(grid.NBI));
174  c_jl_v_minus(I_c_jl_v_deri_neg) = ...
175  grid.NX(I_c_jl_v_deri_neg).* FxNB(I_c_jl_v_deri_neg) + ...
176  grid.NY(I_c_jl_v_deri_neg).* FyNB(I_c_jl_v_deri_neg);
177  c_jl_v_minus(I_c_jl_v_deri_nonneg) = 0;
178 
179  % add both components for final flux in all inner edges
180  num_flux.G = grid.EL.*(c_jl_u_plus + c_jl_v_minus);
181 
182  % Lipschitz konstant Lg
183  % |g_ij(w,v) - g_ij(w',v')| <= Lg |S_ij| ( |w'-w| + |v'-v| )
184 
185  num_flux.Lg = 1/ lambda;
186 
187 % if grid.nelements == 200
188 % disp('halt in fv_num_conv_flux_engquist_osher');
189 % keyboard;
190 % end;
191 
192 %keyboard;
function [ flux_mat , lambda ] = fv_conv_flux_matrix(model, model_data, U, conv_flux_ptr)
function computing the flux matrix of a convection problem. simply reformatting the grid data suitabl...
function num_flux = fv_num_conv_flux_engquist_osher(model, model_data, U, NU_ind)
Function computing a numerical convective Engquist-Osher flux matrix.