Mercurial > repos > public > sbplib
comparison +scheme/Elastic2dStaggeredCurvilinearAnisotropic.m @ 1281:01a0500de446 feature/poroelastic
Add working implementation of Elastic2dStaggeredCurvilinearAnisotropic, which wraps around the Cartesian anisotropic scheme.
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Sun, 07 Jun 2020 11:33:44 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1280:c7f5b480e455 | 1281:01a0500de446 |
---|---|
1 classdef Elastic2dStaggeredCurvilinearAnisotropic < scheme.Scheme | |
2 | |
3 % Discretizes the elastic wave equation: | |
4 % rho u_{i,tt} = dj C_{ijkl} dk u_j | |
5 % in curvilinear coordinates, using Lebedev staggered grids | |
6 | |
7 properties | |
8 m % Number of points in each direction, possibly a vector | |
9 h % Grid spacing | |
10 | |
11 grid | |
12 dim | |
13 nGrids | |
14 | |
15 order % Order of accuracy for the approximation | |
16 | |
17 % Diagonal matrices for variable coefficients | |
18 J, Ji | |
19 RHO % Density | |
20 C % Elastic stiffness tensor | |
21 | |
22 D % Total operator | |
23 | |
24 % Dx, Dy % Physical derivatives | |
25 n_w, n_e, n_s, n_n % Physical normals | |
26 | |
27 % Boundary operators in cell format, used for BC | |
28 T_w, T_e, T_s, T_n | |
29 | |
30 % Traction operators | |
31 % tau_w, tau_e, tau_s, tau_n % Return vector field | |
32 % tau1_w, tau1_e, tau1_s, tau1_n % Return scalar field | |
33 % tau2_w, tau2_e, tau2_s, tau2_n % Return scalar field | |
34 | |
35 % Inner products | |
36 H | |
37 | |
38 % Boundary inner products (for scalar field) | |
39 H_w, H_e, H_s, H_n | |
40 | |
41 % Surface Jacobian vectors | |
42 s_w, s_e, s_s, s_n | |
43 | |
44 % Boundary restriction operators | |
45 e_w_u, e_e_u, e_s_u, e_n_u % Act on scalar field, return scalar field at boundary | |
46 e_w_s, e_e_s, e_s_s, e_n_s % Act on scalar field, return scalar field at boundary | |
47 % e1_w, e1_e, e1_s, e1_n % Act on vector field, return scalar field at boundary | |
48 % e2_w, e2_e, e2_s, e2_n % Act on vector field, return scalar field at boundary | |
49 % e_scalar_w, e_scalar_e, e_scalar_s, e_scalar_n; % Act on scalar field, return scalar field | |
50 % en_w, en_e, en_s, en_n % Act on vector field, return normal component | |
51 | |
52 % U{i}^T picks out component i | |
53 U | |
54 | |
55 % G{i}^T picks out displacement grid i | |
56 G | |
57 | |
58 % Elastic2dVariableAnisotropic object for reference domain | |
59 refObj | |
60 end | |
61 | |
62 methods | |
63 | |
64 % The coefficients can either be function handles or grid functions | |
65 % optFlag -- if true, extra computations are performed, which may be helpful for optimization. | |
66 function obj = Elastic2dStaggeredCurvilinearAnisotropic(g, order, rho, C) | |
67 default_arg('rho', @(x,y) 0*x+1); | |
68 | |
69 opSet = @sbp.D1StaggeredUpwind; | |
70 dim = 2; | |
71 nGrids = 2; | |
72 | |
73 C_default = cell(dim,dim,dim,dim); | |
74 for i = 1:dim | |
75 for j = 1:dim | |
76 for k = 1:dim | |
77 for l = 1:dim | |
78 C_default{i,j,k,l} = @(x,y) 0*x; | |
79 end | |
80 end | |
81 end | |
82 end | |
83 default_arg('C', C_default); | |
84 assert(isa(g, 'grid.Staggered')); | |
85 | |
86 g_u = g.gridGroups{1}; | |
87 g_s = g.gridGroups{2}; | |
88 | |
89 m_u = {g_u{1}.size(), g_u{2}.size()}; | |
90 m_s = {g_s{1}.size(), g_s{2}.size()}; | |
91 | |
92 if isa(rho, 'function_handle') | |
93 rho_vec = cell(nGrids, 1); | |
94 for a = 1:nGrids | |
95 rho_vec{a} = grid.evalOn(g_u{a}, rho); | |
96 end | |
97 rho = rho_vec; | |
98 end | |
99 for a = 1:nGrids | |
100 RHO{a} = spdiag(rho{a}); | |
101 end | |
102 obj.RHO = RHO; | |
103 | |
104 C_mat = cell(nGrids, 1); | |
105 for a = 1:nGrids | |
106 C_mat{a} = cell(dim,dim,dim,dim); | |
107 end | |
108 for a = 1:nGrids | |
109 for i = 1:dim | |
110 for j = 1:dim | |
111 for k = 1:dim | |
112 for l = 1:dim | |
113 if numel(C) == dim | |
114 C_mat{a}{i,j,k,l} = spdiag(C{a}{i,j,k,l}); | |
115 else | |
116 C_mat{a}{i,j,k,l} = spdiag(grid.evalOn(g_s{a}, C{i,j,k,l})); | |
117 end | |
118 end | |
119 end | |
120 end | |
121 end | |
122 end | |
123 obj.C = C_mat; | |
124 | |
125 C = cell(nGrids, 1); | |
126 for a = 1:nGrids | |
127 C{a} = cell(dim,dim,dim,dim); | |
128 for i = 1:dim | |
129 for j = 1:dim | |
130 for k = 1:dim | |
131 for l = 1:dim | |
132 C{a}{i,j,k,l} = diag(C_mat{a}{i,j,k,l}); | |
133 end | |
134 end | |
135 end | |
136 end | |
137 end | |
138 | |
139 % Reference m for primal grid | |
140 m = g_u{1}.size(); | |
141 | |
142 % 1D operators | |
143 ops = cell(dim,1); | |
144 D1p = cell(dim, 1); | |
145 D1d = cell(dim, 1); | |
146 mp = cell(dim, 1); | |
147 md = cell(dim, 1); | |
148 Ip = cell(dim, 1); | |
149 Id = cell(dim, 1); | |
150 Hp = cell(dim, 1); | |
151 Hd = cell(dim, 1); | |
152 | |
153 opSet = @sbp.D1StaggeredUpwind; | |
154 for i = 1:dim | |
155 ops{i} = opSet(m(i), {0,1}, order); | |
156 D1p{i} = ops{i}.D1_dual; | |
157 D1d{i} = ops{i}.D1_primal; | |
158 mp{i} = length(ops{i}.x_primal); | |
159 md{i} = length(ops{i}.x_dual); | |
160 Ip{i} = speye(mp{i}, mp{i}); | |
161 Id{i} = speye(md{i}, md{i}); | |
162 Hp{i} = ops{i}.H_primal; | |
163 Hd{i} = ops{i}.H_dual; | |
164 ep_l{i} = ops{i}.e_primal_l; | |
165 ep_r{i} = ops{i}.e_primal_r; | |
166 ed_l{i} = ops{i}.e_dual_l; | |
167 ed_r{i} = ops{i}.e_dual_r; | |
168 end | |
169 | |
170 % D1_u2s{a, b}{i} approximates ddi and | |
171 % takes from u grid number b to s grid number a | |
172 % Some of D1_x2y{a, b} are 0. | |
173 D1_u2s = cell(nGrids, nGrids); | |
174 D1_s2u = cell(nGrids, nGrids); | |
175 | |
176 N_u = cell(nGrids, 1); | |
177 N_s = cell(nGrids, 1); | |
178 for a = 1:nGrids | |
179 N_u{a} = g_u{a}.N(); | |
180 N_s{a} = g_s{a}.N(); | |
181 end | |
182 | |
183 %---- Grid layout ------- | |
184 % gu1 = xp o yp; | |
185 % gu2 = xd o yd; | |
186 % gs1 = xd o yp; | |
187 % gs2 = xp o yd; | |
188 %------------------------ | |
189 | |
190 % Logical operators | |
191 D1_u2s{1,1}{1} = kron(D1p{1}, Ip{2}); | |
192 D1_s2u{1,1}{1} = kron(D1d{1}, Ip{2}); | |
193 | |
194 D1_u2s{1,2}{2} = kron(Id{1}, D1d{2}); | |
195 D1_u2s{2,1}{2} = kron(Ip{1}, D1p{2}); | |
196 | |
197 D1_s2u{1,2}{2} = kron(Ip{1}, D1d{2}); | |
198 D1_s2u{2,1}{2} = kron(Id{1}, D1p{2}); | |
199 | |
200 D1_u2s{2,2}{1} = kron(D1d{1}, Id{2}); | |
201 D1_s2u{2,2}{1} = kron(D1p{1}, Id{2}); | |
202 | |
203 D1_u2s{1,1}{2} = sparse(N_s{1}, N_u{1}); | |
204 D1_s2u{1,1}{2} = sparse(N_u{1}, N_s{1}); | |
205 | |
206 D1_u2s{2,2}{2} = sparse(N_s{2}, N_u{2}); | |
207 D1_s2u{2,2}{2} = sparse(N_u{2}, N_s{2}); | |
208 | |
209 D1_u2s{1,2}{1} = sparse(N_s{1}, N_u{2}); | |
210 D1_s2u{1,2}{1} = sparse(N_u{1}, N_s{2}); | |
211 | |
212 D1_u2s{2,1}{1} = sparse(N_s{2}, N_u{1}); | |
213 D1_s2u{2,1}{1} = sparse(N_u{2}, N_s{1}); | |
214 | |
215 | |
216 %---- Combine grids and components ----- | |
217 | |
218 % U{a}{i}^T picks out u component i on grid a | |
219 U = cell(nGrids, 1); | |
220 for a = 1:nGrids | |
221 U{a} = cell(dim, 1); | |
222 I = speye(N_u{a}, N_u{a}); | |
223 for i = 1:dim | |
224 E = sparse(dim,1); | |
225 E(i) = 1; | |
226 U{a}{i} = kron(I, E); | |
227 end | |
228 end | |
229 obj.U = U; | |
230 | |
231 % Order grids | |
232 % u1, u2 | |
233 Iu1 = speye(dim*N_u{1}, dim*N_u{1}); | |
234 Iu2 = speye(dim*N_u{2}, dim*N_u{2}); | |
235 | |
236 Gu1 = cell2mat( {Iu1; sparse(dim*N_u{2}, dim*N_u{1})} ); | |
237 Gu2 = cell2mat( {sparse(dim*N_u{1}, dim*N_u{2}); Iu2} ); | |
238 | |
239 G = {Gu1; Gu2}; | |
240 | |
241 %---- Grid layout ------- | |
242 % gu1 = xp o yp; | |
243 % gu2 = xd o yd; | |
244 % gs1 = xd o yp; | |
245 % gs2 = xp o yd; | |
246 %------------------------ | |
247 | |
248 % Boundary restriction ops | |
249 e_w_u = cell(nGrids, 1); | |
250 e_s_u = cell(nGrids, 1); | |
251 e_e_u = cell(nGrids, 1); | |
252 e_n_u = cell(nGrids, 1); | |
253 | |
254 e_w_s = cell(nGrids, 1); | |
255 e_s_s = cell(nGrids, 1); | |
256 e_e_s = cell(nGrids, 1); | |
257 e_n_s = cell(nGrids, 1); | |
258 | |
259 e_w_u{1} = kron(ep_l{1}, Ip{2}); | |
260 e_e_u{1} = kron(ep_r{1}, Ip{2}); | |
261 e_s_u{1} = kron(Ip{1}, ep_l{2}); | |
262 e_n_u{1} = kron(Ip{1}, ep_r{2}); | |
263 | |
264 e_w_u{2} = kron(ed_l{1}, Id{2}); | |
265 e_e_u{2} = kron(ed_r{1}, Id{2}); | |
266 e_s_u{2} = kron(Id{1}, ed_l{2}); | |
267 e_n_u{2} = kron(Id{1}, ed_r{2}); | |
268 | |
269 e_w_s{1} = kron(ed_l{1}, Ip{2}); | |
270 e_e_s{1} = kron(ed_r{1}, Ip{2}); | |
271 e_s_s{1} = kron(Id{1}, ep_l{2}); | |
272 e_n_s{1} = kron(Id{1}, ep_r{2}); | |
273 | |
274 e_w_s{2} = kron(ep_l{1}, Id{2}); | |
275 e_e_s{2} = kron(ep_r{1}, Id{2}); | |
276 e_s_s{2} = kron(Ip{1}, ed_l{2}); | |
277 e_n_s{2} = kron(Ip{1}, ed_r{2}); | |
278 | |
279 % --- Metric coefficients on stress grids ------- | |
280 x = cell(nGrids, 1); | |
281 y = cell(nGrids, 1); | |
282 J = cell(nGrids, 1); | |
283 x_xi = cell(nGrids, 1); | |
284 x_eta = cell(nGrids, 1); | |
285 y_xi = cell(nGrids, 1); | |
286 y_eta = cell(nGrids, 1); | |
287 | |
288 for a = 1:nGrids | |
289 coords = g_u{a}.points(); | |
290 x{a} = coords(:,1); | |
291 y{a} = coords(:,2); | |
292 end | |
293 | |
294 for a = 1:nGrids | |
295 x_xi{a} = zeros(N_s{a}, 1); | |
296 y_xi{a} = zeros(N_s{a}, 1); | |
297 x_eta{a} = zeros(N_s{a}, 1); | |
298 y_eta{a} = zeros(N_s{a}, 1); | |
299 | |
300 for b = 1:nGrids | |
301 x_xi{a} = x_xi{a} + D1_u2s{a,b}{1}*x{b}; | |
302 y_xi{a} = y_xi{a} + D1_u2s{a,b}{1}*y{b}; | |
303 x_eta{a} = x_eta{a} + D1_u2s{a,b}{2}*x{b}; | |
304 y_eta{a} = y_eta{a} + D1_u2s{a,b}{2}*y{b}; | |
305 end | |
306 end | |
307 | |
308 for a = 1:nGrids | |
309 J{a} = x_xi{a}.*y_eta{a} - x_eta{a}.*y_xi{a}; | |
310 end | |
311 | |
312 K = cell(nGrids, 1); | |
313 for a = 1:nGrids | |
314 K{a} = cell(dim, dim); | |
315 K{a}{1,1} = y_eta{a}./J{a}; | |
316 K{a}{1,2} = -y_xi{a}./J{a}; | |
317 K{a}{2,1} = -x_eta{a}./J{a}; | |
318 K{a}{2,2} = x_xi{a}./J{a}; | |
319 end | |
320 % ---------------------------------------------- | |
321 | |
322 % --- Metric coefficients on displacement grids ------- | |
323 x_s = cell(nGrids, 1); | |
324 y_s = cell(nGrids, 1); | |
325 J_u = cell(nGrids, 1); | |
326 x_xi_u = cell(nGrids, 1); | |
327 x_eta_u = cell(nGrids, 1); | |
328 y_xi_u = cell(nGrids, 1); | |
329 y_eta_u = cell(nGrids, 1); | |
330 | |
331 for a = 1:nGrids | |
332 coords = g_s{a}.points(); | |
333 x_s{a} = coords(:,1); | |
334 y_s{a} = coords(:,2); | |
335 end | |
336 | |
337 for a = 1:nGrids | |
338 x_xi_u{a} = zeros(N_u{a}, 1); | |
339 y_xi_u{a} = zeros(N_u{a}, 1); | |
340 x_eta_u{a} = zeros(N_u{a}, 1); | |
341 y_eta_u{a} = zeros(N_u{a}, 1); | |
342 | |
343 for b = 1:nGrids | |
344 x_xi_u{a} = x_xi_u{a} + D1_s2u{a,b}{1}*x_s{b}; | |
345 y_xi_u{a} = y_xi_u{a} + D1_s2u{a,b}{1}*y_s{b}; | |
346 x_eta_u{a} = x_eta_u{a} + D1_s2u{a,b}{2}*x_s{b}; | |
347 y_eta_u{a} = y_eta_u{a} + D1_s2u{a,b}{2}*y_s{b}; | |
348 end | |
349 end | |
350 | |
351 for a = 1:nGrids | |
352 J_u{a} = x_xi_u{a}.*y_eta_u{a} - x_eta_u{a}.*y_xi_u{a}; | |
353 end | |
354 % ---------------------------------------------- | |
355 | |
356 % x_u = Du*x; | |
357 % x_v = Dv*x; | |
358 % y_u = Du*y; | |
359 % y_v = Dv*y; | |
360 | |
361 % J = x_u.*y_v - x_v.*y_u; | |
362 | |
363 % K = cell(dim, dim); | |
364 % K{1,1} = y_v./J; | |
365 % K{1,2} = -y_u./J; | |
366 % K{2,1} = -x_v./J; | |
367 % K{2,2} = x_u./J; | |
368 | |
369 % Physical derivatives | |
370 % obj.Dx = spdiag( y_v./J)*Du + spdiag(-y_u./J)*Dv; | |
371 % obj.Dy = spdiag(-x_v./J)*Du + spdiag( x_u./J)*Dv; | |
372 | |
373 % Wrap around Aniosotropic Cartesian. Transformed density and stiffness | |
374 rho_tilde = cell(nGrids, 1); | |
375 PHI = cell(nGrids, 1); | |
376 | |
377 for a = 1:nGrids | |
378 rho_tilde{a} = J_u{a}.*rho{a}; | |
379 end | |
380 | |
381 for a = 1:nGrids | |
382 PHI{a} = cell(dim,dim,dim,dim); | |
383 for i = 1:dim | |
384 for j = 1:dim | |
385 for k = 1:dim | |
386 for l = 1:dim | |
387 PHI{a}{i,j,k,l} = 0*C{a}{i,j,k,l}; | |
388 for m = 1:dim | |
389 for n = 1:dim | |
390 PHI{a}{i,j,k,l} = PHI{a}{i,j,k,l} + J{a}.*K{a}{m,i}.*C{a}{m,j,n,l}.*K{a}{n,k}; | |
391 end | |
392 end | |
393 end | |
394 end | |
395 end | |
396 end | |
397 end | |
398 | |
399 refObj = scheme.Elastic2dStaggeredAnisotropic(g.logic, order, rho_tilde, PHI); | |
400 | |
401 G = refObj.G; | |
402 U = refObj.U; | |
403 H_u = refObj.H_u; | |
404 | |
405 % Volume quadrature | |
406 [m, n] = size(refObj.H); | |
407 obj.H = sparse(m, n); | |
408 obj.J = sparse(m, n); | |
409 for a = 1:nGrids | |
410 for i = 1:dim | |
411 obj.H = obj.H + G{a}*U{a}{i}*spdiag(J_u{a})*refObj.H_u{a}*U{a}{i}'*G{a}'; | |
412 obj.J = obj.J + G{a}*U{a}{i}*spdiag(J_u{a})*U{a}{i}'*G{a}'; | |
413 end | |
414 end | |
415 obj.Ji = inv(obj.J); | |
416 | |
417 % Boundary quadratures on stress grids | |
418 s_w = cell(nGrids, 1); | |
419 s_e = cell(nGrids, 1); | |
420 s_s = cell(nGrids, 1); | |
421 s_n = cell(nGrids, 1); | |
422 | |
423 % e_w_u = refObj.e_w_u; | |
424 % e_e_u = refObj.e_e_u; | |
425 % e_s_u = refObj.e_s_u; | |
426 % e_n_u = refObj.e_n_u; | |
427 | |
428 e_w_s = refObj.e_w_s; | |
429 e_e_s = refObj.e_e_s; | |
430 e_s_s = refObj.e_s_s; | |
431 e_n_s = refObj.e_n_s; | |
432 | |
433 for a = 1:nGrids | |
434 s_w{a} = sqrt((e_w_s{a}'*x_eta{a}).^2 + (e_w_s{a}'*y_eta{a}).^2); | |
435 s_e{a} = sqrt((e_e_s{a}'*x_eta{a}).^2 + (e_e_s{a}'*y_eta{a}).^2); | |
436 s_s{a} = sqrt((e_s_s{a}'*x_xi{a}).^2 + (e_s_s{a}'*y_xi{a}).^2); | |
437 s_n{a} = sqrt((e_n_s{a}'*x_xi{a}).^2 + (e_n_s{a}'*y_xi{a}).^2); | |
438 end | |
439 | |
440 obj.s_w = s_w; | |
441 obj.s_e = s_e; | |
442 obj.s_s = s_s; | |
443 obj.s_n = s_n; | |
444 | |
445 % for a = 1:nGrids | |
446 % obj.H_w_s{a} = refObj.H_w_s{a}*spdiag(s_w{a}); | |
447 % obj.H_e_s{a} = refObj.H_e_s{a}*spdiag(s_e{a}); | |
448 % obj.H_s_s{a} = refObj.H_s_s{a}*spdiag(s_s{a}); | |
449 % obj.H_n_s{a} = refObj.H_n_s{a}*spdiag(s_n{a}); | |
450 % end | |
451 | |
452 % Restriction operators | |
453 obj.e_w_u = refObj.e_w_u; | |
454 obj.e_e_u = refObj.e_e_u; | |
455 obj.e_s_u = refObj.e_s_u; | |
456 obj.e_n_u = refObj.e_n_u; | |
457 | |
458 obj.e_w_s = refObj.e_w_s; | |
459 obj.e_e_s = refObj.e_e_s; | |
460 obj.e_s_s = refObj.e_s_s; | |
461 obj.e_n_s = refObj.e_n_s; | |
462 | |
463 % Adapt things from reference object | |
464 obj.D = refObj.D; | |
465 obj.U = refObj.U; | |
466 obj.G = refObj.G; | |
467 | |
468 % obj.e1_w = refObj.e1_w; | |
469 % obj.e1_e = refObj.e1_e; | |
470 % obj.e1_s = refObj.e1_s; | |
471 % obj.e1_n = refObj.e1_n; | |
472 | |
473 % obj.e2_w = refObj.e2_w; | |
474 % obj.e2_e = refObj.e2_e; | |
475 % obj.e2_s = refObj.e2_s; | |
476 % obj.e2_n = refObj.e2_n; | |
477 | |
478 % obj.e_scalar_w = refObj.e_scalar_w; | |
479 % obj.e_scalar_e = refObj.e_scalar_e; | |
480 % obj.e_scalar_s = refObj.e_scalar_s; | |
481 % obj.e_scalar_n = refObj.e_scalar_n; | |
482 | |
483 % e1_w = obj.e1_w; | |
484 % e1_e = obj.e1_e; | |
485 % e1_s = obj.e1_s; | |
486 % e1_n = obj.e1_n; | |
487 | |
488 % e2_w = obj.e2_w; | |
489 % e2_e = obj.e2_e; | |
490 % e2_s = obj.e2_s; | |
491 % e2_n = obj.e2_n; | |
492 | |
493 % obj.tau1_w = (spdiag(1./s_w)*refObj.tau1_w')'; | |
494 % obj.tau1_e = (spdiag(1./s_e)*refObj.tau1_e')'; | |
495 % obj.tau1_s = (spdiag(1./s_s)*refObj.tau1_s')'; | |
496 % obj.tau1_n = (spdiag(1./s_n)*refObj.tau1_n')'; | |
497 | |
498 % obj.tau2_w = (spdiag(1./s_w)*refObj.tau2_w')'; | |
499 % obj.tau2_e = (spdiag(1./s_e)*refObj.tau2_e')'; | |
500 % obj.tau2_s = (spdiag(1./s_s)*refObj.tau2_s')'; | |
501 % obj.tau2_n = (spdiag(1./s_n)*refObj.tau2_n')'; | |
502 | |
503 % obj.tau_w = (refObj.e_w'*obj.e1_w*obj.tau1_w')' + (refObj.e_w'*obj.e2_w*obj.tau2_w')'; | |
504 % obj.tau_e = (refObj.e_e'*obj.e1_e*obj.tau1_e')' + (refObj.e_e'*obj.e2_e*obj.tau2_e')'; | |
505 % obj.tau_s = (refObj.e_s'*obj.e1_s*obj.tau1_s')' + (refObj.e_s'*obj.e2_s*obj.tau2_s')'; | |
506 % obj.tau_n = (refObj.e_n'*obj.e1_n*obj.tau1_n')' + (refObj.e_n'*obj.e2_n*obj.tau2_n')'; | |
507 | |
508 % % Physical normals | |
509 % e_w = obj.e_scalar_w; | |
510 % e_e = obj.e_scalar_e; | |
511 % e_s = obj.e_scalar_s; | |
512 % e_n = obj.e_scalar_n; | |
513 | |
514 % e_w_vec = obj.e_w; | |
515 % e_e_vec = obj.e_e; | |
516 % e_s_vec = obj.e_s; | |
517 % e_n_vec = obj.e_n; | |
518 | |
519 % nu_w = [-1,0]; | |
520 % nu_e = [1,0]; | |
521 % nu_s = [0,-1]; | |
522 % nu_n = [0,1]; | |
523 | |
524 % obj.n_w = cell(2,1); | |
525 % obj.n_e = cell(2,1); | |
526 % obj.n_s = cell(2,1); | |
527 % obj.n_n = cell(2,1); | |
528 | |
529 % n_w_1 = (1./s_w).*e_w'*(J.*(K{1,1}*nu_w(1) + K{1,2}*nu_w(2))); | |
530 % n_w_2 = (1./s_w).*e_w'*(J.*(K{2,1}*nu_w(1) + K{2,2}*nu_w(2))); | |
531 % obj.n_w{1} = spdiag(n_w_1); | |
532 % obj.n_w{2} = spdiag(n_w_2); | |
533 | |
534 % n_e_1 = (1./s_e).*e_e'*(J.*(K{1,1}*nu_e(1) + K{1,2}*nu_e(2))); | |
535 % n_e_2 = (1./s_e).*e_e'*(J.*(K{2,1}*nu_e(1) + K{2,2}*nu_e(2))); | |
536 % obj.n_e{1} = spdiag(n_e_1); | |
537 % obj.n_e{2} = spdiag(n_e_2); | |
538 | |
539 % n_s_1 = (1./s_s).*e_s'*(J.*(K{1,1}*nu_s(1) + K{1,2}*nu_s(2))); | |
540 % n_s_2 = (1./s_s).*e_s'*(J.*(K{2,1}*nu_s(1) + K{2,2}*nu_s(2))); | |
541 % obj.n_s{1} = spdiag(n_s_1); | |
542 % obj.n_s{2} = spdiag(n_s_2); | |
543 | |
544 % n_n_1 = (1./s_n).*e_n'*(J.*(K{1,1}*nu_n(1) + K{1,2}*nu_n(2))); | |
545 % n_n_2 = (1./s_n).*e_n'*(J.*(K{2,1}*nu_n(1) + K{2,2}*nu_n(2))); | |
546 % obj.n_n{1} = spdiag(n_n_1); | |
547 % obj.n_n{2} = spdiag(n_n_2); | |
548 | |
549 % % Operators that extract the normal component | |
550 % obj.en_w = (obj.n_w{1}*obj.e1_w' + obj.n_w{2}*obj.e2_w')'; | |
551 % obj.en_e = (obj.n_e{1}*obj.e1_e' + obj.n_e{2}*obj.e2_e')'; | |
552 % obj.en_s = (obj.n_s{1}*obj.e1_s' + obj.n_s{2}*obj.e2_s')'; | |
553 % obj.en_n = (obj.n_n{1}*obj.e1_n' + obj.n_n{2}*obj.e2_n')'; | |
554 | |
555 % Misc. | |
556 obj.refObj = refObj; | |
557 obj.m = refObj.m; | |
558 obj.h = refObj.h; | |
559 obj.order = order; | |
560 obj.grid = g; | |
561 obj.dim = dim; | |
562 obj.nGrids = nGrids; | |
563 | |
564 end | |
565 | |
566 | |
567 % Closure functions return the operators applied to the own domain to close the boundary | |
568 % Penalty functions return the operators to force the solution. In the case of an interface it returns the operator applied to the other doamin. | |
569 % boundary is a string specifying the boundary e.g. 'l','r' or 'e','w','n','s'. | |
570 % bc is a cell array of component and bc type, e.g. {1, 'd'} for Dirichlet condition | |
571 % on the first component. Can also be e.g. | |
572 % {'normal', 'd'} or {'tangential', 't'} for conditions on | |
573 % tangential/normal component. | |
574 % data is a function returning the data that should be applied at the boundary. | |
575 % neighbour_scheme is an instance of Scheme that should be interfaced to. | |
576 % neighbour_boundary is a string specifying which boundary to interface to. | |
577 | |
578 % For displacement bc: | |
579 % bc = {comp, 'd', dComps}, | |
580 % where | |
581 % dComps = vector of components with displacement BC. Default: 1:dim. | |
582 % In this way, we can specify one BC at a time even though the SATs depend on all BC. | |
583 function [closure, penalty] = boundary_condition(obj, boundary, bc, tuning) | |
584 default_arg('tuning', 1.0); | |
585 assert( iscell(bc), 'The BC type must be a 2x1 or 3x1 cell array' ); | |
586 | |
587 [closure, penalty] = obj.refObj.boundary_condition(boundary, bc, tuning); | |
588 | |
589 type = bc{2}; | |
590 | |
591 switch type | |
592 case {'F','f','Free','free','traction','Traction','t','T'} | |
593 s = obj.(['s_' boundary]); | |
594 s = spdiag(cell2mat(s)); | |
595 penalty = penalty*s; | |
596 end | |
597 end | |
598 | |
599 % type Struct that specifies the interface coupling. | |
600 % Fields: | |
601 % -- tuning: penalty strength, defaults to 1.0 | |
602 % -- interpolation: type of interpolation, default 'none' | |
603 function [closure, penalty] = interface(obj,boundary,neighbour_scheme,neighbour_boundary,type) | |
604 | |
605 defaultType.tuning = 1.0; | |
606 defaultType.interpolation = 'none'; | |
607 default_struct('type', defaultType); | |
608 | |
609 [closure, penalty] = obj.refObj.interface(boundary,neighbour_scheme.refObj,neighbour_boundary,type); | |
610 end | |
611 | |
612 % Returns h11 for the boundary specified by the string boundary. | |
613 % op -- string | |
614 function h11 = getBorrowing(obj, boundary) | |
615 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
616 | |
617 switch boundary | |
618 case {'w','e'} | |
619 h11 = obj.refObj.h11{1}; | |
620 case {'s', 'n'} | |
621 h11 = obj.refObj.h11{2}; | |
622 end | |
623 end | |
624 | |
625 % Returns the outward unit normal vector for the boundary specified by the string boundary. | |
626 % n is a cell of diagonal matrices for each normal component, n{1} = n_1, n{2} = n_2. | |
627 function n = getNormal(obj, boundary) | |
628 error('Not implemented'); | |
629 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
630 | |
631 n = obj.(['n_' boundary]); | |
632 end | |
633 | |
634 % Returns the boundary operator op for the boundary specified by the string boundary. | |
635 % op -- string | |
636 function o = getBoundaryOperator(obj, op, boundary) | |
637 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
638 assertIsMember(op, {'e', 'e1', 'e2', 'tau', 'tau1', 'tau2', 'en'}) | |
639 | |
640 o = obj.([op, '_', boundary]); | |
641 | |
642 end | |
643 | |
644 % Returns the boundary operator op for the boundary specified by the string boundary. | |
645 % op -- string | |
646 function o = getBoundaryOperatorForScalarField(obj, op, boundary) | |
647 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
648 assertIsMember(op, {'e_u', 'e_s'}) | |
649 | |
650 switch op | |
651 case 'e_u' | |
652 o = obj.(['e_', boundary, '_u']); | |
653 case 'e_s' | |
654 o = obj.(['e_', boundary, '_s']); | |
655 end | |
656 | |
657 end | |
658 | |
659 % Returns the boundary operator T_ij (cell format) for the boundary specified by the string boundary. | |
660 % Formula: tau_i = T_ij u_j | |
661 % op -- string | |
662 function T = getBoundaryTractionOperator(obj, boundary) | |
663 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
664 | |
665 T = obj.(['T', '_', boundary]); | |
666 end | |
667 | |
668 % Returns square boundary quadrature matrix, of dimension | |
669 % corresponding to the number of boundary unknowns | |
670 % | |
671 % boundary -- string | |
672 function H = getBoundaryQuadrature(obj, boundary) | |
673 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
674 | |
675 H = obj.getBoundaryQuadratureForScalarField(boundary); | |
676 I_dim = speye(obj.dim, obj.dim); | |
677 H = kron(H, I_dim); | |
678 end | |
679 | |
680 % Returns square boundary quadrature matrix, of dimension | |
681 % corresponding to the number of boundary grid points | |
682 % | |
683 % boundary -- string | |
684 function H_b = getBoundaryQuadratureForScalarField(obj, boundary) | |
685 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
686 | |
687 H_b = obj.(['H_', boundary]); | |
688 end | |
689 | |
690 function N = size(obj) | |
691 N = length(obj.D); | |
692 end | |
693 end | |
694 end |