rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
fv_operators_diff_implicit_gradient2.m
Go to the documentation of this file.
2  model, model_data, U, NU_ind)
3 %function [L_I_diff, bdir_I_diff] = ...
4 % fv_operators_diff_implicit_gradient2(model,model_data[, U, NU_ind])
5 % computes diffusion contributions to finite volume time evolution matrices,
6 % <b> or their Frechet derivative </b>
7 %
8 % This function computes a diffusion operator `L_{\text{diff}}` and a
9 % corresponding offset vector `b_{\text{diff}}` 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 % The analytical term inspiring this operator looks like
15 % `` - \nabla \cdot \left(d(u) \nabla l(u) \right). ``
16 % Here, the functions `d(u)` and `l(u)` differ in the numerical
17 % implementation.
18 %
19 % The latter is evaluated in cell centers during flux computation, whereas
20 % the diffusion functional `d(u)` is evaluated on the cell edges by averaging
21 % the solutions value there.
22 %
23 % See also: fv_num_diff_flux_gradient()
24 %
25 % The implemented flux then can be written for inner boundaries as
26 % `` g_{ij}(u,v) = d(\{u,v\}) \frac{l(v) - l(u)}{|d_{ij}|} |e_{ij}| ``
27 % and for Dirichlet boundaries as
28 % `` g_{dir,ij}(u) = d(u_{dir}(x_{ij}))
29 % \frac{l(u_{dir}(x_{ij})) - u}{|d_{ij}|} |e_{ij}|, ``
30 % where `\{u,v\}` refers to the average of `u` and `v`.
31 %
32 % \note that this implementation only works for trivial functions `l = id`,
33 % because otherwise the operator would became non-linear in the space
34 % variable.
35 %
36 % If, however, `l(u)` is non-trivial, the flux arguments are simply
37 % <b>scaled</b> by `l'(u)` giving rise to the Frechet derivative
38 % `D L_I|_{U}` that can be used in a Newton scheme. The offset vector
39 % 'bdir_I_diff' can then be ignored, of course!
40 %
41 % required fields of model:
42 % diffusivity_ptr : The diffusivity function `d(u)`
43 % laplacian_derivative_ptr : The derivative `l'(u)`. See above for
44 % explanation.
45 % dirichlet_values_ptr : The dirichlet function `u_{\text{dir}}`
46 %
47 % Return values:
48 % L_I_diff : a sparse matrix with diffusion contributions to `L_I`.
49 % bdir_I_diff : and offset vector containing the Dirichlet value
50 % contributions of the diffusion parts.
51 %
52 
53 % Bernard Haasdonk 13.7.2006
54 
55 % determine affine_decomposition_mode as integer
56 decomp_mode = model.decomp_mode;
57 
58 grid = [];
59 if ~isempty(model_data)
60  grid = model_data.grid;
61 end
62 
63 if nargin < 4
64  NU_ind = [];
65 end
66 
67 if decomp_mode < 2
68  n = grid.nelements;
69  % determine index sets of boundary types
70  real_NB_ind = find(grid.NBI>0);
71  %NBIind = grid.NBI(real_NB_ind);
72  %INBind = grid.INB(real_NB_ind);
73  % NB_real_NB_ind = sub2ind(size(grid.NBI),NBIind, INBind);
74  dir_NB_ind =find(grid.NBI == -1);
75  real_or_dir_NB_ind = [real_NB_ind(:); dir_NB_ind(:)];
76 
77  if model.verbose >= 29
78  disp(['found ',num2str(length(real_NB_ind)),' non-boundary edges.'])
79  disp(['found ',num2str(length(dir_NB_ind)),' dirichlet-boundary edges.'])
80  end;
81 end;
82 
83 % currently assuming full implicit discretization of diffusivity
84 
85 %%%%%%%% 1. implicit matrix:
86 % has entries
87 % (L_I_diff)il = 1/|T_i| sum_j (NB(i) cup NB_dir(i))
88 % diff*|S_ij|/d_ij if l=i
89 % -diff |S_il|/d_il if l is NB(i)
90 
91 % evaluate all edge midpoint diffusivities at time t+dt:
92 
93 
94 if decomp_mode == 2
95  diff = model.diffusivity_ptr([],[],model);
96 else
97  if nargin == 4
98  tmpU = repmat(U, 1, grid.nneigh);
99  neiU = tmpU;
100  real_nb_ind = grid.NBI > 0;
101  neiU(real_nb_ind) = U(grid.NBI(real_nb_ind));
102 
103  %edgeU = 0.5 * (tmpU + neiU);
104  %edgeU = sqrt(tmpU.*neiU);
105  %edgeU = min(tmpU,neiU);
106  %edgeU = 2*(1./tmpU + 1./neiU).^(-1);
107  %diff = model.diffusivity_ptr([grid.ESX(:), grid.ESY(:)],edgeU(:), model);
108  difftmp = model.diffusivity_ptr([grid.ESX(:),grid.ESY(:)],tmpU(:),model);
109  diffnei = model.diffusivity_ptr([grid.ESX(:),grid.ESY(:)],neiU(:),model);
110 
111  if ~isfield(model, 'mean_ptr')
112  model.mean_ptr = @mean;
113  end
114  mymean = model.mean_ptr;
115  %diff.K = 2*(difftmp.K + diffnei.K) ./ (difftmp.K + diffnei.K);
116 
117  diff.K = mymean([difftmp.K, diffnei.K], 2);
118  diff.epsilon = mymean([difftmp.epsilon, diffnei.epsilon]);
119  else
120  diff = model.diffusivity_ptr([grid.ESX(:), grid.ESY(:)],[],model);
121  end
122  % exact diffusivity on dirichlet edges
123  if (~isempty(dir_NB_ind)) & (model.decomp_mode == 0)
124  Xdir = grid.ECX(dir_NB_ind);
125  Ydir = grid.ECY(dir_NB_ind);
126  Udir = model.dirichlet_values_ptr([Xdir(:),Ydir(:)],model);
127  Kdir = model.diffusivity_ptr([Xdir(:),Ydir(:)],Udir,model);
128  diff.K(dir_NB_ind) = Kdir.K(:);
129  end
130 
131 end;
132 
133 
134 if length(diff.K)==1
135  K = ones(size(grid.ESX))*diff.K;
136 else
137  K = reshape(diff.K,size(grid.ESX));
138 end
139 Ulaplace = model.laplacian_derivative_ptr([grid.CX(:),...
140  grid.CY(:)],...
141  U, model);
142 if length(Ulaplace) == 1
143  Ulaplace = ones(size(grid.CX)) * Ulaplace;
144 end
145 Ulaplace = repmat(Ulaplace,1,grid.nneigh);
146 if ~isempty(dir_NB_ind)
147  Udirlaplace = model.laplacian_derivative_ptr([Xdir,Ydir],...
148  Udir, model);
149 else
150  Udirlaplace = [];
151 end
152 % compute products
153 val = zeros(size(grid.ESX));
154 val(real_or_dir_NB_ind) = K(real_or_dir_NB_ind).* ...
155  grid.EL(real_or_dir_NB_ind).* ...
156  [ Ulaplace(real_NB_ind); Udirlaplace ] .* ...
157  (([grid.DS(real_NB_ind);1.0*grid.DS(dir_NB_ind)]).^(-1));
158 % Ti_inv = repmat(grid.Ainv(:),1,grid.nneigh);
159 % val = val .* Ti_inv;
160 
161 % diagonal values:
162 %L_I_diag = sparse(1:n,1:n, sum(val,2));
163 % off-diagonal values:
164 [i,dummy] = ind2sub(size(grid.NBI),real_NB_ind);
165 i = i';
166 %L_I_offdiag = sparse(i,grid.NBI(real_NB_ind), -val(real_NB_ind),n,n);
167 spm.sn = n;
168 spm.sm = n;
169 spm.si = [1:n, i];
170 spm.sj = [1:n, grid.NBI(real_NB_ind)'];
171 spm.svals = [sum(val,2)', -val(real_NB_ind(:)')];
172 
173 if ~isempty(dir_NB_ind)
174  error('Dirichlet values not yet supported');
175  % evaluate dirichlet values at edge midpoints at t+dt
176  % Xdir, Ydir, Udir, K(dir_NB_ind) already computed above
177 
178  Kdir = K(dir_NB_ind); % diffusivity already computed above
179  val2 = zeros(size(grid.ESX));
180  val2(dir_NB_ind)= - grid.EL(dir_NB_ind).*...
181  Udirlaplace.*((1.0*grid.DS(dir_NB_ind)).^(-1)) ...
182  .* Kdir .*Udir;
183 % bdir_I_diff = - grid.Ainv(:).* sum(val2,2);
184  bdir_I_diff = - sum(val2,2);
185 else
186  bdir_I_diff = zeros(grid.nelements,1);
187 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 num_flux_mat = fv_num_diff_flux_gradient(model, model_data, U, NU_ind)
computes a numerical diffusive flux for a diffusion problem
function spm = fv_operators_diff_implicit_gradient2(model, model_data, U, NU_ind)
computes diffusion contributions to finite volume time evolution matrices, or their Frechet derivati...