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)
43
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
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
169
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
274