30def create_rusanov_kernel_definitions(patch_size, unknowns, auxiliary_variables, flux_implementation, ncp_implementation, source_term_implementation, compute_max_eigenvalue_of_next_time_step):
31 if not os.path.exists(
"kernels"):
32 os.makedirs(
"kernels")
34 file = open(
"kernels/rusanov.h",
"w")
35 file.write(
"""#if Dimensions == 2
42 create_rusanov_kernel_definitions_for_function(exahype2.solvers.fv.rusanov.timeStepWithRusanov2d,
"rusanov2d", patch_size, unknowns, auxiliary_variables, flux_implementation, ncp_implementation, source_term_implementation, compute_max_eigenvalue_of_next_time_step)
43 create_rusanov_kernel_definitions_for_function(exahype2.solvers.fv.rusanov.timeStepWithRusanov3d,
"rusanov3d", patch_size, unknowns, auxiliary_variables, flux_implementation, ncp_implementation, source_term_implementation, compute_max_eigenvalue_of_next_time_step)
46 template_parameters = [DSL.SyntaxTree.Argument(
"NumberOfVolumesPerAxisInPatch", DSL.SyntaxTree.TInteger(),
"applications::exahype2::ccz4::AbstractCCZ4"),
47 DSL.SyntaxTree.Argument(
"HaloSize", DSL.SyntaxTree.TInteger(),
"applications::exahype2"),
48 DSL.SyntaxTree.Argument(
"NumberOfUnknowns", DSL.SyntaxTree.TInteger(),
"applications::exahype2::ccz4::AbstractCCZ4"),
49 DSL.SyntaxTree.Argument(
"NumberOfAuxiliaryVariables", DSL.SyntaxTree.TInteger(),
"applications::exahype2::ccz4::AbstractCCZ4"),
50 DSL.SyntaxTree.Argument(
"EvaluateFlux", DSL.SyntaxTree.TBoolean(),
"applications::exahype2::ccz4"),
51 DSL.SyntaxTree.Argument(
"EvaluateNonconservativeProduct", DSL.SyntaxTree.TBoolean(),
"applications::exahype2::ccz4"),
52 DSL.SyntaxTree.Argument(
"EvaluateSource", DSL.SyntaxTree.TBoolean(),
"applications::exahype2::ccz4"),
53 DSL.SyntaxTree.Argument(
"EvaluateMaximumEigenvalueAfterTimeStep", DSL.SyntaxTree.TBoolean(),
"applications::exahype2::ccz4")]
56 functor_arguments = [DSL.SyntaxTree.Argument(
"flux", DSL.SyntaxTree.TCustom(
"const FluxFunctor&"),
"(!llvm.ptr, !llvm.ptr, !llvm.ptr, f64, f64, i32, !llvm.ptr) -> ()", is_function=
True),
57 DSL.SyntaxTree.Argument(
"nonconservativeProduct", DSL.SyntaxTree.TCustom(
"const NonconservativeProductFunctor&"),
"(!llvm.ptr, !llvm.ptr, !llvm.ptr, !llvm.ptr, f64, f64, i32, !llvm.ptr) -> ()", is_function=
True),
58 DSL.SyntaxTree.Argument(
"sourceTerm", DSL.SyntaxTree.TCustom(
"const SourceFunctor&"),
"(!llvm.ptr, !llvm.ptr, !llvm.ptr, f64, f64, !llvm.ptr) -> ()", is_function=
True),
59 DSL.SyntaxTree.Argument(
"maxEigenvalue", DSL.SyntaxTree.TCustom(
"const MaxEigenvalueFunctor&"),
"(!llvm.ptr, !llvm.ptr, !llvm.ptr, f64, f64, i32, !llvm.ptr) -> ()", is_function=
True)]
61 solver_includes =
"""#include "exahype2/CellData.h"
62#include "exahype2/VolumeIndex.h"
63#include "exahype2/fv/PatchUtils.h"
64#include "exahype2/fv/rusanov/Functors.h"
65#include "peano4/utils/Loop.h"
66#include "tarch/timing/Measurement.h"
67#include "tarch/timing/Watch.h"
71 d[
"KERNEL_NAMESPACE"] =
"exahype2::fv::rusanov"
72 d[
"SOLVER"] =
"Rusanov"
73 d[
"SOLVER_CLASS"] =
"FVRusanov"
74 d[
"KERNEL_NAME"] =
"timeStepWithRusanov"
75 d[
"SOLVER_INCLUDES"] = solver_includes
76 d[
"SOLVER_CLASS_NAMESPACE"] =
"benchmarks::exahype2::kernelbenchmarks"
78 d[
"PATCH_SIZE"] = patch_size
79 d[
"NUMBER_OF_UNKNOWNS"] = unknowns
80 d[
"NUMBER_OF_AUXILIARY_VARIABLES"] = auxiliary_variables
81 d[
"FLUX_IMPLEMENTATION"] = flux_implementation
82 d[
"NCP_IMPLEMENTATION"] = ncp_implementation
83 d[
"SOURCE_IMPLEMENTATION"] = source_term_implementation
84 d[
"COMPUTE_MAX_EIGENVALUE"] = compute_max_eigenvalue_of_next_time_step
88 template_call_jinja =
"""
89 {{SOLVER_CLASS_NAMESPACE}}::{{SOLVER_CLASS}},
92 {{NUMBER_OF_UNKNOWNS}},
93 {{NUMBER_OF_AUXILIARY_VARIABLES}},
94 {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
95 {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
96 {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
97 {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %}
99 d[
"TEMPLATE_CALL"] = jinja2.Template(template_call_jinja).render(**d)
101 template_value_definitions_jinja =
"""
102 int NumberOfVolumesPerAxisInPatch = {{PATCH_SIZE}};
103 int NumberOfUnknowns = {{NUMBER_OF_UNKNOWNS}};
104 int NumberOfAuxiliaryVariables = {{NUMBER_OF_AUXILIARY_VARIABLES}};
105 int HaloSize = {{HALO_SIZE}};
106 bool EvaluateFlux = {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %};
107 bool EvaluateNonconservativeProduct = {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %};
108 bool EvaluateSource = {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %};
109 bool EvaluateMaximumEigenvalueAfterTimeStep = {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %};
111 d[
"TEMPLATE_VALUE_DEFINITIONS"] = jinja2.Template(template_value_definitions_jinja).render(**d)
113 bridge_functions_jinja =
"""
114 void flux_bridge(void* Q_ptr, void* x_ptr, void* h_ptr, double t, double dt, int normal, void* F_ptr) {
115 double* Q = static_cast<double*>(Q_ptr);
116 tarch::la::Vector<Dimensions, double>* x = static_cast<tarch::la::Vector<Dimensions, double>*>(x_ptr);
117 tarch::la::Vector<Dimensions, double>* h = static_cast<tarch::la::Vector<Dimensions, double>*>(h_ptr);
118 double* F = static_cast<double*>(F_ptr);
119 {{SOLVER_CLASS_NAMESPACE}}::Abstract{{SOLVER_CLASS}}::flux(Q, *x, *h, t, dt, normal, F, OffloadableType::Yes);
122 void nonconservativeProduct_bridge(void* Q_ptr, void* deltaQ_ptr, void* x_ptr, void* h_ptr, double t, double dt, int normal, void* result_ptr) {
123 double* Q = static_cast<double*>(Q_ptr);
124 double* deltaQ = static_cast<double*>(deltaQ_ptr);
125 tarch::la::Vector<Dimensions, double>* x = static_cast<tarch::la::Vector<Dimensions, double>*>(x_ptr);
126 tarch::la::Vector<Dimensions, double>* h = static_cast<tarch::la::Vector<Dimensions, double>*>(h_ptr);
127 double* result = static_cast<double*>(result_ptr);
128 {{SOLVER_CLASS_NAMESPACE}}::Abstract{{SOLVER_CLASS}}::nonconservativeProduct(Q, deltaQ, *x, *h, t, dt, normal, result, OffloadableType::Yes);
131 void sourceTerm_bridge(void* Q_ptr, void* x_ptr, void* h_ptr, double t, double dt, void* S_ptr) {
132 double* Q = static_cast<double*>(Q_ptr);
133 tarch::la::Vector<Dimensions, double>* x = static_cast<tarch::la::Vector<Dimensions, double>*>(x_ptr);
134 tarch::la::Vector<Dimensions, double>* h = static_cast<tarch::la::Vector<Dimensions, double>*>(h_ptr);
135 double* S = static_cast<double*>(S_ptr);
136 {{SOLVER_CLASS_NAMESPACE}}::Abstract{{SOLVER_CLASS}}::sourceTerm(Q, *x, *h, t, dt, S, OffloadableType::Yes);
139 void maxEigenvalue_bridge(void* Q_ptr, void* x_ptr, void* h_ptr, double t, double dt, int normal, void* result_ptr) {
140 double* Q = static_cast<double*>(Q_ptr);
141 tarch::la::Vector<Dimensions, double>* x = static_cast<tarch::la::Vector<Dimensions, double>*>(x_ptr);
142 tarch::la::Vector<Dimensions, double>* h = static_cast<tarch::la::Vector<Dimensions, double>*>(h_ptr);
143 double* result = static_cast<double*>(result_ptr);
144 {{SOLVER_CLASS_NAMESPACE}}::Abstract{{SOLVER_CLASS}}::maxEigenvalue(Q, *x, *h, t, dt, normal, result, OffloadableType::Yes);
147 d[
"BRIDGE_FUNCTIONS"] = jinja2.Template(bridge_functions_jinja).render(**d)
149 d[
"EXTERN_FUNCTION_ARGUMENT_DEFINITIONS"] =
"""
150 void (*flux_fn)(void*, void*, void*, double, double, int, void*),
151 void (*ncp_fn)(void*, void*, void*, void*, double, double, int, void*),
152 void (*source_fn)(void*, void*, void*, double, double, void*),
153 void (*maxeig_fn)(void*, void*, void*, double, double, int, void*)
155 enabled_pde_terms = []
156 if flux_implementation
is not None and flux_implementation != exahype2.solvers.PDETerms.None_Implementation:
157 enabled_pde_terms.append(
"EvaluateFlux")
158 if source_term_implementation
is not None and source_term_implementation != exahype2.solvers.PDETerms.None_Implementation:
159 enabled_pde_terms.append(
"EvaluateSource")
160 if ncp_implementation
is not None and ncp_implementation != exahype2.solvers.PDETerms.None_Implementation:
161 enabled_pde_terms.append(
"EvaluateNonconservativeProduct")
162 if compute_max_eigenvalue_of_next_time_step:
163 enabled_pde_terms.append(
"EvaluateMaximumEigenvalueAfterTimeStep")
165 DSL.create_kernel_definitions(
171 [
"exahype2",
"fv",
"rusanov"],
176def create_compute_Riemann_kernel_for_Rusanov_dsl(flux_implementation,
178 source_implementation,
179 compute_max_eigenvalue_of_next_time_step,
180 solver_variant: SolverVariant,
181 kernel_variant: KernelVariant):
183 Return only the unqualified function call, i.e., without any namespaces.
184 So by setting the right namespace as prefix, you can direct it to particular
188 template =
"timeStepWithRusanov"
190 if solver_variant == SolverVariant.WithVirtualFunctions:
192 {{NUMBER_OF_VOLUMES_PER_AXIS}},
194 {{NUMBER_OF_UNKNOWNS}},
195 {{NUMBER_OF_AUXILIARY_VARIABLES}},
196 {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
197 {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
198 {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
199 {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %}
202 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
203 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
204 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
205 [[maybe_unused]] double t,
206 [[maybe_unused]] double dt,
207 [[maybe_unused]] int normal,
208 [[maybe_unused]] double* __restrict__ F // F[{{NUMBER_OF_UNKNOWNS}}]
210 {% if FLUX_IMPLEMENTATION!="<none>" %}
211 repositories::{{SOLVER_INSTANCE}}.flux(Q, faceCentre, volumeH, t, dt, normal, F);
215 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
216 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
217 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
218 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
219 [[maybe_unused]] double t,
220 [[maybe_unused]] double dt,
221 [[maybe_unused]] int normal,
222 [[maybe_unused]] double* __restrict__ BTimesDeltaQ // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
224 {% if NCP_IMPLEMENTATION!="<none>" %}
225 repositories::{{SOLVER_INSTANCE}}.nonconservativeProduct(Q, deltaQ, faceCentre, volumeH, t, dt, normal, BTimesDeltaQ);
229 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
230 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeX,
231 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
232 [[maybe_unused]] double t,
233 [[maybe_unused]] double dt,
234 [[maybe_unused]] double* __restrict__ S // S[{{NUMBER_OF_UNKNOWNS}}]
236 {% if SOURCE_IMPLEMENTATION!="<none>" %}
237 repositories::{{SOLVER_INSTANCE}}.sourceTerm(Q, volumeX, volumeH, t, dt, S);
241 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
242 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
243 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
244 [[maybe_unused]] double t,
245 [[maybe_unused]] double dt,
246 [[maybe_unused]] int normal,
247 [[maybe_unused]] double* __restrict__ maxEigenvalue
249 repositories::{{SOLVER_INSTANCE}}.maxEigenvalue(Q, faceCentre, volumeH, t, dt, normal, maxEigenvalue);
253 elif solver_variant == SolverVariant.Stateless:
254 template +=
"""Stateless<
256 {{NUMBER_OF_VOLUMES_PER_AXIS}},
258 {{NUMBER_OF_UNKNOWNS}},
259 {{NUMBER_OF_AUXILIARY_VARIABLES}},
260 {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
261 {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
262 {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
263 {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %}
266 elif solver_variant == SolverVariant.Accelerator:
267 template +=
"""Stateless<
269 {{NUMBER_OF_VOLUMES_PER_AXIS}},
271 {{NUMBER_OF_UNKNOWNS}},
272 {{NUMBER_OF_AUXILIARY_VARIABLES}},
273 {% if FLUX_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
274 {% if NCP_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
275 {% if SOURCE_IMPLEMENTATION=="<none>" %} false {% else %} true {% endif %},
276 {% if COMPUTE_MAX_EIGENVALUE==False %} false {% else %} true {% endif %}
277 >(gpuPatchData.targetDevice, gpuPatchData);
280 assert False,
"Not supported combination: {} x {}".format(solver_variant, kernel_variant)
282 result = jinja2.Template( template, undefined=jinja2.DebugUndefined)
284 d[
"FLUX_IMPLEMENTATION"] = flux_implementation
285 d[
"NCP_IMPLEMENTATION"] = ncp_implementation
286 d[
"SOURCE_IMPLEMENTATION"] = source_implementation
287 d[
"COMPUTE_MAX_EIGENVALUE"] = compute_max_eigenvalue_of_next_time_step
288 return result.render(**d)
291def create_abstract_solver_declarations(flux_implementation,
293 eigenvalues_implementation,
294 source_term_implementation,
295 pde_terms_without_state):
296 Template = jinja2.Template(
"""
298 {% if EIGENVALUES_IMPLEMENTATION=="<none>" %}
299 #error eigenvalue implementation cannot be none
302 {% if EIGENVALUES_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
304 * Depending on the implementation, this variant might be slow as it
305 * lacks an inline define. Also, if you don't want to use ipo aggressively,
306 * it might be clever to put the implementation into the header.
310 * At the moment, SYCL seems to struggle with ipo, even if a function is
311 * never called. So I embed the (empty) implementation directly into the
314 #if defined(GPUOffloadingOMP)
315 #pragma omp declare target
317 static GPUCallableMethod void maxEigenvalue(
318 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
319 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
320 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
321 [[maybe_unused]] double t,
322 [[maybe_unused]] double dt,
323 [[maybe_unused]] int normal,
324 [[maybe_unused]] double* __restrict__ maxEigenvalue,
327 //#if defined(GPUOffloadingSYCL)
332 #if defined(GPUOffloadingOMP)
333 #pragma omp end declare target
338 * Determine max eigenvalue over Jacobian in a given point with solution values
339 * (states) Q. All parameters are in.
341 * @return Max eigenvalue. Result has to be positive, so we are actually speaking
342 * about the maximum absolute eigenvalue.
344 virtual void maxEigenvalue(
345 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
346 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
347 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
348 [[maybe_unused]] double t,
349 [[maybe_unused]] double dt,
350 [[maybe_unused]] int normal,
351 [[maybe_unused]] double* __restrict__ maxEigenvalue
352 ) {% if EIGENVALUES_IMPLEMENTATION=="<user-defined>" %}= 0{% else %} final{% endif %};
354 {% if FLUX_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
356 * Depending on the implementation, this variant might be slow as it
357 * lacks an inline define. Also, if you don't want to use ipo aggressively,
358 * it might be clever to put the implementation into the header.
362 * At the moment, SYCL seems to struggle with ipo, even if a function is
363 * never called. So I embed the (empty) implementation directly into the
366 #if defined(GPUOffloadingOMP)
367 #pragma omp declare target
369 static GPUCallableMethod void flux(
370 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
371 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
372 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
373 [[maybe_unused]] double t,
374 [[maybe_unused]] double dt,
375 [[maybe_unused]] int normal,
376 [[maybe_unused]] double* __restrict__ F, // F[{{NUMBER_OF_UNKNOWNS}}]
379 #if defined(GPUOffloadingOMP)
380 #pragma omp end declare target
384 {% if FLUX_IMPLEMENTATION!="<none>" %}
386 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
387 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
388 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
389 [[maybe_unused]] double t,
390 [[maybe_unused]] double dt,
391 [[maybe_unused]] int normal,
392 [[maybe_unused]] double* __restrict__ F // F[{{NUMBER_OF_UNKNOWNS}}]
393 ) {% if FLUX_IMPLEMENTATION=="<user-defined>" %}=0{% else %} final {% endif %};
396 {% if NCP_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
398 * Depending on the implementation, this variant might be slow as it
399 * lacks an inline define. Also, if you don't want to use ipo aggressively,
400 * it might be clever to put the implementation into the header.
404 * At the moment, SYCL seems to struggle with ipo, even if a function is
405 * never called. So I embed the (empty) implementation directly into the
408 #if defined(GPUOffloadingOMP)
409 #pragma omp declare target
411 static GPUCallableMethod void nonconservativeProduct(
412 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
413 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
414 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
415 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
416 [[maybe_unused]] double t,
417 [[maybe_unused]] double dt,
418 [[maybe_unused]] int normal,
419 [[maybe_unused]] double* __restrict__ BTimesDeltaQ, // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
422 #if defined(GPUOffloadingOMP)
423 #pragma omp end declare target
427 {% if NCP_IMPLEMENTATION!="<none>" %}
428 virtual void nonconservativeProduct(
429 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
430 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
431 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
432 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
433 [[maybe_unused]] double t,
434 [[maybe_unused]] double dt,
435 [[maybe_unused]] int normal,
436 [[maybe_unused]] double* __restrict__ BTimesDeltaQ // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
437 ) {% if NCP_IMPLEMENTATION=="<user-defined>" %}=0{% endif %};
440 {% if SOURCE_TERM_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
442 * Depending on the implementation, this variant might be slow as it
443 * lacks an inline define. Also, if you don't want to use ipo aggressively,
444 * it might be clever to put the implementation into the header.
448 * At the moment, SYCL seems to struggle with ipo, even if a function is
449 * never called. So I embed the (empty) implementation directly into the
452 #if defined(GPUOffloadingOMP)
453 #pragma omp declare target
455 static GPUCallableMethod void sourceTerm(
456 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
457 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
458 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
459 [[maybe_unused]] double t,
460 [[maybe_unused]] double dt,
461 [[maybe_unused]] double* __restrict__ S, // S[{{NUMBER_OF_UNKNOWNS}}]
464 #if defined(GPUOffloadingOMP)
465 #pragma omp end declare target
469 {% if SOURCE_TERM_IMPLEMENTATION!="<none>" %}
470 virtual void sourceTerm(
471 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
472 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
473 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
474 [[maybe_unused]] double t,
475 [[maybe_unused]] double dt,
476 [[maybe_unused]] double* __restrict__ S // S[{{NUMBER_OF_UNKNOWNS}}]
477 ) {% if SOURCE_TERM_IMPLEMENTATION=="<user-defined>" %}= 0{% else %} final {% endif %};
479""", undefined=jinja2.DebugUndefined)
482 d[
"FLUX_IMPLEMENTATION"] = flux_implementation
483 d[
"NCP_IMPLEMENTATION"] = ncp_implementation
484 d[
"EIGENVALUES_IMPLEMENTATION"] = eigenvalues_implementation
485 d[
"SOURCE_TERM_IMPLEMENTATION"] = source_term_implementation
486 d[
"STATELESS_PDE_TERMS"] = pde_terms_without_state
487 return Template.render(**d)
489def create_abstract_solver_definitions(flux_implementation, ncp_implementation, eigenvalues_implementation, source_term_implementation, pde_terms_without_state):
490 Template = jinja2.Template(
"""
491{% if EIGENVALUES_IMPLEMENTATION!="<user-defined>" and EIGENVALUES_IMPLEMENTATION!="<none>" %}
492void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::maxEigenvalue(
493 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
494 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
495 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
496 [[maybe_unused]] double t,
497 [[maybe_unused]] double dt,
498 [[maybe_unused]] int normal,
499 [[maybe_unused]] double* __restrict__ maxEigenvalue
501 {{EIGENVALUES_IMPLEMENTATION}}
505{% if FLUX_IMPLEMENTATION!="<none>" and FLUX_IMPLEMENTATION!="<user-defined>" %}
506void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::flux(
507 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
508 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
509 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
510 [[maybe_unused]] double t,
511 [[maybe_unused]] double dt,
512 [[maybe_unused]] int normal,
513 [[maybe_unused]] double* __restrict__ F // F[{{NUMBER_OF_UNKNOWNS}}]
515 {{FLUX_IMPLEMENTATION}}
519{% if NCP_IMPLEMENTATION!="<none>" and NCP_IMPLEMENTATION!="<user-defined>" %}
520void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::nonconservativeProduct(
521 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
522 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
523 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
524 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
525 [[maybe_unused]] double t,
526 [[maybe_unused]] double dt,
527 [[maybe_unused]] int normal,
528 [[maybe_unused]] double* __restrict__ BTimesDeltaQ // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
530 {{NCP_IMPLEMENTATION}}
534{% if SOURCE_TERM_IMPLEMENTATION!="<user-defined>" and SOURCE_TERM_IMPLEMENTATION!="<none>" %}
535//#if !defined(GPUOffloadingSYCL)
536void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::sourceTerm(
537 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
538 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
539 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
540 [[maybe_unused]] double t,
541 [[maybe_unused]] double dt,
542 [[maybe_unused]] double* __restrict__ S // S[{{NUMBER_OF_UNKNOWNS}}]
544 {% if SOURCE_TERM_IMPLEMENTATION!="<empty>" %}
545 {{SOURCE_TERM_IMPLEMENTATION}}
547 std::fill_n(S,{{NUMBER_OF_UNKNOWNS}},0.0);
553{% if EIGENVALUES_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
554#if defined(GPUOffloadingOMP)
555#pragma omp declare target
557//#if !defined(GPUOffloadingSYCL)
558GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::maxEigenvalue(
559 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
560 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
561 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
562 [[maybe_unused]] double t,
563 [[maybe_unused]] double dt,
564 [[maybe_unused]] int normal,
565 [[maybe_unused]] double* __restrict__ maxEigenvalue,
568 {{EIGENVALUES_IMPLEMENTATION}};
571#if defined(GPUOffloadingOMP)
572#pragma omp end declare target
577{% if FLUX_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
578#if defined(GPUOffloadingOMP)
579#pragma omp declare target
581//#if !defined(GPUOffloadingSYCL)
582GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::flux(
583 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
584 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
585 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
586 [[maybe_unused]] double t,
587 [[maybe_unused]] double dt,
588 [[maybe_unused]] int normal,
589 [[maybe_unused]] double* __restrict__ F, // F[{{NUMBER_OF_UNKNOWNS}}]
592 {% if FLUX_IMPLEMENTATION=="<none>" %}
595 {{FLUX_IMPLEMENTATION}}
599#if defined(GPUOffloadingOMP)
600#pragma omp end declare target
604{% if NCP_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
605#if defined(GPUOffloadingOMP)
606#pragma omp declare target
608GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::nonconservativeProduct(
609 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
610 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
611 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
612 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
613 [[maybe_unused]] double t,
614 [[maybe_unused]] double dt,
615 [[maybe_unused]] int normal,
616 [[maybe_unused]] double* __restrict__ BTimesDeltaQ, // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
617 [[maybe_unused]] Offloadable
619 {% if NCP_IMPLEMENTATION=="<none>" %}
622 {{NCP_IMPLEMENTATION}}
625#if defined(GPUOffloadingOMP)
626#pragma omp end declare target
630{% if SOURCE_TERM_IMPLEMENTATION!="<user-defined>" and STATELESS_PDE_TERMS %}
631#if defined(GPUOffloadingOMP)
632#pragma omp declare target
634GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::sourceTerm(
635 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
636 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
637 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
638 [[maybe_unused]] double t,
639 [[maybe_unused]] double dt,
640 [[maybe_unused]] double* __restrict__ S, // S[{{NUMBER_OF_UNKNOWNS}}]
641 [[maybe_unused]] Offloadable
643 {% if SOURCE_TERM_IMPLEMENTATION=="<none>" %}
646 {{SOURCE_TERM_IMPLEMENTATION}}
649#if defined(GPUOffloadingOMP)
650#pragma omp end declare target
653""", undefined=jinja2.DebugUndefined)
656 d[
"FLUX_IMPLEMENTATION"] = flux_implementation
657 d[
"NCP_IMPLEMENTATION"] = ncp_implementation
658 d[
"EIGENVALUES_IMPLEMENTATION"] = eigenvalues_implementation
659 d[
"SOURCE_TERM_IMPLEMENTATION"] = source_term_implementation
660 d[
"STATELESS_PDE_TERMS"] = pde_terms_without_state
661 return Template.render(**d)
663def create_solver_declarations(flux_implementation, ncp_implementation, eigenvalues_implementation, source_term_implementation, pde_terms_without_state):
664 Template = jinja2.Template(
"""
666 {% if SOURCE_TERM_IMPLEMENTATION=="<user-defined>" %}
667 virtual void sourceTerm(
668 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
669 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
670 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
671 [[maybe_unused]] double t,
672 [[maybe_unused]] double dt,
673 [[maybe_unused]] double* __restrict__ S // S[{{NUMBER_OF_UNKNOWNS}}]
677 {% if EIGENVALUES_IMPLEMENTATION=="<user-defined>" %}
679 * Determine max eigenvalue over Jacobian in a given point with solution values
680 * (states) Q. All parameters are in.
682 * @return Max eigenvalue. Result has to be positive, so we are actually speaking
683 * about the maximum absolute eigenvalue.
685 virtual void maxEigenvalue(
686 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
687 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
688 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
689 [[maybe_unused]] double t,
690 [[maybe_unused]] double dt,
691 [[maybe_unused]] int normal,
692 [[maybe_unused]] double* __restrict__ maxEigenvalue
696 {% if FLUX_IMPLEMENTATION=="<user-defined>" %}
698 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
699 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
700 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
701 [[maybe_unused]] double t,
702 [[maybe_unused]] double dt,
703 [[maybe_unused]] int normal,
704 [[maybe_unused]] double* __restrict__ F // F[{{NUMBER_OF_UNKNOWNS}}]
708 {% if NCP_IMPLEMENTATION=="<user-defined>" %}
709 virtual void nonconservativeProduct(
710 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
711 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
712 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
713 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
714 [[maybe_unused]] double t,
715 [[maybe_unused]] double dt,
716 [[maybe_unused]] int normal,
717 [[maybe_unused]] double* __restrict__ BTimesDeltaQ // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
721 {% if STATELESS_PDE_TERMS and SOURCE_TERM_IMPLEMENTATION=="<user-defined>" %}
723 * To obtain the best performance, I recommend to man inline command to
724 * this signature and to copy the implementation into the header. So it would
727 * static inline void sourceTerm( ... ) {
731 * The GPU offloading requires static functions. As we cannot overload the
732 * original (virtual) function with a static alternative, we do the
733 * TBB trick and overload by adding an additional enum. It has no semantics
734 * but helps the compiler to distinguish the different function variants.
736 #if defined(GPUOffloadingOMP)
737 #pragma omp declare target
739 static GPUCallableMethod void sourceTerm(
740 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
741 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
742 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
743 [[maybe_unused]] double t,
744 [[maybe_unused]] double dt,
745 [[maybe_unused]] double* __restrict__ S, // S[{{NUMBER_OF_UNKNOWNS}}]
746 [[maybe_unused]] Offloadable
748 #if defined(GPUOffloadingOMP)
749 #pragma omp end declare target
753 {% if EIGENVALUES_IMPLEMENTATION=="<user-defined>" and STATELESS_PDE_TERMS %}
754 #if defined(GPUOffloadingOMP)
755 #pragma omp declare target
757 static GPUCallableMethod void maxEigenvalue(
758 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
759 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
760 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
761 [[maybe_unused]] double t,
762 [[maybe_unused]] double dt,
763 [[maybe_unused]] int normal,
764 [[maybe_unused]] double* __restrict__ maxEigenvalue,
765 [[maybe_unused]] Offloadable
767 #if defined(GPUOffloadingOMP)
768 #pragma omp end declare target
772 {% if STATELESS_PDE_TERMS and FLUX_IMPLEMENTATION=="<user-defined>" %}
774 * To obtain the best performance, I recommend to man inline command to
775 * this signature and to copy the implementation into the header. So it would
778 * static inline void flux( ... ) {
782 * The GPU offloading requires static functions. As we cannot overload the
783 * original (virtual) function with a static alternative, we do the
784 * TBB trick and overload by adding an additional enum. It has no semantics
785 * but helps the compiler to distinguish the different function variants.
787 #if defined(GPUOffloadingOMP)
788 #pragma omp declare target
790 static GPUCallableMethod void flux(
791 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
792 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
793 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
794 [[maybe_unused]] double t,
795 [[maybe_unused]] double dt,
796 [[maybe_unused]] int normal,
797 [[maybe_unused]] double* __restrict__ F, // F[{{NUMBER_OF_UNKNOWNS}}]
798 [[maybe_unused]] Offloadable
800 #if defined(GPUOffloadingOMP)
801 #pragma omp end declare target
805 {% if STATELESS_PDE_TERMS and NCP_IMPLEMENTATION=="<user-defined>" %}
807 * To obtain the best performance, I recommend to man inline command to
808 * this signature and to copy the implementation into the header. So it would
811 * static inline void nonconservativeProduct( ... ) {
815 * The GPU offloading requires static functions. As we cannot overload the
816 * original (virtual) function with a static alternative, we do the
817 * TBB trick and overload by adding an additional enum. It has no semantics
818 * but helps the compiler to distinguish the different function variants.
820 #if defined(GPUOffloadingOMP)
821 #pragma omp declare target
823 static GPUCallableMethod void nonconservativeProduct(
824 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
825 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
826 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
827 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
828 [[maybe_unused]] double t,
829 [[maybe_unused]] double dt,
830 [[maybe_unused]] int normal,
831 [[maybe_unused]] double* __restrict__ BTimesDeltaQ, // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
832 [[maybe_unused]] Offloadable
834 #if defined(GPUOffloadingOMP)
835 #pragma omp end declare target
838""", undefined=jinja2.DebugUndefined)
840 d[
"FLUX_IMPLEMENTATION"] = flux_implementation
841 d[
"NCP_IMPLEMENTATION"] = ncp_implementation
842 d[
"EIGENVALUES_IMPLEMENTATION"] = eigenvalues_implementation
843 d[
"SOURCE_TERM_IMPLEMENTATION"] = source_term_implementation
844 d[
"STATELESS_PDE_TERMS"] = pde_terms_without_state
845 return Template.render(**d)
847def create_solver_definitions(flux_implementation, ncp_implementation, eigenvalues_implementation, source_term_implementation, pde_terms_without_state):
848 Template = jinja2.Template(
"""
849{% if EIGENVALUES_IMPLEMENTATION=="<user-defined>" %}
850void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::maxEigenvalue(
851 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
852 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
853 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
854 [[maybe_unused]] double t,
855 [[maybe_unused]] double dt,
856 [[maybe_unused]] int normal,
857 [[maybe_unused]] double* __restrict__ maxEigenvalue
859 logTraceInWith4Arguments( "maxEigenvalue(...)", faceCentre, volumeH, t, normal );
861 logTraceOut( "maxEigenvalue(...)" );
865{% if FLUX_IMPLEMENTATION=="<user-defined>" %}
866void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::flux(
867 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
868 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
869 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
870 [[maybe_unused]] double t,
871 [[maybe_unused]] double dt,
872 [[maybe_unused]] int normal,
873 [[maybe_unused]] double* __restrict__ F // F[{{NUMBER_OF_UNKNOWNS}}]
875 logTraceInWith4Arguments("flux(...)", faceCentre, volumeH, t, normal);
877 logTraceOut("flux(...)");
881{% if NCP_IMPLEMENTATION=="<user-defined>" %}
882void {{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 // BTimesDeltaQQ[{{NUMBER_OF_UNKNOWNS}}]
892 logTraceInWith4Arguments("nonconservativeProduct(...)", faceCentre, volumeH, t, normal);
894 logTraceOut("nonconservativeProduct(...)");
898{% if SOURCE_TERM_IMPLEMENTATION=="<user-defined>" %}
899void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::sourceTerm(
900 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
901 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeX,
902 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
903 [[maybe_unused]] double t,
904 [[maybe_unused]] double dt,
905 [[maybe_unused]] double* __restrict__ S // S[{{NUMBER_OF_UNKNOWNS}}]
907 logTraceInWith4Arguments("sourceTerm(...)", volumeX, volumeH, t, dt);
909 // @todo Implement and ensure that all entries of S are properly set
910 for (int i = 0; i < NumberOfUnknowns; i++) {
914 logTraceOut("sourceTerm(...)");
919{% if EIGENVALUES_IMPLEMENTATION=="<user-defined>" and STATELESS_PDE_TERMS %}
920#if defined(GPUOffloadingOMP)
921#pragma omp declare target
923GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::maxEigenvalue(
924 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
925 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
926 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
927 [[maybe_unused]] double t,
928 [[maybe_unused]] double dt,
929 [[maybe_unused]] int normal,
930 [[maybe_unused]] double* __restrict__ maxEigenvalue,
935#if defined(GPUOffloadingOMP)
936#pragma omp end declare target
940{% if FLUX_IMPLEMENTATION=="<user-defined>" and STATELESS_PDE_TERMS %}
941#if defined(GPUOffloadingOMP)
942#pragma omp declare target
944GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::flux(
945 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
946 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
947 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
948 [[maybe_unused]] double t,
949 [[maybe_unused]] double dt,
950 [[maybe_unused]] int normal,
951 [[maybe_unused]] double* __restrict__ F, // F[{{NUMBER_OF_UNKNOWNS}}]
956#if defined(GPUOffloadingOMP)
957#pragma omp end declare target
961{% if NCP_IMPLEMENTATION=="<user-defined>" and STATELESS_PDE_TERMS %}
962#if defined(GPUOffloadingOMP)
963#pragma omp declare target
965GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::nonconservativeProduct(
966 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
967 [[maybe_unused]] const double* __restrict__ deltaQ, // deltaQ[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
968 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& faceCentre,
969 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
970 [[maybe_unused]] double t,
971 [[maybe_unused]] double dt,
972 [[maybe_unused]] int normal,
973 [[maybe_unused]] double* __restrict__ BTimesDeltaQ, // BTimesDeltaQ[{{NUMBER_OF_UNKNOWNS}}]
974 [[maybe_unused]] Offloadable
978#if defined(GPUOffloadingOMP)
979#pragma omp end declare target
983{% if SOURCE_TERM_IMPLEMENTATION=="<user-defined>" and STATELESS_PDE_TERMS %}
984#if defined(GPUOffloadingOMP)
985#pragma omp declare target
987GPUCallableMethod void {{FULL_QUALIFIED_NAMESPACE}}::{{CLASSNAME}}::sourceTerm(
988 [[maybe_unused]] const double* __restrict__ Q, // Q[{{NUMBER_OF_UNKNOWNS}}+{{NUMBER_OF_AUXILIARY_VARIABLES}}]
989 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeCentre,
990 [[maybe_unused]] const tarch::la::Vector<Dimensions, double>& volumeH,
991 [[maybe_unused]] double t,
992 [[maybe_unused]] double dt,
993 [[maybe_unused]] double* __restrict__ S, // S[{{NUMBER_OF_UNKNOWNS}}]
994 [[maybe_unused]] Offloadable
996 // @todo Implement but ensure that all entries of S are properly set
997 for (int i = 0; i < NumberOfUnknowns; i++) {
1001#if defined(GPUOffloadingOMP)
1002#pragma omp end declare target
1006""", undefined=jinja2.DebugUndefined)
1008 d[
"FLUX_IMPLEMENTATION"] = flux_implementation
1009 d[
"NCP_IMPLEMENTATION"] = ncp_implementation
1010 d[
"EIGENVALUES_IMPLEMENTATION"] = eigenvalues_implementation
1011 d[
"SOURCE_TERM_IMPLEMENTATION"] = source_term_implementation
1012 d[
"STATELESS_PDE_TERMS"] = pde_terms_without_state
1013 return Template.render(**d)
create_rusanov_kernel_definitions_for_function(function, filename, patch_size, unknowns, auxiliary_variables, flux_implementation, ncp_implementation, source_term_implementation, compute_max_eigenvalue_of_next_time_step)