3 #include "KernelBenchmarks-main.h"
5 #include "AbstractFVSolver.h"
9 #include "celldata/FVSolverQ.h"
10 #include "celldata/FVSolverQReconstructed.h"
11 #include "exahype2/CellData.h"
12 #include "exahype2/EnclaveBookkeeping.h"
13 #include "exahype2/fv/BoundaryConditions.h"
14 #include "exahype2/fv/PatchUtils.h"
15 #include "facedata/FVSolverQNew.h"
16 #include "kernels/FVSolver/ReconstructPatch.h"
17 #include "peano4/datamanagement/CellMarker.h"
18 #include "peano4/datamanagement/FaceEnumerator.h"
19 #include "peano4/peano4.h"
20 #include "peano4/utils/Globals.h"
21 #include "peano4/utils/Loop.h"
22 #include "tarch/logging/Log.h"
23 #include "tarch/plotter/griddata/blockstructured/PeanoTextPatchFileWriter.h"
24 #include "tarch/timing/Measurement.h"
25 #include "tarch/timing/Watch.h"
26 #include "tasks/FVSolverEnclaveTask.h"
27 #include "toolbox/blockstructured/Projection.h"
32 tarch::logging::Log
_log(
"");
34 double printNextTimeStep = 0.0;
35 bool haveReceivedNonCriticalAssertion =
false;
37 std::vector<peano4::datamanagement::CellMarker> _cells;
38 const tarch::la::Vector<DIMENSIONS, double>
CellSize = DomainSize /
static_cast<double>(GridLength);
42 const std::string context =
"reportRuntime()";
43 constexpr
int LabelWidth = 25;
45 if (measurement.getNumberOfMeasurements() == 0) {
46 logInfo(context,
"Timing Measurement Report: No data recorded.");
50 logInfo(context,
"---------- Timing Measurement Report ----------");
51 double avg = measurement.getValue();
52 double std_dev = measurement.getStandardDeviation();
53 double min_val = measurement.min();
54 double max_val = measurement.max();
55 int min_idx = measurement.getMinMeasurement();
56 int max_idx = measurement.getMaxMeasurement();
57 double min_dev_percent = (avg == 0) ? 0.0 : (min_val / avg - 1.0) * 100.0;
58 double max_dev_percent = (avg == 0) ? 0.0 : (max_val / avg - 1.0) * 100.0;
60 std::stringstream
msg;
63 msg << std::left << std::setw(LabelWidth) <<
"Average Value:" << std::fixed << std::setprecision(8) << avg <<
"s";
64 logInfo(context,
msg.str());
67 msg << std::left << std::setw(LabelWidth) <<
"Average Cell Updates:" << std::fixed << std::setprecision(0)
68 << _cells.size() / avg;
69 logInfo(context,
msg.str());
72 msg << std::left << std::setw(LabelWidth) <<
"Standard Deviation:" << std::scientific << std::setprecision(8)
74 logInfo(context,
msg.str());
77 msg << std::left << std::setw(LabelWidth) <<
"# Measurements:" << measurement.getNumberOfMeasurements();
78 logInfo(context,
msg.str());
82 << std::left << std::setw(LabelWidth) <<
"Min Value:" << std::fixed << std::setprecision(8) << min_val <<
"s (at #"
84 <<
"[" << std::fixed << std::setprecision(2) << min_dev_percent <<
"%]";
85 logInfo(context,
msg.str());
89 << std::left << std::setw(LabelWidth) <<
"Max Value:" << std::fixed << std::setprecision(8) << max_val <<
"s (at #"
90 << max_idx <<
") " << std::showpos
91 <<
"[" << std::fixed << std::setprecision(2) << max_dev_percent <<
"%]";
92 logInfo(context,
msg.str());
95 msg << std::left << std::setw(LabelWidth) <<
"Most Recent Value:" << std::fixed << std::setprecision(8)
96 << measurement.getMostRecentValue() <<
"s";
97 logInfo(context,
msg.str());
100 msg << std::left << std::setw(LabelWidth) <<
"Accumulated Time:" << std::fixed << std::setprecision(8)
101 << measurement.getAccumulatedValue() <<
"s";
102 logInfo(context,
msg.str());
104 logInfo(context,
"-----------------------------------------------");
108 repositories::startPlottingStep();
109 static int counter = -1;
112 std::ostringstream snapshotFileName;
113 snapshotFileName <<
"solutions/solution-FVSolver-" << counter;
115 auto writer = tarch::plotter::griddata::blockstructured::PeanoTextPatchFileWriter(
117 snapshotFileName.str(),
118 "solutions/solution-FVSolver",
119 tarch::plotter::griddata::blockstructured::PeanoTextPatchFileWriter::IndexFileMode::AppendNewData,
120 0.5 * (repositories::getMinTimeStamp() + repositories::getMaxTimeStamp())
123 auto dataWriter = writer.createCellDataWriter(
125 AbstractFVSolver::NumberOfFiniteVolumesPerAxisPerPatch,
126 AbstractFVSolver::NumberOfUnknowns,
131 dataWriter->setPrecision(PlotterPrecision);
133 for (
auto&
marker : _cells) {
135 int cellIndex = dataWriter->getFirstCellWithinPatch(patchIndex);
138 dfor(k, AbstractFVSolver::NumberOfFiniteVolumesPerAxisPerPatch) {
139 double* data = QOut + currentDoF;
141 dataWriter->plotCell(cellIndex, data);
143 currentDoF += AbstractFVSolver::NumberOfUnknowns;
147 writer.writeToFile();
149 repositories::finishPlottingStep();
153 const double* NOALIAS Qinside,
154 double* NOALIAS Qoutside,
155 const tarch::la::Vector<DIMENSIONS, double>&
x,
156 const tarch::la::Vector<DIMENSIONS, double>&
h,
161 repositories::instanceOfFVSolver.boundaryConditions(Qinside, Qoutside,
x,
h,
t, normal);
165 const double ratio = DomainSize[0] /
CellSize[0];
166 const int depth =
static_cast<int>(std::round(std::log(ratio) / std::log(3.0)));
167 dfore(volume, GridLength, axis, 0) {
168 tarch::la::Vector<DIMENSIONS, double> faceOffset =
CellSize / 2.0;
170 tarch::la::Vector<DIMENSIONS, double>
171 faceCenterLow = tarch::la::multiplyComponents(tarch::la::convertScalar<double>(volume),
CellSize) + faceOffset
174 faceCenterLow[axis] = DomainOffset[axis];
177 tarch::la::Vector<DIMENSIONS, double> faceCenterHigh = faceCenterLow;
178 faceCenterHigh[axis] = DomainSize[axis] - faceOffset[axis] + DomainOffset[axis];
180 faceCenterHigh[axis] = DomainSize[axis] + DomainOffset[axis];
184 ::exahype2::fv::applyBoundaryConditions<double>(
190 AbstractFVSolver::NumberOfFiniteVolumesPerAxisPerPatch,
192 AbstractFVSolver::NumberOfUnknowns + AbstractFVSolver::NumberOfAuxiliaryVariables,
199 ::exahype2::fv::applyBoundaryConditions<double>(
205 AbstractFVSolver::NumberOfFiniteVolumesPerAxisPerPatch,
207 AbstractFVSolver::NumberOfUnknowns + AbstractFVSolver::NumberOfAuxiliaryVariables,
215 const double t = 0.0;
216 const double dt = 0.0;
218 for (
int axis = 0; axis < DIMENSIONS; ++axis) {
224 for (
auto&
marker : _cells) {
226 double* faces[TWO_TIMES_D];
227 for (
int i = 0; i < TWO_TIMES_D; i++) {
230 toolbox::blockstructured::projectPatchSolutionOntoFaces(
231 AbstractFVSolver::NumberOfFiniteVolumesPerAxisPerPatch,
233 AbstractFVSolver::NumberOfUnknowns,
234 AbstractFVSolver::NumberOfAuxiliaryVariables,
242 for (
auto&
marker : _cells) {
245 dfor(volume, AbstractFVSolver::NumberOfFiniteVolumesPerAxisPerPatch) {
246 int linearIndex = peano4::utils::dLinearised(volume, AbstractFVSolver::NumberOfFiniteVolumesPerAxisPerPatch)
247 * (AbstractFVSolver::NumberOfUnknowns + AbstractFVSolver::NumberOfAuxiliaryVariables);
248 FVSolver::initialCondition(
251 getVolumeCentre(
marker.x(),
marker.h(), AbstractFVSolver::NumberOfFiniteVolumesPerAxisPerPatch, volume),
252 ::exahype2::fv::getVolumeSize(
marker.h(), AbstractFVSolver::NumberOfFiniteVolumesPerAxisPerPatch),
260 tarch::la::Vector<DIMENSIONS, double> cellIndex = tarch::la::convertScalar<double>(index);
261 tarch::la::Vector<DIMENSIONS, double> cellPositionBase = DomainOffset +
CellSize / 2.0;
262 tarch::la::Vector<DIMENSIONS, double>
263 cellPosition = cellPositionBase + tarch::la::multiplyComponents(cellIndex,
CellSize);
264 peano4::grid::GridTraversalEvent event;
265 event.setX(cellPosition);
267 return peano4::datamanagement::CellMarker(event);
271 repositories::startGridConstructionStep();
272 _cells.reserve(std::pow(GridLength, DIMENSIONS));
274 repositories::finishGridConstructionStep();
278 repositories::startGridInitialisationStep();
281 repositories::finishGridInitialisationStep();
284 int main(
int argc,
char** argv) {
285 int returnCode = EXIT_SUCCESS;
290 benchmarks::exahype2::kernelbenchmarks::DomainOffset,
291 benchmarks::exahype2::kernelbenchmarks::DomainSize
294 repositories::initLogFilters();
295 repositories::startSimulation();
298 logInfo(
"main()",
"Created grid with " << _cells.size() <<
" cells");
300 logInfo(
"main()",
"Initialised grid");
304 ::exahype2::CellData<double, double, 3> patchData(_cells.size(), tarch::MemoryLocation::Pinned);
306 double* QInFlattened = tarch::allocateMemory<double>(
308 tarch::MemoryLocation::Pinned
311 double* QOutFlattened = tarch::allocateMemory<double>(
313 tarch::MemoryLocation::Pinned
315 double* QOutFlattenedHost = grid.
getCellQ(0);
317 tarch::la::Vector<DIMENSIONS, double>* cellCentresHost =
new tarch::la::Vector<DIMENSIONS, double>[_cells.size()];
318 tarch::la::Vector<DIMENSIONS, double>* cellSizeHost =
new tarch::la::Vector<DIMENSIONS, double>[_cells.size()];
320 for (
int patchIndex = 0; patchIndex < _cells.size(); patchIndex++) {
321 cellCentresHost[patchIndex] = _cells[patchIndex].x();
322 cellSizeHost[patchIndex] = _cells[patchIndex].h();
324 for (
int face = 0; face < TWO_TIMES_D; face++) {
326 _cells[patchIndex].
x(),
327 _cells[patchIndex].
h(),
333 tarch::copyTo<tarch::la::Vector<DIMENSIONS, double>, tarch::la::Vector<DIMENSIONS, double>>(
334 patchData.cellCentre,
337 tarch::MemoryLocation::Pinned
339 tarch::copyTo<tarch::la::Vector<DIMENSIONS, double>, tarch::la::Vector<DIMENSIONS, double>>(
343 tarch::MemoryLocation::Pinned
346 tarch::copyTo<double, double>(
350 tarch::MemoryLocation::Pinned
353 patchData.QOutFlattened = QOutFlattened;
354 patchData.QInFlattened = QInFlattened;
356 tarch::timing::Measurement measurement(1.0);
357 tarch::timing::Watch timeStepWatch(
"::",
"main()",
false);
359 double nextMinPlotTimeStamp = FirstPlotTimeStamp;
360 double nextMaxPlotTimeStamp = FirstPlotTimeStamp;
361 bool continueToSolve =
true;
363 while (continueToSolve) {
364 if (repositories::getMinTimeStamp() >= nextMinPlotTimeStamp
365 or repositories::getMaxTimeStamp() >= nextMaxPlotTimeStamp) {
366 if (repositories::getMinTimeStamp() >= nextMinPlotTimeStamp) {
367 nextMinPlotTimeStamp += TimeInBetweenPlots;
369 if (repositories::getMaxTimeStamp() >= nextMaxPlotTimeStamp) {
370 nextMaxPlotTimeStamp += TimeInBetweenPlots;
373 if constexpr (ShouldPlot) {
378 timeStepWatch.start();
384 patchData.dt = repositories::instanceOfFVSolver.getAdmissibleTimeStepSize();
385 repositories::startTimeStep();
387 tarch::timing::Watch watch(
"",
"",
false);
388 benchmarks::exahype2::kernelbenchmarks::tasks::FVSolverEnclaveTask::fuse(patchData);
390 measurement.setValue(watch.getCalendarTime());
392 timeStamp += repositories::instanceOfFVSolver.getAdmissibleTimeStepSize();
393 repositories::finishTimeStep();
395 tarch::copyFrom<double, double>(
399 tarch::MemoryLocation::Pinned
403 timeStepWatch.stop();
407 repositories::printTimeStep(
false);
409 logInfo(
"main()",
"Average cell updates per second: " << _cells.size() / measurement.getValue());
411 printNextTimeStep += repositories::PrintTimeStepIntervalInSeconds;
414 if (repositories::getMinTimeStamp() >= MinTerminalTime and repositories::getMaxTimeStamp() >= MaxTerminalTime) {
415 continueToSolve =
false;
418 if (tarch::hasNonCriticalAssertionBeenViolated() and not haveReceivedNonCriticalAssertion) {
419 continueToSolve =
false;
420 haveReceivedNonCriticalAssertion =
true;
421 logError(
"main()",
"Noncritical assertion has been triggered in code. Dump final state and terminate.");
426 if constexpr (ShouldPlot) {
429 repositories::finishSimulation();
431 if (haveReceivedNonCriticalAssertion) {
432 logWarning(
"main()",
"Terminated gracefully after noncritical assertion");
433 returnCode = EXIT_FAILURE;
436 repositories::printTimeStep(
false);
437 logInfo(
"main()",
"Terminated successfully");
438 returnCode = EXIT_SUCCESS;
443 delete[] cellCentresHost;
444 delete[] cellSizeHost;
445 tarch::freeMemory(QOutFlattened, tarch::MemoryLocation::Pinned);
446 tarch::freeMemory(QInFlattened, tarch::MemoryLocation::Pinned);
constexpr double timeStamp
int main(int argc, char **argv)
tarch::logging::Log _log("::")
const tarch::la::Vector< DIMENSIONS, double > CellSize
tarch::timing::Measurement timeStepMeasurement
A singleton repository to manage and provide access to grid cell and face data.
int getCellQReconstructedCardinality()
double * getFaceQNew(int index, int axis)
void copyFacesFromDevice()
double * getFaceQNewDevice(const tarch::la::Vector< DIMENSIONS, double > &cellCentre, const tarch::la::Vector< DIMENSIONS, double > &cellSize, int axis)
int getCellQCardinality()
static DataRepository & getInstance()
double * getCellQ(int index)
peano4::datamanagement::CellMarker createMarkerFromIndex(const tarch ::la ::Vector< DIMENSIONS, int > &index)
void applyBoundaryConditionsToAxis(int axis, double t, double dt)
void applyBoundaryConditions()
void applyInitialConditions()
void invokeFVSolverBoundaryConditions(const double *NOALIAS Qinside, double *NOALIAS Qoutside, const tarch::la::Vector< DIMENSIONS, double > &x, const tarch::la::Vector< DIMENSIONS, double > &h, double t, double dt, int normal)
void projectPatchOntoFaces()
void reportRuntime(const std::string &kernelIdentificator, const tarch::timing::Measurement &timingComputeKernel, const tarch::timing::Measurement &timingKernelLaunch, int numberOfCells, int numberOfThreads, tarch::logging::Log _log)
Reports the runtime and throughput of the benchmarks.
static int getFaceIndex(const tarch::la::Vector< DIMENSIONS, double > &cellCentre, const tarch::la::Vector< DIMENSIONS, double > &cellSize, int axis)