Mercurial > repos > public > sbplib
comparison +scheme/Elastic2dVariableAnisotropic.m @ 1201:8f4e79aa32ba feature/poroelastic
Add fully compatible D2Variable opSet and first implementation of ElasticAnisotropic
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Thu, 05 Sep 2019 14:13:00 -0700 |
parents | |
children | 31d7288d0653 |
comparison
equal
deleted
inserted
replaced
1200:d9da4c1cdaa0 | 1201:8f4e79aa32ba |
---|---|
1 classdef Elastic2dVariableAnisotropic < scheme.Scheme | |
2 | |
3 % Discretizes the elastic wave equation: | |
4 % rho u_{i,tt} = dj C_{ijkl} dk u_j | |
5 % opSet should be cell array of opSets, one per dimension. This | |
6 % is useful if we have periodic BC in one direction. | |
7 % Assumes fully compatible operators | |
8 | |
9 properties | |
10 m % Number of points in each direction, possibly a vector | |
11 h % Grid spacing | |
12 | |
13 grid | |
14 dim | |
15 | |
16 order % Order of accuracy for the approximation | |
17 | |
18 % Diagonal matrices for variable coefficients | |
19 RHO, RHOi, RHOi_kron % Density | |
20 C % Elastic stiffness tensor | |
21 | |
22 D % Total operator | |
23 D1 % First derivatives | |
24 D2 % Second derivatives | |
25 | |
26 % Boundary operators in cell format, used for BC | |
27 T_w, T_e, T_s, T_n | |
28 | |
29 % Traction operators | |
30 tau_w, tau_e, tau_s, tau_n % Return vector field | |
31 tau1_w, tau1_e, tau1_s, tau1_n % Return scalar field | |
32 tau2_w, tau2_e, tau2_s, tau2_n % Return scalar field | |
33 | |
34 % Inner products | |
35 H, Hi, Hi_kron, H_1D | |
36 | |
37 % Boundary inner products (for scalar field) | |
38 H_w, H_e, H_s, H_n | |
39 | |
40 % Boundary restriction operators | |
41 e_w, e_e, e_s, e_n % Act on vector field, return vector field at boundary | |
42 e1_w, e1_e, e1_s, e1_n % Act on vector field, return scalar field at boundary | |
43 e2_w, e2_e, e2_s, e2_n % Act on vector field, return scalar field at boundary | |
44 e_scalar_w, e_scalar_e, e_scalar_s, e_scalar_n; % Act on scalar field, return scalar field | |
45 | |
46 % E{i}^T picks out component i | |
47 E | |
48 | |
49 % Borrowing constants of the form gamma*h, where gamma is a dimensionless constant. | |
50 h11 % First entry in norm matrix | |
51 | |
52 end | |
53 | |
54 methods | |
55 | |
56 % The coefficients can either be function handles or grid functions | |
57 % optFlag -- if true, extra computations are performed, which may be helpful for optimization. | |
58 function obj = Elastic2dVariableAnisotropic(g, order, rho, C, opSet, optFlag) | |
59 default_arg('rho', @(x,y) 0*x+1); | |
60 default_arg('opSet',{@sbp.D2VariableCompatible, @sbp.D2VariableCompatible}); | |
61 default_arg('optFlag', false); | |
62 dim = 2; | |
63 | |
64 C_default = cell(dim,dim,dim,dim); | |
65 for i = 1:dim | |
66 for j = 1:dim | |
67 for k = 1:dim | |
68 for l = 1:dim | |
69 C_default{i,j,k,l} = @(x,y) 0*x + 1; | |
70 end | |
71 end | |
72 end | |
73 end | |
74 default_arg('C', C_default); | |
75 assert(isa(g, 'grid.Cartesian')) | |
76 | |
77 if isa(rho, 'function_handle') | |
78 rho = grid.evalOn(g, rho); | |
79 end | |
80 | |
81 C_mat = cell(dim,dim,dim,dim); | |
82 for i = 1:dim | |
83 for j = 1:dim | |
84 for k = 1:dim | |
85 for l = 1:dim | |
86 if isa(C{i,j,k,l}, 'function_handle') | |
87 C{i,j,k,l} = grid.evalOn(g, C{i,j,k,l}); | |
88 end | |
89 C_mat{i,j,k,l} = spdiag(C{i,j,k,l}); | |
90 end | |
91 end | |
92 end | |
93 end | |
94 obj.C = C_mat; | |
95 | |
96 m = g.size(); | |
97 m_tot = g.N(); | |
98 lim = g.lim; | |
99 if isempty(lim) | |
100 x = g.x; | |
101 lim = cell(length(x),1); | |
102 for i = 1:length(x) | |
103 lim{i} = {min(x{i}), max(x{i})}; | |
104 end | |
105 end | |
106 | |
107 % 1D operators | |
108 ops = cell(dim,1); | |
109 h = zeros(dim,1); | |
110 for i = 1:dim | |
111 ops{i} = opSet{i}(m(i), lim{i}, order); | |
112 h(i) = ops{i}.h; | |
113 end | |
114 | |
115 % Borrowing constants | |
116 for i = 1:dim | |
117 obj.h11{i} = h(i)*ops{i}.borrowing.H11; | |
118 end | |
119 | |
120 I = cell(dim,1); | |
121 D1 = cell(dim,1); | |
122 D2 = cell(dim,1); | |
123 H = cell(dim,1); | |
124 Hi = cell(dim,1); | |
125 e_0 = cell(dim,1); | |
126 e_m = cell(dim,1); | |
127 d1_0 = cell(dim,1); | |
128 d1_m = cell(dim,1); | |
129 | |
130 for i = 1:dim | |
131 I{i} = speye(m(i)); | |
132 D1{i} = ops{i}.D1; | |
133 D2{i} = ops{i}.D2; | |
134 H{i} = ops{i}.H; | |
135 Hi{i} = ops{i}.HI; | |
136 e_0{i} = ops{i}.e_l; | |
137 e_m{i} = ops{i}.e_r; | |
138 d1_0{i} = ops{i}.d1_l; | |
139 d1_m{i} = ops{i}.d1_r; | |
140 end | |
141 | |
142 %====== Assemble full operators ======== | |
143 RHO = spdiag(rho); | |
144 obj.RHO = RHO; | |
145 obj.RHOi = inv(RHO); | |
146 | |
147 obj.D1 = cell(dim,1); | |
148 obj.D2 = cell(dim,dim,dim); | |
149 | |
150 % D1 | |
151 obj.D1{1} = kron(D1{1},I{2}); | |
152 obj.D1{2} = kron(I{1},D1{2}); | |
153 | |
154 % Boundary restriction operators | |
155 e_l = cell(dim,1); | |
156 e_r = cell(dim,1); | |
157 e_l{1} = kron(e_0{1}, I{2}); | |
158 e_l{2} = kron(I{1}, e_0{2}); | |
159 e_r{1} = kron(e_m{1}, I{2}); | |
160 e_r{2} = kron(I{1}, e_m{2}); | |
161 | |
162 e_scalar_w = e_l{1}; | |
163 e_scalar_e = e_r{1}; | |
164 e_scalar_s = e_l{2}; | |
165 e_scalar_n = e_r{2}; | |
166 | |
167 I_dim = speye(dim, dim); | |
168 e_w = kron(e_scalar_w, I_dim); | |
169 e_e = kron(e_scalar_e, I_dim); | |
170 e_s = kron(e_scalar_s, I_dim); | |
171 e_n = kron(e_scalar_n, I_dim); | |
172 | |
173 % E{i}^T picks out component i. | |
174 E = cell(dim,1); | |
175 I = speye(m_tot,m_tot); | |
176 for i = 1:dim | |
177 e = sparse(dim,1); | |
178 e(i) = 1; | |
179 E{i} = kron(I,e); | |
180 end | |
181 obj.E = E; | |
182 | |
183 e1_w = (e_scalar_w'*E{1}')'; | |
184 e1_e = (e_scalar_e'*E{1}')'; | |
185 e1_s = (e_scalar_s'*E{1}')'; | |
186 e1_n = (e_scalar_n'*E{1}')'; | |
187 | |
188 e2_w = (e_scalar_w'*E{2}')'; | |
189 e2_e = (e_scalar_e'*E{2}')'; | |
190 e2_s = (e_scalar_s'*E{2}')'; | |
191 e2_n = (e_scalar_n'*E{2}')'; | |
192 | |
193 | |
194 % D2 | |
195 for i = 1:dim | |
196 for k = 2:dim | |
197 for l = 2:dim | |
198 obj.D2{i,k,l} = sparse(m_tot); | |
199 end | |
200 end | |
201 end | |
202 ind = grid.funcToMatrix(g, 1:m_tot); | |
203 | |
204 k = 1; | |
205 for r = 1:m(2) | |
206 p = ind(:,r); | |
207 for i = 1:dim | |
208 for l = 1:dim | |
209 coeff = C{i,k,k,l}; | |
210 D_kk = D2{1}(coeff(p)); | |
211 obj.D2{i,k,l}(p,p) = D_kk; | |
212 end | |
213 end | |
214 end | |
215 | |
216 k = 2; | |
217 for r = 1:m(1) | |
218 p = ind(r,:); | |
219 for i = 1:dim | |
220 for l = 1:dim | |
221 coeff = C{i,k,k,l}; | |
222 D_kk = D2{2}(coeff(p)); | |
223 obj.D2{i,k,l}(p,p) = D_kk; | |
224 end | |
225 end | |
226 end | |
227 | |
228 % Quadratures | |
229 obj.H = kron(H{1},H{2}); | |
230 obj.Hi = inv(obj.H); | |
231 obj.H_w = H{2}; | |
232 obj.H_e = H{2}; | |
233 obj.H_s = H{1}; | |
234 obj.H_n = H{1}; | |
235 obj.H_1D = {H{1}, H{2}}; | |
236 | |
237 % Differentiation matrix D (without SAT) | |
238 D2 = obj.D2; | |
239 D1 = obj.D1; | |
240 D = sparse(dim*m_tot,dim*m_tot); | |
241 d = @kroneckerDelta; % Kronecker delta | |
242 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta | |
243 for i = 1:dim | |
244 for j = 1:dim | |
245 for k = 1:dim | |
246 for l = 1:dim | |
247 D = D + E{i}*inv(RHO)*( d(j,k)*D2{i,k,l}*E{l}' +... | |
248 db(j,k)*D1{j}*C_mat{i,j,k,l}*D1{k}*E{l}' ... | |
249 ); | |
250 end | |
251 end | |
252 end | |
253 end | |
254 obj.D = D; | |
255 %=========================================%' | |
256 | |
257 % Numerical traction operators for BC. | |
258 % | |
259 % Formula at boundary j: % tau^{j}_i = sum_l T^{j}_{il} u_l | |
260 % | |
261 T_l = cell(dim,1); | |
262 T_r = cell(dim,1); | |
263 tau_l = cell(dim,1); | |
264 tau_r = cell(dim,1); | |
265 | |
266 D1 = obj.D1; | |
267 | |
268 % Boundary j | |
269 for j = 1:dim | |
270 T_l{j} = cell(dim,dim); | |
271 T_r{j} = cell(dim,dim); | |
272 tau_l{j} = cell(dim,1); | |
273 tau_r{j} = cell(dim,1); | |
274 | |
275 [~, n_l] = size(e_l{j}); | |
276 [~, n_r] = size(e_r{j}); | |
277 | |
278 % Traction component i | |
279 for i = 1:dim | |
280 tau_l{j}{i} = sparse(dim*m_tot, n_l); | |
281 tau_r{j}{i} = sparse(dim*m_tot, n_r); | |
282 | |
283 % Displacement component l | |
284 for l = 1:dim | |
285 T_l{j}{i,l} = sparse(m_tot, n_l); | |
286 T_r{j}{i,l} = sparse(m_tot, n_r); | |
287 | |
288 % Derivative direction k | |
289 for k = 1:dim | |
290 T_l{j}{i,l} = T_l{j}{i,l} ... | |
291 - (e_l{j}'*C_mat{i,j,k,l}*D1{k})'; | |
292 T_r{j}{i,l} = T_r{j}{i,l} ... | |
293 + (e_r{j}'*C_mat{i,j,k,l}*D1{k})'; | |
294 end | |
295 tau_l{j}{i} = tau_l{j}{i} + (T_l{j}{i,l}'*E{l}')'; | |
296 tau_r{j}{i} = tau_r{j}{i} + (T_r{j}{i,l}'*E{l}')'; | |
297 end | |
298 end | |
299 end | |
300 | |
301 % Traction tensors, T_ij | |
302 obj.T_w = T_l{1}; | |
303 obj.T_e = T_r{1}; | |
304 obj.T_s = T_l{2}; | |
305 obj.T_n = T_r{2}; | |
306 | |
307 % Restriction operators | |
308 obj.e_w = e_w; | |
309 obj.e_e = e_e; | |
310 obj.e_s = e_s; | |
311 obj.e_n = e_n; | |
312 | |
313 obj.e1_w = e1_w; | |
314 obj.e1_e = e1_e; | |
315 obj.e1_s = e1_s; | |
316 obj.e1_n = e1_n; | |
317 | |
318 obj.e2_w = e2_w; | |
319 obj.e2_e = e2_e; | |
320 obj.e2_s = e2_s; | |
321 obj.e2_n = e2_n; | |
322 | |
323 obj.e_scalar_w = e_scalar_w; | |
324 obj.e_scalar_e = e_scalar_e; | |
325 obj.e_scalar_s = e_scalar_s; | |
326 obj.e_scalar_n = e_scalar_n; | |
327 | |
328 % First component of traction | |
329 obj.tau1_w = tau_l{1}{1}; | |
330 obj.tau1_e = tau_r{1}{1}; | |
331 obj.tau1_s = tau_l{2}{1}; | |
332 obj.tau1_n = tau_r{2}{1}; | |
333 | |
334 % Second component of traction | |
335 obj.tau2_w = tau_l{1}{2}; | |
336 obj.tau2_e = tau_r{1}{2}; | |
337 obj.tau2_s = tau_l{2}{2}; | |
338 obj.tau2_n = tau_r{2}{2}; | |
339 | |
340 % Traction vectors | |
341 obj.tau_w = (e_w'*e1_w*obj.tau1_w')' + (e_w'*e2_w*obj.tau2_w')'; | |
342 obj.tau_e = (e_e'*e1_e*obj.tau1_e')' + (e_e'*e2_e*obj.tau2_e')'; | |
343 obj.tau_s = (e_s'*e1_s*obj.tau1_s')' + (e_s'*e2_s*obj.tau2_s')'; | |
344 obj.tau_n = (e_n'*e1_n*obj.tau1_n')' + (e_n'*e2_n*obj.tau2_n')'; | |
345 | |
346 % Kroneckered norms and coefficients | |
347 obj.RHOi_kron = kron(obj.RHOi, I_dim); | |
348 obj.Hi_kron = kron(obj.Hi, I_dim); | |
349 | |
350 % Misc. | |
351 obj.m = m; | |
352 obj.h = h; | |
353 obj.order = order; | |
354 obj.grid = g; | |
355 obj.dim = dim; | |
356 | |
357 end | |
358 | |
359 | |
360 % Closure functions return the operators applied to the own domain to close the boundary | |
361 % Penalty functions return the operators to force the solution. In the case of an interface it returns the operator applied to the other doamin. | |
362 % boundary is a string specifying the boundary e.g. 'l','r' or 'e','w','n','s'. | |
363 % bc is a cell array of component and bc type, e.g. {1, 'd'} for Dirichlet condition | |
364 % on the first component. Can also be e.g. | |
365 % {'normal', 'd'} or {'tangential', 't'} for conditions on | |
366 % tangential/normal component. | |
367 % data is a function returning the data that should be applied at the boundary. | |
368 % neighbour_scheme is an instance of Scheme that should be interfaced to. | |
369 % neighbour_boundary is a string specifying which boundary to interface to. | |
370 function [closure, penalty] = boundary_condition(obj, boundary, bc, tuning) | |
371 default_arg('tuning', 1.0); | |
372 | |
373 assert( iscell(bc), 'The BC type must be a 2x1 cell array' ); | |
374 comp = bc{1}; | |
375 type = bc{2}; | |
376 if ischar(comp) | |
377 comp = obj.getComponent(comp, boundary); | |
378 end | |
379 | |
380 e = obj.getBoundaryOperatorForScalarField('e', boundary); | |
381 tau = obj.getBoundaryOperator(['tau' num2str(comp)], boundary); | |
382 T = obj.getBoundaryTractionOperator(boundary); | |
383 h11 = obj.getBorrowing(boundary); | |
384 H_gamma = obj.getBoundaryQuadratureForScalarField(boundary); | |
385 nu = obj.getNormal(boundary); | |
386 | |
387 E = obj.E; | |
388 Hi = obj.Hi; | |
389 RHOi = obj.RHOi; | |
390 C = obj.C; | |
391 | |
392 dim = obj.dim; | |
393 m_tot = obj.grid.N(); | |
394 | |
395 % Preallocate | |
396 [~, col] = size(tau); | |
397 closure = sparse(dim*m_tot, dim*m_tot); | |
398 penalty = sparse(dim*m_tot, col); | |
399 | |
400 j = comp; | |
401 switch type | |
402 | |
403 % Dirichlet boundary condition | |
404 % OBS! Cannot yet set one component at a time unless one assumes Displacement for all components | |
405 case {'D','d','dirichlet','Dirichlet','displacement','Displacement'} | |
406 | |
407 % Loop over components that Dirichlet penalties end up on | |
408 % Y: symmetrizing part of penalty | |
409 % Z: symmetric part of penalty | |
410 % X = Y + Z. | |
411 for i = 1:dim | |
412 Y = T{j,i}'; | |
413 | |
414 Z = sparse(m_tot, m_tot); | |
415 for l = 1:dim | |
416 for k = 1:dim | |
417 Z = Z + nu(l)*C{i,l,k,j}*nu(k); | |
418 end | |
419 end | |
420 Z = -tuning*dim/h11*Z; | |
421 X = Z + e*Y; | |
422 closure = closure + E{i}*RHOi*Hi*X'*e*H_gamma*(e'*E{j}' ); | |
423 penalty = penalty - E{i}*RHOi*Hi*X'*e*H_gamma; | |
424 end | |
425 | |
426 % Free boundary condition | |
427 case {'F','f','Free','free','traction','Traction','t','T'} | |
428 closure = closure - E{j}*RHOi*Hi*e*H_gamma*tau'; | |
429 penalty = penalty + E{j}*RHOi*Hi*e*H_gamma; | |
430 | |
431 % Unknown boundary condition | |
432 otherwise | |
433 error('No such boundary condition: type = %s',type); | |
434 end | |
435 end | |
436 | |
437 % type Struct that specifies the interface coupling. | |
438 % Fields: | |
439 % -- tuning: penalty strength, defaults to 1.2 | |
440 % -- interpolation: type of interpolation, default 'none' | |
441 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,type) | |
442 | |
443 defaultType.tuning = 1.2; | |
444 defaultType.interpolation = 'none'; | |
445 default_struct('type', defaultType); | |
446 | |
447 switch type.interpolation | |
448 case {'none', ''} | |
449 [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,type); | |
450 case {'op','OP'} | |
451 [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,type); | |
452 otherwise | |
453 error('Unknown type of interpolation: %s ', type.interpolation); | |
454 end | |
455 end | |
456 | |
457 function [closure, penalty] = interfaceStandard(obj,boundary,neighbour_scheme,neighbour_boundary,type) | |
458 tuning = type.tuning; | |
459 | |
460 % u denotes the solution in the own domain | |
461 % v denotes the solution in the neighbour domain | |
462 % Operators without subscripts are from the own domain. | |
463 | |
464 % Get boundary operators | |
465 e = obj.getBoundaryOperator('e', boundary); | |
466 tau = obj.getBoundaryOperator('tau', boundary); | |
467 | |
468 e_v = neighbour_scheme.getBoundaryOperator('e', neighbour_boundary); | |
469 tau_v = neighbour_scheme.getBoundaryOperator('tau', neighbour_boundary); | |
470 | |
471 H_gamma = obj.getBoundaryQuadrature(boundary); | |
472 | |
473 % Operators and quantities that correspond to the own domain only | |
474 Hi = obj.Hi_kron; | |
475 RHOi = obj.RHOi_kron; | |
476 | |
477 % Penalty strength operators | |
478 alpha_u = 1/4*tuning*obj.getBoundaryOperator('alpha', boundary); | |
479 alpha_v = 1/4*tuning*neighbour_scheme.getBoundaryOperator('alpha', neighbour_boundary); | |
480 | |
481 closure = -RHOi*Hi*e*H_gamma*(alpha_u' + alpha_v'*e_v*e'); | |
482 penalty = RHOi*Hi*e*H_gamma*(alpha_u'*e*e_v' + alpha_v'); | |
483 | |
484 closure = closure - 1/2*RHOi*Hi*e*H_gamma*tau'; | |
485 penalty = penalty - 1/2*RHOi*Hi*e*H_gamma*tau_v'; | |
486 | |
487 closure = closure + 1/2*RHOi*Hi*tau*H_gamma*e'; | |
488 penalty = penalty - 1/2*RHOi*Hi*tau*H_gamma*e_v'; | |
489 | |
490 end | |
491 | |
492 function [closure, penalty] = interfaceNonConforming(obj,boundary,neighbour_scheme,neighbour_boundary,type) | |
493 error('Non-conforming interfaces not implemented yet.'); | |
494 end | |
495 | |
496 % Returns the component number that is the tangential/normal component | |
497 % at the specified boundary | |
498 function comp = getComponent(obj, comp_str, boundary) | |
499 assertIsMember(comp_str, {'normal', 'tangential'}); | |
500 assertIsMember(boundary, {'w', 'e', 's', 'n'}); | |
501 | |
502 switch boundary | |
503 case {'w', 'e'} | |
504 switch comp_str | |
505 case 'normal' | |
506 comp = 1; | |
507 case 'tangential' | |
508 comp = 2; | |
509 end | |
510 case {'s', 'n'} | |
511 switch comp_str | |
512 case 'normal' | |
513 comp = 2; | |
514 case 'tangential' | |
515 comp = 1; | |
516 end | |
517 end | |
518 end | |
519 | |
520 % Returns h11 for the boundary specified by the string boundary. | |
521 % op -- string | |
522 function h11 = getBorrowing(obj, boundary) | |
523 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
524 | |
525 switch boundary | |
526 case {'w','e'} | |
527 h11 = obj.h11{1}; | |
528 case {'s', 'n'} | |
529 h11 = obj.h11{2}; | |
530 end | |
531 end | |
532 | |
533 % Returns the outward unit normal vector for the boundary specified by the string boundary. | |
534 function nu = getNormal(obj, boundary) | |
535 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
536 | |
537 switch boundary | |
538 case 'w' | |
539 nu = [-1,0]; | |
540 case 'e' | |
541 nu = [1,0]; | |
542 case 's' | |
543 nu = [0,-1]; | |
544 case 'n' | |
545 nu = [0,1]; | |
546 end | |
547 end | |
548 | |
549 % Returns the boundary operator op for the boundary specified by the string boundary. | |
550 % op -- string | |
551 function o = getBoundaryOperator(obj, op, boundary) | |
552 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
553 assertIsMember(op, {'e', 'e1', 'e2', 'tau', 'tau1', 'tau2'}) | |
554 | |
555 switch op | |
556 case {'e', 'e1', 'e2', 'tau', 'tau1', 'tau2'} | |
557 o = obj.([op, '_', boundary]); | |
558 end | |
559 | |
560 end | |
561 | |
562 % Returns the boundary operator op for the boundary specified by the string boundary. | |
563 % op -- string | |
564 function o = getBoundaryOperatorForScalarField(obj, op, boundary) | |
565 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
566 assertIsMember(op, {'e'}) | |
567 | |
568 switch op | |
569 | |
570 case 'e' | |
571 o = obj.(['e_scalar', '_', boundary]); | |
572 end | |
573 | |
574 end | |
575 | |
576 % Returns the boundary operator T_ij (cell format) for the boundary specified by the string boundary. | |
577 % Formula: tau_i = T_ij u_j | |
578 % op -- string | |
579 function T = getBoundaryTractionOperator(obj, boundary) | |
580 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
581 | |
582 T = obj.(['T', '_', boundary]); | |
583 end | |
584 | |
585 % Returns square boundary quadrature matrix, of dimension | |
586 % corresponding to the number of boundary unknowns | |
587 % | |
588 % boundary -- string | |
589 function H = getBoundaryQuadrature(obj, boundary) | |
590 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
591 | |
592 H = obj.getBoundaryQuadratureForScalarField(boundary); | |
593 I_dim = speye(obj.dim, obj.dim); | |
594 H = kron(H, I_dim); | |
595 end | |
596 | |
597 % Returns square boundary quadrature matrix, of dimension | |
598 % corresponding to the number of boundary grid points | |
599 % | |
600 % boundary -- string | |
601 function H_b = getBoundaryQuadratureForScalarField(obj, boundary) | |
602 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
603 | |
604 H_b = obj.(['H_', boundary]); | |
605 end | |
606 | |
607 function N = size(obj) | |
608 N = obj.dim*prod(obj.m); | |
609 end | |
610 end | |
611 end |