3 % computes a numerical diffusive flux
for a diffusion problem
5 % This
function computes a numerical diffusive flux matrix
for a diffusion
6 % problem. Dirichlet boundary treatment is performed, but neuman values are set
7 % to
'NaN'. These must be handled by the calling
function.
9 % The analytical term inspiring
this flux looks like
10 % `` \nabla \cdot \left(d(u) \nabla l(u) \right). ``
11 % Here, the functions `d(u)` and `l(u)` differ in the numerical implementation.
12 % The latter is evaluated in cell centers during flux computation, whereas the
13 % diffusion functional `d(u)` is evaluated on the cell edges by averaging the
14 % solutions value there.
16 % The implemented flux then can be written
for inner boundaries as
17 % `` g_{ij}(u,v) = d(\{u,v\}) \frac{l(v) - l(u)}{|d_{ij}|} |e_{ij}| ``
18 % and
for Dirichlet boundaries as
19 % `` g_{dir,ij}(u) = d(u_{dir}(x_{ij}))
20 % \frac{l(u_{dir}(x_{ij})) - l(u)}{|d_{ij}|} |e_{ij}|, ``
21 % where `\{u,v\}` refers to the average of `u` and `v`.
24 % U: Dof vector of finite volume
function `u`, i.e. argument
for this
27 % required fields of model:
28 % diffusivity_ptr:
function pointer to diffusivity
function `d`
29 % laplacian_ptr:
function pointer to non-linear
function `l`
31 % generated fields of num_flux_mat:
32 % epsilon: diffusion coefficient bound
33 % G: the matrix of numerical flux values across the edges.
34 % boundary treatment is performed as follows:
35 % in dirichlet-boundary edges, the neighbour-values are simply set
36 % to
this value and the flux is computed.
39 % Bernard Haasdonk 10.4.2006
41 grid = model_data.grid;
43 %
if nargin <=3 || isempty(NU_ind)
44 % NU_ind = 1:grid.nelements;
48 num_flux_mat.epsilon = 0;
49 num_flux_mat.G = zeros(size(grid.NBI));
51 % determine index sets of boundary types
52 real_NB_ind = find(grid.NBI>0);
53 % NBIind = grid.NBI(real_NB_ind);
54 % INBind = grid.INB(real_NB_ind);
55 % NB_real_NB_ind = sub2ind(size(grid.NBI),NBIind,INBind);
57 dir_NB_ind =find(grid.NBI == -1);
58 neu_NB_ind =find(grid.NBI == -2);
60 if model.verbose >= 29
61 disp([
'found ',num2str(length(real_NB_ind)),
' non-boundary edges.'])
62 disp(['found ',num2str(length(dir_NB_ind)),' dirichlet-boundary edges.'])
63 disp(['found ',num2str(length(neu_NB_ind)),' neumann-boundary edges.'])
66 % 1. method: evaluation of diffusivity in edge-circumcenter-intersections
68 tmpU = repmat(U, 1, grid.nneigh);
70 real_nb_ind = grid.NBI > 0;
71 neiU(real_nb_ind) = U(grid.NBI(real_nb_ind));
72 %edgeU = 0.5 * (tmpU + neiU);
73 %edgeU = sqrt(tmpU.*neiU);
74 %edgeU = min(tmpU, neiU);
75 %edgeU = 2*(tmpU.*neiU)./(tmpU+neiU);
77 difftmp = model.diffusivity_ptr([grid.ESX(:),grid.ESY(:)],tmpU(:),model);
78 diffnei = model.diffusivity_ptr([grid.ESX(:),grid.ESY(:)],neiU(:),model);
79 if ~isfield(model, 'mean_ptr')
80 model.mean_ptr = @(X) mean(X,2);
82 mymean = model.mean_ptr;
85 diff.K = mymean([difftmp.K, diffnei.K]);
86 diff.epsilon = mymean(max([difftmp.epsilon, diffnei.epsilon],0));
87 if length(diff.K) == 1
88 K = ones(size(grid.ESX))*diff.K;
90 K = reshape(diff.K,size(grid.ESX));
92 nfaces = size(grid.NBI,2);
94 UU = model.laplacian_ptr([grid.CX(:), grid.CY(:)], U(:), model);
96 UU = repmat(UU,1,nfaces);
97 % matrix with the neighbouring values products
98 UNB = nan * ones(size(UU));
99 UNB(real_NB_ind) = UU(grid.NBI(real_NB_ind));
102 % set real neighbour values
103 num_flux_mat.G(real_NB_ind) = ...
104 K(real_NB_ind).*grid.EL(real_NB_ind).*(grid.DS(real_NB_ind).^(-1).* ...
105 (UU(real_NB_ind)- ...
108 % determine dirichlet-boundary values as required by convective
109 % and diffusive flux.
110 if ~isempty(dir_NB_ind)
111 Xdir = grid.ESX(dir_NB_ind);
112 Ydir = grid.ESY(dir_NB_ind);
113 Udir = model.dirichlet_values_ptr([Xdir,Ydir],model);
114 Uldir = model.laplacian_ptr([Xdir,Ydir],Udir,model);
115 Kdir = model.diffusivity_ptr([Xdir,Ydir], Udir, model);
117 % determine distances circumcenter to edge-midpoint for
118 % gradient approximation
119 %[dir_NB_i,dir_NB_j] = ind2sub(size(UU),dir_NB_ind);
120 %Ddir = sqrt((grid.ESX(dir_NB_ind)-grid.CX(dir_NB_i)).^2 + ...
121 % (grid.ESY(dir_NB_ind)-grid.CY(dir_NB_i)).^2);
122 % set dirichlet neighbour values
123 %num_flux_mat.G(dir_NB_ind) = ...
124 % grid.EL(dir_NB_ind).*(Ddir.^(-1).* Kdir .*(UU(dir_NB_ind)-Udir));
125 num_flux_mat.G(dir_NB_ind) = ...
126 grid.EL(dir_NB_ind).*((grid.DS(dir_NB_ind)).^(-1).* Kdir ...
127 .*(UU(dir_NB_ind)-Uldir));
130 % num_flux_mat.G = num_flux_mat.G(NU_ind, :);
132 % set diffusivity bound
133 num_flux_mat.epsilon = diff.epsilon;
function num_flux_mat = fv_num_diff_flux_gradient(model, model_data, U, NU_ind)
computes a numerical diffusive flux for a diffusion problem