2 model,model_data,U,NU_ind)
4 % model,model_data[,U,NU_ind])
5 % computes convection contribution to finite volume time evolution matrices,
6 % <b> or their Frechet derivative </b>
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
12 % `L_I U^{k+1} = L_E U^k + b_E + b_I`.
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
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 \\
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)`.
44 % The result are a sparse matrix
'L_E_conv' and an offset vector
45 %
'bdir_E_conv', the latter containing dirichlet value contributions
50 % L_E_conv : sparse matrix `L_{\text{eo}}`
51 % bdir_E_conv : offset vector `b_{\text{eo}}`
54 % Bernard Haasdonk 13.7.2006
56 % determine affine_decomposition_mode as integer
57 decomp_mode = model.decomp_mode;
60 if ~isempty(model_data)
61 grid = model_data.grid;
64 %%%%%%%%%%%%%%%%%%%%%%%%%%%%% engquist osher %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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(:)];
75 disp(['found ',num2str(length(real_NB_ind)),' non-boundary edges.'])
76 disp(['found ',num2str(length(dir_NB_ind)),' dirichlet-boundary edges.'])
83 % ATTENTION: by using u=1, we get the velocity field
84 % Of course, this only works, when the conv_flux function is linear
89 % non-linear case: use f' for flux matrix generation
92 % disp('halt after flux_mat')
94 else % decomp_mode == 2
98 if model.debug && decomp_mode == 0
99 disp('test affine decomposition of flux_matrix:');
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));
111 %%%%%%%% explicit matrix:
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
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) * ...
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));
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));
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;
155 L_E_conv = L_E_conv(NU_ind, :);
160 elseif decomp_mode==1
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);
170 % velocity components
172 V.Vx = reshape(flux_mat{q}(1,:,:),size(grid.ECX));
173 V.Vy = reshape(flux_mat{q}(2,:,:),size(grid.ECX));
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));
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);
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;
198 %%%%%%%% dirichlet-offset-vector:
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
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);
213 bdir_E_conv((q1-1)*(Q_v)+ q2) = Udir(q1)*flux_mat(q2);
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);
226 disp(
'test affine decomposition of dirichlet values:');
227 test_affine_decomp(model.dirichlet_values_ptr,...
228 1,2,[Xdir(:), Ydir(:)],model);
232 val2 = zeros(size(grid.ESX));
233 % vn_dir_nb = zeros(length(dir_NB_ind),1);
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');
243 bdir_E_conv = zeros(grid.nelements,1);
246 else % decomp_mode == 1
247 if ~isempty(dir_NB_ind > 0)
248 %
for each udir-component compute Q_v components
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);
255 Q_Udir = length(Udir);
256 bdir_E_conv = cell(Q_Udir * Q_v,1);
258 % vn_dir_nb = zeros(length(dir_NB_ind),1);
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));
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);
278 % save(
'ws_components');
280 % still produce dummy components as the availability of dir
281 % boundary cannot be detected in online phase
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);
function r = verbose(level, message, messageId)
This function displays messages depending on a message-id and/or a level. Aditionally you can set/res...
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.