Mercurial > repos > public > sbplib
comparison +scheme/Hypsyst2dCurve.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 Hypsyst2dCurve < 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 % Values of x and y for each grid point | |
7 | |
8 J, Ji % Jacobaian and inverse Jacobian | |
9 xi,eta | |
10 Xi,Eta | |
11 | |
12 A,B | |
13 X_eta, Y_eta | |
14 X_xi,Y_xi | |
15 order % Order accuracy for the approximation | |
16 | |
17 D % non-stabalized scheme operator | |
18 Ahat, Bhat, E | |
19 | |
20 H % Discrete norm | |
21 Hxii,Hetai % Kroneckerd norms in xi and eta. | |
22 I_xi,I_eta, I_N, onesN | |
23 e_w, e_e, e_s, e_n | |
24 index_w, index_e,index_s,index_n | |
25 params % Parameters for the coeficient matrice | |
26 end | |
27 | |
28 | |
29 methods | |
30 % Solving Hyperbolic systems on the form u_t=-Au_x-Bu_y-Eu | |
31 function obj = Hypsyst2dCurve(m, order, A, B, E, params, ti) | |
32 default_arg('E', []) | |
33 xilim = {0 1}; | |
34 etalim = {0 1}; | |
35 | |
36 if length(m) == 1 | |
37 m = [m m]; | |
38 end | |
39 obj.params = params; | |
40 obj.A=A; | |
41 obj.B=B; | |
42 | |
43 obj.Ahat=@(params,x,y,x_eta,y_eta)(A(params,x,y).*y_eta-B(params,x,y).*x_eta); | |
44 obj.Bhat=@(params,x,y,x_xi,y_xi)(B(params,x,y).*x_xi-A(params,x,y).*y_xi); | |
45 obj.E=@(params,x,y,~,~)E(params,x,y); | |
46 | |
47 m_xi = m(1); | |
48 m_eta = m(2); | |
49 m_tot=m_xi*m_eta; | |
50 | |
51 ops_xi = sbp.D2Standard(m_xi,xilim,order); | |
52 ops_eta = sbp.D2Standard(m_eta,etalim,order); | |
53 | |
54 obj.xi = ops_xi.x; | |
55 obj.eta = ops_eta.x; | |
56 | |
57 obj.Xi = kr(obj.xi,ones(m_eta,1)); | |
58 obj.Eta = kr(ones(m_xi,1),obj.eta); | |
59 | |
60 obj.n = length(A(obj.params,0,0)); | |
61 obj.onesN=ones(obj.n); | |
62 | |
63 obj.index_w=1:m_eta; | |
64 obj.index_e=(m_tot-m_e | |
65 | |
66 metric_termsta+1):m_tot; | |
67 obj.index_s=1:m_eta:(m_tot-m_eta+1); | |
68 obj.index_n=(m_eta):m_eta:m_tot; | |
69 | |
70 I_n = eye(obj.n); | |
71 I_xi = speye(m_xi); | |
72 obj.I_xi = I_xi; | |
73 I_eta = speye(m_eta); | |
74 obj.I_eta = I_eta; | |
75 | |
76 D1_xi = kr(I_n, ops_xi.D1, I_eta); | |
77 obj.Hxii = kr(I_n, ops_xi.HI, I_eta); | |
78 D1_eta = kr(I_n, I_xi, ops_eta.D1); | |
79 obj.Hetai = kr(I_n, I_xi, ops_eta.HI); | |
80 | |
81 obj.e_w = kr(I_n, ops_xi.e_l, I_eta); | |
82 obj.e_e = kr(I_n, ops_xi.e_r, I_eta); | |
83 obj.e_s = kr(I_n, I_xi, ops_eta.e_l); | |
84 obj.e_n = kr(I_n, I_xi, | |
85 | |
86 metric_termsops_eta.e_r); | |
87 | |
88 [X,Y] = ti.map(obj.xi,obj.eta); | |
89 | |
90 [x_xi,x_eta] = gridDerivatives(X,ops_xi.D1,ops_eta.D1); | |
91 [y_xi,y_eta] = gridDerivatives(Y,ops_xi.D1, ops_eta.D1); | |
92 | |
93 obj.X = reshape(X,m_tot,1); | |
94 obj.Y = reshape(Y,m_tot,1); | |
95 obj.X_xi = reshape(x_xi,m_tot,1); | |
96 obj.Y_xi = reshape(y_xi,m_tot,1); | |
97 obj.X_eta = reshape(x_eta,m_tot,1); | |
98 obj.Y_eta = reshape(y_eta,m_tot,1); | |
99 | |
100 Ahat_evaluated = obj.evaluateCoefficientMatrix(obj.Ahat, obj.X, obj.Y,obj.X_eta,obj.Y_eta); | |
101 Bhat_evaluated = obj.evaluateCoefficientMatrix(obj.Bhat, obj.X, obj.Y,obj.X_xi,obj.Y_xi); | |
102 E_evaluated = obj.evaluateCoefficientMatrix(obj.E, obj.X, obj.Y,[],[]); | |
103 | |
104 obj.m = m; | |
105 obj.h = [ops_xi.h ops_eta.h]; | |
106 obj.order = order; | |
107 obj.J = obj.X_xi.*obj.Y_eta - obj.X_eta.*obj.Y_xi; | |
108 obj.Ji = kr(I_n,spdiags(1./obj.J,0,m_tot,m_tot)); | |
109 | |
110 obj.D = obj.Ji*(-Ahat_evaluated*D1_xi-Bhat_evaluated*D1_eta)-E_evaluated; | |
111 | |
112 end | |
113 | |
114 % Closure functions return the opertors applied to the own doamin to close the boundary | |
115 % Penalty functions return the opertors to force the solution. In the case of an interface it returns the operator applied to the other doamin. | |
116 % boundary is a string specifying the boundary e.g. 'l','r' or 'e','w',General boundary conditions'n','s'. | |
117 % type is a string specifying the type of boundary condition if there are several. | |
118 % data is a function returning the data that should be applied at the boundary. | |
119 function [closure, penalty] = boundary_condition(obj,boundary,type,L) | |
120 default_arg('type','char'); | |
121 switch type | |
122 case{'c','char'} | |
123 [closure,penalty] = boundary_condition_char(obj,boundary); | |
124 case{'general'} | |
125 [closure,penalty] = boundary_condition_general(obj,boundary,L); | |
126 otherwise | |
127 error('No such boundary condition') | |
128 end | |
129 end | |
130 | |
131 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundaryGeneral boundary conditions) | |
132 error('An interface function does not exist yet'); | |
133 end | |
134 | |
135 function N = size(obj) | |
136 N = obj.m; | |
137 end | |
138 | |
139 function [ret] = evaluateCoefficientMatrix(obj, mat, X, Y,x_,y_) | |
140 params = obj.params; | |
141 | |
142 if isa(mat,'function_handle') | |
143 [rows,cols] = size(mat(params,0,0,0,0)); | |
144 x_ = kr(obj.onesN,x_); | |
145 y_ = kr(obj.onesN,y_); | |
146 matVec = mat(params,X',Y',x_',y_'); | |
147 matVec = sparse(matVec); | |
148 side = max(length(X),length(Y)); | |
149 else | |
150 matVec = mat; | |
151 [rows,cols] = size(matVec); | |
152 side = max(length(X),length(Y)); | |
153 cols = cols/side; | |
154 end | |
155 | |
156 ret = cell(rows,cols); | |
157 for ii = 1:rows | |
158 for jj = 1:cols | |
159 ret{ii,jj} = diag(matVec(ii,(jj-1)*side+1:jj*side)); | |
160 end | |
161 end | |
162 ret = cell2mat(ret); | |
163 end | |
164 | |
165 %Characteristic boundary conditions | |
166 function [closure, penalty] = boundary_condition_char(obj,boundary) | |
167 params = obj.params; | |
168 X = obj.X; | |
169 Y = obj.Y; | |
170 xi = obj.xi; | |
171 eta = obj.eta; | |
172 | |
173 switch boundary | |
174 case {'w','W','west'} | |
175 e_ = obj.e_w; | |
176 mat = obj.Ahat; | |
177 boundPos = 'l'; | |
178 Hi = obj.Hxii; | |
179 [V,Vi,D,signVec] = obj.matrixDiag(mat,X(obj.index_w),Y(obj.index_w),obj.X_eta(obj.index_w),obj.Y_eta(obj.index_w)); | |
180 side = max(length(eta)); | |
181 case {'e','E','east'} | |
182 e_ = obj.e_e; | |
183 mat = obj.Ahat; | |
184 boundPos = 'r'; | |
185 Hi = obj.Hxii; | |
186 [V,Vi,D,signVec] = obj.matrixDiag(mat,X(obj.index_e),Y(obj.index_e),obj.X_eta(obj.index_e),obj.Y_eta(obj.index_e)); | |
187 side = max(length(eta)); | |
188 case {'s','S','south'} | |
189 e_ = obj.e_s; | |
190 mat = obj.Bhat; | |
191 boundPos = 'l'; | |
192 Hi = obj.Hetai; | |
193 [V,Vi,D,signVec] = obj.matrixDiag(mat,X(obj.index_s),Y(obj.index_s),obj.X_xi(obj.index_s),obj.Y_xi(obj.index_s)); | |
194 side = max(length(xi)); | |
195 case {'n','N','north'} | |
196 e_ = obj.e_n; | |
197 mat = obj.Bhat; | |
198 boundPos = 'r'; | |
199 Hi = obj.Hetai; | |
200 [V,Vi,D,signVec] = obj.matrixDiag(mat,X(obj.index_n),Y(obj.index_n),obj.X_xi(obj.index_n),obj.Y_xi(obj.index_n)); | |
201 side = max(length(xi)); | |
202 end | |
203 | |
204 pos = signVec(1); | |
205 zeroval = signVec(2); | |
206 neg = signVec(3); | |
207 | |
208 switch boundPos | |
209 case {'l'} | |
210 tau = sparse(obj.n*side,pos); | |
211 Vi_plus = Vi(1:pos,:); | |
212 tau(1:pos,:) = -abs(D(1:pos,1:pos)); | |
213 closure = Hi*e_*V*tau*Vi_plus*e_'; | |
214 penalty = -Hi*e_*V*tau*Vi_plus; | |
215 case {'r'} | |
216 tau = sparse(obj.n*side,neg); | |
217 tau((pos+zeroval)+1:obj.n*side,:) = -abs(D((pos+zeroval)+1:obj.n*side,(pos+zeroval)+1:obj.n*side)); | |
218 Vi_minus = Vi((pos+zeroval)+1:obj.n*side,:); | |
219 closure = Hi*e_*V*tau*Vi_minus*e_'; | |
220 penalty = -Hi*e_*V*tau*Vi_minus; | |
221 end | |
222 end | |
223 | |
224 | |
225 % General boundary condition in the form Lu=g(x) | |
226 function [closure,penalty] = boundary_condition_general(obj,boundary,L) | |
227 params = obj.params; | |
228 X = obj.X; | |
229 Y = obj.Y; | |
230 xi = obj.xi; | |
231 eta = obj.eta; | |
232 | |
233 switch boundary | |
234 case {'w','W','west'} | |
235 e_ = obj.e_w; | |
236 mat = obj.Ahat; | |
237 boundPos = 'l'; | |
238 Hi = obj.Hxii; | |
239 [V,Vi,D,signVec] = obj.matrixDiag(mat,X(obj.index_w),Y(obj.index_w),obj.X_eta(obj.index_w),obj.Y_eta(obj.index_w)); | |
240 | |
241 Ji_vec = diag(obj.Ji); | |
242 Ji = diag(Ji_vec(obj.index_w)); | |
243 xi_x = Ji*obj.Y_eta(obj.index_w); | |
244 xi_y = -Ji*obj.X_eta(obj.index_w); | |
245 L = obj.evaluateCoefficientMatrix(L,xi_x,xi_y,[],[]); | |
246 side = max(length(eta)); | |
247 case {'e','E','east'} | |
248 e_ = obj.e_e; | |
249 mat = obj.Ahat; | |
250 boundPos = 'r'; | |
251 Hi = obj.Hxii; | |
252 [V,Vi,D,signVec] = obj.matrixDiag(mat,X(obj.index_e),Y(obj.index_e),obj.X_eta(obj.index_e),obj.Y_eta(obj.index_e)); | |
253 | |
254 Ji_vec = diag(obj.Ji); | |
255 Ji = diag(Ji_vec(obj.index_e)); | |
256 xi_x = Ji*obj.Y_eta(obj.index_e); | |
257 xi_y = -Ji*obj.X_eta(obj.index_e); | |
258 L = obj.evaluateCoefficientMatrix(L,-xi_x,-xi_y,[],[]); | |
259 side = max(length(eta)); | |
260 case {'s','S','south'} | |
261 e_ = obj.e_s; | |
262 mat = obj.Bhat; | |
263 boundPos = 'l'; | |
264 Hi = obj.Hetai; | |
265 [V,Vi,D,signVec] = obj.matrixDiag(mat,X(obj.index_s),Y(obj.index_s),obj.X_xi(obj.index_s),obj.Y_xi(obj.index_s)); | |
266 | |
267 Ji_vec = diag(obj.Ji); | |
268 Ji = diag(Ji_vec(obj.index_s)); | |
269 eta_x = Ji*obj.Y_xi(obj.index_s); | |
270 eta_y = -Ji*obj.X_xi(obj.index_s); | |
271 L = obj.evaluateCoefficientMatrix(L,eta_x,eta_y,[],[]); | |
272 side = max(length(xi)); | |
273 case {'n','N','north'} | |
274 e_ = obj.e_n; | |
275 mat = obj.Bhat; | |
276 boundPos = 'r'; | |
277 Hi = obj.Hetai; | |
278 [V,Vi,D,signVec] = obj.matrixDiag(mat,X(obj.index_n),Y(obj.index_n),obj.X_xi(obj.index_n),obj.Y_xi(obj.index_n)); | |
279 | |
280 Ji_vec = diag(obj.Ji); | |
281 Ji = diag(Ji_vec(obj.index_n)); | |
282 eta_x = Ji*obj.Y_xi(obj.index_n); | |
283 eta_y = -Ji*obj.X_xi(obj.index_n); | |
284 L = obj.evaluateCoefficientMatrix(L,-eta_x,-eta_y,[],[]); | |
285 side = max(length(xi)); | |
286 end | |
287 | |
288 pos = signVec(1); | |
289 zeroval = signVec(2); | |
290 neg = signVec(3); | |
291 | |
292 switch boundPos | |
293 case {'l'} | |
294 tau = sparse(obj.n*side,pos); | |
295 Vi_plus = Vi(1:pos,:); | |
296 Vi_minus = Vi(pos+1:obj.n*side,:); | |
297 V_plus = V(:,1:pos); | |
298 V_minus = V(:,(pos)+1:obj.n*side); | |
299 | |
300 tau(1:pos,:) = -abs(D(1:pos,1:pos)); | |
301 R = -inv(L*V_plus)*(L*V_minus); | |
302 closure = Hi*e_*V*tau*(Vi_plus-R*Vi_minus)*e_'; | |
303 penalty = -Hi*e_*V*tau*inv(L*V_plus)*L; | |
304 case {'r'} | |
305 tau = sparse(obj.n*side,neg); | |
306 tau((pos+zeroval)+1:obj.n*side,:) = -abs(D((pos+zeroval)+1:obj.n*side,(pos+zeroval)+1:obj.n*side)); | |
307 Vi_plus = Vi(1:pos,:); | |
308 Vi_minus = Vi((pos+zeroval)+1:obj.n*side,:); | |
309 | |
310 V_plus = V(:,1:pos); | |
311 V_minus = V(:,(pos+zeroval)+1:obj.n*side); | |
312 R = -inv(L*V_minus)*(L*V_plus); | |
313 closure = Hi*e_*V*tau*(Vi_minus-R*Vi_plus)*e_'; | |
314 penalty = -Hi*e_*V*tau*inv(L*V_minus)*L; | |
315 end | |
316 end | |
317 | |
318 % Function that diagonalizes a symbolic matrix A as A=V*D*Vi | |
319 % D is a diagonal matrix with the eigenvalues on A on the diagonal sorted by their sign | |
320 % [d+ ] | |
321 % D = [ d0 ] | |
322 % [ d-] | |
323 % signVec is a vector specifying the number of possitive, zero and negative eigenvalues of D | |
324 function [V,Vi, D,signVec] = matrixDiag(obj,mat,x,y,x_,y_) | |
325 params = obj.params; | |
326 syms xs ys | |
327 if(sum(abs(x_)) ~= 0) | |
328 syms xs_ | |
329 else | |
330 xs_ = 0; | |
331 end | |
332 | |
333 if(sum(abs(y_))~= 0) | |
334 syms ys_; | |
335 else | |
336 ys_ = 0; | |
337 end | |
338 | |
339 [V, D] = eig(mat(params,xs,ys,xs_,ys_)); | |
340 Vi = inv(V); | |
341 syms xs ys xs_ ys_ | |
342 | |
343 xs = x; | |
344 ys = y; | |
345 xs_ = x_; | |
346 ys_ = y_; | |
347 | |
348 side = max(length(x),length(y)); | |
349 Dret = zeros(obj.n,side*obj.n); | |
350 Vret = zeros(obj.n,side*obj.n); | |
351 Viret = zeros(obj.n,side*obj.n); | |
352 for ii = 1:obj.n | |
353 for jj = 1:obj.n | |
354 Dret(jj,(ii-1)*side+1:side*ii) = eval(D(jj,ii)); | |
355 Vret(jj,(ii-1)*side+1:side*ii) = eval(V(jj,ii)); | |
356 Viret(jj,(ii-1)*side+1:side*ii) = eval(Vi(jj,ii)); | |
357 end | |
358 end | |
359 | |
360 D = sparse(Dret); | |
361 V = sparse(Vret); | |
362 Vi = sparse(Viret); | |
363 V = obj.evaluateCoefficientMatrix(V,x,y,x_,y_); | |
364 D = obj.evaluateCoefficientMatrix(D,x,y,x_,y_); | |
365 Vi = obj.evaluateCoefficientMatrix(Vi,x,y,x_,y_); | |
366 DD = diag(D); | |
367 | |
368 poseig = (DD>0); | |
369 zeroeig = (DD==0); | |
370 negeig = (DD<0); | |
371 | |
372 D = diag([DD(poseig); DD(zeroeig); DD(negeig)]); | |
373 V = [V(:,poseig) V(:,zeroeig) V(:,negeig)]; | |
374 Vi = [Vi(poseig,:); Vi(zeroeig,:); Vi(negeig,:)]; | |
375 signVec = [sum(poseig),sum(zeroeig),sum(negeig)]; | |
376 end | |
377 end | |
378 end |