1   
  2  """Canned operators for several PDEs, such as Maxwell's, heat, Poisson, etc. (deprecated module)""" 
  3   
  4  from __future__ import division 
  5   
  6  __copyright__ = "Copyright (C) 2007 Andreas Kloeckner" 
  7   
  8  __license__ = """ 
  9  This program is free software: you can redistribute it and/or modify 
 10  it under the terms of the GNU General Public License as published by 
 11  the Free Software Foundation, either version 3 of the License, or 
 12  (at your option) any later version. 
 13   
 14  This program is distributed in the hope that it will be useful, 
 15  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 17  GNU General Public License for more details. 
 18   
 19  You should have received a copy of the GNU General Public License 
 20  along with this program.  If not, see U{http://www.gnu.org/licenses/}. 
 21  """ 
 22   
 23   
 24   
 25   
 26   
 27   
 28   
 29   
 30   
 31   
 32   
 33  import numpy 
 34  import numpy.linalg as la 
 35  import hedge.tools 
 36  import hedge.mesh 
 37  import hedge.data 
 38  from pytools import memoize_method 
 39  from hedge.models import Operator, TimeDependentOperator 
 40   
 41   
 42   
 43   
 45      """This operator discretizes the Wave equation S{part}tt u = c^2 S{Delta} u. 
 46   
 47      To be precise, we discretize the hyperbolic system 
 48   
 49       - S{part}t u - c div v = 0 
 50       - S{part}t v - c grad u = 0 
 51   
 52      The sign of M{v} determines whether we discretize the forward or the 
 53      backward wave equation. 
 54   
 55      c is assumed to be constant across all space. 
 56      """ 
 57   
 63          assert isinstance(dimensions, int) 
 64   
 65          self.c = c 
 66          self.dimensions = dimensions 
 67          self.source_f = source_f 
 68   
 69          if self.c > 0: 
 70              self.sign = 1 
 71          else: 
 72              self.sign = -1 
 73   
 74          self.dirichlet_tag = dirichlet_tag 
 75          self.neumann_tag = neumann_tag 
 76          self.radiation_tag = radiation_tag 
 77   
 78          self.flux_type = flux_type 
  79   
109   
111          from hedge.optemplate import \ 
112                  make_vector_field, \ 
113                  pair_with_boundary, \ 
114                  get_flux_operator, \ 
115                  make_nabla, \ 
116                  InverseMassOperator, \ 
117                  BoundarizeOperator 
118   
119          d = self.dimensions 
120   
121          w = make_vector_field("w", d+1) 
122          u = w[0] 
123          v = w[1:] 
124   
125           
126          from hedge.tools import join_fields 
127   
128   
129           
130          dir_u = BoundarizeOperator(self.dirichlet_tag) * u 
131          dir_v = BoundarizeOperator(self.dirichlet_tag) * v 
132          dir_bc = join_fields(-dir_u, dir_v) 
133   
134           
135          neu_u = BoundarizeOperator(self.neumann_tag) * u 
136          neu_v = BoundarizeOperator(self.neumann_tag) * v 
137          neu_bc = join_fields(neu_u, -neu_v) 
138   
139           
140          from hedge.optemplate import make_normal 
141          rad_normal = make_normal(self.radiation_tag, d) 
142   
143          rad_u = BoundarizeOperator(self.radiation_tag) * u 
144          rad_v = BoundarizeOperator(self.radiation_tag) * v 
145   
146          rad_bc = join_fields( 
147                  0.5*(rad_u - self.sign*numpy.dot(rad_normal, rad_v)), 
148                  0.5*rad_normal*(numpy.dot(rad_normal, rad_v) - self.sign*rad_u) 
149                  ) 
150   
151           
152          nabla = make_nabla(d) 
153          flux_op = get_flux_operator(self.flux()) 
154   
155          from hedge.tools import join_fields 
156          return ( 
157                  - join_fields( 
158                      -self.c*numpy.dot(nabla, v), 
159                      -self.c*(nabla*u) 
160                      ) 
161                  + 
162                  InverseMassOperator() * ( 
163                      flux_op*w 
164                      + flux_op * pair_with_boundary(w, dir_bc, self.dirichlet_tag) 
165                      + flux_op * pair_with_boundary(w, neu_bc, self.neumann_tag) 
166                      + flux_op * pair_with_boundary(w, rad_bc, self.radiation_tag) 
167                      )) 
 168   
