|
1 | 1 | #include "input.h" |
2 | 2 | #include "../global/allvars.h" |
3 | 3 | #include <algorithm> |
| 4 | +#include <dirent.h> |
4 | 5 | #include <fstream> |
5 | 6 | #include <iostream> |
6 | 7 | #include <sstream> |
@@ -109,7 +110,33 @@ bool InputHandler::getParameterBool(const std::string& key) const { |
109 | 110 | "' to bool (expected: true/false/1/0/yes/no/on/off)"); |
110 | 111 | } |
111 | 112 |
|
| 113 | +// check if a parameter exists |
| 114 | +bool InputHandler::hasParameter(const std::string& key) const { |
| 115 | + return parameters.find(key) != parameters.end(); |
| 116 | +} |
| 117 | + |
112 | 118 | #ifdef USE_HDF5 |
| 119 | + |
| 120 | +// find the latest snapshot_N.hdf5 in a directory, return N (or -1 if none found) |
| 121 | +int InputHandler::findLatestSnapshot(const std::string& dir) { |
| 122 | + DIR* d = opendir(dir.c_str()); |
| 123 | + if (!d) return -1; |
| 124 | + int max_num = -1; |
| 125 | + struct dirent* entry; |
| 126 | + while ((entry = readdir(d)) != NULL) { |
| 127 | + std::string name(entry->d_name); |
| 128 | + if (name.size() > 14 && name.substr(0, 9) == "snapshot_" && name.substr(name.size() - 5) == ".hdf5") { |
| 129 | + std::string num_str = name.substr(9, name.size() - 14); |
| 130 | + try { |
| 131 | + int num = std::stoi(num_str); |
| 132 | + if (num > max_num) max_num = num; |
| 133 | + } catch (...) {} |
| 134 | + } |
| 135 | + } |
| 136 | + closedir(d); |
| 137 | + return max_num; |
| 138 | +} |
| 139 | + |
113 | 140 | // opens IC.hdf5 file and reads initial conditions into ICData struct |
114 | 141 | // will get extended if additional fields get added to IC file ... |
115 | 142 | bool InputHandler::readICFile(const std::string& filename, ICData& icData) { |
@@ -297,4 +324,136 @@ bool InputHandler::readICFile(const std::string& filename, ICData& icData) { |
297 | 324 | std::cout << "INPUT: IC file loaded successfully!" << std::endl; |
298 | 325 | return true; |
299 | 326 | } |
| 327 | + |
| 328 | +// read a snapshot file into ICData for restart (seeds from cells/seeds, hydro from hydro/) |
| 329 | +bool InputHandler::readSnapshotFile(const std::string& filename, ICData& icData, double& t_sim) { |
| 330 | + |
| 331 | + std::ifstream f(filename); |
| 332 | + if (!f.good()) { |
| 333 | + std::cerr << "INPUT: Error! Snapshot file [" << filename << "] does not exist!" << std::endl; |
| 334 | + return false; |
| 335 | + } |
| 336 | + |
| 337 | + hid_t file_id = H5Fopen(filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); |
| 338 | + if (file_id < 0) { |
| 339 | + std::cerr << "INPUT: Error! Could not open snapshot file: " << filename << std::endl; |
| 340 | + return false; |
| 341 | + } |
| 342 | + |
| 343 | + // read header/time |
| 344 | + hid_t header_group = H5Gopen(file_id, "header", H5P_DEFAULT); |
| 345 | + if (header_group < 0) { |
| 346 | + std::cerr << "INPUT: Error! Could not open header group in snapshot" << std::endl; |
| 347 | + H5Fclose(file_id); |
| 348 | + return false; |
| 349 | + } |
| 350 | + |
| 351 | + hid_t attr_dim = H5Aopen(header_group, "dimension", H5P_DEFAULT); |
| 352 | + if (attr_dim >= 0) { |
| 353 | + H5Aread(attr_dim, H5T_NATIVE_INT, &icData.header.dimension); |
| 354 | + H5Aclose(attr_dim); |
| 355 | + } |
| 356 | + |
| 357 | +#ifdef dim_2D |
| 358 | + if (icData.header.dimension != 2) |
| 359 | +#else |
| 360 | + if (icData.header.dimension != 3) |
| 361 | +#endif |
| 362 | + { |
| 363 | + std::cerr << "INPUT: Error! Snapshot dimension mismatch! Snapshot: " << icData.header.dimension |
| 364 | + << "D, compiled: " << DIMENSION << "D" << std::endl; |
| 365 | + H5Gclose(header_group); |
| 366 | + H5Fclose(file_id); |
| 367 | + return false; |
| 368 | + } |
| 369 | + |
| 370 | + hid_t attr_time = H5Aopen(header_group, "time", H5P_DEFAULT); |
| 371 | + if (attr_time >= 0) { |
| 372 | + H5Aread(attr_time, H5T_NATIVE_DOUBLE, &t_sim); |
| 373 | + H5Aclose(attr_time); |
| 374 | + } else { |
| 375 | + std::cerr << "INPUT: Error! Could not read time attribute from snapshot" << std::endl; |
| 376 | + H5Gclose(header_group); |
| 377 | + H5Fclose(file_id); |
| 378 | + return false; |
| 379 | + } |
| 380 | + H5Gclose(header_group); |
| 381 | + |
| 382 | + // read cells/seeds -> icData.seedpos |
| 383 | + hid_t cells_group = H5Gopen(file_id, "cells", H5P_DEFAULT); |
| 384 | + if (cells_group < 0) { |
| 385 | + std::cerr << "INPUT: Error! Could not open cells group in snapshot" << std::endl; |
| 386 | + H5Fclose(file_id); |
| 387 | + return false; |
| 388 | + } |
| 389 | + |
| 390 | + hid_t dataset_id = H5Dopen(cells_group, "seeds", H5P_DEFAULT); |
| 391 | + if (dataset_id < 0) { |
| 392 | + std::cerr << "INPUT: Error! Could not open seeds dataset in snapshot" << std::endl; |
| 393 | + H5Gclose(cells_group); |
| 394 | + H5Fclose(file_id); |
| 395 | + return false; |
| 396 | + } |
| 397 | + |
| 398 | + hid_t dataspace_id = H5Dget_space(dataset_id); |
| 399 | + icData.seedpos_dims.resize(2); |
| 400 | + H5Sget_simple_extent_dims(dataspace_id, icData.seedpos_dims.data(), NULL); |
| 401 | + hsize_t totalElements = icData.seedpos_dims[0] * icData.seedpos_dims[1]; |
| 402 | + icData.seedpos.resize(totalElements); |
| 403 | + H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, icData.seedpos.data()); |
| 404 | + H5Sclose(dataspace_id); |
| 405 | + H5Dclose(dataset_id); |
| 406 | + H5Gclose(cells_group); |
| 407 | + |
| 408 | + // read hydro/rho |
| 409 | + hid_t hydro_group = H5Gopen(file_id, "hydro", H5P_DEFAULT); |
| 410 | + if (hydro_group < 0) { |
| 411 | + std::cerr << "INPUT: Error! Could not open hydro group in snapshot" << std::endl; |
| 412 | + H5Fclose(file_id); |
| 413 | + return false; |
| 414 | + } |
| 415 | + |
| 416 | + hsize_t n = icData.seedpos_dims[0]; |
| 417 | + |
| 418 | + dataset_id = H5Dopen(hydro_group, "rho", H5P_DEFAULT); |
| 419 | + if (dataset_id < 0) { |
| 420 | + std::cerr << "INPUT: Error! Could not open rho dataset in snapshot" << std::endl; |
| 421 | + H5Gclose(hydro_group); |
| 422 | + H5Fclose(file_id); |
| 423 | + return false; |
| 424 | + } |
| 425 | + icData.rho.resize(n); |
| 426 | + H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, icData.rho.data()); |
| 427 | + H5Dclose(dataset_id); |
| 428 | + |
| 429 | + // read hydro/vel |
| 430 | + dataset_id = H5Dopen(hydro_group, "vel", H5P_DEFAULT); |
| 431 | + if (dataset_id < 0) { |
| 432 | + std::cerr << "INPUT: Error! Could not open vel dataset in snapshot" << std::endl; |
| 433 | + H5Gclose(hydro_group); |
| 434 | + H5Fclose(file_id); |
| 435 | + return false; |
| 436 | + } |
| 437 | + icData.vel.resize(n * DIMENSION); |
| 438 | + H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, icData.vel.data()); |
| 439 | + H5Dclose(dataset_id); |
| 440 | + |
| 441 | + // read hydro/Energy |
| 442 | + dataset_id = H5Dopen(hydro_group, "Energy", H5P_DEFAULT); |
| 443 | + if (dataset_id < 0) { |
| 444 | + std::cerr << "INPUT: Error! Could not open Energy dataset in snapshot" << std::endl; |
| 445 | + H5Gclose(hydro_group); |
| 446 | + H5Fclose(file_id); |
| 447 | + return false; |
| 448 | + } |
| 449 | + icData.Energy.resize(n); |
| 450 | + H5Dread(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT, icData.Energy.data()); |
| 451 | + H5Dclose(dataset_id); |
| 452 | + |
| 453 | + H5Gclose(hydro_group); |
| 454 | + H5Fclose(file_id); |
| 455 | + |
| 456 | + std::cout << "INPUT: Snapshot loaded successfully! (" << n << " cells, t = " << t_sim << ")" << std::endl; |
| 457 | + return true; |
| 458 | +} |
300 | 459 | #endif |
0 commit comments