Package hedge :: Package cuda :: Module optemplate
[frames] | no frames]

Source Code for Module hedge.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   
 25  import pymbolic.primitives 
 26  import hedge.optemplate 
 27   
 28   
 29   
 30   
31 -class StringifyMapper(hedge.optemplate.StringifyMapper):
32 - def map_whole_domain_flux(self, expr, enclosing_prec):
33 if expr.is_lift: 34 tag = "WLift" 35 else: 36 tag = "WFlux" 37 38 return "%s(int=%s, bdry=%s)" % (tag, 39 expr.interiors, 40 expr.boundaries)
41 42 43 44
45 -class WholeDomainFluxOperator(pymbolic.primitives.Leaf):
46 - def __init__(self, discr, is_lift, interiors, boundaries, 47 flux_optemplate=None):
48 self.discr = discr 49 self.is_lift = is_lift 50 51 self.fluxes = [] 52 53 from pytools import Record 54 self.interiors = interiors 55 56 interior_deps = set( 57 iflux.field_expr for iflux in interiors) 58 boundary_deps = ( 59 set(bflux.field_expr for bflux in boundaries) 60 | 61 set(bflux.bfield_expr for bflux in boundaries) 62 ) 63 self.interior_deps = list(interior_deps) 64 self.boundary_deps = list(boundary_deps) 65 self.all_deps = list(interior_deps|boundary_deps) 66 67 tag_to_bdry_id = {} 68 self.bdry_id_to_fluxes = {} 69 70 for bflux in boundaries: 71 bdry_id = tag_to_bdry_id.setdefault(bflux.tag, len(tag_to_bdry_id)) 72 self.bdry_id_to_fluxes.setdefault(bdry_id, []).append(bflux) 73 74 self.flux_optemplate = flux_optemplate 75 76 self.elface_to_bdry_id = {} 77 for btag, bdry_id in tag_to_bdry_id.iteritems(): 78 for elface in discr.mesh.tag_to_boundary.get(btag, []): 79 if elface in self.elface_to_bdry_id: 80 raise ValueError, "face contained in two boundaries of WholeDomainFlux" 81 self.elface_to_bdry_id[elface] = bdry_id
82 83 @staticmethod
84 - def short_name(field):
85 from pymbolic.primitives import Subscript 86 if isinstance(field, Subscript): 87 return "%s%d" % (field.aggregate, field.index) 88 else: 89 return str(field)
90
91 - def boundary_elface_to_bdry_id(self, elface):
92 try: 93 return self.elface_to_bdry_id[elface] 94 except KeyError: 95 return len(self.fluxes)
96
97 - def stringifier(self):
98 return StringifyMapper
99
100 - def get_mapper_method(self, mapper):
101 return mapper.map_whole_domain_flux
102 103 104 105
106 -class BoundaryCombiner(hedge.optemplate.IdentityMapper):
107 """Combines inner fluxes and boundary fluxes on disjoint parts of the 108 boundary into a single, whole-domain operator. 109 """
110 - def __init__(self, discr):
111 self.discr = discr
112
113 - def handle_unsupported_expression(self, expr):
114 return expr
115
116 - def map_sum(self, expr):
117 from hedge.optemplate import OperatorBinding, \ 118 FluxCoefficientOperator, LiftingFluxCoefficientOperator, \ 119 Field, BoundaryPair 120 121 flux_op_types = (FluxCoefficientOperator, LiftingFluxCoefficientOperator) 122 123 def is_valid_arg(arg): 124 from pymbolic.primitives import Subscript, Variable 125 if isinstance(arg, BoundaryPair): 126 return is_valid_arg(arg.field) and is_valid_arg(arg.bfield) 127 elif isinstance(arg, Subscript): 128 return isinstance(arg.aggregate, Variable) and isinstance(arg.index, int) 129 else: 130 return isinstance(arg, Variable)
131 132 def gather_one_wdflux(expressions): 133 interiors = [] 134 boundaries = [] 135 is_lift = None 136 137 rest = [] 138 flux_optemplate_summands = [] 139 140 from pytools import Record 141 for ch in expressions: 142 if (isinstance(ch, OperatorBinding) 143 and isinstance(ch.op, flux_op_types) 144 and is_valid_arg(ch.field)): 145 my_is_lift = isinstance(ch.op, LiftingFluxCoefficientOperator), 146 147 if is_lift is None: 148 is_lift = my_is_lift 149 else: 150 if is_lift != my_is_lift: 151 rest.append(ch) 152 continue 153 154 flux_optemplate_summands.append(ch) 155 156 if isinstance(ch.field, BoundaryPair): 157 bp = ch.field 158 if ch.op.discr.mesh.tag_to_boundary.get(bp.tag, []): 159 boundaries.append(Record( 160 tag=bp.tag, 161 int_coeff=ch.op.int_coeff, 162 ext_coeff=ch.op.ext_coeff, 163 field_expr=bp.field, 164 bfield_expr=bp.bfield, 165 field_short_name=\ 166 WholeDomainFluxOperator.short_name(bp.field), 167 bfield_short_name= 168 WholeDomainFluxOperator.short_name(bp.bfield), 169 )) 170 else: 171 interiors.append(Record( 172 int_coeff=ch.op.int_coeff, 173 ext_coeff=ch.op.ext_coeff, 174 field_expr=ch.field, 175 short_name=WholeDomainFluxOperator.short_name(ch.field))) 176 else: 177 rest.append(ch) 178 179 if interiors or boundaries: 180 from pymbolic.primitives import flattened_sum 181 wdf = WholeDomainFluxOperator( 182 self.discr, 183 is_lift=is_lift, 184 interiors=interiors, 185 boundaries=boundaries, 186 flux_optemplate=flattened_sum(flux_optemplate_summands)) 187 else: 188 wdf = None 189 return wdf, rest
190 191 result = 0 192 193 from pymbolic.primitives import flattened_sum 194 expressions = expr.children 195 while True: 196 wdf, expressions = gather_one_wdflux(expressions) 197 if wdf is not None: 198 result += wdf 199 else: 200 return result + flattened_sum(self.rec(r_i) for r_i in expressions) 201