1  """Interface with Nvidia CUDA.""" 
  2   
  3  from __future__ import division 
  4   
  5  __copyright__ = "Copyright (C) 2008 Andreas Kloeckner" 
  6   
  7  __license__ = """ 
  8  This program is free software: you can redistribute it and/or modify 
  9  it under the terms of the GNU General Public License as published by 
 10  the Free Software Foundation, either version 3 of the License, or 
 11  (at your option) any later version. 
 12   
 13  This program is distributed in the hope that it will be useful, 
 14  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 16  GNU General Public License for more details. 
 17   
 18  You should have received a copy of the GNU General Public License 
 19  along with this program.  If not, see U{http://www.gnu.org/licenses/}. 
 20  """ 
 21   
 22   
 23   
 24  from pytools import Record, memoize_method 
 25  import pymbolic.primitives 
 26  import pymbolic.mapper 
 27  import hedge.optemplate 
 33 -    def map_whole_domain_flux(self, expr, enclosing_prec): 
  34          if expr.is_lift: 
 35              tag = "WLift" 
 36          else: 
 37              tag = "WFlux" 
 38   
 39          return "%s(is_lift=%s,\n    int=%s,\n    tag->flux=%s)" % (tag,  
 40                  expr.is_lift, 
 41                  expr.interiors, 
 42                  expr.boundaries) 
  85   
 86   
 87   
 88 -class WholeDomainFluxOperator(pymbolic.primitives.Leaf): 
  89 -    class FluxInfo(Record): 
  90          __slots__ = [] 
 91   
 93               
 94              return "%s(%s)" % ( 
 95                      self.__class__.__name__, 
 96                      ", ".join("%s=%s" % (fld, getattr(self, fld)) 
 97                          for fld in self.__class__.fields 
 98                          if hasattr(self, fld))) 
   99   
100 -    class InteriorInfo(FluxInfo): 
 101           
102   
103          @property 
104          @memoize_method 
105 -        def dependencies(self): 
 106              return set(get_flux_dependencies( 
107                  self.flux_expr, self.field_expr)) 
  108   
109 -    class BoundaryInfo(FluxInfo): 
 110           
111   
112          @property 
113          @memoize_method 
115              return set(get_flux_dependencies( 
116                      self.flux_expr, self.bpair, bdry="int")) 
 117   
118          @property 
119          @memoize_method 
121              return set(get_flux_dependencies( 
122                      self.flux_expr, self.bpair, bdry="ext")) 
  123                   
124   
125 -    def __init__(self, is_lift, interiors, boundaries,  
126              flux_optemplate=None): 
 127          self.is_lift = is_lift 
128   
129          self.interiors = interiors 
130          self.boundaries = boundaries 
131   
132          from pytools import set_sum 
133          interior_deps = set_sum(iflux.dependencies 
134                  for iflux in interiors) 
135          boundary_int_deps = set_sum(bflux.int_dependencies 
136                  for bflux in boundaries) 
137          boundary_ext_deps = set_sum(bflux.ext_dependencies 
138                  for bflux in boundaries) 
139   
140          self.interior_deps = list(interior_deps) 
141          self.boundary_int_deps = list(boundary_int_deps) 
142          self.boundary_ext_deps = list(boundary_ext_deps) 
143          self.boundary_deps = list(boundary_int_deps | boundary_ext_deps) 
144   
145          self.dep_to_tag = {} 
146          for bflux in boundaries: 
147              for dep in get_flux_dependencies( 
148                      bflux.flux_expr, bflux.bpair, bdry="ext"): 
149                  self.dep_to_tag[dep] = bflux.bpair.tag 
150   
151          self.flux_optemplate = flux_optemplate 
 152   
153       
154 -    def get_hash(self): 
 155          return hash((self.__class__, self.flux_optemplate)) 
 156   
157 -    def is_equal(self, other): 
 158          return (other.__class__ == WholeDomainFluxOperator 
159                  and self.flux_optemplate == other.flux_optemplate) 
 160   
161 -    def __getinitargs__(self): 
 162          return self.is_lift, self.interiors, self.boundaries 
 163           
164 -    def stringifier(self): 
 166   
167 -    def get_mapper_method(self, mapper):  
 168          return mapper.map_whole_domain_flux 
174      """Combines inner fluxes and boundary fluxes into a  
175      single, whole-domain operator of type  
176      L{hedge.backends.cuda.execute.WholeDomainFluxOperator}. 
177      """ 
180   
181      flux_op_types = (hedge.optemplate.FluxOperator,  
182              hedge.optemplate.LiftingFluxOperator) 
183   
185          from hedge.optemplate import OperatorBinding, \ 
186                  LiftingFluxOperator, BoundaryPair 
187           
188          interiors = [] 
189          boundaries = [] 
190          is_lift = None 
191   
192          rest = [] 
193          flux_optemplate_summands = [] 
194   
195          for ch in expressions: 
196              if (isinstance(ch, OperatorBinding)  
197                      and isinstance(ch.op, self.flux_op_types)): 
198                  my_is_lift = isinstance(ch.op, LiftingFluxOperator) 
199   
200                  if is_lift is None: 
201                      is_lift = my_is_lift 
202                  else: 
203                      if is_lift != my_is_lift: 
204                          rest.append(ch) 
205                          continue 
206   
207                  flux_optemplate_summands.append(ch) 
208   
209                  if isinstance(ch.field, BoundaryPair): 
210                      bpair = ch.field 
211                      if self.mesh.tag_to_boundary.get(bpair.tag, []): 
212                          boundaries.append(WholeDomainFluxOperator.BoundaryInfo( 
213                              flux_expr=ch.op.flux, 
214                              bpair=bpair)) 
215                  else: 
216                      interiors.append(WholeDomainFluxOperator.InteriorInfo( 
217                              flux_expr=ch.op.flux, 
218                              field_expr=ch.field)) 
219              else: 
220                  rest.append(ch) 
221   
222          if interiors or boundaries: 
223              from pymbolic.primitives import flattened_sum 
224              wdf = WholeDomainFluxOperator( 
225                      is_lift=is_lift, 
226                      interiors=interiors, 
227                      boundaries=boundaries, 
228                      flux_optemplate=flattened_sum(flux_optemplate_summands)) 
229          else: 
230              wdf = None 
231          return wdf, rest 
 232   
241   
243          from pymbolic.primitives import flattened_sum 
244   
245          result = 0 
246          expressions = expr.children 
247          while True: 
248              wdf, expressions = self.gather_one_wdflux(expressions) 
249              if wdf is not None: 
250                  result += wdf 
251              else: 
252                  return result + flattened_sum(self.rec(r_i) for r_i in expressions) 
  253   
254   
255   
256   
257   
258 -class FluxCollector(hedge.optemplate.CollectorMixin, hedge.optemplate.CombineMapper): 
 261   
263 -    def map_whole_domain_flux(self, expr): 
 264          result = set() 
265   
266          for ii in expr.interiors: 
267              result.update(self.rec(ii.field_expr)) 
268   
269          for bi in expr.boundaries: 
270              result.update(self.rec(bi.bpair.field)) 
271              result.update(self.rec(bi.bpair.bfield)) 
272   
273          return result