21#define PICURV_CHECKPOINT_FORMAT "picurv-checkpoint"
22#define PICURV_CHECKPOINT_VERSION 1
23#define PICURV_CHECKPOINTS_DIRECTORY "checkpoints"
24#define PICURV_EULERIAN_DIRECTORY "eulerian"
25#define PICURV_PARTICLE_DIRECTORY "particles"
26#define PICURV_STATISTICS_DIRECTORY "statistics"
27#define PICURV_CHECKPOINT_STEP_WIDTH 12
54 const PetscScalar ***local_array = NULL;
55 PetscScalar ***global_array = NULL;
57 PetscFunctionBeginUser;
59 PetscCall(DMDAGetLocalInfo(dm, &info));
60 PetscCall(DMDAVecGetArrayRead(dm, local_vec, &local_array));
61 PetscCall(DMDAVecGetArray(dm, global_vec, &global_array));
62 for (PetscInt k = info.zs; k < info.zs + info.zm; ++k)
63 for (PetscInt j = info.ys; j < info.ys + info.ym; ++j)
64 for (PetscInt i = info.xs; i < info.xs + info.xm; ++i)
65 global_array[k][j][i] = local_array[k][j][i];
66 PetscCall(DMDAVecRestoreArray(dm, global_vec, &global_array));
67 PetscCall(DMDAVecRestoreArrayRead(dm, local_vec, &local_array));
68 PetscFunctionReturn(0);
100 const char *payload_name,
char *path,
size_t path_size)
104 PetscFunctionBeginUser;
105 PetscCheck(path != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output path is required.");
108 if (window < 0) PetscFunctionReturn(0);
110 PetscCall(PetscStrlen(path, &used));
111 PetscCall(PetscSNPrintf(path + used, path_size - used,
"/window_%04" PetscInt_FMT, window));
112 if (block < 0) PetscFunctionReturn(0);
114 PetscCall(PetscStrlen(path, &used));
115 PetscCall(PetscSNPrintf(path + used, path_size - used,
"/block_%04" PetscInt_FMT, block));
116 if (!payload_name) PetscFunctionReturn(0);
118 PetscCall(PetscStrlen(path, &used));
119 PetscCall(PetscSNPrintf(path + used, path_size - used,
"/%s.dat", payload_name));
120 PetscFunctionReturn(0);
127 const char *dm_type = NULL;
128 Vec natural_vec = NULL;
129 VecScatter scatter = NULL;
131 PetscFunctionBeginUser;
132 PetscCheck(field_vec != NULL && sequential_vec != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
133 "A source vector and output vector pointer are required.");
134 *sequential_vec = NULL;
136 PetscCall(VecGetDM(field_vec, &dm));
137 if (dm) PetscCall(DMGetType(dm, &dm_type));
138 if (dm_type && !strcmp(dm_type, DMDA)) {
139 PetscCall(DMDACreateNaturalVector(dm, &natural_vec));
140 PetscCall(DMDAGlobalToNaturalBegin(dm, field_vec, INSERT_VALUES, natural_vec));
141 PetscCall(DMDAGlobalToNaturalEnd(dm, field_vec, INSERT_VALUES, natural_vec));
144 PetscCall(VecScatterCreateToZero(natural_vec ? natural_vec : field_vec, &scatter, sequential_vec));
145 PetscCall(VecScatterBegin(scatter, natural_vec ? natural_vec : field_vec, *sequential_vec,
146 INSERT_VALUES, SCATTER_FORWARD));
147 PetscCall(VecScatterEnd(scatter, natural_vec ? natural_vec : field_vec, *sequential_vec,
148 INSERT_VALUES, SCATTER_FORWARD));
149 PetscCall(VecScatterDestroy(&scatter));
150 PetscCall(VecDestroy(&natural_vec));
151 PetscFunctionReturn(0);
160 PetscFunctionBeginUser;
161 PetscCheck(simCtx != NULL && user != NULL && digest_hex != NULL,
162 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Geometry hash inputs cannot be NULL.");
165 PetscFunctionReturn(0);
169 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
171 Vec sequential_vec = NULL;
175 if (simCtx->
rank == 0) {
176 const PetscScalar *values = NULL;
177 PetscInt value_count = 0;
178 size_t metadata_length = 0;
180 PetscCall(PetscSNPrintf(metadata,
sizeof(metadata),
181 "block=%" PetscInt_FMT
";im=%" PetscInt_FMT
";jm=%" PetscInt_FMT
182 ";km=%" PetscInt_FMT
";periodic=%d,%d,%d;",
183 block, user[block].IM, user[block].JM, user[block].KM,
185 PetscCall(PetscStrlen(metadata, &metadata_length));
187 PetscCall(VecGetSize(sequential_vec, &value_count));
189 PetscCall(VecGetArrayRead(sequential_vec, &values));
191 PetscCall(VecRestoreArrayRead(sequential_vec, &values));
193 PetscCall(VecDestroy(&sequential_vec));
197 PetscCallMPI(MPI_Bcast(digest_hex, 65, MPI_CHAR, 0, PETSC_COMM_WORLD));
200 PetscFunctionReturn(0);
206 PetscFunctionBeginUser;
207 PetscCheck(root != NULL && path != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
208 "Checkpoint root and output path are required.");
209 PetscCall(PetscSNPrintf(path, path_size,
"%s/%s/step_%0*" PetscInt_FMT,
211 PetscFunctionReturn(0);
216 char *path,
size_t path_size)
218 char metadata_path[PETSC_MAX_PATH_LEN];
219 PetscBool exact_bundle = PETSC_FALSE;
221 PetscFunctionBeginUser;
222 PetscCheck(source_root != NULL && path != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
223 "Checkpoint source and output path are required.");
224 PetscCall(PetscSNPrintf(metadata_path,
sizeof(metadata_path),
"%s/checkpoint.meta", source_root));
225 PetscCall(PetscTestFile(metadata_path,
'r', &exact_bundle));
226 if (exact_bundle) PetscCall(PetscStrncpy(path, source_root, path_size));
228 PetscFunctionReturn(0);
234 PetscMPIInt create_failed = 0;
236 PetscFunctionBeginUser;
237 PetscCheck(simCtx != NULL && path != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
238 "Simulation context and directory path are required.");
239 if (simCtx->
rank == 0 && mkdir(path, 0777) != 0) {
240 struct stat directory_stat;
241 if (errno != EEXIST || stat(path, &directory_stat) != 0 || !S_ISDIR(directory_stat.st_mode)) {
245 PetscCallMPI(MPI_Bcast(&create_failed, 1, MPI_INT, 0, PETSC_COMM_WORLD));
246 PetscCheck(!create_failed, PETSC_COMM_WORLD, PETSC_ERR_FILE_OPEN,
247 "Unable to create checkpoint directory '%s'.", path);
248 PetscFunctionReturn(0);
253 const char *checkpoint_directory,
254 PetscInt expected_step,
255 PetscReal *physical_time,
256 PetscInt *particle_count,
257 PetscBool *particles_saved,
258 PetscBool *les_saved,
259 PetscBool *rans_saved)
261 char metadata_path[PETSC_MAX_PATH_LEN];
262 char commit_path[PETSC_MAX_PATH_LEN];
263 char expected_digest[65] =
"";
264 char actual_digest[65] =
"";
265 char format[64] =
"";
266 char saved_geometry_digest[65] =
"";
267 char current_geometry_digest[65] =
"";
268 PetscOptions options = NULL;
269 PetscInt version = 0;
270 PetscInt saved_step = -1;
271 PetscInt payload_count = 0;
272 PetscInt saved_particle_count = 0;
273 PetscReal saved_time = 0.0;
274 PetscBool saved_particles = PETSC_FALSE;
275 PetscBool saved_les = PETSC_FALSE;
276 PetscBool saved_rans = PETSC_FALSE;
277 PetscBool found = PETSC_FALSE;
278 FILE *commit_file = NULL;
280 PetscFunctionBeginUser;
281 PetscCheck(simCtx != NULL && user != NULL && checkpoint_directory != NULL,
282 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Checkpoint validation inputs cannot be NULL.");
283 PetscCall(PetscSNPrintf(metadata_path,
sizeof(metadata_path),
"%s/checkpoint.meta", checkpoint_directory));
284 PetscCall(PetscSNPrintf(commit_path,
sizeof(commit_path),
"%s/COMMITTED", checkpoint_directory));
286 PetscCall(PetscTestFile(metadata_path,
'r', &found));
287 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_OPEN,
288 "Checkpoint metadata is missing: %s", metadata_path);
289 PetscCall(PetscTestFile(commit_path,
'r', &found));
290 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_OPEN,
291 "Checkpoint is not committed: %s", checkpoint_directory);
293 commit_file = fopen(commit_path,
"r");
294 PetscCheck(commit_file != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
295 "Unable to read checkpoint commit marker '%s'.", commit_path);
296 PetscCheck(fgets(expected_digest,
sizeof(expected_digest), commit_file) != NULL,
297 PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
298 "Checkpoint commit marker '%s' is empty.", commit_path);
299 PetscCheck(fclose(commit_file) == 0, PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
300 "Unable to close checkpoint commit marker '%s'.", commit_path);
302 PetscCheck(strlen(expected_digest) == 64, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
303 "Checkpoint commit marker '%s' does not contain a SHA-256 digest.", commit_path);
305 PetscCheck(!strcmp(expected_digest, actual_digest), PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
306 "Checkpoint metadata hash mismatch in '%s'.", checkpoint_directory);
308 PetscCall(PetscOptionsCreate(&options));
309 PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, metadata_path, PETSC_TRUE));
310 PetscCall(PetscOptionsGetString(options, NULL,
"-checkpoint_format", format,
sizeof(format), &found));
312 "Unsupported checkpoint format '%s' in '%s'.", found ? format :
"<missing>", metadata_path);
313 PetscCall(PetscOptionsGetInt(options, NULL,
"-checkpoint_version", &version, &found));
315 "Unsupported checkpoint version %" PetscInt_FMT
" in '%s'; expected %d.",
317 PetscCall(PetscOptionsGetInt(options, NULL,
"-checkpoint_step", &saved_step, &found));
318 PetscCheck(found && saved_step == expected_step, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
319 "Checkpoint step is %" PetscInt_FMT
", expected %" PetscInt_FMT
".",
320 saved_step, expected_step);
321 PetscCall(PetscOptionsGetReal(options, NULL,
"-checkpoint_time", &saved_time, &found));
322 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
323 "Checkpoint '%s' does not record physical time.", metadata_path);
324 PetscCall(PetscOptionsGetString(options, NULL,
"-checkpoint_geometry_sha256",
325 saved_geometry_digest,
sizeof(saved_geometry_digest), &found));
326 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
327 "Checkpoint '%s' does not record geometry identity.", metadata_path);
329 PetscCheck(!strcmp(saved_geometry_digest, current_geometry_digest), PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
330 "Checkpoint geometry/layout does not match the active grid.");
332 PetscCall(PetscOptionsGetInt(options, NULL,
"-checkpoint_payload_count", &payload_count, &found));
333 PetscCheck(found && payload_count > 0, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
334 "Checkpoint '%s' has no payload inventory.", metadata_path);
335 PetscCall(PetscOptionsGetInt(options, NULL,
"-checkpoint_particle_count",
336 &saved_particle_count, &found));
337 PetscCheck(found && saved_particle_count >= 0, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
338 "Checkpoint '%s' has no valid particle count.", metadata_path);
339 PetscCall(PetscOptionsGetBool(options, NULL,
"-checkpoint_particles", &saved_particles, &found));
340 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
341 "Checkpoint '%s' does not record particle-state availability.", metadata_path);
342 PetscCall(PetscOptionsGetBool(options, NULL,
"-checkpoint_les", &saved_les, &found));
343 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
344 "Checkpoint '%s' does not record LES-state availability.", metadata_path);
345 PetscCall(PetscOptionsGetBool(options, NULL,
"-checkpoint_rans", &saved_rans, &found));
346 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
347 "Checkpoint '%s' does not record RANS-state availability.", metadata_path);
348 for (PetscInt payload = 0; payload < payload_count; ++payload) {
349 char option_name[96];
350 char relative_path[PETSC_MAX_PATH_LEN];
351 char payload_path[PETSC_MAX_PATH_LEN];
352 long long expected_bytes = -1;
353 char expected_bytes_text[64];
354 struct stat payload_stat;
356 PetscCall(PetscSNPrintf(option_name,
sizeof(option_name),
357 "-checkpoint_payload_%" PetscInt_FMT
"_path", payload));
358 PetscCall(PetscOptionsGetString(options, NULL, option_name,
359 relative_path,
sizeof(relative_path), &found));
360 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
361 "Checkpoint payload %" PetscInt_FMT
" has no path.", payload);
362 PetscCall(PetscSNPrintf(option_name,
sizeof(option_name),
363 "-checkpoint_payload_%" PetscInt_FMT
"_bytes", payload));
364 PetscCall(PetscOptionsGetString(options, NULL, option_name,
365 expected_bytes_text,
sizeof(expected_bytes_text), &found));
366 if (found) expected_bytes = strtoll(expected_bytes_text, NULL, 10);
367 PetscCheck(found && expected_bytes >= 0, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
368 "Checkpoint payload %" PetscInt_FMT
" has no valid byte size.", payload);
369 PetscCall(PetscSNPrintf(payload_path,
sizeof(payload_path),
"%s/%s",
370 checkpoint_directory, relative_path));
371 PetscCheck(stat(payload_path, &payload_stat) == 0 && S_ISREG(payload_stat.st_mode),
372 PETSC_COMM_WORLD, PETSC_ERR_FILE_OPEN,
373 "Checkpoint payload is missing: %s", payload_path);
374 PetscCheck((
long long)payload_stat.st_size == expected_bytes,
375 PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
376 "Checkpoint payload '%s' is %lld bytes; expected %lld.",
377 payload_path, (
long long)payload_stat.st_size, expected_bytes);
379 PetscCall(PetscOptionsDestroy(&options));
380 if (physical_time) *physical_time = saved_time;
381 if (particle_count) *particle_count = saved_particle_count;
382 if (particles_saved) *particles_saved = saved_particles;
383 if (les_saved) *les_saved = saved_les;
384 if (rans_saved) *rans_saved = saved_rans;
385 PetscFunctionReturn(0);
401 if (str[0] ==
'\0')
return;
405 while (isspace((
unsigned char)*start)) {
410 char *end = str + strlen(str) - 1;
412 while (end > start && isspace((
unsigned char)*end)) {
421 memmove(str, start, (end - start) + 2);
437 return (PetscBool)(simCtx->
tiout > 0 && completed_step > 0 && completed_step % simCtx->
tiout == 0);
442#define __FUNCT__ "ReadGridGenerationInputs"
452 PetscInt block_index = user->
_this;
456 PetscInt *IMs = NULL, *JMs = NULL, *KMs = NULL, *cgrids = NULL;
457 PetscReal *xMins = NULL, *xMaxs = NULL, *rxs = NULL;
458 PetscReal *yMins = NULL, *yMaxs = NULL, *rys = NULL;
459 PetscReal *zMins = NULL, *zMaxs = NULL, *rzs = NULL;
461 PetscFunctionBeginUser;
466 if (block_index >= nblk) {
467 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
"Block index %d is out of range for nblk=%d", block_index, nblk);
471 ierr = PetscMalloc4(nblk, &IMs, nblk, &JMs, nblk, &KMs, nblk, &cgrids); CHKERRQ(ierr);
472 ierr = PetscMalloc6(nblk, &xMins, nblk, &xMaxs, nblk, &rxs, nblk, &yMins, nblk, &yMaxs, nblk, &rys); CHKERRQ(ierr);
473 ierr = PetscMalloc3(nblk, &zMins, nblk, &zMaxs, nblk, &rzs); CHKERRQ(ierr);
476 for (PetscInt i = 0; i < nblk; ++i) {
477 IMs[i] = 10; JMs[i] = 10; KMs[i] = 10; cgrids[i] = 0;
478 xMins[i] = 0.0; xMaxs[i] = 1.0; rxs[i] = 1.0;
479 yMins[i] = 0.0; yMaxs[i] = 1.0; rys[i] = 1.0;
480 zMins[i] = 0.0; zMaxs[i] = 1.0; rzs[i] = 1.0;
485 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-im", IMs, &count, &found); CHKERRQ(ierr);
486 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-jm", JMs, &count, &found); CHKERRQ(ierr);
487 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-km", KMs, &count, &found); CHKERRQ(ierr);
488 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-xMins", xMins, &count, &found); CHKERRQ(ierr);
489 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-xMaxs", xMaxs, &count, &found); CHKERRQ(ierr);
490 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-rxs", rxs, &count, &found); CHKERRQ(ierr);
491 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-yMins", yMins, &count, &found); CHKERRQ(ierr);
492 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-yMaxs", yMaxs, &count, &found); CHKERRQ(ierr);
493 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-rys", rys, &count, &found); CHKERRQ(ierr);
494 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-zMins", zMins, &count, &found); CHKERRQ(ierr);
495 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-zMaxs", zMaxs, &count, &found); CHKERRQ(ierr);
496 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-rzs", rzs, &count, &found); CHKERRQ(ierr);
497 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-cgrids", cgrids, &count, &found); CHKERRQ(ierr);
500 user->
IM = IMs[block_index];
501 user->
JM = JMs[block_index];
502 user->
KM = KMs[block_index];
503 user->
Min_X = xMins[block_index];
504 user->
Max_X = xMaxs[block_index];
505 user->
rx = rxs[block_index];
506 user->
Min_Y = yMins[block_index];
507 user->
Max_Y = yMaxs[block_index];
508 user->
ry = rys[block_index];
509 user->
Min_Z = zMins[block_index];
510 user->
Max_Z = zMaxs[block_index];
511 user->
rz = rzs[block_index];
512 user->
cgrid = cgrids[block_index];
515 simCtx->
rank, block_index, user->
IM, user->
JM, user->
KM);
520 ierr = PetscFree4(IMs, JMs, KMs, cgrids); CHKERRQ(ierr);
521 ierr = PetscFree6(xMins, xMaxs, rxs, yMins, yMaxs, rys); CHKERRQ(ierr);
522 ierr = PetscFree3(zMins, zMaxs, rzs); CHKERRQ(ierr);
525 PetscFunctionReturn(0);
536 PetscInt *IMs = NULL, *JMs = NULL, *KMs = NULL;
539 PetscFunctionBeginUser;
542 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"finest_users cannot be NULL.");
545 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
"nblk must be positive. Got %d.", nblk);
547 simCtx = finest_users[0].
simCtx;
549 ierr = PetscMalloc3(nblk, &IMs, nblk, &JMs, nblk, &KMs); CHKERRQ(ierr);
550 for (PetscInt i = 0; i < nblk; ++i) {
551 IMs[i] = 10; JMs[i] = 10; KMs[i] = 10;
555 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-im", IMs, &count, &found); CHKERRQ(ierr);
556 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-jm", JMs, &count, &found); CHKERRQ(ierr);
557 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-km", KMs, &count, &found); CHKERRQ(ierr);
559 for (PetscInt bi = 0; bi < nblk; ++bi) {
560 finest_users[bi].
IM = IMs[bi];
561 finest_users[bi].
JM = JMs[bi];
562 finest_users[bi].
KM = KMs[bi];
565 "Rank %d: Preloaded analytical grid resolution for block %d: IM=%d, JM=%d, KM=%d\n",
566 simCtx->
rank, bi, finest_users[bi].
IM, finest_users[bi].
JM, finest_users[bi].
KM);
570 ierr = PetscFree3(IMs, JMs, KMs); CHKERRQ(ierr);
571 PetscFunctionReturn(0);
576#define __FUNCT__ "ReadGridFile"
585 PetscInt block_index = user->
_this;
587 PetscFunctionBeginUser;
593 PetscMPIInt rank = simCtx->
rank;
597 FILE *fd = fopen(simCtx->
grid_file,
"r");
598 if (!fd) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Cannot open file: %s", simCtx->
grid_file);
601 char firstTok[32] = {0};
602 if (fscanf(fd,
"%31s", firstTok) != 1)
603 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
"Empty grid file: %s", simCtx->
grid_file);
604 if (strcmp(firstTok,
"PICGRID") != 0)
605 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
606 "Grid file %s must begin with the canonical PICGRID header.", simCtx->
grid_file);
608 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
"Expected number of blocks after \"PICGRID\" in %s", simCtx->
grid_file);
610 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED,
"Mismatch: -nblk is %d but grid file specifies %d blocks.", nblk,
g_nblk_from_file);
614 for (PetscInt i = 0; i < nblk; ++i) {
616 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
"Expected 3 integers for block %d in %s", i, simCtx->
grid_file);
623 ierr = MPI_Bcast(&
g_nblk_from_file, 1, MPI_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
631 ierr = MPI_Bcast(
g_IMs_from_file, nblk, MPI_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
632 ierr = MPI_Bcast(
g_JMs_from_file, nblk, MPI_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
633 ierr = MPI_Bcast(
g_KMs_from_file, nblk, MPI_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
645 simCtx->
rank, block_index, user->
IM, user->
JM, user->
KM);
648 PetscFunctionReturn(0);
666 while (current != NULL) {
668 PetscFree(current->
key);
669 PetscFree(current->
value);
681 else if (strcasecmp(str,
"+Xi") == 0) *face_out =
BC_FACE_POS_X;
682 else if (strcasecmp(str,
"-Eta") == 0) *face_out =
BC_FACE_NEG_Y;
683 else if (strcasecmp(str,
"+Eta") == 0) *face_out =
BC_FACE_POS_Y;
684 else if (strcasecmp(str,
"-Zeta") == 0) *face_out =
BC_FACE_NEG_Z;
685 else if (strcasecmp(str,
"+Zeta") == 0) *face_out =
BC_FACE_POS_Z;
686 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE,
"Unknown face specifier: %s", str);
695 if (strcasecmp(str,
"WALL") == 0) *type_out =
WALL;
696 else if (strcasecmp(str,
"SYMMETRY") == 0) *type_out =
SYMMETRY;
697 else if (strcasecmp(str,
"INLET") == 0) *type_out =
INLET;
698 else if (strcasecmp(str,
"OUTLET") == 0) *type_out =
OUTLET;
699 else if (strcasecmp(str,
"PERIODIC") == 0) *type_out =
PERIODIC;
701 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE,
"Unknown BC Type string: %s", str);
719 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE,
"Unknown BC Handler string: %s", str);
753 *found = PETSC_FALSE;
759 if (strcasecmp(current->
key, key) == 0) {
760 *value_out = atof(current->
value);
764 current = current->
next;
774 *found = PETSC_FALSE;
775 *value_out = PETSC_FALSE;
780 if (strcasecmp(current->
key, key) == 0) {
785 if (current->
value &&
786 (strcasecmp(current->
value,
"true") == 0 ||
787 strcmp(current->
value,
"1") == 0 ||
788 strcasecmp(current->
value,
"yes") == 0))
790 *value_out = PETSC_TRUE;
792 *value_out = PETSC_FALSE;
796 current = current->
next;
802#define __FUNCT__ "GetDrivenSeamFluxFlag"
817 PetscFunctionBeginUser;
819 ierr =
GetBCParamBool(params,
"enforce_seam_flux", value_out, found); CHKERRQ(ierr);
821 ierr =
GetBCParamBool(params,
"apply_trim", value_out, found); CHKERRQ(ierr);
823 PetscFunctionReturn(0);
832#define __FUNCT__ "ParseAllBoundaryConditions"
845 PetscFunctionBeginUser;
847 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
851 char line_buffer[1024];
854 for (
int i = 0; i < 6; i++) {
858 configs_rank0[i].
params = NULL;
859 configs_rank0[i].
handler = NULL;
863 file = fopen(bcs_input_filename,
"r");
864 if (!file) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Could not open BCs file '%s'.", bcs_input_filename);
866 while (fgets(line_buffer,
sizeof(line_buffer), file)) {
867 char *current_pos = line_buffer;
868 while (isspace((
unsigned char)*current_pos)) current_pos++;
869 if (*current_pos ==
'#' || *current_pos ==
'\0' || *current_pos ==
'\n' || *current_pos ==
'\r')
continue;
871 char *face_str = strtok(current_pos,
" \t\n\r");
872 char *type_str = strtok(NULL,
" \t\n\r");
873 char *handler_str = strtok(NULL,
" \t\n\r");
875 if (!face_str || !type_str || !handler_str) {
883 const char* handler_name_for_log;
890 if (ierr) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"Validation failed: Handler '%s' is not valid for Type '%s' on Face '%s'.\n", handler_str, type_str, face_str);
896 LOG_ALLOW(
GLOBAL,
LOG_DEBUG,
" Parsed Face '%s': Type=%s, Handler=%s \n", face_str, type_str, handler_name_for_log);
900 configs_rank0[face_enum].
params = NULL;
904 while ((token = strtok(NULL,
" \t\n\r")) != NULL) {
905 char* equals_ptr = strchr(token,
'=');
912 char* key_str = token;
913 char* value_str = equals_ptr + 1;
916 ierr = PetscMalloc1(1, &new_param); CHKERRQ(ierr);
917 ierr = PetscStrallocpy(key_str, &new_param->
key); CHKERRQ(ierr);
918 ierr = PetscStrallocpy(value_str, &new_param->
value); CHKERRQ(ierr);
919 new_param->
next = NULL;
921 *param_next_ptr = new_param;
922 param_next_ptr = &new_param->
next;
936 for (
int i = 0; i < 6; i++) {
945 PetscInt n_params = 0;
949 ierr = MPI_Bcast(&n_params, 1, MPI_INT, 0, PETSC_COMM_WORLD);CHKERRQ(ierr);
958 for (
int j = 0; j < n_params; j++) {
959 char key_buf[256] = {0}, val_buf[256] = {0};
963 for (
int k = 0; k < j; k++) p = p->
next;
964 strncpy(key_buf, p->
key, 255);
965 strncpy(val_buf, p->
value, 255);
968 ierr = MPI_Bcast(key_buf, 256, MPI_CHAR, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
969 ierr = MPI_Bcast(val_buf, 256, MPI_CHAR, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
974 ierr = PetscMalloc1(1, &new_param); CHKERRQ(ierr);
975 ierr = PetscStrallocpy(key_buf, &new_param->
key); CHKERRQ(ierr);
976 ierr = PetscStrallocpy(val_buf, &new_param->
value); CHKERRQ(ierr);
977 new_param->
next = NULL;
978 *param_next_ptr = new_param;
979 param_next_ptr = &new_param->
next;
982 param_next_ptr = &((*param_next_ptr)->next);
990 for (
int i=0; i<6; i++) {
1008 PetscFunctionReturn(0);
1019#define __FUNCT__ "DeterminePeriodicity"
1026 PetscErrorCode ierr;
1028 PetscInt periodic_flags[3] = {0, 0, 0};
1030 PetscFunctionBeginUser;
1031 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1034 for (PetscInt bi = 0; bi < simCtx->
block_number; bi++) {
1035 const char *bcs_filename = simCtx->
bcs_files[bi];
1036 if (!bcs_filename) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_NULL,
"BCS filename for block %d is not set in SimCtx.", bi);
1038 PetscBool file_exists;
1039 snprintf(desc_buf,
sizeof(desc_buf),
"BCS file for block %d", bi);
1040 ierr =
VerifyPathExistence(bcs_filename, PETSC_FALSE, PETSC_FALSE, desc_buf, &file_exists); CHKERRQ(ierr);
1045 PetscBool global_is_periodic[3] = {PETSC_FALSE, PETSC_FALSE, PETSC_FALSE};
1046 PetscBool is_set = PETSC_FALSE;
1048 for (PetscInt bi = 0; bi < simCtx->
block_number; bi++) {
1049 const char *bcs_filename = simCtx->
bcs_files[bi];
1050 FILE *file = fopen(bcs_filename,
"r");
1052 PetscBool face_is_periodic[6] = {PETSC_FALSE};
1053 char line_buffer[1024];
1055 while (fgets(line_buffer,
sizeof(line_buffer), file)) {
1056 char *current_pos = line_buffer;
1057 while (isspace((
unsigned char)*current_pos)) current_pos++;
1058 if (*current_pos ==
'#' || *current_pos ==
'\0' || *current_pos ==
'\n')
continue;
1061 char *face_str = strtok(current_pos,
" \t\n\r");
1062 char *type_str = strtok(NULL,
" \t\n\r");
1065 if (!face_str || !type_str)
continue;
1068 if (strcasecmp(type_str,
"PERIODIC") == 0) {
1072 face_is_periodic[face_enum] = PETSC_TRUE;
1080 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
"Inconsistent X-periodicity in file '%s' for block %d. Both -Xi and +Xi must be periodic or neither.", bcs_filename, bi);
1082 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
"Inconsistent Y-periodicity in file '%s' for block %d. Both -Eta and +Eta must be periodic or neither.", bcs_filename, bi);
1084 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
"Inconsistent Z-periodicity in file '%s' for block %d. Both -Zeta and +Zeta must be periodic or neither.", bcs_filename, bi);
1090 global_is_periodic[0] = local_is_periodic[0];
1091 global_is_periodic[1] = local_is_periodic[1];
1092 global_is_periodic[2] = local_is_periodic[2];
1093 is_set = PETSC_TRUE;
1095 if (global_is_periodic[0] != local_is_periodic[0] || global_is_periodic[1] != local_is_periodic[1] || global_is_periodic[2] != local_is_periodic[2]) {
1096 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
1097 "Periodicity mismatch between blocks. Block 0 requires (I:%d, J:%d, K:%d), but block %d (file '%s') has (I:%d, J:%d, K:%d).",
1098 (
int)global_is_periodic[0], (
int)global_is_periodic[1], (
int)global_is_periodic[2],
1100 (
int)local_is_periodic[0], (
int)local_is_periodic[1], (
int)local_is_periodic[2]);
1105 periodic_flags[0] = (global_is_periodic[0]) ? 1 : 0;
1106 periodic_flags[1] = (global_is_periodic[1]) ? 1 : 0;
1107 periodic_flags[2] = (global_is_periodic[2]) ? 1 : 0;
1110 periodic_flags[0], periodic_flags[1], periodic_flags[2]);
1114 ierr = MPI_Bcast(periodic_flags, 3, MPIU_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
1121 PetscFunctionReturn(0);
1128PetscErrorCode
VerifyPathExistence(
const char *path, PetscBool is_dir, PetscBool is_optional,
const char *description, PetscBool *exists)
1130 PetscErrorCode ierr;
1132 MPI_Comm comm = PETSC_COMM_WORLD;
1134 PetscFunctionBeginUser;
1135 ierr = MPI_Comm_rank(comm, &rank); CHKERRQ(ierr);
1139 ierr = PetscTestDirectory(path,
'r', exists); CHKERRQ(ierr);
1141 ierr = PetscTestFile(path,
'r', exists); CHKERRQ(ierr);
1156 PetscMPIInt exists_int = (rank == 0) ? (PetscMPIInt)(*exists) : 0;
1157 ierr = MPI_Bcast(&exists_int, 1, MPI_INT, 0, comm); CHKERRMPI(ierr);
1158 *exists = (PetscBool)exists_int;
1161 if (!(*exists) && !is_optional) {
1162 SETERRQ(comm, PETSC_ERR_FILE_OPEN,
"Mandatory %s not found. Rank 0 expected it at '%s'. Check path and permissions.", description, path);
1165 PetscFunctionReturn(0);
1169#define __FUNCT__ "ReadFieldData"
1175 const char *field_name,
1179 PetscErrorCode ierr;
1180 char filename[PETSC_MAX_PATH_LEN];
1182 PetscMPIInt rank,size;
1186 PetscFunctionBeginUser;
1190 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,
"I/O context directory was not set before calling ReadFieldData().");
1194 ierr = PetscObjectGetComm((PetscObject)field_vec,&comm);CHKERRQ(ierr);
1195 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1196 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1198 const char *source_path = NULL;
1202 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,
"source_path was not set for the current execution mode.");
1204 ierr = PetscSNPrintf(filename,
sizeof(filename),
"%s/%s.%s",
1205 source_path, field_name, ext); CHKERRQ(ierr);
1208 "Attempting to read <%s> on rank %d/%d\n",
1209 filename,(
int)rank,(
int)size);
1219 PetscInt expectedSize,loadedSize;
1221 ierr = PetscTestFile(filename,
'r',&found);CHKERRQ(ierr);
1222 if(!found) SETERRQ(comm,PETSC_ERR_FILE_OPEN,
1223 "Restart/Source file not found: %s",filename);
1225 ierr = PetscViewerBinaryOpen(PETSC_COMM_SELF,filename,FILE_MODE_READ,&viewer);CHKERRQ(ierr);
1229 ierr = VecCreate(PETSC_COMM_SELF, &temp_vec); CHKERRQ(ierr);
1230 ierr = VecLoad(temp_vec,viewer);CHKERRQ(ierr);
1231 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1234 ierr = VecGetSize(field_vec, &expectedSize);CHKERRQ(ierr);
1235 ierr = VecGetSize(temp_vec, &loadedSize);CHKERRQ(ierr);
1236 if (loadedSize != expectedSize) {
1237 SETERRQ(comm,PETSC_ERR_FILE_UNEXPECTED,
1238 "File %s holds %d entries – expected %d for field '%s'",
1239 filename, loadedSize, expectedSize, field_name);
1243 ierr = VecCopy(temp_vec, field_vec);CHKERRQ(ierr);
1246 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1262 "Loaded <%s> (serial path)\n",filename);
1265 PetscFunctionReturn(0);
1271 PetscInt globalSize;
1272 ierr = VecGetSize(field_vec,&globalSize);CHKERRQ(ierr);
1275 const char *dmtype = NULL;
1280 const PetscScalar *seqArray = NULL;
1287 ierr = PetscTestFile(filename,
'r',&found);CHKERRQ(ierr);
1288 if(!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,
1289 "Restart file not found: %s",filename);
1292 ierr = VecCreate(PETSC_COMM_SELF,&seq_vec);CHKERRQ(ierr);
1293 ierr = VecSetType(seq_vec,VECSEQ);CHKERRQ(ierr);
1295 ierr = PetscViewerBinaryOpen(PETSC_COMM_SELF,filename,
1296 FILE_MODE_READ,&viewer);CHKERRQ(ierr);
1297 ierr = VecLoad(seq_vec,viewer);CHKERRQ(ierr);
1298 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1302 ierr = VecGetSize(seq_vec,&loaded);CHKERRQ(ierr);
1303 if(loaded != globalSize)
1304 SETERRQ(comm,PETSC_ERR_FILE_UNEXPECTED,
1305 "File %s holds %d entries – expected %d",
1306 filename,loaded,globalSize);
1309 ierr = VecGetArrayRead(seq_vec,&seqArray);CHKERRQ(ierr);
1312 "Rank 0 successfully loaded <%s>\n",filename);
1316 ierr = VecGetDM(field_vec, &dm); CHKERRQ(ierr);
1317 if (dm) { ierr = DMGetType(dm, &dmtype); CHKERRQ(ierr); }
1319 if (dmtype && !strcmp(dmtype, DMDA)) {
1325 ierr = DMDACreateNaturalVector(dm, &nat); CHKERRQ(ierr);
1331 ierr = VecScatterCreateToZero(nat, &scatter, &nat_seq); CHKERRQ(ierr);
1334 ierr = VecScatterBegin(scatter, (rank == 0 ? seq_vec : nat_seq), nat,
1335 INSERT_VALUES, SCATTER_REVERSE); CHKERRQ(ierr);
1336 ierr = VecScatterEnd(scatter, (rank == 0 ? seq_vec : nat_seq), nat,
1337 INSERT_VALUES, SCATTER_REVERSE); CHKERRQ(ierr);
1340 ierr = DMDANaturalToGlobalBegin(dm, nat, INSERT_VALUES, field_vec); CHKERRQ(ierr);
1341 ierr = DMDANaturalToGlobalEnd(dm, nat, INSERT_VALUES, field_vec); CHKERRQ(ierr);
1344 ierr = VecScatterDestroy(&scatter); CHKERRQ(ierr);
1345 ierr = VecDestroy(&nat_seq); CHKERRQ(ierr);
1346 ierr = VecDestroy(&nat); CHKERRQ(ierr);
1353 PetscScalar *buffer = NULL;
1355 buffer = (PetscScalar *)seqArray;
1357 ierr = PetscMalloc1(globalSize, &buffer); CHKERRQ(ierr);
1360 ierr = MPI_Bcast(buffer, (
int)globalSize, MPIU_SCALAR, 0, comm); CHKERRQ(ierr);
1363 PetscInt rstart, rend, loc;
1364 PetscScalar *locArray;
1366 ierr = VecGetOwnershipRange(field_vec, &rstart, &rend); CHKERRQ(ierr);
1367 loc = rend - rstart;
1369 ierr = VecGetArray(field_vec, &locArray); CHKERRQ(ierr);
1370 ierr = PetscMemcpy(locArray, buffer + rstart, loc *
sizeof(PetscScalar)); CHKERRQ(ierr);
1371 ierr = VecRestoreArray(field_vec, &locArray); CHKERRQ(ierr);
1374 ierr = PetscFree(buffer); CHKERRQ(ierr);
1380 ierr = VecRestoreArrayRead(seq_vec, &seqArray); CHKERRQ(ierr);
1381 ierr = VecDestroy(&seq_vec); CHKERRQ(ierr);
1385 "Loaded <%s> (parallel path)\n",filename);
1388 PetscFunctionReturn(0);
1393#define __FUNCT__ "RestoreDrivenFluxTarget"
1413 const char *checkpoint_directory)
1415 char metadata_path[PETSC_MAX_PATH_LEN];
1416 PetscOptions options = NULL;
1417 PetscBool uses_initial_flux = PETSC_FALSE;
1418 PetscBool saved_latched = PETSC_FALSE;
1419 PetscBool found = PETSC_FALSE;
1420 PetscReal saved_target = 0.0;
1422 PetscFunctionBeginUser;
1424 for (PetscInt face = 0; face < 6; ++face) {
1426 uses_initial_flux = PETSC_TRUE;
1430 if (!uses_initial_flux) PetscFunctionReturn(0);
1432 PetscCall(PetscSNPrintf(metadata_path,
sizeof(metadata_path),
1433 "%s/checkpoint.meta", checkpoint_directory));
1434 PetscCall(PetscOptionsCreate(&options));
1435 PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, metadata_path, PETSC_TRUE));
1436 PetscCall(PetscOptionsGetBool(options, NULL,
"-checkpoint_driven_flux_latched", &saved_latched, &found));
1437 if (found && saved_latched) {
1438 PetscCall(PetscOptionsGetReal(options, NULL,
"-checkpoint_driven_flux_target", &saved_target, &found));
1440 found = PETSC_FALSE;
1442 PetscCall(PetscOptionsDestroy(&options));
1448 "Driven Flow: restored latched target volumetric flux %.6e from checkpoint '%s'.\n",
1449 (
double)saved_target, checkpoint_directory);
1452 "Driven Flow: checkpoint '%s' records no latched flux target; the initial_flux "
1453 "controller will re-measure it from the restarted field.\n", checkpoint_directory);
1456 PetscFunctionReturn(0);
1466 const char *source_path = NULL;
1467 char checkpoint_directory[PETSC_MAX_PATH_LEN];
1468 PetscReal checkpoint_time = 0.0;
1469 PetscBool particles_saved = PETSC_FALSE;
1470 PetscBool les_saved = PETSC_FALSE;
1471 PetscBool rans_saved = PETSC_FALSE;
1473 PetscFunctionBeginUser;
1479 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"Invalid execution mode for reading simulation fields.");
1483 checkpoint_directory,
sizeof(checkpoint_directory)));
1485 checkpoint_directory, ti, &checkpoint_time, NULL,
1486 &particles_saved, &les_saved, &rans_saved));
1488 PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
1489 "Particle restart_mode=load was requested, but checkpoint step %" PetscInt_FMT
1490 " contains no particle state.", ti);
1492 simCtx->
ti = checkpoint_time;
1498 user->
_this, checkpoint_directory);
1500 "%s/%s/block_%04" PetscInt_FMT,
1515 !((simCtx->
les && les_saved) || (simCtx->
rans && rans_saved)))
continue;
1526 PetscFunctionReturn(0);
1531#define __FUNCT__ "ReadStatisticsWindowState"
1534 const char *metadata_path, PetscReal checkpoint_time,
1538 char option_name[128];
1540 char saved_digest[65] =
"";
1542 char saved_state[32] =
"";
1543 char current_digest[65] =
"";
1544 PetscBool found = PETSC_FALSE;
1545 PetscBool name_matches = PETSC_FALSE;
1547 PetscFunctionBeginUser;
1550#define PICURV_STATISTICS_REQUIRE(suffix, getter, target) \
1552 PetscCall(PetscSNPrintf(option_name, sizeof(option_name), \
1553 "-checkpoint_statistics_window_%" PetscInt_FMT "_" suffix, window)); \
1554 PetscCall(getter(options, NULL, option_name, target, &found)); \
1555 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED, \
1556 "Statistics continuation requested, but '%s' records no %s for window " \
1557 "%" PetscInt_FMT ".", metadata_path, suffix, window); \
1560 PetscCall(PetscSNPrintf(option_name,
sizeof(option_name),
1561 "-checkpoint_statistics_window_%" PetscInt_FMT
"_name", window));
1562 PetscCall(PetscOptionsGetString(options, NULL, option_name, saved_name,
sizeof(saved_name), &found));
1563 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
1564 "Statistics continuation requested, but '%s' records no name for window %" PetscInt_FMT
".",
1565 metadata_path, window);
1566 PetscCall(PetscStrcmp(saved_name, state->
definition.
name, &name_matches));
1567 PetscCheck(name_matches, PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
1568 "Statistics window %" PetscInt_FMT
" is '%s' in the checkpoint but '%s' in this run. "
1569 "Window order and names must match to continue.",
1572 PetscCall(PetscSNPrintf(option_name,
sizeof(option_name),
1573 "-checkpoint_statistics_window_%" PetscInt_FMT
"_hash", window));
1574 PetscCall(PetscOptionsGetString(options, NULL, option_name, saved_digest,
sizeof(saved_digest), &found));
1575 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
1576 "Statistics continuation requested, but '%s' records no hash for window '%s'.",
1579 if (strcmp(saved_digest, current_digest)) {
1580 const char *differing =
"an unrecorded property";
1585 PetscCall(PetscSNPrintf(option_name,
sizeof(option_name),
1586 "-checkpoint_statistics_window_%" PetscInt_FMT
"_hash_groups", window));
1587 PetscCall(PetscOptionsGetString(options, NULL, option_name, saved_groups,
1588 sizeof(saved_groups), &found));
1590 PetscInt group = -1;
1595 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
1596 "Statistics window '%s' was defined differently in the checkpoint: %s changed. "
1597 "Continuing would merge incompatible samples; rename the window to start a new one.",
1611#undef PICURV_STATISTICS_REQUIRE
1613 PetscCall(PetscSNPrintf(option_name,
sizeof(option_name),
1614 "-checkpoint_statistics_window_%" PetscInt_FMT
"_state", window));
1615 PetscCall(PetscOptionsGetString(options, NULL, option_name, saved_state,
sizeof(saved_state), &found));
1616 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
1617 "Statistics continuation requested, but '%s' records no lifecycle state for window '%s'.",
1631 PetscCheck(checkpoint_time - state->
effective_end <= PetscMax(step_size, 0.0),
1632 PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
1633 "Statistics window '%s' ended at t=%.17g and this checkpoint is at t=%.17g, "
1634 "so extending it to %.17g would weight %.17g of unobserved time. "
1635 "Start a new window instead.",
1640 "Statistics window '%s' was complete at t=%.6g and is extended to t=%.6g.\n",
1646 PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
1647 "Statistics window '%s' already represents time up to %.17g, past the requested end "
1648 "%.17g. A window may be extended forward but never shortened; rename it to start a new one.",
1656 PetscFunctionReturn(0);
1660#define __FUNCT__ "RestoreFieldStatisticsState"
1670 PetscOptions options = NULL;
1671 char checkpoint_directory[PETSC_MAX_PATH_LEN];
1672 char metadata_path[PETSC_MAX_PATH_LEN];
1673 const char *source_path = NULL;
1674 PetscInt saved_window_count = 0;
1675 PetscReal checkpoint_time = 0.0;
1676 PetscBool found = PETSC_FALSE;
1678 PetscFunctionBeginUser;
1680 PetscCheck(simCtx != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"SimCtx cannot be NULL.");
1684 "Statistics continuation was not requested; %d window(s) start from zero.\n",
1687 PetscFunctionReturn(0);
1691 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
1692 "Finest-level fields must exist before statistics state is restored.");
1695 PetscCheck(source_path != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
1696 "No checkpoint source directory is set for the current execution mode.");
1698 checkpoint_directory,
sizeof(checkpoint_directory)));
1700 &checkpoint_time, NULL, NULL, NULL, NULL));
1701 PetscCall(PetscSNPrintf(metadata_path,
sizeof(metadata_path),
"%s/checkpoint.meta",
1702 checkpoint_directory));
1704 PetscCall(PetscOptionsCreate(&options));
1705 PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, metadata_path, PETSC_TRUE));
1706 PetscCall(PetscOptionsGetInt(options, NULL,
"-checkpoint_statistics_window_count",
1707 &saved_window_count, &found));
1712 PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
1713 "Statistics continuation requested, but checkpoint '%s' holds %" PetscInt_FMT
1714 " window(s) and this run configures %" PetscInt_FMT
".",
1715 checkpoint_directory, found ? saved_window_count : 0,
1723 PetscCall(PetscOptionsDestroy(&options));
1725 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
1726 PetscCheck(user[block].fieldStatisticsStorage != NULL, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
1727 "Statistics accumulators were not allocated for block %" PetscInt_FMT
".", block);
1731 PetscInt payload_count = 0;
1738 for (PetscInt index = 0; index < payload_count; ++index) {
1752 "Statistics window '%s' continued from '%s': state %s, %d sample(s), "
1753 "total weight %.6g, represented time %.6g, restart segment %d.\n",
1760 PetscFunctionReturn(0);
1769 PetscErrorCode ierr;
1775 swarm = user->
swarm;
1780 ierr = DMSwarmCreateGlobalVectorFromField(swarm, field_name, &fieldVec);CHKERRQ(ierr);
1785 ierr =
ReadFieldData(user, field_name, fieldVec, ext);CHKERRQ(ierr);
1788 ierr = DMSwarmDestroyGlobalVectorFromField(swarm, field_name, &fieldVec);CHKERRQ(ierr);
1790 PetscFunctionReturn(0);
1799 PetscErrorCode ierr;
1800 DM swarm = user->
swarm;
1802 PetscInt nlocal, nglobal, bs, i;
1803 PetscDataType field_type;
1804 const PetscScalar *scalar_array;
1805 void *field_array_void;
1808 PetscFunctionBeginUser;
1813 ierr = DMSwarmGetLocalSize(swarm, &nlocal); CHKERRQ(ierr);
1814 ierr = DMSwarmGetSize(swarm, &nglobal); CHKERRQ(ierr);
1816 ierr = DMSwarmGetField(swarm, field_name, &bs, &field_type, NULL); CHKERRQ(ierr);
1817 ierr = DMSwarmRestoreField(swarm, field_name, &bs, NULL, NULL); CHKERRQ(ierr);
1818 PetscCheck(field_type == PETSC_INT || field_type == PETSC_INT64,
1819 PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
1820 "Swarm field '%s' must use PETSC_INT or PETSC_INT64 for integer restart input, not %s.",
1821 field_name, PetscDataTypes[field_type]);
1824 ierr = VecCreate(PETSC_COMM_WORLD, &temp_vec); CHKERRQ(ierr);
1825 ierr = VecSetType(temp_vec, VECMPI); CHKERRQ(ierr);
1826 ierr = VecSetSizes(temp_vec, nlocal * bs, nglobal * bs); CHKERRQ(ierr);
1827 ierr = VecSetBlockSize(temp_vec, bs); CHKERRQ(ierr);
1828 ierr = VecSetUp(temp_vec); CHKERRQ(ierr);
1831 ierr =
ReadFieldData(user, field_name, temp_vec, ext); CHKERRQ(ierr);
1834 ierr = VecGetArrayRead(temp_vec, &scalar_array); CHKERRQ(ierr);
1835 ierr = DMSwarmGetField(swarm, field_name, NULL, NULL, &field_array_void); CHKERRQ(ierr);
1838 if (field_type == PETSC_INT64) {
1839 PetscInt64 *int64_array = (PetscInt64 *)field_array_void;
1840 for (i = 0; i < nlocal * bs; i++) {
1841 int64_array[i] = (PetscInt64)scalar_array[i];
1844 PetscInt *int_array = (PetscInt *)field_array_void;
1845 for (i = 0; i < nlocal * bs; i++) {
1846 int_array[i] = (PetscInt)scalar_array[i];
1851 ierr = DMSwarmRestoreField(swarm, field_name, NULL, NULL, &field_array_void); CHKERRQ(ierr);
1852 ierr = VecRestoreArrayRead(temp_vec, &scalar_array); CHKERRQ(ierr);
1855 ierr = VecDestroy(&temp_vec); CHKERRQ(ierr);
1857 PetscFunctionReturn(0);
1868 const char *source_path = NULL;
1869 char checkpoint_directory[PETSC_MAX_PATH_LEN];
1871 PetscFunctionBeginUser;
1872 PetscCall(DMSwarmGetSize(user->
swarm, &nGlobal));
1877 PetscFunctionReturn(0);
1886 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
"Invalid execution mode for reading simulation fields.");
1890 checkpoint_directory,
sizeof(checkpoint_directory)));
1910 PetscFunctionReturn(0);
1917 const char *source_path = NULL;
1918 char checkpoint_directory[PETSC_MAX_PATH_LEN];
1919 PetscBool particles_saved = PETSC_FALSE;
1921 PetscFunctionBeginUser;
1922 PetscCheck(user != NULL && particle_count != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
1923 "Simulation context and particle-count output are required.");
1927 else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
1928 "Invalid execution mode for reading checkpoint particle metadata.");
1931 checkpoint_directory,
sizeof(checkpoint_directory)));
1933 checkpoint_directory, ti, NULL, particle_count,
1934 &particles_saved, NULL, NULL));
1935 PetscCheck(particles_saved, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
1936 "Checkpoint step %" PetscInt_FMT
" contains no particle state.", ti);
1937 PetscFunctionReturn(0);
1942#define __FUNCT__ "WriteFieldData"
1948 const char *field_name,
1954 Vec sequential_vec = NULL;
1955 char filename[PETSC_MAX_PATH_LEN];
1958 PetscFunctionBeginUser;
1962 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,
"I/O context directory was not set before calling WriteFieldData().");
1968 PetscCall(PetscObjectGetComm((PetscObject)field_vec,&comm));
1969 PetscCallMPI(MPI_Comm_rank(comm,&rank));
1971 PetscCall(PetscSNPrintf(filename,
sizeof(filename),
"%s/%s.%s",
1977 PetscReal vmin, vmax;
1979 PetscCall(VecMin(sequential_vec, NULL, &vmin));
1980 PetscCall(VecMax(sequential_vec, NULL, &vmax));
1982 " <%s> range = [%.4e … %.4e]\n",
1983 field_name,(
double)vmin,(
double)vmax);
1984 PetscCall(PetscViewerBinaryOpen(PETSC_COMM_SELF, filename, FILE_MODE_WRITE, &viewer));
1985 PetscCall(PetscViewerBinarySetSkipInfo(viewer, PETSC_TRUE));
1986 PetscCall(VecView(sequential_vec, viewer));
1987 PetscCall(PetscViewerDestroy(&viewer));
1990 PetscCall(VecDestroy(&sequential_vec));
1993 PetscFunctionReturn(0);
2006 PetscFunctionBeginUser;
2007 PetscCheck(checkpoint_directory != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2008 "Checkpoint destination cannot be NULL.");
2010 "%s/%s/block_%04" PetscInt_FMT,
2028 PetscFunctionReturn(0);
2032#define __FUNCT__ "WriteStatisticsFields"
2038 PetscFunctionBeginUser;
2040 PetscCheck(checkpoint_directory != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2041 "Checkpoint destination cannot be NULL.");
2046 PetscInt payload_count = 0;
2053 for (PetscInt index = 0; index < payload_count; ++index) {
2057 storage, index, &payload));
2061 "Wrote %d statistics payload(s) for window '%s' block %d.\n",
2067 PetscFunctionReturn(0);
2078 PetscErrorCode ierr;
2082 PetscFunctionBeginUser;
2088 swarm = user->
swarm;
2096 "Attempting to create global vector from field: %s\n",
2098 ierr = DMSwarmCreateGlobalVectorFromField(swarm, field_name, &fieldVec);CHKERRQ(ierr);
2105 "Calling WriteFieldData for field: %s\n",
2107 ierr =
WriteFieldData(user, field_name, fieldVec, ext);CHKERRQ(ierr);
2115 "Destroying the global vector for field: %s\n",
2117 ierr = DMSwarmDestroyGlobalVectorFromField(swarm, field_name, &fieldVec);CHKERRQ(ierr);
2121 "Successfully wrote swarm data for field: %s\n",
2124 PetscFunctionReturn(0);
2133 PetscErrorCode ierr;
2134 DM swarm = user->
swarm;
2136 PetscInt nlocal, nglobal,bs,i;
2137 PetscDataType field_type;
2138 void *field_array_void;
2139 PetscScalar *scalar_array;
2141 PetscFunctionBeginUser;
2146 ierr = DMSwarmGetLocalSize(swarm, &nlocal); CHKERRQ(ierr);
2147 ierr = DMSwarmGetSize(swarm, &nglobal); CHKERRQ(ierr);
2148 ierr = DMSwarmGetField(swarm, field_name, &bs, &field_type, &field_array_void); CHKERRQ(ierr);
2149 PetscCheck(field_type == PETSC_INT || field_type == PETSC_INT64,
2150 PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
2151 "Swarm field '%s' must use PETSC_INT or PETSC_INT64 for integer output, not %s.",
2152 field_name, PetscDataTypes[field_type]);
2155 ierr = VecCreate(PETSC_COMM_WORLD, &temp_vec); CHKERRQ(ierr);
2156 ierr = VecSetType(temp_vec, VECMPI); CHKERRQ(ierr);
2157 ierr = VecSetSizes(temp_vec, nlocal*bs, nglobal*bs); CHKERRQ(ierr);
2158 ierr = VecSetUp(temp_vec); CHKERRQ(ierr);
2163 ierr = VecGetArray(temp_vec, &scalar_array); CHKERRQ(ierr);
2165 if (field_type == PETSC_INT64) {
2166 PetscInt64 *int64_array = (PetscInt64 *)field_array_void;
2168 for (i = 0; i < nlocal*bs; i++) {
2169 scalar_array[i] = (PetscScalar)int64_array[i];
2172 PetscInt *int_array = (PetscInt *)field_array_void;
2174 for (i = 0; i < nlocal*bs; i++) {
2175 scalar_array[i] = (PetscScalar)int_array[i];
2180 ierr = VecRestoreArray(temp_vec, &scalar_array); CHKERRQ(ierr);
2181 ierr = DMSwarmRestoreField(swarm, field_name, &bs, NULL, &field_array_void); CHKERRQ(ierr);
2184 ierr =
WriteFieldData(user, field_name, temp_vec, ext); CHKERRQ(ierr);
2187 ierr = VecDestroy(&temp_vec); CHKERRQ(ierr);
2189 PetscFunctionReturn(0);
2200 PetscFunctionBeginUser;
2203 if (!user->
swarm || simCtx->
np <= 0) {
2204 PetscFunctionReturn(0);
2207 PetscCheck(checkpoint_directory != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2208 "Checkpoint destination cannot be NULL.");
2227 PetscFunctionReturn(0);
2232 const char *checkpoint_directory,
2233 PetscInt payload_index,
2234 const char *relative_path,
2236 const char *field_name,
2239 PetscInt components,
2240 const char *logical_type,
2241 PetscInt global_size,
2242 const char *encoding)
2244 char payload_path[PETSC_MAX_PATH_LEN];
2245 struct stat payload_stat;
2247 PetscFunctionBeginUser;
2248 PetscCheck(manifest != NULL && checkpoint_directory != NULL && relative_path != NULL,
2249 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Checkpoint payload metadata inputs are required.");
2250 PetscCall(PetscSNPrintf(payload_path,
sizeof(payload_path),
"%s/%s",
2251 checkpoint_directory, relative_path));
2252 PetscCheck(stat(payload_path, &payload_stat) == 0 && S_ISREG(payload_stat.st_mode),
2253 PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
2254 "Expected checkpoint payload was not written: %s", payload_path);
2255 PetscCheck(fprintf(manifest,
2256 "-checkpoint_payload_%" PetscInt_FMT
"_path %s\n"
2257 "-checkpoint_payload_%" PetscInt_FMT
"_kind %s\n"
2258 "-checkpoint_payload_%" PetscInt_FMT
"_field %s\n"
2259 "-checkpoint_payload_%" PetscInt_FMT
"_block %" PetscInt_FMT
"\n"
2260 "-checkpoint_payload_%" PetscInt_FMT
"_layout %s\n"
2261 "-checkpoint_payload_%" PetscInt_FMT
"_components %" PetscInt_FMT
"\n"
2262 "-checkpoint_payload_%" PetscInt_FMT
"_logical_type %s\n"
2263 "-checkpoint_payload_%" PetscInt_FMT
"_global_size %" PetscInt_FMT
"\n"
2264 "-checkpoint_payload_%" PetscInt_FMT
"_encoding %s\n"
2265 "-checkpoint_payload_%" PetscInt_FMT
"_bytes %lld\n",
2266 payload_index, relative_path,
2267 payload_index, kind,
2268 payload_index, field_name,
2269 payload_index, block,
2270 payload_index, layout,
2271 payload_index, components,
2272 payload_index, logical_type,
2273 payload_index, global_size,
2274 payload_index, encoding,
2275 payload_index, (
long long)payload_stat.st_size) > 0,
2276 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2277 "Unable to append payload metadata for '%s'.", relative_path);
2278 PetscFunctionReturn(0);
2283 const char *checkpoint_directory,
2285 const char *geometry_digest,
2286 PetscInt particle_count,
2287 char manifest_digest[65])
2289 char metadata_path[PETSC_MAX_PATH_LEN];
2290 PetscInt payload_count = 0;
2291 PetscInt payload_index = 0;
2292 FILE *manifest = NULL;
2294 PetscFunctionBeginUser;
2295 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2302 if (simCtx->
np > 0) {
2310 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2311 if (!user[block].fieldStatisticsStorage)
continue;
2313 PetscInt storage_payloads = 0;
2316 &storage_payloads));
2317 payload_count += storage_payloads;
2322 if (simCtx->
rank == 0) {
2323 PetscCall(PetscSNPrintf(metadata_path,
sizeof(metadata_path),
2324 "%s/checkpoint.meta", checkpoint_directory));
2325 manifest = fopen(metadata_path,
"w");
2326 PetscCheck(manifest != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
2327 "Unable to create checkpoint metadata '%s'.", metadata_path);
2328 PetscCheck(fprintf(manifest,
2329 "-checkpoint_format %s\n"
2330 "-checkpoint_version %d\n"
2331 "-checkpoint_step %" PetscInt_FMT
"\n"
2332 "-checkpoint_time %.17g\n"
2333 "-checkpoint_dt %.17g\n"
2334 "-checkpoint_reason %s\n"
2335 "-checkpoint_geometry_sha256 %s\n"
2336 "-checkpoint_block_count %" PetscInt_FMT
"\n"
2337 "-checkpoint_particles %s\n"
2338 "-checkpoint_particle_count %" PetscInt_FMT
"\n"
2339 "-checkpoint_les %s\n"
2340 "-checkpoint_rans %s\n"
2341 "-checkpoint_payload_count %" PetscInt_FMT
"\n",
2343 simCtx->
step, (
double)simCtx->
ti, (
double)simCtx->
dt,
2345 simCtx->
np > 0 ?
"true" :
"false",
2347 simCtx->
les ?
"true" :
"false",
2348 simCtx->
rans ?
"true" :
"false",
2350 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2351 "Unable to write checkpoint metadata '%s'.", metadata_path);
2353 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2354 PetscCheck(fprintf(manifest,
2355 "-checkpoint_block_%" PetscInt_FMT
"_im %" PetscInt_FMT
"\n"
2356 "-checkpoint_block_%" PetscInt_FMT
"_jm %" PetscInt_FMT
"\n"
2357 "-checkpoint_block_%" PetscInt_FMT
"_km %" PetscInt_FMT
"\n",
2358 block, user[block].IM, block, user[block].JM, block, user[block].KM) > 0,
2359 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2360 "Unable to write block metadata for block %" PetscInt_FMT
".", block);
2362 PetscCheck(fprintf(manifest,
"-checkpoint_periodic %d,%d,%d\n",
2365 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2366 "Unable to write checkpoint periodicity metadata.");
2371 PetscCheck(fprintf(manifest,
2372 "-checkpoint_driven_flux_latched %s\n"
2373 "-checkpoint_driven_flux_target %.17g\n",
2376 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2377 "Unable to write driven-flow controller metadata.");
2381 PetscCheck(fprintf(manifest,
"-checkpoint_statistics_window_count %" PetscInt_FMT
"\n",
2383 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2384 "Unable to write statistics window count.");
2388 char digest[65] =
"";
2397 PetscCall(PetscStrlen(group_list, &used));
2398 PetscCall(PetscSNPrintf(group_list + used,
sizeof(group_list) - used,
"%s%s",
2399 group ?
"," :
"", groups[group]));
2401 PetscCheck(fprintf(manifest,
2402 "-checkpoint_statistics_window_%" PetscInt_FMT
"_name %s\n"
2403 "-checkpoint_statistics_window_%" PetscInt_FMT
"_hash %s\n"
2404 "-checkpoint_statistics_window_%" PetscInt_FMT
"_hash_groups %s\n"
2405 "-checkpoint_statistics_window_%" PetscInt_FMT
"_state %s\n"
2406 "-checkpoint_statistics_window_%" PetscInt_FMT
"_sample_count %" PetscInt_FMT
"\n"
2407 "-checkpoint_statistics_window_%" PetscInt_FMT
"_total_weight %.17g\n"
2408 "-checkpoint_statistics_window_%" PetscInt_FMT
"_represented_time %.17g\n"
2409 "-checkpoint_statistics_window_%" PetscInt_FMT
"_last_accepted_time %.17g\n"
2410 "-checkpoint_statistics_window_%" PetscInt_FMT
"_effective_start %.17g\n"
2411 "-checkpoint_statistics_window_%" PetscInt_FMT
"_effective_end %.17g\n"
2412 "-checkpoint_statistics_window_%" PetscInt_FMT
"_activation_step %" PetscInt_FMT
"\n"
2413 "-checkpoint_statistics_window_%" PetscInt_FMT
"_last_event_step %" PetscInt_FMT
"\n"
2414 "-checkpoint_statistics_window_%" PetscInt_FMT
"_next_time_target %" PetscInt_FMT
"\n"
2415 "-checkpoint_statistics_window_%" PetscInt_FMT
"_restart_count %" PetscInt_FMT
"\n",
2430 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2431 "Unable to write metadata for statistics window '%s'.",
2436 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2440 PetscInt global_size = 0;
2441 char relative_path[PETSC_MAX_PATH_LEN];
2446 PetscCall(VecGetSize(view.
global_vec, &global_size));
2447 PetscCall(PetscSNPrintf(relative_path,
sizeof(relative_path),
2448 "%s/block_%04" PetscInt_FMT
"/%s.dat",
2451 payload_index++, relative_path,
2454 descriptor->
dof,
"PetscScalar", global_size,
2455 "petsc_vec_binary_natural"));
2458 if (simCtx->
np > 0) {
2461 char relative_path[PETSC_MAX_PATH_LEN];
2462 const char *encoding =
"petsc_vec_binary_global";
2467 encoding =
"petsc_vec_binary_scalar_cast";
2469 PetscCall(PetscSNPrintf(relative_path,
sizeof(relative_path),
2473 payload_index++, relative_path,
2482 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2483 if (!user[block].fieldStatisticsStorage)
continue;
2488 PetscInt storage_payloads = 0;
2491 for (PetscInt index = 0; index < storage_payloads; ++index) {
2493 PetscInt global_size = 0;
2494 char relative_path[PETSC_MAX_PATH_LEN];
2495 char qualified_name[PETSC_MAX_PATH_LEN];
2499 PetscCall(VecGetSize(payload.
vec, &global_size));
2501 relative_path,
sizeof(relative_path)));
2505 PetscCall(PetscSNPrintf(qualified_name,
sizeof(qualified_name),
"%s/%s",
2508 payload_index++, relative_path,
2509 payload.
role, qualified_name,
2513 "petsc_vec_binary_natural"));
2518 PetscCheck(fflush(manifest) == 0 && fsync(fileno(manifest)) == 0,
2519 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2520 "Unable to flush checkpoint metadata '%s'.", metadata_path);
2521 PetscCheck(fclose(manifest) == 0, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2522 "Unable to close checkpoint metadata '%s'.", metadata_path);
2525 PetscCallMPI(MPI_Bcast(manifest_digest, 65, MPI_CHAR, 0, PETSC_COMM_WORLD));
2526 PetscFunctionReturn(0);
2533 char checkpoints_root[PETSC_MAX_PATH_LEN];
2534 char final_directory[PETSC_MAX_PATH_LEN];
2535 char temporary_directory[PETSC_MAX_PATH_LEN];
2536 char nested_directory[PETSC_MAX_PATH_LEN];
2537 char commit_path[PETSC_MAX_PATH_LEN];
2538 char geometry_digest[65] =
"";
2539 char manifest_digest[65] =
"";
2540 PetscBool final_exists = PETSC_FALSE;
2541 PetscInt particle_count = 0;
2542 PetscMPIInt writer_pid = 0;
2544 PetscFunctionBeginUser;
2545 PetscCheck(simCtx != NULL && reason != NULL && reason[0] !=
'\0',
2546 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2547 "Simulation context and checkpoint reason are required.");
2549 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
2550 "Finest-level fields must exist before checkpoint output.");
2552 PetscCall(PetscSNPrintf(checkpoints_root,
sizeof(checkpoints_root),
"%s/%s",
2555 final_directory,
sizeof(final_directory)));
2556 PetscCall(PetscTestDirectory(final_directory,
'r', &final_exists));
2558 PetscReal saved_time = 0.0;
2560 &saved_time, NULL, NULL, NULL, NULL));
2561 PetscCheck(PetscAbsReal(saved_time - simCtx->
ti) <=
2562 10.0 * PETSC_MACHINE_EPSILON * PetscMax(1.0, PetscAbsReal(simCtx->
ti)),
2563 PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
2564 "Committed checkpoint step %" PetscInt_FMT
" has time %.17g, current state has time %.17g.",
2565 simCtx->
step, (
double)saved_time, (
double)simCtx->
ti);
2568 PetscFunctionReturn(0);
2571 if (simCtx->
rank == 0) writer_pid = (PetscMPIInt)getpid();
2572 PetscCallMPI(MPI_Bcast(&writer_pid, 1, MPI_INT, 0, PETSC_COMM_WORLD));
2573 PetscCall(PetscSNPrintf(temporary_directory,
sizeof(temporary_directory),
2574 "%s/.step_%0*" PetscInt_FMT
".incomplete.%d",
2576 simCtx->
step, (
int)writer_pid));
2579 PetscCall(PetscSNPrintf(nested_directory,
sizeof(nested_directory),
"%s/%s",
2582 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2583 PetscCall(PetscSNPrintf(nested_directory,
sizeof(nested_directory),
2584 "%s/%s/block_%04" PetscInt_FMT,
2588 if (simCtx->
np > 0) {
2589 PetscCall(PetscSNPrintf(nested_directory,
sizeof(nested_directory),
"%s/%s",
2592 PetscCall(DMSwarmGetSize(user->
swarm, &particle_count));
2596 nested_directory,
sizeof(nested_directory)));
2600 nested_directory,
sizeof(nested_directory)));
2602 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2604 nested_directory,
sizeof(nested_directory)));
2611 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2615 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2618 PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
2621 geometry_digest, particle_count, manifest_digest));
2622 if (simCtx->
rank == 0) {
2623 FILE *commit_file = NULL;
2625 PetscCall(PetscSNPrintf(commit_path,
sizeof(commit_path),
"%s/COMMITTED", temporary_directory));
2626 commit_file = fopen(commit_path,
"w");
2627 PetscCheck(commit_file != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
2628 "Unable to create checkpoint commit marker '%s'.", commit_path);
2629 PetscCheck(fprintf(commit_file,
"%s\n", manifest_digest) > 0 &&
2630 fflush(commit_file) == 0 && fsync(fileno(commit_file)) == 0,
2631 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2632 "Unable to write checkpoint commit marker '%s'.", commit_path);
2633 PetscCheck(fclose(commit_file) == 0, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2634 "Unable to close checkpoint commit marker '%s'.", commit_path);
2635 PetscCheck(rename(temporary_directory, final_directory) == 0,
2636 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2637 "Unable to commit checkpoint '%s': %s", final_directory, strerror(errno));
2639 PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
2641 "Committed checkpoint step %d at t=%.17g (%s): %s\n",
2642 simCtx->
step, (
double)simCtx->
ti, reason, final_directory);
2643 PetscFunctionReturn(0);
2654 Vec sequential_vec = NULL;
2656 PetscFunctionBeginUser;
2657 PetscCheck(inVec != NULL && N != NULL && arrayOut != NULL,
2658 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2659 "Vector, size output, and array output are required.");
2660 PetscCall(PetscObjectGetComm((PetscObject)inVec, &comm));
2661 PetscCallMPI(MPI_Comm_rank(comm, &rank));
2662 PetscCall(VecGetSize(inVec, N));
2667 const PetscScalar *values = NULL;
2668 PetscInt local_size = 0;
2670 PetscCall(VecGetLocalSize(sequential_vec, &local_size));
2671 PetscCall(PetscMalloc1(local_size, arrayOut));
2672 PetscCall(VecGetArrayRead(sequential_vec, &values));
2673 for (PetscInt index = 0; index < local_size; ++index) {
2674 (*arrayOut)[index] = (double)PetscRealPart(values[index]);
2676 PetscCall(VecRestoreArrayRead(sequential_vec, &values));
2678 PetscCall(VecDestroy(&sequential_vec));
2679 PetscFunctionReturn(0);
2687 PetscInt *n_total_particles, PetscInt *n_components,
2688 PetscDataType *field_type_out,
void **gathered_array)
2690 PetscErrorCode ierr;
2691 PetscMPIInt rank, size;
2692 PetscInt nlocal, nglobal, bs;
2693 PetscDataType field_type;
2694 void *local_array_void;
2695 size_t element_size = 0;
2697 PetscFunctionBeginUser;
2699 PetscCheck(swarm != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"DMSwarm cannot be NULL.");
2700 PetscCheck(field_name != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Swarm field name cannot be NULL.");
2701 PetscCheck(n_total_particles != NULL && n_components != NULL && field_type_out != NULL && gathered_array != NULL,
2702 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2703 "Swarm gather output pointers cannot be NULL.");
2705 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2706 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
2709 ierr = DMSwarmGetLocalSize(swarm, &nlocal); CHKERRQ(ierr);
2710 ierr = DMSwarmGetSize(swarm, &nglobal); CHKERRQ(ierr);
2711 ierr = DMSwarmGetField(swarm, field_name, &bs, &field_type, &local_array_void); CHKERRQ(ierr);
2714 if (field_type == PETSC_INT64) element_size =
sizeof(PetscInt64);
2715 else if (field_type == PETSC_INT) element_size =
sizeof(PetscInt);
2716 else if (field_type == PETSC_REAL) element_size =
sizeof(PetscReal);
2717#if defined(PETSC_USE_COMPLEX)
2718 else if (field_type == PETSC_SCALAR) element_size =
sizeof(PetscScalar);
2720 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
2721 "Swarm field '%s' uses unsupported gathered data type %s.",
2722 field_name, PetscDataTypes[field_type]);
2724 *field_type_out = field_type;
2725 *n_total_particles = nglobal;
2727 *gathered_array = NULL;
2731 ierr = PetscMalloc(nglobal * bs * element_size, gathered_array); CHKERRQ(ierr);
2732 ierr = PetscMemcpy(*gathered_array, local_array_void, nglobal * bs * element_size); CHKERRQ(ierr);
2735 PetscInt *recvcounts = NULL, *displs = NULL;
2737 ierr = PetscMalloc1(size, &recvcounts); CHKERRQ(ierr);
2738 ierr = PetscMalloc1(size, &displs); CHKERRQ(ierr);
2740 PetscInt sendcount = nlocal * bs;
2743 ierr = MPI_Gather(&sendcount, 1, MPIU_INT, recvcounts, 1, MPIU_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
2748 for (PetscMPIInt i = 0; i < size; i++) recvcounts[i] *= element_size;
2749 for (PetscMPIInt i = 1; i < size; i++) displs[i] = displs[i-1] + recvcounts[i-1];
2751 ierr = PetscMalloc(nglobal * bs * element_size, gathered_array); CHKERRQ(ierr);
2755 ierr = MPI_Gatherv(local_array_void, nlocal * bs * element_size, MPI_BYTE,
2756 *gathered_array, recvcounts, displs, MPI_BYTE,
2757 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
2760 ierr = PetscFree(recvcounts); CHKERRQ(ierr);
2761 ierr = PetscFree(displs); CHKERRQ(ierr);
2765 ierr = DMSwarmRestoreField(swarm, field_name, &bs, NULL, &local_array_void); CHKERRQ(ierr);
2767 PetscFunctionReturn(0);
2778 PetscErrorCode ierr;
2780 Cmpnts global_min_coords, global_max_coords;
2781 PetscReal StartTime;
2782 PetscInt StartStep,StepsToRun,total_num_particles;
2783 PetscMPIInt num_mpi_procs;
2784 const char *log_level_name;
2785 const char *convergence_mode_name;
2789 num_mpi_procs = simCtx->
size;
2793 total_num_particles = simCtx->
np;
2797 PetscFunctionBeginUser;
2799 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"DisplayBanner - UserCtx pointer is NULL.");
2801 case LOG_ERROR: log_level_name =
"ERROR";
break;
2802 case LOG_WARNING: log_level_name =
"WARNING";
break;
2803 case LOG_INFO: log_level_name =
"INFO";
break;
2804 case LOG_DEBUG: log_level_name =
"DEBUG";
break;
2805 case LOG_TRACE: log_level_name =
"TRACE";
break;
2806 case LOG_VERBOSE: log_level_name =
"VERBOSE";
break;
2807 default: log_level_name =
"UNKNOWN";
break;
2814 default: convergence_mode_name =
"UNKNOWN";
break;
2818 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2823 if (bboxlist_on_rank0 && num_mpi_procs > 0) {
2824 global_min_coords = bboxlist_on_rank0[0].
min_coords;
2825 global_max_coords = bboxlist_on_rank0[0].
max_coords;
2826 for (PetscMPIInt p = 1; p < num_mpi_procs; ++p) {
2827 global_min_coords.
x = PetscMin(global_min_coords.
x, bboxlist_on_rank0[p].
min_coords.
x);
2828 global_min_coords.
y = PetscMin(global_min_coords.
y, bboxlist_on_rank0[p].
min_coords.
y);
2829 global_min_coords.
z = PetscMin(global_min_coords.
z, bboxlist_on_rank0[p].
min_coords.
z);
2830 global_max_coords.
x = PetscMax(global_max_coords.
x, bboxlist_on_rank0[p].
max_coords.
x);
2831 global_max_coords.
y = PetscMax(global_max_coords.
y, bboxlist_on_rank0[p].
max_coords.
y);
2832 global_max_coords.
z = PetscMax(global_max_coords.
z, bboxlist_on_rank0[p].
max_coords.
z);
2839 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"(Rank 0) - bboxlist not provided or num_mpi_procs <=0; using user->bbox for domain bounds.\n");
2844 ierr = PetscPrintf(PETSC_COMM_SELF,
"\n"); CHKERRQ(ierr);
2845 ierr = PetscPrintf(PETSC_COMM_SELF,
"=============================================================\n"); CHKERRQ(ierr);
2846 ierr = PetscPrintf(PETSC_COMM_SELF,
" CASE SUMMARY \n"); CHKERRQ(ierr);
2847 ierr = PetscPrintf(PETSC_COMM_SELF,
"=============================================================\n"); CHKERRQ(ierr);
2848 ierr = PetscPrintf(PETSC_COMM_SELF,
" Grid Points : %d X %d X %d\n", user->
IM, user->
JM, user->
KM); CHKERRQ(ierr);
2849 ierr = PetscPrintf(PETSC_COMM_SELF,
" Cells : %d X %d X %d\n", user->
IM - 1, user->
JM - 1, user->
KM - 1); CHKERRQ(ierr);
2850 ierr = PetscPrintf(PETSC_COMM_SELF,
" Global Domain Bounds (X) : %.6f to %.6f\n", (
double)global_min_coords.
x, (
double)global_max_coords.
x); CHKERRQ(ierr);
2851 ierr = PetscPrintf(PETSC_COMM_SELF,
" Global Domain Bounds (Y) : %.6f to %.6f\n", (
double)global_min_coords.
y, (
double)global_max_coords.
y); CHKERRQ(ierr);
2852 ierr = PetscPrintf(PETSC_COMM_SELF,
" Global Domain Bounds (Z) : %.6f to %.6f\n", (
double)global_min_coords.
z, (
double)global_max_coords.
z); CHKERRQ(ierr);
2853 ierr = PetscPrintf(PETSC_COMM_SELF,
" Periodic Axes (BC-derived) : I=%s, J=%s, K=%s\n",
2856 simCtx->
k_periodic ?
"YES" :
"NO"); CHKERRQ(ierr);
2857 for (PetscInt axis = 0; axis < 3; axis++) {
2859 ierr = PetscPrintf(PETSC_COMM_SELF,
2860 " Periodic %c Translation : (%.6e, %.6e, %.6e)\n",
2866 if (total_num_particles > 0 &&
2868 ierr = PetscPrintf(PETSC_COMM_SELF,
2869 " Particle Periodic Wrapping : UNSUPPORTED (Eulerian periodicity only)\n"); CHKERRQ(ierr);
2872 ierr = PetscPrintf(PETSC_COMM_SELF,
"-------------------- Boundary Conditions --------------------\n"); CHKERRQ(ierr);
2873 const int face_name_width = 17;
2874 for (PetscInt i_face = 0; i_face < 6; ++i_face) {
2882 Cmpnts inlet_velocity = {0.0,0.0,0.0};
2887 ierr = PetscPrintf(PETSC_COMM_SELF,
" Face %-*s : %s - %s - [%.4f,%.4f,%.4f]\n",
2888 face_name_width, face_str, bc_type_str, bc_handler_type_str,inlet_velocity.
x,inlet_velocity.
y,inlet_velocity.
z); CHKERRQ(ierr);
2890 PetscReal v_max = 0.0;
2893 ierr = PetscPrintf(PETSC_COMM_SELF,
" Face %-*s : %s - %s - v_max=%.4f\n",
2894 face_name_width, face_str, bc_type_str, bc_handler_type_str, v_max); CHKERRQ(ierr);
2896 const char *source_file =
"(missing)";
2898 if (strcasecmp(param->key,
"source_file") == 0 && param->value) {
2899 source_file = param->value;
2903 ierr = PetscPrintf(PETSC_COMM_SELF,
" Face %-*s : %s - %s - source_file=%s\n",
2904 face_name_width, face_str, bc_type_str, bc_handler_type_str, source_file); CHKERRQ(ierr);
2907 PetscBool trimflag,foundtrimflag;
2909 ierr = PetscPrintf(PETSC_COMM_SELF,
" Face %-*s : %s - %s - [from initial state] - %s\n",
2910 face_name_width, face_str, bc_type_str, bc_handler_type_str,trimflag?
"Enforce seam flux":
"Seam flux not enforced"); CHKERRQ(ierr);
2913 PetscBool trimflag,foundflux,foundtrimflag;
2916 ierr = PetscPrintf(PETSC_COMM_SELF,
" Face %-*s : %s - %s - [%.4f] - %s\n",
2917 face_name_width, face_str, bc_type_str, bc_handler_type_str,flux,trimflag?
"Enforce seam flux":
"Seam flux not enforced"); CHKERRQ(ierr);
2919 ierr = PetscPrintf(PETSC_COMM_SELF,
" Face %-*s : %s - %s\n",
2920 face_name_width, face_str, bc_type_str,bc_handler_type_str); CHKERRQ(ierr);
2924 ierr = PetscPrintf(PETSC_COMM_SELF,
"-------------------------------------------------------------\n"); CHKERRQ(ierr);
2925 ierr = PetscPrintf(PETSC_COMM_SELF,
" Run Mode : %s\n", simCtx->
OnlySetup ?
"SETUP ONLY" :
"Full Simulation"); CHKERRQ(ierr);
2926 ierr = PetscPrintf(PETSC_COMM_SELF,
" Start Time : %.4f\n", (
double)StartTime); CHKERRQ(ierr);
2927 ierr = PetscPrintf(PETSC_COMM_SELF,
" Timestep Size : %.4f\n", (
double)simCtx->
dt); CHKERRQ(ierr);
2928 ierr = PetscPrintf(PETSC_COMM_SELF,
" Starting Step : %d\n", StartStep); CHKERRQ(ierr);
2929 ierr = PetscPrintf(PETSC_COMM_SELF,
" Total Steps to Run : %d\n", StepsToRun); CHKERRQ(ierr);
2930 ierr = PetscPrintf(PETSC_COMM_SELF,
" Ending Step : %d\n", StartStep + StepsToRun); CHKERRQ(ierr);
2931 if (simCtx->
tiout > 0) {
2932 ierr = PetscPrintf(PETSC_COMM_SELF,
" Field/Restart Cadence : every %d step(s)\n", simCtx->
tiout); CHKERRQ(ierr);
2934 ierr = PetscPrintf(PETSC_COMM_SELF,
" Field/Restart Cadence : DISABLED\n"); CHKERRQ(ierr);
2939 ierr = PetscPrintf(PETSC_COMM_SELF,
" Statistics Console Cadence : every %d step(s), %d window(s)\n",
2942 ierr = PetscPrintf(PETSC_COMM_SELF,
" Statistics Console Cadence : DISABLED (%d window(s) accumulating)\n",
2945 ierr = PetscPrintf(PETSC_COMM_SELF,
" Statistics Console Cadence : DISABLED (no window configured)\n"); CHKERRQ(ierr);
2947 ierr = PetscPrintf(PETSC_COMM_SELF,
" Immersed Boundary : %s\n", simCtx->
immersed ?
"ENABLED" :
"DISABLED"); CHKERRQ(ierr);
2951 " Runtime Walltime Guard : %s (warmup=%d, multiplier=%.2f, min=%.1f s, alpha=%.2f)\n",
2959 ierr = PetscPrintf(PETSC_COMM_SELF,
" Runtime Walltime Guard : DISABLED\n"); CHKERRQ(ierr);
2961 ierr = PetscPrintf(PETSC_COMM_SELF,
" Console Log Level : %s\n", log_level_name); CHKERRQ(ierr);
2962 ierr = PetscPrintf(PETSC_COMM_SELF,
" Profiling Timestep Output : %s\n", simCtx->
profilingTimestepMode); CHKERRQ(ierr);
2963 ierr = PetscPrintf(PETSC_COMM_SELF,
" Profiling Final Summary : %s\n", simCtx->
profilingFinalSummary ?
"ENABLED" :
"DISABLED"); CHKERRQ(ierr);
2965 ierr = PetscPrintf(PETSC_COMM_SELF,
" Runtime Memory Log : ENABLED (%s)\n", simCtx->
runtimeMemoryLogFile); CHKERRQ(ierr);
2967 ierr = PetscPrintf(PETSC_COMM_SELF,
" Runtime Memory Log : DISABLED\n"); CHKERRQ(ierr);
2969 ierr = PetscPrintf(PETSC_COMM_SELF,
" Solution Convergence Log : %s\n",
2971 ierr = PetscPrintf(PETSC_COMM_SELF,
" Number of MPI Processes : %d\n", num_mpi_procs); CHKERRQ(ierr);
2972 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Number of Particles : %d\n", total_num_particles); CHKERRQ(ierr);
2973 if (simCtx->
np > 0) {
2977 ierr = PetscPrintf(PETSC_COMM_SELF,
" Particle Console Cadence : every %d step(s)\n", simCtx->
particleConsoleOutputFreq); CHKERRQ(ierr);
2979 ierr = PetscPrintf(PETSC_COMM_SELF,
" Particle Console Cadence : DISABLED\n"); CHKERRQ(ierr);
2981 ierr = PetscPrintf(PETSC_COMM_SELF,
" Particle Log Row Sampling : every %d particle(s)\n", simCtx->
LoggingFrequency); CHKERRQ(ierr);
2983 ierr = PetscPrintf(PETSC_COMM_SELF,
" Particle Restart Mode : %s\n", simCtx->
particleRestartMode); CHKERRQ(ierr);
2985 ierr = PetscPrintf(PETSC_COMM_SELF,
" Particle Initialization Mode: %s\n", particle_init_str); CHKERRQ(ierr);
2986 ierr = PetscPrintf(PETSC_COMM_SELF,
" Interpolation Method : %s\n",
2993 ierr = PetscPrintf(PETSC_COMM_SELF,
" Particles Initialized At : --- (No INLET face identified)\n"); CHKERRQ(ierr);
2998 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Reynolds Number : %le\n", simCtx->
ren); CHKERRQ(ierr);
3004 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Initial Pseudo-CFL (Courant): %le\n", simCtx->
pseudo_cfl); CHKERRQ(ierr);
3005 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Pseudo-CFL Range : [%le, %le]\n", simCtx->
min_pseudo_cfl, simCtx->
max_pseudo_cfl); CHKERRQ(ierr);
3006 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Pseudo-CFL Adaptation : growth=%le, reduction=%le, backtrack=%s\n",
3009 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Pseudo-Time Iteration Limit : %d\n", simCtx->
mom_max_pseudo_steps); CHKERRQ(ierr);
3011 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Newton-Krylov PETSc Controls: SNES/KSP options (mom_nk_*)\n"); CHKERRQ(ierr);
3012 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Newton-Krylov History Log : %s\n", simCtx->
mom_nk_monitor_history ?
"ENABLED" :
"DISABLED"); CHKERRQ(ierr);
3014 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Pseudo-Time Controller : NOT APPLICABLE\n"); CHKERRQ(ierr);
3016 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Solution Convergence Mode : %s\n", convergence_mode_name); CHKERRQ(ierr);
3022 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Large Eddy Simulation Model : %s\n",
LESModelToString(simCtx->
les)); CHKERRQ(ierr);
3025 ierr = PetscPrintf(PETSC_COMM_SELF,
" Eulerian State Source : load (%s)\n",
3028 ierr = PetscPrintf(PETSC_COMM_SELF,
" Eulerian State Source : restart step %d (%s)\n",
3032 ierr = PetscPrintf(PETSC_COMM_SELF,
" Eulerian State Source : initial condition (%s)\n",
3033 field_init_str); CHKERRQ(ierr);
3037 ierr = PetscPrintf(PETSC_COMM_SELF,
3038 " Constant Velocity (Cart.) : x=%.4f y=%.4f z=%.4f\n",
3044 ierr = PetscPrintf(PETSC_COMM_SELF,
3045 " Constant Velocity (Curv.) : speed=%.4f direction=%s\n",
3050 ierr = PetscPrintf(PETSC_COMM_SELF,
3051 " Poiseuille Peak Velocity : speed=%.4f direction=%s\n",
3056 ierr = PetscPrintf(PETSC_COMM_SELF,
3057 " Initial Velocity File : field=%s directory=%s\n",
3062 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Analytical Solution Type : %s\n", simCtx->
AnalyticalSolutionType); CHKERRQ(ierr);
3064 ierr = PetscPrintf(PETSC_COMM_SELF,
"=============================================================\n"); CHKERRQ(ierr);
3065 ierr = PetscPrintf(PETSC_COMM_SELF,
"\n"); CHKERRQ(ierr);
3067 PetscFunctionReturn(0);
3071#define __FUNCT__ "ParsePostProcessingSettings"
3080 PetscBool startTimeSet, endTimeSet, timeStepSet;
3082 PetscFunctionBeginUser;
3085 if (!simCtx || !simCtx->
pps) {
3086 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_NULL,
"SimCtx or its pps member is NULL in ParsePostProcessingSettings.");
3120 file = fopen(configFile,
"r");
3123 while (fgets(line,
sizeof(line), file)) {
3124 char *key, *value, *comment;
3125 comment = strchr(line,
'#');
if (comment) *comment =
'\0';
3127 key = strtok(line,
"="); value = strtok(NULL,
"=");
3130 if (strcmp(key,
"startTime") == 0) pps->
startTime = atoi(value);
3131 else if (strcmp(key,
"endTime") == 0) pps->
endTime = atoi(value);
3132 else if (strcmp(key,
"timeStep") == 0) pps->
timeStep = atoi(value);
3133 else if (strcmp(key,
"output_particles") == 0) {
3134 if (strcasecmp(value,
"true") == 0) pps->
outputParticles = PETSC_TRUE;
3136 else if (strcasecmp(key,
"process_pipeline") == 0) {
3139 }
else if (strcasecmp(key,
"field_statistics_windows") == 0) {
3142 }
else if (strcasecmp(key,
"field_statistics_formats") == 0) {
3145 }
else if (strcasecmp(key,
"field_statistics_outputs") == 0) {
3148 }
else if (strcasecmp(key,
"field_statistics_source_step") == 0) {
3150 }
else if (strcasecmp(key,
"output_fields_instantaneous") == 0) {
3153 }
else if (strcasecmp(key,
"output_prefix") == 0) {
3156 }
else if (strcasecmp(key,
"particle_output_prefix") == 0) {
3159 }
else if (strcasecmp(key,
"particle_fields_instantaneous") == 0) {
3162 }
else if (strcasecmp(key,
"particle_pipeline") == 0) {
3165 }
else if (strcasecmp(key,
"particle_output_freq") == 0) {
3167 }
else if (strcasecmp(key,
"statistics_pipeline") == 0) {
3170 }
else if (strcasecmp(key,
"statistics_output_prefix") == 0) {
3173 }
else if (strcasecmp(key,
"particleExt") == 0) {
3176 }
else if (strcasecmp(key,
"eulerianExt") == 0) {
3179 }
else if (strcmp(key,
"reference_ip") == 0) {pps->
reference[0] = atoi(value);
3180 }
else if (strcmp(key,
"reference_jp") == 0) {pps->
reference[1] = atoi(value);
3181 }
else if (strcmp(key,
"reference_kp") == 0) {pps->
reference[2] = atoi(value);
3182 }
else if (strcasecmp(key,
"source_directory") == 0) {
3185 }
else if (strcasecmp(key,
"spectra_signature") == 0) {
3199 LOG_ALLOW(
GLOBAL,
LOG_WARNING,
"Could not open post-processing config file '%s'. Using defaults and command-line overrides.\n", configFile);
3203 PetscOptionsGetInt(NULL, NULL,
"-startTime", &pps->
startTime, &startTimeSet);
3204 PetscOptionsGetInt(NULL, NULL,
"-endTime", &pps->
endTime, &endTimeSet);
3205 PetscOptionsGetInt(NULL, NULL,
"-timeStep", &pps->
timeStep, &timeStepSet);
3206 PetscOptionsGetBool(NULL, NULL,
"-output_particles", &pps->
outputParticles, NULL);
3213 if (startTimeSet && !endTimeSet) {
3217 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Post-processing configured to run from t=%d to t=%d with step %d. Particle output: %s.\n",
3230 PetscFunctionReturn(0);
3235#define __FUNCT__ "ParseScalingInformation"
3244 PetscErrorCode ierr;
3247 PetscFunctionBeginUser;
3250 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"SimCtx is NULL in ParseScalingInformation");
3259 ierr = PetscOptionsGetReal(NULL, NULL,
"-scaling_L_ref", &simCtx->
scaling.
L_ref, &flg); CHKERRQ(ierr);
3260 ierr = PetscOptionsGetReal(NULL, NULL,
"-scaling_U_ref", &simCtx->
scaling.
U_ref, &flg); CHKERRQ(ierr);
3261 ierr = PetscOptionsGetReal(NULL, NULL,
"-scaling_rho_ref", &simCtx->
scaling.
rho_ref, &flg); CHKERRQ(ierr);
3266 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
"Reference velocity U_ref must be positive. Got %g", (
double)simCtx->
scaling.
U_ref);
3271 LOG(
GLOBAL,
LOG_INFO,
"---------------- Physical Scales Initialized -----------------\n");
3272 LOG(
GLOBAL,
LOG_INFO,
" L_ref: %.4f, U_ref: %.4f, rho_ref: %.4f, P_ref: %.4f\n",
3274 LOG(
GLOBAL,
LOG_INFO,
"--------------------------------------------------------------\n");
3277 PetscFunctionReturn(0);
3292 PetscMPIInt rank, size;
3293 PetscErrorCode ierr;
3296 double *array = NULL;
3297 PetscInt fileExistsFlag = 0;
3300 "Start reading from file: %s\n",
3304 if (!filename || !data_out || !Nout) {
3306 "Null pointer argument provided.\n");
3311 MPI_Comm_rank(comm, &rank);
3312 MPI_Comm_size(comm, &size);
3316 fp = fopen(filename,
"r");
3325 ierr = MPI_Bcast(&fileExistsFlag, 1, MPI_INT, 0, comm); CHKERRQ(ierr);
3327 if (!fileExistsFlag) {
3331 "File '%s' not found.\n",
3339 fp = fopen(filename,
"r");
3342 "File '%s' could not be opened for reading.\n",
3350 while (fgets(line,
sizeof(line), fp)) {
3356 "File '%s' has %d lines.\n",
3360 array = (
double*)malloc(N *
sizeof(
double));
3364 "malloc failed for array.\n");
3373 while (fgets(line,
sizeof(line), fp)) {
3375 if (sscanf(line,
"%lf", &val) == 1) {
3383 "Successfully read %d values from '%s'.\n",
3388 ierr = MPI_Bcast(&N, 1, MPI_INT, 0, comm); CHKERRQ(ierr);
3392 array = (
double*)malloc(N *
sizeof(
double));
3395 "malloc failed on rank %d.\n",
3402 ierr = MPI_Bcast(array, N, MPI_DOUBLE, 0, comm); CHKERRQ(ierr);
3409 "Done. Provided array of length=%d to all ranks.\n",
3420 double **coordsArray,
3423 PetscFunctionBeginUser;
3425 PetscErrorCode ierr;
3429 ierr = VecCreate(PETSC_COMM_WORLD, &coordsVec);CHKERRQ(ierr);
3430 ierr = VecSetFromOptions(coordsVec);CHKERRQ(ierr);
3436 "Error reading position data (ti=%d).\n",
3438 PetscFunctionReturn(ierr);
3444 ierr = VecDestroy(&coordsVec);CHKERRQ(ierr);
3447 "Successfully gathered coordinates. Ncoords=%d.\n", *Ncoords);
3448 PetscFunctionReturn(0);
3457 const char *fieldName,
3459 double **scalarArray,
3462 PetscFunctionBeginUser;
3464 PetscErrorCode ierr;
3468 ierr = VecCreate(PETSC_COMM_WORLD, &fieldVec);CHKERRQ(ierr);
3469 ierr = VecSetFromOptions(fieldVec);CHKERRQ(ierr);
3474 "Error reading field '%s' (ti=%d).\n",
3475 fieldName, timeIndex);
3476 PetscFunctionReturn(ierr);
3482 ierr = VecDestroy(&fieldVec);CHKERRQ(ierr);
3485 "Successfully gathered field '%s'. Nscalars=%d.\n",
3486 fieldName, *Nscalars);
3487 PetscFunctionReturn(0);
Small dependency-free SHA-256 utility for persistent metadata identity.
PetscErrorCode PicurvSHA256File(const char *path, char digest_hex[65])
Compute the lowercase SHA-256 digest of a file.
void PicurvSHA256Init(PicurvSHA256Context *context)
Initialize an incremental SHA-256 calculation.
void PicurvSHA256Update(PicurvSHA256Context *context, const void *data, size_t length)
Add bytes to an incremental SHA-256 calculation.
void PicurvSHA256FinalHex(PicurvSHA256Context *context, char digest_hex[65])
Finish a SHA-256 calculation and return a lowercase hexadecimal digest.
Incremental SHA-256 state.
Authoritative identities and storage metadata for persistent Eulerian fields.
@ FIELD_CAPABILITY_CHECKPOINT
@ FIELD_AVAILABILITY_RANS
@ FIELD_AVAILABILITY_PARTICLES
@ FIELD_AVAILABILITY_TURBULENCE
@ FIELD_AVAILABILITY_ALWAYS
unsigned int capabilities
unsigned int availability
PetscErrorCode FieldGetView(UserCtx *user, FieldId field_id, FieldView *view)
Resolve the existing DM and global/local vectors for one field.
const char * canonical_name
const char * FieldLayoutName(FieldLayout layout)
Return a stable printable label for a field layout.
PetscErrorCode FieldGetDescriptor(FieldId field_id, const FieldDescriptor **descriptor)
Return immutable metadata for a valid field identifier.
FieldId
Compile-time identity for a catalogued Eulerian field.
Immutable metadata for one field identity.
Non-owning runtime objects resolved for one field and UserCtx.
PetscErrorCode ParsePostProcessingSettings(SimCtx *simCtx)
Internal helper implementation: ParsePostProcessingSettings().
PetscErrorCode ParseScalingInformation(SimCtx *simCtx)
Implementation of ParseScalingInformation().
PetscInt ReadDataFileToArray(const char *filename, double **data_out, PetscInt *Nout, MPI_Comm comm)
Implementation of ReadDataFileToArray().
PetscErrorCode ReadGridFile(UserCtx *user)
Internal helper implementation: ReadGridFile().
static PetscErrorCode WriteCheckpointPayloadEntry(FILE *manifest, const char *checkpoint_directory, PetscInt payload_index, const char *relative_path, const char *kind, const char *field_name, PetscInt block, const char *layout, PetscInt components, const char *logical_type, PetscInt global_size, const char *encoding)
Append one payload inventory entry to a checkpoint manifest.
PetscErrorCode StringToBCHandlerType(const char *str, BCHandlerType *handler_out)
Internal helper implementation: StringToBCHandlerType().
PetscErrorCode ReadSwarmField(UserCtx *user, const char *field_name, const char *ext)
Internal helper implementation: ReadSwarmField().
#define PICURV_CHECKPOINT_STEP_WIDTH
PetscErrorCode GetBCParamReal(BC_Param *params, const char *key, PetscReal *value_out, PetscBool *found)
Internal helper implementation: GetBCParamReal().
PetscErrorCode SwarmFieldToArrayOnRank0(DM swarm, const char *field_name, PetscInt *n_total_particles, PetscInt *n_components, PetscDataType *field_type_out, void **gathered_array)
Internal helper implementation: SwarmFieldToArrayOnRank0().
#define PICURV_CHECKPOINTS_DIRECTORY
PetscErrorCode WriteAllSwarmFields(UserCtx *user, const char *checkpoint_directory)
Internal helper implementation: WriteAllSwarmFields().
static PetscErrorCode FormatStatisticsPath(const char *root, PetscInt window, PetscInt block, const char *payload_name, char *path, size_t path_size)
Format any level of the statistics subtree, from the root down to one payload.
static PetscErrorCode ValidateCheckpointBundle(SimCtx *simCtx, UserCtx *user, const char *checkpoint_directory, PetscInt expected_step, PetscReal *physical_time, PetscInt *particle_count, PetscBool *particles_saved, PetscBool *les_saved, PetscBool *rans_saved)
Validate a committed bundle and return selected authoritative metadata.
#define PICURV_PARTICLE_DIRECTORY
static PetscInt * g_IMs_from_file
Caches the IM dimensions for all blocks read from the grid file.
PetscErrorCode WriteSwarmIntField(UserCtx *user, const char *field_name, const char *ext)
Internal helper implementation: WriteSwarmIntField().
PetscErrorCode ReadCheckpointParticleCount(UserCtx *user, PetscInt ti, PetscInt *particle_count)
Implementation of ReadCheckpointParticleCount().
#define PICURV_STATISTICS_DIRECTORY
PetscErrorCode ReadSimulationFields(UserCtx *user, PetscInt ti)
Internal helper implementation: ReadSimulationFields().
static PetscInt g_nblk_from_file
Stores the number of blocks read from the grid file.
PetscBool ShouldWriteDataOutput(const SimCtx *simCtx, PetscInt completed_step)
Implementation of ShouldWriteDataOutput().
static PetscErrorCode RestoreDrivenFluxTarget(SimCtx *simCtx, UserCtx *user, const char *checkpoint_directory)
Restore a latched driven-flow flux target from a checkpoint manifest.
#define PICURV_CHECKPOINT_FORMAT
static PetscErrorCode FormatCheckpointStepDirectory(const char *root, PetscInt step, char *path, size_t path_size)
Format the canonical directory name for one completed step.
PetscErrorCode GetDrivenSeamFluxFlag(BC_Param *params, PetscBool *value_out, PetscBool *found)
Implementation of GetDrivenSeamFluxFlag().
PetscErrorCode ParseAllBoundaryConditions(UserCtx *user, const char *bcs_input_filename)
Internal helper implementation: ParseAllBoundaryConditions().
PetscErrorCode ValidateBCHandlerForBCType(BCType type, BCHandlerType handler)
Internal helper implementation: ValidateBCHandlerForBCType().
void TrimWhitespace(char *str)
Implementation of TrimWhitespace().
PetscErrorCode ReadAllSwarmFields(UserCtx *user, PetscInt ti)
Internal helper implementation: ReadAllSwarmFields().
PetscErrorCode WriteSimulationFields(UserCtx *user, const char *checkpoint_directory)
Implementation of WriteSimulationFields().
static PetscErrorCode CreateCheckpointDirectoryCollective(const SimCtx *simCtx, const char *path)
Create one directory on rank zero and report failures collectively.
static PetscBool g_file_has_been_read
A flag to ensure the grid file is read only once.
PetscErrorCode ReadGridGenerationInputs(UserCtx *user)
Internal helper implementation: ReadGridGenerationInputs().
static PetscErrorCode ComputeCheckpointGeometrySHA256(SimCtx *simCtx, UserCtx *user, char digest_hex[65])
Compute and cache a rank-count-independent hash of the active grid geometry.
PetscErrorCode ReadFieldData(UserCtx *user, const char *field_name, Vec field_vec, const char *ext)
Internal helper implementation: ReadFieldData().
PetscErrorCode PopulateFinestUserGridResolutionFromOptions(UserCtx *finest_users, PetscInt nblk)
Internal helper implementation: PopulateFinestUserGridResolutionFromOptions().
PetscErrorCode DeterminePeriodicity(SimCtx *simCtx)
Internal helper implementation: DeterminePeriodicity().
static PetscErrorCode GatherVectorToRankZero(Vec field_vec, Vec *sequential_vec)
Gather a vector in decomposition-independent natural ordering onto rank zero.
PetscErrorCode ReadFieldDataToRank0(PetscInt timeIndex, const char *fieldName, UserCtx *user, double **scalarArray, PetscInt *Nscalars)
Internal helper implementation: ReadFieldDataToRank0().
PetscErrorCode VecToArrayOnRank0(Vec inVec, PetscInt *N, double **arrayOut)
Internal helper implementation: VecToArrayOnRank0().
static PetscErrorCode CopyOwnedLocalScalarToGlobal(DM dm, Vec local_vec, Vec global_vec)
Copies the owned entries of a ghosted scalar DMDA vector to its global vector.
PetscErrorCode RestoreFieldStatisticsState(SimCtx *simCtx, PetscInt ti)
Implementation of RestoreFieldStatisticsState().
static PetscInt * g_KMs_from_file
Caches the KM dimensions for all blocks read from the grid file.
static PetscInt * g_JMs_from_file
Caches the JM dimensions for all blocks read from the grid file.
static PetscErrorCode ReadStatisticsWindowState(PetscOptions options, PetscInt window, const char *metadata_path, PetscReal checkpoint_time, PetscReal step_size, ExecutionMode exec_mode, PicurvWindow *state)
Restore one window's scalar bookkeeping from a validated manifest.
PetscErrorCode StringToBCFace(const char *str, BCFace *face_out)
Internal helper implementation: StringToBCFace().
PetscErrorCode ReadPositionsFromFile(PetscInt timeIndex, UserCtx *user, double **coordsArray, PetscInt *Ncoords)
Internal helper implementation: ReadPositionsFromFile().
PetscErrorCode WriteSwarmField(UserCtx *user, const char *field_name, const char *ext)
Implementation of WriteSwarmField().
PetscErrorCode ReadSwarmIntField(UserCtx *user, const char *field_name, const char *ext)
Internal helper implementation: ReadSwarmIntField().
static PetscErrorCode ResolveCheckpointStepDirectory(const char *source_root, PetscInt step, char *path, size_t path_size)
Resolve either an exact bundle or a run/output root to one step bundle.
PetscErrorCode WriteFieldData(UserCtx *user, const char *field_name, Vec field_vec, const char *ext)
Internal helper implementation: WriteFieldData().
PetscErrorCode VerifyPathExistence(const char *path, PetscBool is_dir, PetscBool is_optional, const char *description, PetscBool *exists)
Internal helper implementation: VerifyPathExistence().
static PetscErrorCode WriteStatisticsFields(UserCtx *user, const char *checkpoint_directory)
Write every window's accumulator payloads for one block into a bundle.
PetscErrorCode GetBCParamBool(BC_Param *params, const char *key, PetscBool *value_out, PetscBool *found)
Internal helper implementation: GetBCParamBool().
void FreeBC_ParamList(BC_Param *head)
Implementation of FreeBC_ParamList().
static PetscBool CheckpointFieldIsEnabled(const SimCtx *simCtx, const FieldDescriptor *descriptor)
Return whether a catalogued field belongs in the current checkpoint.
PetscErrorCode StringToBCType(const char *str, BCType *type_out)
Internal helper implementation: StringToBCType().
PetscErrorCode DisplayBanner(SimCtx *simCtx)
Emit the rank-zero startup summary from the effective simulation context.
#define PICURV_CHECKPOINT_VERSION
PetscErrorCode WriteCheckpointBundle(SimCtx *simCtx, const char *reason)
Implementation of the transactional full-state checkpoint coordinator.
#define PICURV_EULERIAN_DIRECTORY
#define PICURV_STATISTICS_REQUIRE(suffix, getter, target)
static PetscErrorCode WriteCheckpointManifest(SimCtx *simCtx, UserCtx *user, const char *checkpoint_directory, const char *reason, const char *geometry_digest, PetscInt particle_count, char manifest_digest[65])
Write the complete manifest after every payload has closed successfully.
Public interface for data input/output routines.
const char * BCHandlerTypeToString(BCHandlerType handler_type)
Converts a BCHandlerType enum to its string representation.
#define LOG_ALLOW_SYNC(scope, level, fmt,...)
Synchronized logging macro that checks both the log level and whether the calling function is in the ...
#define LOCAL
Logging scope definitions for controlling message output.
#define GLOBAL
Scope for global logging across all processes.
const char * BCFaceToString(BCFace face)
Returns the canonical log token for a boundary-face enum value.
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
#define LOG(scope, level, fmt,...)
Logging macro for PETSc-based applications with scope control.
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
const char * BCTypeToString(BCType type)
Returns the canonical log token for a boundary mathematical type.
const char * FlowDirectionToString(FlowDirection fd)
Convert a FlowDirection enum value to its YAML token string.
const char * InitialConditionModeToString(InitialConditionMode mode)
Convert an initial-condition mode to a string representation.
@ LOG_ERROR
Critical errors that may halt the program.
@ LOG_TRACE
Very fine-grained tracing information for in-depth debugging.
@ LOG_INFO
Informational messages about program execution.
@ LOG_WARNING
Non-critical issues that warrant attention.
@ LOG_DEBUG
Detailed debugging information.
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
const char * LESModelToString(LESModelType LESFlag)
Returns the canonical log token for an LES model selector.
const char * MomentumSolverTypeToString(MomentumSolverType SolverFlag)
Returns the canonical log token for a momentum-solver selector.
const char * ParticleInitializationToString(ParticleInitializationType ParticleInitialization)
Returns the canonical log token for a particle-initialization mode.
Typed identities and metadata for persistent solver-particle fields.
const char * ParticleFieldName(ParticleFieldId field_id)
Return the canonical PETSc DMSwarm name for an ID.
ParticleFieldId
Compile-time identity for a persistent solver-particle field.
@ PARTICLE_FIELD_ID_POSITION
@ PARTICLE_FIELD_ID_COUNT
unsigned int capabilities
@ PARTICLE_FIELD_CAPABILITY_CHECKPOINT
PetscErrorCode ParticleFieldGetDescriptor(ParticleFieldId field_id, const ParticleFieldDescriptor **descriptor)
Return immutable metadata for a valid particle field ID.
const char * canonical_name
Immutable metadata for one persistent particle field.
PetscErrorCode UpdateLocalGhosts(UserCtx *user, FieldId field_id)
Updates the local vector (including ghost points) from its corresponding global vector.
Per-window PETSc accumulator storage and pointwise application.
PetscInt components
Degrees of freedom the vector carries.
Vec vec
Borrowed accumulator vector; never owned by the caller.
PetscErrorCode PicurvWindowStoragePayload(UserCtx *user, const PicurvWindowDefinition *definition, const PicurvWindowStorage *storage, PetscInt index, PicurvStatisticsPayload *payload)
Resolves one enumerated payload of a window's storage.
const char * role
Inventory role: occupancy, mean, second_moment, co_moment.
char name[96]
File basename, no extension.
const char * layout
Catalog layout name for the inventory entry.
PetscErrorCode PicurvWindowStoragePayloadCount(const PicurvWindowStorage *storage, PetscInt *count)
Reports how many checkpointable vectors one window's storage holds.
One checkpointable accumulator vector, resolved by enumeration index.
Independent accumulator state for one window on one block.
PetscInt last_event_step
Guards against a step being offered twice.
PetscErrorCode PicurvWindowComputeHash(const PicurvWindowDefinition *definition, char digest_hex[65], char group_digest_hex[][17])
Computes the resolved identity hash of one window definition.
#define PICURV_WINDOW_HASH_GROUP_COUNT
Number of independently hashed property groups in a window definition.
#define PICURV_WINDOW_HASH_GROUP_LENGTH
Stored length of one truncated group digest, including the terminator.
PetscReal effective_start
Origin of the first represented interval.
const char * PicurvWindowHashGroupName(PetscInt group)
Returns the stable name of one hashed property group.
PetscReal last_accepted_time
Right edge of the last represented interval.
PetscInt restart_count
Restart segments this state descends from.
PetscReal effective_end
End of the last represented interval.
PetscReal end_time
Requested end; ignored when bounded is false.
#define PICURV_WINDOW_NAME_LENGTH
Maximum stored length of a window name, including the terminator.
@ PICURV_WINDOW_PENDING
Requested start not yet reached.
@ PICURV_WINDOW_COMPLETE
Bounded end reached; accepts nothing further.
@ PICURV_WINDOW_ACTIVE
Accepting due states.
const char * PicurvWindowStateName(PicurvWindowState state)
Returns a stable human-readable name for a window state.
PetscBool bounded
False for an open-ended window.
PicurvWindowDefinition definition
PetscInt next_time_target
k in effective_start + k*time_cadence.
PetscBool FieldStatisticsIsActive(const struct SimCtx *simCtx)
Reports whether this run has live field-statistics state.
PetscInt activation_step
Step at which the window became active.
PetscReal represented_time
Physical time the window covers.
PetscErrorCode PicurvWindowFirstHashDifference(const PicurvWindowDefinition *definition, const char *saved_group_digests, PetscInt *group)
Reports which hashed property group first differs from saved group digests.
Runtime state of one window.
The scientifically immutable definition of one window.
PetscReal icVelocityPhysical
PetscBool mom_nk_monitor_history
PetscInt fieldStatisticsWindowCount
char statistics_output_prefix[256]
basename for CSV output, e.g.
BCType
Defines the general mathematical/physical Category of a boundary.
PetscBool inletFaceDefined
PetscBool profilingFinalSummary
char particle_output_prefix[256]
BoundaryFaceConfig boundary_faces[6]
PetscInt statisticsConsoleOutputFreq
BCFace identifiedInletBCFace
PetscReal targetVolumetricFlux
PetscBool walltimeGuardActive
PetscReal pseudo_cfl_reduction_factor
InitialConditionMode initialConditionMode
SimCtx * simCtx
Back-pointer to the master simulation context.
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
@ PARTICLE_INIT_SURFACE_EDGES
Deterministic placement at inlet face edges.
FlowDirection flowDirection
PetscBool runtimeMemoryLogEnabled
Enable the rank-reduced runtime memory log.
#define MAX_FIELD_LIST_LENGTH
PetscReal walltimeGuardMinSeconds
BCHandlerType
Defines the specific computational "strategy" for a boundary handler.
@ BC_HANDLER_PERIODIC_GEOMETRIC
@ BC_HANDLER_INLET_PARABOLIC
@ BC_HANDLER_INLET_CONSTANT_VELOCITY
@ BC_HANDLER_PERIODIC_DRIVEN_INITIAL_FLUX
@ BC_HANDLER_PERIODIC_DRIVEN_CONSTANT_FLUX
@ BC_HANDLER_INLET_PROFILE_FROM_FILE
@ BC_HANDLER_OUTLET_CONSERVATION
#define MAX_PIPELINE_LENGTH
BCHandlerType handler_type
Cmpnts max_coords
Maximum x, y, z coordinates of the bounding box.
PetscBool drivenFluxTargetLatched
char output_dir[PETSC_MAX_PATH_LEN]
PetscBool solutionConvergenceEnabled
char runtimeMemoryLogFile[PETSC_MAX_PATH_LEN]
File name written under log_dir.
char profilingTimestepMode[32]
PetscBool no_pseudo_cfl_backtrack
#define MAX_FILENAME_LENGTH
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
@ MOMENTUM_SOLVER_DUALTIME_PICARD_JAMESON_RK
@ MOMENTUM_SOLVER_EXPLICIT_RK
@ MOMENTUM_SOLVER_NEWTON_KRYLOV
PetscInt solutionConvergencePeriodSteps
char * current_io_directory
char grid_file[PETSC_MAX_PATH_LEN]
char statistics_pipeline[1024]
e.g.
InterpolationMethod interpolationMethod
char field_statistics_formats[1024]
Comma-separated formats: vtk for derived fields, csv for the convergence history.
char output_fields_instantaneous[1024]
char particleRestartMode[16]
struct PicurvWindow * fieldStatisticsWindows
char source_dir[PETSC_MAX_PATH_LEN]
char particle_pipeline[1024]
char eulerianSource[PETSC_MAX_PATH_LEN]
PetscBool walltimeGuardEnabled
PetscBool checkpointGeometryHashReady
PetscInt walltimeGuardWarmupSteps
ParticleInitializationType ParticleInitialization
PetscInt solutionConvergenceWindowSteps
char process_pipeline[1024]
PetscInt particle_output_freq
char particle_fields[1024]
PetscReal pseudo_cfl_growth_factor
PetscBool outputParticles
char initialConditionDirectory[PETSC_MAX_PATH_LEN]
struct PicurvWindowStorage * fieldStatisticsStorage
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
@ IC_MODE_CONSTANT_CARTESIAN
@ IC_MODE_CONSTANT_STREAMWISE
PetscInt particleConsoleOutputFreq
Cmpnts InitialConstantContra
char checkpointGeometrySHA256[65]
PetscInt mom_max_pseudo_steps
ExecutionMode
Defines the execution mode of the application.
@ EXEC_MODE_POSTPROCESSOR
char _io_context_buffer[PETSC_MAX_PATH_LEN]
PetscInt field_statistics_source_step
Committed step supplying the state; negative means the step being processed.
Cmpnts periodic_translation[3]
PetscReal walltimeGuardEstimatorAlpha
char field_statistics_windows[1024]
Comma-separated window names to derive; empty disables the pipeline.
char field_statistics_outputs[1024]
Comma-separated outputs: mean, reynolds_stress, rms, tke, flux.
@ SOLUTION_CONVERGENCE_TRANSIENT
@ SOLUTION_CONVERGENCE_PERIODIC_DETERMINISTIC
@ SOLUTION_CONVERGENCE_STATISTICAL_STEADY
@ SOLUTION_CONVERGENCE_STEADY_DETERMINISTIC
PetscBool periodic_translation_valid[3]
SolutionConvergenceMode solutionConvergenceMode
InitialConditionField initialConditionField
PetscBool restartHistoryAvailable
PetscReal walltimeGuardMultiplier
MomentumSolverType mom_solver_type
char PostprocessingControlFile[PETSC_MAX_PATH_LEN]
char restart_dir[PETSC_MAX_PATH_LEN]
PetscInt LoggingFrequency
PetscBool fieldStatisticsContinue
BCFace
Identifies the six logical faces of a structured computational block.
BoundaryCondition * handler
A node in a linked list for storing key-value parameters from the bcs.dat file.
Holds the complete configuration for one of the six boundary faces.
Defines a 3D axis-aligned bounding box.
A 3D point or vector with PetscScalar components.
Holds all configuration parameters for a post-processing run.
The master context for the entire simulation.
User-defined context containing data specific to a single computational grid level.