rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
fv_operators_neumann_explicit.m
Go to the documentation of this file.
1 function [L_E_neu, b_E_neu] = fv_operators_neumann_explicit(model,model_data,U,NU_ind)
2 %function [L_E_neu, b_E_neu] = fv_operators_neumann_explicit(model,model_data,[U,NU_ind])
3 % computes a neumann contribution matrix for finite volume time evolution operators,
4 % <b> or their Frechet derivative </b>
5 %
6 % This function computes the neumann boundary contribution operator
7 % `L_{\text{neu}}` and a corresponding vector ` b_{\text{neu}}` that can be used
8 % by fv_operators_implicit_explicit() to build evolution matrices for a finite
9 % volume time step `L_I U^{k+1} = L_E U^k + b_E + b_I`. This operator
10 % contribution must be activated via the flag
11 % 'model.operators_neumann_implicit'
12 %
13 % The analytical terms inspiring this operator look like
14 % ` f(u) \cdot n = b_{\text{neu}}(u) \quad
15 % \text{on }\partial \Omega_{\text{neu}},`
16 % where `f` can be some flux function, e.g. chosen via the
17 % 'model.conv_flux_ptr' and `b_{\text{neu}}(u)` is the neumann boundary
18 % condition selected via 'model.neumann_values_ptr'.
19 %
22 % fv_operators_diff_implicit_gradient_tensor()
23 %
24 % Required fields of model:
25 % neumann_values_ptr :
26 %
27 % Return values:
28 % L_E_neu : sparse matrix `L_{\text{neu}}`
29 % b_E_neu : offset vector `b_{\text{neu}}`
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 (decomp_mode==2)
42  % only get and forward sigmas:
43  bneu0 = model.neumann_values_ptr([],[],[],model);
44  L_E_neu = bneu0;
45  b_E_neu = bneu0;
46 
47 else % decomp_mode == 0 or 1
48 
49  n = grid.nelements;
50  % determine index sets of boundary types
51  real_NB_ind = find(grid.NBI>0);
52  % dir_NB_ind =find(grid.NBI == -1);
53  neu_NB_ind =find(grid.NBI == -2);
54 
55  if model.verbose >= 10
56  disp(['found ',num2str(length(real_NB_ind)),' non-boundary edges.'])
57  disp(['found ',num2str(length(neu_NB_ind)),' neumann-boundary edges.'])
58  end;
59 
60  if ~isempty(neu_NB_ind)
61  % determine linearization of neumann boundary values
62  % FNneu = aneu * u + bneu
63  Xneu = grid.ECX(neu_NB_ind);
64  Yneu = grid.ECY(neu_NB_ind);
65 
66  if model.flux_linear
67  Uneu = zeros(length(Xneu),1);
68  bneu0 = model.neumann_values_ptr([Xneu(:),Yneu(:)],...
69  Uneu,...
70  [grid.NX(neu_NB_ind),grid.NY(neu_NB_ind)],...
71  model);
72 
73  Uneu = ones(length(Xneu),1);
74  bneu1 = model.neumann_values_ptr([Xneu(:),Yneu(:)],...
75  Uneu,...
76  [grid.NX(neu_NB_ind),grid.NY(neu_NB_ind)],...
77  model);
78  if decomp_mode == 0
79  %%%%%%%% explicit matrix:
80  % has entries
81  % (L_E_neu)il = 1/|Ti| *
82  % (sum j NBneu(i) |S_ij| a_neu_ij for l=i
83  % 0 else
84 
85  aneu = bneu1-bneu0;
86 
87  val = zeros(size(grid.ESX));
88  val(neu_NB_ind)= grid.EL(neu_NB_ind).* aneu;
89  L_E_neu = sparse(1:n,1:n, grid.Ainv(:).* sum(val,2));
90 
91  % check nonnegativity
92  if ~isempty(find(diag(L_E_neu)<0,1))
93  disp('warning: neumann-boundary has inflow velocity !!!! ');
94  end;
95  % keyboard;
96 
97  %%%%%%%% offset-vector:
98  % (b_E_neu)_i = - 1/|T_i| * ...
99  % sum_j NBneu(i) |S_ij| b_E_neu_ij
100  val(neu_NB_ind) = grid.EL(neu_NB_ind).* bneu0;
101  b_E_neu = - grid.Ainv(:) .* sum(val,2);
102  else % decomp_mode == 1 % identical computation for all components
103  Q_bneu = length(bneu0);
104  L_E_neu = cell(Q_bneu,1);
105  b_E_neu = cell(Q_bneu,1);
106  for q=1:Q_bneu
107  aneu = bneu1{q}-bneu0{q};
108  val = zeros(size(grid.ESX));
109  val(neu_NB_ind)= grid.EL(neu_NB_ind).* aneu;
110  L_E_neu{q} = sparse(1:n,1:n, grid.Ainv(:).* sum(val,2));
111  val(neu_NB_ind)= grid.EL(neu_NB_ind).* bneu0{q};
112  b_E_neu{q}= - grid.Ainv(:) .* sum(val,2);
113  end;
114  end; % decomp more select
115  else % compute frechet derivative ( non-linear flux )
116  old_conv_flux_ptr = model.conv_flux_ptr;
117  model.conv_flux_ptr = model.conv_flux_derivative_ptr;
118 
119  bneu = model.neumann_values_ptr([Xneu(:),Yneu(:)], U,...
120  [grid.NX(neu_NB_ind), grid.NY(neu_NB_ind)],...
121  model);
122  model.conv_flux_ptr = old_conv_flux_ptr;
123  if decomp_mode ~= 0
124  error('only decomp mode == 0 is allowed!')
125  end
126  val = zeros(size(grid.ESX));
127  val(neu_NB_ind)= grid.EL(neu_NB_ind).* bneu;
128  L_E_neu = sparse(1:n,1:n, grid.Ainv(:).* sum(val,2));
129  b_E_neu = 0;
130 
131  % check nonnegativity
132  if ~isempty(find(diag(L_E_neu)<0,1))
133  disp('warning: neumann-boundary has inflow velocity !!!! ');
134  end;
135  end
136  else % neumann boundary empty
137  if decomp_mode == 0
138  L_E_neu = sparse(n,n);
139  b_E_neu = zeros(n,1);
140  else % decomp_mode == 1
141  % L_E_neu = {}; %{sparse(n,n)};
142  % b_E_neu = {}; % {zeros(n,1)};
143  % cannot determine in mode==2, whether neumann boundary is empty. So
144  % at least one component must be provided.
145  L_E_neu = {sparse(n,n)};
146  b_E_neu = {zeros(n,1)};
147  end; % neumann boundary nonempty
148  end; % neumann-boundary empty select
149 
150 end; % decomp_mode ==0 or 1
151 
152 
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 [ L_I_diff , bdir_I_diff ] = fv_operators_diff_implicit_gradient(model, model_data, U, NU_ind)
computes diffusion contributions to finite volume time evolution matrices, or their Frechet derivati...
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 [ L_E_neu , b_E_neu ] = fv_operators_neumann_explicit(model, model_data, U, NU_ind)
computes a neumann contribution matrix for finite volume time evolution operators, or their Frechet derivative