Mercurial > repos > public > sbplib
comparison +scheme/Elastic2dVariable.m @ 1059:d8ab528f10f6 feature/poroelastic
Massive boundary operator cleanup in Elastic2dVariable
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Sat, 26 Jan 2019 15:38:58 -0800 |
parents | 84933722ec0e |
children | e40899094f20 |
comparison
equal
deleted
inserted
replaced
1058:84933722ec0e | 1059:d8ab528f10f6 |
---|---|
13 dim | 13 dim |
14 | 14 |
15 order % Order of accuracy for the approximation | 15 order % Order of accuracy for the approximation |
16 | 16 |
17 % Diagonal matrices for varible coefficients | 17 % Diagonal matrices for varible coefficients |
18 LAMBDA % Variable coefficient, related to dilation | 18 LAMBDA % Lame's first parameter, related to dilation |
19 MU % Shear modulus, variable coefficient | 19 MU % Shear modulus |
20 RHO, RHOi % Density, variable | 20 RHO, RHOi, RHOi_kron % Density |
21 | 21 |
22 D % Total operator | 22 D % Total operator |
23 D1 % First derivatives | 23 D1 % First derivatives |
24 | 24 |
25 % Second derivatives | 25 % Second derivatives |
26 D2_lambda | 26 D2_lambda |
27 D2_mu | 27 D2_mu |
28 | 28 |
29 % Traction operators used for BC | 29 % Boundary operators in cell format, used for BC |
30 T_l, T_r | 30 T_w, T_e, T_s, T_n |
31 tau_l, tau_r | 31 |
32 | 32 % Traction operators |
33 H, Hi, H_1D % Inner products | 33 tau_w, tau_e, tau_s, tau_n % Return vector field |
34 e_l, e_r | 34 tau1_w, tau1_e, tau1_s, tau1_n % Return scalar field |
35 | 35 tau2_w, tau2_e, tau2_s, tau2_n % Return scalar field |
36 | 36 |
37 d1_l, d1_r % Normal derivatives at the boundary | 37 % Inner products |
38 E % E{i}^T picks out component i | 38 H, Hi, Hi_kron, H_1D |
39 | 39 |
40 H_boundary % Boundary inner products | 40 % Boundary inner products (for scalar field) |
41 | 41 H_w, H_e, H_s, H_n |
42 % Kroneckered norms and coefficients | 42 |
43 RHOi_kron | 43 % Boundary restriction operators |
44 Hi_kron | 44 e_w, e_e, e_s, e_n % Act on vector field, return vector field at boundary |
45 e1_w, e1_e, e1_s, e1_n % Act on vector field, return scalar field at boundary | |
46 e2_w, e2_e, e2_s, e2_n % Act on vector field, return scalar field at boundary | |
47 e_scalar_w, e_scalar_e, e_scalar_s, e_scalar_n; % Act on scalar field, return scalar field | |
48 | |
49 % E{i}^T picks out component i | |
50 E | |
45 | 51 |
46 % Borrowing constants of the form gamma*h, where gamma is a dimensionless constant. | 52 % Borrowing constants of the form gamma*h, where gamma is a dimensionless constant. |
47 theta_R % Borrowing (d1- D1)^2 from R | 53 theta_R % Borrowing (d1- D1)^2 from R |
48 theta_H % First entry in norm matrix | 54 theta_H % First entry in norm matrix |
49 theta_M % Borrowing d1^2 from M. | 55 theta_M % Borrowing d1^2 from M. |
103 I = cell(dim,1); | 109 I = cell(dim,1); |
104 D1 = cell(dim,1); | 110 D1 = cell(dim,1); |
105 D2 = cell(dim,1); | 111 D2 = cell(dim,1); |
106 H = cell(dim,1); | 112 H = cell(dim,1); |
107 Hi = cell(dim,1); | 113 Hi = cell(dim,1); |
108 e_l = cell(dim,1); | 114 e_0 = cell(dim,1); |
109 e_r = cell(dim,1); | 115 e_m = cell(dim,1); |
110 d1_l = cell(dim,1); | 116 d1_0 = cell(dim,1); |
111 d1_r = cell(dim,1); | 117 d1_m = cell(dim,1); |
112 | 118 |
113 for i = 1:dim | 119 for i = 1:dim |
114 I{i} = speye(m(i)); | 120 I{i} = speye(m(i)); |
115 D1{i} = ops{i}.D1; | 121 D1{i} = ops{i}.D1; |
116 D2{i} = ops{i}.D2; | 122 D2{i} = ops{i}.D2; |
117 H{i} = ops{i}.H; | 123 H{i} = ops{i}.H; |
118 Hi{i} = ops{i}.HI; | 124 Hi{i} = ops{i}.HI; |
119 e_l{i} = ops{i}.e_l; | 125 e_0{i} = ops{i}.e_l; |
120 e_r{i} = ops{i}.e_r; | 126 e_m{i} = ops{i}.e_r; |
121 d1_l{i} = ops{i}.d1_l; | 127 d1_0{i} = ops{i}.d1_l; |
122 d1_r{i} = ops{i}.d1_r; | 128 d1_m{i} = ops{i}.d1_r; |
123 end | 129 end |
124 | 130 |
125 %====== Assemble full operators ======== | 131 %====== Assemble full operators ======== |
126 LAMBDA = spdiag(lambda); | 132 LAMBDA = spdiag(lambda); |
127 obj.LAMBDA = LAMBDA; | 133 obj.LAMBDA = LAMBDA; |
132 obj.RHOi = inv(RHO); | 138 obj.RHOi = inv(RHO); |
133 | 139 |
134 obj.D1 = cell(dim,1); | 140 obj.D1 = cell(dim,1); |
135 obj.D2_lambda = cell(dim,1); | 141 obj.D2_lambda = cell(dim,1); |
136 obj.D2_mu = cell(dim,1); | 142 obj.D2_mu = cell(dim,1); |
137 obj.e_l = cell(dim,1); | |
138 obj.e_r = cell(dim,1); | |
139 obj.d1_l = cell(dim,1); | |
140 obj.d1_r = cell(dim,1); | |
141 | 143 |
142 % D1 | 144 % D1 |
143 obj.D1{1} = kron(D1{1},I{2}); | 145 obj.D1{1} = kron(D1{1},I{2}); |
144 obj.D1{2} = kron(I{1},D1{2}); | 146 obj.D1{2} = kron(I{1},D1{2}); |
145 | 147 |
146 % Boundary operators | 148 % Boundary restriction operators |
147 obj.e_l{1} = kron(e_l{1},I{2}); | 149 e_l = cell(dim,1); |
148 obj.e_l{2} = kron(I{1},e_l{2}); | 150 e_r = cell(dim,1); |
149 obj.e_r{1} = kron(e_r{1},I{2}); | 151 e_l{1} = kron(e_0{1}, I{2}); |
150 obj.e_r{2} = kron(I{1},e_r{2}); | 152 e_l{2} = kron(I{1}, e_0{2}); |
151 | 153 e_r{1} = kron(e_m{1}, I{2}); |
152 obj.d1_l{1} = kron(d1_l{1},I{2}); | 154 e_r{2} = kron(I{1}, e_m{2}); |
153 obj.d1_l{2} = kron(I{1},d1_l{2}); | 155 |
154 obj.d1_r{1} = kron(d1_r{1},I{2}); | 156 e_scalar_w = e_l{1}; |
155 obj.d1_r{2} = kron(I{1},d1_r{2}); | 157 e_scalar_e = e_r{1}; |
158 e_scalar_s = e_l{2}; | |
159 e_scalar_n = e_r{2}; | |
160 | |
161 I_dim = speye(dim, dim); | |
162 e_w = kron(e_scalar_w, I_dim); | |
163 e_e = kron(e_scalar_e, I_dim); | |
164 e_s = kron(e_scalar_s, I_dim); | |
165 e_n = kron(e_scalar_n, I_dim); | |
166 | |
167 % Boundary derivatives | |
168 d1_l = cell(dim,1); | |
169 d1_r = cell(dim,1); | |
170 d1_l{1} = kron(d1_0{1}, I{2}); | |
171 d1_l{2} = kron(I{1}, d1_0{2}); | |
172 d1_r{1} = kron(d1_m{1}, I{2}); | |
173 d1_r{2} = kron(I{1}, d1_m{2}); | |
174 | |
175 | |
176 % E{i}^T picks out component i. | |
177 E = cell(dim,1); | |
178 I = speye(m_tot,m_tot); | |
179 for i = 1:dim | |
180 e = sparse(dim,1); | |
181 e(i) = 1; | |
182 E{i} = kron(I,e); | |
183 end | |
184 obj.E = E; | |
185 | |
186 e1_w = (e_scalar_w'*E{1}')'; | |
187 e1_e = (e_scalar_e'*E{1}')'; | |
188 e1_s = (e_scalar_s'*E{1}')'; | |
189 e1_n = (e_scalar_n'*E{1}')'; | |
190 | |
191 e2_w = (e_scalar_w'*E{2}')'; | |
192 e2_e = (e_scalar_e'*E{2}')'; | |
193 e2_s = (e_scalar_s'*E{2}')'; | |
194 e2_n = (e_scalar_n'*E{2}')'; | |
195 | |
156 | 196 |
157 % D2 | 197 % D2 |
158 for i = 1:dim | 198 for i = 1:dim |
159 obj.D2_lambda{i} = sparse(m_tot); | 199 obj.D2_lambda{i} = sparse(m_tot); |
160 obj.D2_mu{i} = sparse(m_tot); | 200 obj.D2_mu{i} = sparse(m_tot); |
180 end | 220 end |
181 | 221 |
182 % Quadratures | 222 % Quadratures |
183 obj.H = kron(H{1},H{2}); | 223 obj.H = kron(H{1},H{2}); |
184 obj.Hi = inv(obj.H); | 224 obj.Hi = inv(obj.H); |
185 obj.H_boundary = cell(dim,1); | 225 obj.H_w = H{2}; |
186 obj.H_boundary{1} = H{2}; | 226 obj.H_e = H{2}; |
187 obj.H_boundary{2} = H{1}; | 227 obj.H_s = H{1}; |
228 obj.H_n = H{1}; | |
188 obj.H_1D = {H{1}, H{2}}; | 229 obj.H_1D = {H{1}, H{2}}; |
189 | |
190 % E{i}^T picks out component i. | |
191 E = cell(dim,1); | |
192 I = speye(m_tot,m_tot); | |
193 for i = 1:dim | |
194 e = sparse(dim,1); | |
195 e(i) = 1; | |
196 E{i} = kron(I,e); | |
197 end | |
198 obj.E = E; | |
199 | 230 |
200 % Differentiation matrix D (without SAT) | 231 % Differentiation matrix D (without SAT) |
201 D2_lambda = obj.D2_lambda; | 232 D2_lambda = obj.D2_lambda; |
202 D2_mu = obj.D2_mu; | 233 D2_mu = obj.D2_mu; |
203 D1 = obj.D1; | 234 D1 = obj.D1; |
219 %=========================================%' | 250 %=========================================%' |
220 | 251 |
221 % Numerical traction operators for BC. | 252 % Numerical traction operators for BC. |
222 % Because d1 =/= e0^T*D1, the numerical tractions are different | 253 % Because d1 =/= e0^T*D1, the numerical tractions are different |
223 % at every boundary. | 254 % at every boundary. |
255 % | |
256 % Formula at boundary j: % tau^{j}_i = sum_k T^{j}_{ik} u_k | |
257 % | |
224 T_l = cell(dim,1); | 258 T_l = cell(dim,1); |
225 T_r = cell(dim,1); | 259 T_r = cell(dim,1); |
226 tau_l = cell(dim,1); | 260 tau_l = cell(dim,1); |
227 tau_r = cell(dim,1); | 261 tau_r = cell(dim,1); |
228 % tau^{j}_i = sum_k T^{j}_{ik} u_k | 262 |
229 | |
230 d1_l = obj.d1_l; | |
231 d1_r = obj.d1_r; | |
232 e_l = obj.e_l; | |
233 e_r = obj.e_r; | |
234 D1 = obj.D1; | 263 D1 = obj.D1; |
235 | 264 |
236 % Loop over boundaries | 265 % Loop over boundaries |
237 for j = 1:dim | 266 for j = 1:dim |
238 T_l{j} = cell(dim,dim); | 267 T_l{j} = cell(dim,dim); |
248 [~, n_l] = size(e_l{j}); | 277 [~, n_l] = size(e_l{j}); |
249 [~, n_r] = size(e_r{j}); | 278 [~, n_r] = size(e_r{j}); |
250 | 279 |
251 % Loop over components | 280 % Loop over components |
252 for i = 1:dim | 281 for i = 1:dim |
253 tau_l{j}{i} = sparse(n_l, dim*m_tot); | 282 tau_l{j}{i} = sparse(dim*m_tot, n_l); |
254 tau_r{j}{i} = sparse(n_r, dim*m_tot); | 283 tau_r{j}{i} = sparse(dim*m_tot, n_r); |
255 for k = 1:dim | 284 for k = 1:dim |
256 T_l{j}{i,k} = ... | 285 T_l{j}{i,k} = ... |
257 -d(i,j)*LAMBDA_l*(d(i,k)*d1_l{j}' + db(i,k)*e_l{j}'*D1{k})... | 286 (-d(i,j)*LAMBDA_l*(d(i,k)*d1_l{j}' + db(i,k)*e_l{j}'*D1{k})... |
258 -d(j,k)*MU_l*(d(i,j)*d1_l{j}' + db(i,j)*e_l{j}'*D1{i})... | 287 -d(j,k)*MU_l*(d(i,j)*d1_l{j}' + db(i,j)*e_l{j}'*D1{i})... |
259 -d(i,k)*MU_l*d1_l{j}'; | 288 -d(i,k)*MU_l*d1_l{j}')'; |
260 | 289 |
261 T_r{j}{i,k} = ... | 290 T_r{j}{i,k} = ... |
262 d(i,j)*LAMBDA_r*(d(i,k)*d1_r{j}' + db(i,k)*e_r{j}'*D1{k})... | 291 (d(i,j)*LAMBDA_r*(d(i,k)*d1_r{j}' + db(i,k)*e_r{j}'*D1{k})... |
263 +d(j,k)*MU_r*(d(i,j)*d1_r{j}' + db(i,j)*e_r{j}'*D1{i})... | 292 +d(j,k)*MU_r*(d(i,j)*d1_r{j}' + db(i,j)*e_r{j}'*D1{i})... |
264 +d(i,k)*MU_r*d1_r{j}'; | 293 +d(i,k)*MU_r*d1_r{j}')'; |
265 | 294 |
266 tau_l{j}{i} = tau_l{j}{i} + T_l{j}{i,k}*E{k}'; | 295 tau_l{j}{i} = tau_l{j}{i} + (T_l{j}{i,k}'*E{k}')'; |
267 tau_r{j}{i} = tau_r{j}{i} + T_r{j}{i,k}*E{k}'; | 296 tau_r{j}{i} = tau_r{j}{i} + (T_r{j}{i,k}'*E{k}')'; |
268 end | 297 end |
269 | 298 |
270 end | 299 end |
271 end | 300 end |
272 | 301 |
273 % Transpose T and tau to match boundary operator convention | 302 % Traction tensors, T_ij |
274 for i = 1:dim | 303 obj.T_w = T_l{1}; |
275 for j = 1:dim | 304 obj.T_e = T_r{1}; |
276 tau_l{i}{j} = transpose(tau_l{i}{j}); | 305 obj.T_s = T_l{2}; |
277 tau_r{i}{j} = transpose(tau_r{i}{j}); | 306 obj.T_n = T_r{2}; |
278 for k = 1:dim | 307 |
279 T_l{i}{j,k} = transpose(T_l{i}{j,k}); | 308 % Restriction operators |
280 T_r{i}{j,k} = transpose(T_r{i}{j,k}); | 309 obj.e_w = e_w; |
281 end | 310 obj.e_e = e_e; |
282 end | 311 obj.e_s = e_s; |
283 end | 312 obj.e_n = e_n; |
284 | 313 |
285 obj.T_l = T_l; | 314 obj.e1_w = e1_w; |
286 obj.T_r = T_r; | 315 obj.e1_e = e1_e; |
287 obj.tau_l = tau_l; | 316 obj.e1_s = e1_s; |
288 obj.tau_r = tau_r; | 317 obj.e1_n = e1_n; |
318 | |
319 obj.e2_w = e2_w; | |
320 obj.e2_e = e2_e; | |
321 obj.e2_s = e2_s; | |
322 obj.e2_n = e2_n; | |
323 | |
324 obj.e_scalar_w = e_scalar_w; | |
325 obj.e_scalar_e = e_scalar_e; | |
326 obj.e_scalar_s = e_scalar_s; | |
327 obj.e_scalar_n = e_scalar_n; | |
328 | |
329 % First component of traction | |
330 obj.tau1_w = tau_l{1}{1}; | |
331 obj.tau1_e = tau_r{1}{1}; | |
332 obj.tau1_s = tau_l{2}{1}; | |
333 obj.tau1_n = tau_r{2}{1}; | |
334 | |
335 % Second component of traction | |
336 obj.tau2_w = tau_l{1}{2}; | |
337 obj.tau2_e = tau_r{1}{2}; | |
338 obj.tau2_s = tau_l{2}{2}; | |
339 obj.tau2_n = tau_r{2}{2}; | |
340 | |
341 % Traction vectors | |
342 obj.tau_w = (e_w'*e1_w*obj.tau1_w')' + (e_w'*e2_w*obj.tau2_w')'; | |
343 obj.tau_e = (e_e'*e1_e*obj.tau1_e')' + (e_e'*e2_e*obj.tau2_e')'; | |
344 obj.tau_s = (e_s'*e1_s*obj.tau1_s')' + (e_s'*e2_s*obj.tau2_s')'; | |
345 obj.tau_n = (e_n'*e1_n*obj.tau1_n')' + (e_n'*e2_n*obj.tau2_n')'; | |
289 | 346 |
290 % Kroneckered norms and coefficients | 347 % Kroneckered norms and coefficients |
291 I_dim = speye(dim); | |
292 obj.RHOi_kron = kron(obj.RHOi, I_dim); | 348 obj.RHOi_kron = kron(obj.RHOi, I_dim); |
293 obj.Hi_kron = kron(obj.Hi, I_dim); | 349 obj.Hi_kron = kron(obj.Hi, I_dim); |
294 | 350 |
295 % Misc. | 351 % Misc. |
296 obj.m = m; | 352 obj.m = m; |
358 type = bc{2}; | 414 type = bc{2}; |
359 if ischar(comp) | 415 if ischar(comp) |
360 comp = obj.getComponent(comp, boundary); | 416 comp = obj.getComponent(comp, boundary); |
361 end | 417 end |
362 | 418 |
363 e = obj.getBoundaryOperator('e', boundary); | 419 e = obj.getBoundaryOperatorForScalarField('e', boundary); |
364 T = obj.getBoundaryOperator('T', boundary); | 420 tau = obj.getBoundaryOperator(['tau' num2str(comp)], boundary); |
365 tau = obj.getBoundaryOperator('tau', boundary); | 421 T = obj.getBoundaryTractionOperator(boundary); |
366 H_gamma = obj.getBoundaryOperator('H', boundary); | 422 alpha = obj.getBoundaryOperatorForScalarField('alpha', boundary); |
423 H_gamma = obj.getBoundaryQuadratureForScalarField(boundary); | |
367 | 424 |
368 E = obj.E; | 425 E = obj.E; |
369 Hi = obj.Hi; | 426 Hi = obj.Hi; |
370 LAMBDA = obj.LAMBDA; | 427 LAMBDA = obj.LAMBDA; |
371 MU = obj.MU; | 428 MU = obj.MU; |
373 | 430 |
374 dim = obj.dim; | 431 dim = obj.dim; |
375 m_tot = obj.grid.N(); | 432 m_tot = obj.grid.N(); |
376 | 433 |
377 % Preallocate | 434 % Preallocate |
378 [~, col] = size(tau{comp}); | 435 [~, col] = size(tau); |
379 closure = sparse(dim*m_tot, dim*m_tot); | 436 closure = sparse(dim*m_tot, dim*m_tot); |
380 penalty = sparse(dim*m_tot, col); | 437 penalty = sparse(dim*m_tot, col); |
381 | 438 |
382 k = comp; | 439 k = comp; |
383 switch type | 440 switch type |
384 | 441 |
385 % Dirichlet boundary condition | 442 % Dirichlet boundary condition |
386 case {'D','d','dirichlet','Dirichlet'} | 443 case {'D','d','dirichlet','Dirichlet'} |
387 | |
388 alpha = obj.getBoundaryOperator('alpha', boundary); | |
389 | 444 |
390 % Loop over components that Dirichlet penalties end up on | 445 % Loop over components that Dirichlet penalties end up on |
391 for i = 1:dim | 446 for i = 1:dim |
392 C = transpose(T{k,i}); | 447 C = transpose(T{k,i}); |
393 A = -tuning*e*transpose(alpha{i,k}); | 448 A = -tuning*e*transpose(alpha{i,k}); |
396 penalty = penalty - E{i}*RHOi*Hi*B'*e*H_gamma; | 451 penalty = penalty - E{i}*RHOi*Hi*B'*e*H_gamma; |
397 end | 452 end |
398 | 453 |
399 % Free boundary condition | 454 % Free boundary condition |
400 case {'F','f','Free','free','traction','Traction','t','T'} | 455 case {'F','f','Free','free','traction','Traction','t','T'} |
401 closure = closure - E{k}*RHOi*Hi*e*H_gamma*tau{k}'; | 456 closure = closure - E{k}*RHOi*Hi*e*H_gamma*tau'; |
402 penalty = penalty + E{k}*RHOi*Hi*e*H_gamma; | 457 penalty = penalty + E{k}*RHOi*Hi*e*H_gamma; |
403 | 458 |
404 % Unknown boundary condition | 459 % Unknown boundary condition |
405 otherwise | 460 otherwise |
406 error('No such boundary condition: type = %s',type); | 461 error('No such boundary condition: type = %s',type); |
433 % u denotes the solution in the own domain | 488 % u denotes the solution in the own domain |
434 % v denotes the solution in the neighbour domain | 489 % v denotes the solution in the neighbour domain |
435 % Operators without subscripts are from the own domain. | 490 % Operators without subscripts are from the own domain. |
436 | 491 |
437 % Get boundary operators | 492 % Get boundary operators |
438 e = obj.getBoundaryOperator('e_tot', boundary); | 493 e = obj.getBoundaryOperator('e', boundary); |
439 tau = obj.getBoundaryOperator('tau_tot', boundary); | 494 tau = obj.getBoundaryOperator('tau', boundary); |
440 | 495 |
441 e_v = neighbour_scheme.getBoundaryOperator('e_tot', neighbour_boundary); | 496 e_v = neighbour_scheme.getBoundaryOperator('e', neighbour_boundary); |
442 tau_v = neighbour_scheme.getBoundaryOperator('tau_tot', neighbour_boundary); | 497 tau_v = neighbour_scheme.getBoundaryOperator('tau', neighbour_boundary); |
443 | 498 |
444 H_gamma = obj.getBoundaryQuadrature(boundary); | 499 H_gamma = obj.getBoundaryQuadrature(boundary); |
445 | 500 |
446 % Operators and quantities that correspond to the own domain only | 501 % Operators and quantities that correspond to the own domain only |
447 Hi = obj.Hi_kron; | 502 Hi = obj.Hi_kron; |
448 RHOi = obj.RHOi_kron; | 503 RHOi = obj.RHOi_kron; |
449 | 504 |
450 % Penalty strength operators | 505 % Penalty strength operators |
451 alpha_u = 1/4*tuning*obj.getBoundaryOperator('alpha_tot', boundary); | 506 alpha_u = 1/4*tuning*obj.getBoundaryOperator('alpha', boundary); |
452 alpha_v = 1/4*tuning*neighbour_scheme.getBoundaryOperator('alpha_tot', neighbour_boundary); | 507 alpha_v = 1/4*tuning*neighbour_scheme.getBoundaryOperator('alpha', neighbour_boundary); |
453 | 508 |
454 closure = -RHOi*Hi*e*H_gamma*(alpha_u' + alpha_v'*e_v*e'); | 509 closure = -RHOi*Hi*e*H_gamma*(alpha_u' + alpha_v'*e_v*e'); |
455 penalty = RHOi*Hi*e*H_gamma*(alpha_u'*e*e_v' + alpha_v'); | 510 penalty = RHOi*Hi*e*H_gamma*(alpha_u'*e*e_v' + alpha_v'); |
456 | 511 |
457 closure = closure - 1/2*RHOi*Hi*e*H_gamma*tau'; | 512 closure = closure - 1/2*RHOi*Hi*e*H_gamma*tau'; |
490 end | 545 end |
491 end | 546 end |
492 | 547 |
493 % Returns the boundary operator op for the boundary specified by the string boundary. | 548 % Returns the boundary operator op for the boundary specified by the string boundary. |
494 % op -- string | 549 % op -- string |
495 % Only operators with name *_tot can be used with multiblock.DiffOp.getBoundaryOperator() | |
496 function o = getBoundaryOperator(obj, op, boundary) | 550 function o = getBoundaryOperator(obj, op, boundary) |
497 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | 551 assertIsMember(boundary, {'w', 'e', 's', 'n'}) |
498 assertIsMember(op, {'e', 'e_tot', 'd', 'T', 'tau', 'tau_tot', 'H', 'alpha', 'alpha_tot'}) | 552 assertIsMember(op, {'e', 'e1', 'e2', 'tau', 'tau1', 'tau2', 'alpha'}) |
499 | |
500 switch boundary | |
501 case {'w', 'e'} | |
502 j = 1; | |
503 case {'s', 'n'} | |
504 j = 2; | |
505 end | |
506 | 553 |
507 switch op | 554 switch op |
508 case 'e' | 555 |
509 switch boundary | 556 case {'e', 'e1', 'e2', 'tau', 'tau1', 'tau2'} |
510 case {'w', 's'} | 557 o = obj.([op, '_', boundary]); |
511 o = obj.e_l{j}; | |
512 case {'e', 'n'} | |
513 o = obj.e_r{j}; | |
514 end | |
515 | |
516 case 'e_tot' | |
517 e = obj.getBoundaryOperator('e', boundary); | |
518 I_dim = speye(obj.dim, obj.dim); | |
519 o = kron(e, I_dim); | |
520 | |
521 case 'd' | |
522 switch boundary | |
523 case {'w', 's'} | |
524 o = obj.d1_l{j}; | |
525 case {'e', 'n'} | |
526 o = obj.d1_r{j}; | |
527 end | |
528 | |
529 case 'T' | |
530 switch boundary | |
531 case {'w', 's'} | |
532 o = obj.T_l{j}; | |
533 case {'e', 'n'} | |
534 o = obj.T_r{j}; | |
535 end | |
536 | |
537 case 'tau' | |
538 switch boundary | |
539 case {'w', 's'} | |
540 o = obj.tau_l{j}; | |
541 case {'e', 'n'} | |
542 o = obj.tau_r{j}; | |
543 end | |
544 | |
545 case 'tau_tot' | |
546 e = obj.getBoundaryOperator('e', boundary); | |
547 tau = obj.getBoundaryOperator('tau', boundary); | |
548 | |
549 I_dim = speye(obj.dim, obj.dim); | |
550 e_tot = kron(e, I_dim); | |
551 E = obj.E; | |
552 tau_tot = (e_tot'*E{1}*e*tau{1}')'; | |
553 for i = 2:obj.dim | |
554 tau_tot = tau_tot + (e_tot'*E{i}*e*tau{i}')'; | |
555 end | |
556 o = tau_tot; | |
557 | |
558 case 'H' | |
559 o = obj.H_boundary{j}; | |
560 | 558 |
561 case 'alpha' | 559 case 'alpha' |
562 % alpha = alpha(i,j) is the penalty strength for displacement BC. | 560 % alpha = alpha(i,j) is the penalty strength for displacement BC. |
563 e = obj.getBoundaryOperator('e', boundary); | 561 e = obj.getBoundaryOperatorForScalarField('e', boundary); |
564 | 562 e_tot = obj.getBoundaryOperator('e', boundary); |
565 LAMBDA = obj.LAMBDA; | 563 alpha = obj.getBoundaryOperatorForScalarField('alpha', boundary); |
566 MU = obj.MU; | |
567 | |
568 dim = obj.dim; | |
569 theta_R = obj.theta_R{j}; | |
570 theta_H = obj.theta_H{j}; | |
571 theta_M = obj.theta_M{j}; | |
572 | |
573 a_lambda = dim/theta_H + 1/theta_R; | |
574 a_mu_i = 2/theta_M; | |
575 a_mu_ij = 2/theta_H + 1/theta_R; | |
576 | |
577 d = @kroneckerDelta; % Kronecker delta | |
578 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta | |
579 alpha = cell(obj.dim, obj.dim); | |
580 | |
581 alpha_func = @(i,j) d(i,j)* a_lambda*LAMBDA ... | |
582 + d(i,j)* a_mu_i*MU ... | |
583 + db(i,j)*a_mu_ij*MU; | |
584 for i = 1:obj.dim | |
585 for l = 1:obj.dim | |
586 alpha{i,l} = d(i,l)*alpha_func(i,j)*e; | |
587 end | |
588 end | |
589 | |
590 o = alpha; | |
591 | |
592 case 'alpha_tot' | |
593 % alpha = alpha(i,j) is the penalty strength for displacement BC. | |
594 e = obj.getBoundaryOperator('e', boundary); | |
595 e_tot = obj.getBoundaryOperator('e_tot', boundary); | |
596 alpha = obj.getBoundaryOperator('alpha', boundary); | |
597 E = obj.E; | 564 E = obj.E; |
598 [m, n] = size(alpha{1,1}); | 565 [m, n] = size(alpha{1,1}); |
599 alpha_tot = sparse(m*obj.dim, n*obj.dim); | 566 alpha_tot = sparse(m*obj.dim, n*obj.dim); |
600 for i = 1:obj.dim | 567 for i = 1:obj.dim |
601 for l = 1:obj.dim | 568 for l = 1:obj.dim |
605 o = alpha_tot; | 572 o = alpha_tot; |
606 end | 573 end |
607 | 574 |
608 end | 575 end |
609 | 576 |
577 % Returns the boundary operator op for the boundary specified by the string boundary. | |
578 % op -- string | |
579 function o = getBoundaryOperatorForScalarField(obj, op, boundary) | |
580 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
581 assertIsMember(op, {'e', 'alpha'}) | |
582 | |
583 switch op | |
584 | |
585 case 'e' | |
586 o = obj.(['e_scalar', '_', boundary]); | |
587 | |
588 case 'alpha' | |
589 % alpha = alpha(i,j) is the penalty strength for displacement BC. | |
590 e = obj.getBoundaryOperatorForScalarField('e', boundary); | |
591 | |
592 LAMBDA = obj.LAMBDA; | |
593 MU = obj.MU; | |
594 dim = obj.dim; | |
595 | |
596 switch boundary | |
597 case {'w', 'e'} | |
598 k = 1; | |
599 case {'s', 'n'} | |
600 k = 2; | |
601 end | |
602 | |
603 theta_R = obj.theta_R{k}; | |
604 theta_H = obj.theta_H{k}; | |
605 theta_M = obj.theta_M{k}; | |
606 | |
607 a_lambda = dim/theta_H + 1/theta_R; | |
608 a_mu_i = 2/theta_M; | |
609 a_mu_ij = 2/theta_H + 1/theta_R; | |
610 | |
611 d = @kroneckerDelta; % Kronecker delta | |
612 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta | |
613 alpha = cell(obj.dim, obj.dim); | |
614 | |
615 alpha_func = @(i,j) d(i,j)* a_lambda*LAMBDA ... | |
616 + d(i,j)* a_mu_i*MU ... | |
617 + db(i,j)*a_mu_ij*MU; | |
618 for i = 1:obj.dim | |
619 for j = 1:obj.dim | |
620 alpha{i,j} = d(i,j)*alpha_func(i,k)*e; | |
621 end | |
622 end | |
623 | |
624 o = alpha; | |
625 end | |
626 | |
627 end | |
628 | |
629 % Returns the boundary operator T_ij (cell format) for the boundary specified by the string boundary. | |
630 % op -- string | |
631 function T = getBoundaryTractionOperator(obj, boundary) | |
632 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
633 | |
634 T = obj.(['T', '_', boundary]); | |
635 end | |
636 | |
637 % Returns square boundary quadrature matrix, of dimension | |
638 % corresponding to the number of boundary unknowns | |
639 % | |
640 % boundary -- string | |
610 function H = getBoundaryQuadrature(obj, boundary) | 641 function H = getBoundaryQuadrature(obj, boundary) |
611 switch boundary | 642 assertIsMember(boundary, {'w', 'e', 's', 'n'}) |
612 case {'w','W','west','West', 'e', 'E', 'east', 'East'} | 643 |
613 j = 1; | 644 H = obj.getBoundaryQuadratureForScalarField(boundary); |
614 case {'s','S','south','South', 'n', 'N', 'north', 'North'} | |
615 j = 2; | |
616 otherwise | |
617 error('No such boundary: boundary = %s',boundary); | |
618 end | |
619 H = obj.H_boundary{j}; | |
620 I_dim = speye(obj.dim, obj.dim); | 645 I_dim = speye(obj.dim, obj.dim); |
621 H = kron(H, I_dim); | 646 H = kron(H, I_dim); |
622 end | 647 end |
623 | 648 |
649 % Returns square boundary quadrature matrix, of dimension | |
650 % corresponding to the number of boundary grid points | |
651 % | |
652 % boundary -- string | |
653 function H_b = getBoundaryQuadratureForScalarField(obj, boundary) | |
654 assertIsMember(boundary, {'w', 'e', 's', 'n'}) | |
655 | |
656 H_b = obj.(['H_', boundary]); | |
657 end | |
658 | |
624 function N = size(obj) | 659 function N = size(obj) |
625 N = obj.dim*prod(obj.m); | 660 N = obj.dim*prod(obj.m); |
626 end | 661 end |
627 end | 662 end |
628 end | 663 end |