Mercurial > repos > public > sbplib
comparison +scheme/Wave2d.m @ 0:48b6fb693025
Initial commit.
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Thu, 17 Sep 2015 10:12:50 +0200 |
parents | |
children | a8ed986fcf57 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:48b6fb693025 |
---|---|
1 classdef SchmWave2d < noname.Scheme | |
2 properties | |
3 m % Number of points in each direction, possibly a vector | |
4 h % Grid spacing | |
5 x,y % Grid | |
6 X,Y % Values of x and y for each grid point | |
7 order % Order accuracy for the approximation | |
8 | |
9 D % non-stabalized scheme operator | |
10 M % Derivative norm | |
11 alpha | |
12 | |
13 H % Discrete norm | |
14 Hi | |
15 H_x, H_y % Norms in the x and y directions | |
16 Hx,Hy % Kroneckerd norms. 1'*Hx*v corresponds to integration in the x dir. | |
17 Hi_x, Hi_y | |
18 Hix, Hiy | |
19 e_w, e_e, e_s, e_n | |
20 d1_w, d1_e, d1_s, d1_n | |
21 gamm_x, gamm_y | |
22 end | |
23 | |
24 methods | |
25 function obj = SchmWave2d(m,xlim,ylim,order,alpha) | |
26 default_arg('a',1); | |
27 | |
28 if length(m) == 1 | |
29 m = [m m]; | |
30 end | |
31 | |
32 m_x = m(1); | |
33 m_y = m(2); | |
34 | |
35 [x, h_x] = util.get_grid(xlim{:},m_x); | |
36 [y, h_y] = util.get_grid(ylim{:},m_y); | |
37 | |
38 ops_x = sbp.Ordinary(m_x,h_x,order); | |
39 ops_y = sbp.Ordinary(m_y,h_y,order); | |
40 | |
41 I_x = speye(m_x); | |
42 I_y = speye(m_y); | |
43 | |
44 D2_x = sparse(ops_x.derivatives.D2); | |
45 H_x = sparse(ops_x.norms.H); | |
46 Hi_x = sparse(ops_x.norms.HI); | |
47 M_x = sparse(ops_x.norms.M); | |
48 e_l_x = sparse(ops_x.boundary.e_1); | |
49 e_r_x = sparse(ops_x.boundary.e_m); | |
50 d1_l_x = sparse(ops_x.boundary.S_1); | |
51 d1_r_x = sparse(ops_x.boundary.S_m); | |
52 | |
53 D2_y = sparse(ops_y.derivatives.D2); | |
54 H_y = sparse(ops_y.norms.H); | |
55 Hi_y = sparse(ops_y.norms.HI); | |
56 M_y = sparse(ops_y.norms.M); | |
57 e_l_y = sparse(ops_y.boundary.e_1); | |
58 e_r_y = sparse(ops_y.boundary.e_m); | |
59 d1_l_y = sparse(ops_y.boundary.S_1); | |
60 d1_r_y = sparse(ops_y.boundary.S_m); | |
61 | |
62 D2 = kr(D2_x, I_y) + kr(I_x, D2_y); | |
63 obj.H = kr(H_x,H_y); | |
64 obj.Hx = kr(H_x,I_y); | |
65 obj.Hy = kr(I_x,H_y); | |
66 obj.Hix = kr(Hi_x,I_y); | |
67 obj.Hiy = kr(I_x,Hi_y); | |
68 obj.Hi = kr(Hi_x,Hi_y); | |
69 obj.M = kr(M_x,H_y)+kr(H_x,M_y); | |
70 obj.e_w = kr(e_l_x,I_y); | |
71 obj.e_e = kr(e_r_x,I_y); | |
72 obj.e_s = kr(I_x,e_l_y); | |
73 obj.e_n = kr(I_x,e_r_y); | |
74 obj.d1_w = kr(d1_l_x,I_y); | |
75 obj.d1_e = kr(d1_r_x,I_y); | |
76 obj.d1_s = kr(I_x,d1_l_y); | |
77 obj.d1_n = kr(I_x,d1_r_y); | |
78 | |
79 obj.m = m; | |
80 obj.h = [h_x h_y]; | |
81 obj.order = order; | |
82 | |
83 obj.alpha = alpha; | |
84 obj.D = alpha*D2; | |
85 obj.x = x; | |
86 obj.y = y; | |
87 obj.X = kr(x,ones(m_y,1)); | |
88 obj.Y = kr(ones(m_x,1),y); | |
89 | |
90 obj.gamm_x = h_x*ops_x.borrowing.M.S; | |
91 obj.gamm_y = h_y*ops_y.borrowing.M.S; | |
92 end | |
93 | |
94 | |
95 % Closure functions return the opertors applied to the own doamin to close the boundary | |
96 % Penalty functions return the opertors to force the solution. In the case of an interface it returns the operator applied to the other doamin. | |
97 % boundary is a string specifying the boundary e.g. 'l','r' or 'e','w','n','s'. | |
98 % type is a string specifying the type of boundary condition if there are several. | |
99 % data is a function returning the data that should be applied at the boundary. | |
100 % neighbour_scheme is an instance of Scheme that should be interfaced to. | |
101 % neighbour_boundary is a string specifying which boundary to interface to. | |
102 function [closure, penalty] = boundary_condition(obj,boundary,type,data) | |
103 default_arg('type','neumann'); | |
104 default_arg('data',0); | |
105 | |
106 [e,d,s,gamm,halfnorm_inv] = obj.get_boundary_ops(boundary); | |
107 | |
108 switch type | |
109 % Dirichlet boundary condition | |
110 case {'D','d','dirichlet'} | |
111 alpha = obj.alpha; | |
112 | |
113 % tau1 < -alpha^2/gamma | |
114 tuning = 1.1; | |
115 tau1 = -tuning*alpha/gamm; | |
116 tau2 = s*alpha; | |
117 | |
118 p = tau1*e + tau2*d; | |
119 | |
120 closure = halfnorm_inv*p*e'; | |
121 | |
122 pp = halfnorm_inv*p; | |
123 switch class(data) | |
124 case 'double' | |
125 penalty = pp*data; | |
126 case 'function_handle' | |
127 penalty = @(t)pp*data(t); | |
128 otherwise | |
129 error('Wierd data argument!') | |
130 end | |
131 | |
132 | |
133 % Neumann boundary condition | |
134 case {'N','n','neumann'} | |
135 alpha = obj.alpha; | |
136 tau1 = -s*alpha; | |
137 tau2 = 0; | |
138 tau = tau1*e + tau2*d; | |
139 | |
140 closure = halfnorm_inv*tau*d'; | |
141 | |
142 pp = halfnorm_inv*tau; | |
143 switch class(data) | |
144 case 'double' | |
145 penalty = pp*data; | |
146 case 'function_handle' | |
147 penalty = @(t)pp*data(t); | |
148 otherwise | |
149 error('Wierd data argument!') | |
150 end | |
151 | |
152 % Unknown, boundary condition | |
153 otherwise | |
154 error('No such boundary condition: type = %s',type); | |
155 end | |
156 end | |
157 | |
158 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary) | |
159 % u denotes the solution in the own domain | |
160 % v denotes the solution in the neighbour domain | |
161 [e_u,d_u,s_u,gamm_u, halfnorm_inv] = obj.get_boundary_ops(boundary); | |
162 [e_v,d_v,s_v,gamm_v] = neighbour_scheme.get_boundary_ops(neighbour_boundary); | |
163 | |
164 tuning = 1.1; | |
165 | |
166 alpha_u = obj.alpha; | |
167 alpha_v = neighbour_scheme.alpha; | |
168 | |
169 % tau1 < -(alpha_u/gamm_u + alpha_v/gamm_v) | |
170 | |
171 tau1 = -(alpha_u/gamm_u + alpha_v/gamm_v) * tuning; | |
172 tau2 = s_u*1/2*alpha_u; | |
173 sig1 = s_u*(-1/2); | |
174 sig2 = 0; | |
175 | |
176 tau = tau1*e_u + tau2*d_u; | |
177 sig = sig1*e_u + sig2*d_u; | |
178 | |
179 closure = halfnorm_inv*( tau*e_u' + sig*alpha_u*d_u'); | |
180 penalty = halfnorm_inv*(-tau*e_v' - sig*alpha_v*d_v'); | |
181 end | |
182 | |
183 % Ruturns the boundary ops and sign for the boundary specified by the string boundary. | |
184 % The right boundary is considered the positive boundary | |
185 function [e,d,s,gamm, halfnorm_inv] = get_boundary_ops(obj,boundary) | |
186 switch boundary | |
187 case 'w' | |
188 e = obj.e_w; | |
189 d = obj.d1_w; | |
190 s = -1; | |
191 gamm = obj.gamm_x; | |
192 halfnorm_inv = obj.Hix; | |
193 case 'e' | |
194 e = obj.e_e; | |
195 d = obj.d1_e; | |
196 s = 1; | |
197 gamm = obj.gamm_x; | |
198 halfnorm_inv = obj.Hix; | |
199 case 's' | |
200 e = obj.e_s; | |
201 d = obj.d1_s; | |
202 s = -1; | |
203 gamm = obj.gamm_y; | |
204 halfnorm_inv = obj.Hiy; | |
205 case 'n' | |
206 e = obj.e_n; | |
207 d = obj.d1_n; | |
208 s = 1; | |
209 gamm = obj.gamm_y; | |
210 halfnorm_inv = obj.Hiy; | |
211 otherwise | |
212 error('No such boundary: boundary = %s',boundary); | |
213 end | |
214 end | |
215 | |
216 function N = size(obj) | |
217 N = prod(obj.m); | |
218 end | |
219 | |
220 end | |
221 | |
222 methods(Static) | |
223 % Calculates the matrcis need for the inteface coupling between boundary bound_u of scheme schm_u | |
224 % and bound_v of scheme schm_v. | |
225 % [uu, uv, vv, vu] = inteface_couplong(A,'r',B,'l') | |
226 function [uu, uv, vv, vu] = interface_coupling(schm_u,bound_u,schm_v,bound_v) | |
227 [uu,uv] = schm_u.interface(bound_u,schm_v,bound_v); | |
228 [vv,vu] = schm_v.interface(bound_v,schm_u,bound_u); | |
229 end | |
230 end | |
231 end |