46 const std::
string &fname,
47 const std::
string &fnameSeries,
53 reader->SetASCIIPrecision(config.dataIOControl.nASCIIPrecision);
54 reader->SetVTKFloatEncodeMode(config.dataIOControl.vtuFloatEncodeMode);
55 mesh->SetHDF5OutSetting(config.dataIOControl.hdfChunkSize, config.dataIOControl.hdfDeflateLevel,
56 config.dataIOControl.hdfCollOnData, config.dataIOControl.hdfCollOnMeta);
72 std::vector<std::function<void()>> fOuts;
75 if (config.dataIOControl.outVolumeData || mode == PrintDataTimeAverage)
78 std::lock_guard<std::mutex> outLock(outArraysMutex);
79 if (config.dataIOControl.outAtCellData || mode == PrintDataTimeAverage)
80 for (
index iCell = 0; iCell < mesh->NumCell(); iCell++)
87 TU recu = uOut[iCell];
88 if (eval.settings.frameConstRotation.enabled)
89 eval.TransformURotatingFrame_ABS_VELO(recu, vfv->GetCellQuadraturePPhys(iCell, -1), -1);
90 TVec velo = (recu(Seq123).array() / recu(0)).matrix();
95 real M = std::sqrt(std::abs(vsqr / asqr));
96 real T = p / recu(0) / eval.settings.idealGasProperty.Rgas;
98 (*outDist)[iCell][0] = recu(0);
99 for (
int i = 0; i < dim; i++)
100 (*outDist)[iCell][i + 1] =
velo(i);
101 (*outDist)[iCell][I4 + 0] = p;
102 (*outDist)[iCell][I4 + 1] = T;
103 (*outDist)[iCell][I4 + 2] = M;
105 (*outDist)[iCell][I4 + 3] = ifUseLimiter[iCell][0] / (vfv->getSettings().smoothThreshold +
verySmallReal);
107 (*outDist)[iCell][I4 + 4] = odeResidualF(iCell);
116 for (
int i = I4 + 1; i < nVars; i++)
118 (*outDist)[iCell][4 + i] = recu(i) / recu(0);
120 int iCur = 4 + nVars;
121 for (
auto &out : additionalCellScalars)
123 (*outDist)[iCell][iCur] = std::get<1>(out)(iCell);
128 if (config.dataIOControl.outAtPointData)
130 if (config.limiterControl.useLimiter)
132 uRecNew.trans.startPersistentPull();
133 uRecNew.trans.waitPersistentPull();
137 uRec.trans.startPersistentPull();
138 uRec.trans.waitPersistentPull();
141 uOut.
trans.startPersistentPull();
142 uOut.
trans.waitPersistentPull();
144 for (
index iN = 0; iN < mesh->NumNodeProc(); iN++)
145 outDistPointPair[iN].setZero();
146 std::vector<int> nN2C(mesh->NumNodeProc(), 0);
147 DNDS_assert(outDistPointPair.father->Size() == mesh->NumNode());
148 DNDS_assert(outDistPointPair.son->Size() == mesh->NumNodeGhost());
149 for (
index iCell = 0; iCell < mesh->NumCellProc(); iCell++)
151 for (
int ic2n = 0; ic2n < mesh->cell2node.RowSize(iCell); ic2n++)
153 auto iNode = mesh->cell2node(iCell, ic2n);
155 auto pPhy = mesh->GetCoordNodeOnCell(iCell, ic2n);
158 DiBj.resize(1, uRecNew[iCell].rows() + 1);
160 vfv->FDiffBaseValue(DiBj, pPhy, iCell, -2, -2);
162 TU vRec = (DiBj(EigenAll, Eigen::seq(1, EigenLast)) * (config.limiterControl.useLimiter ? uRecNew[iCell] : uRec[iCell])).transpose() +
164 if (mesh->isPeriodic)
165 vRec(Seq123) = mesh->periodicInfo.GetVectorBackByBits<dim, 1>(vRec(Seq123), mesh->cell2nodePbi(iCell, ic2n));
166 if (mode == PrintDataTimeAverage)
168 if (eval.settings.frameConstRotation.enabled)
169 eval.TransformURotatingFrame_ABS_VELO(vRec, pPhy, -1);
170 if (iNode < mesh->NumNode())
171 outDistPointPair[iNode](Eigen::seq(0, nVars - 1)) += vRec;
175 for (
index iN = 0; iN < mesh->NumNode(); iN++)
177 TU recu = outDistPointPair[iN](Eigen::seq(0, nVars - 1)) / (nN2C.at(iN) +
verySmallReal);
180 TVec velo = (recu(Seq123).array() / recu(0)).matrix();
183 Gas::IdealGasThermal(recu(I4), recu(0), vsqr, eval.settings.idealGasProperty.gamma, p, asqr, H);
185 real M = std::sqrt(std::abs(vsqr / asqr));
186 real T = p / recu(0) / eval.settings.idealGasProperty.Rgas;
188 outDistPointPair[iN][0] = recu(0);
189 for (
int i = 0; i < dim; i++)
190 outDistPointPair[iN][i + 1] =
velo(i);
191 outDistPointPair[iN][I4 + 0] = p;
192 outDistPointPair[iN][I4 + 1] = T;
193 outDistPointPair[iN][I4 + 2] = M;
195 for (
int i = I4 + 1; i < nVars; i++)
197 outDistPointPair[iN][2 + i] = recu(i) / recu(0);
200 outDistPointPair.trans.startPersistentPull();
201 outDistPointPair.trans.waitPersistentPull();
204 if (config.dataIOControl.outPltMode == 0)
206 if (config.dataIOControl.outAtCellData || mode == PrintDataTimeAverage)
208 outDist2SerialTrans.startPersistentPull();
209 outDist2SerialTrans.waitPersistentPull();
211 if (config.dataIOControl.outAtPointData)
213 outDist2SerialTransPoint.startPersistentPull();
214 outDist2SerialTransPoint.waitPersistentPull();
218 int NOUTS_C{0}, NOUTSPoint_C{0};
219 if (config.dataIOControl.outAtCellData || mode == PrintDataTimeAverage)
221 if (config.dataIOControl.outAtPointData)
222 NOUTSPoint_C = nOUTSPoint;
224 std::vector<std::string> names, namesPoint;
225 if constexpr (dim == 2)
227 "R",
"U",
"V",
"P",
"T",
"M",
"ifUseLimiter",
"RHSr"};
230 "R",
"U",
"V",
"W",
"P",
"T",
"M",
"ifUseLimiter",
"RHSr"};
231 if constexpr (dim == 2)
233 "R",
"U",
"V",
"P",
"T",
"M"};
236 "R",
"U",
"V",
"W",
"P",
"T",
"M"};
237 for (
int i = I4 + 1; i < nVars; i++)
239 names.push_back(
"V" + std::to_string(i - I4));
240 namesPoint.push_back(
"V" + std::to_string(i - I4));
242 for (
auto &out : additionalCellScalars)
244 names.push_back(std::get<0>(out));
246 if (config.dataIOControl.outAtCellData)
248 if (config.dataIOControl.outAtPointData)
251 if (config.dataIOControl.outPltTecplotFormat)
253 if (config.dataIOControl.outPltMode == 0)
255 auto outRun = [mesh = mesh, reader = reader,
256 outDist = outDist, outSerial = outSerial, &outDistPointPair = outDistPointPair,
257 outSerialPoint = outSerialPoint,
258 fname, fnameSeries, NOUTS_C, NOUTSPoint_C, cDim,
259 names, namesPoint, tSimu,
260 &outArraysMutex = outArraysMutex]()
262 std::lock_guard<std::mutex> outArraysLock(outArraysMutex);
263 reader->PrintSerialPartPltBinaryDataArray(
265 NOUTS_C, NOUTSPoint_C,
267 {
return names[idata]; },
268 [&](
int idata,
index iv)
270 return (*outSerial)[iv][idata];
273 {
return namesPoint[idata] +
"_p"; },
274 [&](
int idata,
index in)
275 {
return (*outSerialPoint)[in][idata]; },
284 else if (config.dataIOControl.outPltMode == 1)
287 auto outRun = [mesh = mesh, reader = reader,
288 outDist = outDist, outSerial = outSerial, &outDistPointPair = outDistPointPair,
289 outSerialPoint = outSerialPoint,
290 fname, fnameSeries, NOUTS_C, NOUTSPoint_C, cDim,
291 names, namesPoint, tSimu,
292 &outArraysMutex = outArraysMutex]()
294 std::lock_guard<std::mutex> outArraysLock(outArraysMutex);
295 reader->PrintSerialPartPltBinaryDataArray(
297 NOUTS_C, NOUTSPoint_C,
299 {
return names[idata]; },
300 [&](
int idata,
index iv)
302 return (*outDist)[iv][idata];
305 {
return namesPoint[idata] +
"_p"; },
306 [&](
int idata,
index in)
307 {
return outDistPointPair[in][idata]; },
318 if (config.dataIOControl.outPltVTKFormat)
320 if (config.dataIOControl.outPltMode == 0)
322 auto outRun = [mesh = mesh, reader = reader,
323 outDist = outDist, outSerial = outSerial, &outDistPointPair = outDistPointPair,
324 outSerialPoint = outSerialPoint,
325 fname, fnameSeries, NOUTS_C, NOUTSPoint_C, cDim,
326 names, namesPoint, tSimu,
327 &outArraysMutex = outArraysMutex]()
329 std::lock_guard<std::mutex> outArraysLock(outArraysMutex);
330 reader->PrintSerialPartVTKDataArray(
332 std::max(NOUTS_C - cDim, 0), std::min(NOUTS_C, 1),
333 std::max(NOUTSPoint_C - cDim, 0), std::min(NOUTSPoint_C, 1),
336 idata = idata > 0 ? idata + cDim : 0;
339 [&](
int idata,
index iv)
341 idata = idata > 0 ? idata + cDim : 0;
342 return (*outSerial)[iv][idata];
348 [&](
int idata,
index iv,
int idim)
350 return (*outSerial)[iv][1 + idim];
354 idata = idata > 0 ? idata + cDim : 0;
355 return namesPoint[idata];
357 [&](
int idata,
index iv)
359 idata = idata > 0 ? idata + cDim : 0;
360 return (*outSerialPoint)[iv][idata];
366 [&](
int idata,
index iv,
int idim)
369 return (*outSerialPoint)[iv][1 + idim];
377 fOuts.push_back(outRun);
379 else if (config.dataIOControl.outPltMode == 1)
381 auto outRun = [mesh = mesh, reader = reader,
382 outDist = outDist, outSerial = outSerial, &outDistPointPair = outDistPointPair,
383 outSerialPoint = outSerialPoint,
384 fname, fnameSeries, NOUTS_C, NOUTSPoint_C, cDim,
385 names, namesPoint, tSimu,
386 &outArraysMutex = outArraysMutex]()
388 std::lock_guard<std::mutex> outArraysLock(outArraysMutex);
389 reader->PrintSerialPartVTKDataArray(
391 std::max(NOUTS_C - cDim, 0), std::min(NOUTS_C, 1),
392 std::max(NOUTSPoint_C - cDim, 0), std::min(NOUTSPoint_C, 1),
395 idata = idata > 0 ? idata + cDim : 0;
398 [&](
int idata,
index iv)
400 idata = idata > 0 ? idata + cDim : 0;
401 return (*outDist)[iv][idata];
407 [&](
int idata,
index iv,
int idim)
409 return idim < cDim ? (*outDist)[iv][1 + idim] : 0.0;
413 idata = idata > 0 ? idata + cDim : 0;
414 return namesPoint[idata];
416 [&](
int idata,
index iv)
418 idata = idata > 0 ? idata + cDim : 0;
419 return outDistPointPair[iv][idata];
425 [&](
int idata,
index iv,
int idim)
427 return idim < cDim ? outDistPointPair[iv][1 + idim] : 0.0;
435 fOuts.push_back(outRun);
439 if (config.dataIOControl.outPltVTKHDFFormat)
441 MPI_Comm commDup = MPI_COMM_NULL;
442 MPI_Comm_dup(mpi.comm, &commDup);
443 auto outRun = [mesh = mesh, reader = reader, outDist = outDist, &outDistPointPair = outDistPointPair,
444 fname, fnameSeries, NOUTS_C, NOUTSPoint_C, cDim,
445 names, namesPoint, tSimu,
446 &outArraysMutex = outArraysMutex, commDup]()
450 std::scoped_lock lock(outArraysMutex,
HDF_mutex);
451 MPI_Comm commDup1 = commDup;
452 mesh->PrintParallelVTKHDFDataArray(
454 std::max(NOUTS_C - cDim, 0), std::min(NOUTS_C, 1),
455 std::max(NOUTSPoint_C - cDim, 0), std::min(NOUTSPoint_C, 1),
458 idata = idata > 0 ? idata + cDim : 0;
461 [&](
int idata,
index iv)
463 idata = idata > 0 ? idata + cDim : 0;
464 return (*outDist)[iv][idata];
470 [&](
int idata,
index iv,
int idim)
472 return idim < cDim ? (*outDist)[iv][1 + idim] : 0.0;
476 idata = idata > 0 ? idata + cDim : 0;
477 return namesPoint[idata];
479 [&](
int idata,
index iv)
481 idata = idata > 0 ? idata + cDim : 0;
482 return outDistPointPair[iv][idata];
488 [&](
int idata,
index iv,
int idim)
490 return idim < cDim ? outDistPointPair[iv][1 + idim] : 0.0;
493 MPI_Comm_free(&commDup1);
501 fOuts.push_back(outRun);
505 if (config.dataIOControl.outBndData)
508 std::lock_guard<std::mutex> outBndLock(outBndArraysMutex);
510 for (
index iB = 0; iB < meshBnd->NumCell(); iB++)
517 index iBnd = meshBnd->cell2parentCell.at(iB);
518 index iCell = mesh->bnd2cell[iBnd][0];
519 index iFace = mesh->bnd2faceV.at(iBnd);
523 (*outDistBnd)[iB](nOUTSBnd - 4) = meshBnd->GetCellZone(iB);
526 TU recu = uOut[iCell];
527 if (eval.settings.frameConstRotation.enabled)
528 eval.TransformURotatingFrame_ABS_VELO(recu, vfv->GetCellQuadraturePPhys(iCell, -1), -1);
529 TVec velo = (recu(Seq123).array() / recu(0)).matrix();
532 Gas::IdealGasThermal(recu(I4), recu(0), vsqr, eval.settings.idealGasProperty.gamma, p, asqr, H);
534 real M = std::sqrt(std::abs(vsqr / asqr));
535 real T = p / recu(0) / eval.settings.idealGasProperty.Rgas;
537 (*outDistBnd)[iB][0] = recu(0);
538 for (
int i = 0; i < dim; i++)
539 (*outDistBnd)[iB][i + 1] =
velo(i);
540 (*outDistBnd)[iB][I4 + 0] = p;
541 (*outDistBnd)[iB][I4 + 1] = T;
542 (*outDistBnd)[iB][I4 + 2] = M;
543 for (
int i = I4 + 1; i < nVars; i++)
545 (*outDistBnd)[iB][2 + i] = recu(i) / recu(0);
553 (*outDistBnd)[iB](Eigen::seq(nVars + 2, nVars + 2 + nVars - 1)) = eval.fluxBnd.at(iBnd);
556 fluxT(Seq012) = eval.fluxBndForceT.at(iBnd);
557 (*outDistBnd)[iB](Eigen::seq(nVars + 2 + nVars, nVars + 2 + nVars + 3 - 1)) = fluxT;
559 (*outDistBnd)[iB](nOUTSBnd - 4) = meshBnd->GetCellZone(iB);
560 (*outDistBnd)[iB](Eigen::seq(nOUTSBnd - 3, nOUTSBnd - 1)) = vfv->GetFaceNorm(iFace, 0) * vfv->GetFaceArea(iFace);
565 if (config.dataIOControl.outPltMode == 0)
567 outDist2SerialTransBnd.startPersistentPull();
568 outDist2SerialTransBnd.waitPersistentPull();
571 int NOUTS_C{0}, NOUTSPoint_C{0};
575 std::vector<std::string> names;
576 std::vector<std::string> namesScalar;
577 std::vector<std::string> namesVector;
578 std::vector<int> offsetsScalar;
579 std::vector<int> offsetsVector;
580 if constexpr (dim == 2)
582 "R",
"U",
"V",
"P",
"T",
"M"};
585 "R",
"U",
"V",
"W",
"P",
"T",
"M"};
586 namesScalar = {
"R",
"P",
"T",
"M"};
587 offsetsScalar = {0, dim + 1, dim + 2, dim + 3};
588 namesVector = {
"Velo"};
590 int currentTop = dim + 4;
591 for (
int i = I4 + 1; i < nVars; i++)
593 names.push_back(
"V" + std::to_string(i - I4));
594 namesScalar.push_back(
"V" + std::to_string(i - I4));
595 offsetsScalar.push_back(currentTop++);
597 for (
int i = 0; i < nVars; i++)
599 names.push_back(
"F" + std::to_string(i));
600 namesScalar.push_back(
"F" + std::to_string(i));
601 offsetsScalar.push_back(currentTop++);
603 names.push_back(
"FT1");
604 names.push_back(
"FT2");
605 names.push_back(
"FT3");
606 namesVector.push_back(
"FT");
607 offsetsVector.push_back(currentTop), currentTop += 3;
608 names.push_back(
"FaceZone");
609 namesScalar.push_back(
"FaceZone");
610 offsetsScalar.push_back(currentTop++);
611 names.push_back(
"N0");
612 names.push_back(
"N1");
613 names.push_back(
"N2");
614 namesVector.push_back(
"Norm");
615 offsetsVector.push_back(currentTop), currentTop += 3;
617 if (config.dataIOControl.outPltTecplotFormat)
620 if (config.dataIOControl.outPltMode == 0)
622 auto outBndRun = [meshBnd = meshBnd, readerBnd = readerBnd, outDistBnd = outDistBnd, outSerialBnd = outSerialBnd,
623 fname, fnameSeries, NOUTS_C, nOUTSBnd = nOUTSBnd, cDim, names, tSimu,
624 &outBndArraysMutex = outBndArraysMutex]()
626 std::lock_guard<std::mutex> outBndArraysLock(outBndArraysMutex);
627 readerBnd->PrintSerialPartPltBinaryDataArray(
631 {
return names.at(idata); },
632 [&](
int idata,
index iv)
634 return (*outSerialBnd)[iv][idata];
638 [&](
int idata,
index in)
639 {
return std::nan(
"0"); },
648 else if (config.dataIOControl.outPltMode == 1)
650 auto outBndRun = [meshBnd = meshBnd, readerBnd = readerBnd, outDistBnd = outDistBnd, outSerialBnd = outSerialBnd,
651 fname, fnameSeries, NOUTS_C, nOUTSBnd = nOUTSBnd, cDim, names, tSimu,
652 &outBndArraysMutex = outBndArraysMutex]()
654 std::lock_guard<std::mutex> outBndArraysLock(outBndArraysMutex);
655 readerBnd->PrintSerialPartPltBinaryDataArray(
659 {
return names.at(idata); },
660 [&](
int idata,
index iv)
662 return (*outDistBnd)[iv][idata];
666 [&](
int idata,
index in)
667 {
return std::nan(
"0"); },
678 const int cDim = dim;
679 if (config.dataIOControl.outPltVTKFormat)
682 if (config.dataIOControl.outPltMode == 0)
684 auto outBndRun = [meshBnd = meshBnd, readerBnd = readerBnd, outDistBnd = outDistBnd, outSerialBnd = outSerialBnd,
685 fname, fnameSeries, NOUTS_C, nOUTSBnd = nOUTSBnd, nVars = nVars, cDim,
686 namesScalar, namesVector, offsetsScalar, offsetsVector, tSimu,
687 &outBndArraysMutex = outBndArraysMutex]()
689 std::lock_guard<std::mutex> outBndArraysLock(outBndArraysMutex);
690 readerBnd->PrintSerialPartVTKDataArray(
692 fnameSeries.size() ? fnameSeries +
"_bnd" :
"",
693 namesScalar.size(), namesVector.size(),
697 return namesScalar.at(idata);
699 [&](
int idata,
index iv)
701 return (*outSerialBnd)[iv][offsetsScalar.at(idata)];
705 return namesVector.at(idata);
707 [&](
int idata,
index iv,
int idim)
709 return (*outSerialBnd)[iv][offsetsVector.at(idata) + idim];
715 [&](
int idata,
index iv)
717 return std::nan(
"0");
723 [&](
int idata,
index iv,
int idim)
725 return std::nan(
"0");
733 fOuts.push_back(outBndRun);
735 else if (config.dataIOControl.outPltMode == 1)
737 auto outBndRun = [meshBnd = meshBnd, readerBnd = readerBnd, outDistBnd = outDistBnd, outSerialBnd = outSerialBnd,
738 fname, fnameSeries, NOUTS_C, nOUTSBnd = nOUTSBnd, cDim,
739 namesScalar, namesVector, offsetsScalar, offsetsVector, tSimu,
740 &outBndArraysMutex = outBndArraysMutex]()
742 std::lock_guard<std::mutex> outBndArraysLock(outBndArraysMutex);
743 readerBnd->PrintSerialPartVTKDataArray(
745 fnameSeries.size() ? fnameSeries +
"_bnd" :
"",
746 namesScalar.size(), namesVector.size(),
750 return namesScalar.at(idata);
752 [&](
int idata,
index iv)
754 return (*outDistBnd)[iv][offsetsScalar.at(idata)];
758 return namesVector.at(idata);
760 [&](
int idata,
index iv,
int idim)
762 return (*outDistBnd)[iv][offsetsVector.at(idata) + idim];
768 [&](
int idata,
index iv)
770 return std::nan(
"0");
776 [&](
int idata,
index iv,
int idim)
778 return std::nan(
"0");
786 fOuts.push_back(outBndRun);
790 if (config.dataIOControl.outPltVTKHDFFormat)
792 MPI_Comm commDup = MPI_COMM_NULL;
793 MPI_Comm_dup(mpi.comm, &commDup);
794 auto outBndRun = [meshBnd = meshBnd, outDistBnd = outDistBnd,
795 fname, fnameSeries, NOUTS_C, nOUTSBnd = nOUTSBnd, cDim,
796 namesScalar, namesVector, offsetsScalar, offsetsVector, tSimu,
797 &outBndArraysMutex = outBndArraysMutex, commDup]()
802 std::scoped_lock lock(outBndArraysMutex,
HDF_mutex);
803 MPI_Comm commDup1 = commDup;
804 meshBnd->PrintParallelVTKHDFDataArray(
806 fnameSeries.size() ? fnameSeries +
"_bnd" :
"",
807 namesScalar.size(), namesVector.size(),
811 return namesScalar.at(idata);
813 [&](
int idata,
index iv)
815 return (*outDistBnd)[iv][offsetsScalar.at(idata)];
819 return namesVector.at(idata);
821 [&](
int idata,
index iv,
int idim)
823 return (*outDistBnd)[iv][offsetsVector.at(idata) + idim];
829 [](
int idata,
index iv)
831 return std::nan(
"0");
837 [](
int idata,
index iv,
int idim)
839 return std::nan(
"0");
842 MPI_Comm_free(&commDup1);
848 fOuts.push_back(outBndRun);
852 auto runFOuts = [fOuts]()
854 for (
auto &f : fOuts)
857 bool useAsyncOut = config.dataIOControl.allowAsyncPrintData;
858#ifndef H5_HAVE_THREADSAFE
859 if (config.dataIOControl.outPltVTKHDFFormat)
862 if (config.dataIOControl.outPltVTKHDFFormat)
867 if (outSeqFuture.valid())
870 outSeqFuture = std::async(std::launch::async, runFOuts);