Peano
Loading...
Searching...
No Matches
kernels.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
3from exahype2.solvers.PDETerms import PDETerms
4
5import jinja2
6from enum import Enum
7import os
8import exahype2
9import exahype2.dslhype as DSL
10
11
12class SolverVariant(Enum):
13 WithVirtualFunctions = 0
14 Stateless = 1
15 Accelerator = 2
16
17
19 PatchWiseAoSStack = 0
20 PatchWiseAoSoAStack = 1
21 PatchWiseSoAStack = 2
22 BatchedAoSStack = 10
23 BatchedAoSoAStack = 11
24 BatchedSoAStack = 12
25 PatchWiseSplitTermsAoSStack = 20
26 PatchWiseSplitTermsAoSoAStack = 21
27 PatchWiseAoSHeap = 30
28 PatchWiseAoSoAHeap = 31
29 PatchWiseSoAHeap = 32
30 BatchedAoSHeap = 40
31 BatchedAoSoAHeap = 41
32 BatchedSoAHeap = 42
33 PatchWiseSplitTermsAoSHeap = 50
34 PatchWiseSplitTermsAoSoAHeap = 51
35 TaskGraphAoSHeap = 60
36 TaskGraphAoSoAHeap = 61
37 TaskGraphSoAHeap = 62
38 PatchWiseInSitu = 90
39 BatchedInSitu = 91
40
41class KernelVariant(Enum):
42 PatchWiseAoS = 10
43 PatchWiseAoSoA = 11
44 PatchWiseSoA = 12
45 BatchedAoS = 20
46 BatchedAoSoA = 21
47 BatchedSoA = 22
48 TaskGraphAoS = 30
49 TaskGraphAoSoA = 31
50 TaskGraphSoA = 32
51 VolumeWiseAoS = 40
52 VolumeWiseAoSoA = 41
53 VolumeWiseSoA = 42
54
55
57 if not os.path.exists("kernels"):
58 os.makedirs("kernels")
59
60 file = open("kernels/musclhancock.h", "w")
61 file.write("""#if Dimensions == 2
62#include "musclhancock2d.h"
63#elif Dimensions == 3
64#include "musclhancock3d.h"
65#endif
66""")
67
70
72 template_parameters = [DSL.SyntaxTree.Argument("NV", DSL.SyntaxTree.TInteger()),
73 DSL.SyntaxTree.Argument("H", DSL.SyntaxTree.TInteger()),
74 DSL.SyntaxTree.Argument("NumberOfUnknowns", DSL.SyntaxTree.TInteger()),
75 DSL.SyntaxTree.Argument("NumberOfAuxiliaryVariables", DSL.SyntaxTree.TInteger()),
76 DSL.SyntaxTree.Argument("EvaluateFlux", DSL.SyntaxTree.TBoolean()),
77 DSL.SyntaxTree.Argument("EvaluateNonconservativeProduct", DSL.SyntaxTree.TBoolean()),
78 DSL.SyntaxTree.Argument("EvaluateSource", DSL.SyntaxTree.TBoolean()),
79 DSL.SyntaxTree.Argument("EvaluateMaximumEigenvalueAfterTimeStep", DSL.SyntaxTree.TBoolean())]
80
81 functor_arguments = [DSL.SyntaxTree.Argument("flux", DSL.SyntaxTree.TCustom("const FluxFunctor&")),
82 DSL.SyntaxTree.Argument("nonconservativeProduct", DSL.SyntaxTree.TCustom("const NonconservativeProductFunctor&")),
83 DSL.SyntaxTree.Argument("sourceTerm", DSL.SyntaxTree.TCustom("const SourceFunctor&")),
84 DSL.SyntaxTree.Argument("maxEigenvalue", DSL.SyntaxTree.TCustom("const MaxEigenvalueFunctor&"))]
85
86 musclhancock_kernel_tree = DSL.Parser().parse(exahype2.solvers.fv.musclhancock.timeStepWithMUSCLHancock2d, template_parameters, functor_arguments, ["exahype2", "fv", "musclhancock"], stateless=False)
87 musclhancock_kernel = musclhancock_kernel_tree.print_cpp()
88 musclhancock_call_with_measurement = musclhancock_kernel_tree.print_definition_with_timer()
89 musclhancock_kernel_declaration = musclhancock_kernel_tree.print_declaration()
90 musclhancock_call_with_measurement_declaration = musclhancock_kernel_tree.print_declaration_with_timer()
91
92 musclhancock_stateless_kernel_tree = DSL.Parser().parse(exahype2.solvers.fv.musclhancock.timeStepWithMUSCLHancock2d, template_parameters, functor_arguments, ["exahype2", "fv", "musclhancock"], stateless=True)
93 musclhancock_stateless_kernel = musclhancock_stateless_kernel_tree.print_cpp()
94 musclhancock_stateless_call_with_measurement = musclhancock_stateless_kernel_tree.print_definition_with_timer()
95 musclhancock_stateless_kernel_declaration = musclhancock_stateless_kernel_tree.print_declaration()
96 musclhancock_stateless_call_with_measurement_declaration = musclhancock_stateless_kernel_tree.print_declaration_with_timer()
97
98 musclhancock_omp_kernel_tree = DSL.Parser().parse(exahype2.solvers.fv.musclhancock.timeStepWithMUSCLHancock2d, template_parameters, functor_arguments, ["exahype2", "fv", "musclhancock", "omp"], stateless=False)
99 musclhancock_omp_kernel = musclhancock_omp_kernel_tree.print_omp()
100 musclhancock_omp_call_with_measurement = musclhancock_omp_kernel_tree.print_definition_with_timer()
101 musclhancock_omp_kernel_declaration = musclhancock_omp_kernel_tree.print_declaration()
102 musclhancock_omp_call_with_measurement_declaration = musclhancock_omp_kernel_tree.print_declaration_with_timer()
103
104 musclhancock_omp_stateless_kernel_tree = DSL.Parser().parse(exahype2.solvers.fv.musclhancock.timeStepWithMUSCLHancock2d, template_parameters, functor_arguments, ["exahype2", "fv", "musclhancock", "omp"], stateless=True)
105 musclhancock_omp_stateless_kernel = musclhancock_omp_stateless_kernel_tree.print_omp()
106 musclhancock_omp_stateless_call_with_measurement = musclhancock_omp_stateless_kernel_tree.print_definition_with_timer()
107 musclhancock_omp_stateless_kernel_declaration = musclhancock_omp_stateless_kernel_tree.print_declaration()
108 musclhancock_omp_stateless_call_with_measurement_declaration = musclhancock_omp_stateless_kernel_tree.print_declaration_with_timer()
109
110 musclhancock_omp_accelerator_kernel_tree = DSL.Parser().parse(exahype2.solvers.fv.musclhancock.timeStepWithMUSCLHancock2d, template_parameters, functor_arguments, ["exahype2", "fv", "musclhancock", "omp"], stateless=True, use_accelerator=True)
111 musclhancock_omp_accelerator_kernel = musclhancock_omp_accelerator_kernel_tree.print_omp()
112 musclhancock_omp_accelerator_call_with_measurement = musclhancock_omp_accelerator_kernel_tree.print_definition_with_timer()
113 musclhancock_omp_accelerator_kernel_declaration = musclhancock_omp_accelerator_kernel_tree.print_declaration()
114 musclhancock_omp_accelerator_call_with_measurement_declaration = musclhancock_omp_accelerator_kernel_tree.print_declaration_with_timer()
115
116 if not os.path.exists("kernels"):
117 os.makedirs("kernels")
118
119 file = open("kernels/musclhancock2d.h", "w")
120 file.write(f"""#pragma once
121#include "exahype2/CellData.h"
122#include "exahype2/VolumeIndex.h"
123#include "exahype2/fv/PatchUtils.h"
124#include "exahype2/fv/musclhancock/Functors.h"
125#include "peano4/utils/Loop.h"
126#include "tarch/timing/Measurement.h"
127#include "tarch/timing/Watch.h"
128
129{musclhancock_kernel_declaration}
130{musclhancock_call_with_measurement_declaration}
131
132{musclhancock_stateless_kernel_declaration}
133{musclhancock_stateless_call_with_measurement_declaration}
134
135#if defined(SharedOMP)
136{musclhancock_omp_kernel_declaration}
137{musclhancock_omp_call_with_measurement_declaration}
138{musclhancock_omp_stateless_kernel_declaration}
139{musclhancock_omp_stateless_call_with_measurement_declaration}
140#endif
141
142#if defined(GPUOffloadingOMP)
143{musclhancock_omp_accelerator_kernel_declaration}
144{musclhancock_omp_accelerator_call_with_measurement_declaration}
145#endif
146
147#include "musclhancock2d.cpph"
148""")
149 file.close()
150
151 file = open("kernels/musclhancock2d.cpph", "w")
152 file.write(musclhancock_kernel)
153 file.write(musclhancock_call_with_measurement)
154 file.write(musclhancock_stateless_kernel)
155 file.write(musclhancock_stateless_call_with_measurement)
156
157 file.write("#if defined(SharedOMP)\n")
158 file.write(musclhancock_omp_kernel)
159 file.write(musclhancock_omp_call_with_measurement)
160 file.write(musclhancock_omp_stateless_kernel)
161 file.write(musclhancock_omp_stateless_call_with_measurement)
162 file.write("#endif\n")
163
164 file.write("#if defined(GPUOffloadingOMP)\n")
165 file.write(musclhancock_omp_accelerator_kernel)
166 file.write(musclhancock_omp_accelerator_call_with_measurement)
167 file.write("#endif\n")
168 file.close()
169
171 template_parameters = [DSL.SyntaxTree.Argument("NV", DSL.SyntaxTree.TInteger()),
172 DSL.SyntaxTree.Argument("H", DSL.SyntaxTree.TInteger()),
173 DSL.SyntaxTree.Argument("NumberOfUnknowns", DSL.SyntaxTree.TInteger()),
174 DSL.SyntaxTree.Argument("NumberOfAuxiliaryVariables", DSL.SyntaxTree.TInteger()),
175 DSL.SyntaxTree.Argument("EvaluateFlux", DSL.SyntaxTree.TBoolean()),
176 DSL.SyntaxTree.Argument("EvaluateNonconservativeProduct", DSL.SyntaxTree.TBoolean()),
177 DSL.SyntaxTree.Argument("EvaluateSource", DSL.SyntaxTree.TBoolean()),
178 DSL.SyntaxTree.Argument("EvaluateMaximumEigenvalueAfterTimeStep", DSL.SyntaxTree.TBoolean())]
179
180 functor_arguments = [DSL.SyntaxTree.Argument("flux", DSL.SyntaxTree.TCustom("const FluxFunctor&")),
181 DSL.SyntaxTree.Argument("nonconservativeProduct", DSL.SyntaxTree.TCustom("const NonconservativeProductFunctor&")),
182 DSL.SyntaxTree.Argument("sourceTerm", DSL.SyntaxTree.TCustom("const SourceFunctor&")),
183 DSL.SyntaxTree.Argument("maxEigenvalue", DSL.SyntaxTree.TCustom("const MaxEigenvalueFunctor&"))]
184
185 musclhancock_kernel_tree = DSL.Parser().parse(exahype2.solvers.fv.musclhancock.timeStepWithMUSCLHancock3d, template_parameters, functor_arguments, ["exahype2", "fv", "musclhancock"], stateless=False)
186 musclhancock_kernel = musclhancock_kernel_tree.print_cpp()
187 musclhancock_call_with_measurement = musclhancock_kernel_tree.print_definition_with_timer()
188 musclhancock_kernel_declaration = musclhancock_kernel_tree.print_declaration()
189 musclhancock_call_with_measurement_declaration = musclhancock_kernel_tree.print_declaration_with_timer()
190
191 musclhancock_stateless_kernel_tree = DSL.Parser().parse(exahype2.solvers.fv.musclhancock.timeStepWithMUSCLHancock3d, template_parameters, functor_arguments, ["exahype2", "fv", "musclhancock"], stateless=True)
192 musclhancock_stateless_kernel = musclhancock_stateless_kernel_tree.print_cpp()
193 musclhancock_stateless_call_with_measurement = musclhancock_stateless_kernel_tree.print_definition_with_timer()
194 musclhancock_stateless_kernel_declaration = musclhancock_stateless_kernel_tree.print_declaration()
195 musclhancock_stateless_call_with_measurement_declaration = musclhancock_stateless_kernel_tree.print_declaration_with_timer()
196
197 musclhancock_omp_kernel_tree = DSL.Parser().parse(exahype2.solvers.fv.musclhancock.timeStepWithMUSCLHancock3d, template_parameters, functor_arguments, ["exahype2", "fv", "musclhancock", "omp"], stateless=False)
198 musclhancock_omp_kernel = musclhancock_omp_kernel_tree.print_omp()
199 musclhancock_omp_call_with_measurement = musclhancock_omp_kernel_tree.print_definition_with_timer()
200 musclhancock_omp_kernel_declaration = musclhancock_omp_kernel_tree.print_declaration()
201 musclhancock_omp_call_with_measurement_declaration = musclhancock_omp_kernel_tree.print_declaration_with_timer()
202
203 musclhancock_omp_stateless_kernel_tree = DSL.Parser().parse(exahype2.solvers.fv.musclhancock.timeStepWithMUSCLHancock3d, template_parameters, functor_arguments, ["exahype2", "fv", "musclhancock", "omp"], stateless=True)
204 musclhancock_omp_stateless_kernel = musclhancock_omp_stateless_kernel_tree.print_omp()
205 musclhancock_omp_stateless_call_with_measurement = musclhancock_omp_stateless_kernel_tree.print_definition_with_timer()
206 musclhancock_omp_stateless_kernel_declaration = musclhancock_omp_stateless_kernel_tree.print_declaration()
207 musclhancock_omp_stateless_call_with_measurement_declaration = musclhancock_omp_stateless_kernel_tree.print_declaration_with_timer()
208
209 musclhancock_omp_accelerator_kernel_tree = DSL.Parser().parse(exahype2.solvers.fv.musclhancock.timeStepWithMUSCLHancock3d, template_parameters, functor_arguments, ["exahype2", "fv", "musclhancock", "omp"], stateless=True, use_accelerator=True)
210 musclhancock_omp_accelerator_kernel = musclhancock_omp_accelerator_kernel_tree.print_omp()
211 musclhancock_omp_accelerator_call_with_measurement = musclhancock_omp_accelerator_kernel_tree.print_definition_with_timer()
212 musclhancock_omp_accelerator_kernel_declaration = musclhancock_omp_accelerator_kernel_tree.print_declaration()
213 musclhancock_omp_accelerator_call_with_measurement_declaration = musclhancock_omp_accelerator_kernel_tree.print_declaration_with_timer()
214
215 if not os.path.exists("kernels"):
216 os.makedirs("kernels")
217
218 file = open("kernels/musclhancock3d.h", "w")
219 file.write(f"""#pragma once
220#include "exahype2/CellData.h"
221#include "exahype2/VolumeIndex.h"
222#include "exahype2/fv/PatchUtils.h"
223#include "exahype2/fv/musclhancock/Functors.h"
224#include "peano4/utils/Loop.h"
225#include "tarch/timing/Measurement.h"
226#include "tarch/timing/Watch.h"
227
228{musclhancock_kernel_declaration}
229{musclhancock_call_with_measurement_declaration}
230
231{musclhancock_stateless_kernel_declaration}
232{musclhancock_stateless_call_with_measurement_declaration}
233
234#if defined(SharedOMP)
235{musclhancock_omp_kernel_declaration}
236{musclhancock_omp_call_with_measurement_declaration}
237{musclhancock_omp_stateless_kernel_declaration}
238{musclhancock_omp_stateless_call_with_measurement_declaration}
239#endif
240
241#if defined(GPUOffloadingOMP)
242{musclhancock_omp_accelerator_kernel_declaration}
243{musclhancock_omp_accelerator_call_with_measurement_declaration}
244#endif
245
246#include "musclhancock3d.cpph"
247""")
248 file.close()
249
250 file = open("kernels/musclhancock3d.cpph", "w")
251 file.write(musclhancock_kernel)
252 file.write(musclhancock_call_with_measurement)
253 file.write(musclhancock_stateless_kernel)
254 file.write(musclhancock_stateless_call_with_measurement)
255
256 file.write("#if defined(SharedOMP)\n")
257 file.write(musclhancock_omp_kernel)
258 file.write(musclhancock_omp_call_with_measurement)
259 file.write(musclhancock_omp_stateless_kernel)
260 file.write(musclhancock_omp_stateless_call_with_measurement)
261 file.write("#endif\n")
262
263 file.write("#if defined(GPUOffloadingOMP)\n")
264 file.write(musclhancock_omp_accelerator_kernel)
265 file.write(musclhancock_omp_accelerator_call_with_measurement)
266 file.write("#endif\n")
267 file.close()
268
269def create_compute_Riemann_kernel_for_MUSCLHancock_dsl(flux_implementation,
270 ncp_implementation,
271 source_implementation,
272 compute_max_eigenvalue_of_next_time_step,
273 solver_variant: SolverVariant,
274 kernel_variant: KernelVariant):
275 """
276 Return only the unqualified function call, i.e., without any namespaces.
277 So by setting the right namespace as prefix, you can direct it to particular
278 implementations.
279 """
280
281 template = "timeStepWithMUSCLHancock"
282
283 if solver_variant == SolverVariant.WithVirtualFunctions:
284 template += """<
285 {{NUMBER_OF_VOLUMES_PER_AXIS}},
286 {{HALO_SIZE}},
287 {{NUMBER_OF_UNKNOWNS}},
288 {{NUMBER_OF_AUXILIARY_VARIABLES}},
289 {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
290 {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
291 {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
292 {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %}
293 >(patchData,
294 [&](
295 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
296 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
297 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
298 [[maybe_unused]] double t,
299 [[maybe_unused]] double dt,
300 [[maybe_unused]] int normal,
301 [[maybe_unused]] double* __restrict__ F // F[{{NUMBER_OF_UNKNOWNS}}]
302 )->void {
303 {% if FLUX_IMPLEMENTATION!="<none>" %}
304 repositories::{{SOLVER_INSTANCE}}.flux(Q, faceCentre, volumeH, t, dt, normal, F);
305 {% endif %}
306 },
307 [&](
308 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
309 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
310 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
311 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
312 [[maybe_unused]] double t,
313 [[maybe_unused]] double dt,
314 [[maybe_unused]] int normal,
315 [[maybe_unused]] double* __restrict__ BTimesDeltaQ // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
316 )->void {
317 {% if NCP_IMPLEMENTATION!="<none>" %}
318 repositories::{{SOLVER_INSTANCE}}.nonconservativeProduct(Q, deltaQ, faceCentre, volumeH, t, dt, normal, BTimesDeltaQ);
319 {% endif %}
320 },
321 [&](
322 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
323 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeX,
324 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
325 [[maybe_unused]] double t,
326 [[maybe_unused]] double dt,
327 [[maybe_unused]] double* __restrict__ S // S[{{NUMBER_OF_UNKNOWNS}}]
328 )->void {
329 {% if SOURCE_IMPLEMENTATION!="<none>" %}
330 repositories::{{SOLVER_INSTANCE}}.sourceTerm(Q, volumeX, volumeH, t, dt, S);
331 {% endif %}
332 },
333 [&](
334 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
335 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
336 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
337 [[maybe_unused]] double t,
338 [[maybe_unused]] double dt,
339 [[maybe_unused]] int normal,
340 [[maybe_unused]] double* __restrict__ maxEigenvalue
341 )->void {
342 repositories::{{SOLVER_INSTANCE}}.maxEigenvalue(Q, faceCentre, volumeH, t, dt, normal, maxEigenvalue);
343 }
344);
345 """
346 elif solver_variant == SolverVariant.Stateless:
347 template += """Stateless<
348 {{SOLVER_NAME}},
349 {{NUMBER_OF_VOLUMES_PER_AXIS}},
350 {{HALO_SIZE}},
351 {{NUMBER_OF_UNKNOWNS}},
352 {{NUMBER_OF_AUXILIARY_VARIABLES}},
353 {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
354 {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
355 {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
356 {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %}
357 >(patchData);
358 """
359 elif solver_variant == SolverVariant.Accelerator:
360 template += """Stateless<
361 {{SOLVER_NAME}},
362 {{NUMBER_OF_VOLUMES_PER_AXIS}},
363 {{HALO_SIZE}},
364 {{NUMBER_OF_UNKNOWNS}},
365 {{NUMBER_OF_AUXILIARY_VARIABLES}},
366 {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
367 {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
368 {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
369 {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %}
370 >(targetDevice, patchData);
371"""
372 else:
373 assert False, "Not supported combination: {} x {}".format(solver_variant, kernel_variant)
374
375 result = jinja2.Template( template, undefined=jinja2.DebugUndefined)
376 d= {}
377 d["FLUX_IMPLEMENTATION"] = flux_implementation
378 d["NCP_IMPLEMENTATION"] = ncp_implementation
379 d["SOURCE_IMPLEMENTATION"] = source_implementation
380 d["COMPUTE_MAX_EIGENVALUE"] = compute_max_eigenvalue_of_next_time_step
381 return result.render(**d)
382
383def create_compute_Riemann_kernel_for_MusclHancock(flux_implementation,
384 ncp_implementation,
385 source_implementation,
386 compute_max_eigenvalue_of_next_time_step,
387 solver_variant,
388 riemann_kernel_variant):
389 """
390
391 I return only the unqualified function call, i.e. without any namespaces.
392 So by setting the right namespace as prefix, you can direct it to particular
393 implementations.
394
395 solver_variant: SolverVariant
396
397 riemann_kernel_variant: RiemannKernelVariant
398
399 """
400 RiemannKernelCalls = {
401 RiemannKernelVariant.PatchWiseAoSStack: "timeStepWithMUSCLHancock_patchwise_call_stack",
402 RiemannKernelVariant.PatchWiseAoSoAStack: "timeStepWithMUSCLHancock_patchwise_call_stack",
403 RiemannKernelVariant.PatchWiseSoAStack: "timeStepWithMUSCLHancock_patchwise_call_stack",
404 RiemannKernelVariant.BatchedAoSStack: "timeStepWithMUSCLHancock_batched_call_stack",
405 RiemannKernelVariant.BatchedAoSoAStack: "timeStepWithMUSCLHancock_batched_call_stack",
406 RiemannKernelVariant.BatchedSoAStack: "timeStepWithMUSCLHancock_batched_call_stack",
407 RiemannKernelVariant.PatchWiseSplitTermsAoSStack: "timeStepWithMUSCLHancock_patchwise_split_terms_call_stack",
408 RiemannKernelVariant.PatchWiseSplitTermsAoSoAStack: "timeStepWithMUSCLHancock_patchwise_split_terms_call_stack",
409 RiemannKernelVariant.PatchWiseAoSHeap: "timeStepWithMUSCLHancock_patchwise_heap",
410 RiemannKernelVariant.PatchWiseAoSoAHeap: "timeStepWithMUSCLHancock_patchwise_heap",
411 RiemannKernelVariant.PatchWiseSoAHeap: "timeStepWithMUSCLHancock_patchwise_heap",
412 RiemannKernelVariant.BatchedAoSHeap: "timeStepWithMUSCLHancock_batched_heap",
413 RiemannKernelVariant.BatchedAoSoAHeap: "timeStepWithMUSCLHancock_batched_heap",
414 RiemannKernelVariant.BatchedSoAHeap: "timeStepWithMUSCLHancock_batched_heap",
415 RiemannKernelVariant.TaskGraphAoSHeap: "timeStepWithMUSCLHancock_batched_heap",
416 RiemannKernelVariant.TaskGraphAoSoAHeap: "timeStepWithMUSCLHancock_batched_heap",
417 RiemannKernelVariant.TaskGraphSoAHeap: "timeStepWithMUSCLHancock_batched_heap",
418 RiemannKernelVariant.PatchWiseSplitTermsAoSHeap: "timeStepWithMUSCLHancock_patchwise_split_terms_heap",
419 RiemannKernelVariant.PatchWiseSplitTermsAoSoAHeap: "timeStepWithMUSCLHancock_patchwise_split_terms_heap",
420 RiemannKernelVariant.PatchWiseInSitu: "timeStepWithMUSCLHancock_patchwise_in_situ",
421 RiemannKernelVariant.BatchedInSitu: "timeStepWithMUSCLHancock_patchwise_in_situ"
422 }
423
424 EnumeratorTemplateTypes = {
425 RiemannKernelVariant.PatchWiseAoSStack: "::exahype2::enumerator::AoSLexicographicEnumerator",
426 RiemannKernelVariant.PatchWiseAoSoAStack: "::exahype2::enumerator::AoSoALexicographicEnumerator",
427 RiemannKernelVariant.PatchWiseSoAStack: "::exahype2::enumerator::SoALexicographicEnumerator",
428 RiemannKernelVariant.BatchedAoSStack: "::exahype2::enumerator::AoSLexicographicEnumerator",
429 RiemannKernelVariant.BatchedAoSoAStack: "::exahype2::enumerator::AoSoALexicographicEnumerator",
430 RiemannKernelVariant.BatchedSoAStack: "::exahype2::enumerator::SoALexicographicEnumerator",
431 RiemannKernelVariant.PatchWiseSplitTermsAoSStack: "::exahype2::enumerator::AoSLexicographicEnumerator",
432 RiemannKernelVariant.PatchWiseSplitTermsAoSoAStack: "::exahype2::enumerator::AoSoALexicographicEnumerator",
433 RiemannKernelVariant.PatchWiseAoSHeap: "::exahype2::enumerator::AoSLexicographicEnumerator",
434 RiemannKernelVariant.PatchWiseAoSoAHeap: "::exahype2::enumerator::AoSoALexicographicEnumerator",
435 RiemannKernelVariant.PatchWiseSoAHeap: "::exahype2::enumerator::SoALexicographicEnumerator",
436 RiemannKernelVariant.BatchedAoSHeap: "::exahype2::enumerator::AoSLexicographicEnumerator",
437 RiemannKernelVariant.BatchedAoSoAHeap: "::exahype2::enumerator::AoSoALexicographicEnumerator",
438 RiemannKernelVariant.BatchedSoAHeap: "::exahype2::enumerator::SoALexicographicEnumerator",
439 RiemannKernelVariant.TaskGraphAoSHeap: "::exahype2::enumerator::AoSLexicographicEnumerator",
440 RiemannKernelVariant.TaskGraphAoSoAHeap: "::exahype2::enumerator::AoSoALexicographicEnumerator",
441 RiemannKernelVariant.TaskGraphSoAHeap: "::exahype2::enumerator::SoALexicographicEnumerator",
442 RiemannKernelVariant.PatchWiseSplitTermsAoSHeap: "::exahype2::enumerator::AoSLexicographicEnumerator",
443 RiemannKernelVariant.PatchWiseSplitTermsAoSoAHeap: "::exahype2::enumerator::AoSoALexicographicEnumerator",
444 RiemannKernelVariant.PatchWiseInSitu: None,
445 RiemannKernelVariant.BatchedInSitu: None
446 }
447
448 template = RiemannKernelCalls[riemann_kernel_variant]
449
450 if solver_variant == SolverVariant.WithVirtualFunctions:
451 template += """_functors(
452 patchData,
453 {{NUMBER_OF_VOLUMES_PER_AXIS}},
454 {{HALO_SIZE}},
455 {{NUMBER_OF_UNKNOWNS}},
456 {{NUMBER_OF_AUXILIARY_VARIABLES}},
457 {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
458 {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
459 {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
460 {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %},
461 [&](
462 const double * __restrict__ Q,
463 const tarch::la::Vector<Dimensions,double>& faceCentre,
464 const tarch::la::Vector<Dimensions,double>& volumeH,
465 double t,
466 double dt,
467 int normal,
468 double * __restrict__ F
469 )->void {
470 {% if FLUX_IMPLEMENTATION!="<none>" %}
471 repositories::{{SOLVER_INSTANCE}}.flux( Q, faceCentre, volumeH, t, dt, normal, F );
472 {% endif %}
473 },
474 [&](
475 const double * __restrict__ Q,
476 const double * __restrict__ deltaQ,
477 const tarch::la::Vector<Dimensions,double>& faceCentre,
478 const tarch::la::Vector<Dimensions,double>& volumeH,
479 double t,
480 double dt,
481 int normal,
482 double * __restrict__ BTimesDeltaQ
483 )->void {
484 {% if NCP_IMPLEMENTATION!="<none>" %}
485 repositories::{{SOLVER_INSTANCE}}.nonconservativeProduct( Q, deltaQ, faceCentre, volumeH, t, dt, normal, BTimesDeltaQ );
486 {% endif %}
487 },
488 [&](
489 const double * __restrict__ Q,
490 const tarch::la::Vector<Dimensions,double>& volumeX,
491 const tarch::la::Vector<Dimensions,double>& volumeH,
492 double t,
493 double dt,
494 double * __restrict__ S
495 )->void {
496 {% if SOURCE_IMPLEMENTATION!="<none>" %}
497 repositories::{{SOLVER_INSTANCE}}.sourceTerm( Q, volumeX, volumeH, t, dt, S );
498 {% endif %}
499 },
500 [&](
501 const double * __restrict__ Q,
502 const tarch::la::Vector<Dimensions,double>& faceCentre,
503 const tarch::la::Vector<Dimensions,double>& volumeH,
504 double t,
505 double dt,
506 int normal
507 )->double {
508 return repositories::{{SOLVER_INSTANCE}}.maxEigenvalue( Q, faceCentre, volumeH, t, dt, normal);
509 }
510);
511 """
512 if solver_variant == SolverVariant.Stateless and EnumeratorTemplateTypes[riemann_kernel_variant]==None:
513 template += """_static_calls<{{SOLVER_NAME}},{{NUMBER_OF_VOLUMES_PER_AXIS}},{{HALO_SIZE}}, {{NUMBER_OF_UNKNOWNS}}, {{NUMBER_OF_AUXILIARY_VARIABLES}}>(
514 patchData,
515 {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
516 {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
517 {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
518 {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %}
519 );
520 """
521 if solver_variant == SolverVariant.Accelerator and EnumeratorTemplateTypes[riemann_kernel_variant]==None:
522 template += """_static_calls<{{SOLVER_NAME}},{{NUMBER_OF_VOLUMES_PER_AXIS}},{{HALO_SIZE}}, {{NUMBER_OF_UNKNOWNS}}, {{NUMBER_OF_AUXILIARY_VARIABLES}}>(
523 targetDevice,
524 patchData,
525 {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
526 {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
527 {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
528 {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %}
529 );
530 """
531 if solver_variant == SolverVariant.Stateless and EnumeratorTemplateTypes[riemann_kernel_variant]!=None:
532 template += """_static_calls<{{SOLVER_NAME}},{{NUMBER_OF_VOLUMES_PER_AXIS}},{{HALO_SIZE}}, {{NUMBER_OF_UNKNOWNS}}, {{NUMBER_OF_AUXILIARY_VARIABLES}}, {{TEMP_DATA_ENUMERATOR}}>(
533 patchData,
534 {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
535 {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
536 {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
537 {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %}
538 );
539 """
540 if solver_variant == SolverVariant.Accelerator and EnumeratorTemplateTypes[riemann_kernel_variant]!=None:
541 template += """_static_calls<{{SOLVER_NAME}},{{NUMBER_OF_VOLUMES_PER_AXIS}},{{HALO_SIZE}}, {{NUMBER_OF_UNKNOWNS}}, {{NUMBER_OF_AUXILIARY_VARIABLES}}, {{TEMP_DATA_ENUMERATOR}}>(
542 targetDevice,
543 patchData,
544 {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
545 {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
546 {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
547 {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %}
548 );
549 """
550
551
552 result = jinja2.Template( template, undefined=jinja2.DebugUndefined)
553 d= {}
554 d[ "FLUX_IMPLEMENTATION" ] = flux_implementation
555 d[ "NCP_IMPLEMENTATION" ] = ncp_implementation
556 d[ "SOURCE_IMPLEMENTATION" ] = source_implementation
557 d[ "COMPUTE_MAX_EIGENVALUE" ] = compute_max_eigenvalue_of_next_time_step
558 #if EnumeratorTemplateTypes[riemann_kernel_variant]==None:
559 # d[ "TEMP_DATA_ENUMERATOR" ] = "::exahype2::fv::enumerator::AoSoALexicographicEnumerator"
560 #else:
561 d[ "TEMP_DATA_ENUMERATOR" ] = EnumeratorTemplateTypes[riemann_kernel_variant]
562 return result.render(**d)
563
564
565def create_abstract_solver_declarations(flux_implementation,
566 ncp_implementation,
567 eigenvalues_implementation,
568 source_term_implementation,
569 pde_terms_without_state):
570 Template = jinja2.Template( """
571 public:
572 {% if EIGENVALUES_IMPLEMENTATION=="<none>" %}
573 #error eigenvalue implementation cannot be none
574 {% endif %}
575
576 {% if EIGENVALUES_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
577 /**
578 * Depending on the implementation, this variant might be slow as it
579 * lacks an inline define. Also, if you don't want to use ipo aggressively,
580 * it might be clever to put the implementation into the header.
581 *
582 * ## SYCL
583 *
584 * At the moment, SYCL seems to struggle with ipo, even if a function is
585 * never called. So I embed the (empty) implementation directly into the
586 * header.
587 */
588 #if defined(GPUOffloadingOMP)
589 #pragma omp declare target
590 #endif
591 static GPUCallableMethod void maxEigenvalue(
592 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
593 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
594 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
595 [[maybe_unused]] double t,
596 [[maybe_unused]] double dt,
597 [[maybe_unused]] int normal,
598 [[maybe_unused]] double* __restrict__ maxEigenvalue,
599 Offloadable
600 )
601 //#if defined(GPUOffloadingSYCL)
602 //{}
603 //#else
604 ;
605 //#endif
606 #if defined(GPUOffloadingOMP)
607 #pragma omp end declare target
608 #endif
609 {% endif %}
610
611 /**
612 * Determine max eigenvalue over Jacobian in a given point with solution values
613 * (states) Q. All parameters are in.
614 *
615 * @return Max eigenvalue. Result has to be positive, so we are actually speaking
616 * about the maximum absolute eigenvalue.
617 */
618 virtual void maxEigenvalue(
619 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
620 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
621 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
622 [[maybe_unused]] double t,
623 [[maybe_unused]] double dt,
624 [[maybe_unused]] int normal,
625 [[maybe_unused]] double* __restrict__ maxEigenvalue
626 ) {% if EIGENVALUES_IMPLEMENTATION=="<user-defined>" %}= 0{% else %} final{% endif %};
627
628 {% if FLUX_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
629 /**
630 * Depending on the implementation, this variant might be slow as it
631 * lacks an inline define. Also, if you don't want to use ipo aggressively,
632 * it might be clever to put the implementation into the header.
633 *
634 * ## SYCL
635 *
636 * At the moment, SYCL seems to struggle with ipo, even if a function is
637 * never called. So I embed the (empty) implementation directly into the
638 * header.
639 */
640 #if defined(GPUOffloadingOMP)
641 #pragma omp declare target
642 #endif
643 static GPUCallableMethod void flux(
644 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
645 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
646 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
647 [[maybe_unused]] double t,
648 [[maybe_unused]] double dt,
649 [[maybe_unused]] int normal,
650 [[maybe_unused]] double* __restrict__ F, // F[{{NUMBER_OF_UNKNOWNS}}]
651 Offloadable
652 );
653 #if defined(GPUOffloadingOMP)
654 #pragma omp end declare target
655 #endif
656 {% endif %}
657
658 {% if FLUX_IMPLEMENTATION!="<none>" %}
659 virtual void flux(
660 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
661 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
662 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
663 [[maybe_unused]] double t,
664 [[maybe_unused]] double dt,
665 [[maybe_unused]] int normal,
666 [[maybe_unused]] double* __restrict__ F // F[{{NUMBER_OF_UNKNOWNS}}]
667 ) {% if FLUX_IMPLEMENTATION=="<user-defined>" %}=0{% else %} final {% endif %};
668 {% endif %}
669
670 {% if NCP_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
671 /**
672 * Depending on the implementation, this variant might be slow as it
673 * lacks an inline define. Also, if you don't want to use ipo aggressively,
674 * it might be clever to put the implementation into the header.
675 *
676 * ## SYCL
677 *
678 * At the moment, SYCL seems to struggle with ipo, even if a function is
679 * never called. So I embed the (empty) implementation directly into the
680 * header.
681 */
682 #if defined(GPUOffloadingOMP)
683 #pragma omp declare target
684 #endif
685 static GPUCallableMethod void nonconservativeProduct(
686 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
687 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
688 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
689 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
690 [[maybe_unused]] double t,
691 [[maybe_unused]] double dt,
692 [[maybe_unused]] int normal,
693 [[maybe_unused]] double* __restrict__ BTimesDeltaQ, // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
694 Offloadable
695 );
696 #if defined(GPUOffloadingOMP)
697 #pragma omp end declare target
698 #endif
699 {% endif %}
700
701 {% if NCP_IMPLEMENTATION!="<none>" %}
702 virtual void nonconservativeProduct(
703 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
704 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
705 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
706 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
707 [[maybe_unused]] double t,
708 [[maybe_unused]] double dt,
709 [[maybe_unused]] int normal,
710 [[maybe_unused]] double* __restrict__ BTimesDeltaQ // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
711 ) {% if NCP_IMPLEMENTATION=="<user-defined>" %}=0{% endif %};
712 {% endif %}
713
714 {% if SOURCE_TERM_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
715 /**
716 * Depending on the implementation, this variant might be slow as it
717 * lacks an inline define. Also, if you don't want to use ipo aggressively,
718 * it might be clever to put the implementation into the header.
719 *
720 * ## SYCL
721 *
722 * At the moment, SYCL seems to struggle with ipo, even if a function is
723 * never called. So I embed the (empty) implementation directly into the
724 * header.
725 */
726 #if defined(GPUOffloadingOMP)
727 #pragma omp declare target
728 #endif
729 static GPUCallableMethod void sourceTerm(
730 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
731 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
732 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
733 [[maybe_unused]] double t,
734 [[maybe_unused]] double dt,
735 [[maybe_unused]] double* __restrict__ S, // S[{{NUMBER_OF_UNKNOWNS}}]
736 Offloadable
737 );
738 #if defined(GPUOffloadingOMP)
739 #pragma omp end declare target
740 #endif
741 {% endif %}
742
743 {% if SOURCE_TERM_IMPLEMENTATION!="<none>" %}
744 virtual void sourceTerm(
745 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
746 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
747 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
748 [[maybe_unused]] double t,
749 [[maybe_unused]] double dt,
750 [[maybe_unused]] double* __restrict__ S // S[{{NUMBER_OF_UNKNOWNS}}]
751 ) {% if SOURCE_TERM_IMPLEMENTATION=="<user-defined>" %}= 0{% else %} final {% endif %};
752 {% endif %}
753""", undefined=jinja2.DebugUndefined)
754
755 d= {}
756 d[ "FLUX_IMPLEMENTATION"] = flux_implementation
757 d[ "NCP_IMPLEMENTATION"] = ncp_implementation
758 d[ "EIGENVALUES_IMPLEMENTATION"] = eigenvalues_implementation
759 d[ "SOURCE_TERM_IMPLEMENTATION"] = source_term_implementation
760 d[ "STATELESS_PDE_TERMS"] = pde_terms_without_state
761 return Template.render(**d)
762
763def create_abstract_solver_definitions(flux_implementation, ncp_implementation, eigenvalues_implementation, source_term_implementation, pde_terms_without_state):
764 Template = jinja2.Template( """
765{% if EIGENVALUES_IMPLEMENTATION!="<user-defined>" and EIGENVALUES_IMPLEMENTATION!="<none>" %}
766void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::maxEigenvalue(
767 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
768 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
769 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
770 [[maybe_unused]] double t,
771 [[maybe_unused]] double dt,
772 [[maybe_unused]] int normal,
773 [[maybe_unused]] double* __restrict__ maxEigenvalue
774) {
775 {{EIGENVALUES_IMPLEMENTATION}}
776}
777{% endif %}
778
779{% if FLUX_IMPLEMENTATION!="<none>" and FLUX_IMPLEMENTATION!="<user-defined>" %}
780void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::flux(
781 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
782 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
783 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
784 [[maybe_unused]] double t,
785 [[maybe_unused]] double dt,
786 [[maybe_unused]] int normal,
787 [[maybe_unused]] double* __restrict__ F // F[{{NUMBER_OF_UNKNOWNS}}]
788) {
789 {{FLUX_IMPLEMENTATION}}
790}
791{% endif %}
792
793{% if NCP_IMPLEMENTATION!="<none>" and NCP_IMPLEMENTATION!="<user-defined>" %}
794void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::nonconservativeProduct(
795 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
796 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
797 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
798 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
799 [[maybe_unused]] double t,
800 [[maybe_unused]] double dt,
801 [[maybe_unused]] int normal,
802 [[maybe_unused]] double* __restrict__ BTimesDeltaQ // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
803) {
804 {{NCP_IMPLEMENTATION}}
805}
806{% endif %}
807
808{% if SOURCE_TERM_IMPLEMENTATION!="<user-defined>" and SOURCE_TERM_IMPLEMENTATION!="<none>" %}
809//#if !defined(GPUOffloadingSYCL)
810void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::sourceTerm(
811 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
812 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
813 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
814 [[maybe_unused]] double t,
815 [[maybe_unused]] double dt,
816 [[maybe_unused]] double* __restrict__ S // S[{{NUMBER_OF_UNKNOWNS}}]
817) {
818 {% if SOURCE_TERM_IMPLEMENTATION!="<empty>" %}
819 {{SOURCE_TERM_IMPLEMENTATION}}
820 {% else %}
821 std::fill_n(S,{{NUMBER_OF_UNKNOWNS}},0.0);
822 {% endif %}
823}
824//#endif
825{% endif %}
826
827{% if EIGENVALUES_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
828#if defined(GPUOffloadingOMP)
829#pragma omp declare target
830#endif
831//#if !defined(GPUOffloadingSYCL)
832GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::maxEigenvalue(
833 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
834 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
835 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
836 [[maybe_unused]] double t,
837 [[maybe_unused]] double dt,
838 [[maybe_unused]] int normal,
839 [[maybe_unused]] double* __restrict__ maxEigenvalue,
840 Offloadable
841) {
842 {{EIGENVALUES_IMPLEMENTATION}};
843}
844//#endif
845#if defined(GPUOffloadingOMP)
846#pragma omp end declare target
847#endif
848{% endif %}
849
850
851{% if FLUX_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
852#if defined(GPUOffloadingOMP)
853#pragma omp declare target
854#endif
855//#if !defined(GPUOffloadingSYCL)
856GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::flux(
857 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
858 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
859 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
860 [[maybe_unused]] double t,
861 [[maybe_unused]] double dt,
862 [[maybe_unused]] int normal,
863 [[maybe_unused]] double* __restrict__ F, // F[{{NUMBER_OF_UNKNOWNS}}]
864 Offloadable
865) {
866 {% if FLUX_IMPLEMENTATION=="<none>" %}
867 tarch::gpuAbort();
868 {% else %}
869 {{FLUX_IMPLEMENTATION}}
870 {% endif %}
871}
872//#endif
873#if defined(GPUOffloadingOMP)
874#pragma omp end declare target
875#endif
876{% endif %}
877
878{% if NCP_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
879#if defined(GPUOffloadingOMP)
880#pragma omp declare target
881#endif
882GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::nonconservativeProduct(
883 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
884 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
885 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
886 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
887 [[maybe_unused]] double t,
888 [[maybe_unused]] double dt,
889 [[maybe_unused]] int normal,
890 [[maybe_unused]] double* __restrict__ BTimesDeltaQ, // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
891 [[maybe_unused]] Offloadable
892) {
893 {% if NCP_IMPLEMENTATION=="<none>" %}
894 tarch::gpuAbort();
895 {% else %}
896 {{NCP_IMPLEMENTATION}}
897 {% endif %}
898}
899#if defined(GPUOffloadingOMP)
900#pragma omp end declare target
901#endif
902{% endif %}
903
904{% if SOURCE_TERM_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
905#if defined(GPUOffloadingOMP)
906#pragma omp declare target
907#endif
908GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::sourceTerm(
909 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
910 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
911 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
912 [[maybe_unused]] double t,
913 [[maybe_unused]] double dt,
914 [[maybe_unused]] double* __restrict__ S, // S[{{NUMBER_OF_UNKNOWNS}}]
915 [[maybe_unused]] Offloadable
916) {
917 {% if SOURCE_TERM_IMPLEMENTATION=="<none>" %}
918 tarch::gpuAbort();
919 {% else %}
920 {{SOURCE_TERM_IMPLEMENTATION}}
921 {% endif %}
922}
923#if defined(GPUOffloadingOMP)
924#pragma omp end declare target
925#endif
926{% endif %}
927""", undefined=jinja2.DebugUndefined)
928
929 d= {}
930 d[ "FLUX_IMPLEMENTATION"] = flux_implementation
931 d[ "NCP_IMPLEMENTATION"] = ncp_implementation
932 d[ "EIGENVALUES_IMPLEMENTATION"] = eigenvalues_implementation
933 d[ "SOURCE_TERM_IMPLEMENTATION"] = source_term_implementation
934 d[ "STATELESS_PDE_TERMS"] = pde_terms_without_state
935 return Template.render(**d)
936
937def create_solver_declarations(flux_implementation, ncp_implementation, eigenvalues_implementation, source_term_implementation, pde_terms_without_state):
938 Template = jinja2.Template( """
939 public:
940 {% if SOURCE_TERM_IMPLEMENTATION=="<user-defined>" %}
941 virtual void sourceTerm(
942 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
943 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
944 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
945 [[maybe_unused]] double t,
946 [[maybe_unused]] double dt,
947 [[maybe_unused]] double* __restrict__ S // S[{{NUMBER_OF_UNKNOWNS}}]
948 ) override;
949 {% endif %}
950
951 {% if EIGENVALUES_IMPLEMENTATION=="<user-defined>" %}
952 /**
953 * Determine max eigenvalue over Jacobian in a given point with solution values
954 * (states) Q. All parameters are in.
955 *
956 * @return Max eigenvalue. Result has to be positive, so we are actually speaking
957 * about the maximum absolute eigenvalue.
958 */
959 virtual void maxEigenvalue(
960 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
961 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
962 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
963 [[maybe_unused]] double t,
964 [[maybe_unused]] double dt,
965 [[maybe_unused]] int normal,
966 [[maybe_unused]] double* __restrict__ maxEigenvalue
967 ) override;
968 {% endif %}
969
970 {% if FLUX_IMPLEMENTATION=="<user-defined>" %}
971 virtual void flux(
972 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
973 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
974 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
975 [[maybe_unused]] double t,
976 [[maybe_unused]] double dt,
977 [[maybe_unused]] int normal,
978 [[maybe_unused]] double* __restrict__ F // F[{{NUMBER_OF_UNKNOWNS}}]
979 ) override;
980 {% endif %}
981
982 {% if NCP_IMPLEMENTATION=="<user-defined>" %}
983 virtual void nonconservativeProduct(
984 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
985 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
986 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
987 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
988 [[maybe_unused]] double t,
989 [[maybe_unused]] double dt,
990 [[maybe_unused]] int normal,
991 [[maybe_unused]] double* __restrict__ BTimesDeltaQ // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
992 ) override;
993 {% endif %}
994
995 {% if STATELESS_PDE_TERMS and SOURCE_TERM_IMPLEMENTATION=="<user-defined>" %}
996 /**
997 * To obtain the best performance, I recommend to man inline command to
998 * this signature and to copy the implementation into the header. So it would
999 * read
1000 *
1001 * static inline void sourceTerm( ... ) {
1002 * code here
1003 * }
1004 *
1005 * The GPU offloading requires static functions. As we cannot overload the
1006 * original (virtual) function with a static alternative, we do the
1007 * TBB trick and overload by adding an additional enum. It has no semantics
1008 * but helps the compiler to distinguish the different function variants.
1009 */
1010 #if defined(GPUOffloadingOMP)
1011 #pragma omp declare target
1012 #endif
1013 static GPUCallableMethod void sourceTerm(
1014 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1015 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
1016 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
1017 [[maybe_unused]] double t,
1018 [[maybe_unused]] double dt,
1019 [[maybe_unused]] double* __restrict__ S, // S[{{NUMBER_OF_UNKNOWNS}}]
1020 [[maybe_unused]] Offloadable
1021 );
1022 #if defined(GPUOffloadingOMP)
1023 #pragma omp end declare target
1024 #endif
1025 {% endif %}
1026
1027 {% if EIGENVALUES_IMPLEMENTATION=="<user-defined>" and STATELESS_PDE_TERMS %}
1028 #if defined(GPUOffloadingOMP)
1029 #pragma omp declare target
1030 #endif
1031 static GPUCallableMethod void maxEigenvalue(
1032 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1033 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
1034 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
1035 [[maybe_unused]] double t,
1036 [[maybe_unused]] double dt,
1037 [[maybe_unused]] int normal,
1038 [[maybe_unused]] double* __restrict__ maxEigenvalue,
1039 [[maybe_unused]] Offloadable
1040 );
1041 #if defined(GPUOffloadingOMP)
1042 #pragma omp end declare target
1043 #endif
1044 {% endif %}
1045
1046 {% if STATELESS_PDE_TERMS and FLUX_IMPLEMENTATION=="<user-defined>" %}
1047 /**
1048 * To obtain the best performance, I recommend to man inline command to
1049 * this signature and to copy the implementation into the header. So it would
1050 * read
1051 *
1052 * static inline void flux( ... ) {
1053 * code here
1054 * }
1055 *
1056 * The GPU offloading requires static functions. As we cannot overload the
1057 * original (virtual) function with a static alternative, we do the
1058 * TBB trick and overload by adding an additional enum. It has no semantics
1059 * but helps the compiler to distinguish the different function variants.
1060 */
1061 #if defined(GPUOffloadingOMP)
1062 #pragma omp declare target
1063 #endif
1064 static GPUCallableMethod void flux(
1065 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1066 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
1067 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
1068 [[maybe_unused]] double t,
1069 [[maybe_unused]] double dt,
1070 [[maybe_unused]] int normal,
1071 [[maybe_unused]] double* __restrict__ F, // F[{{NUMBER_OF_UNKNOWNS}}]
1072 [[maybe_unused]] Offloadable
1073 );
1074 #if defined(GPUOffloadingOMP)
1075 #pragma omp end declare target
1076 #endif
1077 {% endif %}
1078
1079 {% if STATELESS_PDE_TERMS and NCP_IMPLEMENTATION=="<user-defined>" %}
1080 /**
1081 * To obtain the best performance, I recommend to man inline command to
1082 * this signature and to copy the implementation into the header. So it would
1083 * read
1084 *
1085 * static inline void nonconservativeProduct( ... ) {
1086 * code here
1087 * }
1088 *
1089 * The GPU offloading requires static functions. As we cannot overload the
1090 * original (virtual) function with a static alternative, we do the
1091 * TBB trick and overload by adding an additional enum. It has no semantics
1092 * but helps the compiler to distinguish the different function variants.
1093 */
1094 #if defined(GPUOffloadingOMP)
1095 #pragma omp declare target
1096 #endif
1097 static GPUCallableMethod void nonconservativeProduct(
1098 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1099 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1100 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
1101 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
1102 [[maybe_unused]] double t,
1103 [[maybe_unused]] double dt,
1104 [[maybe_unused]] int normal,
1105 [[maybe_unused]] double* __restrict__ BTimesDeltaQ, // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
1106 [[maybe_unused]] Offloadable
1107 );
1108 #if defined(GPUOffloadingOMP)
1109 #pragma omp end declare target
1110 #endif
1111 {% endif %}
1112""", undefined=jinja2.DebugUndefined)
1113 d= {}
1114 d[ "FLUX_IMPLEMENTATION"] = flux_implementation
1115 d[ "NCP_IMPLEMENTATION"] = ncp_implementation
1116 d[ "EIGENVALUES_IMPLEMENTATION"] = eigenvalues_implementation
1117 d[ "SOURCE_TERM_IMPLEMENTATION"] = source_term_implementation
1118 d[ "STATELESS_PDE_TERMS"] = pde_terms_without_state
1119 return Template.render(**d)
1120
1121def create_solver_definitions(flux_implementation, ncp_implementation, eigenvalues_implementation, source_term_implementation, pde_terms_without_state):
1122 Template = jinja2.Template( """
1123{% if EIGENVALUES_IMPLEMENTATION=="<user-defined>" %}
1124void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::maxEigenvalue(
1125 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1126 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
1127 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
1128 [[maybe_unused]] double t,
1129 [[maybe_unused]] double dt,
1130 [[maybe_unused]] int normal,
1131 [[maybe_unused]] double* __restrict__ maxEigenvalue
1132) {
1133 logTraceInWith4Arguments( "maxEigenvalue(...)", faceCentre, volumeH, t, normal );
1134 // @todo implement
1135 logTraceOut( "maxEigenvalue(...)" );
1136}
1137{% endif %}
1138
1139{% if FLUX_IMPLEMENTATION=="<user-defined>" %}
1140void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::flux(
1141 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1142 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
1143 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
1144 [[maybe_unused]] double t,
1145 [[maybe_unused]] double dt,
1146 [[maybe_unused]] int normal,
1147 [[maybe_unused]] double* __restrict__ F // F[{{NUMBER_OF_UNKNOWNS}}]
1148) {
1149 logTraceInWith4Arguments("flux(...)", faceCentre, volumeH, t, normal);
1150 // @todo Implement
1151 logTraceOut("flux(...)");
1152}
1153{% endif %}
1154
1155{% if NCP_IMPLEMENTATION=="<user-defined>" %}
1156void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::nonconservativeProduct(
1157 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1158 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1159 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
1160 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
1161 [[maybe_unused]] double t,
1162 [[maybe_unused]] double dt,
1163 [[maybe_unused]] int normal,
1164 [[maybe_unused]] double* __restrict__ BTimesDeltaQ // BTimesDeltaQQ[{{NUMBER_OF_UNKNOWNS}}]
1165) {
1166 logTraceInWith4Arguments("nonconservativeProduct(...)", faceCentre, volumeH, t, normal);
1167 // @todo Implement
1168 logTraceOut("nonconservativeProduct(...)");
1169}
1170{% endif %}
1171
1172{% if SOURCE_TERM_IMPLEMENTATION=="<user-defined>" %}
1173void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::sourceTerm(
1174 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1175 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeX,
1176 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
1177 [[maybe_unused]] double t,
1178 [[maybe_unused]] double dt,
1179 [[maybe_unused]] double* __restrict__ S // S[{{NUMBER_OF_UNKNOWNS}}]
1180) {
1181 logTraceInWith4Arguments("sourceTerm(...)", volumeX, volumeH, t, dt);
1182
1183 // @todo Implement and ensure that all entries of S are properly set
1184 for (int i = 0; i < NumberOfUnknowns; i++) {
1185 S[i] = 0.0;
1186 }
1187
1188 logTraceOut("sourceTerm(...)");
1189}
1190{% endif %}
1191
1192
1193{% if EIGENVALUES_IMPLEMENTATION=="<user-defined>" and STATELESS_PDE_TERMS %}
1194#if defined(GPUOffloadingOMP)
1195#pragma omp declare target
1196#endif
1197GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::maxEigenvalue(
1198 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1199 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
1200 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
1201 [[maybe_unused]] double t,
1202 [[maybe_unused]] double dt,
1203 [[maybe_unused]] int normal,
1204 [[maybe_unused]] double* __restrict__ maxEigenvalue,
1205 Offloadable
1206) {
1207 // @todo implement
1208}
1209#if defined(GPUOffloadingOMP)
1210#pragma omp end declare target
1211#endif
1212{% endif %}
1213
1214{% if FLUX_IMPLEMENTATION=="<user-defined>" and STATELESS_PDE_TERMS %}
1215#if defined(GPUOffloadingOMP)
1216#pragma omp declare target
1217#endif
1218GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::flux(
1219 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1220 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
1221 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
1222 [[maybe_unused]] double t,
1223 [[maybe_unused]] double dt,
1224 [[maybe_unused]] int normal,
1225 [[maybe_unused]] double* __restrict__ F, // F[{{NUMBER_OF_UNKNOWNS}}]
1226 Offloadable
1227) {
1228 // @todo Implement
1229}
1230#if defined(GPUOffloadingOMP)
1231#pragma omp end declare target
1232#endif
1233{% endif %}
1234
1235{% if NCP_IMPLEMENTATION=="<user-defined>" and STATELESS_PDE_TERMS %}
1236#if defined(GPUOffloadingOMP)
1237#pragma omp declare target
1238#endif
1239GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::nonconservativeProduct(
1240 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1241 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1242 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
1243 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
1244 [[maybe_unused]] double t,
1245 [[maybe_unused]] double dt,
1246 [[maybe_unused]] int normal,
1247 [[maybe_unused]] double* __restrict__ BTimesDeltaQ, // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
1248 [[maybe_unused]] Offloadable
1249) {
1250 // @todo Implement
1251}
1252#if defined(GPUOffloadingOMP)
1253#pragma omp end declare target
1254#endif
1255{% endif %}
1256
1257{% if SOURCE_TERM_IMPLEMENTATION=="<user-defined>" and STATELESS_PDE_TERMS %}
1258#if defined(GPUOffloadingOMP)
1259#pragma omp declare target
1260#endif
1261GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::sourceTerm(
1262 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
1263 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
1264 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
1265 [[maybe_unused]] double t,
1266 [[maybe_unused]] double dt,
1267 [[maybe_unused]] double* __restrict__ S, // S[{{NUMBER_OF_UNKNOWNS}}]
1268 [[maybe_unused]] Offloadable
1269) {
1270 // @todo Implement but ensure that all entries of S are properly set
1271 for (int i = 0; i < NumberOfUnknowns; i++) {
1272 S[i] = 0.0;
1273 }
1274}
1275#if defined(GPUOffloadingOMP)
1276#pragma omp end declare target
1277#endif
1278{% endif %}
1279
1280""", undefined=jinja2.DebugUndefined)
1281 d= {}
1282 d[ "FLUX_IMPLEMENTATION"] = flux_implementation
1283 d[ "NCP_IMPLEMENTATION"] = ncp_implementation
1284 d[ "EIGENVALUES_IMPLEMENTATION"] = eigenvalues_implementation
1285 d[ "SOURCE_TERM_IMPLEMENTATION"] = source_term_implementation
1286 d[ "STATELESS_PDE_TERMS"] = pde_terms_without_state
1287 return Template.render(**d)