1 """Building blocks for flux computation. Flux compilation."""
2
3 __copyright__ = "Copyright (C) 2007 Andreas Kloeckner"
4
5 __license__ = """
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see U{http://www.gnu.org/licenses/}.
18 """
19
20
21
22
23 import numpy
24 import hedge._internal as _internal
25 import pymbolic.primitives
26 import pymbolic.mapper.collector
27 import pymbolic.mapper.expander
28 import pymbolic.mapper.flattener
29 import pymbolic.mapper.substitutor
30 import pymbolic.mapper.constant_folder
31 import pymbolic.mapper.flop_counter
32
33
34
35
36 FluxFace = _internal.FluxFace
37
38
39
40
41
42 -class Flux(pymbolic.primitives.AlgebraicLeaf):
45
50 - def __init__(self, name, is_complex=False):
51 pymbolic.primitives.Variable.__init__(self, name)
52 self.is_complex = is_complex
53
56
62 self.index = index
63 self.is_local = is_local
64
66 return (isinstance(other, FieldComponent)
67 and self.index == other.index
68 and self.is_local == other.is_local
69 )
70
72 return self.index, self.is_local
73
75 return hash((
76 self.__class__,
77 self.index,
78 self.is_local))
79
82
89
92
94 return isinstance(other, Normal) and self.axis == other.axis
95
97 return hash((
98 self.__class__,
99 self.axis))
100
103
110
113
115 return isinstance(other, PenaltyTerm) and self.power == other.power
116
118 return hash((
119 self.__class__,
120 self.power))
121
124
129 - def __init__(self, criterion, then, else_):
130 self.criterion = criterion
131 self.then = then
132 self.else_ = else_
133
135 return self.criterion, self.then, self.else_
136
138 return (isinstance(other, IfPositive)
139 and self.criterion == other.criterion
140 and self.then == other.then
141 and self.else_ == other.else_)
142
144 return hash((
145 self.__class__,
146 self.criterion,
147 self.then,
148 self.else_))
149
152
158
159 -class Abs(FluxFunctionSymbol):
161
162 -class Max(FluxFunctionSymbol):
164
165 -class Min(FluxFunctionSymbol):
167
168 flux_abs = Abs()
169 flux_max = Max()
170 flux_min = Min()
171
172
173
174 -def norm(v):
175 return numpy.dot(v, v)**0.5
176
183
189 @property
192
193 @property
196
197 @property
200
207
208 @property
211
212 @property
215
216 @property
218 return 0.5*(self.int+self.ext)
219
224 - def __init__(self, components=None, scalars=None):
225 if not (components is not None or scalars is not None):
226 raise ValueError, "either components or scalars must be specified"
227 if components is not None and scalars is not None:
228 raise ValueError, "only one of components and scalars may be specified"
229
230
231 if components:
232 self.scalars = numpy.array([
233 FluxScalarPlaceholder(i)
234 for i in range(components)])
235 else:
236 self.scalars = numpy.array(scalars)
237
239 return len(self.scalars)
240
246
247 @property
249 return numpy.array([scalar.int for scalar in self.scalars])
250
251 @property
253 return numpy.array([scalar.ext for scalar in self.scalars])
254
255 @property
257 return numpy.array([scalar.avg for scalar in self.scalars])
258
282
283
284
285
286 -class FluxIdentityMapper(
287 pymbolic.mapper.IdentityMapper,
288 FluxIdentityMapperMixin):
290
301
307 if expr.is_local:
308 return "Int[%d]" % expr.index
309 else:
310 return "Ext[%d]" % expr.index
311
313 return "Normal(%d)" % expr.axis
314
316 return "Penalty(%s)" % (expr.power)
317
319 return "IfPositive(%s, %s, %s)" % (expr.criterion, expr.then, expr.else_)
320
321
322
323
324 -class FluxFlattenMapper(pymbolic.mapper.flattener.FlattenMapper,
325 FluxIdentityMapperMixin):
327
347
348
349
350
351
352 -class FluxTermCollector(pymbolic.mapper.collector.TermCollector,
353 FluxIdentityMapperMixin):
355
365
373
375 if expr.local_c == expr.neighbor_c:
376 return expr.local_c
377 else:
378 return expr
379
380
381
382
383 -class FluxCCFMapper(pymbolic.mapper.constant_folder.CommutativeConstantFoldingMapper,
384 FluxIdentityMapperMixin):
387
388
389
390
391 -class FluxExpandMapper(pymbolic.mapper.expander.ExpandMapper,
392 FluxIdentityMapperMixin):
396
406
407
408
409
410
411 -class FluxFlopCounter(pymbolic.mapper.flop_counter.FlopCounter):
431
439