37#include <unordered_map>
38#include <unordered_set>
50#include "vlsv_reader_parallel.h"
57using namespace phiprof;
74 if (stat(
"STOP", &tempStat) == 0) {
75 bailout(
true,
"Received an external STOP command. Setting bailout.write_restart to true.");
79 const time_t rawTime = time(NULL);
80 const struct tm* timeInfo = localtime(&rawTime);
81 strftime(newName, 80,
"STOP_%F_%H-%M-%S", timeInfo);
82 rename(
"STOP", newName);
85 if (stat(
"KILL", &tempStat) == 0) {
86 bailout(
true,
"Received an external KILL command. Setting bailout.write_restart to false.");
90 const time_t rawTime = time(NULL);
91 const struct tm* timeInfo = localtime(&rawTime);
92 strftime(newName, 80,
"KILL_%F_%H-%M-%S", timeInfo);
93 rename(
"KILL", newName);
96 if(stat(
"SAVE", &tempStat) == 0) {
97 logFile <<
"Received an external SAVE command. Writing a restart file." << endl;
101 const time_t rawTime = time(NULL);
102 const struct tm* timeInfo = localtime(&rawTime);
103 strftime(newName, 80,
"SAVE_%F_%H-%M-%S", timeInfo);
104 rename(
"SAVE", newName);
107 if(stat(
"DORC", &tempStat) == 0) {
108 logFile <<
"Received an external DORC command. Writing a recover file." << endl;
112 const time_t rawTime = time(NULL);
113 const struct tm * timeInfo = localtime(&rawTime);
114 strftime(newName, 80,
"DORC_%F_%H-%M-%S", timeInfo);
115 rename(
"DORC", newName);
118 if(stat(
"DOLB", &tempStat) == 0) {
119 logFile <<
"Received an external DOLB command. Balancing load." << endl;
123 const time_t rawTime = time(NULL);
124 const struct tm* timeInfo = localtime(&rawTime);
125 strftime(newName, 80,
"DOLB_%F_%H-%M-%S", timeInfo);
126 rename(
"DOLB", newName);
129 if(stat(
"DOMR", &tempStat) == 0) {
130 logFile <<
"Received an external DOMR command. Refining grid." << endl;
134 const time_t rawTime = time(NULL);
135 const struct tm* timeInfo = localtime(&rawTime);
136 strftime(newName, 80,
"DOMR_%F_%H-%M-%S", timeInfo);
137 rename(
"DOMR", newName);
152bool exitOnError(
bool success,
const string& message, MPI_Comm comm) {
154 int globalSuccessInt;
160 MPI_Allreduce(&successInt, &globalSuccessInt, 1, MPI_INT, MPI_MIN, comm);
162 if (globalSuccessInt == 1) {
178bool readCellIds(vlsv::ParallelReader&
file, vector<CellID>& fileCells,
const int masterRank, MPI_Comm comm) {
180 uint64_t arraySize = 0;
182 vlsv::datatype::type dataType;
184 list<pair<string, string>> attribs;
187 MPI_Comm_rank(comm, &rank);
188 if (rank == masterRank) {
189 const short int readFromFirstIndex = 0;
191 attribs.push_back(make_pair(
"name",
"CellID"));
192 attribs.push_back(make_pair(
"mesh",
"SpatialGrid"));
193 if (
file.getArrayInfoMaster(
"VARIABLE", attribs, arraySize, vectorSize, dataType, byteSize) ==
false) {
194 logFile <<
"(RESTART) ERROR: Failed to read cell ID array info!" << endl <<
write;
199 if (vectorSize != 1) {
200 logFile <<
"(RESTART) ERROR: Bad vectorsize at " << __FILE__ <<
" " << __LINE__ << endl <<
write;
205 char* IDbuffer =
new char[arraySize * vectorSize * byteSize];
206 if (
file.readArrayMaster(
"VARIABLE", attribs, readFromFirstIndex, arraySize, IDbuffer) ==
false) {
207 logFile <<
"(RESTART) ERROR: Failed to read cell Ids!" << endl <<
write;
212 const uint64_t& numberOfCells = arraySize;
213 fileCells.resize(numberOfCells);
214 if (dataType == vlsv::datatype::type::UINT && byteSize == 4) {
215 uint32_t* ptr =
reinterpret_cast<uint32_t*
>(IDbuffer);
217 for (uint64_t
i = 0;
i < numberOfCells; ++
i) {
219 fileCells[
i] = cellID;
221 }
else if (dataType == vlsv::datatype::type::UINT && byteSize == 8) {
222 uint64_t* ptr =
reinterpret_cast<uint64_t*
>(IDbuffer);
223 for (uint64_t
i = 0;
i < numberOfCells; ++
i) {
225 fileCells[
i] = cellID;
228 logFile <<
"(RESTART) ERROR: ParallelReader returned an unsupported datatype for cell Ids!" << endl <<
write;
235 MPI_Bcast(&arraySize, 1, MPI_UINT64_T, masterRank, comm);
236 fileCells.resize(arraySize);
237 MPI_Bcast(&(fileCells[0]), arraySize, MPI_UINT64_T, masterRank, comm);
253 std::vector<size_t>& nBlocks,
int masterRank, MPI_Comm comm) {
259 vlsv::datatype::type dataType;
265 list<pair<string, string>> attribsIn;
266 map<string, string> attribsOut;
267 attribsIn.push_back(make_pair(
"mesh", meshName));
271 file.getArrayAttributes(
"MESH_DOMAIN_SIZES", attribsIn, attribsOut);
272 auto it = attribsOut.find(
"arraysize");
273 if (it == attribsOut.end()) {
274 cerr <<
"VLSV\t\t ERROR: Array 'MESH_DOMAIN_SIZES' XML tag does not have attribute 'arraysize'" << endl;
277 N_domains = atoi(it->second.c_str());
280 uint64_t N_spatialCells = 0;
281 int64_t* domainInfo = NULL;
282 if (
file.read(
"MESH_DOMAIN_SIZES", attribsIn, 0, N_domains, domainInfo) ==
false)
return false;
284 for (uint i_domain = 0; i_domain < N_domains; ++i_domain) {
285 N_spatialCells += domainInfo[2 * i_domain];
287 nBlocks.resize(N_spatialCells);
289 #pragma omp parallel for
290 for (
size_t i = 0;
i < nBlocks.size(); ++
i) nBlocks[
i] = 0;
296 if (
file.getUniqueAttributeValues(
"BLOCKSPERCELL",
"name", speciesNames) ==
false)
return false;
300 uint64_t* buffer =
new uint64_t[N_spatialCells];
303 attribsIn.push_back(make_pair(
"mesh", meshName));
304 attribsIn.push_back(make_pair(
"name", *s));
305 if (
file.getArrayInfo(
"BLOCKSPERCELL", attribsIn, arraySize, vectorSize, dataType, byteSize) ==
false)
return false;
307 if (
file.read(
"BLOCKSPERCELL", attribsIn, 0, arraySize, buffer) ==
false) {
313 #pragma omp parallel for
314 for (
size_t i = 0;
i < N_spatialCells; ++
i) {
315 nBlocks[
i] += buffer[
i];
332 if (
file.readParameter(name, value) ==
false) {
333 logFile <<
"(RESTART) ERROR: Failed to read parameter '" << name <<
"' value in ";
334 logFile << __FILE__ <<
":" << __LINE__ << endl <<
write;
354 s <<
"(RESTART) ERROR: Failed to read parameter '" << name <<
"' value in " << __FILE__ <<
":" << __LINE__ << endl;
358 if (value != correctValue) {
360 s <<
"(RESTART) Parameter " << name <<
" has mismatching value.";
361 s <<
" CFG value = " << correctValue;
362 s <<
" Restart file value = " << value;
370template <
typename fileReal>
372 const std::string& spatMeshName,
373 const std::vector<uint64_t>& fileCells,
374 const uint64_t localCellStartOffset,
375 const uint64_t localCells,
377 const std::vector<uint64_t>& blockSumOffsets,
378 const uint64_t localBlockStartOffset,
379 const uint64_t localBlocks,
380 dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
385 uint64_t avgVectorSize;
386 vlsv::datatype::type dataType;
388 list<pair<string, string>> avgAttribs;
391 const string tagName =
"BLOCKIDS";
393 avgAttribs.push_back(make_pair(
"mesh", spatMeshName));
394 avgAttribs.push_back(make_pair(
"name", popName));
397 list<pair<string, string>> blockIdAttribs;
398 uint64_t blockIdVectorSize, blockIdByteSize;
399 vlsv::datatype::type blockIdDataType;
400 blockIdAttribs.push_back(make_pair(
"mesh", spatMeshName));
401 blockIdAttribs.push_back(make_pair(
"name", popName));
402 if (
file.getArrayInfo(
"BLOCKIDS", blockIdAttribs, arraySize, blockIdVectorSize, blockIdDataType, blockIdByteSize) ==
false) {
403 logFile <<
"(RESTART) ERROR: Failed to read BLOCKCOORDINATES array info " << endl <<
write;
406 if (
file.getArrayInfo(
"BLOCKVARIABLE", avgAttribs, arraySize, avgVectorSize, dataType, byteSize) ==
false) {
407 logFile <<
"(RESTART) ERROR: Failed to read BLOCKVARIABLE array info " << endl <<
write;
412 if (avgVectorSize !=
WID3) {
413 logFile <<
"(RESTART) ERROR: Blocksize does not match in restart file " << endl <<
write;
416 if (byteSize !=
sizeof(fileReal)) {
417 logFile <<
"(RESTART) ERROR: Bad avgs bytesize at " << __FILE__ <<
" " << __LINE__ << endl <<
write;
422 logFile <<
"(RESTART) ERROR: BlockID data size does not match " << __FILE__ <<
" " << __LINE__ << endl <<
write;
430 blockIdBuffer = ::new
vmesh::GlobalID[blockIdVectorSize * localBlocks];
432 avgBuffer =
new fileReal[avgVectorSize * localBlocks];
437 if (
file.readArray(
"BLOCKIDS", blockIdAttribs, localBlockStartOffset, localBlocks, (
char*)blockIdBuffer) ==
false) {
438 cerr <<
"ERROR, failed to read BLOCKIDS in " << __FILE__ <<
":" << __LINE__ << endl;
441 if (
file.readArray(
"BLOCKVARIABLE", avgAttribs, localBlockStartOffset, localBlocks, (
char*)avgBuffer) ==
false) {
442 cerr <<
"ERROR, failed to read BLOCKVARIABLE in " << __FILE__ <<
":" << __LINE__ << endl;
447 #pragma omp parallel for schedule(dynamic, 1)
448 for (uint64_t
i = 0;
i < localCells;
i++) {
449 CellID cell = fileCells[localCellStartOffset +
i];
450 uint64_t blockBufferOffset = blockSumOffsets[
i];
453 vector<vmesh::GlobalID> blockIdsInCell;
454 blockIdsInCell.reserve(nBlocksInCell);
455 blockIdsInCell.assign(blockIdBuffer + blockBufferOffset, blockIdBuffer + blockBufferOffset + nBlocksInCell);
456 for (
auto&
id : blockIdsInCell) {
457 id = blockIDremapper(
id);
461 mpiGrid[cell]->add_velocity_blocks(popID, blockIdsInCell, &avgBuffer[blockBufferOffset *
WID3]);
462#if defined(USE_GPU) && defined(DEBUG_VLASIATOR)
463 mpiGrid[cell]->checkMesh(popID);
474 delete[] blockIdBuffer;
479template <
typename fileReal>
480bool _readBlockDataCompressionZFP(vlsv::ParallelReader &
file,
481 const std::string& spatMeshName,
482 const std::vector<uint64_t>& fileCells,
483 const uint64_t localCellStartOffset,
484 const uint64_t localCells,
486 const uint64_t localBlockStartOffset,
487 const uint64_t localBlocks,
488 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
493 uint64_t avgVectorSize;
494 vlsv::datatype::type dataType;
496 list<pair<string,string> > avgAttribs;
499 const string tagName =
"BLOCKIDS";
501 avgAttribs.push_back(make_pair(
"mesh",spatMeshName));
502 avgAttribs.push_back(make_pair(
"name",popName));
505 list<pair<string,string> > blockIdAttribs,bytesPerCellAttribs;
506 uint64_t blockIdVectorSize, blockIdByteSize;
507 vlsv::datatype::type blockIdDataType;
508 blockIdAttribs.push_back( make_pair(
"mesh", spatMeshName));
509 blockIdAttribs.push_back( make_pair(
"name", popName));
510 bytesPerCellAttribs.push_back( make_pair(
"mesh", spatMeshName));
511 bytesPerCellAttribs.push_back( make_pair(
"name", popName));
513 uint64_t bytesPerCellArraySize;
514 uint64_t bytesPerCellVectorSize;
515 uint64_t bytesPerCellByteSize;
517 if (
file.getArrayInfo(
"BYTESPERCELL",blockIdAttribs,bytesPerCellArraySize,bytesPerCellVectorSize,dataType,bytesPerCellByteSize) ==
false ){
518 logFile <<
"(RESTART) ERROR: Failed to read BLOCKCOORDINATES array info " << endl <<
write;
522 if (
file.getArrayInfo(
"BLOCKIDS",blockIdAttribs,arraySize,blockIdVectorSize,blockIdDataType,blockIdByteSize) ==
false ){
523 logFile <<
"(RESTART) ERROR: Failed to read BLOCKCOORDINATES array info " << endl <<
write;
526 if(
file.getArrayInfo(
"BLOCKVARIABLE",avgAttribs,arraySize,avgVectorSize,dataType,byteSize) ==
false ){
527 logFile <<
"(RESTART) ERROR: Failed to read BLOCKVARIABLE array info " << endl <<
write;
531 if (!
file.readParameter(
"VDF_BYTE_SIZE",byteSize )){
532 logFile<<
"ERROR: Failed to read parameter VDF_BYTE_SIZE"<<std::endl<<
write;
537 if( avgVectorSize!=1 ){
538 logFile <<
"(RESTART) ERROR: ZFP VectorSize should be 1." << endl <<
write;
541 if( byteSize !=
sizeof(fileReal) ) {
542 logFile <<
"(RESTART) ERROR: Bad avgs bytesize at " << __FILE__ <<
" " << __LINE__ << endl <<
write;
546 std::vector<std::size_t> bytesPerCell(fileCells.size(),{0});
550 if (
file.readArray(
"BYTESPERCELL", bytesPerCellAttribs, 0, fileCells.size(),
reinterpret_cast<char*
>(bytesPerCell.data()) ) ==
false) {
551 cerr <<
"ERROR, failed to read BYTESPERCELL in " << __FILE__ <<
":" << __LINE__ << endl;
555 std::vector<std::size_t> scanBytesPerCell(fileCells.size(),{0});
556 std::vector<std::size_t> localScanBytesPerCell(localCells,{0});
557 std::exclusive_scan(bytesPerCell.begin(), bytesPerCell.end(),scanBytesPerCell.begin(),0ull);
558 std::exclusive_scan(bytesPerCell.begin()+localCellStartOffset,bytesPerCell.begin()+localCellStartOffset+localCells ,localScanBytesPerCell.begin(),0ull);
559 std::size_t n_compressed_bytes=std::accumulate(&bytesPerCell[localCellStartOffset],&bytesPerCell[localCellStartOffset+localCells],0ull);
560 std::vector<char>compressed_bytes(n_compressed_bytes);
563 if (
file.readArray(
"BLOCKIDS", blockIdAttribs, localBlockStartOffset, localBlocks, (
char*)blockIdBuffer ) ==
false) {
564 cerr <<
"ERROR, failed to read BLOCKIDS in " << __FILE__ <<
":" << __LINE__ << endl;
567 std::cout<<
"REading n bytres"<<n_compressed_bytes<<std::endl;
569 if (
file.readArray(
"BLOCKVARIABLE", avgAttribs, scanBytesPerCell[localCellStartOffset], n_compressed_bytes, compressed_bytes.data()) ==
false) {
570 cerr <<
"ERROR, failed to read BLOCKVARIABLE in " << __FILE__ <<
":" << __LINE__ << endl;
574 uint64_t blockBufferOffset=0;
576 vector<vmesh::GlobalID> blockIdsInCell;
578 for(uint64_t
i=0;
i<localCells;
i++) {
579 CellID cell = fileCells[localCellStartOffset +
i];
585 blockIdsInCell.reserve(nBlocksInCell);
586 blockIdsInCell.assign(blockIdBuffer + blockBufferOffset, blockIdBuffer + blockBufferOffset + nBlocksInCell);
587 for(
auto&
id : blockIdsInCell) {
588 id = blockIDremapper(
id);
590 mpiGrid[cell]->add_velocity_blocks<
float>(popID,blockIdsInCell,NULL);
591 Realf *cellBlockData=mpiGrid[cell]->get_data(popID);
592 fileReal* data =
new fileReal[nBlocksInCell*
WID3];
594 std::runtime_error(
"ERROR: failed to allocate memory for reading in compressed VDFs.");
596 if constexpr (
sizeof(fileReal) ==
sizeof(float)) {
597 std::vector<float> vdf_vals =
599 bytesPerCell[localCellStartOffset +
i], nBlocksInCell *
WID3, sparse);
600 std::memcpy(data, vdf_vals.data(), vdf_vals.size() *
sizeof(
float));
601 }
else if constexpr (
sizeof(fileReal) ==
sizeof(double)) {
602 std::vector<double> vdf_vals =
604 bytesPerCell[localCellStartOffset +
i], nBlocksInCell *
WID3, sparse);
605 std::memcpy(data, vdf_vals.data(), vdf_vals.size() *
sizeof(
double));
607 std::runtime_error(
"ERROR: failed to read in VDFs for type fileReal. ");
609 for(uint64_t
i = 0;
i<
WID3 * nBlocksInCell ;
i++){
610 cellBlockData[
i] =
static_cast<Realf>(data[
i]);
613 blockBufferOffset += nBlocksInCell;
616 delete[] blockIdBuffer;
622template <
typename fileReal>
623bool _readBlockDataCompressionOCTREE(vlsv::ParallelReader &
file,
624 const std::string& spatMeshName,
625 const std::vector<uint64_t>& fileCells,
626 const uint64_t localCellStartOffset,
627 const uint64_t localCells,
629 const uint64_t localBlockStartOffset,
630 const uint64_t localBlocks,
631 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
636 uint64_t avgVectorSize;
637 vlsv::datatype::type dataType;
639 list<pair<string,string> > avgAttribs;
642 const string tagName =
"BLOCKIDS";
644 avgAttribs.push_back(make_pair(
"mesh",spatMeshName));
645 avgAttribs.push_back(make_pair(
"name",popName));
648 list<pair<string,string> > blockIdAttribs,bytesPerCellAttribs;
649 uint64_t blockIdVectorSize, blockIdByteSize;
650 vlsv::datatype::type blockIdDataType;
651 blockIdAttribs.push_back( make_pair(
"mesh", spatMeshName));
652 blockIdAttribs.push_back( make_pair(
"name", popName));
653 bytesPerCellAttribs.push_back( make_pair(
"mesh", spatMeshName));
654 bytesPerCellAttribs.push_back( make_pair(
"name", popName));
656 uint64_t bytesPerCellArraySize;
657 uint64_t bytesPerCellVectorSize;
658 uint64_t bytesPerCellByteSize;
660 if (
file.getArrayInfo(
"BYTESPERCELL",blockIdAttribs,bytesPerCellArraySize,bytesPerCellVectorSize,dataType,bytesPerCellByteSize) ==
false ){
661 logFile <<
"(RESTART) ERROR: Failed to read BLOCKCOORDINATES array info " << endl <<
write;
665 if(
file.getArrayInfo(
"BLOCKVARIABLE",avgAttribs,arraySize,avgVectorSize,dataType,byteSize) ==
false ){
666 logFile <<
"(RESTART) ERROR: Failed to read BLOCKVARIABLE array info " << endl <<
write;
669 if (!
file.readParameter(
"VDF_BYTE_SIZE",byteSize )){
670 logFile<<
"ERROR: Failed to read parameter VDF_BYTE_SIZE"<<std::endl<<
write;
675 if( avgVectorSize!=1 ){
676 logFile <<
"(RESTART) ERROR: ZFP VectorSize should be 1." << endl <<
write;
679 if( byteSize !=
sizeof(fileReal) ) {
680 logFile <<
"(RESTART) ERROR: Bad avgs bytesize at " << __FILE__ <<
" " << __LINE__ << endl <<
write;
684 std::vector<std::size_t> bytesPerCell(fileCells.size(),{0});
686 if (
file.readArray(
"BYTESPERCELL", bytesPerCellAttribs, 0, fileCells.size(),
reinterpret_cast<char*
>(bytesPerCell.data()) ) ==
false) {
687 cerr <<
"ERROR, failed to read BYTESPERCELL in " << __FILE__ <<
":" << __LINE__ << endl;
691 std::vector<std::size_t> scanBytesPerCell(fileCells.size(),{0});
692 std::vector<std::size_t> localScanBytesPerCell(localCells,{0});
693 std::exclusive_scan(bytesPerCell.begin(), bytesPerCell.end(),scanBytesPerCell.begin(),0ull);
694 std::exclusive_scan(bytesPerCell.begin()+localCellStartOffset,bytesPerCell.begin()+localCellStartOffset+localCells ,localScanBytesPerCell.begin(),0ull);
695 std::size_t n_compressed_bytes=std::accumulate(&bytesPerCell[localCellStartOffset],&bytesPerCell[localCellStartOffset+localCells],0ull);
696 std::vector<char>compressed_bytes(n_compressed_bytes);
698 if (
file.readArray(
"BLOCKVARIABLE", avgAttribs, scanBytesPerCell[localCellStartOffset], n_compressed_bytes, compressed_bytes.data()) ==
false) {
699 cerr <<
"ERROR, failed to read BLOCKVARIABLE in " << __FILE__ <<
":" << __LINE__ << endl;
703 if (
sizeof (fileReal)!=4){
704 throw std::runtime_error(
"TODO: Not implemented yet!");
707 for(uint64_t
i=0;
i<localCells;
i++) {
708 CellID cell = fileCells[localCellStartOffset +
i];
712 std::size_t read_index = localScanBytesPerCell[
i];
713 const std::size_t* n_ignored_blocks=
reinterpret_cast<const std::size_t*
>(compressed_bytes.data()+read_index);
714 read_index+=
sizeof(std::size_t);
716 std::memcpy(blocks_to_ignore.data() ,compressed_bytes.data()+read_index , blocks_to_ignore.size()*
sizeof(
vmesh::GlobalID) );
718 const std::size_t* bbox_shape=
reinterpret_cast<const std::size_t*
>(compressed_bytes.data()+read_index);
719 read_index+=3*
sizeof(std::size_t);
720 const Real* bbox_lims=
reinterpret_cast<const Real*
>(compressed_bytes.data()+read_index);
721 read_index+=6*
sizeof(
Real);
724 Real dv= (bbox_lims[3]-bbox_lims[0])/(
Realf)bbox_shape[0];
726 const std::size_t inflated_size=bbox_shape[0]*bbox_shape[1]*bbox_shape[2];
728 .vdf_vals=std::vector<Realf>(inflated_size,0),
729 .v_limits{bbox_lims[0],bbox_lims[1],bbox_lims[2],bbox_lims[3],bbox_lims[4],bbox_lims[5]},
730 .shape={bbox_shape[0],bbox_shape[1],bbox_shape[2]}};
732 uncompress_with_toctree_method(
vdf.vdf_vals.data(),bbox_shape[0],bbox_shape[1],bbox_shape[2], (uint8_t*)&compressed_bytes[read_index],bytesPerCell[localCellStartOffset+
i]-read_index);
735 for (std::size_t
i=0;
i<bbox_shape[0];++
i){
736 for (std::size_t
j=0;
j<bbox_shape[1];++
j){
737 for (std::size_t
k=0;
k<bbox_shape[2];++
k){
738 const std::array<Real,3>
coords={bbox_lims[0]+
i*
dv,bbox_lims[1]+
j*
dv,bbox_lims[2]+
k*
dv};
741 const bool ignore_me=std::find(blocks_to_ignore.cbegin(),blocks_to_ignore.cend(),gid)!=blocks_to_ignore.cend();
742 if (val>=sparse && !ignore_me){
756template <
typename fileReal>
757bool _readBlockDataCompressionMLP(vlsv::ParallelReader &
file,
758 const std::string& spatMeshName,
759 const std::vector<uint64_t>& fileCells,
760 const uint64_t localCellStartOffset,
761 const uint64_t localCells,
763 const uint64_t localBlockStartOffset,
764 const uint64_t localBlocks,
765 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
771 list<pair<string,string> > attribs;
772 attribs.push_back(make_pair(
"name",popName));
775 if (!
file.readParameter(
"numWritingRanks",nFileRanks)){
776 logFile <<
"ERROR: Could not read numWritingRanks from restart file!";
779 std::vector<std::size_t> nbytes(nFileRanks);
780 if (!
file.readArray(
"MLP_BYTES_PER_RANK",attribs,0,nFileRanks,
reinterpret_cast<char*
>((nbytes.data())))){
781 logFile<<
"ERROR: Could not read mlp bytes per rank"<<endl<<
write;
782 std::cerr<<
"MLP BYTES PER RANK ARE INVALID"<<std::endl;
785 std::vector<std::size_t> nclusters(nFileRanks);
786 if (!
file.readArray(
"MLP_CLUSTERS_PER_RANK",attribs,0,nFileRanks,
reinterpret_cast<char*
>((nclusters.data())))){
787 logFile<<
"ERROR: Could not read mlp bytes per rank"<<endl<<
write;
788 std::cerr<<
"MLP CLUSTERS PER RANK ARE INVALID"<<std::endl;
791 const std::size_t nmlps = std::accumulate(nclusters.cbegin(),nclusters.cend(),0ull);
794 std::vector<std::size_t> scanBytesPerCell(nFileRanks);
795 std::exclusive_scan(nbytes.cbegin(), nbytes.cend(),scanBytesPerCell.begin(),0ull);
796 std::vector<ASTERIX::PhaseSpaceUnion<Realf>::Header> mlp_headers(nmlps);
798 std::vector<std::size_t> nbytes_multi_mlp_case;
800 for (std::size_t
i=0;
i<(std::size_t)nFileRanks;++
i){
802 for (std::size_t cluster=0;cluster<nclusters[
i];++cluster){
804 cerr <<
"ERROR, failed to read MLP BYTES in " << __FILE__ <<
":" << __LINE__ << endl;
807 if(nmlps>(std::size_t)nFileRanks){
808 nbytes_multi_mlp_case.push_back(mlp_headers.at(cnt).total_size);
810 offset+=mlp_headers.at(cnt).total_size;
814 if (nmlps>(std::size_t)nFileRanks){
815 nbytes=nbytes_multi_mlp_case;
820 if (nmlps>(std::size_t)nFileRanks){
821 scanBytesPerCell.resize(nmlps);
822 std::exclusive_scan(nbytes.cbegin(), nbytes.cend(),scanBytesPerCell.begin(),0ull);
826 std::vector<std::vector<CellID>> mlp_cids(nmlps);
829 for (std::size_t
i=0;
i<(std::size_t)nFileRanks;++
i){
830 for (std::size_t cluster=0;cluster<nclusters[
i];++cluster){
831 mlp_cids.at(cnt).resize(mlp_headers.at(cnt).cols);
833 cerr <<
"ERROR, failed to read MLP BYTES in " << __FILE__ <<
":" << __LINE__ << endl;
841 std::unordered_map<CellID ,std::size_t> cid2mlp_map;
842 std::unordered_set<std::size_t> mlp_lookup;
844 for (std::size_t
i=0;
i<localCells;++
i){
845 CellID cid= fileCells[localCellStartOffset +
i];
850 for (std::size_t
j = 0;
j < mlp_cids.size(); ++
j) {
851 const auto& cand = mlp_cids.at(
j);
852 if(std::find(cand.begin(),cand.end(),cid)!=cand.end()){
854 mlp_lookup.insert(
j);
861 std::vector<std::size_t >lookup;
862 lookup.reserve(mlp_lookup.size());
863 for (
auto it = mlp_lookup.begin(); it != mlp_lookup.end(); ) {
864 lookup.push_back(std::move(mlp_lookup.extract(it++).value()));
867 std::size_t global_n_reads={0};
868 const std::size_t local_n_reads=lookup.size();
874 MPI_UNSIGNED_LONG_LONG,
877 MPI_Barrier(MPI_COMM_WORLD);
883 for (std::size_t
i=0;
i<global_n_reads;++
i){
884 if (
i<local_n_reads){
885 const auto id=lookup.at(
i);
888 std::vector<char> mlp_bytes( nbytes.at(
id) );
891 if (
file.readArray(
"BLOCKVARIABLE", attribs, scanBytesPerCell[
id], nbytes[
id], mlp_bytes.data()) ==
false) {
892 cerr <<
"ERROR, failed to read MLP BYTES in " << __FILE__ <<
":" << __LINE__ << endl;
898 ASTERIX::decompressPhaseSpace<Realf>(b);
899 b.unormalize_and_unscale(sparse);
903 for (
const auto& [cid,mlpid]:cid2mlp_map){
909 const std::size_t column = std::find(
b._cids.begin(),
b._cids.end(), cid) -
b._cids.begin();
910 for (std::size_t
i=0;
i<
b._nrows;++
i){
911 auto vbulk=
b._vbulks[column];
916 std::array<Real, 3> coords_updated = {
static_cast<Real>(
coords[0]),
static_cast<Real>(coords[1]),
919 const bool exists =
b._map.find(gid)!=
b._map.end();
929 if (
file.readArray(
"BLOCKVARIABLE", attribs, scanBytesPerCell[0], 0, ptr) ==
false) {
930 cerr <<
"ERROR, failed to read MLP BYTES in " << __FILE__ <<
":" << __LINE__ << endl;
953template <
typename fileReal>
955 vlsv::ParallelReader &
file,
956 const std::string& spatMeshName,
957 const std::vector<uint64_t>& fileCells,
958 const uint64_t localCellStartOffset,
959 const uint64_t localCells,
961 const std::vector<uint64_t>& blockSumOffsets,
962 const uint64_t localBlockStartOffset,
963 const uint64_t localBlocks,
964 dccrg::Dccrg<SpatialCell,dccrg::Cartesian_Geometry>& mpiGrid,
971 if (!
file.readParameter(
"COMPRESSION",cmp)){
972 logFile<<
"(RESTART): Compression defaulted to NONE"<<endl<<
write;
978 localCells, blocksPerCell,blockSumOffsets, localBlockStartOffset,
979 localBlocks, mpiGrid, blockIDremapper, popID);
983 success=_readBlockDataCompressionZFP<fileReal>(
file,spatMeshName,fileCells,localCellStartOffset,localCells,blocksPerCell,localBlockStartOffset,localBlocks,mpiGrid,blockIDremapper,popID);
988 success=_readBlockDataCompressionMLP<fileReal>(
file,spatMeshName,fileCells,localCellStartOffset,localCells,blocksPerCell,localBlockStartOffset,localBlocks,mpiGrid,blockIDremapper,popID);
991 success=_readBlockDataCompressionMLP<fileReal>(
file,spatMeshName,fileCells,localCellStartOffset,localCells,blocksPerCell,localBlockStartOffset,localBlocks,mpiGrid,blockIDremapper,popID);
996 success=_readBlockDataCompressionOCTREE<fileReal>(
file,spatMeshName,fileCells,localCellStartOffset,localCells,blocksPerCell,localBlockStartOffset,localBlocks,mpiGrid,blockIDremapper,popID);
1015bool readBlockData(vlsv::ParallelReader&
file,
const string& meshName,
const vector<CellID>& fileCells,
1016 const uint64_t localCellStartOffset,
const uint64_t localCells,
1017 dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid) {
1018 bool success =
true;
1020 const uint64_t bytesReadStart =
file.getBytesRead();
1022 MPI_Comm_size(MPI_COMM_WORLD, &N_processes);
1025 uint64_t vectorSize;
1026 vlsv::datatype::type dataType;
1028 uint64_t* offsetArray =
new uint64_t[N_processes];
1040 list<pair<string, string>> attribs;
1041 attribs.push_back(make_pair(
"mesh", popName));
1042 std::array<unsigned int, 6> fileMeshBBox;
1043 unsigned int* bufferpointer = &fileMeshBBox[0];
1044 if (
file.read(
"MESH_BBOX", attribs, 0, 6, bufferpointer,
false) ==
false) {
1045 logFile <<
"(RESTART) ERROR: Failed to read MESH_BBOX at " << __FILE__ <<
":" << __LINE__ << endl <<
write;
1051 if (fileMeshBBox[0] != ourMeshParams.
gridLength[0] ||
1052 fileMeshBBox[1] != ourMeshParams.
gridLength[1] ||
1053 fileMeshBBox[2] != ourMeshParams.
gridLength[2]) {
1055 logFile <<
"(RESTART) INFO: velocity mesh sizes don't match:" << endl
1056 <<
" restart file has " << fileMeshBBox[0] <<
" x " << fileMeshBBox[1] <<
" x " << fileMeshBBox[2] <<
"," << endl
1059 if (ourMeshParams.
gridLength[0] < fileMeshBBox[0] ||
1060 ourMeshParams.
gridLength[1] < fileMeshBBox[1] ||
1061 ourMeshParams.
gridLength[2] < fileMeshBBox[2]) {
1062 logFile <<
"(RESTART) ERROR: trying to shrink velocity space." << endl <<
write;
1068 std::vector<Real> fileVelCoordsX(fileMeshBBox[0] * fileMeshBBox[3] + 1);
1069 std::vector<Real> fileVelCoordsY(fileMeshBBox[1] * fileMeshBBox[4] + 1);
1070 std::vector<Real> fileVelCoordsZ(fileMeshBBox[2] * fileMeshBBox[5] + 1);
1072 Real* tempPointer = fileVelCoordsX.data();
1073 if (
file.read(
"MESH_NODE_CRDS_X", attribs, 0, fileMeshBBox[0] * fileMeshBBox[3] + 1, tempPointer,
false) ==
false) {
1074 logFile <<
"(RESTART) ERROR: Failed to read MESH_NODE_CRDS_X at " << __FILE__ <<
":" << __LINE__ << endl <<
write;
1077 tempPointer = fileVelCoordsY.data();
1078 if (
file.read(
"MESH_NODE_CRDS_Y", attribs, 0, fileMeshBBox[1] * fileMeshBBox[4] + 1, tempPointer,
false) ==
false) {
1079 logFile <<
"(RESTART) ERROR: Failed to read MESH_NODE_CRDS_Y at " << __FILE__ <<
":" << __LINE__ << endl <<
write;
1082 tempPointer = fileVelCoordsZ.data();
1083 if (
file.read(
"MESH_NODE_CRDS_Z", attribs, 0, fileMeshBBox[2] * fileMeshBBox[5] + 1, tempPointer,
false) ==
false) {
1084 logFile <<
"(RESTART) ERROR: Failed to read MESH_NODE_CRDS_Z at " << __FILE__ <<
":" << __LINE__ << endl <<
write;
1089 for (
const auto&
c : fileVelCoordsX) {
1091 if (fabs(nearbyint(cellindex) - cellindex) > 1. / 10000.) {
1092 logFile <<
"(RESTART) ERROR: Can't resize velocity space as cell coordinates don't match." << endl
1093 <<
" (X coordinate " <<
c <<
" = " << cellindex <<
" * " << dVx <<
" + "
1095 <<
" coordinate = cellindex * dV + meshMinLimits)" << endl
1102 for (
const auto&
c : fileVelCoordsY) {
1104 if (fabs(nearbyint(cellindex) - cellindex) > 1. / 10000.) {
1105 logFile <<
"(RESTART) ERROR: Can't resize velocity space as cell coordinates don't match." << endl
1106 <<
" (Y coordinate " <<
c <<
" = " << cellindex <<
" * " << dVy <<
" + "
1108 <<
" coordinate = cellindex * dV + meshMinLimits)" << endl
1115 for (
const auto&
c : fileVelCoordsY) {
1117 if (fabs(nearbyint(cellindex) - cellindex) > 1. / 10000.) {
1118 logFile <<
"(RESTART) ERROR: Can't resize velocity space as cell coordinates don't match." << endl
1119 <<
" (Z coordinate " <<
c <<
" = " << cellindex <<
" * " << dVz <<
" + "
1121 <<
" coordinate = cellindex * dV + meshMinLimits)" << endl
1129 std::array<int, 3> velGridOffset;
1134 if ((velGridOffset[0] % ourMeshParams.
blockLength[0] != 0) ||
1135 (velGridOffset[1] % ourMeshParams.
blockLength[1] != 0) ||
1136 (velGridOffset[2] % ourMeshParams.
blockLength[2] != 0)) {
1137 logFile <<
"(RESTART) ERROR: resizing velocity space on restart must end up with the old velocity space" << endl
1138 <<
" at a block boundary of the new space!" << endl
1139 <<
" (It now starts at cell [" << velGridOffset[0] <<
", " << velGridOffset[1] <<
"," << velGridOffset[2] <<
"])" << endl <<
write;
1148 unsigned int x, y, z;
1149 x = oldID % fileMeshBBox[0];
1150 y = (oldID / fileMeshBBox[0]) % fileMeshBBox[1];
1151 z = oldID / (fileMeshBBox[0] * fileMeshBBox[1]);
1153 x += velGridOffset[0];
1154 y += velGridOffset[1];
1155 z += velGridOffset[2];
1161 logFile <<
" => Resizing velocity space by renumbering GlobalIDs." << endl << endl <<
write;
1167 attribs.push_back(make_pair(
"mesh", meshName));
1168 attribs.push_back(make_pair(
"name", popName));
1171 if (
file.read(
"BLOCKSPERCELL", attribs, localCellStartOffset, localCells, blocksPerCell,
true) ==
false) {
1172 logFile <<
"(RESTART) ERROR: Failed to read BLOCKSPERCELL at " << __FILE__ <<
":" << __LINE__ << endl <<
write;
1177 uint64_t blockSum = 0;
1178 std::vector<uint64_t> blockSumOffsets(localCells);
1179 for (uint64_t
i = 0;
i < localCells; ++
i) {
1180 blockSumOffsets[
i] = blockSum;
1181 blockSum += blocksPerCell[
i];
1189 uint64_t myOffset = 0;
1190 for (int64_t
i = 0;
i < mpiGrid.get_rank(); ++
i) {
1191 myOffset += offsetArray[
i];
1194 if (!
file.readParameter(
"VDF_BYTE_SIZE",byteSize)){
1195 logFile <<
"(RESTART): This must be a non Asterix Restart" << endl <<
write;
1196 if (
file.getArrayInfo(
"BLOCKVARIABLE",attribs,arraySize,vectorSize,dataType,byteSize) ==
false) {
1197 logFile <<
"(RESTART) ERROR: Failed to read BLOCKVARIABLE INFO" << endl <<
write;
1203 case sizeof(double):
1205 blockSumOffsets, myOffset, blockSum, mpiGrid, blockIDremapper, popID) ==
false)
1211 blockSumOffsets, myOffset, blockSum, mpiGrid, blockIDremapper, popID) ==
false)
1215 delete[] blocksPerCell;
1216 blocksPerCell = NULL;
1219 delete[] offsetArray;
1222 const uint64_t bytesReadEnd =
file.getBytesRead() - bytesReadStart;
1223 logFile <<
"Velocity meshes and data read, approximate data rate is ";
1224 logFile << vlsv::printDataRate(bytesReadEnd,
file.getReadTime()) << endl <<
write;
1238template <
typename fileReal>
1240 const uint64_t localCellStartOffset,
const uint64_t localCells,
1241 const string& variableName,
const size_t cellParamsIndex,
1242 const size_t expectedVectorSize,
1243 dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid) {
1245 uint64_t vectorSize;
1246 vlsv::datatype::type dataType;
1248 list<pair<string, string>> attribs;
1250 bool success =
true;
1252 attribs.push_back(make_pair(
"name", variableName));
1253 attribs.push_back(make_pair(
"mesh",
"SpatialGrid"));
1255 if (
file.getArrayInfo(
"VARIABLE", attribs, arraySize, vectorSize, dataType, byteSize) ==
false) {
1256 logFile <<
"(RESTART) ERROR: Failed to read DCCRG ArrayInfo" << endl <<
write;
1260 if (vectorSize != expectedVectorSize) {
1261 logFile <<
"(RESTART) vectorsize wrong " << endl <<
write;
1265 buffer = ::new fileReal[vectorSize * localCells];
1266 if (
file.readArray(
"VARIABLE", attribs, localCellStartOffset, localCells, (
char*)buffer) ==
false) {
1267 logFile <<
"(RESTART) ERROR: Failed to read " << variableName << endl <<
write;
1271 for (uint
i = 0;
i < localCells;
i++) {
1272 uint cell = fileCells[localCellStartOffset +
i];
1273 for (uint
j = 0;
j < vectorSize;
j++) {
1274 mpiGrid[cell]->parameters[cellParamsIndex +
j] = buffer[
i * vectorSize +
j];
1292 const uint64_t localCellStartOffset,
const uint64_t localCells,
const string& variableName,
1293 const size_t cellParamsIndex,
const size_t expectedVectorSize,
1294 dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid) {
1296 uint64_t vectorSize;
1297 vlsv::datatype::type dataType;
1299 list<pair<string, string>> attribs;
1301 attribs.push_back(make_pair(
"name", variableName));
1302 attribs.push_back(make_pair(
"mesh",
"SpatialGrid"));
1304 if (
file.getArrayInfo(
"VARIABLE", attribs, arraySize, vectorSize, dataType, byteSize) ==
false) {
1305 logFile <<
"(RESTART) ERROR: Failed to read DCCRG ArrayInfo" << endl <<
write;
1310 if (dataType == vlsv::datatype::type::FLOAT) {
1312 case sizeof(double):
1319 }
else if (dataType == vlsv::datatype::type::UINT) {
1321 case sizeof(uint32_t):
1324 case sizeof(uint64_t):
1328 }
else if (dataType == vlsv::datatype::type::INT) {
1330 case sizeof(int32_t):
1333 case sizeof(int64_t):
1338 logFile <<
"(RESTART) ERROR: Failed to read data type at readCellParamsVariable" << endl <<
write;
1351template <
unsigned long int N>
1354 std::span<std::array<Real, N>> targetData) {
1355 phiprof::Timer preparations{
"preparations"};
1358 uint64_t vectorSize;
1359 vlsv::datatype::type dataType;
1361 list<pair<string, string>> attribs;
1362 bool convertFloatType =
false;
1364 attribs.push_back(make_pair(
"name", variableName));
1365 attribs.push_back(make_pair(
"mesh",
"fsgrid"));
1367 phiprof::Timer getArrayInfo{
"getArrayInfo"};
1368 if (
file.getArrayInfo(
"VARIABLE", attribs, arraySize, vectorSize, dataType, byteSize) ==
false) {
1369 logFile <<
"(RESTART) ERROR: Failed to read FsGrid ArrayInfo " << endl <<
write;
1372 if (!(dataType == vlsv::datatype::type::FLOAT && byteSize ==
sizeof(
Real))) {
1373 logFile <<
"(RESTART) Converting floating point format of fsgrid variable " << variableName <<
" from "
1374 << byteSize * 8 <<
" bits to " <<
sizeof(
Real) * 8 <<
" bits." << endl
1376 convertFloatType =
true;
1380 getArrayInfo.stop();
1384 MPI_Comm_size(MPI_COMM_WORLD, &size);
1385 MPI_Comm_rank(MPI_COMM_WORLD, &
myRank);
1387 const auto* localSize = &
fsgrid.getLocalSize()[0];
1388 const auto& localStart =
fsgrid.getLocalStart();
1389 const auto& globalSize =
fsgrid.getGlobalSize();
1392 size_t storageSize = localSize[0] * localSize[1] * localSize[2];
1394 preparations.stop();
1395 std::array<fsgrid::Task_t, 3> fileDecomposition = {0, 0, 0};
1400 exitOnError(
false,
"(RESTART) Failed to read Fsgrid decomposition", MPI_COMM_WORLD);
1404 logFile <<
"(RESTART) Using manual override for FsGrid MESH_DECOMPOSITION." << endl <<
write;
1406 int fsgridInputRanks = 0;
1409 exitOnError(
false,
"(RESTART) FSGrid writing rank number not found in restart file", MPI_COMM_WORLD);
1412 if (fileDecomposition[0] * fileDecomposition[1] * fileDecomposition[2] != fsgridInputRanks) {
1415 "(RESTART) Trying to use a manual FsGrid decomposition for a file with a differing number of input ranks.",
1420 const auto& decomposition =
fsgrid.getDecomposition();
1422 if (decomposition == fileDecomposition) {
1427 size_t localStartOffset = 0;
1428 for (fsgrid::Task_t task = 0; task <
myRank; task++) {
1429 std::array<fsgrid::FsIndex_t, 3> thatTasksSize;
1430 thatTasksSize[0] = fsgrid::calcLocalSize(globalSize[0], decomposition[0], task / decomposition[2] / decomposition[1]);
1431 thatTasksSize[1] = fsgrid::calcLocalSize(globalSize[1], decomposition[1], (task / decomposition[2]) % decomposition[1]);
1432 thatTasksSize[2] = fsgrid::calcLocalSize(globalSize[2], decomposition[2], task % decomposition[2]);
1433 localStartOffset += thatTasksSize[0] * thatTasksSize[1] * thatTasksSize[2];
1437 std::vector<Real> buffer(storageSize * N);
1439 if (
file.readArray(
"VARIABLE", attribs, localStartOffset, storageSize, buffer.data()) ==
false) {
1440 logFile <<
"(RESTART) ERROR: Failed to read fsgrid variable " << variableName << endl <<
write;
1446 fsgrid.parallel_for([](
int timerId) -> phiprof::Timer {
return phiprof::Timer{timerId}; },
1447 phiprof::initializeTimer(
"Map Refinement Level to FsGrid"), technical,
1448 [=](
const fsgrid::Coordinates &coordinates,
const fsgrid::FsStencil& stencil,
cuint sysBoundaryFlag,
cuint sysBoundaryLayer) {
1449 cint index = N * (stencil.k * coordinates.localSize[1] * coordinates.localSize[0] + stencil.j * coordinates.localSize[0] + stencil.i);
1450 memcpy(targetData[stencil.ooo()].data(), &buffer[
index], N *
sizeof(
Real));
1475 size_t fileOffset = 0;
1476 for (
int task = 0; task < numWritingRanks; task++) {
1478 phiprof::Timer taskArithmetics1{
"task overlap arithmetics 1"};
1480 std::array<fsgrid::FsIndex_t, 3> thatTasksSize;
1481 std::array<fsgrid::FsIndex_t, 3> thatTasksStart;
1482 thatTasksSize[0] = fsgrid::calcLocalSize(globalSize[0], fileDecomposition[0], task / fileDecomposition[2] / fileDecomposition[1]);
1483 thatTasksSize[1] = fsgrid::calcLocalSize(globalSize[1], fileDecomposition[1], (task / fileDecomposition[2]) % fileDecomposition[1]);
1484 thatTasksSize[2] = fsgrid::calcLocalSize(globalSize[2], fileDecomposition[2], task % fileDecomposition[2]);
1486 thatTasksStart[0] = fsgrid::calcLocalStart(globalSize[0], fileDecomposition[0], task / fileDecomposition[2] / fileDecomposition[1]);
1487 thatTasksStart[1] = fsgrid::calcLocalStart(globalSize[1], fileDecomposition[1], (task / fileDecomposition[2]) % fileDecomposition[1]);
1488 thatTasksStart[2] = fsgrid::calcLocalStart(globalSize[2], fileDecomposition[2], task % fileDecomposition[2]);
1491 std::array<fsgrid::FsIndex_t, 3> overlapStart, overlapEnd, overlapSize;
1492 overlapStart[0] =
max(localStart[0], thatTasksStart[0]);
1493 overlapStart[1] =
max(localStart[1], thatTasksStart[1]);
1494 overlapStart[2] =
max(localStart[2], thatTasksStart[2]);
1496 overlapEnd[0] =
min(localStart[0] + localSize[0], thatTasksStart[0] + thatTasksSize[0]);
1497 overlapEnd[1] =
min(localStart[1] + localSize[1], thatTasksStart[1] + thatTasksSize[1]);
1498 overlapEnd[2] =
min(localStart[2] + localSize[2], thatTasksStart[2] + thatTasksSize[2]);
1500 overlapSize[0] =
max(overlapEnd[0] - overlapStart[0], (fsgrid::FsIndex_t)0);
1501 overlapSize[1] =
max(overlapEnd[1] - overlapStart[1], (fsgrid::FsIndex_t)0);
1502 overlapSize[2] =
max(overlapEnd[2] - overlapStart[2], (fsgrid::FsIndex_t)0);
1504 taskArithmetics1.stop();
1507 std::vector<Real> buffer(thatTasksSize[0] * thatTasksSize[1] * thatTasksSize[2] * N);
1509 phiprof::Timer multiRead{
"multiRead"};
1510 file.startMultiread(
"VARIABLE", attribs);
1512 if (overlapSize[0] * overlapSize[1] * overlapSize[2] > 0) {
1514 if (!convertFloatType) {
1515 if (
file.addMultireadUnit((
char*)buffer.data(),
1516 thatTasksSize[0] * thatTasksSize[1] * thatTasksSize[2]) ==
false) {
1517 logFile <<
"(RESTART) ERROR: Failed to read fsgrid variable " << variableName << endl <<
write;
1520 file.endMultiread(fileOffset);
1522 std::vector<float> readBuffer(thatTasksSize[0] * thatTasksSize[1] * thatTasksSize[2] * N);
1523 if (
file.addMultireadUnit((
char*)readBuffer.data(),
1524 thatTasksSize[0] * thatTasksSize[1] * thatTasksSize[2]) ==
false) {
1525 logFile <<
"(RESTART) ERROR: Failed to read fsgrid variable " << variableName << endl <<
write;
1528 file.endMultiread(fileOffset);
1530 for (uint64_t
i = 0;
i < thatTasksSize[0] * thatTasksSize[1] * thatTasksSize[2] * N;
i++) {
1531 buffer[
i] = readBuffer[
i];
1536 for (
auto z = overlapStart[2]; z < overlapEnd[2]; z++) {
1537 for (
auto y = overlapStart[1]; y < overlapEnd[1]; y++) {
1538 for (
auto x = overlapStart[0]; x < overlapEnd[0]; x++) {
1539 const auto stencil =
fsgrid.makeStencil(x, y, z);
1540 const fsgrid::FsIndex_t
index = (z - thatTasksStart[2]) * thatTasksSize[0] * thatTasksSize[1] +
1541 (y - thatTasksStart[1]) * thatTasksSize[0] +
1542 (x - thatTasksStart[0]);
1544 memcpy(targetData[stencil.indexFromOffset(-localStart[0], -localStart[1], -localStart[2])].data(),
1551 file.endMultiread(fileOffset);
1553 fileOffset += thatTasksSize[0] * thatTasksSize[1] * thatTasksSize[2];
1557 phiprof::Timer updateGhostsTimer{
"updateGhostCells"};
1558 fsgrid.updateGhostCells(targetData);
1559 updateGhostsTimer.stop();
1574 uint64_t vectorSize;
1575 vlsv::datatype::type dataType;
1577 list<pair<string, string>> attribs;
1579 attribs.push_back(make_pair(
"name", variableName));
1580 attribs.push_back(make_pair(
"mesh",
"ionosphere"));
1583 if (grid.nodes.size() == 0) {
1587 if (
file.getArrayInfo(
"VARIABLE", attribs, arraySize, vectorSize, dataType, byteSize) ==
false) {
1588 logFile <<
"(RESTART) ERROR: Failed to read array info for " << variableName << endl <<
write;
1593 if (vectorSize != 1) {
1594 logFile <<
"(RESTART) ERROR: Trying to read vector valued (" << vectorSize
1595 <<
" components) ionosphere parameter from restart file. Only scalars are supported." << endl
1601 if (grid.nodes.size() != arraySize) {
1602 logFile <<
"(RESTART) ERROR: Ionosphere restart size mismatch: trying to read variable " << variableName
1603 <<
" with " << arraySize <<
" values into a ionosphere grid with " << grid.nodes.size() <<
" nodes!"
1609 std::vector<Real> buffer(arraySize);
1610 if (
file.readArray(
"VARIABLE", attribs, 0, arraySize, buffer.data()) ==
false) {
1611 logFile <<
"(RESTART) ERROR: Failed to read ionosphere variable " << variableName << endl <<
write;
1614 for (uint
i = 0;
i < grid.nodes.size();
i++) {
1615 grid.nodes[
i].parameters[
index] = buffer[
i];
1628bool exec_readGrid(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
1632 vector<CellID> fileCells;
1633 vector<size_t> nBlocks;
1634 bool success =
true;
1639 const string meshName =
"SpatialGrid";
1642 MPI_Comm_rank(MPI_COMM_WORLD, &
myRank);
1643 MPI_Comm_size(MPI_COMM_WORLD, &processes);
1645 phiprof::Timer readGridTimer{
"readGrid"};
1647 phiprof::Timer readScalarsTimer{
"readScalars"};
1649 vlsv::ParallelReader
file;
1653 MPIinfo = MPI_INFO_NULL;
1655 MPI_Info_create(&MPIinfo);
1657 for (std::vector<std::pair<std::string, std::string>>::const_iterator it =
P::restartReadHints.begin();
1659 MPI_Info_set(MPIinfo, it->first.c_str(), it->second.c_str());
1666 exitOnError(success,
"(RESTART) Could not open file", MPI_COMM_WORLD);
1694 cout <<
" No P::fieldSolverSubcycles found in restart, setting 1." << endl;
1708 readScalarsTimer.stop();
1710 phiprof::Timer readLayoutimer{
"readDatalayout"};
1717 vector<CellID> allGridCells = mpiGrid.get_all_cells();
1718 if (fileCells.size() != allGridCells.size()) {
1719 std::cout <<
"File has " << fileCells.size() <<
" cells, got " << allGridCells.size() <<
" cells!" << std::endl;
1724 exitOnError(success,
"(RESTART) Wrong number of cells in restart file", MPI_COMM_WORLD);
1728 if (success ==
true) {
1736 for (
size_t i = 0;
i < gridCells.size();
i++) {
1738 mpiGrid[gridCells[
i]]->clear(popID);
1742 uint64_t totalNumberOfBlocks = 0;
1743 unsigned int numberOfBlocksPerProcess;
1744 for (uint
i = 0;
i < nBlocks.size(); ++
i) {
1745 totalNumberOfBlocks += nBlocks[
i];
1747 numberOfBlocksPerProcess = 1 + totalNumberOfBlocks / processes;
1749 uint64_t localCellStartOffset = 0;
1750 uint64_t localCells = 0;
1751 uint64_t numberOfBlocksCount = 0;
1755 for (
size_t i = 0;
i < fileCells.size(); ++
i) {
1756 numberOfBlocksCount += nBlocks[
i];
1757 int newCellProcess = numberOfBlocksCount / numberOfBlocksPerProcess;
1758 if (newCellProcess ==
myRank) {
1759 if (localCells == 0)
1760 localCellStartOffset =
i;
1763 if (mpiGrid.is_local(fileCells[
i])) {
1764 mpiGrid.pin(fileCells[
i], newCellProcess);
1771 mpiGrid.balance_load(
false);
1780 for (
size_t i = 0;
i < gridCells.size(); ++
i) {
1781 mpiGrid.unpin(gridCells[
i]);
1785 if (localCells != gridCells.size()) {
1789 if (success ==
true) {
1790 for (uint64_t
i = localCellStartOffset;
i < localCellStartOffset + localCells; ++
i) {
1791 if (mpiGrid.is_local(fileCells[
i]) ==
false) {
1797 exitOnError(success,
"(RESTART) Cell migration failed", MPI_COMM_WORLD);
1800 for (
size_t i = 0;
i < gridCells.size(); ++
i) {
1801 array<double, 3> cell_min = mpiGrid.geometry.get_min(gridCells[
i]);
1802 array<double, 3> cell_length = mpiGrid.geometry.get_length(gridCells[
i]);
1817 readLayoutimer.stop();
1820 phiprof::Timer readParametersTimer{
"readCellParameters"};
1872 readParametersTimer.stop();
1874 phiprof::Timer readBlocksTimer{
"readBlockData"};
1875 if (success ==
true) {
1876 success =
readBlockData(
file, meshName, fileCells, localCellStartOffset, localCells, mpiGrid);
1878 readBlocksTimer.stop();
1880 phiprof::Timer updateNeighborsTimer{
"updateMpiGridNeighbors"};
1882 updateNeighborsTimer.stop();
1884 phiprof::Timer readfsTimer{
"readFsGrid"};
1886 int fsgridInputRanks = 0;
1887 phiprof::Timer tReadScalarParameter{
"readScalarParameter"};
1889 exitOnError(
false,
"(RESTART) FSGrid writing rank number not found in restart file", MPI_COMM_WORLD);
1891 tReadScalarParameter.stop();
1899 exitOnError(success,
"(RESTART) Failure reading fsgrid restart variables", MPI_COMM_WORLD);
1902 phiprof::Timer readIonosphereTimer{
"readIonosphere"};
1903 bool ionosphereSuccess =
true;
1917 if (!ionosphereSuccess) {
1918 logFile <<
"(RESTART) Reading ionosphere variables failed. Continuing anyway. Variables will be zero, assuming "
1919 "this is an ionosphere cold start?"
1932 if (ionosphereSuccess && !ionosphereOptionalSuccess) {
1933 logFile <<
"(RESTART) Restart file contains no ionosphere conductivity data. Ionosphere will run fine, but first "
1934 "output bulk file might have bogus conductivities."
1937 readIonosphereTimer.stop();
1939 success =
file.close();
1941 exitOnError(success,
"(RESTART) Other failure", MPI_COMM_WORLD);
1951bool readGrid(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
1964bool readFileCells(dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid,
const std::string& name) {
1965 phiprof::Timer readCellIdsTimer{
"Restart read File cellIDs"};
1966 vector<CellID> fileCells;
1967 bool success =
true;
1968 vlsv::ParallelReader
file;
1969 MPI_Info mpiInfo = MPI_INFO_NULL;
1973 exitOnError(success,
"(READ_FILE_CELLS) Could not open file", MPI_COMM_WORLD);
1976 phiprof::Timer loadCellsTimer{
"load CellIDs into grid"};
1977 success = mpiGrid.load_cells(fileCells);
1978 exitOnError(success,
"(READ_FILE_CELLS) Failed to refine grid", MPI_COMM_WORLD);
1979 loadCellsTimer.stop();
1981 success =
file.close();
1982 exitOnError(success,
"(READ_FILE_CELLS) Other error", MPI_COMM_WORLD);
1987 list<pair<string, string>> attribs;
1989 MPI_Comm_rank(MPI_COMM_WORLD, &
myRank);
1991 phiprof::Timer readFsGridDecomposition{
"readFsGridDecomposition"};
1993 attribs.push_back(make_pair(
"mesh",
"fsgrid"));
1995 std::array<fsgrid::FsSize_t, 3> gridSize;
1996 fsgrid::FsSize_t* gridSizePtr = &gridSize[0];
1997 bool success =
file.read(
"MESH_BBOX", attribs, 0, 3, gridSizePtr,
false);
1998 if (success ==
false) {
1999 exitOnError(
false,
"(RESTART) FSGrid gridsize not found in file.", MPI_COMM_WORLD);
2003 std::array<fsgrid::Task_t, 3> fsGridDecomposition = {0, 0, 0};
2004 fsgrid::Task_t* ptr = &fsGridDecomposition[0];
2006 success =
file.read(
"MESH_DECOMPOSITION", attribs, 0, 3, ptr,
false);
2007 if (success ==
false) {
2009 std::cout <<
"Could not read MESH_DECOMPOSITION, attempting to calculate it from MESH." << endl;
2011 int fsgridInputRanks = 0;
2012 if (
file.readParameter(
"numWritingRanks", fsgridInputRanks) ==
false) {
2013 exitOnError(
false,
"(RESTART) FSGrid writing rank number not found in restart file.", MPI_COMM_WORLD);
2017 int64_t* domainInfo = NULL;
2018 success =
file.read(
"MESH_DOMAIN_SIZES", attribs, 0, fsgridInputRanks, domainInfo);
2019 if (success ==
false) {
2021 std::cerr <<
"Could not read MESH_DOMAIN_SIZES from file" << endl;
2025 std::vector<uint64_t> mesh_domain_sizes;
2026 for (
int i = 0;
i < 2 * fsgridInputRanks;
i += 2) {
2027 mesh_domain_sizes.push_back(domainInfo[
i]);
2029 list<pair<string, string>> mesh_attribs;
2030 mesh_attribs.push_back(make_pair(
"name",
"fsgrid"));
2031 std::vector<fsgrid::FsSize_t> rank_first_ids(fsgridInputRanks);
2032 fsgrid::FsSize_t* ids_ptr = &rank_first_ids[0];
2034 std::set<fsgrid::FsIndex_t> x_corners, y_corners, z_corners;
2036 int64_t begin_rank = 0;
2037 for (
auto rank_size : mesh_domain_sizes) {
2039 if (
file.read(
"MESH", mesh_attribs, begin_rank, 1, ids_ptr,
false) ==
false) {
2041 std::cerr <<
"Reading MESH failed.\n";
2045 std::array<fsgrid::FsIndex_t, 3> inds = fsgrid::globalIDtoCellCoord(*ids_ptr, gridSize);
2046 x_corners.insert(inds[0]);
2047 y_corners.insert(inds[1]);
2048 z_corners.insert(inds[2]);
2050 begin_rank += rank_size;
2052 file.read(
"MESH", mesh_attribs, begin_rank, 0, ids_ptr,
false);
2056 decomposition[0] = x_corners.size();
2057 decomposition[1] = y_corners.size();
2058 decomposition[2] = z_corners.size();
2059 MPI_Bcast(&decomposition, 3, MPI_INT,
MASTER_RANK, MPI_COMM_WORLD);
2061 if (decomposition[0] * decomposition[1] * decomposition[2] == fsgridInputRanks) {
2063 std::cout <<
"Fsgrid decomposition computed from MESH to be " << decomposition[0] <<
" " << decomposition[1] <<
" " << decomposition[2] << endl;
2068 std::cout <<
"Fsgrid decomposition computed from MESH to be " << decomposition[0] <<
" " << decomposition[1] <<
" " << decomposition[2] <<
", which is not compatible with numWritingRanks (" << fsgridInputRanks <<
")" << endl;
2074 decomposition[0] = fsGridDecomposition[0];
2075 decomposition[1] = fsGridDecomposition[1];
2076 decomposition[2] = fsGridDecomposition[2];
2077 logFile <<
"(RESTART) Fsgrid decomposition read as " << decomposition[0] <<
" " << decomposition[1] <<
" " << decomposition[2] <<
"\n";
set(gca, 'YDir', 'normal')
void adjustSingleCellVelocityBlocks(const uint popID, bool doDeleteEmpty=false)
static void set_mpi_transfer_type(const uint64_t type, bool atSysBoundaries=false)
vmesh::GlobalID get_velocity_block(const uint popID, vmesh::GlobalID blockIndices[3]) const
bool add_velocity_block(const vmesh::GlobalID &block, const uint popID)
void bailout(const bool condition, const std::string &message, const char *const file, const int line)
A function to stop the simulation if the boolean condition is true. Raises a flag which gets MPI_Redu...
const std::vector< CellID > & getLocalCells()
fsgrid::FsGrid< FS_STENCIL_WIDTH > FieldSolverGrid
__global__ void vmesh::VelocityMesh **__restrict__ ColumnOffsets split::SplitVector< vmesh::GlobalID > Hashinator::Hashmap< vmesh::GlobalID, vmesh::LocalID > const uint *__restrict__ const Realf const int const int const Realf const Realf dv
void recalculateLocalCellsCache(const dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid)
ObjectWrapper & getObjectWrapper()
bool readFsGridVariable(vlsv::ParallelReader &file, const string &variableName, int numWritingRanks, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, std::span< std::array< Real, N > > targetData)
bool exitOnError(bool success, const string &message, MPI_Comm comm)
Collective exit on error functions.
bool readFsgridDecomposition(vlsv::ParallelReader &file, std::array< fsgrid::Task_t, 3 > &decomposition)
bool readCellIds(vlsv::ParallelReader &file, vector< CellID > &fileCells, const int masterRank, MPI_Comm comm)
Read cell ID's Read in cell ID's from file. Note: Uses the newer version of vlsv parallel reader.
bool readBlockData(vlsv::ParallelReader &file, const string &meshName, const vector< CellID > &fileCells, const uint64_t localCellStartOffset, const uint64_t localCells, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid)
bool _readBlockDataCompressionNone(vlsv::ParallelReader &file, const std::string &spatMeshName, const std::vector< uint64_t > &fileCells, const uint64_t localCellStartOffset, const uint64_t localCells, const vmesh::LocalID *blocksPerCell, const std::vector< uint64_t > &blockSumOffsets, const uint64_t localBlockStartOffset, const uint64_t localBlocks, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, std::function< vmesh::GlobalID(vmesh::GlobalID)> blockIDremapper, const uint popID)
bool readIonosphereNodeVariable(vlsv::ParallelReader &file, const string &variableName, SBC::SphericalTriGrid &grid, ionosphereParameters index)
bool _readBlockData(vlsv::ParallelReader &file, const std::string &spatMeshName, const std::vector< uint64_t > &fileCells, const uint64_t localCellStartOffset, const uint64_t localCells, const vmesh::LocalID *blocksPerCell, const std::vector< uint64_t > &blockSumOffsets, const uint64_t localBlockStartOffset, const uint64_t localBlocks, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, std::function< vmesh::GlobalID(vmesh::GlobalID)> blockIDremapper, const uint popID)
bool readCellParamsVariable(vlsv::ParallelReader &file, const vector< CellID > &fileCells, const uint64_t localCellStartOffset, const uint64_t localCells, const string &variableName, const size_t cellParamsIndex, const size_t expectedVectorSize, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid)
bool exec_readGrid(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::perbspan perb, fsgrids::efieldspan e, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, const std::string &name)
Read in state from a vlsv file in order to restart simulations.
void checkExternalCommands()
Checks for command files written to the local directory. If a file STOP was written and is readable,...
bool checkScalarParameter(vlsv::ParallelReader &file, const string &name, T correctValue, int masterRank, MPI_Comm comm)
bool readNBlocks(vlsv::ParallelReader &file, const std::string &meshName, std::vector< size_t > &nBlocks, int masterRank, MPI_Comm comm)
static bool _readCellParamsVariable(vlsv::ParallelReader &file, const vector< uint64_t > &fileCells, const uint64_t localCellStartOffset, const uint64_t localCells, const string &variableName, const size_t cellParamsIndex, const size_t expectedVectorSize, dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid)
bool readFileCells(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, const std::string &name)
Refine the grid to be identical to the file's.
bool readScalarParameter(vlsv::ParallelReader &file, string name, T &value, int masterRank, MPI_Comm comm)
bool readGrid(dccrg::Dccrg< SpatialCell, dccrg::Cartesian_Geometry > &mpiGrid, fsgrids::perbspan perb, fsgrids::efieldspan e, fsgrids::technicalspan technical, FieldSolverGrid &fsgrid, const std::string &name)
Read in state from a vlsv file in order to restart simulations.
Logger & write(Logger &logger)
auto overwrite_pop_spatial_cell_vdf(spatial_cell::SpatialCell *sc, uint popID, const std::vector< Realf > &new_vspace) -> void
std::vector< double > decompressArrayDouble(char *compressedData, size_t compressedSize, size_t arraySize, double tol)
std::vector< float > decompressArrayFloat(char *compressedData, size_t compressedSize, size_t arraySize, float tol)
void overwrite_cellids_vdf_single_cell(const std::span< const CellID > cids, uint popID, spatial_cell::SpatialCell *sc, size_t cc, const std::vector< std::array< T, 3 > > &vcoords, const std::vector< T > &vspace_union, const std::unordered_map< vmesh::LocalID, std::size_t > &map_exists_id)
SphericalTriGrid ionosphereGrid
std::span< std::array< Real, fsgrids::bfield::N_BFIELD > > perbspan
std::span< technical > technicalspan
std::span< std::array< Real, fsgrids::efield::N_EFIELD > > efieldspan
static const uint64_t ALL_SPATIAL_DATA
static const GlobalID INVALID_GLOBALID
ARCH_HOSTDEV MeshWrapper * getMeshWrapper()
std::vector< species::Species > particleSpecies
static std::vector< std::pair< std::string, std::string > > restartReadHints
ASTERIX_COMPRESSION_METHODS
static bool refineOnRestart
static std::array< fsgrid::Task_t, 3 > overrideReadFsGridDecomposition
static uint fieldSolverSubcycles
static bool bailout_write_restart
vmesh::LocalID gridLength[3]
vmesh::LocalID blockLength[3]
std::array< vmesh::MeshParameters, MAX_VMESH_PARAMETERS_COUNT > * velocityMeshes
static ARCH_HOSTDEV VecSimple< T > min(VecSimple< T > const &l, VecSimple< T > const &r)
static ARCH_HOSTDEV VecSimple< T > max(VecSimple< T > const &l, VecSimple< T > const &r)