169   
170 -    def bind(self, discr): 
 171          from hedge.mesh import check_bc_coverage 
172          check_bc_coverage(discr.mesh, [ 
173              self.dirichlet_tag, 
174              self.neumann_tag, 
175              self.radiation_tag]) 
176   
177          compiled_op_template = discr.compile(self.op_template()) 
178   
179          def rhs(t, w): 
180              rhs = compiled_op_template(w=w) 
181   
182              if self.source_f is not None: 
183                  rhs[0] += self.source_f(t) 
184   
185              return rhs 
 186   
187          return rhs 
 188   
191   
192   
193   
194   
196      """This operator discretizes the Wave equation S{part}tt u = c^2 S{Delta} u. 
197   
198      To be precise, we discretize the hyperbolic system 
199   
200       - S{part}t u - c div v = 0 
201       - S{part}t v - c grad u = 0 
202      """ 
203   
210          """`c` is assumed to be positive and conforms to the 
211          `hedge.data.ITimeDependentGivenFunction` interface. 
212   
213          `source` also conforms to the 
214          `hedge.data.ITimeDependentGivenFunction` interface. 
215          """ 
216          assert isinstance(dimensions, int) 
217   
218          self.c = c 
219          self.time_sign = time_sign 
220          self.dimensions = dimensions 
221          self.source = source 
222   
223          self.dirichlet_tag = dirichlet_tag 
224          self.neumann_tag = neumann_tag 
225          self.radiation_tag = radiation_tag 
226   
227          self.flux_type = flux_type 
 228   
257   
259          from hedge.optemplate import \ 
260                  Field, \ 
261                  make_vector_field, \ 
262                  pair_with_boundary, \ 
263                  get_flux_operator, \ 
264                  make_nabla, \ 
265                  InverseMassOperator, \ 
266                  BoundarizeOperator 
267   
268          d = self.dimensions 
269   
270          w = make_vector_field("w", d+1) 
271          u = w[0] 
272          v = w[1:] 
273   
274          from hedge.tools import join_fields 
275          c = Field("c") 
276          flux_w = join_fields(c, w) 
277   
278           
279          from hedge.flux import make_normal 
280          normal = make_normal(d) 
281   
282          from hedge.tools import join_fields 
283           
284          dir_c = BoundarizeOperator(self.dirichlet_tag) * c 
285          dir_u = BoundarizeOperator(self.dirichlet_tag) * u 
286          dir_v = BoundarizeOperator(self.dirichlet_tag) * v 
287   
288          dir_bc = join_fields(dir_c, -dir_u, dir_v) 
289   
290           
291          neu_c = BoundarizeOperator(self.neumann_tag) * c 
292          neu_u = BoundarizeOperator(self.neumann_tag) * u 
293          neu_v = BoundarizeOperator(self.neumann_tag) * v 
294   
295          neu_bc = join_fields(neu_c, neu_u, -neu_v) 
296   
297           
298          from hedge.optemplate import make_normal 
299          rad_normal = make_normal(self.radiation_tag, d) 
300   
301          rad_c = BoundarizeOperator(self.radiation_tag) * c 
302          rad_u = BoundarizeOperator(self.radiation_tag) * u 
303          rad_v = BoundarizeOperator(self.radiation_tag) * v 
304   
305          rad_bc = join_fields( 
306                  rad_c, 
307                  0.5*(rad_u - self.time_sign*numpy.dot(rad_normal, rad_v)), 
308                  0.5*rad_normal*(numpy.dot(rad_normal, rad_v) - self.time_sign*rad_u) 
309                  ) 
310   
311           
312          nabla = make_nabla(d) 
313          flux_op = get_flux_operator(self.flux()) 
314   
315          return ( 
316                  - join_fields( 
317                      -numpy.dot(nabla, self.time_sign*c*v), 
318                      -(nabla*(self.time_sign*c*u)) 
319                      ) 
320                  + 
321                  InverseMassOperator() * ( 
322                      flux_op*flux_w 
323                      + flux_op * pair_with_boundary(flux_w, dir_bc, self.dirichlet_tag) 
324                      + flux_op * pair_with_boundary(flux_w, neu_bc, self.neumann_tag) 
325                      + flux_op * pair_with_boundary(flux_w, rad_bc, self.radiation_tag) 
326                      )) 
 327   
