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