172 std::vector<FieldDefinitionsSharedPtr> &fielddefs,
173 std::vector<std::vector<NekDouble>> &fielddata,
177 std::stringstream prfx;
178 prfx <<
m_comm->GetRank() <<
": FieldIOHdf5::v_Write(): ";
179 double tm0 = 0.0, tm1 = 0.0;
181 if (
m_comm->GetRank() == 0)
195 ASSERTL1(fielddefs.size() == fielddata.size(),
196 prfx.str() +
"fielddefs and fielddata have incompatible lengths.");
198 size_t nFields = fielddefs.size();
199 size_t nMaxFields = nFields;
203 int nprocs =
m_comm->GetSpaceComm()->GetSize();
209 max_fields_comm =
m_comm->GetSpaceComm()->CommCreateIf(
210 (nFields == nMaxFields) ? 1 : 0);
214 max_fields_comm =
m_comm->GetSpaceComm();
219 int rank =
m_comm->GetSpaceComm()->GetRank();
222 amRoot = (rank == root_rank);
230 ASSERTL1(root_rank >= 0 && root_rank < nprocs,
231 prfx.str() +
"invalid root rank.");
233 std::vector<uint64_t> decomps(nMaxFields *
MAX_DCMPS, 0);
234 std::vector<uint64_t> all_hashes(nMaxFields * nprocs, 0);
235 std::vector<uint64_t> cnts(
MAX_CNTS, 0);
236 std::vector<std::string> fieldNames(nFields);
237 std::vector<std::string> shapeStrings(nFields);
238 std::vector<std::vector<NekDouble>> homoLengths(nFields);
239 std::vector<std::vector<unsigned int>> homoSIDs(nFields), homoYIDs(nFields),
241 std::vector<std::vector<unsigned int>> numModesPerDirVar(nFields);
242 std::vector<std::string> numModesPerDirUni(nFields);
247 for (
int f = 0; f < nFields; ++f)
249 if (!fielddefs[f]->m_uniOrder)
261 for (
int f = 0; f < nFields; ++f)
265 "fielddata vector must contain at least one value.");
266 ASSERTL1(fielddata[f].size() == fielddefs[f]->m_fields.size() *
268 prfx.str() +
"fielddata vector has invalid size.");
270 std::size_t nFieldElems = fielddefs[f]->m_elementIDs.size();
271 std::size_t nElemVals = fielddata[f].size();
280 std::stringstream hashStream;
281 size_t nSubFields = fielddefs[f]->m_fields.size();
282 for (
size_t sf = 0; sf < nSubFields; ++sf)
284 hashStream << fielddefs[f]->m_fields[sf];
287 nSubFields = fielddefs[f]->m_basis.size();
288 for (
size_t sf = 0; sf < nSubFields; ++sf)
290 hashStream << fielddefs[f]->m_basis[sf];
294 std::stringstream shapeStringStream;
295 shapeStringStream <<
ShapeTypeMap[fielddefs[f]->m_shapeType];
297 if (fielddefs[f]->m_numHomogeneousDir > 0)
301 homDim = fielddefs[f]->m_numHomogeneousDir;
304 ASSERTL1(homDim == fielddefs[f]->m_numHomogeneousDir,
305 "HDF5 does not support variable homogeneous directions in "
308 shapeStringStream <<
"-HomogenousExp"
309 << fielddefs[f]->m_numHomogeneousDir <<
"D";
312 if (fielddefs[f]->m_homoStrips)
314 shapeStringStream <<
"-Strips";
317 shapeStrings[f] = shapeStringStream.str();
318 hashStream << shapeStringStream.str();
321 if (fielddefs[f]->m_numHomogeneousDir)
323 nSubFields = fielddefs[f]->m_homogeneousLengths.size();
324 homoLengths[f].resize(nSubFields);
325 for (
size_t sf = 0; sf < nSubFields; ++sf)
327 NekDouble len = fielddefs[f]->m_homogeneousLengths[sf];
329 homoLengths[f][sf] = len;
332 nSubFields = fielddefs[f]->m_homogeneousYIDs.size();
335 homoYIDs[f].resize(nSubFields);
338 for (
size_t sf = 0; sf < nSubFields; ++sf)
340 homoYIDs[f][sf] = fielddefs[f]->m_homogeneousYIDs[sf];
344 nSubFields = fielddefs[f]->m_homogeneousZIDs.size();
347 homoZIDs[f].resize(nSubFields);
350 for (
size_t sf = 0; sf < nSubFields; ++sf)
352 homoZIDs[f][sf] = fielddefs[f]->m_homogeneousZIDs[sf];
356 nSubFields = fielddefs[f]->m_homogeneousSIDs.size();
359 homoSIDs[f].resize(nSubFields);
362 for (
size_t sf = 0; sf < nSubFields; ++sf)
364 homoSIDs[f][sf] = fielddefs[f]->m_homogeneousSIDs[sf];
369 if (fielddefs[f]->m_uniOrder)
371 std::vector<unsigned int> elemModes(fielddefs[f]->m_basis.size());
373 for (
size_t i = 0; i < fielddefs[f]->m_basis.size(); ++i)
375 elemModes[i] = fielddefs[f]->m_numModes[i];
380 for (
size_t i = 0; i < nFieldElems; ++i)
382 std::copy(elemModes.begin(), elemModes.end(),
383 std::back_inserter(numModesPerDirVar[f]));
386 nFieldElems * elemModes.size();
391 std::stringstream numModesStringStream;
392 numModesStringStream <<
"UNIORDER:";
393 for (
size_t i = 0; i < elemModes.size(); i++)
397 numModesStringStream <<
",";
399 numModesStringStream << elemModes[i];
402 numModesPerDirUni[f] = numModesStringStream.str();
403 hashStream << numModesPerDirUni[f];
408 numModesPerDirVar[f] = fielddefs[f]->m_numModes;
410 fielddefs[f]->m_numModes.size();
414 std::hash<std::string> string_hasher;
415 std::stringstream fieldNameStream;
416 uint64_t fieldDefHash = string_hasher(hashStream.str());
419 all_hashes[
m_comm->GetSpaceComm()->GetRank() * nMaxFields + f] =
422 fieldNameStream << fieldDefHash;
423 fieldNames[f] = fieldNameStream.str();
427 std::vector<uint64_t> all_cnts =
428 m_comm->GetSpaceComm()->Gather(root_rank, cnts);
429 std::vector<uint64_t> all_idxs(nprocs *
MAX_IDXS, 0);
430 std::vector<uint64_t> all_decomps =
431 m_comm->GetSpaceComm()->Gather(root_rank, decomps);
432 std::vector<uint64_t> all_dsetsize(
MAX_CNTS, 0);
438 ASSERTL1(outfile, prfx.str() +
"cannot create HDF5 file.");
440 ASSERTL1(root, prfx.str() +
"cannot create root group.");
449 size_t nTotElems = 0, nTotVals = 0, nTotOrder = 0;
450 size_t nTotHomY = 0, nTotHomZ = 0, nTotHomS = 0;
451 for (
int r = 0; r < nprocs; ++r)
481 root->CreateDataSet(
"DECOMPOSITION", decomps_type, decomps_space);
483 prfx.str() +
"cannot create DECOMPOSITION dataset.");
490 root->CreateDataSet(
"ELEMENTIDS", ids_type, ids_space);
491 ASSERTL1(ids_dset, prfx.str() +
"cannot create ELEMENTIDS dataset.");
498 root->CreateDataSet(
"DATA", data_type, data_space);
499 ASSERTL1(data_dset, prfx.str() +
"cannot create DATA dataset.");
508 root->CreateDataSet(
"HOMOGENEOUSYIDS", homy_type, homy_space);
510 prfx.str() +
"cannot create HOMOGENEOUSYIDS dataset.");
520 root->CreateDataSet(
"HOMOGENEOUSZIDS", homz_type, homz_space);
522 prfx.str() +
"cannot create HOMOGENEOUSZIDS dataset.");
532 root->CreateDataSet(
"HOMOGENEOUSSIDS", homs_type, homs_space);
534 prfx.str() +
"cannot create HOMOGENEOUSSIDS dataset.");
544 root->CreateDataSet(
"POLYORDERS", order_type, order_space);
546 prfx.str() +
"cannot create POLYORDERS dataset.");
550 m_comm->GetSpaceComm()->Bcast(all_dsetsize, root_rank);
561 std::set<uint64_t> hashToProc;
564 std::map<int, std::vector<uint64_t>> writingProcs;
569 for (
int n = 0; n < nprocs; ++n)
571 for (
int i = 0; i < nMaxFields; ++i)
573 uint64_t hash = all_hashes[n * nMaxFields + i];
576 if (hashToProc.find(hash) != hashToProc.end() || hash == 0)
580 hashToProc.insert(hash);
581 writingProcs[n].push_back(hash);
586 for (
auto &sIt : writingProcs)
588 int rank = sIt.first;
591 if (
m_comm->GetSpaceComm()->GetRank() == rank)
599 ASSERTL1(outfile, prfx.str() +
"cannot open HDF5 file.");
601 ASSERTL1(root, prfx.str() +
"cannot open root group.");
605 for (
int i = 0; i < sIt.second.size(); ++i)
607 for (
int f = 0; f < nFields; ++f)
610 all_hashes[
m_comm->GetSpaceComm()->GetRank() *
613 hashToProc.find(sIt.second[i]) != hashToProc.end())
618 hashToProc.insert(sIt.second[i]);
622 root->CreateGroup(fieldNames[f]);
624 prfx.str() +
"cannot create field group.");
625 field_group->SetAttribute(
"FIELDS", fielddefs[f]->m_fields);
626 field_group->SetAttribute(
"BASIS", fielddefs[f]->m_basis);
627 field_group->SetAttribute(
"SHAPE", shapeStrings[f]);
629 if (homoLengths[f].size() > 0)
631 field_group->SetAttribute(
"HOMOGENEOUSLENGTHS",
641 field_group->SetAttribute(
"NUMMODESPERDIR",
642 numModesPerDirUni[f]);
646 std::string numModesPerDir =
"MIXORDER";
647 field_group->SetAttribute(
"NUMMODESPERDIR",
655 m_comm->GetSpaceComm()->Block();
667 ASSERTL1(outfile, prfx.str() +
"cannot open HDF5 file.");
669 ASSERTL1(root, prfx.str() +
"cannot open root group.");
674 prfx.str() +
"cannot open DECOMPOSITION dataset.");
678 prfx.str() +
"cannot open DECOMPOSITION filespace.");
680 decomps_fspace->SelectRange(0, all_decomps.size());
681 decomps_dset->Write(all_decomps, decomps_fspace, writeSR);
685 std::vector<uint64_t> idx =
686 m_comm->GetSpaceComm()->Scatter(root_rank, all_idxs);
701 parallelProps->SetMpio(
m_comm->GetSpaceComm());
704 writePL->SetDxMpioCollective();
710 ASSERTL1(outfile, prfx.str() +
"cannot open HDF5 file.");
712 ASSERTL1(root, prfx.str() +
"cannot open root group.");
714 m_comm->GetSpaceComm()->Block();
719 ASSERTL1(ids_dset, prfx.str() +
"cannot open ELEMENTIDS dataset.");
721 ASSERTL1(ids_fspace, prfx.str() +
"cannot open ELEMENTIDS filespace.");
725 ASSERTL1(data_dset, prfx.str() +
"cannot open DATA dataset.");
727 ASSERTL1(data_fspace, prfx.str() +
"cannot open DATA filespace.");
735 order_dset = root->OpenDataSet(
"POLYORDERS");
736 ASSERTL1(order_dset, prfx.str() +
"cannot open POLYORDERS dataset.");
737 order_fspace = order_dset->GetSpace();
739 prfx.str() +
"cannot open POLYORDERS filespace.");
744 homy_dset = root->OpenDataSet(
"HOMOGENEOUSYIDS");
746 prfx.str() +
"cannot open HOMOGENEOUSYIDS dataset.");
747 homy_fspace = homy_dset->GetSpace();
749 prfx.str() +
"cannot open HOMOGENEOUSYIDS filespace.");
754 homz_dset = root->OpenDataSet(
"HOMOGENEOUSZIDS");
756 prfx.str() +
"cannot open HOMOGENEOUSZIDS dataset.");
757 homz_fspace = homz_dset->GetSpace();
759 prfx.str() +
"cannot open HOMOGENEOUSZIDS filespace.");
764 homs_dset = root->OpenDataSet(
"HOMOGENEOUSSIDS");
766 prfx.str() +
"cannot open HOMOGENEOUSSIDS dataset.");
767 homs_fspace = homs_dset->GetSpace();
769 prfx.str() +
"cannot open HOMOGENEOUSSIDS filespace.");
773 for (
int f = 0; f < nFields; ++f)
776 std::size_t nFieldElems = fielddefs[f]->m_elementIDs.size();
777 ids_fspace->SelectRange(ids_i, nFieldElems);
778 ids_dset->Write(fielddefs[f]->m_elementIDs, ids_fspace, writePL);
779 ids_i += nFieldElems;
782 std::size_t nFieldVals = fielddata[f].size();
783 data_fspace->SelectRange(data_i, nFieldVals);
784 data_dset->Write(fielddata[f], data_fspace, writePL);
785 data_i += nFieldVals;
790 for (
int f = 0; f < nFields; ++f)
792 std::size_t nOrders = numModesPerDirVar[f].size();
793 order_fspace->SelectRange(order_i, nOrders);
794 order_dset->Write(numModesPerDirVar[f], order_fspace, writePL);
801 for (
int f = 0; f < nFields; ++f)
803 std::size_t nYIDs = homoYIDs[f].size();
804 homy_fspace->SelectRange(homy_i, nYIDs);
805 homy_dset->Write(homoYIDs[f], homy_fspace, writePL);
812 for (
int f = 0; f < nFields; ++f)
814 std::size_t nZIDs = homoZIDs[f].size();
815 homz_fspace->SelectRange(homz_i, nZIDs);
816 homz_dset->Write(homoZIDs[f], homz_fspace, writePL);
823 for (
int f = 0; f < nFields; ++f)
825 std::size_t nSIDs = homoSIDs[f].size();
826 homs_fspace->SelectRange(homs_i, nSIDs);
827 homs_dset->Write(homoSIDs[f], homs_fspace, writePL);
832 for (
int f = nFields; f < nMaxFields; ++f)
837 ids_dset->Write(fielddefs[nFields - 1]->m_elementIDs, ids_fspace,
839 data_dset->Write(fielddata[nFields - 1], data_fspace, writePL);
843 order_dset->Write(numModesPerDirVar[nFields - 1], order_fspace,
849 homy_dset->Write(homoYIDs[nFields - 1], homy_fspace, writePL);
854 homz_dset->Write(homoZIDs[nFields - 1], homz_fspace, writePL);
859 homs_dset->Write(homoSIDs[nFields - 1], homs_fspace, writePL);
863 m_comm->GetSpaceComm()->Block();
866 if (
m_comm->GetRank() == 0)
869 std::cout <<
" (" << tm1 - tm0 <<
"s, HDF5)" << std::endl;
886 std::vector<FieldDefinitionsSharedPtr> &fielddefs,
887 std::vector<std::vector<NekDouble>> &fielddata,
891 std::stringstream prfx;
892 int nprocs =
m_comm->GetSpaceComm()->GetSize();
903 parallelProps->SetMpio(
m_comm->GetSpaceComm());
906 readPL->SetDxMpioCollective();
908 readPLInd->SetDxMpioIndependent();
916 std::static_pointer_cast<H5DataSource>(dataSource);
917 ASSERTL1(h5, prfx.str() +
"cannot open HDF5 file.");
919 ASSERTL1(root, prfx.str() +
"cannot open root group.");
922 unsigned int formatVersion;
925 for (; attrIt != attrEnd; ++attrIt)
927 if (*attrIt ==
"FORMAT_VERSION")
934 "Unable to determine Nektar++ HDF5 file version");
935 root->GetAttribute(
"FORMAT_VERSION", formatVersion);
938 "File format if " + infilename +
939 " is higher than supported in "
940 "this version of Nektar++");
944 ASSERTL1(decomps_dset, prfx.str() +
"cannot open DECOMPOSITION dataset.");
947 ASSERTL1(ids_dset, prfx.str() +
"cannot open ELEMENTIDS dataset.");
950 ASSERTL1(data_dset, prfx.str() +
"cannot open DATA dataset.");
955 prfx.str() +
"cannot open DECOMPOSITION filespace.");
958 ASSERTL1(ids_fspace, prfx.str() +
"cannot open ELEMENTIDS filespace.");
961 ASSERTL1(data_fspace, prfx.str() +
"cannot open DATA filespace.");
964 std::vector<uint64_t> ids;
966 ids_dset->Read(ids, ids_fspace, readPL);
968 std::unordered_set<uint64_t> toread;
971 for (
uint64_t i = 0; i < ElementIDs.size(); ++i)
973 toread.insert(ElementIDs[i]);
977 std::vector<uint64_t> decomps;
978 decomps_dset->Read(decomps, decomps_fspace, readPL);
980 size_t nDecomps = decomps.size() /
MAX_DCMPS;
983 std::vector<OffsetHelper> decompsToOffsets(nDecomps);
987 std::map<uint64_t, std::vector<unsigned int>> decompsToElmts;
990 std::map<uint64_t, std::set<uint64_t>> groupsToDecomps;
993 bool selective = toread.size() > 0;
998 for (
size_t i = 0, cnt = 0, cnt2 = 0; i < nDecomps; ++i, cnt +=
MAX_DCMPS)
1009 for (
size_t j = 0; j < nElmt; ++j)
1012 if (toread.find(elmtId) != toread.end())
1014 nElmtSelective += 1;
1020 nElmtSelective = nElmt;
1023 if (nElmtSelective > 0)
1025 groupsToDecomps[groupHash].insert(i);
1029 std::vector<unsigned int> tmp2(nElmt);
1030 for (
size_t j = 0; j < nElmt; ++j)
1032 tmp2[j] = ids[cnt2 + j];
1037 decompsToElmts[i] = tmp2;
1038 decompsToOffsets[i] = running;
1051 for (
auto &gIt : groupsToDecomps)
1054 for (
auto &sIt : gIt.second)
1057 auto groupName = std::to_string(gIt.first);
1061 ImportFieldDef(readPLInd, root, decomps, sIt, decompsToOffsets[sIt],
1062 groupName, fielddef);
1064 fielddef->m_elementIDs = decompsToElmts[sIt];
1068 fielddefs.push_back(fielddef);
1075 std::vector<unsigned int> coeffsPerElmt{
1079 std::vector<unsigned int> newElementIDs;
1080 std::vector<unsigned int> newNumModes;
1081 std::vector<hsize_t> dataIdxToRead;
1085 size_t numbasis = fielddef->m_basis.size();
1089 for (
size_t i = 0; i < fielddef->m_elementIDs.size();
1093 if (toread.find(fielddef->m_elementIDs[i]) !=
1096 newElementIDs.push_back(
1097 fielddef->m_elementIDs[i]);
1099 for (
size_t j = 0; j < coeffsPerElmt[i]; ++j)
1101 dataIdxToRead.push_back(
1102 decompsToOffsets[sIt].data + offset +
1106 if (fielddef->m_uniOrder ==
false)
1108 for (
size_t j = 0; j < numbasis; ++j)
1110 newNumModes.push_back(
1112 ->m_numModes[i * numbasis + j]);
1117 offset += coeffsPerElmt[i];
1123 const size_t nDataPoints = dataIdxToRead.size();
1125 for (
size_t i = 1; i < fielddef->m_fields.size(); ++i)
1127 for (
size_t j = 0; j < nDataPoints; ++j)
1129 dataIdxToRead.push_back(dataIdxToRead[j] +
1135 fielddef->m_elementIDs = newElementIDs;
1136 if (fielddef->m_uniOrder ==
false)
1138 fielddef->m_numModes = newNumModes;
1141 std::vector<NekDouble> decompFieldData;
1143 data_fspace->ClearRange();
1144 data_fspace->SetSelection(dataIdxToRead.size(),
1147 data_dset->Read(decompFieldData, data_fspace, readPLInd);
1150 fielddef->m_fields.size(),
1151 "FieldIOHdf5: input data is not the same length "
1152 "as header information.");
1153 fielddata.push_back(decompFieldData);
1157 std::vector<NekDouble> decompFieldData;
1163 data_fspace->ClearRange();
1164 data_fspace->SelectRange(decompsToOffsets[sIt].data,
1167 data_dset->Read(decompFieldData, data_fspace, readPLInd);
1170 fielddef->m_fields.size(),
1171 "FieldIOHdf5: input data is not the same length "
1172 "as header information.");
1173 fielddata.push_back(decompFieldData);
1180 m_comm->GetSpaceComm()->Block();
1193 std::vector<uint64_t> &decomps,
1198 std::stringstream prfx;
1199 prfx <<
m_comm->GetRank() <<
": FieldIOHdf5::ImportFieldDefsHdf5(): ";
1202 ASSERTL1(field, prfx.str() +
"cannot open field group, " + group +
'.');
1204 def->m_uniOrder =
false;
1208 for (; attrIt != attrEnd; ++attrIt)
1210 const std::string &attrName = *attrIt;
1211 if (attrName ==
"FIELDS")
1213 field->GetAttribute(attrName, def->m_fields);
1215 else if (attrName ==
"SHAPE")
1217 std::string shapeString;
1218 field->GetAttribute(attrName, shapeString);
1224 if (shapeString.find(
"Strips") != std::string::npos)
1226 def->m_homoStrips =
true;
1229 if ((loc = shapeString.find_first_of(
"-")) != std::string::npos)
1231 if (shapeString.find(
"Exp1D") != std::string::npos)
1233 def->m_numHomogeneousDir = 1;
1237 def->m_numHomogeneousDir = 2;
1240 shapeString.erase(loc, shapeString.length());
1258 std::string(
"unable to correctly parse the shape type: ")
1259 .append(shapeString)
1262 else if (attrName ==
"BASIS")
1264 field->GetAttribute(attrName, def->m_basis);
1266 for (
auto &bIt : def->m_basis)
1271 "unable to correctly parse the basis types.");
1274 else if (attrName ==
"HOMOGENEOUSLENGTHS")
1276 field->GetAttribute(attrName, def->m_homogeneousLengths);
1278 else if (attrName ==
"NUMMODESPERDIR")
1280 std::string numModesPerDir;
1281 field->GetAttribute(attrName, numModesPerDir);
1283 if (strstr(numModesPerDir.c_str(),
"UNIORDER:"))
1285 def->m_uniOrder =
true;
1287 numModesPerDir.substr(9), def->m_numModes);
1290 "unable to correctly parse the number of modes.");
1293 else if (attrName ==
"POINTSTYPE")
1295 std::string pointsString;
1296 field->GetAttribute(attrName, pointsString);
1297 def->m_pointsDef =
true;
1299 std::vector<std::string> pointsStrings;
1303 "unable to correctly parse the points types.");
1304 for (
size_t i = 0; i < pointsStrings.size(); i++)
1320 "unable to correctly parse the points type: ")
1321 .append(pointsStrings[i])
1325 else if (attrName ==
"NUMPOINTSPERDIR")
1327 std::string numPointsPerDir;
1328 field->GetAttribute(attrName, numPointsPerDir);
1329 def->m_numPointsDef =
true;
1335 "unable to correctly parse the number of points.");
1339 std::string errstr(
"unknown attribute: ");
1341 ASSERTL1(
false, prfx.str() + errstr.c_str());
1345 if (def->m_numHomogeneousDir >= 1)
1350 homz_fspace->SelectRange(offset.
homz, dsize);
1351 homz_dset->Read(def->m_homogeneousZIDs, homz_fspace, readPL);
1354 if (def->m_numHomogeneousDir >= 2)
1359 homy_fspace->SelectRange(offset.
homy, dsize);
1360 homy_dset->Read(def->m_homogeneousYIDs, homy_fspace, readPL);
1363 if (def->m_homoStrips)
1368 homs_fspace->SelectRange(offset.
homs, dsize);
1369 homs_dset->Read(def->m_homogeneousSIDs, homs_fspace, readPL);
1372 if (!def->m_uniOrder)
1377 order_fspace->SelectRange(offset.
order, dsize);
1378 order_dset->Read(def->m_numModes, order_fspace, readPL);