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])
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.
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.
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.
19 % required fields of model:
20 % name_diffusive_num_flux :
'none',
'gradient',
'gradient2'
21 %
'gradient': use edge-midpoints
for diffusivity
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.
33 % Bernard Haasdonk 10.4.2006
35 grid = model_data.grid;
38 NU_ind = 1:grid.nelements;
41 %nu_ind_length = length(NU_ind);
44 num_flux_mat.epsilon = 0;
45 num_flux_mat.G = zeros(size(grid.NBI));
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);
53 dir_NB_ind =find(grid.NBI == -1);
54 neu_NB_ind =find(grid.NBI == -2);
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.'])
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));
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).* ...
82 % determine dirichlet-boundary values as required by convective
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);
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));
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));
103 % set diffusivity bound
104 num_flux_mat.epsilon = diff.epsilon;
106 elseif isequal(model.name_diffusive_num_flux,'gradient2')
107 % 2. method: vector evaluating the diffusivity in all element
109 diff = model.diffusivity_ptr([grid.SX,grid.SY],model);
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));
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)- ...
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);
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);
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));
143 % set diffusivity bound
144 num_flux_mat.epsilon = diff.epsilon;
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
152 if isequal(model.gridtype, '
rectgrid')
153 G_with_nans = zeros(size(num_flux_mat.G));
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
162 % [tmpgrad,bdir] = gradient_approx_matrix(model,model_data,NU_ind,edge);
163 [tmpgrad] = gradient_approx(model,model_data,U,NU_ind,edge);
165 % tmp2 stores the matrix vector product of 'diffusion tensor x
167 % tmpgrad = tmpgrad(NU_ind,:);
168 vlen = size(tmpgrad,1);
169 tmpgrad = reshape(tmpgrad',2*vlen,1);
171 % tmpggrad = model.gravity*repmat([0;grid.EL(1,2)],vlen,1);
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) ];
179 % if edge == 2 || edge == 4
180 % quiver(grid.ECX(:,edge),grid.ECY(:,edge), tmpgrad(:,1), tmpgrad(:,2));
182 % quiver(grid.ECX(:,edge),grid.ECY(:,edge), tmp2(:,1), tmp2(:,2));
187 tmp2 = reshape(tmp2, 2, vlen)';
189 % M = length(NU_ind);
190 % offset = kron(M,NU_ind)-M;
191 % indices = repmat(offset',M,1)+repmat(NU_ind,1,M);
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;
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);
206 num_flux_mat.epsilon = max(max(num_flux_mat.G));
208 error(['gradient_tensor is not implemented for specified gridtype ', ...
212 error ('diffusive numerical flux unknown');
function r = verbose(level, message, messageId)
This function displays messages depending on a message-id and/or a level. Aditionally you can set/res...
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.