Mercurial > repos > public > sbplib
comparison +scheme/elasticShearVariable.m @ 664:8e6dfd22fc59 feature/poroelastic
Free BC now yields symmetric negative semidefinite discretization.
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Fri, 15 Dec 2017 16:23:10 -0800 |
parents | b45ec2b28cc2 |
children | ed853945ee99 |
comparison
equal
deleted
inserted
replaced
663:b45ec2b28cc2 | 664:8e6dfd22fc59 |
---|---|
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 | 5 |
6 grid | 6 grid |
7 dim | |
7 | 8 |
8 order % Order accuracy for the approximation | 9 order % Order accuracy for the approximation |
9 | 10 |
10 a % Variable coefficient lambda of the operator | 11 A % Variable coefficient lambda of the operator (as diagonal matrix here) |
11 rho % Density | 12 RHO % Density (as diagonal matrix here) |
12 | 13 |
13 D % Total operator | 14 D % Total operator |
14 D1 % First derivatives | 15 D1 % First derivatives |
15 D2 % Second derivatives | 16 D2 % Second derivatives |
16 H, Hi % Inner products | 17 H, Hi % Inner products |
17 e_l, e_r | 18 e_l, e_r |
18 d_l, d_r % Normal derivatives at the boundary | 19 d1_l, d1_r % Normal derivatives at the boundary |
20 E % E{i}^T picks out component i | |
21 | |
19 H_boundary % Boundary inner products | 22 H_boundary % Boundary inner products |
23 | |
24 A_boundary_l % Variable coefficient at boundaries | |
25 A_boundary_r % | |
20 end | 26 end |
21 | 27 |
22 methods | 28 methods |
23 % Implements the shear part of the elastic wave equation, i.e. | 29 % Implements the shear part of the elastic wave equation, i.e. |
24 % rho u_{i,tt} = d_i a d_j u_j + d_j a d_j u_i | 30 % rho u_{i,tt} = d_i a d_j u_j + d_j a d_j u_i |
54 e_r = cell(dim,1); | 60 e_r = cell(dim,1); |
55 d1_l = cell(dim,1); | 61 d1_l = cell(dim,1); |
56 d1_r = cell(dim,1); | 62 d1_r = cell(dim,1); |
57 | 63 |
58 for i = 1:dim | 64 for i = 1:dim |
59 I{i} = speye{m(i)); | 65 I{i} = speye(m(i)); |
60 D1{i} = ops{i}.D1; | 66 D1{i} = ops{i}.D1; |
61 D2{i} = ops{i}.D2; | 67 D2{i} = ops{i}.D2; |
62 H{i} = ops{i}.H; | 68 H{i} = ops{i}.H; |
63 Hi{i} = ops{i}.HI; | 69 Hi{i} = ops{i}.HI; |
64 e_l{i} = ops{i}.e_l; | 70 e_l{i} = ops{i}.e_l; |
67 d1_r{i} = ops{i}.d1_r; | 73 d1_r{i} = ops{i}.d1_r; |
68 end | 74 end |
69 | 75 |
70 %====== Assemble full operators ======== | 76 %====== Assemble full operators ======== |
71 A = spdiag(a); | 77 A = spdiag(a); |
78 obj.A = A; | |
72 RHO = spdiag(rho); | 79 RHO = spdiag(rho); |
80 obj.RHO = RHO; | |
81 | |
73 | 82 |
74 obj.D1 = cell(dim,1); | 83 obj.D1 = cell(dim,1); |
75 obj.D2 = cell(dim,1); | 84 obj.D2 = cell(dim,1); |
76 obj.e_l = cell(dim,1); | 85 obj.e_l = cell(dim,1); |
77 obj.e_r = cell(dim,1); | 86 obj.e_r = cell(dim,1); |
78 obj.d1_l = cell(dim,1); | 87 obj.d1_l = cell(dim,1); |
79 obj.d1_r = cell(dim,1); | 88 obj.d1_r = cell(dim,1); |
80 | 89 |
81 % D1 | 90 % D1 |
82 obj.D1{1} = kron{D1{1},I(2)}; | 91 obj.D1{1} = kron(D1{1},I{2}); |
83 obj.D1{2} = kron{I{1},D1(2)}; | 92 obj.D1{2} = kron(I{1},D1{2}); |
84 | 93 |
85 % Boundary operators | 94 % Boundary operators |
86 obj.e_l{1} = kron{e_l{1},I(2)}; | 95 obj.e_l{1} = kron(e_l{1},I{2}); |
87 obj.e_l{2} = kron{I{1},e_l(2)}; | 96 obj.e_l{2} = kron(I{1},e_l{2}); |
88 obj.e_r{1} = kron{e_r{1},I(2)}; | 97 obj.e_r{1} = kron(e_r{1},I{2}); |
89 obj.e_r{2} = kron{I{1},e_r(2)}; | 98 obj.e_r{2} = kron(I{1},e_r{2}); |
90 | 99 |
91 obj.d1_l{1} = kron{d1_l{1},I(2)}; | 100 obj.d1_l{1} = kron(d1_l{1},I{2}); |
92 obj.d1_l{2} = kron{I{1},d1_l(2)}; | 101 obj.d1_l{2} = kron(I{1},d1_l{2}); |
93 obj.d1_r{1} = kron{d1_r{1},I(2)}; | 102 obj.d1_r{1} = kron(d1_r{1},I{2}); |
94 obj.d1_r{2} = kron{I{1},d1_r(2)}; | 103 obj.d1_r{2} = kron(I{1},d1_r{2}); |
95 | 104 |
96 % D2 | 105 % D2 |
97 for i = 1:dim | 106 for i = 1:dim |
98 obj.D2{i} = sparse(m_tot); | 107 obj.D2{i} = sparse(m_tot); |
99 end | 108 end |
111 obj.D2{2}(p,p) = D; | 120 obj.D2{2}(p,p) = D; |
112 end | 121 end |
113 | 122 |
114 % Quadratures | 123 % Quadratures |
115 obj.H = kron(H{1},H{2}); | 124 obj.H = kron(H{1},H{2}); |
125 obj.Hi = inv(obj.H); | |
116 obj.H_boundary = cell(dim,1); | 126 obj.H_boundary = cell(dim,1); |
117 obj.H_boundary{1} = H{2}; | 127 obj.H_boundary{1} = H{2}; |
118 obj.H_boundary{2} = H{1}; | 128 obj.H_boundary{2} = H{1}; |
119 | 129 |
120 % Boundary coefficient matrices and quadratures | 130 % Boundary coefficient matrices and quadratures |
121 obj.A_boundary_l = cell(dim,1); | 131 obj.A_boundary_l = cell(dim,1); |
122 obj.A_boundary_r = cell(dim,1); | 132 obj.A_boundary_r = cell(dim,1); |
123 for i = 1:dim | 133 for i = 1:dim |
124 obj.A_boundary_l{i} = e_l{i}'*A*e_l{i}; | 134 obj.A_boundary_l{i} = obj.e_l{i}'*A*obj.e_l{i}; |
125 obj.A_boundary_r{i} = e_r{i}'*A*e_r{i}; | 135 obj.A_boundary_r{i} = obj.e_r{i}'*A*obj.e_r{i}; |
126 end | 136 end |
127 | 137 |
128 % E{i}^T picks out component i. | 138 % E{i}^T picks out component i. |
129 E = cell(dim,1); | 139 E = cell(dim,1); |
130 I = speye{mtot,mtot}; | 140 I = speye(m_tot,m_tot); |
131 for i = 1:dim | 141 for i = 1:dim |
132 e = sparse(dim,1); | 142 e = sparse(dim,1); |
133 e(i) = 1; | 143 e(i) = 1; |
134 E{i} = kron(e,I) | 144 E{i} = kron(I,e); |
135 end | 145 end |
136 obj.E = E; | 146 obj.E = E; |
137 | 147 |
138 % Differentiation matrix D (without SAT) | 148 % Differentiation matrix D (without SAT) |
139 D = 0; | 149 D2 = obj.D2; |
150 D1 = obj.D1; | |
151 D = sparse(dim*m_tot,dim*m_tot); | |
140 d = @kroneckerDelta; % Kronecker delta | 152 d = @kroneckerDelta; % Kronecker delta |
141 db = @(i,j) 1-dij(i,j); % Logical not of Kronecker delta | 153 db = @(i,j) 1-d(i,j); % Logical not of Kronecker delta |
142 for i = 1:dim | 154 for i = 1:dim |
143 for j = 1:dim | 155 for j = 1:dim |
144 D = D + E{i}*inv(rho)*( d(i,j)*D2{i}*E{j}' +... | 156 D = D + E{i}*inv(RHO)*( d(i,j)*D2{i}*E{j}' +... |
145 db(i,j)*D1{j}*A*D1{i}*E{j}' + ... | 157 db(i,j)*D1{j}*A*D1{i}*E{j}' + ... |
146 D2{j}*E{i}' ... | 158 D2{j}*E{i}' ... |
147 ); | 159 ); |
148 end | 160 end |
149 end | 161 end |
150 obj.D = D; | 162 obj.D = D; |
151 %=========================================% | 163 %=========================================% |
152 | |
153 | |
154 | 164 |
155 % Misc. | 165 % Misc. |
156 obj.m = m; | 166 obj.m = m; |
157 obj.h = h; | 167 obj.h = h; |
158 obj.order = order; | 168 obj.order = order; |
159 obj.grid = g; | 169 obj.grid = g; |
160 | 170 obj.dim = dim; |
161 obj.a = a; | |
162 obj.b = b; | |
163 | 171 |
164 % obj.gamm_u = h_u*ops_u.borrowing.M.d1; | 172 % obj.gamm_u = h_u*ops_u.borrowing.M.d1; |
165 % obj.gamm_v = h_v*ops_v.borrowing.M.d1; | 173 % obj.gamm_v = h_v*ops_v.borrowing.M.d1; |
166 end | 174 end |
167 | 175 |
176 function [closure, penalty] = boundary_condition(obj, boundary, type, parameter) | 184 function [closure, penalty] = boundary_condition(obj, boundary, type, parameter) |
177 default_arg('type','free'); | 185 default_arg('type','free'); |
178 default_arg('parameter', []); | 186 default_arg('parameter', []); |
179 | 187 |
180 delta = @kroneckerDelta; % Kronecker delta | 188 delta = @kroneckerDelta; % Kronecker delta |
181 delta_b = @(i,j) 1-dij(i,j); % Logical not of Kronecker delta | 189 delta_b = @(i,j) 1-delta(i,j); % Logical not of Kronecker delta |
182 | 190 |
183 % j is the coordinate direction of the boundary | 191 % j is the coordinate direction of the boundary |
184 % nj: outward unit normal component. | 192 % nj: outward unit normal component. |
185 % nj = -1 for west, south, bottom boundaries | 193 % nj = -1 for west, south, bottom boundaries |
186 % nj = 1 for east, north, top boundaries | 194 % nj = 1 for east, north, top boundaries |
187 [j, nj] = obj.get_boundary_number(boundary); | 195 [j, nj] = obj.get_boundary_number(boundary); |
188 switch nj | 196 switch nj |
189 case 1 | 197 case 1 |
190 e = obj.e_r; | 198 e = obj.e_r; |
191 d = obj.d_r; | 199 d = obj.d1_r; |
192 case -1 | 200 case -1 |
193 e = obj.e_l; | 201 e = obj.e_l; |
194 d = obj.d_l; | 202 d = obj.d1_l; |
195 end | 203 end |
196 | 204 |
197 E = obj.E; | 205 E = obj.E; |
198 Hi = obj.Hi; | 206 Hi = obj.Hi; |
199 H_gamma = obj.H_boundary{j}; | 207 H_gamma = obj.H_boundary{j}; |
200 A = obj.A; | 208 A = obj.A; |
209 RHO = obj.RHO; | |
210 D1 = obj.D1; | |
201 | 211 |
202 switch type | 212 switch type |
203 % Dirichlet boundary condition | 213 % Dirichlet boundary condition |
204 case {'D','d','dirichlet'} | 214 case {'D','d','dirichlet'} |
205 error('Dirichlet not implemented') | 215 error('Dirichlet not implemented') |
218 penalty = -obj.a*obj.Hi*tau; | 228 penalty = -obj.a*obj.Hi*tau; |
219 | 229 |
220 | 230 |
221 % Free boundary condition | 231 % Free boundary condition |
222 case {'F','f','Free','free'} | 232 case {'F','f','Free','free'} |
223 closure = 0; | 233 closure = sparse(obj.dim*obj.grid.N,obj.dim*obj.grid.N); |
224 penalty = 0; | 234 penalty = sparse(obj.dim*obj.grid.N,obj.dim*obj.grid.N); |
225 % Loop over components | 235 % Loop over components |
226 for i = 1:3 | 236 for i = 1:obj.dim |
227 closure = closure + E{i}*(-sign)*Hi*e{j}*H_gamma*(... | 237 closure = closure + E{i}*inv(RHO)*(-nj)*Hi*e{j}*H_gamma*(... |
228 e{j}'*A*e{j}*d{j}'*E{i}' + ... | 238 e{j}'*A*e{j}*d{j}'*E{i}' + ... |
229 delta(i,j)*e{j}'*A*e{i}*d{i}*E{j}' + ... | 239 delta(i,j)*e{j}'*A*e{i}*d{i}'*E{j}' + ... |
230 delta_b(i,j)*A*D1{i}*E{j}' ... | 240 delta_b(i,j)*e{j}'*A*D1{i}*E{j}' ... |
231 ); | 241 ); |
232 penalty = penalty - E{i}*(-sign)*Hi*e{j}*H_gamma; | 242 penalty = penalty - E{i}*inv(RHO)*(-nj)*Hi*e{j}*H_gamma*e{j}'*E{j}'; |
233 end | 243 end |
244 | |
234 | 245 |
235 % Unknown boundary condition | 246 % Unknown boundary condition |
236 otherwise | 247 otherwise |
237 error('No such boundary condition: type = %s',type); | 248 error('No such boundary condition: type = %s',type); |
238 end | 249 end |
244 tuning = 1.2; | 255 tuning = 1.2; |
245 % tuning = 20.2; | 256 % tuning = 20.2; |
246 error('Interface not implemented'); | 257 error('Interface not implemented'); |
247 end | 258 end |
248 | 259 |
249 % Ruturns the coordinate number and outward normal component for the boundary specified by the string boundary. | 260 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. |
250 function [j, nj] = get_boundary_number(obj, boundary) | 261 function [j, nj] = get_boundary_number(obj, boundary) |
251 | 262 |
252 switch boundary | 263 switch boundary |
253 case {'w','W','west','West', 'e', 'E', 'east', 'East'} | 264 case {'w','W','west','West', 'e', 'E', 'east', 'East'} |
254 j = 1; | 265 j = 1; |
264 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 275 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} |
265 nj = 1; | 276 nj = 1; |
266 end | 277 end |
267 end | 278 end |
268 | 279 |
280 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. | |
281 function [return_op] = get_boundary_operator(obj, op, boundary) | |
282 | |
283 switch boundary | |
284 case {'w','W','west','West', 'e', 'E', 'east', 'East'} | |
285 j = 1; | |
286 case {'s','S','south','South', 'n', 'N', 'north', 'North'} | |
287 j = 2; | |
288 otherwise | |
289 error('No such boundary: boundary = %s',boundary); | |
290 end | |
291 | |
292 switch op | |
293 case 'e' | |
294 switch boundary | |
295 case {'w','W','west','West','s','S','south','South'} | |
296 return_op = obj.e_l{j}; | |
297 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | |
298 return_op = obj.e_r{j}; | |
299 end | |
300 case 'd' | |
301 switch boundary | |
302 case {'w','W','west','West','s','S','south','South'} | |
303 return_op = obj.d_l{j}; | |
304 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | |
305 return_op = obj.d_r{j}; | |
306 end | |
307 otherwise | |
308 error(['No such operator: operatr = ' op]); | |
309 end | |
310 | |
311 end | |
312 | |
269 function N = size(obj) | 313 function N = size(obj) |
270 N = prod(obj.m); | 314 N = prod(obj.m); |
271 end | 315 end |
272 end | 316 end |
273 end | 317 end |