Package hedge :: Package backends :: Package cuda :: Module optemplate
[hide private]
[frames] | no frames]

Source Code for Module hedge.backends.cuda.optemplate

  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 
28 29 30 31 32 -class StringifyMapper(hedge.optemplate.StringifyMapper):
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)
43
44 45 46 47 -def get_flux_dependencies(flux, field, bdry="all"):
48 from hedge.flux import FluxDependencyMapper, FieldComponent 49 in_fields = list(FluxDependencyMapper(composite_leaves=True)(flux)) 50 51 # check that all in_fields are FieldComponent instances 52 assert not [in_field 53 for in_field in in_fields 54 if not isinstance(in_field, FieldComponent)] 55 56 def maybe_index(fld, index): 57 from hedge.tools import is_obj_array 58 if is_obj_array(fld): 59 return fld[inf.index] 60 else: 61 return fld
62 63 from hedge.tools import is_zero 64 from hedge.optemplate import BoundaryPair 65 if isinstance(field, BoundaryPair): 66 for inf in in_fields: 67 if inf.is_local: 68 if bdry in ["all", "int"]: 69 value = maybe_index(field.field, inf.index) 70 71 if not is_zero(value): 72 yield value 73 else: 74 if bdry in ["all", "ext"]: 75 value = maybe_index(field.bfield, inf.index) 76 77 if not is_zero(value): 78 yield value 79 else: 80 for inf in in_fields: 81 value = maybe_index(field, inf.index) 82 if not is_zero(value): 83 yield value 84
85 86 87 88 -class WholeDomainFluxOperator(pymbolic.primitives.Leaf):
89 - class FluxInfo(Record):
90 __slots__ = [] 91
92 - def __repr__(self):
93 # override because we want flux_expr in infix 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 # attributes: flux_expr, field_expr, 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 # attributes: flux_expr, bpair 111 112 @property 113 @memoize_method
114 - def int_dependencies(self):
115 return set(get_flux_dependencies( 116 self.flux_expr, self.bpair, bdry="int"))
117 118 @property 119 @memoize_method
120 - def ext_dependencies(self):
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 # infrastructure interaction
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):
165 return StringifyMapper
166
167 - def get_mapper_method(self, mapper):
168 return mapper.map_whole_domain_flux
169
170 171 172 173 -class BoundaryCombiner(hedge.optemplate.IdentityMapper):
174 """Combines inner fluxes and boundary fluxes into a 175 single, whole-domain operator of type 176 L{hedge.backends.cuda.execute.WholeDomainFluxOperator}. 177 """
178 - def __init__(self, mesh):
179 self.mesh = mesh
180 181 flux_op_types = (hedge.optemplate.FluxOperator, 182 hedge.optemplate.LiftingFluxOperator) 183
184 - def gather_one_wdflux(self, expressions):
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
233 - def map_operator_binding(self, expr):
234 if isinstance(expr.op, self.flux_op_types): 235 wdf, rest = self.gather_one_wdflux([expr]) 236 assert not rest 237 return wdf 238 else: 239 return hedge.optemplate.IdentityMapper \ 240 .map_operator_binding(self, expr)
241
242 - def map_sum(self, expr):
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 # collectors ------------------------------------------------------------------ 258 -class FluxCollector(hedge.optemplate.CollectorMixin, hedge.optemplate.CombineMapper):
259 - def map_whole_domain_flux(self, wdflux):
260 return set([wdflux])
261
262 -class BoundOperatorCollector(hedge.optemplate.BoundOperatorCollector):
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
274