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])
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
11 % required fields of model:
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
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
29 % In
'coefficient' mode, the grid is empty
31 % Bernard Haasdonk 13.7.2006
33 % determine affine_decomposition_mode as integer
34 decomp_mode = model.decomp_mode;
37 if ~isempty(model_data)
38 grid = model_data.grid;
45 % call
operator function with or without grid
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);
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);
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);
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})))]);
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));
107 disp([
'current dt = ',num2str(model.dt),...
108 ' is larger than cfl-condition!']);
109 disp([
'cfl: dt_max = ',num2str(dt_max)]);
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)]);
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 + ...
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(:)];
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(:)];
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;
156 if ~isempty(find(diag(L)<0,1))
157 disp('warning: explicit matrix has negative diagonal entries!!');
162 Lo = L-diag(diag(L));
163 if ~isempty(find(Lo>0,1))
164 disp('warning: explicit matrix has positive off-diagona entries!!');
169 if ~isempty(find(sum(L,2)<0,1))
170 disp('warning: explicit matrix has negative row sum contributions!!');
177 % only report this time consuming computation once:
178 if (model.t==0) && (model.
verbose >= 10)
179 fv_estimate_operator_norms(model,model_data);
function r = verbose(level, message, messageId)
This function displays messages depending on a message-id and/or a level. Aditionally you can set/res...