rbmatlab  1.16.09
 All Classes Namespaces Files Functions Variables Modules Pages
fv_num_diff_flux_gradient.m
Go to the documentation of this file.
1 function num_flux_mat = fv_num_diff_flux_gradient(model, model_data, U, NU_ind)
2 %function num_flux_mat = fv_num_diff_flux_gradient(model, model_data, U, NU_ind)
3 % computes a numerical diffusive flux for a diffusion problem
4 %
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.
8 %
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.
15 %
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`.
22 %
23 % Parameters:
24 % U: Dof vector of finite volume function `u`, i.e. argument for this
25 % operator.
26 %
27 % required fields of model:
28 % diffusivity_ptr: function pointer to diffusivity function `d`
29 % laplacian_ptr: function pointer to non-linear function `l`
30 %
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.
37 %
38 
39 % Bernard Haasdonk 10.4.2006
40 
41 grid = model_data.grid;
42 
43 % if nargin <=3 || isempty(NU_ind)
44 % NU_ind = 1:grid.nelements;
45 % end
46 
47 num_flux_mat = [];
48 num_flux_mat.epsilon = 0;
49 num_flux_mat.G = zeros(size(grid.NBI));
50 
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);
56 
57 dir_NB_ind =find(grid.NBI == -1);
58 neu_NB_ind =find(grid.NBI == -2);
59 
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.'])
64 end;
65 
66 % 1. method: evaluation of diffusivity in edge-circumcenter-intersections
67 
68 tmpU = repmat(U, 1, grid.nneigh);
69 neiU = tmpU;
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);
76 
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);
81 end
82 mymean = model.mean_ptr;
83 %mymean = @geomean;
84 %mymean = @mean;
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;
89 else
90  K = reshape(diff.K,size(grid.ESX));
91 end
92 nfaces = size(grid.NBI,2);
93 
94 UU = model.laplacian_ptr([grid.CX(:), grid.CY(:)], U(:), model);
95 
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));
100 
101 
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)- ...
106  UNB(real_NB_ind)));
107 
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);
116  Kdir = Kdir.K;
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));
128 end
129 
130 % num_flux_mat.G = num_flux_mat.G(NU_ind, :);
131 
132 % set diffusivity bound
133 num_flux_mat.epsilon = diff.epsilon;
134 
135 end
136 
137 % vim: set sw=2 et:
function num_flux_mat = fv_num_diff_flux_gradient(model, model_data, U, NU_ind)
computes a numerical diffusive flux for a diffusion problem