rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
fv_num_diff_flux.m
1 function num_flux_mat = fv_num_diff_flux(model, model_data, U, NU_ind)
2 %function num_flux_mat = fv_num_diff_flux(model, model_data, U, [NU_ind])
3 %
4 % function computing a numerical diffusive flux matrix for a convection
5 % diffusion problem. Dirichlet boundary treatment is performed, but
6 % neuman values are set to nan, this must be handled by calling function.
7 %
8 % In case of gradient_approximation for discretization of a
9 % 'gradient_tensor' the parameter NU_ind is necessary, if the gradient
10 % shall only be approximated on the local grid coordinates given by NU_ind.
11 %
12 % fields of num_flux:
13 % epsilon: diffusion coefficient bound
14 % G: the matrix of numerical flux values across the edges.
15 % boundary treatment is performed as follows:
16 % in dirichlet-boundary edges, the neighbour-values are simply set
17 % to this value and the flux is computed.
18 %
19 % required fields of model:
20 % name_diffusive_num_flux : 'none', 'gradient', 'gradient2'
21 % 'gradient': use edge-midpoints for diffusivity
22 % discretization
23 % 'gradient2': use two element-cog values
24 % for diffusivity discretization
25 % instead of edge-midpoint value
26 % 'gradient_tensor': interpolate a gradient at each edge center
27 % and left-multiply it with a 'tensor'
28 % matrix calculated by diffusivity_tensor.
29 % model for diffusivity_tensor must be
30 % given too in this case.
31 % plus additional fields required by dirichlet_values
32 
33 % Bernard Haasdonk 10.4.2006
34 
35  grid = model_data.grid;
36 
37  if isempty(NU_ind)
38  NU_ind = 1:grid.nelements;
39  end
40 
41  %nu_ind_length = length(NU_ind);
42 
43  num_flux_mat = [];
44  num_flux_mat.epsilon = 0;
45  num_flux_mat.G = zeros(size(grid.NBI));
46 
47  % determine index sets of boundary types
48  real_NB_ind = find(grid.NBI>0);
49 % NBIind = grid.NBI(real_NB_ind);
50 % INBind = grid.INB(real_NB_ind);
51 % NB_real_NB_ind = sub2ind(size(grid.NBI),NBIind,INBind);
52 
53  dir_NB_ind =find(grid.NBI == -1);
54  neu_NB_ind =find(grid.NBI == -2);
55 
56  if model.verbose >= 29
57  disp(['found ',num2str(length(real_NB_ind)),' non-boundary edges.'])
58  disp(['found ',num2str(length(dir_NB_ind)),' dirichlet-boundary edges.'])
59  disp(['found ',num2str(length(neu_NB_ind)),' neumann-boundary edges.'])
60  end;
61 
62  %%%%%%%%%%%%%%%%%%% diffusive numerical flux %%%%%%%%%%%%%%%%%%%%%%%%%%
63  if isequal(model.name_diffusive_num_flux,'none')
64  % set output to zero instead of nan
65  num_flux_mat.G(:) = 0;
66  elseif isequal(model.name_diffusive_num_flux,'gradient')
67  % 1. method: evaluation of diffusivity in edge-circumcenter-intersections
68  diff = model.diffusivity_ptr([grid.ESX(:),grid.ESY(:)],model);
69  K = reshape(diff.K,size(grid.ESX));
70  nfaces = size(grid.NBI,2);
71  UU = repmat(U,1,nfaces);
72  % matrix with the neighbouring values products
73  UNB = nan * ones(size(UU));
74  UNB(real_NB_ind) = UU(grid.NBI(real_NB_ind));
75 
76  % set real neighbour values
77  num_flux_mat.G(real_NB_ind) = ...
78  K(real_NB_ind).*grid.EL(real_NB_ind).*(grid.DS(real_NB_ind).^(-1).* ...
79  (UU(real_NB_ind)- ...
80  UNB(real_NB_ind)));
81 
82  % determine dirichlet-boundary values as required by convective
83  % and diffusive flux.
84  if ~isempty(dir_NB_ind)
85  Xdir = grid.ESX(dir_NB_ind);
86  Ydir = grid.ESY(dir_NB_ind);
87  Udir = model.dirichlet_values_ptr([Xdir,Ydir],model);
88  Kdir = K(dir_NB_ind);
89  % determine distances circumcenter to edge-midpoint for
90  % gradient approximation
91  %[dir_NB_i,dir_NB_j] = ind2sub(size(UU),dir_NB_ind);
92  %Ddir = sqrt((grid.ESX(dir_NB_ind)-grid.CX(dir_NB_i)).^2 + ...
93  % (grid.ESY(dir_NB_ind)-grid.CY(dir_NB_i)).^2);
94  % set dirichlet neighbour values
95  %num_flux_mat.G(dir_NB_ind) = ...
96  % grid.EL(dir_NB_ind).*(Ddir.^(-1).* Kdir .*(UU(dir_NB_ind)-Udir));
97 % keyboard
98  num_flux_mat.G(dir_NB_ind) = ...
99  grid.EL(dir_NB_ind).*(grid.DS(dir_NB_ind).^(-1).* Kdir ...
100  .*(UU(dir_NB_ind)-Udir));
101  end;
102 
103  % set diffusivity bound
104  num_flux_mat.epsilon = diff.epsilon;
105 
106  elseif isequal(model.name_diffusive_num_flux,'gradient2')
107  % 2. method: vector evaluating the diffusivity in all element
108  % circumcenters
109  diff = model.diffusivity_ptr([grid.SX,grid.SY],model);
110 
111  nfaces = size(grid.NBI,2);
112  UK = repmat(diff.K.*U,1,nfaces);
113  % matrix with the neighbouring diffusivity products
114  UKNB = nan * ones(size(UK));
115  UKNB(real_NB_ind) = UK(grid.NBI(real_NB_ind));
116 
117  % set real neighbour values
118  num_flux_mat.G(real_NB_ind) = ...
119  grid.S(real_NB_ind).*(grid.DS(real_NB_ind).^(-1).* ...
120  (UK(real_NB_ind)- ...
121  UKNB(real_NB_ind)));
122 
123  % determine dirichlet-boundary values as required by convective
124  % and diffusive flux.
125  if ~isempty(dir_NB_ind)
126  Xdir = grid.ESX(dir_NB_ind);
127  Ydir = grid.ESY(dir_NB_ind);
128  Udir = dirichlet_values(model,Xdir,Ydir);
129  Kdir = diffusivity(model,Xdir, Ydir);
130  % determine distances COG to edge-midpoint for gradient approximation
131  %[dir_NB_i,dir_NB_j] = ind2sub(size(UK),dir_NB_ind);
132  %Ddir = sqrt((grid.Sx(dir_NB_ind)-grid.CX(dir_NB_i)).^2 + ...
133  % (grid.Sy(dir_NB_ind)-grid.CY(dir_NB_i)).^2);
134 
135  % set dirichlet neighbour values
136  %num_flux_mat.G(dir_NB_ind) = ...
137  % grid.S(dir_NB_ind).*(Ddir.^(-1).* (UK(dir_NB_ind)-Udir.*Kdir.K));
138  num_flux_mat.G(dir_NB_ind) = ...
139  grid.EL(dir_NB_ind).*(grid.DS(dir_NB_ind).^(-1).* ...
140  (UK(dir_NB_ind)-Udir.*Kdir.K));
141  end;
142 
143  % set diffusivity bound
144  num_flux_mat.epsilon = diff.epsilon;
145 
146  elseif isequal(model.name_diffusive_num_flux, 'gradient_tensor')
147  % get values in centers of the cells adjacent to the edge an the edges
148  % corner points. The corner values are computed by a 'weighted' average
149  % over the four adjacent cells. Then do an lsq approximation of the
150  % face the four points lie on. QUESTION: How can this be done in 3d and
151  % on general grids?
152  if isequal(model.gridtype, 'rectgrid')
153  G_with_nans = zeros(size(num_flux_mat.G));
154 
155  for edge = 1:4
156  diff = model.diffusivity_tensor_ptr([grid.ECX(NU_ind,edge),grid.ECY(NU_ind,edge)], U, model, 1);
157  diff_k = model.diffusivity_ptr([grid.ECX(NU_ind,edge),grid.ECY(NU_ind,edge)], model, U);
158  % construct the diffusivity matrix D for current edge
159 % diff1 = diff.K1;
160 % diff2 = diff.K2;
161 
162 % [tmpgrad,bdir] = gradient_approx_matrix(model,model_data,NU_ind,edge);
163  [tmpgrad] = gradient_approx(model,model_data,U,NU_ind,edge);
164 
165  % tmp2 stores the matrix vector product of 'diffusion tensor x
166  % gradient'
167 % tmpgrad = tmpgrad(NU_ind,:);
168  vlen = size(tmpgrad,1);
169  tmpgrad = reshape(tmpgrad',2*vlen,1);
170 
171 % tmpggrad = model.gravity*repmat([0;grid.EL(1,2)],vlen,1);
172 
173  tmp1 = diff_k.K * diff.K;
174  tmp2 = tmp1 * tmpgrad;
175 % tmp22 = tmp1 * tmpgrad2;
176 % tmp2 = [ sum(diff1 .* tmpgrad, 2), ...
177 % sum(diff2 .* tmpgrad, 2) ];
178 
179 % if edge == 2 || edge == 4
180 % quiver(grid.ECX(:,edge),grid.ECY(:,edge), tmpgrad(:,1), tmpgrad(:,2));
181 % hold on;
182 % quiver(grid.ECX(:,edge),grid.ECY(:,edge), tmp2(:,1), tmp2(:,2));
183 % hold off;
184 % keyboard;
185 % end
186 
187  tmp2 = reshape(tmp2, 2, vlen)';
188 
189 % M = length(NU_ind);
190 % offset = kron(M,NU_ind)-M;
191 % indices = repmat(offset',M,1)+repmat(NU_ind,1,M);
192 
193  G_with_nans(NU_ind,edge) = sum(tmp2 .* [ grid.NX(NU_ind,edge), grid.NY(NU_ind,edge) ], 2);
194 % helper = sparse([1:nu_ind_length,1:nu_ind_length], ...
195 % [2*(1:nu_ind_length)-1, 2*(1:nu_ind_length)], ...
196 % reshape( [grid.NX(NU_ind,edge), grid.NY(NU_ind,edge)], 1, 2*nu_ind_length ) );
197 % G_with_nans_temp = helper * tmp2;
198 % G_with_nans_temp = G_with_nans_temp * U + helper * tmp1 * bdir;
199 % max(max(G_with_nans_temp - G_with_nans(NU_ind, edge)))
200 % G_with_nans(NU_ind, edge) = G_with_nans_temp * U + helper * tmp1 * bdir;
201  end
202  G_with_nans = G_with_nans .* grid.EL;
203  num_flux_mat.G(real_NB_ind) = G_with_nans(real_NB_ind);
204  num_flux_mat.G(dir_NB_ind) = G_with_nans(dir_NB_ind);
205 
206  num_flux_mat.epsilon = max(max(num_flux_mat.G));
207  else
208  error(['gradient_tensor is not implemented for specified gridtype ', ...
209  model.gridtype]);
210  end
211  else
212  error ('diffusive numerical flux unknown');
213  end;
214 
215 % vim: set sw=2 et:
216 %| \docupdate
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 Udirichlet = dirichlet_values(model, X, Y)
UDIRICHLET = DIRICHLET_VALUES([X],[Y], MODEL) Examples dirichlet_values([0,1,2],[1,1,1],struct(name_dirichlet_values, homogeneous, ... c_dir, 1)) dirichlet_values([0:0.1:1],[0],struct(name_dirichlet_values, xstripes, ... c_dir, [0 1 2], ... dir_borders, [0.3 0.6])) dirichlet_values([0:0.1:1],[0],struct(name_dirichlet_values, box, ... c_dir, 1, ... dir_box_xrange, [0.3 0.6], ... dir_box_yrange, [-0.1 0.1]))
A cartesian rectangular grid in two dimensions with axis parallel elements.
Definition: rectgrid.m:17