Mercurial > repos > public > sbplib
comparison +scheme/LaplaceCurvilinear.m @ 1086:90c23fd08f59 feature/laplace_curvilinear_test
Make LaplaceCurvilinearNew the default version and remove the others
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Fri, 29 Mar 2019 14:41:36 -0700 |
parents | 1341c6cea9c1 |
children | 867307f4d80f |
comparison
equal
deleted
inserted
replaced
1085:49c0b8c7330a | 1086:90c23fd08f59 |
---|---|
1 classdef LaplaceCurvilinear < scheme.Scheme | 1 classdef LaplaceCurvilinear < scheme.Scheme |
2 properties | 2 properties |
3 m % Number of points in each direction, possibly a vector | 3 m % Number of points in each direction, possibly a vector |
4 h % Grid spacing | 4 h % Grid spacing |
5 dim % Number of spatial dimensions | |
5 | 6 |
6 grid | 7 grid |
7 | 8 |
8 order % Order accuracy for the approximation | 9 order % Order of accuracy for the approximation |
9 | 10 |
10 a,b % Parameters of the operator | 11 a,b % Parameters of the operator |
11 | 12 |
12 | 13 |
13 % Inner products and operators for physical coordinates | 14 % Inner products and operators for physical coordinates |
20 M % Gradient inner product | 21 M % Gradient inner product |
21 | 22 |
22 % Metric coefficients | 23 % Metric coefficients |
23 J, Ji | 24 J, Ji |
24 a11, a12, a22 | 25 a11, a12, a22 |
26 K | |
25 x_u | 27 x_u |
26 x_v | 28 x_v |
27 y_u | 29 y_u |
28 y_v | 30 y_v |
31 s_w, s_e, s_s, s_n % Boundary integral scale factors | |
29 | 32 |
30 % Inner product and operators for logical coordinates | 33 % Inner product and operators for logical coordinates |
31 H_u, H_v % Norms in the x and y directions | 34 H_u, H_v % Norms in the x and y directions |
32 Hi_u, Hi_v | 35 Hi_u, Hi_v |
33 Hu,Hv % Kroneckerd norms. 1'*Hx*v corresponds to integration in the x dir. | 36 Hu,Hv % Kroneckerd norms. 1'*Hx*v corresponds to integration in the x dir. |
34 Hiu, Hiv | 37 Hiu, Hiv |
35 du_w, dv_w | 38 du_w, dv_w |
36 du_e, dv_e | 39 du_e, dv_e |
37 du_s, dv_s | 40 du_s, dv_s |
38 du_n, dv_n | 41 du_n, dv_n |
42 | |
43 % Borrowing constants | |
44 theta_M_u, theta_M_v | |
45 theta_R_u, theta_R_v | |
46 theta_H_u, theta_H_v | |
47 | |
48 % Temporary | |
49 lambda | |
39 gamm_u, gamm_v | 50 gamm_u, gamm_v |
40 lambda | |
41 | 51 |
42 end | 52 end |
43 | 53 |
44 methods | 54 methods |
45 % Implements a*div(b*grad(u)) as a SBP scheme | 55 % Implements a*div(b*grad(u)) as a SBP scheme |
46 % TODO: Implement proper H, it should be the real physical quadrature, the logic quadrature may be but in a separate variable (H_logic?) | 56 % TODO: Implement proper H, it should be the real physical quadrature, the logic quadrature may be but in a separate variable (H_logic?) |
47 | 57 |
48 function obj = LaplaceCurvilinear(g ,order, a, b, opSet) | 58 function obj = LaplaceCurvilinear(g, order, a, b, opSet) |
49 default_arg('opSet',@sbp.D2Variable); | 59 default_arg('opSet',@sbp.D2Variable); |
50 default_arg('a', 1); | 60 default_arg('a', 1); |
51 default_arg('b', 1); | 61 default_arg('b', @(x,y) 0*x + 1); |
52 | |
53 if b ~=1 | |
54 error('Not implemented yet') | |
55 end | |
56 | 62 |
57 % assert(isa(g, 'grid.Curvilinear')) | 63 % assert(isa(g, 'grid.Curvilinear')) |
58 if isa(a, 'function_handle') | 64 if isa(a, 'function_handle') |
59 a = grid.evalOn(g, a); | 65 a = grid.evalOn(g, a); |
60 a = spdiag(a); | 66 a = spdiag(a); |
61 end | 67 end |
62 | 68 |
69 if isa(b, 'function_handle') | |
70 b = grid.evalOn(g, b); | |
71 b = spdiag(b); | |
72 end | |
73 | |
74 % If b is scalar | |
75 if length(b) == 1 | |
76 b = b*speye(g.N(), g.N()); | |
77 end | |
78 | |
79 dim = 2; | |
63 m = g.size(); | 80 m = g.size(); |
64 m_u = m(1); | 81 m_u = m(1); |
65 m_v = m(2); | 82 m_v = m(2); |
66 m_tot = g.N(); | 83 m_tot = g.N(); |
67 | 84 |
132 a11 = 1./J .* (x_v.^2 + y_v.^2); | 149 a11 = 1./J .* (x_v.^2 + y_v.^2); |
133 a12 = -1./J .* (x_u.*x_v + y_u.*y_v); | 150 a12 = -1./J .* (x_u.*x_v + y_u.*y_v); |
134 a22 = 1./J .* (x_u.^2 + y_u.^2); | 151 a22 = 1./J .* (x_u.^2 + y_u.^2); |
135 lambda = 1/2 * (a11 + a22 - sqrt((a11-a22).^2 + 4*a12.^2)); | 152 lambda = 1/2 * (a11 + a22 - sqrt((a11-a22).^2 + 4*a12.^2)); |
136 | 153 |
154 K = cell(dim, dim); | |
155 K{1,1} = spdiag(y_v./J); | |
156 K{1,2} = spdiag(-y_u./J); | |
157 K{2,1} = spdiag(-x_v./J); | |
158 K{2,2} = spdiag(x_u./J); | |
159 obj.K = K; | |
160 | |
137 obj.x_u = x_u; | 161 obj.x_u = x_u; |
138 obj.x_v = x_v; | 162 obj.x_v = x_v; |
139 obj.y_u = y_u; | 163 obj.y_u = y_u; |
140 obj.y_v = y_v; | 164 obj.y_v = y_v; |
141 | 165 |
142 | |
143 % Assemble full operators | 166 % Assemble full operators |
144 L_12 = spdiag(a12); | 167 L_12 = spdiag(a12); |
145 Duv = Du*L_12*Dv; | 168 Duv = Du*b*L_12*Dv; |
146 Dvu = Dv*L_12*Du; | 169 Dvu = Dv*b*L_12*Du; |
147 | 170 |
148 Duu = sparse(m_tot); | 171 Duu = sparse(m_tot); |
149 Dvv = sparse(m_tot); | 172 Dvv = sparse(m_tot); |
150 ind = grid.funcToMatrix(g, 1:m_tot); | 173 ind = grid.funcToMatrix(g, 1:m_tot); |
151 | 174 |
152 for i = 1:m_v | 175 for i = 1:m_v |
153 D = D2_u(a11(ind(:,i))); | 176 b_a11 = b*a11; |
177 D = D2_u(b_a11(ind(:,i))); | |
154 p = ind(:,i); | 178 p = ind(:,i); |
155 Duu(p,p) = D; | 179 Duu(p,p) = D; |
156 end | 180 end |
157 | 181 |
158 for i = 1:m_u | 182 for i = 1:m_u |
159 D = D2_v(a22(ind(i,:))); | 183 b_a22 = b*a22; |
184 D = D2_v(b_a22(ind(i,:))); | |
160 p = ind(i,:); | 185 p = ind(i,:); |
161 Dvv(p,p) = D; | 186 Dvv(p,p) = D; |
162 end | 187 end |
163 | 188 |
164 | 189 |
212 % Misc. | 237 % Misc. |
213 obj.m = m; | 238 obj.m = m; |
214 obj.h = [h_u h_v]; | 239 obj.h = [h_u h_v]; |
215 obj.order = order; | 240 obj.order = order; |
216 obj.grid = g; | 241 obj.grid = g; |
242 obj.dim = dim; | |
217 | 243 |
218 obj.a = a; | 244 obj.a = a; |
219 obj.b = b; | 245 obj.b = b; |
220 obj.a11 = a11; | 246 obj.a11 = a11; |
221 obj.a12 = a12; | 247 obj.a12 = a12; |
222 obj.a22 = a22; | 248 obj.a22 = a22; |
249 obj.s_w = spdiag(s_w); | |
250 obj.s_e = spdiag(s_e); | |
251 obj.s_s = spdiag(s_s); | |
252 obj.s_n = spdiag(s_n); | |
253 | |
254 obj.theta_M_u = h_u*ops_u.borrowing.M.d1; | |
255 obj.theta_M_v = h_v*ops_v.borrowing.M.d1; | |
256 | |
257 obj.theta_R_u = h_u*ops_u.borrowing.R.delta_D; | |
258 obj.theta_R_v = h_v*ops_v.borrowing.R.delta_D; | |
259 | |
260 obj.theta_H_u = h_u*ops_u.borrowing.H11; | |
261 obj.theta_H_v = h_v*ops_v.borrowing.H11; | |
262 | |
263 % Temporary | |
223 obj.lambda = lambda; | 264 obj.lambda = lambda; |
224 | |
225 obj.gamm_u = h_u*ops_u.borrowing.M.d1; | 265 obj.gamm_u = h_u*ops_u.borrowing.M.d1; |
226 obj.gamm_v = h_v*ops_v.borrowing.M.d1; | 266 obj.gamm_v = h_v*ops_v.borrowing.M.d1; |
227 end | 267 end |
228 | 268 |
229 | 269 |
236 % neighbour_boundary is a string specifying which boundary to interface to. | 276 % neighbour_boundary is a string specifying which boundary to interface to. |
237 function [closure, penalty] = boundary_condition(obj, boundary, type, parameter) | 277 function [closure, penalty] = boundary_condition(obj, boundary, type, parameter) |
238 default_arg('type','neumann'); | 278 default_arg('type','neumann'); |
239 default_arg('parameter', []); | 279 default_arg('parameter', []); |
240 | 280 |
241 [e, d] = obj.getBoundaryOperator({'e', 'd'}, boundary); | 281 e = obj.getBoundaryOperator('e', boundary); |
282 d = obj.getBoundaryOperator('d', boundary); | |
242 H_b = obj.getBoundaryQuadrature(boundary); | 283 H_b = obj.getBoundaryQuadrature(boundary); |
243 gamm = obj.getBoundaryBorrowing(boundary); | 284 s_b = obj.getBoundaryScaling(boundary); |
285 [th_H, ~, th_R] = obj.getBoundaryBorrowing(boundary); | |
286 m = obj.getBoundaryNumber(boundary); | |
287 | |
288 K = obj.K; | |
289 J = obj.J; | |
290 Hi = obj.Hi; | |
291 a = obj.a; | |
292 b_b = e'*obj.b*e; | |
293 | |
244 switch type | 294 switch type |
245 % Dirichlet boundary condition | 295 % Dirichlet boundary condition |
246 case {'D','d','dirichlet'} | 296 case {'D','d','dirichlet'} |
247 tuning = 1.0; | 297 tuning = 1.0; |
248 | 298 |
249 b1 = gamm*obj.lambda./obj.a11.^2; | 299 sigma = 0*b_b; |
250 b2 = gamm*obj.lambda./obj.a22.^2; | 300 for i = 1:obj.dim |
251 | 301 sigma = sigma + e'*J*K{i,m}*K{i,m}*e; |
252 tau1 = tuning * spdiag(-1./b1 - 1./b2); | 302 end |
253 tau2 = 1; | 303 sigma = sigma/s_b; |
254 | 304 tau = tuning*(1/th_R + obj.dim/th_H)*sigma; |
255 tau = (tau1*e + tau2*d)*H_b; | 305 |
256 | 306 closure = a*Hi*d*b_b*H_b*e' ... |
257 closure = obj.a*obj.Hi*tau*e'; | 307 -a*Hi*e*tau*b_b*H_b*e'; |
258 penalty = -obj.a*obj.Hi*tau; | 308 |
259 | 309 penalty = -a*Hi*d*b_b*H_b ... |
260 | 310 +a*Hi*e*tau*b_b*H_b; |
261 % Neumann boundary condition | 311 |
312 | |
313 % Neumann boundary condition. Note that the penalty is for du/dn and not b*du/dn. | |
262 case {'N','n','neumann'} | 314 case {'N','n','neumann'} |
263 tau1 = -1; | 315 tau1 = -1; |
264 tau2 = 0; | 316 tau2 = 0; |
265 tau = (tau1*e + tau2*d)*H_b; | 317 tau = (tau1*e + tau2*d)*H_b; |
266 | 318 |
267 closure = obj.a*obj.Hi*tau*d'; | 319 closure = a*Hi*tau*b_b*d'; |
268 penalty = -obj.a*obj.Hi*tau; | 320 penalty = -a*Hi*tau*b_b; |
269 | 321 |
270 | 322 |
271 % Unknown, boundary condition | 323 % Unknown, boundary condition |
272 otherwise | 324 otherwise |
273 error('No such boundary condition: type = %s',type); | 325 error('No such boundary condition: type = %s',type); |
278 % Fields: | 330 % Fields: |
279 % -- tuning: penalty strength, defaults to 1.2 | 331 % -- tuning: penalty strength, defaults to 1.2 |
280 % -- interpolation: type of interpolation, default 'none' | 332 % -- interpolation: type of interpolation, default 'none' |
281 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,type) | 333 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,type) |
282 | 334 |
283 defaultType.tuning = 1.2; | 335 % error('Not implemented') |
336 | |
337 defaultType.tuning = 1.0; | |
284 defaultType.interpolation = 'none'; | 338 defaultType.interpolation = 'none'; |
285 default_struct('type', defaultType); | 339 default_struct('type', defaultType); |
286 | 340 |
287 switch type.interpolation | 341 switch type.interpolation |
288 case {'none', ''} | 342 case {'none', ''} |
295 end | 349 end |
296 | 350 |
297 function [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,type) | 351 function [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,type) |
298 tuning = type.tuning; | 352 tuning = type.tuning; |
299 | 353 |
354 dim = obj.dim; | |
300 % u denotes the solution in the own domain | 355 % u denotes the solution in the own domain |
301 % v denotes the solution in the neighbour domain | 356 % v denotes the solution in the neighbour domain |
302 [e_u, d_u] = obj.getBoundaryOperator({'e', 'd'}, boundary); | 357 u = obj; |
358 v = neighbour_scheme; | |
359 | |
360 % Boundary operators, u | |
361 e_u = u.getBoundaryOperator('e', boundary); | |
362 d_u = u.getBoundaryOperator('d', boundary); | |
363 gamm_u = u.getBoundaryBorrowing(boundary); | |
364 s_b_u = u.getBoundaryScaling(boundary); | |
365 [th_H_u, ~, th_R_u] = u.getBoundaryBorrowing(boundary); | |
366 m_u = u.getBoundaryNumber(boundary); | |
367 | |
368 % Coefficients, u | |
369 K_u = u.K; | |
370 J_u = u.J; | |
371 b_b_u = e_u'*u.b*e_u; | |
372 | |
373 % Boundary operators, v | |
374 e_v = v.getBoundaryOperator('e', neighbour_boundary); | |
375 d_v = v.getBoundaryOperator('d', neighbour_boundary); | |
376 gamm_v = v.getBoundaryBorrowing(neighbour_boundary); | |
377 s_b_v = v.getBoundaryScaling(neighbour_boundary); | |
378 [th_H_v, ~, th_R_v] = v.getBoundaryBorrowing(neighbour_boundary); | |
379 m_v = v.getBoundaryNumber(neighbour_boundary); | |
380 | |
381 % Coefficients, v | |
382 K_v = v.K; | |
383 J_v = v.J; | |
384 b_b_v = e_v'*v.b*e_v; | |
385 | |
386 %--- Penalty strength tau ------------- | |
387 sigma_u = 0*b_b_u; | |
388 sigma_v = 0*b_b_v; | |
389 for i = 1:obj.dim | |
390 sigma_u = sigma_u + e_u'*J_u*K_u{i,m_u}*K_u{i,m_u}*e_u; | |
391 sigma_v = sigma_v + e_v'*J_v*K_v{i,m_v}*K_v{i,m_v}*e_v; | |
392 end | |
393 sigma_u = sigma_u/s_b_u; | |
394 sigma_v = sigma_v/s_b_v; | |
395 | |
396 tau_R_u = 1/th_R_u*sigma_u; | |
397 tau_R_v = 1/th_R_v*sigma_v; | |
398 | |
399 tau_H_u = dim*1/th_H_u*sigma_u; | |
400 tau_H_v = dim*1/th_H_v*sigma_v; | |
401 | |
402 tau = 1/4*tuning*(b_b_u*(tau_R_u + tau_H_u) + b_b_v*(tau_R_v + tau_H_v)); | |
403 %-------------------------------------- | |
404 | |
405 % Operators/coefficients that are only required from this side | |
406 Hi = u.Hi; | |
407 H_b = u.getBoundaryQuadrature(boundary); | |
408 a = u.a; | |
409 | |
410 closure = 1/2*a*Hi*d_u*b_b_u*H_b*e_u' ... | |
411 -1/2*a*Hi*e_u*H_b*b_b_u*d_u' ... | |
412 -a*Hi*e_u*tau*H_b*e_u'; | |
413 | |
414 penalty = -1/2*a*Hi*d_u*b_b_u*H_b*e_v' ... | |
415 -1/2*a*Hi*e_u*H_b*b_b_v*d_v' ... | |
416 +a*Hi*e_u*tau*H_b*e_v'; | |
417 end | |
418 | |
419 function [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,type) | |
420 | |
421 % TODO: Make this work for curvilinear grids | |
422 warning('LaplaceCurvilinear: Non-conforming grid interpolation only works for Cartesian grids.'); | |
423 warning('LaplaceCurvilinear: Non-conforming interface uses Virtas penalty strength'); | |
424 warning('LaplaceCurvilinear: Non-conforming interface assumes that b is constant'); | |
425 | |
426 % User can request special interpolation operators by specifying type.interpOpSet | |
427 default_field(type, 'interpOpSet', @sbp.InterpOpsOP); | |
428 interpOpSet = type.interpOpSet; | |
429 tuning = type.tuning; | |
430 | |
431 | |
432 % u denotes the solution in the own domain | |
433 % v denotes the solution in the neighbour domain | |
434 e_u = obj.getBoundaryOperator('e', boundary); | |
435 d_u = obj.getBoundaryOperator('d', boundary); | |
303 H_b_u = obj.getBoundaryQuadrature(boundary); | 436 H_b_u = obj.getBoundaryQuadrature(boundary); |
304 I_u = obj.getBoundaryIndices(boundary); | 437 I_u = obj.getBoundaryIndices(boundary); |
305 gamm_u = obj.getBoundaryBorrowing(boundary); | 438 gamm_u = obj.getBoundaryBorrowing(boundary); |
306 | 439 |
307 [e_v, d_v] = neighbour_scheme.getBoundaryOperator({'e', 'd'}, neighbour_boundary); | 440 e_v = neighbour_scheme.getBoundaryOperator('e', neighbour_boundary); |
441 d_v = neighbour_scheme.getBoundaryOperator('d', neighbour_boundary); | |
308 H_b_v = neighbour_scheme.getBoundaryQuadrature(neighbour_boundary); | 442 H_b_v = neighbour_scheme.getBoundaryQuadrature(neighbour_boundary); |
309 I_v = neighbour_scheme.getBoundaryIndices(neighbour_boundary); | 443 I_v = neighbour_scheme.getBoundaryIndices(neighbour_boundary); |
310 gamm_v = neighbour_scheme.getBoundaryBorrowing(neighbour_boundary); | 444 gamm_v = neighbour_scheme.getBoundaryBorrowing(neighbour_boundary); |
445 | |
446 | |
447 % Find the number of grid points along the interface | |
448 m_u = size(e_u, 2); | |
449 m_v = size(e_v, 2); | |
450 | |
451 Hi = obj.Hi; | |
452 a = obj.a; | |
311 | 453 |
312 u = obj; | 454 u = obj; |
313 v = neighbour_scheme; | 455 v = neighbour_scheme; |
314 | 456 |
315 b1_u = gamm_u*u.lambda(I_u)./u.a11(I_u).^2; | 457 b1_u = gamm_u*u.lambda(I_u)./u.a11(I_u).^2; |
316 b2_u = gamm_u*u.lambda(I_u)./u.a22(I_u).^2; | 458 b2_u = gamm_u*u.lambda(I_u)./u.a22(I_u).^2; |
317 b1_v = gamm_v*v.lambda(I_v)./v.a11(I_v).^2; | 459 b1_v = gamm_v*v.lambda(I_v)./v.a11(I_v).^2; |
318 b2_v = gamm_v*v.lambda(I_v)./v.a22(I_v).^2; | 460 b2_v = gamm_v*v.lambda(I_v)./v.a22(I_v).^2; |
319 | 461 |
320 tau1 = -1./(4*b1_u) -1./(4*b1_v) -1./(4*b2_u) -1./(4*b2_v); | |
321 tau1 = tuning * spdiag(tau1); | |
322 tau2 = 1/2; | |
323 | |
324 sig1 = -1/2; | |
325 sig2 = 0; | |
326 | |
327 tau = (e_u*tau1 + tau2*d_u)*H_b_u; | |
328 sig = (sig1*e_u + sig2*d_u)*H_b_u; | |
329 | |
330 closure = obj.a*obj.Hi*( tau*e_u' + sig*d_u'); | |
331 penalty = obj.a*obj.Hi*(-tau*e_v' + sig*d_v'); | |
332 end | |
333 | |
334 function [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,type) | |
335 | |
336 % TODO: Make this work for curvilinear grids | |
337 warning('LaplaceCurvilinear: Non-conforming grid interpolation only works for Cartesian grids.'); | |
338 | |
339 % User can request special interpolation operators by specifying type.interpOpSet | |
340 default_field(type, 'interpOpSet', @sbp.InterpOpsOP); | |
341 interpOpSet = type.interpOpSet; | |
342 tuning = type.tuning; | |
343 | |
344 | |
345 % u denotes the solution in the own domain | |
346 % v denotes the solution in the neighbour domain | |
347 [e_u, d_u] = obj.getBoundaryOperator({'e', 'd'}, boundary); | |
348 H_b_u = obj.getBoundaryQuadrature(boundary); | |
349 I_u = obj.getBoundaryIndices(boundary); | |
350 gamm_u = obj.getBoundaryBorrowing(boundary); | |
351 | |
352 [e_v, d_v] = neighbour_scheme.getBoundaryOperator({'e', 'd'}, neighbour_boundary); | |
353 H_b_v = neighbour_scheme.getBoundaryQuadrature(neighbour_boundary); | |
354 I_v = neighbour_scheme.getBoundaryIndices(neighbour_boundary); | |
355 gamm_v = neighbour_scheme.getBoundaryBorrowing(neighbour_boundary); | |
356 | |
357 | |
358 % Find the number of grid points along the interface | |
359 m_u = size(e_u, 2); | |
360 m_v = size(e_v, 2); | |
361 | |
362 Hi = obj.Hi; | |
363 a = obj.a; | |
364 | |
365 u = obj; | |
366 v = neighbour_scheme; | |
367 | |
368 b1_u = gamm_u*u.lambda(I_u)./u.a11(I_u).^2; | |
369 b2_u = gamm_u*u.lambda(I_u)./u.a22(I_u).^2; | |
370 b1_v = gamm_v*v.lambda(I_v)./v.a11(I_v).^2; | |
371 b2_v = gamm_v*v.lambda(I_v)./v.a22(I_v).^2; | |
372 | |
373 tau_u = -1./(4*b1_u) -1./(4*b2_u); | 462 tau_u = -1./(4*b1_u) -1./(4*b2_u); |
374 tau_v = -1./(4*b1_v) -1./(4*b2_v); | 463 tau_v = -1./(4*b1_v) -1./(4*b2_v); |
375 | 464 |
376 tau_u = tuning * spdiag(tau_u); | 465 tau_u = tuning * spdiag(tau_u); |
377 tau_v = tuning * spdiag(tau_v); | 466 tau_v = tuning * spdiag(tau_v); |
393 -a*1/2*Hi*e_u*H_b_u*Iv2u.bad*d_v'; | 482 -a*1/2*Hi*e_u*H_b_u*Iv2u.bad*d_v'; |
394 | 483 |
395 end | 484 end |
396 | 485 |
397 % Returns the boundary operator op for the boundary specified by the string boundary. | 486 % Returns the boundary operator op for the boundary specified by the string boundary. |
398 % op -- string or a cell array of strings | 487 % op -- string |
399 % boundary -- string | 488 % boundary -- string |
400 function varargout = getBoundaryOperator(obj, op, boundary) | 489 function o = getBoundaryOperator(obj, op, boundary) |
401 | 490 assertIsMember(op, {'e', 'd'}) |
402 if ~iscell(op) | 491 assertIsMember(boundary, {'w', 'e', 's', 'n'}) |
403 op = {op}; | 492 |
404 end | 493 o = obj.([op, '_', boundary]); |
405 | |
406 for i = 1:numel(op) | |
407 switch op{i} | |
408 case 'e' | |
409 switch boundary | |
410 case 'w' | |
411 e = obj.e_w; | |
412 case 'e' | |
413 e = obj.e_e; | |
414 case 's' | |
415 e = obj.e_s; | |
416 case 'n' | |
417 e = obj.e_n; | |
418 otherwise | |
419 error('No such boundary: boundary = %s',boundary); | |
420 end | |
421 varargout{i} = e; | |
422 | |
423 case 'd' | |
424 switch boundary | |
425 case 'w' | |
426 d = obj.d_w; | |
427 case 'e' | |
428 d = obj.d_e; | |
429 case 's' | |
430 d = obj.d_s; | |
431 case 'n' | |
432 d = obj.d_n; | |
433 otherwise | |
434 error('No such boundary: boundary = %s',boundary); | |
435 end | |
436 varargout{i} = d; | |
437 end | |
438 end | |
439 end | 494 end |
440 | 495 |
441 % Returns square boundary quadrature matrix, of dimension | 496 % Returns square boundary quadrature matrix, of dimension |
442 % corresponding to the number of boundary points | 497 % corresponding to the number of boundary points |
443 % | 498 % |
444 % boundary -- string | 499 % boundary -- string |
445 function H_b = getBoundaryQuadrature(obj, boundary) | 500 function H_b = getBoundaryQuadrature(obj, boundary) |
501 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
502 | |
503 H_b = obj.(['H_', boundary]); | |
504 end | |
505 | |
506 % Returns square boundary quadrature scaling matrix, of dimension | |
507 % corresponding to the number of boundary points | |
508 % | |
509 % boundary -- string | |
510 function s_b = getBoundaryScaling(obj, boundary) | |
511 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
512 | |
513 s_b = obj.(['s_', boundary]); | |
514 end | |
515 | |
516 % Returns the coordinate number corresponding to the boundary | |
517 % | |
518 % boundary -- string | |
519 function m = getBoundaryNumber(obj, boundary) | |
520 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
446 | 521 |
447 switch boundary | 522 switch boundary |
448 case 'w' | 523 case {'w', 'e'} |
449 H_b = obj.H_w; | 524 m = 1; |
450 case 'e' | 525 case {'s', 'n'} |
451 H_b = obj.H_e; | 526 m = 2; |
452 case 's' | |
453 H_b = obj.H_s; | |
454 case 'n' | |
455 H_b = obj.H_n; | |
456 otherwise | |
457 error('No such boundary: boundary = %s',boundary); | |
458 end | 527 end |
459 end | 528 end |
460 | 529 |
461 % Returns the indices of the boundary points in the grid matrix | 530 % Returns the indices of the boundary points in the grid matrix |
462 % boundary -- string | 531 % boundary -- string |
476 end | 545 end |
477 end | 546 end |
478 | 547 |
479 % Returns borrowing constant gamma | 548 % Returns borrowing constant gamma |
480 % boundary -- string | 549 % boundary -- string |
481 function gamm = getBoundaryBorrowing(obj, boundary) | 550 function [theta_H, theta_M, theta_R] = getBoundaryBorrowing(obj, boundary) |
482 switch boundary | 551 switch boundary |
483 case {'w','e'} | 552 case {'w','e'} |
484 gamm = obj.gamm_u; | 553 theta_H = obj.theta_H_u; |
554 theta_M = obj.theta_M_u; | |
555 theta_R = obj.theta_R_u; | |
485 case {'s','n'} | 556 case {'s','n'} |
486 gamm = obj.gamm_v; | 557 theta_H = obj.theta_H_v; |
558 theta_M = obj.theta_M_v; | |
559 theta_R = obj.theta_R_v; | |
487 otherwise | 560 otherwise |
488 error('No such boundary: boundary = %s',boundary); | 561 error('No such boundary: boundary = %s',boundary); |
489 end | 562 end |
490 end | 563 end |
491 | 564 |