6 int NumberOfVolumesPerAxisInPatch,
9 int NumberOfAuxiliaryVariables,
11 bool EvaluateNonconservativeProduct,
13 bool EvaluateMaximumEigenvalueAfterTimeStep>
18 logTraceIn(
"timeStepWithRusanovPatchwiseInsituStateless()");
20 const enumerator::AoSLexicographicEnumerator QInEnumerator(1, NumberOfVolumesPerAxisInPatch,
HaloSize, NumberOfUnknowns, NumberOfAuxiliaryVariables);
21 const enumerator::AoSLexicographicEnumerator QOutEnumerator(1, NumberOfVolumesPerAxisInPatch, 0, NumberOfUnknowns, NumberOfAuxiliaryVariables);
22 const enumerator::SingleDoFEnumerator singleVolumeEnumerator(NumberOfUnknowns, 0);
24 for (
int patchIndex = 0; patchIndex < patchData.numberOfCells; patchIndex++) {
28 if constexpr (EvaluateSource) {
30#pragma omp simd collapse(2)
31 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
32 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
33 loopbodies::copySolutionAndAddSourceTerm<SolverType>(
34 patchData.QIn[patchIndex],
36 patchData.cellCentre[patchIndex],
37 patchData.cellSize[patchIndex],
40 patchData.t[patchIndex],
41 patchData.dt[patchIndex],
42 patchData.QOut[patchIndex],
48#pragma omp simd collapse(3)
49 for (
int z = 0;
z < NumberOfVolumesPerAxisInPatch;
z++) {
50 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
51 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
52 loopbodies::copySolutionAndAddSourceTerm<SolverType>(
53 patchData.QIn[patchIndex],
55 patchData.cellCentre[patchIndex],
56 patchData.cellSize[patchIndex],
59 patchData.t[patchIndex],
60 patchData.dt[patchIndex],
61 patchData.QOut[patchIndex],
70#pragma omp simd collapse(3)
71 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
72 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
73 for (
int unknown = 0; unknown < NumberOfUnknowns + NumberOfAuxiliaryVariables; unknown++) {
74 loopbodies::copySolution(patchData.QIn[patchIndex], QInEnumerator, patchIndex,
volumeIndex(x, y), unknown, patchData.QOut[patchIndex], QOutEnumerator);
79#pragma omp simd collapse(4)
80 for (
int z = 0;
z < NumberOfVolumesPerAxisInPatch;
z++) {
81 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
82 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
83 for (
int unknown = 0; unknown < NumberOfUnknowns + NumberOfAuxiliaryVariables; unknown++) {
84 loopbodies::copySolution(patchData.QIn[patchIndex], QInEnumerator, patchIndex,
volumeIndex(x, y, z), unknown, patchData.QOut[patchIndex], QOutEnumerator);
96 for (
int shift = 0; shift < 2; shift++) {
97 for (
int x = -
HaloSize + shift;
x < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
x += 2) {
99 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
102 loopbodies::computeMaxEigenvalue<SolverType>(
103 patchData.QIn[patchIndex],
105 patchData.cellCentre[patchIndex],
106 patchData.cellSize[patchIndex],
109 patchData.t[patchIndex],
110 patchData.dt[patchIndex],
113 singleVolumeEnumerator
115 loopbodies::computeMaxEigenvalue<SolverType>(
116 patchData.QIn[patchIndex],
118 patchData.cellCentre[patchIndex],
119 patchData.cellSize[patchIndex],
122 patchData.t[patchIndex],
123 patchData.dt[patchIndex],
126 singleVolumeEnumerator
128 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
129 loopbodies::updateSolutionWithEigenvalueDamping(
130 patchData.QIn[patchIndex],
134 patchData.cellCentre[patchIndex],
135 patchData.cellSize[patchIndex],
139 patchData.dt[patchIndex],
141 patchData.QOut[patchIndex],
149 for (
int shift = 0; shift < 2; shift++) {
150 for (
int y = -
HaloSize + shift;
y < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
y += 2) {
152 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
155 loopbodies::computeMaxEigenvalue<SolverType>(
156 patchData.QIn[patchIndex],
158 patchData.cellCentre[patchIndex],
159 patchData.cellSize[patchIndex],
162 patchData.t[patchIndex],
163 patchData.dt[patchIndex],
166 singleVolumeEnumerator
168 loopbodies::computeMaxEigenvalue<SolverType>(
169 patchData.QIn[patchIndex],
171 patchData.cellCentre[patchIndex],
172 patchData.cellSize[patchIndex],
175 patchData.t[patchIndex],
176 patchData.dt[patchIndex],
179 singleVolumeEnumerator
181 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
182 loopbodies::updateSolutionWithEigenvalueDamping(
183 patchData.QIn[patchIndex],
187 patchData.cellCentre[patchIndex],
188 patchData.cellSize[patchIndex],
192 patchData.dt[patchIndex],
194 patchData.QOut[patchIndex],
202 for (
int shift = 0; shift < 2; shift++) {
203 for (
int x = -
HaloSize + shift;
x < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
x += 2) {
204#pragma omp simd collapse(2)
205 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
206 for (
int z = 0;
z < NumberOfVolumesPerAxisInPatch;
z++) {
209 loopbodies::computeMaxEigenvalue<SolverType>(
210 patchData.QIn[patchIndex],
212 patchData.cellCentre[patchIndex],
213 patchData.cellSize[patchIndex],
216 patchData.t[patchIndex],
217 patchData.dt[patchIndex],
220 singleVolumeEnumerator
222 loopbodies::computeMaxEigenvalue<SolverType>(
223 patchData.QIn[patchIndex],
225 patchData.cellCentre[patchIndex],
226 patchData.cellSize[patchIndex],
229 patchData.t[patchIndex],
230 patchData.dt[patchIndex],
233 singleVolumeEnumerator
235 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
236 loopbodies::updateSolutionWithEigenvalueDamping(
237 patchData.QIn[patchIndex],
241 patchData.cellCentre[patchIndex],
242 patchData.cellSize[patchIndex],
246 patchData.dt[patchIndex],
248 patchData.QOut[patchIndex],
257 for (
int shift = 0; shift < 2; shift++) {
258 for (
int y = -
HaloSize + shift;
y < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
y += 2) {
259#pragma omp simd collapse(2)
260 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
261 for (
int z = 0;
z < NumberOfVolumesPerAxisInPatch;
z++) {
264 loopbodies::computeMaxEigenvalue<SolverType>(
265 patchData.QIn[patchIndex],
267 patchData.cellCentre[patchIndex],
268 patchData.cellSize[patchIndex],
271 patchData.t[patchIndex],
272 patchData.dt[patchIndex],
275 singleVolumeEnumerator
277 loopbodies::computeMaxEigenvalue<SolverType>(
278 patchData.QIn[patchIndex],
280 patchData.cellCentre[patchIndex],
281 patchData.cellSize[patchIndex],
284 patchData.t[patchIndex],
285 patchData.dt[patchIndex],
288 singleVolumeEnumerator
290 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
291 loopbodies::updateSolutionWithEigenvalueDamping(
292 patchData.QIn[patchIndex],
296 patchData.cellCentre[patchIndex],
297 patchData.cellSize[patchIndex],
301 patchData.dt[patchIndex],
303 patchData.QOut[patchIndex],
312 for (
int shift = 0; shift < 2; shift++) {
313 for (
int z = -
HaloSize + shift;
z < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
z += 2) {
314#pragma omp simd collapse(2)
315 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
316 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
319 loopbodies::computeMaxEigenvalue<SolverType>(
320 patchData.QIn[patchIndex],
322 patchData.cellCentre[patchIndex],
323 patchData.cellSize[patchIndex],
326 patchData.t[patchIndex],
327 patchData.dt[patchIndex],
330 singleVolumeEnumerator
332 loopbodies::computeMaxEigenvalue<SolverType>(
333 patchData.QIn[patchIndex],
335 patchData.cellCentre[patchIndex],
336 patchData.cellSize[patchIndex],
339 patchData.t[patchIndex],
340 patchData.dt[patchIndex],
343 singleVolumeEnumerator
345 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
346 loopbodies::updateSolutionWithEigenvalueDamping(
347 patchData.QIn[patchIndex],
351 patchData.cellCentre[patchIndex],
352 patchData.cellSize[patchIndex],
356 patchData.dt[patchIndex],
358 patchData.QOut[patchIndex],
371 if constexpr (EvaluateFlux) {
373 for (
int shift = 0; shift < 2; shift++) {
374 for (
int x = -
HaloSize + shift;
x < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
x += 2) {
376 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
379 loopbodies::computeFlux<SolverType>(
380 patchData.QIn[patchIndex],
382 patchData.cellCentre[patchIndex],
383 patchData.cellSize[patchIndex],
386 patchData.t[patchIndex],
387 patchData.dt[patchIndex],
390 singleVolumeEnumerator
392 loopbodies::computeFlux<SolverType>(
393 patchData.QIn[patchIndex],
395 patchData.cellCentre[patchIndex],
396 patchData.cellSize[patchIndex],
399 patchData.t[patchIndex],
400 patchData.dt[patchIndex],
403 singleVolumeEnumerator
405 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
406 loopbodies::updateSolutionWithFlux(
409 singleVolumeEnumerator,
410 patchData.cellCentre[patchIndex],
411 patchData.cellSize[patchIndex],
415 patchData.dt[patchIndex],
417 patchData.QOut[patchIndex],
425 for (
int shift = 0; shift < 2; shift++) {
426 for (
int y = -
HaloSize + shift;
y < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
y += 2) {
428 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
431 loopbodies::computeFlux<SolverType>(
432 patchData.QIn[patchIndex],
434 patchData.cellCentre[patchIndex],
435 patchData.cellSize[patchIndex],
438 patchData.t[patchIndex],
439 patchData.dt[patchIndex],
442 singleVolumeEnumerator
444 loopbodies::computeFlux<SolverType>(
445 patchData.QIn[patchIndex],
447 patchData.cellCentre[patchIndex],
448 patchData.cellSize[patchIndex],
451 patchData.t[patchIndex],
452 patchData.dt[patchIndex],
455 singleVolumeEnumerator
457 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
458 loopbodies::updateSolutionWithFlux(
461 singleVolumeEnumerator,
462 patchData.cellCentre[patchIndex],
463 patchData.cellSize[patchIndex],
467 patchData.dt[patchIndex],
469 patchData.QOut[patchIndex],
477 for (
int shift = 0; shift < 2; shift++) {
478 for (
int x =
HaloSize + shift;
x < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
x += 2) {
479#pragma omp simd collapse(2)
480 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
481 for (
int z = 0;
z < NumberOfVolumesPerAxisInPatch;
z++) {
484 loopbodies::computeFlux<SolverType>(
485 patchData.QIn[patchIndex],
487 patchData.cellCentre[patchIndex],
488 patchData.cellSize[patchIndex],
491 patchData.t[patchIndex],
492 patchData.dt[patchIndex],
495 singleVolumeEnumerator
497 loopbodies::computeFlux<SolverType>(
498 patchData.QIn[patchIndex],
500 patchData.cellCentre[patchIndex],
501 patchData.cellSize[patchIndex],
504 patchData.t[patchIndex],
505 patchData.dt[patchIndex],
508 singleVolumeEnumerator
510 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
511 loopbodies::updateSolutionWithFlux(
514 singleVolumeEnumerator,
515 patchData.cellCentre[patchIndex],
516 patchData.cellSize[patchIndex],
520 patchData.dt[patchIndex],
522 patchData.QOut[patchIndex],
531 for (
int shift = 0; shift < 2; shift++) {
532 for (
int y = -
HaloSize + shift;
y < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
y += 2) {
533#pragma omp simd collapse(2)
534 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
535 for (
int z = 0;
z < NumberOfVolumesPerAxisInPatch;
z++) {
538 loopbodies::computeFlux<SolverType>(
539 patchData.QIn[patchIndex],
541 patchData.cellCentre[patchIndex],
542 patchData.cellSize[patchIndex],
545 patchData.t[patchIndex],
546 patchData.dt[patchIndex],
549 singleVolumeEnumerator
551 loopbodies::computeFlux<SolverType>(
552 patchData.QIn[patchIndex],
554 patchData.cellCentre[patchIndex],
555 patchData.cellSize[patchIndex],
558 patchData.t[patchIndex],
559 patchData.dt[patchIndex],
562 singleVolumeEnumerator
564 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
565 loopbodies::updateSolutionWithFlux(
568 singleVolumeEnumerator,
569 patchData.cellCentre[patchIndex],
570 patchData.cellSize[patchIndex],
574 patchData.dt[patchIndex],
576 patchData.QOut[patchIndex],
585 for (
int shift = 0; shift < 2; shift++) {
586 for (
int z = -
HaloSize + shift;
z < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
z += 2) {
587#pragma omp simd collapse(2)
588 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
589 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
592 loopbodies::computeFlux<SolverType>(
593 patchData.QIn[patchIndex],
595 patchData.cellCentre[patchIndex],
596 patchData.cellSize[patchIndex],
599 patchData.t[patchIndex],
600 patchData.dt[patchIndex],
603 singleVolumeEnumerator
605 loopbodies::computeFlux<SolverType>(
606 patchData.QIn[patchIndex],
608 patchData.cellCentre[patchIndex],
609 patchData.cellSize[patchIndex],
612 patchData.t[patchIndex],
613 patchData.dt[patchIndex],
616 singleVolumeEnumerator
618 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
619 loopbodies::updateSolutionWithFlux(
622 singleVolumeEnumerator,
623 patchData.cellCentre[patchIndex],
624 patchData.cellSize[patchIndex],
628 patchData.dt[patchIndex],
630 patchData.QOut[patchIndex],
641 if constexpr (EvaluateNonconservativeProduct) {
643 for (
int shift = 0; shift < 2; shift++) {
644 for (
int x = -
HaloSize + shift;
x < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
x += 2) {
646 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
648 loopbodies::computeNonconservativeFlux<SolverType>(
649 patchData.QIn[patchIndex],
651 patchData.cellCentre[patchIndex],
652 patchData.cellSize[patchIndex],
655 patchData.t[patchIndex],
656 patchData.dt[patchIndex],
659 singleVolumeEnumerator
661 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
662 loopbodies::updateSolutionWithNonconservativeFlux(
664 singleVolumeEnumerator,
665 patchData.cellCentre[patchIndex],
666 patchData.cellSize[patchIndex],
670 patchData.dt[patchIndex],
672 patchData.QOut[patchIndex],
680 for (
int shift = 0; shift < 2; shift++) {
681 for (
int y = -
HaloSize + shift;
y < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
y += 2) {
683 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
685 loopbodies::computeNonconservativeFlux<SolverType>(
686 patchData.QIn[patchIndex],
688 patchData.cellCentre[patchIndex],
689 patchData.cellSize[patchIndex],
692 patchData.t[patchIndex],
693 patchData.dt[patchIndex],
696 singleVolumeEnumerator
698 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
699 loopbodies::updateSolutionWithNonconservativeFlux(
701 singleVolumeEnumerator,
702 patchData.cellCentre[patchIndex],
703 patchData.cellSize[patchIndex],
707 patchData.dt[patchIndex],
709 patchData.QOut[patchIndex],
717 for (
int shift = 0; shift < 2; shift++) {
718 for (
int x = -
HaloSize + shift;
x < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
x += 2) {
719#pragma omp simd collapse(2)
720 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
721 for (
int z = 0;
z < NumberOfVolumesPerAxisInPatch;
z++) {
723 loopbodies::computeNonconservativeFlux<SolverType>(
724 patchData.QIn[patchIndex],
726 patchData.cellCentre[patchIndex],
727 patchData.cellSize[patchIndex],
730 patchData.t[patchIndex],
731 patchData.dt[patchIndex],
734 singleVolumeEnumerator
736 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
737 loopbodies::updateSolutionWithNonconservativeFlux(
739 singleVolumeEnumerator,
740 patchData.cellCentre[patchIndex],
741 patchData.cellSize[patchIndex],
745 patchData.dt[patchIndex],
747 patchData.QOut[patchIndex],
756 for (
int shift = 0; shift < 2; shift++) {
757 for (
int y = -
HaloSize + shift;
y < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
y += 2) {
758#pragma omp simd collapse(2)
759 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
760 for (
int z = 0;
z < NumberOfVolumesPerAxisInPatch;
z++) {
762 loopbodies::computeNonconservativeFlux<SolverType>(
763 patchData.QIn[patchIndex],
765 patchData.cellCentre[patchIndex],
766 patchData.cellSize[patchIndex],
769 patchData.t[patchIndex],
770 patchData.dt[patchIndex],
773 singleVolumeEnumerator
775 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
776 loopbodies::updateSolutionWithNonconservativeFlux(
778 singleVolumeEnumerator,
779 patchData.cellCentre[patchIndex],
780 patchData.cellSize[patchIndex],
784 patchData.dt[patchIndex],
786 patchData.QOut[patchIndex],
795 for (
int shift = 0; shift < 2; shift++) {
796 for (
int z = -
HaloSize + shift;
z < NumberOfVolumesPerAxisInPatch +
HaloSize - 1;
z += 2) {
797#pragma omp simd collapse(2)
798 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
799 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
801 loopbodies::computeNonconservativeFlux<SolverType>(
802 patchData.QIn[patchIndex],
804 patchData.cellCentre[patchIndex],
805 patchData.cellSize[patchIndex],
808 patchData.t[patchIndex],
809 patchData.dt[patchIndex],
812 singleVolumeEnumerator
814 for (
int unknown = 0; unknown < NumberOfUnknowns; unknown++) {
815 loopbodies::updateSolutionWithNonconservativeFlux(
817 singleVolumeEnumerator,
818 patchData.cellCentre[patchIndex],
819 patchData.cellSize[patchIndex],
823 patchData.dt[patchIndex],
825 patchData.QOut[patchIndex],
836 if constexpr (EvaluateMaximumEigenvalueAfterTimeStep) {
837 double newMaxEigenvalue = 0.0;
839#pragma omp simd collapse(2) reduction(max : newMaxEigenvalue)
840 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
841 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
842 newMaxEigenvalue = std::max(
844 loopbodies::reduceMaxEigenvalue<SolverType>(
845 patchData.QOut[patchIndex],
847 patchData.cellCentre[patchIndex],
848 patchData.cellSize[patchIndex],
851 patchData.t[patchIndex],
852 patchData.dt[patchIndex]
858#pragma omp simd collapse(3) reduction(max : newMaxEigenvalue)
859 for (
int z = 0;
z < NumberOfVolumesPerAxisInPatch;
z++) {
860 for (
int y = 0;
y < NumberOfVolumesPerAxisInPatch;
y++) {
861 for (
int x = 0;
x < NumberOfVolumesPerAxisInPatch;
x++) {
862 newMaxEigenvalue = std::max(
864 loopbodies::reduceMaxEigenvalue<SolverType>(
865 patchData.QOut[patchIndex],
867 patchData.cellCentre[patchIndex],
868 patchData.cellSize[patchIndex],
871 patchData.t[patchIndex],
872 patchData.dt[patchIndex]
879 patchData.maxEigenvalue[patchIndex] = newMaxEigenvalue;
883 logTraceOut(
"timeStepWithRusanovPatchwiseInsituStateless()");
889 int NumberOfVolumesPerAxisInPatch,
891 int NumberOfUnknowns,
892 int NumberOfAuxiliaryVariables,
894 bool EvaluateNonconservativeProduct,
896 bool EvaluateMaximumEigenvalueAfterTimeStep>
900 tarch::timing::Watch watch(
"exahype2::fv::rusanov",
"timeStepWithRusanovPatchwiseInsituStateless",
false,
true);
903 NumberOfVolumesPerAxisInPatch,
906 NumberOfAuxiliaryVariables,
908 EvaluateNonconservativeProduct,
910 EvaluateMaximumEigenvalueAfterTimeStep>(patchData, loopParallelism);
912 measurement.
setValue(watch.getCalendarTime());
int __attribute__((optimize("O0"))) toolbox
static constexpr int HaloSize
#define logTraceOut(methodName)
#define logTraceIn(methodName)
void setValue(const double &value)
Set the value.
A simple class that has to be included to measure the clock ticks required for an operation.
KeywordToAvoidDuplicateSymbolsForInlinedFunctions void timeStepWithRusanovPatchwiseInsituStateless(CellData &patchData, tarch::timing::Measurement &measurement, peano4::utils::LoopPlacement loopParallelism=peano4::utils::LoopPlacement::Serial) InlineMethod
auto volumeIndex(Args... args)
LoopPlacement
Guide loop-level parallelism.
tarch::logging::Log _log("examples::unittests")