1 """Just-in-time compiling backend."""
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 memoize_method
32
33 @memoize_method
34 - def make_lift(self, fgroup, with_scale, dtype):
35 discr = self.discr
36 from codepy.cgen import \
37 FunctionDeclaration, FunctionBody, Typedef, \
38 Const, Reference, Value, POD, \
39 Statement, Include, Line, Block, Initializer, Assign, \
40 For, \
41 Define
42
43 from pytools import to_uncomplex_dtype
44
45 from codepy.bpl import BoostPythonModule
46 mod = BoostPythonModule()
47
48 S = Statement
49 mod.add_to_preamble([
50 Include("hedge/face_operators.hpp"),
51 Include("hedge/volume_operators.hpp"),
52 Include("boost/foreach.hpp"),
53 ])
54
55 mod.add_to_module([
56 S("namespace ublas = boost::numeric::ublas"),
57 S("using namespace hedge"),
58 S("using namespace pyublas"),
59 Line(),
60 Define("DOFS_PER_EL", fgroup.ldis_loc.node_count()),
61 Define("DOFS_PER_FACE", fgroup.ldis_loc.face_node_count()),
62 Define("FACES_PER_EL", fgroup.ldis_loc.face_count()),
63 Define("FACE_DOFS_PER_EL", "(DOFS_PER_FACE*FACES_PER_EL)"),
64 Define("DIMENSIONS", discr.dimensions),
65 Line(),
66 Typedef(POD(dtype, "value_type")),
67 Typedef(POD(to_uncomplex_dtype(dtype), "uncomplex_type")),
68 ])
69
70 def if_(cond, result, else_=None):
71 if cond:
72 return [result]
73 else:
74 if else_ is None:
75 return []
76 else:
77 return [else_]
78
79 fdecl = FunctionDeclaration(
80 Value("void", "lift"),
81 [
82 Const(Reference(Value("face_group", "fg"))),
83 Value("ublas::matrix<uncomplex_type>", "matrix"),
84 Value("numpy_array<value_type>", "field"),
85 Value("numpy_array<value_type>", "result")
86 ]+if_(with_scale,
87 Const(Reference(Value("numpy_array<double>",
88 "elwise_post_scaling"))))
89 )
90
91 def make_it(name, is_const=True, tpname="value_type"):
92 if is_const:
93 const = "const_"
94 else:
95 const = ""
96
97 return Initializer(
98 Value("numpy_array<%s>::%siterator" % (tpname, const), name+"_it"),
99 "%s.begin()" % name)
100
101 fbody = Block([
102 make_it("field"),
103 make_it("result", is_const=False),
104 ]+if_(with_scale, make_it("elwise_post_scaling", tpname="double"))+[
105 Line(),
106 For("unsigned fg_el_nr = 0",
107 "fg_el_nr < fg.element_count()",
108 "++fg_el_nr",
109 Block([
110 Initializer(
111 Value("node_number_t", "dest_el_base"),
112 "fg.local_el_to_global_el_base[fg_el_nr]"),
113 Initializer(
114 Value("node_number_t", "src_el_base"),
115 "FACE_DOFS_PER_EL*fg_el_nr"),
116 Line(),
117 For("unsigned i = 0",
118 "i < DOFS_PER_EL",
119 "++i",
120 Block([
121 Initializer(Value("value_type", "tmp"), 0),
122 Line(),
123 For("unsigned j = 0",
124 "j < FACE_DOFS_PER_EL",
125 "++j",
126 S("tmp += matrix(i, j)*field_it[src_el_base+j]")
127 ),
128 Line(),
129 ]+if_(with_scale,
130 Assign("result_it[dest_el_base+i]",
131 "tmp * value_type(*elwise_post_scaling_it)"),
132 Assign("result_it[dest_el_base+i]", "tmp"))
133 )
134 ),
135 ]+if_(with_scale, S("elwise_post_scaling_it++"))
136 )
137 )
138 ])
139
140 mod.add_function(FunctionBody(fdecl, fbody))
141
142
143
144
145
146 return mod.compile(self.discr.toolchain,
147 wait_on_error="jit_wait_on_compile_error" in discr.debug).lift
148
149 - def __call__(self, fgroup, matrix, scaling, field, out):
162