comparison +scheme/Utux2D.m @ 914:50cafc4b9e40 feature/utux2D

Make default_field overwrite if field exists but is empty. Refactor interface method in Utux2d.
author Martin Almquist <malmquist@stanford.edu>
date Sun, 25 Nov 2018 21:09:22 -0800
parents b9c98661ff5d
children 35701c85e356
comparison
equal deleted inserted replaced
913:95cd70f4b07d 914:50cafc4b9e40
18 18
19 % Boundary operators 19 % Boundary operators
20 e_w, e_e, e_s, e_n 20 e_w, e_e, e_s, e_n
21 21
22 D % Total discrete operator 22 D % Total discrete operator
23
24 % String, type of interface coupling
25 % Default: 'upwind'
26 % Other: 'centered'
27 coupling_type
28
29 % String, type of interpolation operators
30 % Default: 'AWW' (Almquist Wang Werpers)
31 % Other: 'MC' (Mattsson Carpenter)
32 interpolation_type
33
34
35 % Cell array, damping on upwstream and downstream sides.
36 interpolation_damping
37
38 end 23 end
39 24
40 25
41 methods 26 methods
42 function obj = Utux2D(g ,order, opSet, a, coupling_type, interpolation_type, interpolation_damping) 27 function obj = Utux2D(g ,order, opSet, a)
43 28
44 default_arg('interpolation_damping',{0,0});
45 default_arg('interpolation_type','AWW');
46 default_arg('coupling_type','upwind');
47 default_arg('a',1/sqrt(2)*[1, 1]); 29 default_arg('a',1/sqrt(2)*[1, 1]);
48 default_arg('opSet',@sbp.D2Standard); 30 default_arg('opSet',@sbp.D2Standard);
49 31
50 assert(isa(g, 'grid.Cartesian')) 32 assert(isa(g, 'grid.Cartesian'))
51 if iscell(a) 33 if iscell(a)
100 82
101 obj.m = m; 83 obj.m = m;
102 obj.h = [ops_x.h ops_y.h]; 84 obj.h = [ops_x.h ops_y.h];
103 obj.order = order; 85 obj.order = order;
104 obj.a = a; 86 obj.a = a;
105 obj.coupling_type = coupling_type;
106 obj.interpolation_type = interpolation_type;
107 obj.interpolation_damping = interpolation_damping;
108 obj.D = -(a{1}*obj.Dx + a{2}*obj.Dy); 87 obj.D = -(a{1}*obj.Dx + a{2}*obj.Dy);
109 88
110 end 89 end
111 % Closure functions return the opertors applied to the own domain to close the boundary 90 % Closure functions return the opertors applied to the own domain to close the boundary
112 % Penalty functions return the opertors to force the solution. In the case of an interface it returns the operator applied to the other doamin. 91 % Penalty functions return the opertors to force the solution. In the case of an interface it returns the operator applied to the other doamin.
128 tau = sigma*obj.a{2}*obj.e_s*obj.H_x; 107 tau = sigma*obj.a{2}*obj.e_s*obj.H_x;
129 closure = obj.Hi*tau*obj.e_s'; 108 closure = obj.Hi*tau*obj.e_s';
130 end 109 end
131 penalty = -obj.Hi*tau; 110 penalty = -obj.Hi*tau;
132 111
133 end 112 end
134 113
135 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,opts) 114 % opts Struct that specifies the interface coupling.
136 115 % Fields:
137 % Get neighbour boundary operator 116 % -- couplingType String, type of interface coupling
138 switch neighbour_boundary 117 % % Default: 'upwind'. Other: 'centered'
139 case {'e','E','east','East'} 118 % -- interpolation: struct of interpolation operators (empty for conforming grids)
140 e_neighbour = neighbour_scheme.e_e; 119 % -- interpolationDamping: damping on upstream and downstream sides.
141 m_neighbour = neighbour_scheme.m(2); 120 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,opts)
142 case {'w','W','west','West'} 121 if isempty(opts)
143 e_neighbour = neighbour_scheme.e_w; 122 [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary);
144 m_neighbour = neighbour_scheme.m(2); 123 else
145 case {'n','N','north','North'} 124 assertType(opts, 'struct');
146 e_neighbour = neighbour_scheme.e_n; 125 if isfield(opts, 'I_local2neighbor')
147 m_neighbour = neighbour_scheme.m(1); 126 [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,opts);
148 case {'s','S','south','South'} 127 else
149 e_neighbour = neighbour_scheme.e_s; 128 [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,opts);
150 m_neighbour = neighbour_scheme.m(1); 129 end
151 end 130 end
152 131 end
153 switch obj.coupling_type 132
154 133 function [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,opts)
155 % Upwind coupling (energy dissipation) 134 default_arg('opts', struct);
156 case 'upwind' 135 default_field(opts, 'couplingType', 'upwind');
136 couplingType = opts.couplingType;
137
138 % Get neighbour boundary operator
139 switch neighbour_boundary
140 case {'e','E','east','East'}
141 e_neighbour = neighbour_scheme.e_e;
142 case {'w','W','west','West'}
143 e_neighbour = neighbour_scheme.e_w;
144 case {'n','N','north','North'}
145 e_neighbour = neighbour_scheme.e_n;
146 case {'s','S','south','South'}
147 e_neighbour = neighbour_scheme.e_s;
148 end
149
150 switch couplingType
151
152 % Upwind coupling (energy dissipation)
153 case 'upwind'
157 sigma_ds = -1; %"Downstream" penalty 154 sigma_ds = -1; %"Downstream" penalty
158 sigma_us = 0; %"Upstream" penalty 155 sigma_us = 0; %"Upstream" penalty
159 156
160 % Energy-preserving coupling (no energy dissipation) 157 % Energy-preserving coupling (no energy dissipation)
161 case 'centered' 158 case 'centered'
162 sigma_ds = -1/2; %"Downstream" penalty 159 sigma_ds = -1/2; %"Downstream" penalty
163 sigma_us = 1/2; %"Upstream" penalty 160 sigma_us = 1/2; %"Upstream" penalty
164 161
165 otherwise 162 otherwise
166 error(['Interface coupling type ' coupling_type ' is not available.']) 163 error(['Interface coupling type ' couplingType ' is not available.'])
164 end
165
166 switch boundary
167 case {'w','W','west','West'}
168 tau = sigma_ds*obj.a{1}*obj.e_w*obj.H_y;
169 closure = obj.Hi*tau*obj.e_w';
170 penalty = -obj.Hi*tau*e_neighbour';
171 case {'e','E','east','East'}
172 tau = sigma_us*obj.a{1}*obj.e_e*obj.H_y;
173 closure = obj.Hi*tau*obj.e_e';
174 penalty = -obj.Hi*tau*e_neighbour';
175 case {'s','S','south','South'}
176 tau = sigma_ds*obj.a{2}*obj.e_s*obj.H_x;
177 closure = obj.Hi*tau*obj.e_s';
178 penalty = -obj.Hi*tau*e_neighbour';
179 case {'n','N','north','North'}
180 tau = sigma_us*obj.a{2}*obj.e_n*obj.H_x;
181 closure = obj.Hi*tau*obj.e_n';
182 penalty = -obj.Hi*tau*e_neighbour';
167 end 183 end
168 184
169 % Check grid ratio for interpolation 185 end
170 switch boundary 186
171 case {'w','W','west','West','e','E','east','East'} 187 function [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,opts)
172 m = obj.m(2); 188 default_arg('opts', struct);
173 case {'s','S','south','South','n','N','north','North'} 189 default_field(opts, 'couplingType', 'upwind');
174 m = obj.m(1); 190 default_field(opts, 'interpolationDamping', {0,0});
175 end 191 couplingType = opts.couplingType;
176 grid_ratio = m/m_neighbour; 192 interpolationDamping = opts.interpolationDamping;
177 if grid_ratio ~= 1 193
178 194 % Get neighbour boundary operator
179 [ms, index] = sort([m, m_neighbour]); 195 switch neighbour_boundary
180 orders = [obj.order, neighbour_scheme.order]; 196 case {'e','E','east','East'}
181 orders = orders(index); 197 e_neighbour = neighbour_scheme.e_e;
182 198 case {'w','W','west','West'}
183 switch obj.interpolation_type 199 e_neighbour = neighbour_scheme.e_w;
184 case 'MC' 200 case {'n','N','north','North'}
185 interpOpSet = sbp.InterpMC(ms(1),ms(2),orders(1),orders(2)); 201 e_neighbour = neighbour_scheme.e_n;
186 if grid_ratio < 1 202 case {'s','S','south','South'}
187 I_neighbour2local_us = interpOpSet.IF2C; 203 e_neighbour = neighbour_scheme.e_s;
188 I_neighbour2local_ds = interpOpSet.IF2C; 204 end
189 I_local2neighbour_us = interpOpSet.IC2F; 205
190 I_local2neighbour_ds = interpOpSet.IC2F; 206 switch couplingType
191 elseif grid_ratio > 1 207
192 I_neighbour2local_us = interpOpSet.IC2F; 208 % Upwind coupling (energy dissipation)
193 I_neighbour2local_ds = interpOpSet.IC2F; 209 case 'upwind'
194 I_local2neighbour_us = interpOpSet.IF2C; 210 sigma_ds = -1; %"Downstream" penalty
195 I_local2neighbour_ds = interpOpSet.IF2C; 211 sigma_us = 0; %"Upstream" penalty
196 end 212
197 case 'AWW' 213 % Energy-preserving coupling (no energy dissipation)
198 %String 'C2F' indicates that ICF2 is more accurate. 214 case 'centered'
199 interpOpSetF2C = sbp.InterpAWW(ms(1),ms(2),orders(1),orders(2),'F2C'); 215 sigma_ds = -1/2; %"Downstream" penalty
200 interpOpSetC2F = sbp.InterpAWW(ms(1),ms(2),orders(1),orders(2),'C2F'); 216 sigma_us = 1/2; %"Upstream" penalty
201 if grid_ratio < 1 217
202 % Local is coarser than neighbour 218 otherwise
203 I_neighbour2local_us = interpOpSetC2F.IF2C; 219 error(['Interface coupling type ' couplingType ' is not available.'])
204 I_neighbour2local_ds = interpOpSetF2C.IF2C; 220 end
205 I_local2neighbour_us = interpOpSetC2F.IC2F; 221
206 I_local2neighbour_ds = interpOpSetF2C.IC2F; 222 int_damp_us = interpolationDamping{1};
207 elseif grid_ratio > 1 223 int_damp_ds = interpolationDamping{2};
208 % Local is finer than neighbour 224
209 I_neighbour2local_us = interpOpSetF2C.IC2F; 225 % u denotes the solution in the own domain
210 I_neighbour2local_ds = interpOpSetC2F.IC2F; 226 % v denotes the solution in the neighbour domain
211 I_local2neighbour_us = interpOpSetF2C.IF2C; 227 I_local2neighbour_ds = opts.I_local2neighbor.bad;
212 I_local2neighbour_ds = interpOpSetC2F.IF2C; 228 I_local2neighbour_us = opts.I_local2neighbor.good;
213 end 229 I_neighbour2local_ds = opts.I_neighbor2local.good;
214 otherwise 230 I_neighbour2local_us = opts.I_neighbor2local.bad;
215 error(['Interpolation type ' obj.interpolation_type ... 231
216 ' is not available.' ]); 232 I_back_forth_us = I_neighbour2local_us*I_local2neighbour_us;
217 end 233 I_back_forth_ds = I_neighbour2local_ds*I_local2neighbour_ds;
218
219 else
220 % No interpolation required
221 I_neighbour2local_us = speye(m,m);
222 I_neighbour2local_ds = speye(m,m);
223 end
224
225 int_damp_us = obj.interpolation_damping{1};
226 int_damp_ds = obj.interpolation_damping{2};
227
228 I = speye(m,m);
229 I_back_forth_us = I_neighbour2local_us*I_local2neighbour_us;
230 I_back_forth_ds = I_neighbour2local_ds*I_local2neighbour_ds;
231 234
232 235
233 switch boundary 236 switch boundary
234 case {'w','W','west','West'} 237 case {'w','W','west','West'}
235 tau = sigma_ds*obj.a{1}*obj.e_w*obj.H_y; 238 tau = sigma_ds*obj.a{1}*obj.e_w*obj.H_y;
236 closure = obj.Hi*tau*obj.e_w'; 239 closure = obj.Hi*tau*obj.e_w';
237 penalty = -obj.Hi*tau*I_neighbour2local_ds*e_neighbour'; 240 penalty = -obj.Hi*tau*I_neighbour2local_ds*e_neighbour';
238 241
239 beta = int_damp_ds*obj.a{1}... 242 beta = int_damp_ds*obj.a{1}...
240 *obj.e_w*obj.H_y; 243 *obj.e_w*obj.H_y;
241 closure = closure + obj.Hi*beta*(I_back_forth_ds - I)*obj.e_w'; 244 closure = closure + obj.Hi*beta*I_back_forth_ds*obj.e_w' - obj.Hi*beta*obj.e_w';
242 case {'e','E','east','East'} 245 case {'e','E','east','East'}
243 tau = sigma_us*obj.a{1}*obj.e_e*obj.H_y; 246 tau = sigma_us*obj.a{1}*obj.e_e*obj.H_y;
244 closure = obj.Hi*tau*obj.e_e'; 247 closure = obj.Hi*tau*obj.e_e';
245 penalty = -obj.Hi*tau*I_neighbour2local_us*e_neighbour'; 248 penalty = -obj.Hi*tau*I_neighbour2local_us*e_neighbour';
246 249
247 beta = int_damp_us*obj.a{1}... 250 beta = int_damp_us*obj.a{1}...
248 *obj.e_e*obj.H_y; 251 *obj.e_e*obj.H_y;
249 closure = closure + obj.Hi*beta*(I_back_forth_us - I)*obj.e_e'; 252 closure = closure + obj.Hi*beta*I_back_forth_us*obj.e_e' - obj.Hi*beta*obj.e_e';
250 case {'s','S','south','South'} 253 case {'s','S','south','South'}
251 tau = sigma_ds*obj.a{2}*obj.e_s*obj.H_x; 254 tau = sigma_ds*obj.a{2}*obj.e_s*obj.H_x;
252 closure = obj.Hi*tau*obj.e_s'; 255 closure = obj.Hi*tau*obj.e_s';
253 penalty = -obj.Hi*tau*I_neighbour2local_ds*e_neighbour'; 256 penalty = -obj.Hi*tau*I_neighbour2local_ds*e_neighbour';
254 257
255 beta = int_damp_ds*obj.a{2}... 258 beta = int_damp_ds*obj.a{2}...
256 *obj.e_s*obj.H_x; 259 *obj.e_s*obj.H_x;
257 closure = closure + obj.Hi*beta*(I_back_forth_ds - I)*obj.e_s'; 260 closure = closure + obj.Hi*beta*I_back_forth_ds*obj.e_s' - obj.Hi*beta*obj.e_s';
258 case {'n','N','north','North'} 261 case {'n','N','north','North'}
259 tau = sigma_us*obj.a{2}*obj.e_n*obj.H_x; 262 tau = sigma_us*obj.a{2}*obj.e_n*obj.H_x;
260 closure = obj.Hi*tau*obj.e_n'; 263 closure = obj.Hi*tau*obj.e_n';
261 penalty = -obj.Hi*tau*I_neighbour2local_us*e_neighbour'; 264 penalty = -obj.Hi*tau*I_neighbour2local_us*e_neighbour';
262 265
263 beta = int_damp_us*obj.a{2}... 266 beta = int_damp_us*obj.a{2}...
264 *obj.e_n*obj.H_x; 267 *obj.e_n*obj.H_x;
265 closure = closure + obj.Hi*beta*(I_back_forth_us - I)*obj.e_n'; 268 closure = closure + obj.Hi*beta*I_back_forth_us*obj.e_n' - obj.Hi*beta*obj.e_n';
266 end 269 end
267 270
268 271
269 end 272 end
270 273