Mercurial > repos > public > sbplib
comparison +scheme/Heat2dVariable.m @ 997:78db023a7fe3 feature/getBoundaryOp
Add getBoundaryOperator method to all 2d schemes, except obsolete Wave2dCurve and ElastiCurve, which needs a big makeover.
author | Martin Almquist <malmquist@stanford.edu> |
---|---|
date | Sat, 12 Jan 2019 11:57:50 -0800 |
parents | 21394c78c72e |
children | 8d73fcdb07a5 |
comparison
equal
deleted
inserted
replaced
982:a0b3161e44f3 | 997:78db023a7fe3 |
---|---|
1 classdef Heat2dVariable < scheme.Scheme | 1 classdef Heat2dVariable < scheme.Scheme |
2 | 2 |
3 % Discretizes the Laplacian with variable coefficent, | 3 % Discretizes the Laplacian with variable coefficent, |
4 % In the Heat equation way (i.e., the discretization matrix is not necessarily | 4 % In the Heat equation way (i.e., the discretization matrix is not necessarily |
5 % symmetric) | 5 % symmetric) |
6 % u_t = div * (kappa * grad u ) | 6 % u_t = div * (kappa * grad u ) |
7 % opSet should be cell array of opSets, one per dimension. This | 7 % opSet should be cell array of opSets, one per dimension. This |
8 % is useful if we have periodic BC in one direction. | 8 % is useful if we have periodic BC in one direction. |
9 | 9 |
10 properties | 10 properties |
11 m % Number of points in each direction, possibly a vector | 11 m % Number of points in each direction, possibly a vector |
27 | 27 |
28 H, Hi % Inner products | 28 H, Hi % Inner products |
29 e_l, e_r | 29 e_l, e_r |
30 d1_l, d1_r % Normal derivatives at the boundary | 30 d1_l, d1_r % Normal derivatives at the boundary |
31 alpha % Vector of borrowing constants | 31 alpha % Vector of borrowing constants |
32 | 32 |
33 H_boundary % Boundary inner products | 33 H_boundary % Boundary inner products |
34 | 34 |
35 end | 35 end |
36 | 36 |
37 methods | 37 methods |
160 function [closure, penalty] = boundary_condition(obj, boundary, type, symmetric, tuning) | 160 function [closure, penalty] = boundary_condition(obj, boundary, type, symmetric, tuning) |
161 default_arg('type','Neumann'); | 161 default_arg('type','Neumann'); |
162 default_arg('symmetric', false); | 162 default_arg('symmetric', false); |
163 default_arg('tuning',1.2); | 163 default_arg('tuning',1.2); |
164 | 164 |
165 % j is the coordinate direction of the boundary | 165 % nj: outward unit normal component. |
166 % nj: outward unit normal component. | |
167 % nj = -1 for west, south, bottom boundaries | 166 % nj = -1 for west, south, bottom boundaries |
168 % nj = 1 for east, north, top boundaries | 167 % nj = 1 for east, north, top boundaries |
169 [j, nj] = obj.get_boundary_number(boundary); | 168 nj = obj.getBoundarySign(boundary); |
170 switch nj | |
171 case 1 | |
172 e = obj.e_r; | |
173 d = obj.d1_r; | |
174 case -1 | |
175 e = obj.e_l; | |
176 d = obj.d1_l; | |
177 end | |
178 | 169 |
179 Hi = obj.Hi; | 170 Hi = obj.Hi; |
180 H_gamma = obj.H_boundary{j}; | 171 [e, d] = obj.getBoundaryOperator({'e', 'd'}, boundary); |
172 H_gamma = obj.getBoundaryQuadrature(boundary); | |
173 alpha = obj.getBoundaryBorrowing(boundary); | |
174 | |
181 KAPPA = obj.KAPPA; | 175 KAPPA = obj.KAPPA; |
182 kappa_gamma = e{j}'*KAPPA*e{j}; | 176 kappa_gamma = e'*KAPPA*e; |
183 h = obj.h(j); | |
184 alpha = h*obj.alpha(j); | |
185 | 177 |
186 switch type | 178 switch type |
187 | 179 |
188 % Dirichlet boundary condition | 180 % Dirichlet boundary condition |
189 case {'D','d','dirichlet','Dirichlet'} | 181 case {'D','d','dirichlet','Dirichlet'} |
190 | 182 |
191 if ~symmetric | 183 if ~symmetric |
192 closure = -nj*Hi*d{j}*kappa_gamma*H_gamma*(e{j}' ); | 184 closure = -nj*Hi*d*kappa_gamma*H_gamma*(e' ); |
193 penalty = nj*Hi*d{j}*kappa_gamma*H_gamma; | 185 penalty = nj*Hi*d*kappa_gamma*H_gamma; |
194 else | 186 else |
195 closure = nj*Hi*d{j}*kappa_gamma*H_gamma*(e{j}' )... | 187 closure = nj*Hi*d*kappa_gamma*H_gamma*(e' )... |
196 -tuning*2/alpha*Hi*e{j}*kappa_gamma*H_gamma*(e{j}' ) ; | 188 -tuning*2/alpha*Hi*e*kappa_gamma*H_gamma*(e' ) ; |
197 penalty = -nj*Hi*d{j}*kappa_gamma*H_gamma ... | 189 penalty = -nj*Hi*d*kappa_gamma*H_gamma ... |
198 +tuning*2/alpha*Hi*e{j}*kappa_gamma*H_gamma; | 190 +tuning*2/alpha*Hi*e*kappa_gamma*H_gamma; |
199 end | 191 end |
200 | 192 |
201 % Free boundary condition | 193 % Free boundary condition |
202 case {'N','n','neumann','Neumann'} | 194 case {'N','n','neumann','Neumann'} |
203 closure = -nj*Hi*e{j}*kappa_gamma*H_gamma*(d{j}' ); | 195 closure = -nj*Hi*e*kappa_gamma*H_gamma*(d' ); |
204 penalty = Hi*e{j}*kappa_gamma*H_gamma; | 196 penalty = Hi*e*kappa_gamma*H_gamma; |
205 % penalty is for normal derivative and not for derivative, hence the sign. | 197 % penalty is for normal derivative and not for derivative, hence the sign. |
206 | 198 |
207 % Unknown boundary condition | 199 % Unknown boundary condition |
208 otherwise | 200 otherwise |
209 error('No such boundary condition: type = %s',type); | 201 error('No such boundary condition: type = %s',type); |
214 % u denotes the solution in the own domain | 206 % u denotes the solution in the own domain |
215 % v denotes the solution in the neighbour domain | 207 % v denotes the solution in the neighbour domain |
216 error('Interface not implemented'); | 208 error('Interface not implemented'); |
217 end | 209 end |
218 | 210 |
219 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. | 211 % Returns the boundary operator op for the boundary specified by the string boundary. |
220 function [j, nj] = get_boundary_number(obj, boundary) | 212 % op -- string or a cell array of strings |
213 % boundary -- string | |
214 function varargout = getBoundaryOperator(obj, op, boundary) | |
215 | |
216 if ~iscell(op) | |
217 op = {op}; | |
218 end | |
219 | |
220 for i = 1:numel(op) | |
221 switch op{i} | |
222 case 'e' | |
223 switch boundary | |
224 case 'w' | |
225 e = obj.e_l{1}; | |
226 case 'e' | |
227 e = obj.e_r{1}; | |
228 case 's' | |
229 e = obj.e_l{2}; | |
230 case 'n' | |
231 e = obj.e_r{2}; | |
232 otherwise | |
233 error('No such boundary: boundary = %s',boundary); | |
234 end | |
235 varargout{i} = e; | |
236 | |
237 case 'd' | |
238 switch boundary | |
239 case 'w' | |
240 d = obj.d1_l{1}; | |
241 case 'e' | |
242 d = obj.d1_r{1}; | |
243 case 's' | |
244 d = obj.d1_l{2}; | |
245 case 'n' | |
246 d = obj.d1_r{2}; | |
247 otherwise | |
248 error('No such boundary: boundary = %s',boundary); | |
249 end | |
250 varargout{i} = d; | |
251 end | |
252 end | |
253 end | |
254 | |
255 % Returns square boundary quadrature matrix, of dimension | |
256 % corresponding to the number of boundary points | |
257 % | |
258 % boundary -- string | |
259 function H_b = getBoundaryQuadrature(obj, boundary) | |
221 | 260 |
222 switch boundary | 261 switch boundary |
223 case {'w','W','west','West', 'e', 'E', 'east', 'East'} | 262 case 'w' |
224 j = 1; | 263 H_b = obj.H_boundary{1}; |
225 case {'s','S','south','South', 'n', 'N', 'north', 'North'} | 264 case 'e' |
226 j = 2; | 265 H_b = obj.H_boundary{1}; |
266 case 's' | |
267 H_b = obj.H_boundary{2}; | |
268 case 'n' | |
269 H_b = obj.H_boundary{2}; | |
227 otherwise | 270 otherwise |
228 error('No such boundary: boundary = %s',boundary); | 271 error('No such boundary: boundary = %s',boundary); |
229 end | 272 end |
230 | 273 end |
274 | |
275 % Returns the boundary sign. The right boundary is considered the positive boundary | |
276 % boundary -- string | |
277 function s = getBoundarySign(obj, boundary) | |
231 switch boundary | 278 switch boundary |
232 case {'w','W','west','West','s','S','south','South'} | 279 case {'e','n'} |
233 nj = -1; | 280 s = 1; |
234 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 281 case {'w','s'} |
235 nj = 1; | 282 s = -1; |
236 end | |
237 end | |
238 | |
239 % Returns the coordinate number and outward normal component for the boundary specified by the string boundary. | |
240 function [return_op] = get_boundary_operator(obj, op, boundary) | |
241 | |
242 switch boundary | |
243 case {'w','W','west','West', 'e', 'E', 'east', 'East'} | |
244 j = 1; | |
245 case {'s','S','south','South', 'n', 'N', 'north', 'North'} | |
246 j = 2; | |
247 otherwise | 283 otherwise |
248 error('No such boundary: boundary = %s',boundary); | 284 error('No such boundary: boundary = %s',boundary); |
249 end | 285 end |
250 | 286 end |
251 switch op | 287 |
252 case 'e' | 288 % Returns borrowing constant gamma*h |
253 switch boundary | 289 % boundary -- string |
254 case {'w','W','west','West','s','S','south','South'} | 290 function gamm = getBoundaryBorrowing(obj, boundary) |
255 return_op = obj.e_l{j}; | 291 switch boundary |
256 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | 292 case {'w','e'} |
257 return_op = obj.e_r{j}; | 293 gamm = obj.h(1)*obj.alpha(1); |
258 end | 294 case {'s','n'} |
259 case 'd' | 295 gamm = obj.h(2)*obj.alpha(2); |
260 switch boundary | |
261 case {'w','W','west','West','s','S','south','South'} | |
262 return_op = obj.d1_l{j}; | |
263 case {'e', 'E', 'east', 'East','n', 'N', 'north', 'North'} | |
264 return_op = obj.d1_r{j}; | |
265 end | |
266 otherwise | 296 otherwise |
267 error(['No such operator: operatr = ' op]); | 297 error('No such boundary: boundary = %s',boundary); |
268 end | 298 end |
269 | |
270 end | 299 end |
271 | 300 |
272 function N = size(obj) | 301 function N = size(obj) |
273 N = prod(obj.m); | 302 N = prod(obj.m); |
274 end | 303 end |