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)
260 char metadata_path[PETSC_MAX_PATH_LEN];
261 char commit_path[PETSC_MAX_PATH_LEN];
262 char expected_digest[65] =
"";
263 char actual_digest[65] =
"";
264 char format[64] =
"";
265 char saved_geometry_digest[65] =
"";
266 char current_geometry_digest[65] =
"";
267 PetscOptions options = NULL;
268 PetscInt version = 0;
269 PetscInt saved_step = -1;
270 PetscInt payload_count = 0;
271 PetscInt saved_particle_count = 0;
272 PetscReal saved_time = 0.0;
273 PetscBool saved_particles = PETSC_FALSE;
274 PetscBool saved_les = PETSC_FALSE;
275 PetscBool found = PETSC_FALSE;
276 FILE *commit_file = NULL;
278 PetscFunctionBeginUser;
279 PetscCheck(simCtx != NULL && user != NULL && checkpoint_directory != NULL,
280 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Checkpoint validation inputs cannot be NULL.");
281 PetscCall(PetscSNPrintf(metadata_path,
sizeof(metadata_path),
"%s/checkpoint.meta", checkpoint_directory));
282 PetscCall(PetscSNPrintf(commit_path,
sizeof(commit_path),
"%s/COMMITTED", checkpoint_directory));
284 PetscCall(PetscTestFile(metadata_path,
'r', &found));
285 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_OPEN,
286 "Checkpoint metadata is missing: %s", metadata_path);
287 PetscCall(PetscTestFile(commit_path,
'r', &found));
288 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_OPEN,
289 "Checkpoint is not committed: %s", checkpoint_directory);
291 commit_file = fopen(commit_path,
"r");
292 PetscCheck(commit_file != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
293 "Unable to read checkpoint commit marker '%s'.", commit_path);
294 PetscCheck(fgets(expected_digest,
sizeof(expected_digest), commit_file) != NULL,
295 PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
296 "Checkpoint commit marker '%s' is empty.", commit_path);
297 PetscCheck(fclose(commit_file) == 0, PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
298 "Unable to close checkpoint commit marker '%s'.", commit_path);
300 PetscCheck(strlen(expected_digest) == 64, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
301 "Checkpoint commit marker '%s' does not contain a SHA-256 digest.", commit_path);
303 PetscCheck(!strcmp(expected_digest, actual_digest), PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
304 "Checkpoint metadata hash mismatch in '%s'.", checkpoint_directory);
306 PetscCall(PetscOptionsCreate(&options));
307 PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, metadata_path, PETSC_TRUE));
308 PetscCall(PetscOptionsGetString(options, NULL,
"-checkpoint_format", format,
sizeof(format), &found));
310 "Unsupported checkpoint format '%s' in '%s'.", found ? format :
"<missing>", metadata_path);
311 PetscCall(PetscOptionsGetInt(options, NULL,
"-checkpoint_version", &version, &found));
313 "Unsupported checkpoint version %" PetscInt_FMT
" in '%s'; expected %d.",
315 PetscCall(PetscOptionsGetInt(options, NULL,
"-checkpoint_step", &saved_step, &found));
316 PetscCheck(found && saved_step == expected_step, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
317 "Checkpoint step is %" PetscInt_FMT
", expected %" PetscInt_FMT
".",
318 saved_step, expected_step);
319 PetscCall(PetscOptionsGetReal(options, NULL,
"-checkpoint_time", &saved_time, &found));
320 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
321 "Checkpoint '%s' does not record physical time.", metadata_path);
322 PetscCall(PetscOptionsGetString(options, NULL,
"-checkpoint_geometry_sha256",
323 saved_geometry_digest,
sizeof(saved_geometry_digest), &found));
324 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
325 "Checkpoint '%s' does not record geometry identity.", metadata_path);
327 PetscCheck(!strcmp(saved_geometry_digest, current_geometry_digest), PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
328 "Checkpoint geometry/layout does not match the active grid.");
330 PetscCall(PetscOptionsGetInt(options, NULL,
"-checkpoint_payload_count", &payload_count, &found));
331 PetscCheck(found && payload_count > 0, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
332 "Checkpoint '%s' has no payload inventory.", metadata_path);
333 PetscCall(PetscOptionsGetInt(options, NULL,
"-checkpoint_particle_count",
334 &saved_particle_count, &found));
335 PetscCheck(found && saved_particle_count >= 0, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
336 "Checkpoint '%s' has no valid particle count.", metadata_path);
337 PetscCall(PetscOptionsGetBool(options, NULL,
"-checkpoint_particles", &saved_particles, &found));
338 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
339 "Checkpoint '%s' does not record particle-state availability.", metadata_path);
340 PetscCall(PetscOptionsGetBool(options, NULL,
"-checkpoint_les", &saved_les, &found));
341 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
342 "Checkpoint '%s' does not record LES-state availability.", metadata_path);
343 for (PetscInt payload = 0; payload < payload_count; ++payload) {
344 char option_name[96];
345 char relative_path[PETSC_MAX_PATH_LEN];
346 char payload_path[PETSC_MAX_PATH_LEN];
347 long long expected_bytes = -1;
348 char expected_bytes_text[64];
349 struct stat payload_stat;
351 PetscCall(PetscSNPrintf(option_name,
sizeof(option_name),
352 "-checkpoint_payload_%" PetscInt_FMT
"_path", payload));
353 PetscCall(PetscOptionsGetString(options, NULL, option_name,
354 relative_path,
sizeof(relative_path), &found));
355 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
356 "Checkpoint payload %" PetscInt_FMT
" has no path.", payload);
357 PetscCall(PetscSNPrintf(option_name,
sizeof(option_name),
358 "-checkpoint_payload_%" PetscInt_FMT
"_bytes", payload));
359 PetscCall(PetscOptionsGetString(options, NULL, option_name,
360 expected_bytes_text,
sizeof(expected_bytes_text), &found));
361 if (found) expected_bytes = strtoll(expected_bytes_text, NULL, 10);
362 PetscCheck(found && expected_bytes >= 0, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
363 "Checkpoint payload %" PetscInt_FMT
" has no valid byte size.", payload);
364 PetscCall(PetscSNPrintf(payload_path,
sizeof(payload_path),
"%s/%s",
365 checkpoint_directory, relative_path));
366 PetscCheck(stat(payload_path, &payload_stat) == 0 && S_ISREG(payload_stat.st_mode),
367 PETSC_COMM_WORLD, PETSC_ERR_FILE_OPEN,
368 "Checkpoint payload is missing: %s", payload_path);
369 PetscCheck((
long long)payload_stat.st_size == expected_bytes,
370 PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
371 "Checkpoint payload '%s' is %lld bytes; expected %lld.",
372 payload_path, (
long long)payload_stat.st_size, expected_bytes);
374 PetscCall(PetscOptionsDestroy(&options));
375 if (physical_time) *physical_time = saved_time;
376 if (particle_count) *particle_count = saved_particle_count;
377 if (particles_saved) *particles_saved = saved_particles;
378 if (les_saved) *les_saved = saved_les;
379 PetscFunctionReturn(0);
395 if (str[0] ==
'\0')
return;
399 while (isspace((
unsigned char)*start)) {
404 char *end = str + strlen(str) - 1;
406 while (end > start && isspace((
unsigned char)*end)) {
415 memmove(str, start, (end - start) + 2);
431 return (PetscBool)(simCtx->
tiout > 0 && completed_step > 0 && completed_step % simCtx->
tiout == 0);
436#define __FUNCT__ "ReadGridGenerationInputs"
446 PetscInt block_index = user->
_this;
450 PetscInt *IMs = NULL, *JMs = NULL, *KMs = NULL, *cgrids = NULL;
451 PetscReal *xMins = NULL, *xMaxs = NULL, *rxs = NULL;
452 PetscReal *yMins = NULL, *yMaxs = NULL, *rys = NULL;
453 PetscReal *zMins = NULL, *zMaxs = NULL, *rzs = NULL;
455 PetscFunctionBeginUser;
460 if (block_index >= nblk) {
461 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
"Block index %d is out of range for nblk=%d", block_index, nblk);
465 ierr = PetscMalloc4(nblk, &IMs, nblk, &JMs, nblk, &KMs, nblk, &cgrids); CHKERRQ(ierr);
466 ierr = PetscMalloc6(nblk, &xMins, nblk, &xMaxs, nblk, &rxs, nblk, &yMins, nblk, &yMaxs, nblk, &rys); CHKERRQ(ierr);
467 ierr = PetscMalloc3(nblk, &zMins, nblk, &zMaxs, nblk, &rzs); CHKERRQ(ierr);
470 for (PetscInt i = 0; i < nblk; ++i) {
471 IMs[i] = 10; JMs[i] = 10; KMs[i] = 10; cgrids[i] = 0;
472 xMins[i] = 0.0; xMaxs[i] = 1.0; rxs[i] = 1.0;
473 yMins[i] = 0.0; yMaxs[i] = 1.0; rys[i] = 1.0;
474 zMins[i] = 0.0; zMaxs[i] = 1.0; rzs[i] = 1.0;
479 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-im", IMs, &count, &found); CHKERRQ(ierr);
480 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-jm", JMs, &count, &found); CHKERRQ(ierr);
481 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-km", KMs, &count, &found); CHKERRQ(ierr);
482 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-xMins", xMins, &count, &found); CHKERRQ(ierr);
483 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-xMaxs", xMaxs, &count, &found); CHKERRQ(ierr);
484 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-rxs", rxs, &count, &found); CHKERRQ(ierr);
485 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-yMins", yMins, &count, &found); CHKERRQ(ierr);
486 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-yMaxs", yMaxs, &count, &found); CHKERRQ(ierr);
487 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-rys", rys, &count, &found); CHKERRQ(ierr);
488 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-zMins", zMins, &count, &found); CHKERRQ(ierr);
489 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-zMaxs", zMaxs, &count, &found); CHKERRQ(ierr);
490 count = nblk; ierr = PetscOptionsGetRealArray(NULL, NULL,
"-rzs", rzs, &count, &found); CHKERRQ(ierr);
491 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-cgrids", cgrids, &count, &found); CHKERRQ(ierr);
501 PetscCheck(length_ref > 0.0, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
502 "Reference length L_ref must be positive to non-dimensionalize the "
503 "programmatic domain bounds. Got %g", (
double)length_ref);
506 user->
IM = IMs[block_index];
507 user->
JM = JMs[block_index];
508 user->
KM = KMs[block_index];
509 user->
Min_X = xMins[block_index] / length_ref;
510 user->
Max_X = xMaxs[block_index] / length_ref;
511 user->
rx = rxs[block_index];
512 user->
Min_Y = yMins[block_index] / length_ref;
513 user->
Max_Y = yMaxs[block_index] / length_ref;
514 user->
ry = rys[block_index];
515 user->
Min_Z = zMins[block_index] / length_ref;
516 user->
Max_Z = zMaxs[block_index] / length_ref;
517 user->
rz = rzs[block_index];
518 user->
cgrid = cgrids[block_index];
521 simCtx->
rank, block_index, user->
IM, user->
JM, user->
KM);
523 "Y=[%.4g, %.4g], Z=[%.4g, %.4g]\n",
524 simCtx->
rank, block_index, (
double)length_ref,
528 ierr = PetscFree4(IMs, JMs, KMs, cgrids); CHKERRQ(ierr);
529 ierr = PetscFree6(xMins, xMaxs, rxs, yMins, yMaxs, rys); CHKERRQ(ierr);
530 ierr = PetscFree3(zMins, zMaxs, rzs); CHKERRQ(ierr);
533 PetscFunctionReturn(0);
544 PetscInt *IMs = NULL, *JMs = NULL, *KMs = NULL;
547 PetscFunctionBeginUser;
550 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"finest_users cannot be NULL.");
553 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
"nblk must be positive. Got %d.", nblk);
555 simCtx = finest_users[0].
simCtx;
557 ierr = PetscMalloc3(nblk, &IMs, nblk, &JMs, nblk, &KMs); CHKERRQ(ierr);
558 for (PetscInt i = 0; i < nblk; ++i) {
559 IMs[i] = 10; JMs[i] = 10; KMs[i] = 10;
563 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-im", IMs, &count, &found); CHKERRQ(ierr);
564 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-jm", JMs, &count, &found); CHKERRQ(ierr);
565 count = nblk; ierr = PetscOptionsGetIntArray(NULL, NULL,
"-km", KMs, &count, &found); CHKERRQ(ierr);
567 for (PetscInt bi = 0; bi < nblk; ++bi) {
568 finest_users[bi].
IM = IMs[bi];
569 finest_users[bi].
JM = JMs[bi];
570 finest_users[bi].
KM = KMs[bi];
573 "Rank %d: Preloaded analytical grid resolution for block %d: IM=%d, JM=%d, KM=%d\n",
574 simCtx->
rank, bi, finest_users[bi].
IM, finest_users[bi].
JM, finest_users[bi].
KM);
578 ierr = PetscFree3(IMs, JMs, KMs); CHKERRQ(ierr);
579 PetscFunctionReturn(0);
584#define __FUNCT__ "ReadGridFile"
593 PetscInt block_index = user->
_this;
595 PetscFunctionBeginUser;
601 PetscMPIInt rank = simCtx->
rank;
605 FILE *fd = fopen(simCtx->
grid_file,
"r");
606 if (!fd) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Cannot open file: %s", simCtx->
grid_file);
609 char firstTok[32] = {0};
610 if (fscanf(fd,
"%31s", firstTok) != 1)
611 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
"Empty grid file: %s", simCtx->
grid_file);
612 if (strcmp(firstTok,
"PICGRID") != 0)
613 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
614 "Grid file %s must begin with the canonical PICGRID header.", simCtx->
grid_file);
616 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
"Expected number of blocks after \"PICGRID\" in %s", simCtx->
grid_file);
618 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED,
"Mismatch: -nblk is %d but grid file specifies %d blocks.", nblk,
g_nblk_from_file);
622 for (PetscInt i = 0; i < nblk; ++i) {
624 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
"Expected 3 integers for block %d in %s", i, simCtx->
grid_file);
631 ierr = MPI_Bcast(&
g_nblk_from_file, 1, MPI_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
639 ierr = MPI_Bcast(
g_IMs_from_file, nblk, MPI_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
640 ierr = MPI_Bcast(
g_JMs_from_file, nblk, MPI_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
641 ierr = MPI_Bcast(
g_KMs_from_file, nblk, MPI_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
653 simCtx->
rank, block_index, user->
IM, user->
JM, user->
KM);
656 PetscFunctionReturn(0);
674 while (current != NULL) {
676 PetscFree(current->
key);
677 PetscFree(current->
value);
689 else if (strcasecmp(str,
"+Xi") == 0) *face_out =
BC_FACE_POS_X;
690 else if (strcasecmp(str,
"-Eta") == 0) *face_out =
BC_FACE_NEG_Y;
691 else if (strcasecmp(str,
"+Eta") == 0) *face_out =
BC_FACE_POS_Y;
692 else if (strcasecmp(str,
"-Zeta") == 0) *face_out =
BC_FACE_NEG_Z;
693 else if (strcasecmp(str,
"+Zeta") == 0) *face_out =
BC_FACE_POS_Z;
694 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE,
"Unknown face specifier: %s", str);
703 if (strcasecmp(str,
"WALL") == 0) *type_out =
WALL;
704 else if (strcasecmp(str,
"SYMMETRY") == 0) *type_out =
SYMMETRY;
705 else if (strcasecmp(str,
"INLET") == 0) *type_out =
INLET;
706 else if (strcasecmp(str,
"OUTLET") == 0) *type_out =
OUTLET;
707 else if (strcasecmp(str,
"PERIODIC") == 0) *type_out =
PERIODIC;
709 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE,
"Unknown BC Type string: %s", str);
727 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE,
"Unknown BC Handler string: %s", str);
761 *found = PETSC_FALSE;
767 if (strcasecmp(current->
key, key) == 0) {
768 *value_out = atof(current->
value);
772 current = current->
next;
782 *found = PETSC_FALSE;
783 *value_out = PETSC_FALSE;
788 if (strcasecmp(current->
key, key) == 0) {
793 if (current->
value &&
794 (strcasecmp(current->
value,
"true") == 0 ||
795 strcmp(current->
value,
"1") == 0 ||
796 strcasecmp(current->
value,
"yes") == 0))
798 *value_out = PETSC_TRUE;
800 *value_out = PETSC_FALSE;
804 current = current->
next;
810#define __FUNCT__ "GetDrivenSeamFluxFlag"
825 PetscFunctionBeginUser;
827 ierr =
GetBCParamBool(params,
"enforce_seam_flux", value_out, found); CHKERRQ(ierr);
829 ierr =
GetBCParamBool(params,
"apply_trim", value_out, found); CHKERRQ(ierr);
831 PetscFunctionReturn(0);
840#define __FUNCT__ "ParseAllBoundaryConditions"
853 PetscFunctionBeginUser;
855 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
859 char line_buffer[1024];
862 for (
int i = 0; i < 6; i++) {
866 configs_rank0[i].
params = NULL;
867 configs_rank0[i].
handler = NULL;
871 file = fopen(bcs_input_filename,
"r");
872 if (!file) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Could not open BCs file '%s'.", bcs_input_filename);
874 while (fgets(line_buffer,
sizeof(line_buffer), file)) {
875 char *current_pos = line_buffer;
876 while (isspace((
unsigned char)*current_pos)) current_pos++;
877 if (*current_pos ==
'#' || *current_pos ==
'\0' || *current_pos ==
'\n' || *current_pos ==
'\r')
continue;
879 char *face_str = strtok(current_pos,
" \t\n\r");
880 char *type_str = strtok(NULL,
" \t\n\r");
881 char *handler_str = strtok(NULL,
" \t\n\r");
883 if (!face_str || !type_str || !handler_str) {
891 const char* handler_name_for_log;
898 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);
904 LOG_ALLOW(
GLOBAL,
LOG_DEBUG,
" Parsed Face '%s': Type=%s, Handler=%s \n", face_str, type_str, handler_name_for_log);
908 configs_rank0[face_enum].
params = NULL;
912 while ((token = strtok(NULL,
" \t\n\r")) != NULL) {
913 char* equals_ptr = strchr(token,
'=');
920 char* key_str = token;
921 char* value_str = equals_ptr + 1;
924 ierr = PetscMalloc1(1, &new_param); CHKERRQ(ierr);
925 ierr = PetscStrallocpy(key_str, &new_param->
key); CHKERRQ(ierr);
926 ierr = PetscStrallocpy(value_str, &new_param->
value); CHKERRQ(ierr);
927 new_param->
next = NULL;
929 *param_next_ptr = new_param;
930 param_next_ptr = &new_param->
next;
944 for (
int i = 0; i < 6; i++) {
953 PetscInt n_params = 0;
957 ierr = MPI_Bcast(&n_params, 1, MPI_INT, 0, PETSC_COMM_WORLD);CHKERRQ(ierr);
966 for (
int j = 0; j < n_params; j++) {
967 char key_buf[256] = {0}, val_buf[256] = {0};
971 for (
int k = 0; k < j; k++) p = p->
next;
972 strncpy(key_buf, p->
key, 255);
973 strncpy(val_buf, p->
value, 255);
976 ierr = MPI_Bcast(key_buf, 256, MPI_CHAR, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
977 ierr = MPI_Bcast(val_buf, 256, MPI_CHAR, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
982 ierr = PetscMalloc1(1, &new_param); CHKERRQ(ierr);
983 ierr = PetscStrallocpy(key_buf, &new_param->
key); CHKERRQ(ierr);
984 ierr = PetscStrallocpy(val_buf, &new_param->
value); CHKERRQ(ierr);
985 new_param->
next = NULL;
986 *param_next_ptr = new_param;
987 param_next_ptr = &new_param->
next;
990 param_next_ptr = &((*param_next_ptr)->next);
998 for (
int i=0; i<6; i++) {
1016 PetscFunctionReturn(0);
1027#define __FUNCT__ "DeterminePeriodicity"
1034 PetscErrorCode ierr;
1036 PetscInt periodic_flags[3] = {0, 0, 0};
1038 PetscFunctionBeginUser;
1039 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1042 for (PetscInt bi = 0; bi < simCtx->
block_number; bi++) {
1043 const char *bcs_filename = simCtx->
bcs_files[bi];
1044 if (!bcs_filename) SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_NULL,
"BCS filename for block %d is not set in SimCtx.", bi);
1046 PetscBool file_exists;
1047 snprintf(desc_buf,
sizeof(desc_buf),
"BCS file for block %d", bi);
1048 ierr =
VerifyPathExistence(bcs_filename, PETSC_FALSE, PETSC_FALSE, desc_buf, &file_exists); CHKERRQ(ierr);
1053 PetscBool global_is_periodic[3] = {PETSC_FALSE, PETSC_FALSE, PETSC_FALSE};
1054 PetscBool is_set = PETSC_FALSE;
1056 for (PetscInt bi = 0; bi < simCtx->
block_number; bi++) {
1057 const char *bcs_filename = simCtx->
bcs_files[bi];
1058 FILE *file = fopen(bcs_filename,
"r");
1060 PetscBool face_is_periodic[6] = {PETSC_FALSE};
1061 char line_buffer[1024];
1063 while (fgets(line_buffer,
sizeof(line_buffer), file)) {
1064 char *current_pos = line_buffer;
1065 while (isspace((
unsigned char)*current_pos)) current_pos++;
1066 if (*current_pos ==
'#' || *current_pos ==
'\0' || *current_pos ==
'\n')
continue;
1069 char *face_str = strtok(current_pos,
" \t\n\r");
1070 char *type_str = strtok(NULL,
" \t\n\r");
1073 if (!face_str || !type_str)
continue;
1076 if (strcasecmp(type_str,
"PERIODIC") == 0) {
1080 face_is_periodic[face_enum] = PETSC_TRUE;
1088 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);
1090 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);
1092 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);
1098 global_is_periodic[0] = local_is_periodic[0];
1099 global_is_periodic[1] = local_is_periodic[1];
1100 global_is_periodic[2] = local_is_periodic[2];
1101 is_set = PETSC_TRUE;
1103 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]) {
1104 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
1105 "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).",
1106 (
int)global_is_periodic[0], (
int)global_is_periodic[1], (
int)global_is_periodic[2],
1108 (
int)local_is_periodic[0], (
int)local_is_periodic[1], (
int)local_is_periodic[2]);
1113 periodic_flags[0] = (global_is_periodic[0]) ? 1 : 0;
1114 periodic_flags[1] = (global_is_periodic[1]) ? 1 : 0;
1115 periodic_flags[2] = (global_is_periodic[2]) ? 1 : 0;
1118 periodic_flags[0], periodic_flags[1], periodic_flags[2]);
1122 ierr = MPI_Bcast(periodic_flags, 3, MPIU_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
1129 PetscFunctionReturn(0);
1136PetscErrorCode
VerifyPathExistence(
const char *path, PetscBool is_dir, PetscBool is_optional,
const char *description, PetscBool *exists)
1138 PetscErrorCode ierr;
1140 MPI_Comm comm = PETSC_COMM_WORLD;
1142 PetscFunctionBeginUser;
1143 ierr = MPI_Comm_rank(comm, &rank); CHKERRQ(ierr);
1147 ierr = PetscTestDirectory(path,
'r', exists); CHKERRQ(ierr);
1149 ierr = PetscTestFile(path,
'r', exists); CHKERRQ(ierr);
1164 PetscMPIInt exists_int = (rank == 0) ? (PetscMPIInt)(*exists) : 0;
1165 ierr = MPI_Bcast(&exists_int, 1, MPI_INT, 0, comm); CHKERRMPI(ierr);
1166 *exists = (PetscBool)exists_int;
1169 if (!(*exists) && !is_optional) {
1170 SETERRQ(comm, PETSC_ERR_FILE_OPEN,
"Mandatory %s not found. Rank 0 expected it at '%s'. Check path and permissions.", description, path);
1173 PetscFunctionReturn(0);
1177#define __FUNCT__ "ReadFieldData"
1183 const char *field_name,
1187 PetscErrorCode ierr;
1188 char filename[PETSC_MAX_PATH_LEN];
1190 PetscMPIInt rank,size;
1194 PetscFunctionBeginUser;
1198 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,
"I/O context directory was not set before calling ReadFieldData().");
1202 ierr = PetscObjectGetComm((PetscObject)field_vec,&comm);CHKERRQ(ierr);
1203 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
1204 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
1206 const char *source_path = NULL;
1210 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,
"source_path was not set for the current execution mode.");
1212 ierr = PetscSNPrintf(filename,
sizeof(filename),
"%s/%s.%s",
1213 source_path, field_name, ext); CHKERRQ(ierr);
1216 "Attempting to read <%s> on rank %d/%d\n",
1217 filename,(
int)rank,(
int)size);
1227 PetscInt expectedSize,loadedSize;
1229 ierr = PetscTestFile(filename,
'r',&found);CHKERRQ(ierr);
1230 if(!found) SETERRQ(comm,PETSC_ERR_FILE_OPEN,
1231 "Restart/Source file not found: %s",filename);
1233 ierr = PetscViewerBinaryOpen(PETSC_COMM_SELF,filename,FILE_MODE_READ,&viewer);CHKERRQ(ierr);
1237 ierr = VecCreate(PETSC_COMM_SELF, &temp_vec); CHKERRQ(ierr);
1238 ierr = VecLoad(temp_vec,viewer);CHKERRQ(ierr);
1239 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1242 ierr = VecGetSize(field_vec, &expectedSize);CHKERRQ(ierr);
1243 ierr = VecGetSize(temp_vec, &loadedSize);CHKERRQ(ierr);
1244 if (loadedSize != expectedSize) {
1245 SETERRQ(comm,PETSC_ERR_FILE_UNEXPECTED,
1246 "File %s holds %d entries – expected %d for field '%s'",
1247 filename, loadedSize, expectedSize, field_name);
1251 ierr = VecCopy(temp_vec, field_vec);CHKERRQ(ierr);
1254 ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
1270 "Loaded <%s> (serial path)\n",filename);
1273 PetscFunctionReturn(0);
1279 PetscInt globalSize;
1280 ierr = VecGetSize(field_vec,&globalSize);CHKERRQ(ierr);
1283 const char *dmtype = NULL;
1288 const PetscScalar *seqArray = NULL;
1295 ierr = PetscTestFile(filename,
'r',&found);CHKERRQ(ierr);
1296 if(!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,
1297 "Restart file not found: %s",filename);
1300 ierr = VecCreate(PETSC_COMM_SELF,&seq_vec);CHKERRQ(ierr);
1301 ierr = VecSetType(seq_vec,VECSEQ);CHKERRQ(ierr);
1303 ierr = PetscViewerBinaryOpen(PETSC_COMM_SELF,filename,
1304 FILE_MODE_READ,&viewer);CHKERRQ(ierr);
1305 ierr = VecLoad(seq_vec,viewer);CHKERRQ(ierr);
1306 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
1310 ierr = VecGetSize(seq_vec,&loaded);CHKERRQ(ierr);
1311 if(loaded != globalSize)
1312 SETERRQ(comm,PETSC_ERR_FILE_UNEXPECTED,
1313 "File %s holds %d entries – expected %d",
1314 filename,loaded,globalSize);
1317 ierr = VecGetArrayRead(seq_vec,&seqArray);CHKERRQ(ierr);
1320 "Rank 0 successfully loaded <%s>\n",filename);
1324 ierr = VecGetDM(field_vec, &dm); CHKERRQ(ierr);
1325 if (dm) { ierr = DMGetType(dm, &dmtype); CHKERRQ(ierr); }
1327 if (dmtype && !strcmp(dmtype, DMDA)) {
1333 ierr = DMDACreateNaturalVector(dm, &nat); CHKERRQ(ierr);
1339 ierr = VecScatterCreateToZero(nat, &scatter, &nat_seq); CHKERRQ(ierr);
1342 ierr = VecScatterBegin(scatter, (rank == 0 ? seq_vec : nat_seq), nat,
1343 INSERT_VALUES, SCATTER_REVERSE); CHKERRQ(ierr);
1344 ierr = VecScatterEnd(scatter, (rank == 0 ? seq_vec : nat_seq), nat,
1345 INSERT_VALUES, SCATTER_REVERSE); CHKERRQ(ierr);
1348 ierr = DMDANaturalToGlobalBegin(dm, nat, INSERT_VALUES, field_vec); CHKERRQ(ierr);
1349 ierr = DMDANaturalToGlobalEnd(dm, nat, INSERT_VALUES, field_vec); CHKERRQ(ierr);
1352 ierr = VecScatterDestroy(&scatter); CHKERRQ(ierr);
1353 ierr = VecDestroy(&nat_seq); CHKERRQ(ierr);
1354 ierr = VecDestroy(&nat); CHKERRQ(ierr);
1361 PetscScalar *buffer = NULL;
1363 buffer = (PetscScalar *)seqArray;
1365 ierr = PetscMalloc1(globalSize, &buffer); CHKERRQ(ierr);
1368 ierr = MPI_Bcast(buffer, (
int)globalSize, MPIU_SCALAR, 0, comm); CHKERRQ(ierr);
1371 PetscInt rstart, rend, loc;
1372 PetscScalar *locArray;
1374 ierr = VecGetOwnershipRange(field_vec, &rstart, &rend); CHKERRQ(ierr);
1375 loc = rend - rstart;
1377 ierr = VecGetArray(field_vec, &locArray); CHKERRQ(ierr);
1378 ierr = PetscMemcpy(locArray, buffer + rstart, loc *
sizeof(PetscScalar)); CHKERRQ(ierr);
1379 ierr = VecRestoreArray(field_vec, &locArray); CHKERRQ(ierr);
1382 ierr = PetscFree(buffer); CHKERRQ(ierr);
1388 ierr = VecRestoreArrayRead(seq_vec, &seqArray); CHKERRQ(ierr);
1389 ierr = VecDestroy(&seq_vec); CHKERRQ(ierr);
1393 "Loaded <%s> (parallel path)\n",filename);
1396 PetscFunctionReturn(0);
1401#define __FUNCT__ "RestoreDrivenFluxTarget"
1421 const char *checkpoint_directory)
1423 char metadata_path[PETSC_MAX_PATH_LEN];
1424 PetscOptions options = NULL;
1425 PetscBool uses_initial_flux = PETSC_FALSE;
1426 PetscBool saved_latched = PETSC_FALSE;
1427 PetscBool found = PETSC_FALSE;
1428 PetscReal saved_target = 0.0;
1430 PetscFunctionBeginUser;
1432 for (PetscInt face = 0; face < 6; ++face) {
1434 uses_initial_flux = PETSC_TRUE;
1438 if (!uses_initial_flux) PetscFunctionReturn(0);
1440 PetscCall(PetscSNPrintf(metadata_path,
sizeof(metadata_path),
1441 "%s/checkpoint.meta", checkpoint_directory));
1442 PetscCall(PetscOptionsCreate(&options));
1443 PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, metadata_path, PETSC_TRUE));
1444 PetscCall(PetscOptionsGetBool(options, NULL,
"-checkpoint_driven_flux_latched", &saved_latched, &found));
1445 if (found && saved_latched) {
1446 PetscCall(PetscOptionsGetReal(options, NULL,
"-checkpoint_driven_flux_target", &saved_target, &found));
1448 found = PETSC_FALSE;
1450 PetscCall(PetscOptionsDestroy(&options));
1456 "Driven Flow: restored latched target volumetric flux %.6e from checkpoint '%s'.\n",
1457 (
double)saved_target, checkpoint_directory);
1460 "Driven Flow: checkpoint '%s' records no latched flux target; the initial_flux "
1461 "controller will re-measure it from the restarted field.\n", checkpoint_directory);
1464 PetscFunctionReturn(0);
1474 const char *source_path = NULL;
1475 char checkpoint_directory[PETSC_MAX_PATH_LEN];
1476 PetscReal checkpoint_time = 0.0;
1477 PetscBool particles_saved = PETSC_FALSE;
1478 PetscBool les_saved = PETSC_FALSE;
1480 PetscFunctionBeginUser;
1486 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"Invalid execution mode for reading simulation fields.");
1490 checkpoint_directory,
sizeof(checkpoint_directory)));
1492 checkpoint_directory, ti, &checkpoint_time, NULL,
1493 &particles_saved, &les_saved));
1495 PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
1496 "Particle restart_mode=load was requested, but checkpoint step %" PetscInt_FMT
1497 " contains no particle state.", ti);
1499 simCtx->
ti = checkpoint_time;
1505 user->
_this, checkpoint_directory);
1507 "%s/%s/block_%04" PetscInt_FMT,
1520 (!particles_saved ||
1529 !(simCtx->
les && les_saved))
continue;
1536 PetscReal scale = 1.0;
1539 if (scale != 1.0) PetscCall(VecScale(view.
global_vec, scale));
1545 PetscFunctionReturn(0);
1550#define __FUNCT__ "ReadStatisticsWindowState"
1553 const char *metadata_path, PetscReal checkpoint_time,
1557 char option_name[128];
1559 char saved_digest[65] =
"";
1561 char saved_state[32] =
"";
1562 char current_digest[65] =
"";
1563 PetscBool found = PETSC_FALSE;
1564 PetscBool name_matches = PETSC_FALSE;
1566 PetscFunctionBeginUser;
1569#define PICURV_STATISTICS_REQUIRE(suffix, getter, target) \
1571 PetscCall(PetscSNPrintf(option_name, sizeof(option_name), \
1572 "-checkpoint_statistics_window_%" PetscInt_FMT "_" suffix, window)); \
1573 PetscCall(getter(options, NULL, option_name, target, &found)); \
1574 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED, \
1575 "Statistics continuation requested, but '%s' records no %s for window " \
1576 "%" PetscInt_FMT ".", metadata_path, suffix, window); \
1579 PetscCall(PetscSNPrintf(option_name,
sizeof(option_name),
1580 "-checkpoint_statistics_window_%" PetscInt_FMT
"_name", window));
1581 PetscCall(PetscOptionsGetString(options, NULL, option_name, saved_name,
sizeof(saved_name), &found));
1582 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
1583 "Statistics continuation requested, but '%s' records no name for window %" PetscInt_FMT
".",
1584 metadata_path, window);
1585 PetscCall(PetscStrcmp(saved_name, state->
definition.
name, &name_matches));
1586 PetscCheck(name_matches, PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
1587 "Statistics window %" PetscInt_FMT
" is '%s' in the checkpoint but '%s' in this run. "
1588 "Window order and names must match to continue.",
1591 PetscCall(PetscSNPrintf(option_name,
sizeof(option_name),
1592 "-checkpoint_statistics_window_%" PetscInt_FMT
"_hash", window));
1593 PetscCall(PetscOptionsGetString(options, NULL, option_name, saved_digest,
sizeof(saved_digest), &found));
1594 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
1595 "Statistics continuation requested, but '%s' records no hash for window '%s'.",
1598 if (strcmp(saved_digest, current_digest)) {
1599 const char *differing =
"an unrecorded property";
1604 PetscCall(PetscSNPrintf(option_name,
sizeof(option_name),
1605 "-checkpoint_statistics_window_%" PetscInt_FMT
"_hash_groups", window));
1606 PetscCall(PetscOptionsGetString(options, NULL, option_name, saved_groups,
1607 sizeof(saved_groups), &found));
1609 PetscInt group = -1;
1614 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
1615 "Statistics window '%s' was defined differently in the checkpoint: %s changed. "
1616 "Continuing would merge incompatible samples; rename the window to start a new one.",
1630#undef PICURV_STATISTICS_REQUIRE
1632 PetscCall(PetscSNPrintf(option_name,
sizeof(option_name),
1633 "-checkpoint_statistics_window_%" PetscInt_FMT
"_state", window));
1634 PetscCall(PetscOptionsGetString(options, NULL, option_name, saved_state,
sizeof(saved_state), &found));
1635 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
1636 "Statistics continuation requested, but '%s' records no lifecycle state for window '%s'.",
1650 PetscCheck(checkpoint_time - state->
effective_end <= PetscMax(step_size, 0.0),
1651 PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
1652 "Statistics window '%s' ended at t=%.17g and this checkpoint is at t=%.17g, "
1653 "so extending it to %.17g would weight %.17g of unobserved time. "
1654 "Start a new window instead.",
1659 "Statistics window '%s' was complete at t=%.6g and is extended to t=%.6g.\n",
1665 PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
1666 "Statistics window '%s' already represents time up to %.17g, past the requested end "
1667 "%.17g. A window may be extended forward but never shortened; rename it to start a new one.",
1675 PetscFunctionReturn(0);
1679#define __FUNCT__ "RestoreFieldStatisticsState"
1689 PetscOptions options = NULL;
1690 char checkpoint_directory[PETSC_MAX_PATH_LEN];
1691 char metadata_path[PETSC_MAX_PATH_LEN];
1692 const char *source_path = NULL;
1693 PetscInt saved_window_count = 0;
1694 PetscReal checkpoint_time = 0.0;
1695 PetscBool found = PETSC_FALSE;
1697 PetscFunctionBeginUser;
1699 PetscCheck(simCtx != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"SimCtx cannot be NULL.");
1703 "Statistics continuation was not requested; %d window(s) start from zero.\n",
1706 PetscFunctionReturn(0);
1710 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
1711 "Finest-level fields must exist before statistics state is restored.");
1714 PetscCheck(source_path != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
1715 "No checkpoint source directory is set for the current execution mode.");
1717 checkpoint_directory,
sizeof(checkpoint_directory)));
1719 &checkpoint_time, NULL, NULL, NULL));
1720 PetscCall(PetscSNPrintf(metadata_path,
sizeof(metadata_path),
"%s/checkpoint.meta",
1721 checkpoint_directory));
1723 PetscCall(PetscOptionsCreate(&options));
1724 PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, metadata_path, PETSC_TRUE));
1725 PetscCall(PetscOptionsGetInt(options, NULL,
"-checkpoint_statistics_window_count",
1726 &saved_window_count, &found));
1731 PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
1732 "Statistics continuation requested, but checkpoint '%s' holds %" PetscInt_FMT
1733 " window(s) and this run configures %" PetscInt_FMT
".",
1734 checkpoint_directory, found ? saved_window_count : 0,
1742 PetscCall(PetscOptionsDestroy(&options));
1744 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
1745 PetscCheck(user[block].fieldStatisticsStorage != NULL, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
1746 "Statistics accumulators were not allocated for block %" PetscInt_FMT
".", block);
1750 PetscInt payload_count = 0;
1757 for (PetscInt index = 0; index < payload_count; ++index) {
1771 "Statistics window '%s' continued from '%s': state %s, %d sample(s), "
1772 "total weight %.6g, represented time %.6g, restart segment %d.\n",
1779 PetscFunctionReturn(0);
1788 PetscErrorCode ierr;
1794 swarm = user->
swarm;
1799 ierr = DMSwarmCreateGlobalVectorFromField(swarm, field_name, &fieldVec);CHKERRQ(ierr);
1804 ierr =
ReadFieldData(user, field_name, fieldVec, ext);CHKERRQ(ierr);
1807 ierr = DMSwarmDestroyGlobalVectorFromField(swarm, field_name, &fieldVec);CHKERRQ(ierr);
1809 PetscFunctionReturn(0);
1818 PetscErrorCode ierr;
1819 DM swarm = user->
swarm;
1821 PetscInt nlocal, nglobal, bs, i;
1822 PetscDataType field_type;
1823 const PetscScalar *scalar_array;
1824 void *field_array_void;
1827 PetscFunctionBeginUser;
1832 ierr = DMSwarmGetLocalSize(swarm, &nlocal); CHKERRQ(ierr);
1833 ierr = DMSwarmGetSize(swarm, &nglobal); CHKERRQ(ierr);
1835 ierr = DMSwarmGetField(swarm, field_name, &bs, &field_type, NULL); CHKERRQ(ierr);
1836 ierr = DMSwarmRestoreField(swarm, field_name, &bs, NULL, NULL); CHKERRQ(ierr);
1837 PetscCheck(field_type == PETSC_INT || field_type == PETSC_INT64,
1838 PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
1839 "Swarm field '%s' must use PETSC_INT or PETSC_INT64 for integer restart input, not %s.",
1840 field_name, PetscDataTypes[field_type]);
1843 ierr = VecCreate(PETSC_COMM_WORLD, &temp_vec); CHKERRQ(ierr);
1844 ierr = VecSetType(temp_vec, VECMPI); CHKERRQ(ierr);
1845 ierr = VecSetSizes(temp_vec, nlocal * bs, nglobal * bs); CHKERRQ(ierr);
1846 ierr = VecSetBlockSize(temp_vec, bs); CHKERRQ(ierr);
1847 ierr = VecSetUp(temp_vec); CHKERRQ(ierr);
1850 ierr =
ReadFieldData(user, field_name, temp_vec, ext); CHKERRQ(ierr);
1853 ierr = VecGetArrayRead(temp_vec, &scalar_array); CHKERRQ(ierr);
1854 ierr = DMSwarmGetField(swarm, field_name, NULL, NULL, &field_array_void); CHKERRQ(ierr);
1857 if (field_type == PETSC_INT64) {
1858 PetscInt64 *int64_array = (PetscInt64 *)field_array_void;
1859 for (i = 0; i < nlocal * bs; i++) {
1860 int64_array[i] = (PetscInt64)scalar_array[i];
1863 PetscInt *int_array = (PetscInt *)field_array_void;
1864 for (i = 0; i < nlocal * bs; i++) {
1865 int_array[i] = (PetscInt)scalar_array[i];
1870 ierr = DMSwarmRestoreField(swarm, field_name, NULL, NULL, &field_array_void); CHKERRQ(ierr);
1871 ierr = VecRestoreArrayRead(temp_vec, &scalar_array); CHKERRQ(ierr);
1874 ierr = VecDestroy(&temp_vec); CHKERRQ(ierr);
1876 PetscFunctionReturn(0);
1887 const char *source_path = NULL;
1888 char checkpoint_directory[PETSC_MAX_PATH_LEN];
1890 PetscFunctionBeginUser;
1891 PetscCall(DMSwarmGetSize(user->
swarm, &nGlobal));
1896 PetscFunctionReturn(0);
1905 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
"Invalid execution mode for reading simulation fields.");
1909 checkpoint_directory,
sizeof(checkpoint_directory)));
1929 PetscFunctionReturn(0);
1936 const char *source_path = NULL;
1937 char checkpoint_directory[PETSC_MAX_PATH_LEN];
1938 PetscBool particles_saved = PETSC_FALSE;
1940 PetscFunctionBeginUser;
1941 PetscCheck(user != NULL && particle_count != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
1942 "Simulation context and particle-count output are required.");
1946 else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
1947 "Invalid execution mode for reading checkpoint particle metadata.");
1950 checkpoint_directory,
sizeof(checkpoint_directory)));
1952 checkpoint_directory, ti, NULL, particle_count,
1953 &particles_saved, NULL));
1954 PetscCheck(particles_saved, PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
1955 "Checkpoint step %" PetscInt_FMT
" contains no particle state.", ti);
1956 PetscFunctionReturn(0);
1961#define __FUNCT__ "WriteFieldData"
1967 const char *field_name,
1973 Vec sequential_vec = NULL;
1974 char filename[PETSC_MAX_PATH_LEN];
1977 PetscFunctionBeginUser;
1981 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,
"I/O context directory was not set before calling WriteFieldData().");
1987 PetscCall(PetscObjectGetComm((PetscObject)field_vec,&comm));
1988 PetscCallMPI(MPI_Comm_rank(comm,&rank));
1990 PetscCall(PetscSNPrintf(filename,
sizeof(filename),
"%s/%s.%s",
1996 PetscReal vmin, vmax;
1998 PetscCall(VecMin(sequential_vec, NULL, &vmin));
1999 PetscCall(VecMax(sequential_vec, NULL, &vmax));
2001 " <%s> range = [%.4e … %.4e]\n",
2002 field_name,(
double)vmin,(
double)vmax);
2003 PetscCall(PetscViewerBinaryOpen(PETSC_COMM_SELF, filename, FILE_MODE_WRITE, &viewer));
2004 PetscCall(PetscViewerBinarySetSkipInfo(viewer, PETSC_TRUE));
2005 PetscCall(VecView(sequential_vec, viewer));
2006 PetscCall(PetscViewerDestroy(&viewer));
2009 PetscCall(VecDestroy(&sequential_vec));
2012 PetscFunctionReturn(0);
2025 PetscFunctionBeginUser;
2026 PetscCheck(checkpoint_directory != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2027 "Checkpoint destination cannot be NULL.");
2029 "%s/%s/block_%04" PetscInt_FMT,
2050 PetscFunctionReturn(0);
2054#define __FUNCT__ "WriteStatisticsFields"
2060 PetscFunctionBeginUser;
2062 PetscCheck(checkpoint_directory != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2063 "Checkpoint destination cannot be NULL.");
2068 PetscInt payload_count = 0;
2075 for (PetscInt index = 0; index < payload_count; ++index) {
2079 storage, index, &payload));
2083 "Wrote %d statistics payload(s) for window '%s' block %d.\n",
2089 PetscFunctionReturn(0);
2100 PetscErrorCode ierr;
2104 PetscFunctionBeginUser;
2110 swarm = user->
swarm;
2118 "Attempting to create global vector from field: %s\n",
2120 ierr = DMSwarmCreateGlobalVectorFromField(swarm, field_name, &fieldVec);CHKERRQ(ierr);
2127 "Calling WriteFieldData for field: %s\n",
2129 ierr =
WriteFieldData(user, field_name, fieldVec, ext);CHKERRQ(ierr);
2137 "Destroying the global vector for field: %s\n",
2139 ierr = DMSwarmDestroyGlobalVectorFromField(swarm, field_name, &fieldVec);CHKERRQ(ierr);
2143 "Successfully wrote swarm data for field: %s\n",
2146 PetscFunctionReturn(0);
2155 PetscErrorCode ierr;
2156 DM swarm = user->
swarm;
2158 PetscInt nlocal, nglobal,bs,i;
2159 PetscDataType field_type;
2160 void *field_array_void;
2161 PetscScalar *scalar_array;
2163 PetscFunctionBeginUser;
2168 ierr = DMSwarmGetLocalSize(swarm, &nlocal); CHKERRQ(ierr);
2169 ierr = DMSwarmGetSize(swarm, &nglobal); CHKERRQ(ierr);
2170 ierr = DMSwarmGetField(swarm, field_name, &bs, &field_type, &field_array_void); CHKERRQ(ierr);
2171 PetscCheck(field_type == PETSC_INT || field_type == PETSC_INT64,
2172 PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
2173 "Swarm field '%s' must use PETSC_INT or PETSC_INT64 for integer output, not %s.",
2174 field_name, PetscDataTypes[field_type]);
2177 ierr = VecCreate(PETSC_COMM_WORLD, &temp_vec); CHKERRQ(ierr);
2178 ierr = VecSetType(temp_vec, VECMPI); CHKERRQ(ierr);
2179 ierr = VecSetSizes(temp_vec, nlocal*bs, nglobal*bs); CHKERRQ(ierr);
2180 ierr = VecSetUp(temp_vec); CHKERRQ(ierr);
2185 ierr = VecGetArray(temp_vec, &scalar_array); CHKERRQ(ierr);
2187 if (field_type == PETSC_INT64) {
2188 PetscInt64 *int64_array = (PetscInt64 *)field_array_void;
2190 for (i = 0; i < nlocal*bs; i++) {
2191 scalar_array[i] = (PetscScalar)int64_array[i];
2194 PetscInt *int_array = (PetscInt *)field_array_void;
2196 for (i = 0; i < nlocal*bs; i++) {
2197 scalar_array[i] = (PetscScalar)int_array[i];
2202 ierr = VecRestoreArray(temp_vec, &scalar_array); CHKERRQ(ierr);
2203 ierr = DMSwarmRestoreField(swarm, field_name, &bs, NULL, &field_array_void); CHKERRQ(ierr);
2206 ierr =
WriteFieldData(user, field_name, temp_vec, ext); CHKERRQ(ierr);
2209 ierr = VecDestroy(&temp_vec); CHKERRQ(ierr);
2211 PetscFunctionReturn(0);
2222 PetscFunctionBeginUser;
2225 if (!user->
swarm || simCtx->
np <= 0) {
2226 PetscFunctionReturn(0);
2229 PetscCheck(checkpoint_directory != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2230 "Checkpoint destination cannot be NULL.");
2249 PetscFunctionReturn(0);
2254 const char *checkpoint_directory,
2255 PetscInt payload_index,
2256 const char *relative_path,
2258 const char *field_name,
2261 PetscInt components,
2262 const char *logical_type,
2263 PetscInt global_size,
2264 const char *encoding)
2266 char payload_path[PETSC_MAX_PATH_LEN];
2267 struct stat payload_stat;
2269 PetscFunctionBeginUser;
2270 PetscCheck(manifest != NULL && checkpoint_directory != NULL && relative_path != NULL,
2271 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Checkpoint payload metadata inputs are required.");
2272 PetscCall(PetscSNPrintf(payload_path,
sizeof(payload_path),
"%s/%s",
2273 checkpoint_directory, relative_path));
2274 PetscCheck(stat(payload_path, &payload_stat) == 0 && S_ISREG(payload_stat.st_mode),
2275 PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
2276 "Expected checkpoint payload was not written: %s", payload_path);
2277 PetscCheck(fprintf(manifest,
2278 "-checkpoint_payload_%" PetscInt_FMT
"_path %s\n"
2279 "-checkpoint_payload_%" PetscInt_FMT
"_kind %s\n"
2280 "-checkpoint_payload_%" PetscInt_FMT
"_field %s\n"
2281 "-checkpoint_payload_%" PetscInt_FMT
"_block %" PetscInt_FMT
"\n"
2282 "-checkpoint_payload_%" PetscInt_FMT
"_layout %s\n"
2283 "-checkpoint_payload_%" PetscInt_FMT
"_components %" PetscInt_FMT
"\n"
2284 "-checkpoint_payload_%" PetscInt_FMT
"_logical_type %s\n"
2285 "-checkpoint_payload_%" PetscInt_FMT
"_global_size %" PetscInt_FMT
"\n"
2286 "-checkpoint_payload_%" PetscInt_FMT
"_encoding %s\n"
2287 "-checkpoint_payload_%" PetscInt_FMT
"_bytes %lld\n",
2288 payload_index, relative_path,
2289 payload_index, kind,
2290 payload_index, field_name,
2291 payload_index, block,
2292 payload_index, layout,
2293 payload_index, components,
2294 payload_index, logical_type,
2295 payload_index, global_size,
2296 payload_index, encoding,
2297 payload_index, (
long long)payload_stat.st_size) > 0,
2298 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2299 "Unable to append payload metadata for '%s'.", relative_path);
2300 PetscFunctionReturn(0);
2305 const char *checkpoint_directory,
2307 const char *geometry_digest,
2308 PetscInt particle_count,
2309 char manifest_digest[65])
2311 char metadata_path[PETSC_MAX_PATH_LEN];
2312 PetscInt payload_count = 0;
2313 PetscInt payload_index = 0;
2314 FILE *manifest = NULL;
2316 PetscFunctionBeginUser;
2317 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2324 if (simCtx->
np > 0) {
2332 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2333 if (!user[block].fieldStatisticsStorage)
continue;
2335 PetscInt storage_payloads = 0;
2338 &storage_payloads));
2339 payload_count += storage_payloads;
2344 if (simCtx->
rank == 0) {
2345 PetscCall(PetscSNPrintf(metadata_path,
sizeof(metadata_path),
2346 "%s/checkpoint.meta", checkpoint_directory));
2347 manifest = fopen(metadata_path,
"w");
2348 PetscCheck(manifest != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
2349 "Unable to create checkpoint metadata '%s'.", metadata_path);
2350 PetscCheck(fprintf(manifest,
2351 "-checkpoint_format %s\n"
2352 "-checkpoint_version %d\n"
2353 "-checkpoint_picurv_release %s\n"
2354 "-checkpoint_picurv_commit %s\n"
2355 "-checkpoint_picurv_dirty %s\n"
2356 "-checkpoint_step %" PetscInt_FMT
"\n"
2357 "-checkpoint_time %.17g\n"
2358 "-checkpoint_dt %.17g\n"
2359 "-checkpoint_reason %s\n"
2360 "-checkpoint_geometry_sha256 %s\n"
2361 "-checkpoint_block_count %" PetscInt_FMT
"\n"
2362 "-checkpoint_particles %s\n"
2363 "-checkpoint_particle_count %" PetscInt_FMT
"\n"
2364 "-checkpoint_les %s\n"
2365 "-checkpoint_payload_count %" PetscInt_FMT
"\n",
2368 simCtx->
step, (
double)simCtx->
ti, (
double)simCtx->
dt,
2370 simCtx->
np > 0 ?
"true" :
"false",
2372 simCtx->
les ?
"true" :
"false",
2374 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2375 "Unable to write checkpoint metadata '%s'.", metadata_path);
2377 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2378 PetscCheck(fprintf(manifest,
2379 "-checkpoint_block_%" PetscInt_FMT
"_im %" PetscInt_FMT
"\n"
2380 "-checkpoint_block_%" PetscInt_FMT
"_jm %" PetscInt_FMT
"\n"
2381 "-checkpoint_block_%" PetscInt_FMT
"_km %" PetscInt_FMT
"\n",
2382 block, user[block].IM, block, user[block].JM, block, user[block].KM) > 0,
2383 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2384 "Unable to write block metadata for block %" PetscInt_FMT
".", block);
2386 PetscCheck(fprintf(manifest,
"-checkpoint_periodic %d,%d,%d\n",
2389 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2390 "Unable to write checkpoint periodicity metadata.");
2395 PetscCheck(fprintf(manifest,
2396 "-checkpoint_driven_flux_latched %s\n"
2397 "-checkpoint_driven_flux_target %.17g\n",
2400 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2401 "Unable to write driven-flow controller metadata.");
2405 PetscCheck(fprintf(manifest,
"-checkpoint_statistics_window_count %" PetscInt_FMT
"\n",
2407 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2408 "Unable to write statistics window count.");
2412 char digest[65] =
"";
2421 PetscCall(PetscStrlen(group_list, &used));
2422 PetscCall(PetscSNPrintf(group_list + used,
sizeof(group_list) - used,
"%s%s",
2423 group ?
"," :
"", groups[group]));
2425 PetscCheck(fprintf(manifest,
2426 "-checkpoint_statistics_window_%" PetscInt_FMT
"_name %s\n"
2427 "-checkpoint_statistics_window_%" PetscInt_FMT
"_hash %s\n"
2428 "-checkpoint_statistics_window_%" PetscInt_FMT
"_hash_groups %s\n"
2429 "-checkpoint_statistics_window_%" PetscInt_FMT
"_state %s\n"
2430 "-checkpoint_statistics_window_%" PetscInt_FMT
"_sample_count %" PetscInt_FMT
"\n"
2431 "-checkpoint_statistics_window_%" PetscInt_FMT
"_total_weight %.17g\n"
2432 "-checkpoint_statistics_window_%" PetscInt_FMT
"_represented_time %.17g\n"
2433 "-checkpoint_statistics_window_%" PetscInt_FMT
"_last_accepted_time %.17g\n"
2434 "-checkpoint_statistics_window_%" PetscInt_FMT
"_effective_start %.17g\n"
2435 "-checkpoint_statistics_window_%" PetscInt_FMT
"_effective_end %.17g\n"
2436 "-checkpoint_statistics_window_%" PetscInt_FMT
"_activation_step %" PetscInt_FMT
"\n"
2437 "-checkpoint_statistics_window_%" PetscInt_FMT
"_last_event_step %" PetscInt_FMT
"\n"
2438 "-checkpoint_statistics_window_%" PetscInt_FMT
"_next_time_target %" PetscInt_FMT
"\n"
2439 "-checkpoint_statistics_window_%" PetscInt_FMT
"_restart_count %" PetscInt_FMT
"\n",
2454 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2455 "Unable to write metadata for statistics window '%s'.",
2460 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2464 PetscInt global_size = 0;
2465 char relative_path[PETSC_MAX_PATH_LEN];
2470 PetscCall(VecGetSize(view.
global_vec, &global_size));
2471 PetscCall(PetscSNPrintf(relative_path,
sizeof(relative_path),
2472 "%s/block_%04" PetscInt_FMT
"/%s.dat",
2475 payload_index++, relative_path,
2478 descriptor->
dof,
"PetscScalar", global_size,
2479 "petsc_vec_binary_natural"));
2482 if (simCtx->
np > 0) {
2485 char relative_path[PETSC_MAX_PATH_LEN];
2486 const char *encoding =
"petsc_vec_binary_global";
2491 encoding =
"petsc_vec_binary_scalar_cast";
2493 PetscCall(PetscSNPrintf(relative_path,
sizeof(relative_path),
2497 payload_index++, relative_path,
2506 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2507 if (!user[block].fieldStatisticsStorage)
continue;
2512 PetscInt storage_payloads = 0;
2515 for (PetscInt index = 0; index < storage_payloads; ++index) {
2517 PetscInt global_size = 0;
2518 char relative_path[PETSC_MAX_PATH_LEN];
2519 char qualified_name[PETSC_MAX_PATH_LEN];
2523 PetscCall(VecGetSize(payload.
vec, &global_size));
2525 relative_path,
sizeof(relative_path)));
2529 PetscCall(PetscSNPrintf(qualified_name,
sizeof(qualified_name),
"%s/%s",
2532 payload_index++, relative_path,
2533 payload.
role, qualified_name,
2537 "petsc_vec_binary_natural"));
2542 PetscCheck(fflush(manifest) == 0 && fsync(fileno(manifest)) == 0,
2543 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2544 "Unable to flush checkpoint metadata '%s'.", metadata_path);
2545 PetscCheck(fclose(manifest) == 0, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2546 "Unable to close checkpoint metadata '%s'.", metadata_path);
2549 PetscCallMPI(MPI_Bcast(manifest_digest, 65, MPI_CHAR, 0, PETSC_COMM_WORLD));
2550 PetscFunctionReturn(0);
2557 char checkpoints_root[PETSC_MAX_PATH_LEN];
2558 char final_directory[PETSC_MAX_PATH_LEN];
2559 char temporary_directory[PETSC_MAX_PATH_LEN];
2560 char nested_directory[PETSC_MAX_PATH_LEN];
2561 char commit_path[PETSC_MAX_PATH_LEN];
2562 char geometry_digest[65] =
"";
2563 char manifest_digest[65] =
"";
2564 PetscBool final_exists = PETSC_FALSE;
2565 PetscInt particle_count = 0;
2566 PetscMPIInt writer_pid = 0;
2568 PetscFunctionBeginUser;
2569 PetscCheck(simCtx != NULL && reason != NULL && reason[0] !=
'\0',
2570 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2571 "Simulation context and checkpoint reason are required.");
2573 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
2574 "Finest-level fields must exist before checkpoint output.");
2576 PetscCall(PetscSNPrintf(checkpoints_root,
sizeof(checkpoints_root),
"%s/%s",
2579 final_directory,
sizeof(final_directory)));
2580 PetscCall(PetscTestDirectory(final_directory,
'r', &final_exists));
2582 PetscReal saved_time = 0.0;
2584 &saved_time, NULL, NULL, NULL));
2585 PetscCheck(PetscAbsReal(saved_time - simCtx->
ti) <=
2586 10.0 * PETSC_MACHINE_EPSILON * PetscMax(1.0, PetscAbsReal(simCtx->
ti)),
2587 PETSC_COMM_WORLD, PETSC_ERR_FILE_UNEXPECTED,
2588 "Committed checkpoint step %" PetscInt_FMT
" has time %.17g, current state has time %.17g.",
2589 simCtx->
step, (
double)saved_time, (
double)simCtx->
ti);
2592 PetscFunctionReturn(0);
2595 if (simCtx->
rank == 0) writer_pid = (PetscMPIInt)getpid();
2596 PetscCallMPI(MPI_Bcast(&writer_pid, 1, MPI_INT, 0, PETSC_COMM_WORLD));
2597 PetscCall(PetscSNPrintf(temporary_directory,
sizeof(temporary_directory),
2598 "%s/.step_%0*" PetscInt_FMT
".incomplete.%d",
2600 simCtx->
step, (
int)writer_pid));
2603 PetscCall(PetscSNPrintf(nested_directory,
sizeof(nested_directory),
"%s/%s",
2606 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2607 PetscCall(PetscSNPrintf(nested_directory,
sizeof(nested_directory),
2608 "%s/%s/block_%04" PetscInt_FMT,
2612 if (simCtx->
np > 0) {
2613 PetscCall(PetscSNPrintf(nested_directory,
sizeof(nested_directory),
"%s/%s",
2616 PetscCall(DMSwarmGetSize(user->
swarm, &particle_count));
2620 nested_directory,
sizeof(nested_directory)));
2624 nested_directory,
sizeof(nested_directory)));
2626 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2628 nested_directory,
sizeof(nested_directory)));
2635 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2639 for (PetscInt block = 0; block < simCtx->
block_number; ++block) {
2642 PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
2645 geometry_digest, particle_count, manifest_digest));
2646 if (simCtx->
rank == 0) {
2647 FILE *commit_file = NULL;
2649 PetscCall(PetscSNPrintf(commit_path,
sizeof(commit_path),
"%s/COMMITTED", temporary_directory));
2650 commit_file = fopen(commit_path,
"w");
2651 PetscCheck(commit_file != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
2652 "Unable to create checkpoint commit marker '%s'.", commit_path);
2653 PetscCheck(fprintf(commit_file,
"%s\n", manifest_digest) > 0 &&
2654 fflush(commit_file) == 0 && fsync(fileno(commit_file)) == 0,
2655 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2656 "Unable to write checkpoint commit marker '%s'.", commit_path);
2657 PetscCheck(fclose(commit_file) == 0, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2658 "Unable to close checkpoint commit marker '%s'.", commit_path);
2659 PetscCheck(rename(temporary_directory, final_directory) == 0,
2660 PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
2661 "Unable to commit checkpoint '%s': %s", final_directory, strerror(errno));
2663 PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
2665 "Committed checkpoint step %d at t=%.17g (%s): %s\n",
2666 simCtx->
step, (
double)simCtx->
ti, reason, final_directory);
2667 PetscFunctionReturn(0);
2678 Vec sequential_vec = NULL;
2680 PetscFunctionBeginUser;
2681 PetscCheck(inVec != NULL && N != NULL && arrayOut != NULL,
2682 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2683 "Vector, size output, and array output are required.");
2684 PetscCall(PetscObjectGetComm((PetscObject)inVec, &comm));
2685 PetscCallMPI(MPI_Comm_rank(comm, &rank));
2686 PetscCall(VecGetSize(inVec, N));
2691 const PetscScalar *values = NULL;
2692 PetscInt local_size = 0;
2694 PetscCall(VecGetLocalSize(sequential_vec, &local_size));
2695 PetscCall(PetscMalloc1(local_size, arrayOut));
2696 PetscCall(VecGetArrayRead(sequential_vec, &values));
2697 for (PetscInt index = 0; index < local_size; ++index) {
2698 (*arrayOut)[index] = (double)PetscRealPart(values[index]);
2700 PetscCall(VecRestoreArrayRead(sequential_vec, &values));
2702 PetscCall(VecDestroy(&sequential_vec));
2703 PetscFunctionReturn(0);
2711 PetscInt *n_total_particles, PetscInt *n_components,
2712 PetscDataType *field_type_out,
void **gathered_array)
2714 PetscErrorCode ierr;
2715 PetscMPIInt rank, size;
2716 PetscInt nlocal, nglobal, bs;
2717 PetscDataType field_type;
2718 void *local_array_void;
2719 size_t element_size = 0;
2721 PetscFunctionBeginUser;
2723 PetscCheck(swarm != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"DMSwarm cannot be NULL.");
2724 PetscCheck(field_name != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Swarm field name cannot be NULL.");
2725 PetscCheck(n_total_particles != NULL && n_components != NULL && field_type_out != NULL && gathered_array != NULL,
2726 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
2727 "Swarm gather output pointers cannot be NULL.");
2729 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2730 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
2733 ierr = DMSwarmGetLocalSize(swarm, &nlocal); CHKERRQ(ierr);
2734 ierr = DMSwarmGetSize(swarm, &nglobal); CHKERRQ(ierr);
2735 ierr = DMSwarmGetField(swarm, field_name, &bs, &field_type, &local_array_void); CHKERRQ(ierr);
2738 if (field_type == PETSC_INT64) element_size =
sizeof(PetscInt64);
2739 else if (field_type == PETSC_INT) element_size =
sizeof(PetscInt);
2740 else if (field_type == PETSC_REAL) element_size =
sizeof(PetscReal);
2741#if defined(PETSC_USE_COMPLEX)
2742 else if (field_type == PETSC_SCALAR) element_size =
sizeof(PetscScalar);
2744 else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
2745 "Swarm field '%s' uses unsupported gathered data type %s.",
2746 field_name, PetscDataTypes[field_type]);
2748 *field_type_out = field_type;
2749 *n_total_particles = nglobal;
2751 *gathered_array = NULL;
2755 ierr = PetscMalloc(nglobal * bs * element_size, gathered_array); CHKERRQ(ierr);
2756 ierr = PetscMemcpy(*gathered_array, local_array_void, nglobal * bs * element_size); CHKERRQ(ierr);
2759 PetscInt *recvcounts = NULL, *displs = NULL;
2761 ierr = PetscMalloc1(size, &recvcounts); CHKERRQ(ierr);
2762 ierr = PetscMalloc1(size, &displs); CHKERRQ(ierr);
2764 PetscInt sendcount = nlocal * bs;
2767 ierr = MPI_Gather(&sendcount, 1, MPIU_INT, recvcounts, 1, MPIU_INT, 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
2772 for (PetscMPIInt i = 0; i < size; i++) recvcounts[i] *= element_size;
2773 for (PetscMPIInt i = 1; i < size; i++) displs[i] = displs[i-1] + recvcounts[i-1];
2775 ierr = PetscMalloc(nglobal * bs * element_size, gathered_array); CHKERRQ(ierr);
2779 ierr = MPI_Gatherv(local_array_void, nlocal * bs * element_size, MPI_BYTE,
2780 *gathered_array, recvcounts, displs, MPI_BYTE,
2781 0, PETSC_COMM_WORLD); CHKERRQ(ierr);
2784 ierr = PetscFree(recvcounts); CHKERRQ(ierr);
2785 ierr = PetscFree(displs); CHKERRQ(ierr);
2789 ierr = DMSwarmRestoreField(swarm, field_name, &bs, NULL, &local_array_void); CHKERRQ(ierr);
2791 PetscFunctionReturn(0);
2802 PetscErrorCode ierr;
2804 Cmpnts global_min_coords, global_max_coords;
2805 PetscReal StartTime;
2806 PetscInt StartStep,StepsToRun,total_num_particles;
2807 PetscMPIInt num_mpi_procs;
2808 const char *log_level_name;
2809 const char *convergence_mode_name;
2813 num_mpi_procs = simCtx->
size;
2817 total_num_particles = simCtx->
np;
2821 PetscFunctionBeginUser;
2823 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"DisplayBanner - UserCtx pointer is NULL.");
2825 case LOG_ERROR: log_level_name =
"ERROR";
break;
2826 case LOG_WARNING: log_level_name =
"WARNING";
break;
2827 case LOG_INFO: log_level_name =
"INFO";
break;
2828 case LOG_DEBUG: log_level_name =
"DEBUG";
break;
2829 case LOG_TRACE: log_level_name =
"TRACE";
break;
2830 case LOG_VERBOSE: log_level_name =
"VERBOSE";
break;
2831 default: log_level_name =
"UNKNOWN";
break;
2838 default: convergence_mode_name =
"UNKNOWN";
break;
2842 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2847 if (bboxlist_on_rank0 && num_mpi_procs > 0) {
2848 global_min_coords = bboxlist_on_rank0[0].
min_coords;
2849 global_max_coords = bboxlist_on_rank0[0].
max_coords;
2850 for (PetscMPIInt p = 1; p < num_mpi_procs; ++p) {
2851 global_min_coords.
x = PetscMin(global_min_coords.
x, bboxlist_on_rank0[p].
min_coords.
x);
2852 global_min_coords.
y = PetscMin(global_min_coords.
y, bboxlist_on_rank0[p].
min_coords.
y);
2853 global_min_coords.
z = PetscMin(global_min_coords.
z, bboxlist_on_rank0[p].
min_coords.
z);
2854 global_max_coords.
x = PetscMax(global_max_coords.
x, bboxlist_on_rank0[p].
max_coords.
x);
2855 global_max_coords.
y = PetscMax(global_max_coords.
y, bboxlist_on_rank0[p].
max_coords.
y);
2856 global_max_coords.
z = PetscMax(global_max_coords.
z, bboxlist_on_rank0[p].
max_coords.
z);
2863 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"(Rank 0) - bboxlist not provided or num_mpi_procs <=0; using user->bbox for domain bounds.\n");
2868 ierr = PetscPrintf(PETSC_COMM_SELF,
"\n"); CHKERRQ(ierr);
2869 ierr = PetscPrintf(PETSC_COMM_SELF,
"=============================================================\n"); CHKERRQ(ierr);
2870 ierr = PetscPrintf(PETSC_COMM_SELF,
" CASE SUMMARY \n"); CHKERRQ(ierr);
2871 ierr = PetscPrintf(PETSC_COMM_SELF,
"=============================================================\n"); CHKERRQ(ierr);
2872 ierr = PetscPrintf(PETSC_COMM_SELF,
" Grid Points : %d X %d X %d\n", user->
IM, user->
JM, user->
KM); CHKERRQ(ierr);
2873 ierr = PetscPrintf(PETSC_COMM_SELF,
" Cells : %d X %d X %d\n", user->
IM - 1, user->
JM - 1, user->
KM - 1); CHKERRQ(ierr);
2874 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);
2875 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);
2876 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);
2877 ierr = PetscPrintf(PETSC_COMM_SELF,
" Periodic Axes (BC-derived) : I=%s, J=%s, K=%s\n",
2880 simCtx->
k_periodic ?
"YES" :
"NO"); CHKERRQ(ierr);
2881 for (PetscInt axis = 0; axis < 3; axis++) {
2883 ierr = PetscPrintf(PETSC_COMM_SELF,
2884 " Periodic %c Translation : (%.6e, %.6e, %.6e)\n",
2890 if (total_num_particles > 0 &&
2892 ierr = PetscPrintf(PETSC_COMM_SELF,
2893 " Particle Periodic Wrapping : UNSUPPORTED (Eulerian periodicity only)\n"); CHKERRQ(ierr);
2896 ierr = PetscPrintf(PETSC_COMM_SELF,
"-------------------- Boundary Conditions --------------------\n"); CHKERRQ(ierr);
2897 const int face_name_width = 17;
2898 for (PetscInt i_face = 0; i_face < 6; ++i_face) {
2906 Cmpnts inlet_velocity = {0.0,0.0,0.0};
2911 ierr = PetscPrintf(PETSC_COMM_SELF,
" Face %-*s : %s - %s - [%.4f,%.4f,%.4f]\n",
2912 face_name_width, face_str, bc_type_str, bc_handler_type_str,inlet_velocity.
x,inlet_velocity.
y,inlet_velocity.
z); CHKERRQ(ierr);
2914 PetscReal v_max = 0.0;
2917 ierr = PetscPrintf(PETSC_COMM_SELF,
" Face %-*s : %s - %s - v_max=%.4f\n",
2918 face_name_width, face_str, bc_type_str, bc_handler_type_str, v_max); CHKERRQ(ierr);
2920 const char *source_file =
"(missing)";
2922 if (strcasecmp(param->key,
"source_file") == 0 && param->value) {
2923 source_file = param->value;
2927 ierr = PetscPrintf(PETSC_COMM_SELF,
" Face %-*s : %s - %s - source_file=%s\n",
2928 face_name_width, face_str, bc_type_str, bc_handler_type_str, source_file); CHKERRQ(ierr);
2931 PetscBool trimflag,foundtrimflag;
2933 ierr = PetscPrintf(PETSC_COMM_SELF,
" Face %-*s : %s - %s - [from initial state] - %s\n",
2934 face_name_width, face_str, bc_type_str, bc_handler_type_str,trimflag?
"Enforce seam flux":
"Seam flux not enforced"); CHKERRQ(ierr);
2937 PetscBool trimflag,foundflux,foundtrimflag;
2940 ierr = PetscPrintf(PETSC_COMM_SELF,
" Face %-*s : %s - %s - [%.4f] - %s\n",
2941 face_name_width, face_str, bc_type_str, bc_handler_type_str,flux,trimflag?
"Enforce seam flux":
"Seam flux not enforced"); CHKERRQ(ierr);
2943 ierr = PetscPrintf(PETSC_COMM_SELF,
" Face %-*s : %s - %s\n",
2944 face_name_width, face_str, bc_type_str,bc_handler_type_str); CHKERRQ(ierr);
2948 ierr = PetscPrintf(PETSC_COMM_SELF,
"-------------------------------------------------------------\n"); CHKERRQ(ierr);
2949 ierr = PetscPrintf(PETSC_COMM_SELF,
" Run Mode : %s\n", simCtx->
OnlySetup ?
"SETUP ONLY" :
"Full Simulation"); CHKERRQ(ierr);
2950 ierr = PetscPrintf(PETSC_COMM_SELF,
" Start Time : %.4f\n", (
double)StartTime); CHKERRQ(ierr);
2951 ierr = PetscPrintf(PETSC_COMM_SELF,
" Timestep Size : %.4f\n", (
double)simCtx->
dt); CHKERRQ(ierr);
2952 ierr = PetscPrintf(PETSC_COMM_SELF,
" Starting Step : %d\n", StartStep); CHKERRQ(ierr);
2953 ierr = PetscPrintf(PETSC_COMM_SELF,
" Total Steps to Run : %d\n", StepsToRun); CHKERRQ(ierr);
2954 ierr = PetscPrintf(PETSC_COMM_SELF,
" Ending Step : %d\n", StartStep + StepsToRun); CHKERRQ(ierr);
2955 if (simCtx->
tiout > 0) {
2956 ierr = PetscPrintf(PETSC_COMM_SELF,
" Field/Restart Cadence : every %d step(s)\n", simCtx->
tiout); CHKERRQ(ierr);
2958 ierr = PetscPrintf(PETSC_COMM_SELF,
" Field/Restart Cadence : DISABLED\n"); CHKERRQ(ierr);
2963 ierr = PetscPrintf(PETSC_COMM_SELF,
" Statistics Console Cadence : every %d step(s), %d window(s)\n",
2966 ierr = PetscPrintf(PETSC_COMM_SELF,
" Statistics Console Cadence : DISABLED (%d window(s) accumulating)\n",
2969 ierr = PetscPrintf(PETSC_COMM_SELF,
" Statistics Console Cadence : DISABLED (no window configured)\n"); CHKERRQ(ierr);
2971 ierr = PetscPrintf(PETSC_COMM_SELF,
" Immersed Boundary : %s\n", simCtx->
immersed ?
"ENABLED" :
"DISABLED"); CHKERRQ(ierr);
2975 " Runtime Walltime Guard : %s (warmup=%d, multiplier=%.2f, min=%.1f s, alpha=%.2f)\n",
2983 ierr = PetscPrintf(PETSC_COMM_SELF,
" Runtime Walltime Guard : DISABLED\n"); CHKERRQ(ierr);
2985 ierr = PetscPrintf(PETSC_COMM_SELF,
" Console Log Level : %s\n", log_level_name); CHKERRQ(ierr);
2986 ierr = PetscPrintf(PETSC_COMM_SELF,
" Profiling Timestep Output : %s\n", simCtx->
profilingTimestepMode); CHKERRQ(ierr);
2987 ierr = PetscPrintf(PETSC_COMM_SELF,
" Profiling Final Summary : %s\n", simCtx->
profilingFinalSummary ?
"ENABLED" :
"DISABLED"); CHKERRQ(ierr);
2989 ierr = PetscPrintf(PETSC_COMM_SELF,
" Runtime Memory Log : ENABLED (%s)\n", simCtx->
runtimeMemoryLogFile); CHKERRQ(ierr);
2991 ierr = PetscPrintf(PETSC_COMM_SELF,
" Runtime Memory Log : DISABLED\n"); CHKERRQ(ierr);
2993 ierr = PetscPrintf(PETSC_COMM_SELF,
" Solution Convergence Log : %s\n",
2995 ierr = PetscPrintf(PETSC_COMM_SELF,
" Number of MPI Processes : %d\n", num_mpi_procs); CHKERRQ(ierr);
2996 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Number of Particles : %d\n", total_num_particles); CHKERRQ(ierr);
2997 if (simCtx->
np > 0) {
3001 ierr = PetscPrintf(PETSC_COMM_SELF,
" Particle Console Cadence : every %d step(s)\n", simCtx->
particleConsoleOutputFreq); CHKERRQ(ierr);
3003 ierr = PetscPrintf(PETSC_COMM_SELF,
" Particle Console Cadence : DISABLED\n"); CHKERRQ(ierr);
3005 ierr = PetscPrintf(PETSC_COMM_SELF,
" Particle Log Row Sampling : every %d particle(s)\n", simCtx->
LoggingFrequency); CHKERRQ(ierr);
3007 ierr = PetscPrintf(PETSC_COMM_SELF,
" Particle Restart Mode : %s\n", simCtx->
particleRestartMode); CHKERRQ(ierr);
3009 ierr = PetscPrintf(PETSC_COMM_SELF,
" Particle Initialization Mode: %s\n", particle_init_str); CHKERRQ(ierr);
3010 ierr = PetscPrintf(PETSC_COMM_SELF,
" Interpolation Method : %s\n",
3017 ierr = PetscPrintf(PETSC_COMM_SELF,
" Particles Initialized At : --- (No INLET face identified)\n"); CHKERRQ(ierr);
3022 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Reynolds Number : %le\n", simCtx->
ren); CHKERRQ(ierr);
3028 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Initial Pseudo-CFL (Courant): %le\n", simCtx->
pseudo_cfl); CHKERRQ(ierr);
3029 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Pseudo-CFL Range : [%le, %le]\n", simCtx->
min_pseudo_cfl, simCtx->
max_pseudo_cfl); CHKERRQ(ierr);
3030 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Pseudo-CFL Adaptation : growth=%le, reduction=%le, backtrack=%s\n",
3033 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Pseudo-Time Iteration Limit : %d\n", simCtx->
mom_max_pseudo_steps); CHKERRQ(ierr);
3035 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Newton-Krylov PETSc Controls: SNES/KSP options (mom_nk_*)\n"); CHKERRQ(ierr);
3036 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Newton-Krylov History Log : %s\n", simCtx->
mom_nk_monitor_history ?
"ENABLED" :
"DISABLED"); CHKERRQ(ierr);
3038 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Pseudo-Time Controller : NOT APPLICABLE\n"); CHKERRQ(ierr);
3040 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Solution Convergence Mode : %s\n", convergence_mode_name); CHKERRQ(ierr);
3046 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Large Eddy Simulation Model : %s\n",
LESModelToString(simCtx->
les)); CHKERRQ(ierr);
3053 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Filter Width : per direction (cell edges; filter_width unused)\n"); CHKERRQ(ierr);
3055 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Filter Width : %s\n",
3059 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Vreman Coefficient : %.4f (no coefficient field)\n",
3061 }
else if (simCtx->
les ==
WALE) {
3062 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES WALE Coefficient : %.4f (no coefficient field)\n",
3065 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Smagorinsky Constant : %.4f (no coefficient field)\n",
3068 char directions[8] =
"";
3074 directions[used] =
'\0';
3076 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Test Filter : %s (width ratio %.3f)\n",
3079 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Dynamic Update Cadence : every %d step(s)\n",
3084 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Coefficient Averaging : %s%s%s\n",
3086 used > 0 ?
" over " :
"",
3087 used > 0 ? directions :
""); CHKERRQ(ierr);
3089 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Coefficient Limiting : clamp (max Cs %.3f)\n",
3090 (
double)les->
max_cs); CHKERRQ(ierr);
3092 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Coefficient Limiting : %s\n",
3095 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Total Viscosity Floor : %.3f x molecular\n",
3098 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Gradient (Clark) Term : %s\n",
3101 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Coefficient Diagnostics : ENABLED (les_coefficient.csv, every %d step(s))\n",
3105 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Yoshizawa Coefficient : %.4f (subgrid energy estimate)\n",
3108 ierr = PetscPrintf(PETSC_COMM_WORLD,
" LES Coefficient Diagnostics : DISABLED\n"); CHKERRQ(ierr);
3117 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Wall Function Model : %s (roughness height %.3e)\n",
3121 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Wall Function Model : %s (smooth wall; no roughness term)\n",
3125 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Wall Function Model : DISABLED\n"); CHKERRQ(ierr);
3129 ierr = PetscPrintf(PETSC_COMM_SELF,
" Eulerian State Source : load (%s)\n",
3132 ierr = PetscPrintf(PETSC_COMM_SELF,
" Eulerian State Source : restart step %d (%s)\n",
3136 ierr = PetscPrintf(PETSC_COMM_SELF,
" Eulerian State Source : initial condition (%s)\n",
3137 field_init_str); CHKERRQ(ierr);
3141 ierr = PetscPrintf(PETSC_COMM_SELF,
3142 " Constant Velocity (Cart.) : x=%.4f y=%.4f z=%.4f\n",
3148 ierr = PetscPrintf(PETSC_COMM_SELF,
3149 " Constant Velocity (Curv.) : speed=%.4f direction=%s\n",
3154 ierr = PetscPrintf(PETSC_COMM_SELF,
3155 " Poiseuille Peak Velocity : speed=%.4f direction=%s\n",
3160 ierr = PetscPrintf(PETSC_COMM_SELF,
3161 " Initial Velocity File : field=%s directory=%s\n",
3166 ierr = PetscPrintf(PETSC_COMM_WORLD,
" Analytical Solution Type : %s\n", simCtx->
AnalyticalSolutionType); CHKERRQ(ierr);
3168 ierr = PetscPrintf(PETSC_COMM_SELF,
"=============================================================\n"); CHKERRQ(ierr);
3169 ierr = PetscPrintf(PETSC_COMM_SELF,
"\n"); CHKERRQ(ierr);
3171 PetscFunctionReturn(0);
3175#define __FUNCT__ "PicurvPhysicalTime"
3180 PetscReal scale = 1.0;
3182 PetscFunctionBeginUser;
3183 PetscCheck(simCtx && physical, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
3184 "Context and physical-time output are required.");
3186 *physical = solver_time * scale;
3187 PetscFunctionReturn(0);
3191#define __FUNCT__ "PicurvFieldReferenceScale"
3198 PetscReal *scale,
char *description,
3199 size_t description_length)
3204 PetscBool found = PETSC_FALSE;
3206 PetscFunctionBeginUser;
3207 PetscCheck(simCtx && field_name && scale, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
3208 "Context, field name, and output scale are required.");
3221 PetscCheck(found, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE,
3222 "Field '%s' is in neither the Eulerian nor the particle field catalog.", field_name);
3227 "Field '%s' has no fixed physical dimension, so it has no reference scale.", field_name);
3229 if (description && description_length) {
3232 PetscFunctionReturn(0);
3244 PetscBool startTimeSet, endTimeSet, timeStepSet;
3246 PetscFunctionBeginUser;
3249 if (!simCtx || !simCtx->
pps) {
3250 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_NULL,
"SimCtx or its pps member is NULL in ParsePostProcessingSettings.");
3287 file = fopen(configFile,
"r");
3290 while (fgets(line,
sizeof(line), file)) {
3291 char *key, *value, *comment;
3292 comment = strchr(line,
'#');
if (comment) *comment =
'\0';
3294 key = strtok(line,
"="); value = strtok(NULL,
"=");
3297 if (strcmp(key,
"startTime") == 0) pps->
startTime = atoi(value);
3298 else if (strcmp(key,
"endTime") == 0) pps->
endTime = atoi(value);
3299 else if (strcmp(key,
"timeStep") == 0) pps->
timeStep = atoi(value);
3300 else if (strcmp(key,
"step_list_file") == 0) {
3304 else if (strcmp(key,
"output_particles") == 0) {
3305 if (strcasecmp(value,
"true") == 0) pps->
outputParticles = PETSC_TRUE;
3307 else if (strcasecmp(key,
"process_pipeline") == 0) {
3310 }
else if (strcasecmp(key,
"field_statistics_windows") == 0) {
3313 }
else if (strcasecmp(key,
"field_statistics_formats") == 0) {
3316 }
else if (strcasecmp(key,
"field_statistics_outputs") == 0) {
3319 }
else if (strcasecmp(key,
"field_statistics_source_step") == 0) {
3321 }
else if (strcasecmp(key,
"dimensionalize") == 0) {
3323 || strcmp(value,
"1") == 0);
3324 }
else if (strcasecmp(key,
"field_statistics_output_prefix") == 0) {
3329 }
else if (strcasecmp(key,
"output_fields_instantaneous") == 0) {
3332 }
else if (strcasecmp(key,
"output_prefix") == 0) {
3335 }
else if (strcasecmp(key,
"particle_output_prefix") == 0) {
3338 }
else if (strcasecmp(key,
"particle_fields_instantaneous") == 0) {
3341 }
else if (strcasecmp(key,
"particle_pipeline") == 0) {
3344 }
else if (strcasecmp(key,
"particle_output_freq") == 0) {
3346 }
else if (strcasecmp(key,
"statistics_pipeline") == 0) {
3349 }
else if (strcasecmp(key,
"statistics_output_prefix") == 0) {
3352 }
else if (strcasecmp(key,
"particleExt") == 0) {
3355 }
else if (strcasecmp(key,
"eulerianExt") == 0) {
3358 }
else if (strcmp(key,
"reference_ip") == 0) {pps->
reference[0] = atoi(value);
3359 }
else if (strcmp(key,
"reference_jp") == 0) {pps->
reference[1] = atoi(value);
3360 }
else if (strcmp(key,
"reference_kp") == 0) {pps->
reference[2] = atoi(value);
3361 }
else if (strcasecmp(key,
"source_directory") == 0) {
3364 }
else if (strcasecmp(key,
"spectra_signature") == 0) {
3378 LOG_ALLOW(
GLOBAL,
LOG_WARNING,
"Could not open post-processing config file '%s'. Using defaults and command-line overrides.\n", configFile);
3382 PetscOptionsGetInt(NULL, NULL,
"-startTime", &pps->
startTime, &startTimeSet);
3383 PetscOptionsGetInt(NULL, NULL,
"-endTime", &pps->
endTime, &endTimeSet);
3384 PetscCall(PetscOptionsGetInt(NULL, NULL,
"-timeStep", &pps->
timeStep, &timeStepSet));
3385 PetscCheck(pps->
timeStep > 0, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
3386 "Post-processing timeStep must be positive (got %" PetscInt_FMT
"). "
3387 "For one checkpoint, set startTime=endTime and timeStep=1.", pps->
timeStep);
3388 PetscOptionsGetBool(NULL, NULL,
"-output_particles", &pps->
outputParticles, NULL);
3395 if (startTimeSet && !endTimeSet) {
3399 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Post-processing configured to run from t=%d to t=%d with step %d. Particle output: %s.\n",
3412 PetscFunctionReturn(0);
3416#define __FUNCT__ "ParsePostProcessingSettings"
3418#define __FUNCT__ "ParseScalingInformation"
3427 PetscErrorCode ierr;
3430 PetscFunctionBeginUser;
3433 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"SimCtx is NULL in ParseScalingInformation");
3442 ierr = PetscOptionsGetReal(NULL, NULL,
"-scaling_L_ref", &simCtx->
scaling.
L_ref, &flg); CHKERRQ(ierr);
3443 ierr = PetscOptionsGetReal(NULL, NULL,
"-scaling_U_ref", &simCtx->
scaling.
U_ref, &flg); CHKERRQ(ierr);
3444 ierr = PetscOptionsGetReal(NULL, NULL,
"-scaling_rho_ref", &simCtx->
scaling.
rho_ref, &flg); CHKERRQ(ierr);
3449 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
"Reference velocity U_ref must be positive. Got %g", (
double)simCtx->
scaling.
U_ref);
3454 LOG(
GLOBAL,
LOG_INFO,
"---------------- Physical Scales Initialized -----------------\n");
3455 LOG(
GLOBAL,
LOG_INFO,
" L_ref: %.4f, U_ref: %.4f, rho_ref: %.4f, P_ref: %.4f\n",
3457 LOG(
GLOBAL,
LOG_INFO,
"--------------------------------------------------------------\n");
3460 PetscFunctionReturn(0);
3475 PetscMPIInt rank, size;
3476 PetscErrorCode ierr;
3479 double *array = NULL;
3480 PetscInt fileExistsFlag = 0;
3483 "Start reading from file: %s\n",
3487 if (!filename || !data_out || !Nout) {
3489 "Null pointer argument provided.\n");
3494 MPI_Comm_rank(comm, &rank);
3495 MPI_Comm_size(comm, &size);
3499 fp = fopen(filename,
"r");
3508 ierr = MPI_Bcast(&fileExistsFlag, 1, MPI_INT, 0, comm); CHKERRQ(ierr);
3510 if (!fileExistsFlag) {
3514 "File '%s' not found.\n",
3522 fp = fopen(filename,
"r");
3525 "File '%s' could not be opened for reading.\n",
3533 while (fgets(line,
sizeof(line), fp)) {
3539 "File '%s' has %d lines.\n",
3543 array = (
double*)malloc(N *
sizeof(
double));
3547 "malloc failed for array.\n");
3556 while (fgets(line,
sizeof(line), fp)) {
3558 if (sscanf(line,
"%lf", &val) == 1) {
3566 "Successfully read %d values from '%s'.\n",
3571 ierr = MPI_Bcast(&N, 1, MPI_INT, 0, comm); CHKERRQ(ierr);
3575 array = (
double*)malloc(N *
sizeof(
double));
3578 "malloc failed on rank %d.\n",
3585 ierr = MPI_Bcast(array, N, MPI_DOUBLE, 0, comm); CHKERRQ(ierr);
3592 "Done. Provided array of length=%d to all ranks.\n",
3603 double **coordsArray,
3606 PetscFunctionBeginUser;
3608 PetscErrorCode ierr;
3612 ierr = VecCreate(PETSC_COMM_WORLD, &coordsVec);CHKERRQ(ierr);
3613 ierr = VecSetFromOptions(coordsVec);CHKERRQ(ierr);
3619 "Error reading position data (ti=%d).\n",
3621 PetscFunctionReturn(ierr);
3627 ierr = VecDestroy(&coordsVec);CHKERRQ(ierr);
3630 "Successfully gathered coordinates. Ncoords=%d.\n", *Ncoords);
3631 PetscFunctionReturn(0);
3640 const char *fieldName,
3642 double **scalarArray,
3645 PetscFunctionBeginUser;
3647 PetscErrorCode ierr;
3651 ierr = VecCreate(PETSC_COMM_WORLD, &fieldVec);CHKERRQ(ierr);
3652 ierr = VecSetFromOptions(fieldVec);CHKERRQ(ierr);
3657 "Error reading field '%s' (ti=%d).\n",
3658 fieldName, timeIndex);
3659 PetscFunctionReturn(ierr);
3665 ierr = VecDestroy(&fieldVec);CHKERRQ(ierr);
3668 "Successfully gathered field '%s'. Nscalars=%d.\n",
3669 fieldName, *Nscalars);
3670 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_DIMENSION_FIXED
The exponents are the field's dimension.
PetscErrorCode FieldDimensionReferenceScale(const ScalingCtx *scaling, FieldDimension dimension, PetscReal *scale)
Return the factor that turns a solver value of one dimension into physical units.
@ FIELD_CAPABILITY_CHECKPOINT
@ FIELD_AVAILABILITY_WALL_MODEL
@ FIELD_AVAILABILITY_PARTICLES
@ FIELD_AVAILABILITY_TURBULENCE
@ FIELD_AVAILABILITY_LES_DYNAMIC
@ 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.
PetscErrorCode FieldTryIdFromName(const char *field_name, FieldId *field_id, PetscBool *found)
Look a name up without treating an unknown name as an error.
const char * canonical_name
const char * FieldLayoutName(FieldLayout layout)
Return a stable printable label for a field layout.
PetscErrorCode FieldDimensionLabel(FieldDimension dimension, char *label, size_t length)
Write a printable form of a dimension, such as L^2 U or dimensionless.
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.
Physical dimension as exponents of the reference length, velocity, and density.
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.
#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().
PetscErrorCode PicurvFieldReferenceScale(SimCtx *simCtx, const char *field_name, PetscReal *scale, char *description, size_t description_length)
Implementation of PicurvFieldReferenceScale().
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().
PetscBool CheckpointFieldIsEnabled(const SimCtx *simCtx, const FieldDescriptor *descriptor)
Implementation of CheckpointFieldIsEnabled().
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().
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)
Validate a committed bundle and return selected authoritative metadata.
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().
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)
PetscErrorCode PicurvPhysicalTime(const SimCtx *simCtx, PetscReal solver_time, PetscReal *physical)
Implementation of PicurvPhysicalTime().
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 * LESTestFilterKernelToString(LESTestFilterKernel kernel)
Returns the user-facing name of an LES test-filter kernel.
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.
const char * WallFunctionModelToString(WallFunctionModel model)
Returns the user-facing name of a wall-function model.
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
const char * LESFilterWidthModelToString(LESFilterWidthModel model)
Returns the user-facing name of an LES grid-filter-width model.
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 * LESAveragingModeToString(LESAveragingMode mode)
Returns the user-facing name of an LES coefficient-averaging mode.
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 * LESClipModeToString(LESClipMode mode)
Returns the user-facing name of an LES coefficient-limiting mode.
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
@ PARTICLE_FIELD_ID_INVALID
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
PetscErrorCode ParticleFieldTryIdFromName(const char *field_name, ParticleFieldId *field_id, PetscBool *found)
Look a name up without treating an unknown name as an error.
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.
PetscReal yoshizawa_ci
Yoshizawa constant for the reported SGS kinetic energy.
PetscBool inletFaceDefined
PetscBool profilingFinalSummary
char particle_output_prefix[256]
PetscInt dynamic_frequency
Recompute the dynamic coefficient every N steps.
BoundaryFaceConfig boundary_faces[6]
LESFilterWidthModel filter_width_model
How the grid filter width Delta is derived per cell.
PetscInt statisticsConsoleOutputFreq
#define PICURV_BUILD_DIRTY
BCFace identifiedInletBCFace
PetscReal targetVolumetricFlux
PetscBool walltimeGuardActive
LESTestFilterKernel test_filter_kernel
Discrete test-filter stencil.
LESConfig les_config
Parameters of the LES closure selected by les.
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.
PetscBool dimensionalize
Whether derived output leaves non-dimensional form, from global_operations.dimensionalize.
char field_statistics_output_prefix[PETSC_MAX_PATH_LEN]
Analysis prefix for CSV summaries; VTK continues to use output_prefix.
#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 step_list_file[PETSC_MAX_PATH_LEN]
File listing the exact steps to process, one per line; empty uses the time controls.
char output_dir[PETSC_MAX_PATH_LEN]
PetscBool solutionConvergenceEnabled
char runtimeMemoryLogFile[PETSC_MAX_PATH_LEN]
File name written under log_dir.
char profilingTimestepMode[32]
WallFunctionModel
Selects the wall model applied on WALL faces.
PetscReal max_cs
Ceiling on Cs under LES_CLIP_CLAMP.
LESClipMode clip_mode
Admissible range for the coefficient.
PetscBool no_pseudo_cfl_backtrack
#define PICURV_GIT_COMMIT
#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
PetscBool averaging_direction[3]
Averaged-over logical directions (xi, eta, zeta).
PetscReal wale_coefficient
Model constant C_w for WALE (Nicoud & Ducros 1999).
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]
PetscInt les_gradient_model
Add the Clark gradient (tensor-diffusivity) term to the viscous flux.
char particle_pipeline[1024]
char eulerianSource[PETSC_MAX_PATH_LEN]
PetscBool walltimeGuardEnabled
PetscBool checkpointGeometryHashReady
PetscReal wall_roughness_height
PetscInt walltimeGuardWarmupSteps
ParticleInitializationType ParticleInitialization
PetscInt diagnostics_cadence
Steps between diagnostic rows.
PetscReal min_viscosity_ratio
Enforce nu + nu_t >= ratio * nu.
PetscInt wallfunction
Enable wall functions on WALL faces.
PetscBool diagnostics_enabled
Append per-step coefficient statistics to the run log directory.
PetscReal constant_cs
Fixed Cs for CONSTANT_SMAGORINSKY; unused by the dynamic model.
PetscInt solutionConvergenceWindowSteps
char process_pipeline[1024]
PetscInt particle_output_freq
PetscReal test_filter_width_ratio
Test-to-grid ratio per filtered direction; alpha is its square for the box, ratio^(4/3) for Simpson.
char particle_fields[1024]
PetscReal pseudo_cfl_growth_factor
PetscBool outputParticles
char initialConditionDirectory[PETSC_MAX_PATH_LEN]
LESAveragingMode averaging_mode
Averaging set for the Germano contractions.
struct PicurvWindowStorage * fieldStatisticsStorage
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
@ IC_MODE_CONSTANT_CARTESIAN
@ IC_MODE_CONSTANT_STREAMWISE
PetscInt particleConsoleOutputFreq
Cmpnts InitialConstantContra
char checkpointGeometrySHA256[65]
PetscReal vreman_coefficient
Model constant c for VREMAN (Vreman 2004: 2.5 Cs^2).
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
PetscInt les
Active LES closure; an LESModelType value.
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
#define PICURV_RELEASE_VERSION
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.
Every user-selectable parameter of the LES closure.
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.