34template <MInt nDim,
class SolverType>
47 const MInt NotUsed(fileNo),
48 std::vector<MFloat>& NotUsed(coordinates)) {
49 TERMM(1,
"ERROR: not implemented in base class");
54 TERMM(1,
"ERROR: not implemented in base class");
67 const MString fileName = Context::getSolverProperty<MString>(propName,
solverId(), AT_);
68 return fileName !=
"";
78 virtual MString getInputDataFile(
const MInt fileNo)
const {
93 return Context::getSolverProperty<MString>(propName,
solverId(), AT_);
98 TERMM(1,
"Not implemented in derived class!");
104 MFloat*
const NotUsed(coordinates)) {
105 TERMM(1,
"Not implemented in derived class!");
163template <MInt nDim,
class SolverType>
180 std::vector<MFloat>& coordinates)
override;
189template <MInt nDim,
class SolverType>
219template <MInt nDim,
class SolverType>
246 const MString shape = Context::getSolverProperty<MString>(propName,
solverId(), AT_);
282 const MInt writeInterval,
const MInt startTimeStep,
const MInt endTimeStep,
const MInt noFile)
347template <MInt nDim,
class SolverType>
352 const MString type = getBaseName();
362 m_enabled = Context::getSolverProperty<MBool>(type +
"DataEnabled", solverId(), AT_);
369 if(hasInputDataFile(0)) {
373 MInt sampleIntervalGlobal = 1;
387 sampleIntervalGlobal =
388 Context::getSolverProperty<MInt>(type +
"DataSampleInterval", solverId(), AT_, &sampleIntervalGlobal);
403 MInt writeIntervalGlobal = -1;
404 const MInt restartInterval = m_solver.restartInterval();
405 if(restartInterval > 0) {
406 writeIntervalGlobal =
407 Context::getSolverProperty<MInt>(type +
"DataWriteInterval", solverId(), AT_, &restartInterval);
409 writeIntervalGlobal =
410 Context::getSolverProperty<MInt>(type +
"DataWriteInterval", solverId(), AT_, &writeIntervalGlobal);
426 MInt startTimeStepGlobal = 0;
427 startTimeStepGlobal =
428 Context::getSolverProperty<MInt>(type +
"DataStartTimeStep", solverId(), AT_, &startTimeStepGlobal);
443 MInt endTimeStepGlobal = std::numeric_limits<MInt>::max();
444 endTimeStepGlobal = Context::getSolverProperty<MInt>(type +
"DataEndTimeStep", solverId(), AT_, &endTimeStepGlobal);
446 m_solverSamplingVarIds.clear();
447 m_noSolverSamplingVars.clear();
448 m_solverSamplingVarNames.clear();
450 solver().getSolverSamplingProperties(m_solverSamplingVarIds, m_noSolverSamplingVars, m_solverSamplingVarNames);
453 solver().initSolverSamplingVariables(m_solverSamplingVarIds, m_noSolverSamplingVars);
459 while(hasInputDataFile(noFiles)) {
460 const MString samplingDataFileName = getInputDataFile(noFiles);
463 MBool genPoints =
false;
464 if(samplingDataFileName ==
"") {
465 genPoints = generatePoints();
477 genPoints = Context::getSolverProperty<MBool>(type +
"DataGeneratePoints_" + std::to_string(noFiles),
478 solverId(), AT_, &genPoints);
494 const MInt sampleInterval = Context::getSolverProperty<MInt>(
495 type +
"DataSampleInterval_" + std::to_string(noFiles), solverId(), AT_, &sampleIntervalGlobal);
497 const MInt writeInterval = Context::getSolverProperty<MInt>(type +
"DataWriteInterval_" + std::to_string(noFiles),
498 solverId(), AT_, &writeIntervalGlobal);
500 if(sampleInterval < 1) {
501 TERMM(1, type +
"DataSampleInterval must be a positive integer.");
504 if(writeInterval < 1) {
506 +
"DataWriteInterval musst be a positive integer. Check if "
507 "all write intervals are set.");
510 if(writeInterval % sampleInterval != 0) {
511 TERMM(1,
"samplingDataSampleInterval must be a divisor of "
512 "samplingDataWriteInterval (default value: restartInterval) for "
513 "technical reasons. Also it makes more sense this way.");
515 if(m_solver.restartInterval() > 0 && m_solver.restartInterval() % writeInterval != 0) {
517 +
"DataWriteInterval must be a divisor of restartInterval because otherwise "
518 "restarting a simulation without data loss is not possible.");
522 const MInt startTimeStep = Context::getSolverProperty<MInt>(type +
"DataStartTimeStep_" + std::to_string(noFiles),
523 solverId(), AT_, &startTimeStepGlobal);
524 if(startTimeStep < 0) {
526 "Point data recording start time step is negative. It must have "
527 "a positive value.");
530 const MInt endTimeStep = Context::getSolverProperty<MInt>(type +
"DataEndTimeStep_" + std::to_string(noFiles),
531 solverId(), AT_, &endTimeStepGlobal);
533 if(endTimeStep < 0) {
534 TERMM(1,
"Point data recording end time step is negative. It must have "
535 "a positive value.");
537 if(endTimeStep < startTimeStep) {
539 "End time step of point data recording is smaller than start time"
540 " step of point data recording. Check your property file.");
543 m_interpolatePointData =
true;
545 m_interpolatePointData =
546 Context::getSolverProperty<MBool>(
"interpolatePointData", solverId(), AT_, &m_interpolatePointData);
550 readAdditionalProperties(noFiles);
553 SamplingDataSeries samplingData(samplingDataFileName, genPoints, sampleInterval, writeInterval, startTimeStep,
554 endTimeStep, noFiles);
556 m_timeSeries.push_back(samplingData);
570template <MInt nDim,
class SolverType>
572 if(!m_enabled || !solver().isActive()) {
576 for(
MUint i = 0; i < m_timeSeries.size(); i++) {
577 init(m_timeSeries[i]);
589template <MInt nDim,
class SolverType>
591 using namespace maia;
598 std::vector<std::tuple<std::array<MFloat, nDim>,
MInt,
MInt>> localTmpPoints;
600 m_log <<
"Solver #" << solverId() <<
": ";
603 m_log <<
"Loading points for " << getBaseName() <<
" data class...";
605 std::vector<MFloat> tmpCoordinates{};
615 TERMM(1,
"ERROR: no sampling points found for input file '" + timeSeries.
m_inputFileName +
"'");
616 m_log <<
"ERROR: no sampling points found for input file '" << timeSeries.
m_inputFileName <<
"'" << std::endl;
622 copy(tmpCoordinates.begin(), tmpCoordinates.end(), coordinatesScratch.
begin());
625 "coordinatesScratch[0]");
630 std::array<MFloat, nDim> curCoordinates{};
631 MInt curElementId = -1;
633 for(
MInt j = 0; j < nDim; j++) {
634 curCoordinates[j] = tmpCoordinatesTensor(i, j);
638 curElementId = solver().getIdAtPoint(&curCoordinates[0],
true);
640 if(curElementId != -1) {
641 localTmpPoints[timeSeries.
m_noLocalPoints] = make_tuple(curCoordinates, curElementId, i);
645 solver().initInterpolationForCell(curElementId);
651 loadedPointsVector.
fill(0);
653 loadedPointsVector[get<2>(localTmpPoints[i])]++;
658 0, mpiComm(), AT_,
"MPI_IN_PLACE",
"loadedPointsVector[0]");
659 for(
MUint i = 0; i < loadedPointsVector.
size(); i++) {
660 if(loadedPointsVector[i] != 1) {
661 std::ostringstream err;
662 err <<
"Point at line " << i + 1 <<
" of file "
663 << timeSeries.
m_inputFileName <<
" was loaded " << loadedPointsVector[i] <<
" times. Aborting."
670 mpiComm(), AT_,
"loadedPointsVector[0]",
"nullptr");
673 m_log <<
"Generating points for " << getBaseName() <<
" data class...";
676 const MInt noPoints = noSamplingPoints(timeSeries.
m_fileNo);
679 std::array<MFloat, nDim> coordinates{};
682 for(
MInt i = 0; i < noPoints; i++) {
684 getSamplingPoint(timeSeries.
m_fileNo, i, &coordinates[0]);
687 const MInt curElementId = solver().getIdAtPoint(&coordinates[0],
true);
688 if(curElementId != -1) {
689 localTmpPoints.push_back(make_tuple(coordinates, curElementId, i));
694 solver().initInterpolationForCell(curElementId);
700 "MPI_IN_PLACE",
"globalNoPoints");
701 if(globalNoPoints != noPoints) {
702 TERMM(1,
"Global number of points does not match " + std::to_string(globalNoPoints)
703 +
" != " + std::to_string(noPoints));
711 const MLong noPointsTmp = noPoints;
712 if(2 * checkSum != (noPointsTmp * noPointsTmp + noPointsTmp)) {
713 TERMM(1,
"Incorrect check sum for " + std::to_string(noPoints) +
" points: " + std::to_string(checkSum));
716 m_log <<
"Warning: no sampling data input file specified and generation of points disabled." << std::endl;
727 MPI_Comm_rank(mpiComm(), &rank);
732 mpiComm(), AT_,
"rank",
"pointDataScratch[0]");
735 const MInt noPdDomains =
736 count_if(pointDataScratch.
begin(), pointDataScratch.
end(), [](
const MInt a) { return a != -1; });
739 for(
MUint i = 0; i < pointDataScratch.
size(); i++) {
740 if(pointDataScratch[i] != -1) {
741 pdDomains[position] = pointDataScratch[i];
747 MPI_Group globalGroup, localGroup;
749 MPI_Group_incl(globalGroup, noPdDomains, &pdDomains[0], &localGroup, AT_);
759 MPI_Comm_rank(timeSeries.
m_mpiComm, &subRank);
767 stable_sort(localTmpPoints.begin(),
770 [
this](
const std::tuple<std::array<MFloat, nDim>,
MInt,
MInt>&
a,
771 const std::tuple<std::array<MFloat, nDim>,
MInt,
MInt>&
b) {
772 return solver().grid().tree().globalId(solver().getCellIdByIndex(get<1>(a)))
773 < solver().grid().tree().globalId(solver().getCellIdByIndex(get<1>(b)));
783 for(
MInt j = 0; j < nDim; j++) {
784 coordinatesTensor(i, j) = get<0>(localTmpPoints[i])[j];
787 timeSeries.
m_sortIndex[i] = get<2>(localTmpPoints[i]);
793 saveSamplingPointCoordinates(timeSeries);
815 << getBaseName() <<
" sampling feature successfully." << std::endl;
817 m_log <<
" Generated " << timeSeries.
m_noPoints <<
" points for " << getBaseName()
818 <<
" sampling feature successfully." << std::endl;
831template <MInt nDim,
class SolverType>
837 for(
MUint i = 0; i < m_timeSeries.size(); i++) {
838 save(m_timeSeries[i], finalTimeStep);
854template <MInt nDim,
class SolverType>
860 || solver().getCurrentTimeStep() > timeSeries.
m_endTimeStep) {
865 if(!(solver().getCurrentTimeStep() % timeSeries.
m_sampleInterval == 0 || finalTimeStep)) {
870 solver().calcSamplingVariables(m_solverSamplingVarIds,
true);
890 MBool interpolate = m_interpolatePointData;
893 for(
MUint var = 0; var < m_solverSamplingVarIds.size(); var++) {
894 solver().calcSamplingVarAtPoint(&coordinatesTensorBuf(i, 0), timeSeries.
m_elementIds[i],
895 m_solverSamplingVarIds[var], &stateTensorBuf(i, timeSeries.
m_sampleIndex, offset),
897 offset += m_noSolverSamplingVars[var];
904 MBool isFirstDataFile =
false;
910 if(solver().getCurrentTimeStep() >= 0 && solver().getCurrentTimeStep() <= timeSeries.
m_writeInterval) {
911 isFirstDataFile =
true;
914 const MBool isRestartStep =
915 (solver().restartInterval() > 0 && solver().getCurrentTimeStep() % solver().restartInterval() == 0);
917 const MBool writeAtRestartStep = (isRestartStep && !isFirstSample);
922 if(!(writeDataFile || finalTimeStep || writeAtRestartStep || writeFirstDataFile)) {
932 if(finalTimeStep && !(solver().getCurrentTimeStep() % timeSeries.
m_writeInterval == 0)) {
937 if(!finalTimeStep || (solver().getCurrentTimeStep() % timeSeries.
m_writeInterval == 0)) {
940 fileNo = ceil((
static_cast<MFloat>(sampleCount - 1)
945 std::ostringstream fileName;
946 MString baseFileName = getFileBaseName();
947 fileName << solver().outputDir() << baseFileName << std::to_string(timeSeries.
m_fileNo) <<
"_" << setw(8)
948 << setfill(
'0') << fileNo << ParallelIo::fileExt();
952 file.defineArray(PIO_INT,
"timeStep", timeSeries.
m_sampleIndex);
953 file.defineArray(PIO_FLOAT,
"time", timeSeries.
m_sampleIndex);
954 file.defineArray(PIO_INT,
"sortIndex", timeSeries.
m_noPoints);
956 file.setAttribute(
"si[i] = index in input",
"description",
"sortIndex");
959 file.defineArray(PIO_FLOAT,
"pointStates", 3, &dimSizes[0]);
961 std::ostringstream descPs;
965 file.setAttribute(descPs.str(),
"description",
"pointStates");
966 file.setAttribute(
"point index",
"dim_0",
"pointStates");
967 file.setAttribute(
"sample index",
"dim_1",
"pointStates");
968 file.setAttribute(
"var index",
"dim_2",
"pointStates");
969 file.setAttribute(timeSeries.
m_inputFileName,
"inputFileName",
"pointStates");
972 for(
MUint var = 0; var < m_solverSamplingVarIds.size(); var++) {
973 for(
MInt i = 0; i < m_noSolverSamplingVars[var]; i++) {
974 file.setAttribute(m_solverSamplingVarNames[var][i],
"var_" + std::to_string(varOffset + i),
"pointStates");
976 varOffset += m_noSolverSamplingVars[var];
987 for(
MInt k = 0; k < noVars(); k++) {
988 finalStateTensor(i, j, k) = stateTensor(i, j, k);
998 file.setOffset(0, 0);
1004 ParallelIo::size_type offset, totalCount;
1009 file.writeArray(&timeSeries.
m_sortIndex[0],
"sortIndex");
1013 file.writeArray(&timeSeries.
m_stateBuffer[0],
"pointStates");
1022template <MInt nDim,
class SolverType>
1024 const MInt noPoints2D = nPoints[0] * nPoints[1];
1025 const MInt maxNoPoints = (nDim == 2) ? noPoints2D : noPoints2D * nPoints[2];
1026 if(index < 0 || index >= maxNoPoints) {
1027 TERMM(1,
"invalid index: " + std::to_string(index));
1031 indexXD[nDim - 1] = index % nPoints[nDim - 1];
1033 indexXD[nDim - 2] = ((index - indexXD[nDim - 1]) / nPoints[nDim - 1]) % nPoints[nDim - 2];
1034 IF_CONSTEXPR(nDim == 3) {
1036 indexXD[0] = (index - indexXD[1] * nPoints[1] - indexXD[2]) / (nPoints[2] * nPoints[1]);
1043template <MInt nDim,
class SolverType>
1048 std::ostringstream fileName;
1049 fileName << solver().outputDir() << getFileBaseName() <<
"coordinates_" << timeSeries.
m_fileNo
1050 << ParallelIo::fileExt();
1054 file.setAttribute(nDim,
"nDim");
1056 file.defineArray(PIO_INT,
"sortIndex", timeSeries.
m_noPoints);
1057 file.setAttribute(
"si[i] = index in input",
"description",
"sortIndex");
1059 ParallelIo::size_type dimSizes[] = {timeSeries.
m_noPoints, nDim};
1060 file.defineArray(PIO_FLOAT,
"coordinates", 2, &dimSizes[0]);
1062 ParallelIo::size_type offset, totalCount;
1067 file.writeArray(&timeSeries.
m_sortIndex[0],
"sortIndex");
1071 file.writeArray(&timeSeries.
m_coordinates[0],
"coordinates");
1076template <MInt nDim,
class SolverType>
1078 const MInt NotUsed(fileNo),
1079 std::vector<MFloat>& coordinates) {
1082 TERMM(1,
"PointData::loadInputFile() should only be called by mpi root process!");
1090template <MInt nDim,
class SolverType>
1093 if(m_geometry !=
nullptr) {
1105template <MInt nDim,
class SolverType>
1108 std::vector<MFloat>& coordinates) {
1111 TERMM(1,
"SurfaceData::loadInputFile() should only be called by mpi root process!");
1117 m_geometry = geometry;
1120 MInt noElements = geometry->GetNoElements();
1121 coordinates.resize(nDim * noElements);
1123 std::array<MFloat, nDim * nDim> vertex;
1126 for(
MInt i = 0; i < noElements; i++) {
1127 geometry->elements[i].getVertices(&vertex[0]);
1128 geometry->elements[i].calcCentroid(&vertex[0], &coordinates[i * nDim]);
1132 saveGeomInfo(inputFileName, fileNo, &coordinates[0]);
1151template <MInt nDim,
class SysEqn>
1156 const MInt noElements = m_geometry->GetNoElements();
1158 std::ostringstream fileName;
1159 fileName << solver().outputDir() <<
"surface_geometryInfo_" << fileNo << ParallelIo::fileExt();
1161 ParallelIo file(fileName.str(), PIO_REPLACE, MPI_COMM_SELF);
1162 file.setAttribute(inputFileName,
"inputFileName");
1165 std::vector<MFloat> vertices(noElements * nDim * nDim);
1166 std::vector<MFloat> geomMeasures(noElements);
1167 std::vector<MFloat> normalVecs(noElements * nDim);
1173 for(
MInt i = 0; i < nDim; i++) {
1175 Context::getSolverProperty<MFloat>(
"surfaceDataGeometryCenter_" + std::to_string(fileNo), solverId(), AT_, i);
1179 for(
MInt i = 0; i < noElements; i++) {
1180 for(
MInt dim = 0; dim < nDim; dim++) {
1181 geomCenter[dim] += coordinates[i * nDim + dim];
1184 for(
MInt dim = 0; dim < nDim; dim++) {
1185 geomCenter[dim] /=
static_cast<MFloat>(noElements);
1189 m_log <<
"Surface geometry info: geomCenter =";
1190 for(
MInt dim = 0; dim < nDim; dim++) {
1191 m_log <<
" " << geomCenter[dim];
1196 for(
MInt i = 0; i < noElements; i++) {
1197 for(
MInt j = 0; j < nDim; j++) {
1198 for(
MInt k = 0; k < nDim; k++) {
1199 vertices[counter] = m_geometry->elements[i].m_vertices[j][k];
1204 auto&
element = m_geometry->elements[i];
1206 IF_CONSTEXPR(nDim == 3) {
1216 const MFloat v_x = v12_y * v13_z - v12_z * v13_y;
1217 const MFloat v_y = v12_z * v13_x - v12_x * v13_z;
1218 const MFloat v_z = v12_x * v13_y - v12_y * v13_x;
1220 geomMeasures[i] = 0.5 * sqrt(pow(v_x, 2) + pow(v_y, 2) + pow(v_z, 2));
1228 geomMeasures[i] = sqrt(pow(p1_x - p2_x, 2) + pow(p1_y - p2_y, 2));
1231 std::array<MFloat, nDim * nDim> vertex;
1232 m_geometry->elements[i].getVertices(&vertex[0]);
1235 m_geometry->elements[i].calcNormal(&vertex[0], &normalVecs[i * nDim]);
1240 for(
MInt k = 0; k < nDim; k++) {
1241 const MFloat vecCenter = coordinates[i * nDim + k] - geomCenter[k];
1242 dotProduct += normalVecs[i * nDim + k] * vecCenter;
1247 if(!(dotProduct > 0)) {
1248 for(
MInt k = 0; k < nDim; k++) {
1249 normalVecs[i * nDim + k] = -normalVecs[i * nDim + k];
1254 const MFloat totalGeomMeasure = std::accumulate(geomMeasures.begin(), geomMeasures.end(), 0.0);
1255 const MString measure = (nDim == 3) ?
"area" :
"length";
1256 m_log <<
"Total segment " << measure <<
": " << totalGeomMeasure << std::endl;
1259 std::stringstream dumpFileName;
1260 dumpFileName << solver().outputDir() <<
"surface_geometryInfo_" << fileNo <<
".dump";
1263 datei = fopen(dumpFileName.str().c_str(),
"w");
1265 for(
MInt i = 0; i < noElements; i++) {
1266 fprintf(datei,
"%d", i);
1268 for(
MInt j = 0; j < nDim; j++) {
1269 fprintf(datei,
" %.8f", coordinates[i * nDim + j]);
1272 for(
MInt j = 0; j < nDim; j++) {
1273 fprintf(datei,
" %.8f", normalVecs[i * nDim + j]);
1275 fprintf(datei,
"\n");
1279 const MInt sizeArray1 = noElements * nDim;
1280 const MInt sizeArray2 = noElements * nDim * nDim;
1283 file.defineArray(PIO_FLOAT,
"vertices", sizeArray2);
1284 file.defineArray(PIO_FLOAT,
"centroid", sizeArray1);
1285 file.defineArray(PIO_FLOAT,
"normalVector", sizeArray1);
1287 file.defineArray(PIO_FLOAT,
"geomMeasure", noElements);
1288 IF_CONSTEXPR(nDim == 3) { file.setAttribute(
"area",
"description",
"geomMeasure"); }
1290 file.setAttribute(
"length",
"description",
"geomMeasure");
1293 file.setOffset(sizeArray2, 0);
1294 file.writeArray(&vertices[0],
"vertices");
1296 file.setOffset(sizeArray1, 0);
1297 file.writeArray(&coordinates[0],
"centroid");
1299 file.setOffset(sizeArray1, 0);
1300 file.writeArray(&normalVecs[0],
"normalVector");
1302 file.setOffset(noElements, 0);
1303 file.writeArray(&geomMeasures[0],
"geomMeasure");
1308template <MInt nDim,
class SolverType>
1313 Context::getSolverProperty<MString>(getBaseName() +
"DataShape_" + std::to_string(fileNo), solverId(), AT_);
1315 MInt noInputValuesFloat = -1;
1316 MInt noInputValuesInt = -1;
1318 if(volumeShape ==
"box") {
1320 noInputValuesFloat = 2 * nDim;
1321 noInputValuesInt = nDim;
1322 }
else if(volumeShape ==
"cylinder") {
1323 IF_CONSTEXPR(nDim == 2) { TERMM(1,
"Cylinder shape not defined in 2D."); }
1325 noInputValuesFloat = nDim + 2;
1330 noInputValuesInt = nDim + 1;
1332 TERMM(1,
"Unknown volume data shape: " + volumeShape);
1334 m_volumeShape.push_back(volumeShape);
1336 if(noInputValuesFloat < 1 || noInputValuesInt < 1) {
1337 TERMM(1,
"Invalid number of input values for volume data shape " + volumeShape +
": "
1338 + std::to_string(noInputValuesFloat) +
" " + std::to_string(noInputValuesInt));
1341 m_log <<
"Volume data #" << fileNo <<
": " << volumeShape <<
" with parameters";
1344 std::vector<MFloat> paramFloat(noInputValuesFloat);
1345 for(
MInt i = 0; i < noInputValuesFloat; i++) {
1346 paramFloat[i] = Context::getSolverProperty<MFloat>(getBaseName() +
"DataParameterFloat_" + std::to_string(fileNo),
1347 solverId(), AT_, i);
1348 m_log <<
" " << paramFloat[i];
1350 m_volumeParameterFloat.push_back(paramFloat);
1353 std::vector<MInt> paramInt(noInputValuesInt);
1354 for(
MInt i = 0; i < noInputValuesInt; i++) {
1355 paramInt[i] = Context::getSolverProperty<MInt>(getBaseName() +
"DataParameterInt_" + std::to_string(fileNo),
1356 solverId(), AT_, i);
1357 m_log <<
" " << paramInt[i];
1359 m_volumeParameterInt.push_back(paramInt);
1366template <MInt nDim,
class SolverType>
1371 if(m_volumeShape[fileNo] ==
"box") {
1373 for(
MInt i = 0; i < nDim; i++) {
1374 noPoints *= m_volumeParameterInt[fileNo][i];
1376 }
else if(m_volumeShape[fileNo] ==
"cylinder") {
1379 m_volumeParameterInt[fileNo][0] * (m_volumeParameterInt[fileNo][1] * m_volumeParameterInt[fileNo][2] + 1);
1381 TERMM(1,
"Unknown volume data shape: " + m_volumeShape[fileNo]);
1389template <MInt nDim,
class SolverType>
1393 if(pointId < 0 || pointId > noSamplingPoints(fileNo)) {
1394 TERMM(1,
"Invalid point id");
1398 std::vector<MInt> indexNd(3);
1399 if(m_volumeShape[fileNo] ==
"box") {
1401 indexXD(pointId, &m_volumeParameterInt[fileNo][0], &indexNd[0]);
1403 for(
MInt i = 0; i < nDim; i++) {
1404 const MFloat minCoord = m_volumeParameterFloat[fileNo][i];
1405 const MFloat maxCoord = m_volumeParameterFloat[fileNo][nDim + i];
1406 const MFloat delta = (maxCoord - minCoord) /
static_cast<MFloat>(m_volumeParameterInt[fileNo][i] - 1);
1407 coordinates[i] = minCoord + indexNd[i] * delta;
1409 }
else if(m_volumeShape[fileNo] ==
"cylinder") {
1413 const MInt nPointsPerCirc = m_volumeParameterInt[fileNo][1] * m_volumeParameterInt[fileNo][2] + 1;
1414 indexNd[0] = floor(pointId / nPointsPerCirc);
1416 const MInt tmpIndex = pointId - indexNd[0] * nPointsPerCirc;
1417 indexNd[1] = ceil(
static_cast<MFloat>(tmpIndex) /
static_cast<MFloat>(m_volumeParameterInt[fileNo][2]));
1418 indexNd[2] = std::max((tmpIndex - 1) % m_volumeParameterInt[fileNo][2], 0);
1420 const MInt dir = m_volumeParameterInt[fileNo][3];
1421 const MInt dir2 = (dir == 0) ? 1 : 0;
1422 const MInt dir3 = 3 - dir - dir2;
1424 const MFloat* startPos = &m_volumeParameterFloat[fileNo][0];
1425 const MFloat nz =
static_cast<MFloat>(m_volumeParameterInt[fileNo][0]);
1426 const MFloat dist_z =
static_cast<MFloat>(indexNd[0]) * (startPos[3] - startPos[dir]) / (nz - 1);
1428 const MFloat r = m_volumeParameterFloat[fileNo][4];
1429 const MFloat nr = m_volumeParameterInt[fileNo][1];
1430 const MFloat dist_r =
static_cast<MFloat>(indexNd[1]) * r / nr;
1432 const MFloat nphi = m_volumeParameterInt[fileNo][2];
1433 const MFloat phi =
static_cast<MFloat>(indexNd[2]) * 2.0 * PI / nphi;
1435 coordinates[dir] = startPos[dir] + dist_z;
1436 coordinates[dir2] = startPos[dir2] + dist_r * sin(phi);
1437 coordinates[dir3] = startPos[dir3] + dist_r * cos(phi);
1439 TERMM(1,
"Unknown volume data shape: " + m_volumeShape[fileNo]);
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
This class is responsible for the point data feature. It records the state of all sampling variables ...
MInt loadInputFile(const MString inputFileName, const MInt NotUsed(fileNo), std::vector< MFloat > &coordinates) override
Loads an input file with points for the point data feature.
PointData(SolverType &solver_)
MString getBaseName() const override
Return base name of derived class, e.g. used for naming properties and output file names.
This base class is responsible for the sampling data feature that provides the required general metho...
void init(SamplingDataSeries &timeSeries)
std::vector< SamplingDataSeries > m_timeSeries
Holds all properties and buffers for each input file.
virtual MBool generatePoints() const
Default behaviour for point generation which can be overwritten in derived class.
virtual MString getBaseName() const
Return base name of derived class, e.g. used for naming properties and output file names.
std::vector< MInt > m_solverSamplingVarIds
List of sampling variables.
virtual MBool hasInputDataFile(const MInt fileNo) const
Check if an input file exists, might be overwritten in derived class if points are generated.
virtual MInt loadInputFile(const MString NotUsed(inputFileName), const MInt NotUsed(fileNo), std::vector< MFloat > &NotUsed(coordinates))
const SolverType & solver() const
MBool m_interpolatePointData
void setInputOutputProperties()
virtual void getSamplingPoint(const MInt NotUsed(fileNo), const MInt NotUsed(pointId), MFloat *const NotUsed(coordinates))
Return the coordinates of the sampling point with the given id when generating points.
void save(SamplingDataSeries &timeSeries, MBool finalTimeStep)
Saves sampling data Saves all states of conservative variables at specified points....
SolverType & solver()
Return reference to solver.
virtual MInt noSamplingPoints(const MInt NotUsed(fileNo))
Return the number of sampling points which are generated by the derived class (no input file)
MString getFileBaseName() const
Return base name of files for used sampling feature.
std::vector< MInt > m_noSolverSamplingVars
Number of variables for each sampling variable.
void save(MBool finalTimestep)
MInt noVars() const
Return total number of sampling variables.
void saveSamplingPointCoordinates(SamplingDataSeries &timeSeries)
Save point coordinates of time series.
SamplingData(SolverType &solver)
std::vector< std::vector< MString > > m_solverSamplingVarNames
List of variable names for each sampling variable.
void indexXD(const MInt index, const MInt *const nPoints, MInt *indexXD)
Convert 1D index into 2D/3D index.
virtual void readAdditionalProperties(const MInt NotUsed(fileNo))
Read additional properties which are required by the derived class.
This auxiliary class contains buffers and properties for each input file.
std::vector< MInt > m_elementIds
std::vector< MFloat > m_coordinates
const MInt m_writeInterval
std::vector< MInt > m_timeStepBuffer
std::vector< MFloat > m_stateBuffer
const MInt m_startTimeStep
std::vector< MInt > m_sortIndex
const MInt m_sampleInterval
SamplingDataSeries(const MString inputFileName, const MBool generatePoints, const MInt sampleInterval, const MInt writeInterval, const MInt startTimeStep, const MInt endTimeStep, const MInt noFile)
const MString m_inputFileName
const MBool m_generatePoints
std::vector< MFloat > m_timeBuffer
This class is a ScratchSpace.
void fill(T val)
fill the scratch with a given value
Surface data sampling class. Records all sampling variables on all surface elements and outputs addit...
MInt loadInputFile(const MString inputFileName, const MInt fileNo, std::vector< MFloat > &coordinates) override
Load an input file for the surface data sampling feature.
SurfaceData(SolverType &solver_)
GeometryXD< nDim >::type * m_geometry
MString getBaseName() const override
Return base name of derived class, e.g. used for naming properties and output file names.
void saveGeomInfo(const MString inputFileName, const MInt fileNo, MFloat *coordinates)
Store geometric information for all elements of a surface.
Class to handle sampling of volume data.
MString getBaseName() const override
Return base name of derived class, e.g. used for naming properties and output file names.
std::vector< std::vector< MInt > > m_volumeParameterInt
MString getInputDataFile(const MInt NotUsed(fileNo)) const
void readAdditionalProperties(const MInt fileNo) override
Read additional properties for volume sampling.
MBool generatePoints() const override
Always generate points.
void getSamplingPoint(const MInt fileNo, const MInt pointId, MFloat *const coordinates) override
Return sampling point coordinates.
std::vector< std::vector< MFloat > > m_volumeParameterFloat
MInt noSamplingPoints(const MInt fileNo) override
Return number of volume sampling points.
MBool hasInputDataFile(const MInt fileNo) const override
Points are generated not read from file, just check for property 'volumeDataShape_*'.
VolumeData(SolverType &solver_)
std::vector< MString > m_volumeShape
MInt loadPointCoordinatesFromFile(const MString inputFileName, const MInt nDim, std::vector< MFloat > &coordinates)
Loads point coordinates from an input file.
MInt globalNoDomains()
Return global number of domains.
std::basic_string< char > MString
int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newcomm, const MString &name, const MString &varname)
same as MPI_Comm_create, but updates the number of MPI communicators
int MPI_Group_incl(MPI_Group group, int n, const int ranks[], MPI_Group *newgroup, const MString &name)
same as MPI_Group_incl
int MPI_Comm_group(MPI_Comm comm, MPI_Group *group, const MString &name, const MString &varname)
same as MPI_Comm_group
int MPI_Reduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Reduce
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm, const MString &name, const MString &varname)
same as MPI_Bcast
int MPI_Allgather(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allgather
int MPI_Group_free(MPI_Group *group, const MString &name)
same as MPI_Group_free
Namespace for auxiliary functions/classes.
PARALLELIO_DEFAULT_BACKEND ParallelIo