rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
fv_operators_implicit_explicit.m
1 function [L_I,L_E,b] = fv_operators_implicit_explicit(model,model_data, NU_ind)
2 %function [L_I,L_E,b] = fv_operators_implicit_explicit(model,model_data[, NU_ind])
3 %
4 % function computing the time evolution matrices for a finite volume
5 % time step L_I * Unew = L_E * U + b
6 % result are two sparse matrices L_I, L_E and an offset vector b
7 % Function supports affine decomposition, i.e. different operation modes
8 % guided by optional field decomp_mode in model. See also the
9 % contents.txt for general explanation
10 %
11 % required fields of model:
12 % dt : timestep
13 % t : current time, i.e. discretization is taking place in t and
14 % t+dt for explicit and implicit parts respectively
15 % verbose : integer indicating the verbosity level
16 %
17 % optional fields of model:
18 % mu_names : names of fields to be regarded as parameters in vector mu
19 % decomp_mode: operation mode of the function
20 % - 0='complete' (default): no parameter dependence or decomposition is
21 % performed. output is as described above.
22 % - 1='components': For each output argument a cell array of output
23 % arguments is returned representing the q-th component
24 % independent of the parameters given in mu_names
25 % - 2='coefficients': For each output argument a cell array of output
26 % arguments is returned representing the q-th coefficient
27 % dependent of the parameters given in mu_names
28 %
29 % In 'coefficient' mode, the grid is empty
30 
31 % Bernard Haasdonk 13.7.2006
32 
33 % determine affine_decomposition_mode as integer
34 decomp_mode = model.decomp_mode;
35 
36 grid = [];
37 if ~isempty(model_data)
38  grid = model_data.grid;
39 end
40 
41 if nargin < 3
42  NU_ind = [];
43 end
44 
45 % call operator function with or without grid
46 if decomp_mode < 2
47  n = length(grid.A);
48  % old syntax:
49  % [L_I_diff, L_E_diff, bdir_diff] = operators_diff(model,model_data);
50  % [L_I_conv, L_E_conv, bdir_conv] = operators_conv(model,model_data);
51  % [L_I_neu, L_E_neu, bneu] = operators_neuman(model,model_data);
52  [L_I_diff, bdir_I_diff] = model.operators_diff_implicit(model,model_data, NU_ind);
53  [L_E_diff, bdir_E_diff] = model.operators_diff_explicit(model,model_data);
54 % L_E_diff = sparse(n,n); bdir_E_diff = zeros(n,1);
55  [L_E_conv, bdir_E_conv] = model.operators_conv_explicit(model,model_data);
56  [L_I_conv, bdir_I_conv] = model.operators_conv_implicit(model,model_data);
57  [L_E_neu, bneu_E] = model.operators_neumann_explicit(model,model_data);
58  [L_I_neu, bneu_I] = model.operators_neumann_implicit(model,model_data);
59 else
60  [L_E_diff, bdir_E_diff] = model.operators_diff_explicit(model,model_data);
61  [L_I_diff, bdir_I_diff] = model.operators_diff_implicit(model,model_data, NU_ind);
62  [L_E_conv, bdir_E_conv] = model.operators_conv_explicit(model,model_data);
63  [L_I_conv, bdir_I_conv] = model.operators_conv_implicit(model,model_data);
64  [L_E_neu, bneu_E] = model.operators_neumann_explicit(model,model_data);
65  [L_I_neu, bneu_I] = model.operators_neumann_implicit(model,model_data);
66 % keyboard;
67 end;
68 
69 if model.debug && decomp_mode == 0
70  % compute one assembly of affine param decomp with complete mode:
71  disp('test of affine parameter dependence of operators:')
72  test_affine_decomp(model.operators_diff_implicit,...
73  2,1,model,model_data);
74  test_affine_decomp(model.operators_diff_explicit,...
75  2,1,model,model_data);
76  test_affine_decomp(model.operators_conv_explicit,...
77  2,1,model,model_data);
78  test_affine_decomp(model.operators_conv_implicit,...
79  2,1,model,model_data);
80  test_affine_decomp(model.operators_neumann_implicit,...
81  2,1,model,model_data);
82  test_affine_decomp(model.operators_neumann_explicit,...
83  2,1,model,model_data);
84 end;
85 
86 % check that offline and online simulation generate identical
87 % number of components, for this run routine twice and compare numbers:
88 if model.verbose>=20 && decomp_mode >=1
89  disp('in fv_operators_implicit_explicit:')
90  disp(['decomp_mode = ',num2str(model.decomp_mode),', sizes of components:'])
91  vnames = {'L_I_diff','bdir_I_diff','L_E_diff','bdir_E_diff',...
92  'L_E_conv','bdir_E_conv','L_I_conv','bdir_I_conv',...
93  'L_E_neu','bneu_E','L_E_neu','bneu_I'};
94  for v = 1:length(vnames)
95  disp([vnames{v},': ',num2str(size(eval(vnames{v})))]);
96  end
97  keyboard;
98 end;
99 
100 if decomp_mode==0
101  % check for condition: 1-dt * L_E_conv(i,i) >= 0 as this is the
102  % coefficient of u_i^k in the convex-combination representation of u_i^(k+1)
103  % maximum possible dt_max = min ( 1/L_E_conv(i,i))
104  dt_max = min(full(diag(L_E_conv)).^(-1));
105  if model.verbose>=9
106  if model.dt > dt_max
107  disp(['current dt = ',num2str(model.dt),...
108  ' is larger than cfl-condition!']);
109  disp(['cfl: dt_max = ',num2str(dt_max)]);
110  end;
111  if model.dt < dt_max * 0.1;
112  disp(['current dt = ',num2str(model.dt),' can be chosen much larger!']);
113  disp(['cfl: dt_max = ',num2str(dt_max)]);
114  end;
115  end;
116 end;
117 
118 if decomp_mode == 0
119  L_I = speye(n) + model.dt * (L_I_diff + L_I_conv + L_I_neu);
120  L_E = speye(n) - model.dt * (L_E_diff + L_E_conv + L_E_neu);
121  % b = model.dt * (bdir_diff + bdir_conv + bneu);
122  b = model.dt * (bdir_I_diff + bdir_E_diff + ...
123  bdir_I_conv + bdir_E_conv + ...
124  bneu_I + bneu_E);
125 elseif decomp_mode == 1
126  % in case of components: concatenate eye and the other lists
127  L_I = [{speye(n)}; L_I_diff(:); L_I_conv(:); L_I_neu(:)];
128  L_E = [{speye(n)}; L_E_diff(:); L_E_conv(:); L_E_neu(:)];
129  b = [bdir_E_diff(:); bdir_I_diff(:); ...
130  bdir_E_conv(:); bdir_I_conv(:); ...
131  bneu_E(:) ; bneu_I(:)];
132 % keyboard;
133 else
134  % decomp_mode == 2 -> sigmas are required
135  L_I = [1; model.dt* L_I_diff(:); ...
136  model.dt * L_I_conv(:); model.dt * L_I_neu(:)];
137  L_E = [1; - model.dt* L_E_diff(:); ...
138  -model.dt * L_E_conv(:); -model.dt * L_E_neu(:)];
139  b = model.dt * [ bdir_E_diff(:) ; bdir_I_diff(:); ...
140  bdir_E_conv(:) ; bdir_I_conv(:); ...
141  bneu_E(:); bneu_I(:)];
142 % if model.t>2
143 % bdir_E_conv
144 % keyboard;
145 % end;
146 end;
147 %keyboard;
148 
149 if decomp_mode == 0
150  % check L_E contributions:
151  % matrix L should have positive diagonal and nonpositive off-diagonal
152  % with row-sum between 0 and 1
153  L = L_E_diff + L_E_conv + L_E_neu;
154 
155  if model.verbose>=10
156  if ~isempty(find(diag(L)<0,1))
157  disp('warning: explicit matrix has negative diagonal entries!!');
158  if model.verbose>=10
159  keyboard;
160  end;
161  end;
162  Lo = L-diag(diag(L));
163  if ~isempty(find(Lo>0,1))
164  disp('warning: explicit matrix has positive off-diagona entries!!');
165  if model.verbose>=10
166  keyboard;
167  end;
168  end;
169  if ~isempty(find(sum(L,2)<0,1))
170  disp('warning: explicit matrix has negative row sum contributions!!');
171  if model.verbose>=10
172  keyboard;
173  end;
174  end;
175  end;
176 
177  % only report this time consuming computation once:
178  if (model.t==0) && (model.verbose >= 10)
179  fv_estimate_operator_norms(model,model_data);
180  end;
181 end;
182 
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