328   
329 -    def bind(self, discr): 
 330          from hedge.mesh import check_bc_coverage 
331          check_bc_coverage(discr.mesh, [ 
332              self.dirichlet_tag, 
333              self.neumann_tag, 
334              self.radiation_tag]) 
335   
336          compiled_op_template = discr.compile(self.op_template()) 
337   
338          def rhs(t, w): 
339              rhs = compiled_op_template(w=w, 
340                      c=self.c.volume_interpolant(t, discr)) 
341   
342              if self.source is not None: 
343                  rhs[0] += self.source.volume_interpolant(t, discr) 
344   
345              return rhs 
 346   
347          return rhs 
 348   
349       
350           
351   
352   
353   
354   
356      """An nD Euler operator. 
357   
358      Field order is [rho E rho_u_x rho_u_y ...]. 
359      """ 
360 -    def __init__(self, dimensions, gamma, bc): 
 364   
367   
370   
373   
375          from hedge.tools import make_obj_array 
376          return make_obj_array([ 
377                  rho_u_i/self.rho(q) 
378                  for rho_u_i in self.rho_u(q)]) 
 379   
381          from hedge.optemplate import make_vector_field, \ 
382                  make_common_subexpression as cse 
383   
384          def u(q): 
385              return cse(self.u(q)) 
 386   
387          def p(q): 
388              return cse((self.gamma-1)*(self.e(q) - 0.5*numpy.dot(self.rho_u(q), u(q)))) 
 389   
390          def flux(q): 
391              from pytools import delta 
392              from hedge.tools import make_obj_array, join_fields 
393              return [  
394                      cse(join_fields( 
395                           
396                          self.rho_u(q)[i], 
397   
398                           
399                          cse(self.e(q)+p(q))*u(q)[i], 
400   
401                           
402                          make_obj_array([ 
403                              self.rho_u(q)[i]*self.u(q)[j] + delta(i,j) * p(q) 
404                              for j in range(self.dimensions) 
405                              ]) 
406                          )) 
407                      for i in range(self.dimensions)] 
408   
409          from hedge.optemplate import make_nabla, InverseMassOperator, \ 
410                  ElementwiseMaxOperator 
411   
412          from pymbolic import var 
413          sqrt = var("sqrt") 
414   
415          state = make_vector_field("q", self.dimensions+2) 
416          bc_state = make_vector_field("bc_q", self.dimensions+2) 
417   
418          c = cse(sqrt(self.gamma*p(state)/self.rho(state))) 
419   
420          speed = sqrt(numpy.dot(u(state), u(state))) + c 
421   
422          from hedge.tools import make_lax_friedrichs_flux, join_fields 
423          from hedge.mesh import TAG_ALL 
424          return join_fields( 
425                  (- numpy.dot(make_nabla(self.dimensions), flux(state)) 
426                      + InverseMassOperator()*make_lax_friedrichs_flux( 
427                          wave_speed=ElementwiseMaxOperator()*c, 
428                          state=state, flux_func=flux, 
429                          bdry_tags_and_states=[ 
430                              (TAG_ALL, bc_state) 
431                              ], 
432                          strong=True 
433                          )), 
434                      speed) 
435   
436 -    def bind(self, discr): 
 447   
448          return wrap 
449