rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
fv_operators_conv_explicit_engquist_osher.m
Go to the documentation of this file.
1 function [L_E_conv,bdir_E_conv] = fv_operators_conv_explicit_engquist_osher(...
2  model,model_data,U,NU_ind)
3 %function [L_E_conv,bdir_E_conv] = fv_operators_conv_explicit_engquist_osher(...
4 % model,model_data[,U,NU_ind])
5 % computes convection contribution to finite volume time evolution matrices,
6 % <b> or their Frechet derivative </b>
7 %
8 % This function computes a convection operator `L_{\text{eo}}` and a
9 % corresponding offset vector `b_{\text{eo}}` that can be used by
10 % fv_operators_implicit_explicit() to build evolution matrices for a finite
11 % volume time step
12 % `L_I U^{k+1} = L_E U^k + b_E + b_I`.
13 %
14 % @code
15 % (L_E_conv)il = 1/|Ti| *
16 % (sum j (NB(i) cup NB_dir(i): v_ij*n_ij>=0 )
17 % |S_ij| (v(c_ij)*n_ij)) for l=i
18 % 1/|Ti| * |S_il| ( - v(c_il)*n_il)
19 % for l NB(i) and v_il * n_il < 0
20 % 0 else
21 % @endcode
22 %
23 % ``
24 % (L_{E,conv})_{il} =
25 % \begin{cases}
26 % \frac{1}{|T_i|}
27 % \sum_{ j \in \{ NB(i) \cup NB_{dir}(i): v_{ij} \cdot n_{ij}>=0 \} }
28 % |S_{ij}| (v(c_{ij}) \cdot n_{ij})
29 % & \text{for } l=i \\
30 % - \frac{1}{|T_i|} |S_{il}| v(c_{il}) \cdot n_{il}
31 % & \text{for } l \in NB(i)
32 % \text{ and }v_{il} \cdot n_{il} < 0 \\
33 % 0 & \text{else}
34 % \end{cases}
35 % ``
36 %
37 % The analytical term inspiring this operator looks like
38 % ` v \cdot \nabla u `
39 % or in the non-linear case, where the Frechet derivative is computed
40 % ` \nabla \cdot f(u). `
41 % Here, `v` is a space dependent velocity field and `f` some smooth function
42 % in `C^2(\mathbb{R}, \mathbb{R}^d)`.
43 %
44 % The result are a sparse matrix 'L_E_conv' and an offset vector
45 % 'bdir_E_conv', the latter containing dirichlet value contributions
46 %
48 %
49 % Return values:
50 % L_E_conv : sparse matrix `L_{\text{eo}}`
51 % bdir_E_conv : offset vector `b_{\text{eo}}`
52 %
53 
54 % Bernard Haasdonk 13.7.2006
55 
56 % determine affine_decomposition_mode as integer
57 decomp_mode = model.decomp_mode;
58 
59 grid = [];
60 if ~isempty(model_data)
61  grid = model_data.grid;
62 end
63 
64 %%%%%%%%%%%%%%%%%%%%%%%%%%%%% engquist osher %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
65 
66 if decomp_mode < 2
67  n = grid.nelements;
68  % determine index sets of boundary types
69  real_NB_ind = find(grid.NBI>0);
70  %NBIind = grid.NBI(real_NB_ind);
71  %INBind = grid.INB(real_NB_ind);
72  dir_NB_ind =find(grid.NBI == -1);
73  real_or_dir_NB_ind = [real_NB_ind(:); dir_NB_ind(:)];
74  if model.verbose >= 29
75  disp(['found ',num2str(length(real_NB_ind)),' non-boundary edges.'])
76  disp(['found ',num2str(length(dir_NB_ind)),' dirichlet-boundary edges.'])
77  end;
78 
79  if nargin < 4
80  NU_ind = [];
81  end
82 
83  % ATTENTION: by using u=1, we get the velocity field
84  % Of course, this only works, when the conv_flux function is linear
85  if model.flux_linear
86  flux_mat = fv_conv_flux_matrix(model,model_data,ones(n,1));
87  else
88  flux_mat_sign = fv_conv_flux_matrix(model, model_data, ones(n,1));
89  % non-linear case: use f' for flux matrix generation
90  flux_mat = fv_conv_flux_matrix(model, model_data, U, model.conv_flux_derivative_ptr);
91  end
92  % disp('halt after flux_mat')
93  % keyboard;
94 else % decomp_mode == 2
95  flux_mat = fv_conv_flux_matrix(model,[],[]);
96 end;
97 
98 if model.debug && decomp_mode == 0
99  disp('test affine decomposition of flux_matrix:');
100  test_affine_decomp(@fv_conv_flux_matrix,1,1,model,model_data, ...
101  ones(n,1));
102  disp('OK');
103 end;
104 
105 if decomp_mode == 2
106  L_E_conv = flux_mat(:);
107 elseif decomp_mode == 0
108  V.Vx = reshape(flux_mat(1,:,:),size(grid.ECX));
109  V.Vy = reshape(flux_mat(2,:,:),size(grid.ECX));
110 
111  %%%%%%%% explicit matrix:
112  % has entries
113  % (L_E_conv)il = 1/|Ti| *
114  % (sum j (NB(i) cup NB_dir(i): v_ij*n_ij>=0 )
115  % |S_ij| (v(c_ij)*n_ij)) for l=i
116  % 1/|Ti| * |S_il| ( - v(c_il)*n_il)
117  % for l NB(i) and v_il * n_il < 0
118  % 0 else
119 
120  % compute products
121  vn = zeros(size(grid.ESX));
122  vn(real_or_dir_NB_ind) = grid.EL(real_or_dir_NB_ind) .* ...
123  (V.Vx(real_or_dir_NB_ind).*grid.NX(real_or_dir_NB_ind)+ ...
124  V.Vy(real_or_dir_NB_ind).*grid.NY(real_or_dir_NB_ind));
125  % la = zeros(size(grid.ESX));
126  % la(real_or_dir_NB_ind) = 0.5 * grid.EL(real_or_dir_NB_ind) * ...
127  % ( 1 / lambda);
128  if model.flux_linear
129  vn_sign = vn;
130  else
131  vn_sign = zeros(size(grid.ESX));
132  V_sign.Vx = reshape(flux_mat(1,:,:),size(grid.ECX));
133  V_sign.Vy = reshape(flux_mat(2,:,:),size(grid.ECX));
134  vn_sign(real_or_dir_NB_ind) = grid.EL(real_or_dir_NB_ind) .* ...
135  (V_sign.Vx(real_or_dir_NB_ind).*grid.NX(real_or_dir_NB_ind)+ ...
136  V_sign.Vy(real_or_dir_NB_ind).*grid.NY(real_or_dir_NB_ind));
137  end
138 
139  % diagonal entries
140  fi_pos = find(vn_sign>0);
141  fi_neg = find(vn_sign<0);
142  vn_pos = zeros(size(grid.ESX));
143  vn_neg = zeros(size(grid.ESX));
144  vn_pos(fi_pos) = vn(fi_pos);
145  vn_neg(fi_neg) = vn(fi_neg);
146  L_E_diag = sparse(1:n,1:n, grid.Ainv(:) .* sum(vn_pos,2));
147 
148  % off-diagonal entries (nonpositive):
149  [i,dummy ]= ind2sub(size(grid.ESX),real_NB_ind);
150  L_E_offdiag = sparse(i,grid.NBI(real_NB_ind),grid.Ainv(i) .* ...
151  vn_neg(real_NB_ind), n,n);
152  L_E_conv = L_E_diag + L_E_offdiag;
153 
154  if ~isempty(NU_ind)
155  L_E_conv = L_E_conv(NU_ind, :);
156  end
157  bdir_E_conv = 0;
158  return;
159 
160 elseif decomp_mode==1
161 
162  % components as
163  % v-decomposition
164 
165  Q_v = length(flux_mat);
166  L_E_conv = cell(Q_v,1);
167  % auxiliary quantities required some times
168  [i,dummy ]= ind2sub(size(grid.ESX),real_NB_ind);
169 
170  % velocity components
171  for q = 1:Q_v;
172  V.Vx = reshape(flux_mat{q}(1,:,:),size(grid.ECX));
173  V.Vy = reshape(flux_mat{q}(2,:,:),size(grid.ECX));
174  % compute products
175  vn = zeros(size(grid.ESX));
176  vn(real_or_dir_NB_ind) = grid.EL(real_or_dir_NB_ind) .* ...
177  (V.Vx(real_or_dir_NB_ind).*grid.NX(real_or_dir_NB_ind)+ ...
178  V.Vy(real_or_dir_NB_ind).*grid.NY(real_or_dir_NB_ind));
179 
180  % diagonal entries
181  fi_pos = find(vn>0);
182  fi_neg = find(vn<0);
183  vn_pos = zeros(size(grid.ESX));
184  vn_neg = zeros(size(grid.ESX));
185  vn_pos(fi_pos) = vn(fi_pos);
186  vn_neg(fi_neg) = vn(fi_neg);
187 
188  % diagonal entries
189  L_E_diag = sparse(1:n,1:n, grid.Ainv(:) .* sum(vn_pos,2));
190  % off-diagonal entries (nonpositive):
191  L_E_offdiag = sparse(i,grid.NBI(real_NB_ind),grid.Ainv(i) .* ...
192  (vn_neg(real_NB_ind)), n,n);
193  L_E_conv{q} = L_E_diag + L_E_offdiag;
194 
195  end;
196 end;
197 
198 %%%%%%%% dirichlet-offset-vector:
199 
200 % the following is a very rough discretization, should be replaced
201 % by higher order quadratures sometime, as the flux-matrix also is
202 % evaluated with higher order
203 %
204 % (bdir_E_conv)_i = - 1/|T_i| * ...
205 % sum_j Ndir_vn_negative(i) ( |S_ij| v(c_ij)*n_ij u_dir(c_ij,t)
206 if decomp_mode == 2 % decomp_mode == 2 -> coefficients
207  Q_v = length(flux_mat);
208  Udir = model.dirichlet_values_ptr([],model);
209  Q_Udir = length(Udir);
210  bdir_E_conv = zeros(Q_Udir * Q_v,1);
211  for q1 = 1:Q_Udir
212  for q2 = 1:Q_v
213  bdir_E_conv((q1-1)*(Q_v)+ q2) = Udir(q1)*flux_mat(q2);
214  end;
215  end;
216 
217 
218 elseif decomp_mode == 0
219  if ~isempty(dir_NB_ind > 0)
220  % evaluate dirichlet values at edge midpoints at t
221  Xdir = grid.ECX(dir_NB_ind);
222  Ydir = grid.ECY(dir_NB_ind);
223  Udir = model.dirichlet_values_ptr([Xdir(:),Ydir(:)],model);
224 
225  if model.debug
226  disp('test affine decomposition of dirichlet values:');
227  test_affine_decomp(model.dirichlet_values_ptr,...
228  1,2,[Xdir(:), Ydir(:)],model);
229  disp('OK');
230  end;
231 
232  val2 = zeros(size(grid.ESX));
233 % vn_dir_nb = zeros(length(dir_NB_ind),1);
234  vn_dir_nb = ...
235  V.Vx(dir_NB_ind).*grid.NX(dir_NB_ind) + ...
236  V.Vy(dir_NB_ind).*grid.NY(dir_NB_ind);
237  fi_neg = find(vn_dir_nb<0);
238  val2(dir_NB_ind(fi_neg))= grid.EL(dir_NB_ind(fi_neg)).* ...
239  (vn_dir_nb(fi_neg)) .* Udir(fi_neg);
240  bdir_E_conv = - grid.Ainv(:).* sum(val2,2);
241 % save('ws_complete');
242  else
243  bdir_E_conv = zeros(grid.nelements,1);
244  end;
245 
246 else % decomp_mode == 1
247  if ~isempty(dir_NB_ind > 0)
248  % for each udir-component compute Q_v components
249 
250  % evaluate dirichlet values at edge midpoints at t
251  Xdir = grid.ECX(dir_NB_ind);
252  Ydir = grid.ECY(dir_NB_ind);
253  Udir = model.dirichlet_values_ptr([Xdir(:),Ydir(:)],model);
254 
255  Q_Udir = length(Udir);
256  bdir_E_conv = cell(Q_Udir * Q_v,1);
257 
258 % vn_dir_nb = zeros(length(dir_NB_ind),1);
259  for q1 = 1:Q_Udir
260  for q2 = 1:Q_v
261  val2 = zeros(size(grid.ESX));
262  Fx = reshape(flux_mat{q2}(1,:,:),size(grid.ECX));
263  Fy = reshape(flux_mat{q2}(2,:,:),size(grid.ECX));
264  vn_dir_nb = ...
265  Fx(dir_NB_ind).*grid.NX(dir_NB_ind) + ...
266  Fy(dir_NB_ind).*grid.NY(dir_NB_ind);
267  fi_neg = find(vn_dir_nb<0);
268  val2(dir_NB_ind(fi_neg))= grid.EL(dir_NB_ind(fi_neg)).* ...
269  (vn_dir_nb(fi_neg)) .* (Udir{q1}(fi_neg));
270 % disp(['val2 nonzeros:',num2str(length(find(val2))),...
271 % ' q1 = ',num2str(q1),' q2=',num2str(q2)]);
272  % val2(dir_NB_ind)= grid.EL(dir_NB_ind).* ...
273  % (flux_mat{q2}.Fx(dir_NB_ind).*grid.NX(dir_NB_ind) + ...
274  % flux_mat{q2}.Fy(dir_NB_ind).*grid.NY(dir_NB_ind)) .*Udir{q1};
275  bdir_E_conv{(q1-1)*Q_v+q2} = - grid.Ainv(:).* sum(val2,2);
276  end;
277  end;
278 % save('ws_components');
279  else
280  % still produce dummy components as the availability of dir
281  % boundary cannot be detected in online phase
282  tmodel = model;
283  tmodel.decomp_mode = 2;
284  Udir = model.dirichlet_values_ptr([],tmodel);
285  % for each combination of Udir and diffusivity component
286  % perform identical computation as above
287  Q_Udir = length(Udir);
288  bdir_E_conv = cell(Q_Udir * Q_v,1);
289  for q = 1:length(bdir_E_conv)
290  bdir_E_conv{q} = zeros(size(L_E_diag,1),1);
291  end;
292  end;
293 end;
function r = verbose(level, message, messageId)
This function displays messages depending on a message-id and/or a level. Aditionally you can set/res...
Definition: verbose.m:17
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 [ L_E_conv , bdir_E_conv ] = fv_operators_conv_explicit_engquist_osher(model, model_data, U, NU_ind)
computes convection contribution to finite volume time evolution matrices, or their Frechet derivati...
function num_flux = fv_num_conv_flux_engquist_osher(model, model_data, U, NU_ind)
Function computing a numerical convective Engquist-Osher flux matrix.