Peano
Loading...
Searching...
No Matches
LinearCombination.py
Go to the documentation of this file.
1# This file is part of the ExaHyPE2 project. For conditions of distribution and
2# use, please see the copyright notice at www.peano-framework.org
3import os
4
5import exahype2.api.dslhype as dslhype
6
7
8
39 solution: "double**",
40 estimates: "double**",
41 output: "double**",
42 weights: "const double*",
43 timeStepSize: "double",
44) -> "void":
45 dt = Float("timeStepSize")
46 Q = DataBlock(
47 [[0, NumberOfUnknowns + NumberOfAuxiliaryVariables], [0, NumberOfDoFs], [0, 1]],
48 "solution",
49 )
50 K = DataBlock(
51 [[0, NumberOfUnknowns], [0, NumberOfDoFs], [0, NumberOfEstimates]], "estimates"
52 )
53 out = DataBlock(
54 [[0, NumberOfUnknowns + NumberOfAuxiliaryVariables], [0, NumberOfDoFs], [0, 1]],
55 "output",
56 )
57 W = DiagonalMatrix(NumberOfEstimates, "weights")
58 out = Q[:, :, :]
59 dot(W, K[0:NumberOfUnknowns, :, :], contribution)
60 out[0:NumberOfUnknowns, :, 0] = out[0:NumberOfUnknowns, :, 0] + dt * contribution
61
62
63LINEAR_COMBINATION_KERNEL_NAME = "linearCombinationOfRungeKuttaEstimates"
64LINEAR_COMBINATION_KERNEL_FILE = "rungekutta_linear_combination"
65
66
67def generate_linear_combination_kernel(namespace, output_directory):
68 """!
69
70 Translate linearCombinationOfRungeKuttaEstimates() into C++
71
72 The kernel ends up in kernels/rungekutta_linear_combination.h in the
73 output directory. It is a function template over NumberOfDoFs,
74 NumberOfUnknowns, NumberOfAuxiliaryVariables and NumberOfEstimates within
75 namespace. It does not depend on any solver, so several solvers within
76 one project can share it: Each of them generates the very same file.
77
78 @param namespace: [str]
79 Namespace of the generated function template, usually the Peano
80 project's namespace.
81
82 @param output_directory: str
83 Directory the kernels/ subdirectory is created in, usually the Peano
84 project's directory.
85
86 """
87 dslhype.translate_dslhype_function(
88 function=linearCombinationOfRungeKuttaEstimates,
89 function_namespace=namespace,
90 template_parameters=[
93 "NumberOfUnknowns", dslhype.SyntaxTree.TInteger()
94 ),
96 "NumberOfAuxiliaryVariables", dslhype.SyntaxTree.TInteger()
97 ),
99 "NumberOfEstimates", dslhype.SyntaxTree.TInteger()
100 ),
101 ],
102 functor_parameters=[],
103 pde_terms=[],
104 output_file_name=LINEAR_COMBINATION_KERNEL_FILE,
105 target=dslhype.Target.Serial,
106 stateless=False,
107 output_directory=output_directory,
108 )
109 include_implementation_into_header(
110 os.path.join(output_directory, "kernels"), LINEAR_COMBINATION_KERNEL_FILE
111 )
112
113
114def include_implementation_into_header(directory: str, file_name: str):
115 """!
116
117 Make a generated kernel header pull in the template definitions
118
119 The translation of a DSLHyPE function yields the declaration in
120 file_name.h and the definition of the function template in
121 file_name.cpph, which itself includes the header. We therefore guard the
122 header and let it include the definitions at its end.
123
124 @param directory: str
125 Directory of the kernels.
126
127 @param file_name: str
128 Name of the kernel without suffix.
129
130 """
131 header = os.path.join(directory, file_name + ".h")
132 with open(header, "r") as file:
133 content = file.read()
134 with open(header, "w") as file:
135 file.write("#pragma once\n" + content + f'\n#include "{file_name}.cpph"\n')
136
137
138def create_linear_combination_call(
139 namespace,
140 number_of_dofs,
141 unknowns,
142 auxiliary_variables,
143 weights,
144 solution,
145 estimates,
146 output,
147 time_step_size,
148):
149 """!
150
151 C++ code which invokes the kernel from generate_linear_combination_kernel()
152
153 The code is a block of its own. It sets up the arrays of pointers the
154 kernel expects and stores the weights as compile-time constants.
155
156 Only the stages with a non-zero weight enter the kernel call. This is
157 not an optimisation only: The estimates of the stages which a
158 combination does not need may be uninitialised, e.g. the estimates of
159 the later stages before the first time step has completed. Multiplying
160 them with zero would still yield NaN if they hold NaN. If all weights
161 are zero, the code copies the solution into the output.
162
163 @param namespace: [str]
164 Namespace of the kernel, see generate_linear_combination_kernel().
165
166 @param number_of_dofs: int
167 Degrees of freedom per cell.
168
169 @param unknowns: int
170 Number of unknowns per degree of freedom.
171
172 @param auxiliary_variables: int
173 Number of auxiliary variables per degree of freedom.
174
175 @param weights: [float]
176 One weight per Runge-Kutta stage, e.g. a row of
177 exahype2.api.rungekutta.ButcherTableau.weight_matrix().
178
179 @param solution: str
180 C++ expression for the pointer to the input data.
181
182 @param estimates: str
183 C++ expression for the pointer to the estimates of all stages. They
184 are stored one after the other, each with number_of_dofs*unknowns
185 entries.
186
187 @param output: str
188 C++ expression for the pointer to the output data. May equal solution.
189
190 @param time_step_size: str
191 C++ expression for the time step size.
192
193 """
194 stages = [stage for stage, weight in enumerate(weights) if weight != 0.0]
195 if not stages:
196 if solution == output:
197 return "{}"
198 return f"""{{
199 std::copy_n( {solution}, {number_of_dofs * (unknowns + auxiliary_variables)}, {output} );
200 }}"""
201
202 stage_pointers = ", ".join(
203 f"{estimates} + {stage * number_of_dofs * unknowns}" for stage in stages
204 )
205 weight_values = ", ".join(repr(float(weights[stage])) for stage in stages)
206 return f"""{{
207 static constexpr double weights[{len(stages)}] = {{ {weight_values} }};
208 double* solutionPointers[1] = {{ {solution} }};
209 double* estimatePointers[{len(stages)}] = {{ {stage_pointers} }};
210 double* outputPointers[1] = {{ {output} }};
211 ::{"::".join(namespace)}::{LINEAR_COMBINATION_KERNEL_NAME}<
212 {number_of_dofs},
213 {unknowns},
214 {auxiliary_variables},
215 {len(stages)}
216 >(solutionPointers, estimatePointers, outputPointers, weights, {time_step_size});
217 }}"""
"void" linearCombinationOfRungeKuttaEstimates("double**" solution, "double**" estimates, "double**" output, "const double*" weights, "double" timeStepSize)
DSLHyPE kernel for the linear combinations of Runge-Kutta.