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
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
92 try:
93 return self.elface_to_bdry_id[elface]
94 except KeyError:
95 return len(self.fluxes)
96
97 - def stringifier(self):
99
100 - def get_mapper_method(self, mapper):
101 return mapper.map_whole_domain_flux
102
103
104
105
107 """Combines inner fluxes and boundary fluxes on disjoint parts of the
108 boundary into a single, whole-domain operator.
109 """
112
115
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