Mercurial > repos > public > sbplib
comparison +scheme/Beam.m @ 832:5573913a0949 feature/burgers1d
Merged with default, and updated +scheme/Burgers1D accordingly
author | Vidar Stiernström <vidar.stiernstrom@it.uu.se> |
---|---|
date | Tue, 11 Sep 2018 15:58:35 +0200 |
parents | 4ced7d47bd1f |
children | 459eeb99130f |
comparison
equal
deleted
inserted
replaced
831:d0934d1143b7 | 832:5573913a0949 |
---|---|
1 classdef Beam < scheme.Scheme | |
2 properties | |
3 order % Order accuracy for the approximation | |
4 grid | |
5 | |
6 D % non-stabalized scheme operator | |
7 alpha | |
8 | |
9 h | |
10 H % Discrete norm | |
11 Hi | |
12 | |
13 e_l, e_r | |
14 d1_l, d1_r | |
15 d2_l, d2_r | |
16 d3_l, d3_r | |
17 gamm | |
18 delt | |
19 alphaII | |
20 alphaIII | |
21 | |
22 opt | |
23 end | |
24 | |
25 methods | |
26 function obj = Beam(grid, order, alpha, opsGen, opt) | |
27 default_arg('alpha', -1); | |
28 | |
29 % default_arg('opsGen', @sbp.D4); | |
30 default_arg('opsGen', @sbp.D4Variable); % Supposed to be better | |
31 | |
32 opt_default.interface_l.tuning = 1.1; | |
33 opt_default.interface_l.tau = []; | |
34 opt_default.interface_l.sig = []; | |
35 opt_default.interface_r.tuning = 1.1; | |
36 opt_default.interface_r.tau = []; | |
37 opt_default.interface_r.sig = []; | |
38 default_struct('opt', opt_default); | |
39 | |
40 if ~isa(grid, 'grid.Cartesian') || grid.D() ~= 1 | |
41 error('Grid must be 1d cartesian'); | |
42 end | |
43 | |
44 obj.grid = grid; | |
45 obj.order = order; | |
46 obj.alpha = alpha; | |
47 | |
48 m = grid.m; | |
49 h = grid.scaling(); | |
50 | |
51 x_lim = {grid.x{1}(1), grid.x{1}(end)}; | |
52 ops = opsGen(m, x_lim, order); | |
53 | |
54 D4 = ops.D4; | |
55 obj.H = ops.H; | |
56 obj.Hi = ops.HI; | |
57 obj.e_l = ops.e_l; | |
58 obj.e_r = ops.e_r; | |
59 obj.d1_l = ops.d1_l; | |
60 obj.d1_r = ops.d1_r; | |
61 obj.d2_l = ops.d2_l; | |
62 obj.d2_r = ops.d2_r; | |
63 obj.d3_l = ops.d3_l; | |
64 obj.d3_r = ops.d3_r; | |
65 | |
66 obj.D = alpha*D4; | |
67 | |
68 alphaII = ops.borrowing.N.S2/2; | |
69 alphaIII = ops.borrowing.N.S3/2; | |
70 | |
71 obj.gamm = h*alphaII; | |
72 obj.delt = h^3*alphaIII; | |
73 obj.alphaII = alphaII; | |
74 obj.alphaIII = alphaIII; | |
75 obj.h = h; | |
76 obj.opt = opt; | |
77 end | |
78 | |
79 | |
80 % Closure functions return the opertors applied to the own doamin to close the boundary | |
81 % Penalty functions return the opertors to force the solution. In the case of an interface it returns the operator applied to the other doamin. | |
82 % boundary is a string specifying the boundary e.g. 'l','r' or 'e','w','n','s'. | |
83 % type is a string specifying the type of boundary condition if there are several. | |
84 % neighbour_scheme is an instance of Scheme that should be interfaced to. | |
85 % neighbour_boundary is a string specifying which boundary to interface to. | |
86 function [closure, penalty] = boundary_condition(obj,boundary,type) | |
87 default_arg('type','dn'); | |
88 | |
89 [e, d1, d2, d3, s] = obj.get_boundary_ops(boundary); | |
90 gamm = obj.gamm; | |
91 delt = obj.delt; | |
92 | |
93 | |
94 % TODO: Can this be simplifed? Can I handle conditions on u on its own, u_x on its own ... | |
95 | |
96 switch type | |
97 case {'dn', 'clamped'} % Dirichlet-neumann boundary condition | |
98 alpha = obj.alpha; | |
99 | |
100 % tau1 < -alpha^2/gamma | |
101 % tuning = 2; | |
102 tuning = 1.1; | |
103 | |
104 tau1 = tuning * alpha/delt; | |
105 tau4 = s*alpha; | |
106 | |
107 sig2 = tuning * alpha/gamm; | |
108 sig3 = -s*alpha; | |
109 | |
110 tau = tau1*e+tau4*d3; | |
111 sig = sig2*d1+sig3*d2; | |
112 | |
113 closure = obj.Hi*(tau*e' + sig*d1'); | |
114 | |
115 penalty{1} = -obj.Hi*tau; | |
116 penalty{2} = -obj.Hi*sig; | |
117 | |
118 | |
119 case {'free'} | |
120 a = obj.alpha; | |
121 | |
122 tau = s*a*d1; | |
123 sig = -s*a*e; | |
124 | |
125 closure = obj.Hi*(tau*d2' + sig*d3'); | |
126 penalty{1} = -obj.Hi*tau; | |
127 penalty{1} = -obj.Hi*sig; | |
128 | |
129 case 'e' | |
130 alpha = obj.alpha; | |
131 tuning = 1.1; | |
132 | |
133 tau1 = tuning * alpha/delt; | |
134 tau4 = s*alpha; | |
135 | |
136 tau = tau1*e+tau4*d3; | |
137 | |
138 closure = obj.Hi*tau*e'; | |
139 penalty = -obj.Hi*tau; | |
140 case 'd1' | |
141 alpha = obj.alpha; | |
142 | |
143 tuning = 1.1; | |
144 | |
145 sig2 = tuning * alpha/gamm; | |
146 sig3 = -s*alpha; | |
147 | |
148 sig = sig2*d1+sig3*d2; | |
149 | |
150 closure = obj.Hi*sig*d1'; | |
151 penalty = -obj.Hi*sig; | |
152 | |
153 case 'd2' | |
154 a = obj.alpha; | |
155 | |
156 tau = s*a*d1; | |
157 | |
158 closure = obj.Hi*tau*d2'; | |
159 penalty = -obj.Hi*tau; | |
160 case 'd3' | |
161 a = obj.alpha; | |
162 | |
163 sig = -s*a*e; | |
164 | |
165 closure = obj.Hi*sig*d3'; | |
166 penalty = -obj.Hi*sig; | |
167 | |
168 otherwise % Unknown, boundary condition | |
169 error('No such boundary condition: type = %s',type); | |
170 end | |
171 end | |
172 | |
173 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary) | |
174 % u denotes the solution in the own domain | |
175 % v denotes the solution in the neighbour domain | |
176 [e_u,d1_u,d2_u,d3_u,s_u] = obj.get_boundary_ops(boundary); | |
177 [e_v,d1_v,d2_v,d3_v,s_v] = neighbour_scheme.get_boundary_ops(neighbour_boundary); | |
178 | |
179 | |
180 alpha_u = obj.alpha; | |
181 alpha_v = neighbour_scheme.alpha; | |
182 | |
183 | |
184 switch boundary | |
185 case 'l' | |
186 interface_opt = obj.opt.interface_l; | |
187 case 'r' | |
188 interface_opt = obj.opt.interface_r; | |
189 end | |
190 | |
191 | |
192 if isempty(interface_opt.tau) && isempty(interface_opt.sig) | |
193 gamm_u = obj.gamm; | |
194 delt_u = obj.delt; | |
195 | |
196 gamm_v = neighbour_scheme.gamm; | |
197 delt_v = neighbour_scheme.delt; | |
198 | |
199 tuning = interface_opt.tuning; | |
200 | |
201 tau1 = ((alpha_u/2)/delt_u + (alpha_v/2)/delt_v)/2*tuning; | |
202 sig2 = ((alpha_u/2)/gamm_u + (alpha_v/2)/gamm_v)/2*tuning; | |
203 else | |
204 h_u = obj.h; | |
205 h_v = neighbour_scheme.h; | |
206 | |
207 switch neighbour_boundary | |
208 case 'l' | |
209 neighbour_interface_opt = neighbour_scheme.opt.interface_l; | |
210 case 'r' | |
211 neighbour_interface_opt = neighbour_scheme.opt.interface_r; | |
212 end | |
213 | |
214 tau_u = interface_opt.tau; | |
215 sig_u = interface_opt.sig; | |
216 tau_v = neighbour_interface_opt.tau; | |
217 sig_v = neighbour_interface_opt.sig; | |
218 | |
219 tau1 = tau_u/h_u^3 + tau_v/h_v^3; | |
220 sig2 = sig_u/h_u + sig_v/h_v; | |
221 end | |
222 | |
223 tau4 = s_u*alpha_u/2; | |
224 sig3 = -s_u*alpha_u/2; | |
225 phi2 = s_u*1/2; | |
226 psi1 = -s_u*1/2; | |
227 | |
228 tau = tau1*e_u + tau4*d3_u; | |
229 sig = sig2*d1_u + sig3*d2_u ; | |
230 phi = phi2*d1_u ; | |
231 psi = psi1*e_u ; | |
232 | |
233 closure = obj.Hi*(tau*e_u' + sig*d1_u' + phi*alpha_u*d2_u' + psi*alpha_u*d3_u'); | |
234 penalty = -obj.Hi*(tau*e_v' + sig*d1_v' + phi*alpha_v*d2_v' + psi*alpha_v*d3_v'); | |
235 end | |
236 | |
237 % Returns the boundary ops and sign for the boundary specified by the string boundary. | |
238 % The right boundary is considered the positive boundary | |
239 function [e, d1, d2, d3, s] = get_boundary_ops(obj,boundary) | |
240 switch boundary | |
241 case 'l' | |
242 e = obj.e_l; | |
243 d1 = obj.d1_l; | |
244 d2 = obj.d2_l; | |
245 d3 = obj.d3_l; | |
246 s = -1; | |
247 case 'r' | |
248 e = obj.e_r; | |
249 d1 = obj.d1_r; | |
250 d2 = obj.d2_r; | |
251 d3 = obj.d3_r; | |
252 s = 1; | |
253 otherwise | |
254 error('No such boundary: boundary = %s',boundary); | |
255 end | |
256 end | |
257 | |
258 function N = size(obj) | |
259 N = obj.grid.N; | |
260 end | |
261 | |
262 end | |
263 end |