1 function [grad,bdir] = gradient_approx_matrix(model,model_data, NU_ind, edge)
2 %
function grad = gradient_approx_matrix(model,model_data, [NU_ind], edge)
4 %
function that returns a matrix with which an approximation of the gradient
5 % over the edge given by
'edge' can be computed.
7 % Martin Drohmann 13.05.2008
9 decomp_mode = model.decomp_mode;
13 bdir = model.dirichlet_values_ptr([],model);
15 grid = model_data.grid;
16 nels = grid.nelements;
21 nu_ind_length = length(NU_ind);
25 %
get a 6-environment of each cell (see get_enbi
for details)
26 ENBI = get_enbi(grid, edge, model.tstep);
28 %%%% Handle dirichlet cells (
"ghost" cells with index -1) %%%%
29 %
if a cell adjacent to the current edge is a _dirichlet_
"ghost" cell,
30 % entries in the matrix UE have to be replaced by exact evaluations at
31 % the dirichlet boundary. The following cases have to be separated:
32 %
case 1: one of the adjacent cells is a ghost
33 % => replace the cell
's entry in UE with the dirichlet value at
35 %
case 2/3: one cell adjacent to the tip is a ghost
36 % => replace the tip
's entry in UE with the dirichlet value at the
39 % find the _row_ index (edge index) of the three cases
40 case1_dir_ind = find(ENBI(:,4) == -1);
41 case2_dir_ind = find(ENBI(:,5) == -1);
42 case3_dir_ind = find(ENBI(:,6) == -1);
44 % the case23_mapper maps to the correct edge tip (correct column index)
47 case23_mapper = [ mod(edge, 4) + 1, edge ];
49 case23_mapper = [ edge, mod(edge, 4) + 1 ];
52 % update the 4-environment concerning dirichlet cells
55 Xdir = grid.ESX(case1_dir_ind, edge);
56 Ydir = grid.ESY(case1_dir_ind, edge);
57 UE(case1_dir_ind, 1) = model.dirichlet_values_ptr([Xdir,Ydir],model);
58 Xdir = grid.X(grid.VI(case2_dir_ind, case23_mapper(1) ));
59 Ydir = grid.Y(grid.VI(case2_dir_ind, case23_mapper(1) ));
60 UE(case2_dir_ind, 2) = model.dirichlet_values_ptr([Xdir,Ydir],model);
61 Xdir = grid.X(grid.VI(case3_dir_ind, case23_mapper(2) ));
62 Ydir = grid.Y(grid.VI(case3_dir_ind, case23_mapper(2) ));
63 UE(case3_dir_ind, 3) = model.dirichlet_values_ptr([Xdir,Ydir],model);
64 else % decomp_mode == 1
65 Xdir = grid.ESX(case1_dir_ind, edge);
66 Ydir = grid.ESY(case1_dir_ind, edge);
67 tmp = model.dirichlet_values_ptr([Xdir,Ydir],model);
68 UE = cell(length(tmp), 3);
69 UE(:,1) = cellfun(@(X)(assemble_UE(X,nels,case1_dir_ind)), tmp, ...
70 'UniformOutput',
false);
71 Xdir = grid.X(grid.VI(case2_dir_ind, case23_mapper(1) ));
72 Ydir = grid.Y(grid.VI(case2_dir_ind, case23_mapper(1) ));
73 tmp = model.dirichlet_values_ptr([Xdir,Ydir],model);
74 UE(:,2) = cellfun(@(X)(assemble_UE(X,nels,case2_dir_ind)), tmp, ...
75 'UniformOutput',
false);
76 Xdir = grid.X(grid.VI(case3_dir_ind, case23_mapper(2) ));
77 Ydir = grid.Y(grid.VI(case3_dir_ind, case23_mapper(2) ));
78 tmp = model.dirichlet_values_ptr([Xdir,Ydir],model);
79 UE(:,3) = cellfun(@(X)(assemble_UE(X,nels,case3_dir_ind)), tmp, ...
80 'UniformOutput',
false);
83 % neuman boundaries!!! For all other ghost cells the entries of
84 % adjacent non-ghost cells are copied. Ghost cells in the corners of
85 % the
rectgrid are assigned in the end by copying one of the already
86 % assigned adjacent ghost-cell. It is unspecified which ghost cell is
88 if(any(any(ENBI(NU_ind, :) == -10)))
89 disp(
'Attention in gradient_approx_matrix! This line should never be executed');
91 dir_bnd_ind1 = ENBI(NU_ind,4) == -1;
92 dir_bnd_ind2 = find(ENBI(NU_ind,[2,5]) == -1);
93 dir_bnd_ind3 = find(ENBI(NU_ind,[3,6]) == -1);
94 case2_dir_ind = find(ENBI(NU_ind,5) == -1);
95 case3_dir_ind = find(ENBI(NU_ind,6) == -1);
96 nb_ind = find(ENBI(:,2) <= 0);
97 ENBI(nb_ind, 2) = ENBI(nb_ind, 1);
98 nb_ind = find(ENBI(:,3) <= 0);
99 ENBI(nb_ind, 3) = ENBI(nb_ind, 1);
100 nb_ind = find(ENBI(:,4) <= 0);
101 ENBI(nb_ind, 4) = ENBI(nb_ind, 1);
102 nb_ind = find(ENBI(:,5) == -2);
103 ENBI(nb_ind, 5) = ENBI(nb_ind, 2);
104 nb_ind = find(ENBI(:,5) <= 0);
105 ENBI(nb_ind, 5) = ENBI(nb_ind, 4);
106 nb_ind = find(ENBI(:,6) == -2);
107 ENBI(nb_ind, 6) = ENBI(nb_ind, 3);
108 nb_ind = find(ENBI(:,6) <= 0);
109 ENBI(nb_ind, 6) = ENBI(nb_ind, 4);
115 I{1} = ones(nu_ind_length, 2);
116 J{1} = ones(nu_ind_length, 2);
117 S{1} = ones(nu_ind_length, 2);
118 I{2} = ones(nu_ind_length, 4);
119 J{2} = ones(nu_ind_length, 4);
120 S{2} = ones(nu_ind_length, 4);
121 I{3} = ones(length(case2_dir_ind), 2);
122 J{3} = ones(length(case2_dir_ind), 2);
123 S{3} = ones(length(case2_dir_ind), 2);
124 I{4} = ones(length(case3_dir_ind), 2);
125 J{4} = ones(length(case3_dir_ind), 2);
126 S{4} = ones(length(case3_dir_ind), 2);
128 horiz_length = grid.EL(1,1);
129 vert_length = grid.EL(1,2);
132 s1factor = -1/horiz_length;
133 s2factor = -1/vert_length;
137 s1factor = -1/vert_length;
138 s2factor = 1/horiz_length;
142 s1factor = 1/horiz_length;
143 s2factor = -1/vert_length;
147 s1factor = 1/vert_length;
148 s2factor = 1/horiz_length;
153 I{1} = repmat(2*(1:nu_ind_length)+order_addend1,1,2);
154 J{1} = ENBI(NU_ind,[1,4]);
155 % J{1}(dir_bnd_ind1,2) = dir_bnd_ind1;
156 S{1} = s1factor * repmat([1,-1],nu_ind_length,1);
157 S{1}(dir_bnd_ind1,2) = 0;
160 I{2} = repmat(2*(1:nu_ind_length)+order_addend2,1,4);
161 J{2} = ENBI(NU_ind,[2,5,3,6]);
162 [row_numbers1,dummy] = ind2sub([nu_ind_length,2],dir_bnd_ind2);
163 [row_numbers2,dummy] = ind2sub([nu_ind_length,2],dir_bnd_ind3);
164 S{2} = s2factor * repmat([1/4,1/4,-1/4,-1/4],nu_ind_length,1);
165 S{2}(row_numbers1,[1,2]) = 0;
166 S{2}(row_numbers2,[3,4]) = 0;
168 I{3} = repmat(2*case2_dir_ind+order_addend2,1,2);
169 J{3} = ENBI(case2_dir_ind,[1,4]);
170 S{3} = s2factor * repmat([-1/4,-1/4],length(case2_dir_ind),1);
172 I{4} = repmat(2*case3_dir_ind+order_addend2,1,2);
173 J{4} = ENBI(case3_dir_ind,[1,4]);
174 S{4} = s2factor * repmat([1/4,1/4],length(case3_dir_ind),1);
177 II = [ reshape(I{1},2*nu_ind_length,1); reshape(I{2},4*nu_ind_length,1); ...
178 reshape(I{3},2*length(case2_dir_ind),1); reshape(I{4},2*length(case3_dir_ind),1) ];
179 JJ = [ reshape(J{1},2*nu_ind_length,1); reshape(J{2},4*nu_ind_length,1); ...
180 reshape(J{3},2*length(case2_dir_ind),1); reshape(J{4},2*length(case3_dir_ind),1) ];
181 SS = [ reshape(S{1},2*nu_ind_length,1); reshape(S{2},4*nu_ind_length,1); ...
182 reshape(S{3},2*length(case2_dir_ind),1); reshape(S{4},2*length(case3_dir_ind),1) ];
186 bdir = [UE(NU_ind,1)./horiz_length, (UE(NU_ind,3)-UE(NU_ind,2))./(vert_length)];
188 bdir = [(UE(NU_ind,2)-UE(NU_ind,3))./(horiz_length), UE(NU_ind,1)./vert_length];
190 bdir = [-UE(NU_ind,1)./horiz_length, (UE(NU_ind,3)-UE(NU_ind,2))./(vert_length)];
192 bdir = [(UE(NU_ind,2)-UE(NU_ind,3))./(horiz_length), -UE(NU_ind,1)./vert_length];
194 bdir = reshape(bdir
', 2*nu_ind_length,1);
195 grad = sparse(II,JJ,SS, 2*nu_ind_length,nels);
196 else %decomp_mode == 1
198 tmp1 = cellfun(@(X)(X(NU_ind)./horiz_length), UE(:,1), ...
199 'UniformOutput
', false);
200 tmp2 = cellfun(@(X,Y)( (X(NU_ind)-Y(NU_ind))./vert_length ), UE(:,3), UE(:,2), ...
201 'UniformOutput
', false);
203 tmp1 = cellfun(@(X,Y)( (X(NU_ind)-Y(NU_ind))./horiz_length ), UE(:,2), UE(:,3), ...
204 'UniformOutput
', false);
205 tmp2 = cellfun(@(X)(X(NU_ind)./vert_length), UE(:,1), ...
206 'UniformOutput
', false);
208 tmp1 = cellfun(@(X)(-X(NU_ind)./horiz_length), UE(:,1), ...
209 'UniformOutput
', false);
210 tmp2 = cellfun(@(X,Y)( (X(NU_ind)-Y(NU_ind))./vert_length ), UE(:,3), UE(:,2),...
211 'UniformOutput
', false);
213 tmp1 = cellfun(@(X,Y)( (X(NU_ind)-Y(NU_ind))./horiz_length ), UE(:,2), UE(:,3), ...
214 'UniformOutput
', false);
215 tmp2 = cellfun(@(X)(-X(NU_ind)./vert_length), UE(:,1), ...
216 'UniformOutput
', false);
218 bdir = cellfun(@(X,Y)([X,Y]), tmp1, tmp2, 'UniformOutput
', false);
219 bdir = cellfun(@(X)(reshape(X', 2*nu_ind_length,1)), bdir,
'UniformOutput',
false);
220 grad = {sparse(II,JJ,SS,2*nu_ind_length,nels)};
226 function [ret] = assemble_UE(X,nels,dir_ind)
A cartesian rectangular grid in two dimensions with axis parallel elements.