Mercurial > repos > public > sbplib
comparison +scheme/Hypsyst2d.m @ 423:a2cb0d4f4a02 feature/grids
Merge in default.
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Tue, 07 Feb 2017 15:47:51 +0100 |
parents | 9d1fc984f40d |
children | 459eeb99130f |
comparison
equal
deleted
inserted
replaced
218:da058ce66876 | 423:a2cb0d4f4a02 |
---|---|
1 classdef Hypsyst2d < scheme.Scheme | |
2 properties | |
3 m % Number of points in each direction, possibly a vector | |
4 n %size of system | |
5 h % Grid spacing | |
6 x,y % Grid | |
7 X,Y % Values of x and y for each grid point | |
8 order % Order accuracy for the approximation | |
9 | |
10 D % non-stabalized scheme operator | |
11 A, B, E %Coefficient matrices | |
12 | |
13 H % Discrete norm | |
14 % Norms in the x and y directions | |
15 Hxi,Hyi % Kroneckerd norms. 1'*Hx*v corresponds to integration in the x dir. | |
16 I_x,I_y, I_N | |
17 e_w, e_e, e_s, e_n | |
18 params %parameters for the coeficient matrice | |
19 end | |
20 | |
21 methods | |
22 %Solving Hyperbolic systems on the form u_t=-Au_x-Bu_y-Eu | |
23 function obj = Hypsyst2d(m, lim, order, A, B, E, params) | |
24 default_arg('E', []) | |
25 xlim = lim{1}; | |
26 ylim = lim{2}; | |
27 | |
28 if length(m) == 1 | |
29 m = [m m]; | |
30 end | |
31 | |
32 obj.A=A; | |
33 obj.B=B; | |
34 obj.E=E; | |
35 | |
36 m_x = m(1); | |
37 m_y = m(2); | |
38 obj.params = params; | |
39 | |
40 ops_x = sbp.D2Standard(m_x,xlim,order); | |
41 ops_y = sbp.D2Standard(m_y,ylim,order); | |
42 | |
43 obj.x = ops_x.x; | |
44 obj.y = ops_y.x; | |
45 | |
46 obj.X = kr(obj.x,ones(m_y,1)); | |
47 obj.Y = kr(ones(m_x,1),obj.y); | |
48 | |
49 Aevaluated = obj.evaluateCoefficientMatrix(A, obj.X, obj.Y); | |
50 Bevaluated = obj.evaluateCoefficientMatrix(B, obj.X, obj.Y); | |
51 Eevaluated = obj.evaluateCoefficientMatrix(E, obj.X, obj.Y); | |
52 | |
53 obj.n = length(A(obj.params,0,0)); | |
54 | |
55 I_n = eye(obj.n);I_x = speye(m_x); | |
56 obj.I_x = I_x; | |
57 I_y = speye(m_y); | |
58 obj.I_y = I_y; | |
59 | |
60 | |
61 D1_x = kr(I_n, ops_x.D1, I_y); | |
62 obj.Hxi = kr(I_n, ops_x.HI, I_y); | |
63 D1_y = kr(I_n, I_x, ops_y.D1); | |
64 obj.Hyi = kr(I_n, I_x, ops_y.HI); | |
65 | |
66 obj.e_w = kr(I_n, ops_x.e_l, I_y); | |
67 obj.e_e = kr(I_n, ops_x.e_r, I_y); | |
68 obj.e_s = kr(I_n, I_x, ops_y.e_l); | |
69 obj.e_n = kr(I_n, I_x, ops_y.e_r); | |
70 | |
71 obj.m = m; | |
72 obj.h = [ops_x.h ops_y.h]; | |
73 obj.order = order; | |
74 | |
75 obj.D = -Aevaluated*D1_x-Bevaluated*D1_y-Eevaluated; | |
76 | |
77 end | |
78 | |
79 % Closure functions return the opertors applied to the own doamin to close the boundary | |
80 % Penalty functions return the opertors to force the solution. In the case of an interface it returns the operator applied to the other doamin. | |
81 % boundary is a string specifying the boundary e.g. 'l','r' or 'e','w','n','s'. | |
82 % type is a string specifying the type of boundary condition if there are several. | |
83 % data is a function returning the data that should be applied at the boundary. | |
84 function [closure, penalty] = boundary_condition(obj,boundary,type,L) | |
85 default_arg('type','char'); | |
86 switch type | |
87 case{'c','char'} | |
88 [closure,penalty] = boundary_condition_char(obj,boundary); | |
89 case{'general'} | |
90 [closure,penalty] = boundary_condition_general(obj,boundary,L); | |
91 otherwise | |
92 error('No such boundary condition') | |
93 end | |
94 end | |
95 | |
96 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary) | |
97 error('An interface function does not exist yet'); | |
98 end | |
99 | |
100 function N = size(obj) | |
101 N = obj.m; | |
102 end | |
103 | |
104 function [ret] = evaluateCoefficientMatrix(obj, mat, X, Y) | |
105 params = obj.params; | |
106 | |
107 if isa(mat,'function_handle') | |
108 [rows,cols] = size(mat(params,0,0)); | |
109 matVec = mat(params,X',Y'); | |
110 matVec = sparse(matVec); | |
111 side = max(length(X),length(Y)); | |
112 else | |
113 matVec = mat; | |
114 [rows,cols] = size(matVec); | |
115 side = max(length(X),length(Y)); | |
116 cols = cols/side; | |
117 end | |
118 ret = cell(rows,cols); | |
119 | |
120 for ii = 1:rows | |
121 for jj=1:cols | |
122 ret{ii,jj} = diag(matVec(ii,(jj-1)*side+1:jj*side)); | |
123 end | |
124 end | |
125 ret = cell2mat(ret); | |
126 end | |
127 | |
128 %Characteristic boundary conditions | |
129 function [closure, penalty] = boundary_condition_char(obj,boundary) | |
130 params = obj.params; | |
131 x = obj.x; | |
132 y = obj.y; | |
133 | |
134 switch boundary | |
135 case {'w','W','west'} | |
136 e_ = obj.e_w; | |
137 mat = obj.A; | |
138 boundPos = 'l'; | |
139 Hi = obj.Hxi; | |
140 [V,Vi,D,signVec] = obj.matrixDiag(mat,x(1),y); | |
141 side = max(length(y)); | |
142 case {'e','E','east'} | |
143 e_ = obj.e_e; | |
144 mat = obj.A; | |
145 boundPos = 'r'; | |
146 Hi = obj.Hxi; | |
147 [V,Vi,D,signVec] = obj.matrixDiag(mat,x(end),y); | |
148 side = max(length(y)); | |
149 case {'s','S','south'} | |
150 e_ = obj.e_s; | |
151 mat = obj.B; | |
152 boundPos = 'l'; | |
153 Hi = obj.Hyi; | |
154 [V,Vi,D,signVec] = obj.matrixDiag(mat,x,y(1)); | |
155 side = max(length(x)); | |
156 case {'n','N','north'} | |
157 e_ = obj.e_n; | |
158 mat = obj.B; | |
159 boundPos = 'r'; | |
160 Hi = obj.Hyi; | |
161 [V,Vi,D,signVec] = obj.matrixDiag(mat,x,y(end)); | |
162 side = max(length(x)); | |
163 end | |
164 pos = signVec(1); | |
165 zeroval = signVec(2); | |
166 neg = signVec(3); | |
167 | |
168 switch boundPos | |
169 case {'l'} | |
170 tau = sparse(obj.n*side,pos); | |
171 Vi_plus = Vi(1:pos,:); | |
172 tau(1:pos,:) = -abs(D(1:pos,1:pos)); | |
173 closure = Hi*e_*V*tau*Vi_plus*e_'; | |
174 penalty = -Hi*e_*V*tau*Vi_plus; | |
175 case {'r'} | |
176 tau = sparse(obj.n*side,neg); | |
177 tau((pos+zeroval)+1:obj.n*side,:) = -abs(D((pos+zeroval)+1:obj.n*side,(pos+zeroval)+1:obj.n*side)); | |
178 Vi_minus = Vi((pos+zeroval)+1:obj.n*side,:); | |
179 closure = Hi*e_*V*tau*Vi_minus*e_'; | |
180 penalty = -Hi*e_*V*tau*Vi_minus; | |
181 end | |
182 end | |
183 | |
184 % General boundary condition in the form Lu=g(x) | |
185 function [closure,penalty] = boundary_condition_general(obj,boundary,L) | |
186 params = obj.params; | |
187 x = obj.x; | |
188 y = obj.y; | |
189 | |
190 switch boundary | |
191 case {'w','W','west'} | |
192 e_ = obj.e_w; | |
193 mat = obj.A; | |
194 boundPos = 'l'; | |
195 Hi = obj.Hxi; | |
196 [V,Vi,D,signVec] = obj.matrixDiag(mat,x(1),y); | |
197 L = obj.evaluateCoefficientMatrix(L,x(1),y); | |
198 side = max(length(y)); | |
199 case {'e','E','east'} | |
200 e_ = obj.e_e; | |
201 mat = obj.A; | |
202 boundPos = 'r'; | |
203 Hi = obj.Hxi; | |
204 [V,Vi,D,signVec] = obj.matrixDiag(mat,x(end),y); | |
205 L = obj.evaluateCoefficientMatrix(L,x(end),y); | |
206 side = max(length(y)); | |
207 case {'s','S','south'} | |
208 e_ = obj.e_s; | |
209 mat = obj.B; | |
210 boundPos = 'l'; | |
211 Hi = obj.Hyi; | |
212 [V,Vi,D,signVec] = obj.matrixDiag(mat,x,y(1)); | |
213 L = obj.evaluateCoefficientMatrix(L,x,y(1)); | |
214 side = max(length(x)); | |
215 case {'n','N','north'} | |
216 e_ = obj.e_n; | |
217 mat = obj.B; | |
218 boundPos = 'r'; | |
219 Hi = obj.Hyi; | |
220 [V,Vi,D,signVec] = obj.matrixDiag(mat,x,y(end)); | |
221 L = obj.evaluateCoefficientMatrix(L,x,y(end)); | |
222 side = max(length(x)); | |
223 end | |
224 | |
225 pos = signVec(1); | |
226 zeroval = signVec(2); | |
227 neg = signVec(3); | |
228 | |
229 switch boundPos | |
230 case {'l'} | |
231 tau = sparse(obj.n*side,pos); | |
232 Vi_plus = Vi(1:pos,:); | |
233 Vi_minus = Vi(pos+zeroval+1:obj.n*side,:); | |
234 V_plus = V(:,1:pos); | |
235 V_minus = V(:,(pos+zeroval)+1:obj.n*side); | |
236 | |
237 tau(1:pos,:) = -abs(D(1:pos,1:pos)); | |
238 R = -inv(L*V_plus)*(L*V_minus); | |
239 closure = Hi*e_*V*tau*(Vi_plus-R*Vi_minus)*e_'; | |
240 penalty = -Hi*e_*V*tau*inv(L*V_plus)*L; | |
241 case {'r'} | |
242 tau = sparse(obj.n*side,neg); | |
243 tau((pos+zeroval)+1:obj.n*side,:) = -abs(D((pos+zeroval)+1:obj.n*side,(pos+zeroval)+1:obj.n*side)); | |
244 Vi_plus = Vi(1:pos,:); | |
245 Vi_minus = Vi((pos+zeroval)+1:obj.n*side,:); | |
246 | |
247 V_plus = V(:,1:pos); | |
248 V_minus = V(:,(pos+zeroval)+1:obj.n*side); | |
249 R = -inv(L*V_minus)*(L*V_plus); | |
250 closure = Hi*e_*V*tau*(Vi_minus-R*Vi_plus)*e_'; | |
251 penalty = -Hi*e_*V*tau*inv(L*V_minus)*L; | |
252 end | |
253 end | |
254 | |
255 % Function that diagonalizes a symbolic matrix A as A=V*D*Vi | |
256 % D is a diagonal matrix with the eigenvalues on A on the diagonal sorted by their sign | |
257 % [d+ ] | |
258 % D = [ d0 ] | |
259 % [ d-] | |
260 % signVec is a vector specifying the number of possitive, zero and negative eigenvalues of D | |
261 function [V,Vi, D,signVec] = matrixDiag(obj,mat,x,y) | |
262 params = obj.params; | |
263 syms xs ys | |
264 [V, D]= eig(mat(params,xs,ys)); | |
265 Vi = inv(V); | |
266 xs = x; | |
267 ys = y; | |
268 | |
269 side = max(length(x),length(y)); | |
270 Dret = zeros(obj.n,side*obj.n); | |
271 Vret = zeros(obj.n,side*obj.n); | |
272 Viret = zeros(obj.n,side*obj.n); | |
273 | |
274 for ii = 1:obj.n | |
275 for jj = 1:obj.n | |
276 Dret(jj,(ii-1)*side+1:side*ii) = eval(D(jj,ii)); | |
277 Vret(jj,(ii-1)*side+1:side*ii) = eval(V(jj,ii)); | |
278 Viret(jj,(ii-1)*side+1:side*ii) = eval(Vi(jj,ii)); | |
279 end | |
280 end | |
281 | |
282 D = sparse(Dret); | |
283 V = sparse(Vret); | |
284 Vi = sparse(Viret); | |
285 V = obj.evaluateCoefficientMatrix(V,x,y); | |
286 Vi = obj.evaluateCoefficientMatrix(Vi,x,y); | |
287 D = obj.evaluateCoefficientMatrix(D,x,y); | |
288 DD = diag(D); | |
289 | |
290 poseig = (DD>0); | |
291 zeroeig = (DD==0); | |
292 negeig = (DD<0); | |
293 | |
294 D = diag([DD(poseig); DD(zeroeig); DD(negeig)]); | |
295 V = [V(:,poseig) V(:,zeroeig) V(:,negeig)]; | |
296 Vi = [Vi(poseig,:); Vi(zeroeig,:); Vi(negeig,:)]; | |
297 signVec = [sum(poseig),sum(zeroeig),sum(negeig)]; | |
298 end | |
299 | |
300 end | |
301 end |