24static PetscErrorCode
AssertFileContains(
const char *path,
const char *needle,
const char *context)
30 PetscFunctionBeginUser;
31 fp = fopen(path,
"rb");
33 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to open '%s' for assertion.", path);
35 if (fseek(fp, 0, SEEK_END) != 0) {
37 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to seek '%s'.", path);
39 file_size = ftell(fp);
42 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to measure '%s'.", path);
44 if (fseek(fp, 0, SEEK_SET) != 0) {
46 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to rewind '%s'.", path);
49 PetscCall(PetscMalloc1((
size_t)file_size + 1, &buffer));
51 size_t bytes_read = fread(buffer, 1, (
size_t)file_size, fp);
52 if (bytes_read != (
size_t)file_size) {
54 PetscCall(PetscFree(buffer));
55 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to read '%s'.", path);
58 buffer[file_size] =
'\0';
61 PetscCall(
PicurvAssertBool((PetscBool)(strstr(buffer, needle) != NULL), context));
62 PetscCall(PetscFree(buffer));
63 PetscFunctionReturn(0);
75 PetscFunctionBeginUser;
76 fp = fopen(path,
"rb");
78 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to open '%s' for assertion.", path);
80 if (fseek(fp, 0, SEEK_END) != 0) {
82 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to seek '%s'.", path);
84 file_size = ftell(fp);
87 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to measure '%s'.", path);
89 if (fseek(fp, 0, SEEK_SET) != 0) {
91 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to rewind '%s'.", path);
94 PetscCall(PetscMalloc1((
size_t)file_size + 1, &buffer));
96 size_t bytes_read = fread(buffer, 1, (
size_t)file_size, fp);
97 if (bytes_read != (
size_t)file_size) {
99 PetscCall(PetscFree(buffer));
100 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to read '%s'.", path);
103 buffer[file_size] =
'\0';
106 PetscCall(
PicurvAssertBool((PetscBool)(strstr(buffer, needle) == NULL), context));
107 PetscCall(PetscFree(buffer));
108 PetscFunctionReturn(0);
122 PetscInt current_row = 0;
124 PetscFunctionBeginUser;
125 PetscCheck(path != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"CSV path cannot be NULL.");
126 PetscCheck(header != NULL && header_len > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"CSV header buffer cannot be NULL or empty.");
127 PetscCheck(row != NULL && row_len > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"CSV row buffer cannot be NULL or empty.");
128 PetscCheck(row_index >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
"CSV row index must be >= 1.");
130 fp = fopen(path,
"r");
131 PetscCheck(fp != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to open CSV '%s'.", path);
132 PetscCheck(fgets(header, (
int)header_len, fp) != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
"CSV header missing in '%s'.", path);
134 while (fgets(row, (
int)row_len, fp) != NULL) {
136 if (current_row == row_index) {
138 PetscFunctionReturn(0);
143 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
"CSV '%s' does not contain data row %d.", path, (
int)row_index);
149static PetscErrorCode
CsvFindColumnIndex(
const char *header,
const char *column_name, PetscInt *index_out)
151 char local_header[4096];
152 char *saveptr = NULL;
156 PetscFunctionBeginUser;
157 PetscCheck(header != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"CSV header cannot be NULL.");
158 PetscCheck(column_name != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"CSV column name cannot be NULL.");
159 PetscCheck(index_out != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"CSV column index output cannot be NULL.");
160 PetscCheck(strlen(header) <
sizeof(local_header), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
"CSV header is too long for the local parser buffer.");
162 PetscCall(PetscStrncpy(local_header, header,
sizeof(local_header)));
163 token = strtok_r(local_header,
",\r\n", &saveptr);
164 while (token != NULL) {
165 if (strcmp(token, column_name) == 0) {
167 PetscFunctionReturn(0);
169 token = strtok_r(NULL,
",\r\n", &saveptr);
173 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"CSV column '%s' was not found.", column_name);
181 const char *column_name,
185 char local_row[4096];
186 char *saveptr = NULL;
188 PetscInt target_index = -1;
191 PetscFunctionBeginUser;
192 PetscCheck(row != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"CSV row cannot be NULL.");
193 PetscCheck(value != NULL && value_len > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"CSV value buffer cannot be NULL or empty.");
194 PetscCheck(strlen(row) <
sizeof(local_row), PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
"CSV row is too long for the local parser buffer.");
197 PetscCall(PetscStrncpy(local_row, row,
sizeof(local_row)));
199 token = strtok_r(local_row,
",\r\n", &saveptr);
200 while (token != NULL) {
201 if (index == target_index) {
202 PetscCall(PetscStrncpy(value, token, value_len));
203 PetscFunctionReturn(0);
205 token = strtok_r(NULL,
",\r\n", &saveptr);
209 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"CSV row is missing column '%s'.", column_name);
215static PetscErrorCode
CsvGetColumnInt(
const char *header,
const char *row,
const char *column_name, PetscInt *value_out)
221 PetscFunctionBeginUser;
222 PetscCheck(value_out != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"CSV integer output cannot be NULL.");
224 parsed = strtol(text, &endptr, 10);
225 PetscCheck(endptr != text, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"CSV column '%s' did not contain an integer.", column_name);
226 *value_out = (PetscInt)parsed;
227 PetscFunctionReturn(0);
233static PetscErrorCode
CsvGetColumnReal(
const char *header,
const char *row,
const char *column_name, PetscReal *value_out)
239 PetscFunctionBeginUser;
240 PetscCheck(value_out != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"CSV real output cannot be NULL.");
242 parsed = strtod(text, &endptr);
243 PetscCheck(endptr != text, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"CSV column '%s' did not contain a real value.", column_name);
244 *value_out = (PetscReal)parsed;
245 PetscFunctionReturn(0);
264 PetscInt current_row = 0;
266 PetscBool header_found = PETSC_FALSE;
268 PetscFunctionBeginUser;
269 PetscCheck(path != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Log path cannot be NULL.");
270 PetscCheck(header != NULL && header_len > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Log header buffer cannot be NULL.");
271 PetscCheck(row != NULL && row_len > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Log row buffer cannot be NULL.");
272 PetscCheck(row_index >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
"Log row index must be >= 1.");
274 fp = fopen(path,
"r");
275 PetscCheck(fp != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to open log '%s'.", path);
277 while (fgets(line,
sizeof(line), fp) != NULL) {
278 if (line[0] ==
'=' || line[0] ==
'-' || line[0] ==
'\n' || line[0] ==
'\r')
continue;
280 PetscCall(PetscStrncpy(header, line, header_len));
281 header_found = PETSC_TRUE;
285 if (current_row == row_index) {
286 PetscCall(PetscStrncpy(row, line, row_len));
288 PetscFunctionReturn(0);
293 if (!header_found) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
"Log '%s' has no column header.", path);
294 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_READ,
"Log '%s' does not contain data row %d.", path, (
int)row_index);
300static PetscErrorCode
LogFindColumnIndex(
const char *header,
const char *column_name, PetscInt *index_out)
302 char local_header[8192];
303 char *saveptr = NULL;
307 PetscFunctionBeginUser;
308 PetscCheck(header != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Log header cannot be NULL.");
309 PetscCheck(column_name != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Log column name cannot be NULL.");
310 PetscCheck(index_out != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Log column index output cannot be NULL.");
312 PetscCall(PetscStrncpy(local_header, header,
sizeof(local_header)));
313 token = strtok_r(local_header,
"|\r\n", &saveptr);
314 while (token != NULL) {
315 while (*token ==
' ') token++;
316 char *end = token + strlen(token) - 1;
317 while (end > token && (*end ==
' ' || *end ==
'\r' || *end ==
'\n')) end--;
319 if (strcmp(token, column_name) == 0) {
321 PetscFunctionReturn(0);
323 token = strtok_r(NULL,
"|\r\n", &saveptr);
326 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"Log column '%s' was not found.", column_name);
334 const char *column_name,
338 char local_row[8192];
339 char *saveptr = NULL;
341 PetscInt target_index = -1;
344 PetscFunctionBeginUser;
345 PetscCheck(row != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Log row cannot be NULL.");
346 PetscCheck(value != NULL && value_len > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Log value buffer cannot be NULL.");
349 PetscCall(PetscStrncpy(local_row, row,
sizeof(local_row)));
351 token = strtok_r(local_row,
"|\r\n", &saveptr);
352 while (token != NULL) {
353 if (index == target_index) {
354 while (*token ==
' ') token++;
355 char *end = token + strlen(token) - 1;
356 while (end > token && (*end ==
' ' || *end ==
'\r' || *end ==
'\n')) end--;
358 PetscCall(PetscStrncpy(value, token, value_len));
359 PetscFunctionReturn(0);
361 token = strtok_r(NULL,
"|\r\n", &saveptr);
364 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"Log row is missing column '%s'.", column_name);
370static PetscErrorCode
LogGetColumnInt(
const char *header,
const char *row,
const char *column_name, PetscInt *value_out)
376 PetscFunctionBeginUser;
377 PetscCheck(value_out != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Log integer output cannot be NULL.");
379 parsed = strtol(text, &endptr, 10);
380 PetscCheck(endptr != text, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"Log column '%s' did not contain an integer.", column_name);
381 *value_out = (PetscInt)parsed;
382 PetscFunctionReturn(0);
388static PetscErrorCode
LogGetColumnReal(
const char *header,
const char *row,
const char *column_name, PetscReal *value_out)
394 PetscFunctionBeginUser;
395 PetscCheck(value_out != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Log real output cannot be NULL.");
397 parsed = strtod(text, &endptr);
398 PetscCheck(endptr != text, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"Log column '%s' did not contain a real value.", column_name);
399 *value_out = (PetscReal)parsed;
400 PetscFunctionReturn(0);
420 char tmpdir[PETSC_MAX_PATH_LEN];
421 char capture_path[PETSC_MAX_PATH_LEN];
422 FILE *capture_file = NULL;
423 int saved_stdout = -1;
425 size_t bytes_read = 0;
428 PetscFunctionBeginUser;
429 PetscCheck(fn != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Capture callback cannot be NULL.");
430 PetscCheck(captured != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Capture buffer cannot be NULL.");
431 PetscCheck(captured_len > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
"Capture buffer must be non-empty.");
434 PetscCall(PetscSNPrintf(capture_path,
sizeof(capture_path),
"%s/logging.out", tmpdir));
437 saved_stdout = dup(STDOUT_FILENO);
438 PetscCheck(saved_stdout >= 0, PETSC_COMM_SELF, PETSC_ERR_SYS,
"dup(STDOUT_FILENO) failed.");
439 capture_fd = open(capture_path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
440 PetscCheck(capture_fd >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to open capture file '%s'.", capture_path);
441 PetscCheck(dup2(capture_fd, STDOUT_FILENO) >= 0, PETSC_COMM_SELF, PETSC_ERR_SYS,
"dup2() failed while redirecting stdout.");
445 ierr = fn(user, simCtx, ctx);
447 PetscCheck(dup2(saved_stdout, STDOUT_FILENO) >= 0, PETSC_COMM_SELF, PETSC_ERR_SYS,
"dup2() failed while restoring stdout.");
452 capture_file = fopen(capture_path,
"r");
453 PetscCheck(capture_file != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to read capture file '%s'.", capture_path);
454 bytes_read = fread(captured, 1, captured_len - 1, capture_file);
455 captured[bytes_read] =
'\0';
456 fclose(capture_file);
458 PetscFunctionReturn(0);
466 PetscInt print_interval = *((PetscInt *)ctx);
468 PetscFunctionBeginUser;
471 PetscFunctionReturn(0);
479 PetscInt step = *((PetscInt *)ctx);
481 PetscFunctionBeginUser;
483 PetscFunctionReturn(0);
491 PetscInt step = *((PetscInt *)ctx);
493 PetscFunctionBeginUser;
495 PetscFunctionReturn(0);
505 PetscFunctionBeginUser;
508 PetscFunctionReturn(0);
516 PetscReal *positions = NULL;
517 PetscReal *velocities = NULL;
518 PetscReal *weights = NULL;
519 PetscInt *cell_ids = NULL;
520 PetscInt *status = NULL;
521 PetscReal *psi = NULL;
523 PetscFunctionBeginUser;
526 (*simCtx_out)->np = 2;
527 (*simCtx_out)->particleConsoleOutputFreq = 2;
528 (*simCtx_out)->LoggingFrequency = 1;
530 PetscCall(DMSwarmGetField((*user_out)->swarm,
"position", NULL, NULL, (
void **)&positions));
531 PetscCall(DMSwarmGetField((*user_out)->swarm,
"velocity", NULL, NULL, (
void **)&velocities));
532 PetscCall(DMSwarmGetField((*user_out)->swarm,
"weight", NULL, NULL, (
void **)&weights));
533 PetscCall(DMSwarmGetField((*user_out)->swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&cell_ids));
534 PetscCall(DMSwarmGetField((*user_out)->swarm,
"DMSwarm_location_status", NULL, NULL, (
void **)&status));
535 PetscCall(DMSwarmGetField((*user_out)->swarm,
"Psi", NULL, NULL, (
void **)&psi));
537 positions[0] = 0.25; positions[1] = 0.50; positions[2] = 0.75;
538 positions[3] = 0.50; positions[4] = 0.50; positions[5] = 0.50;
539 velocities[0] = 1.0; velocities[1] = 2.0; velocities[2] = 3.0;
540 velocities[3] = 4.0; velocities[4] = 5.0; velocities[5] = 6.0;
541 weights[0] = 0.2; weights[1] = 0.3; weights[2] = 0.4;
542 weights[3] = 0.5; weights[4] = 0.5; weights[5] = 0.5;
543 cell_ids[0] = 0; cell_ids[1] = 0; cell_ids[2] = 0;
544 cell_ids[3] = 1; cell_ids[4] = 1; cell_ids[5] = 1;
550 PetscCall(DMSwarmRestoreField((*user_out)->swarm,
"Psi", NULL, NULL, (
void **)&psi));
551 PetscCall(DMSwarmRestoreField((*user_out)->swarm,
"DMSwarm_location_status", NULL, NULL, (
void **)&status));
552 PetscCall(DMSwarmRestoreField((*user_out)->swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&cell_ids));
553 PetscCall(DMSwarmRestoreField((*user_out)->swarm,
"weight", NULL, NULL, (
void **)&weights));
554 PetscCall(DMSwarmRestoreField((*user_out)->swarm,
"velocity", NULL, NULL, (
void **)&velocities));
555 PetscCall(DMSwarmRestoreField((*user_out)->swarm,
"position", NULL, NULL, (
void **)&positions));
556 PetscFunctionReturn(0);
566 PetscFunctionBeginUser;
567 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx cannot be NULL.");
568 PetscCheck(field != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Velocity field cannot be NULL.");
570 PetscCall(DMDAVecGetArray(user->
fda, field, &arr));
571 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
572 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
573 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
580 PetscCall(DMDAVecRestoreArray(user->
fda, field, &arr));
581 PetscFunctionReturn(0);
589 PetscReal ***arr = NULL;
591 PetscFunctionBeginUser;
592 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx cannot be NULL.");
593 PetscCheck(field != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Scalar field cannot be NULL.");
595 PetscCall(DMDAVecGetArray(user->
da, field, &arr));
596 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
597 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
598 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
599 arr[k][j][i] = value;
603 PetscCall(DMDAVecRestoreArray(user->
da, field, &arr));
604 PetscFunctionReturn(0);
617 const PetscInt ncells = user->
info.mz - 2;
619 PetscFunctionBeginUser;
620 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx cannot be NULL.");
621 PetscCheck(field != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Velocity field cannot be NULL.");
623 PetscCall(DMDAVecGetArray(user->
fda, field, &arr));
624 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
625 const PetscInt cell = (k == 0) ? ncells : (k == user->
info.mz - 1) ? 1 : k;
626 PetscReal z_phase = (2.0 * PETSC_PI * (PetscReal)(cell - 1)) / (PetscReal)ncells;
627 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
628 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
629 arr[k][j][i].
x = 0.0;
630 arr[k][j][i].
y = v_amp * PetscSinReal(z_phase);
631 arr[k][j][i].
z = w_const;
635 PetscCall(DMDAVecRestoreArray(user->
fda, field, &arr));
636 PetscFunctionReturn(0);
645 PetscFunctionBeginUser;
647 "BCFaceToString should report the negative-x face"));
649 "InitialConditionModeToString should report the zero mode"));
651 "InitialConditionModeToString should report the Cartesian constant mode"));
653 "InitialConditionModeToString should report the streamwise constant mode"));
655 "InitialConditionModeToString should report the Poiseuille mode"));
657 "InitialConditionModeToString should report the file mode"));
659 "InitialConditionModeToString should reject unknown selectors"));
661 "ParticleInitializationToString should report the volume mode"));
663 "LESModelToString should report the constant model"));
665 "MomentumSolverTypeToString should report the explicit solver"));
667 "MomentumSolverTypeToString should report the Newton Krylov solver"));
669 "BCTypeToString should report periodic boundaries"));
671 "BCHandlerTypeToString should report the driven periodic handler"));
673 "ParticleLocationStatusToString should report LOST state"));
674 PetscFunctionReturn(0);
682 PetscFunctionBeginUser;
684 "get_log_level should honor LOG_LEVEL=INFO in this test binary"));
686 PetscFunctionReturn(0);
694 const char *allow_list[] = {
"ComputeSpecificKE",
"WriteEulerianFile"};
696 PetscFunctionBeginUser;
699 "Allowed list should include ComputeSpecificKE"));
701 "Allowed list should exclude unknown function names"));
705 "Empty allow-list should permit all functions"));
706 PetscFunctionReturn(0);
716 PetscFunctionBeginUser;
717 PetscCall(PetscMemzero(&simCtx,
sizeof(simCtx)));
722 "Particle snapshot contract should be enabled when particles and cadence are configured"));
724 "Snapshot should emit on cadence-aligned completed steps"));
726 "Snapshot should not emit off-cadence"));
730 "Zero cadence should disable periodic particle snapshots"));
732 "NULL SimCtx should never emit periodic snapshots"));
733 PetscFunctionReturn(0);
745 memset(&definition, 0,
sizeof(definition));
750 definition.
bounded = PETSC_TRUE;
766 PetscFunctionBeginUser;
767 PetscCall(PetscMemzero(&simCtx,
sizeof(simCtx)));
775 "Statistics snapshot contract should be enabled when a window and cadence are configured"));
777 "Snapshot should emit on cadence-aligned completed steps"));
779 "Snapshot should not emit off-cadence"));
781 "Snapshot should not emit for a step that has not completed"));
785 "Zero cadence should disable periodic statistics snapshots"));
787 "Zero cadence should not emit even on the step that opens a run"));
794 "A configured cadence should not enable snapshots without an accumulating window"));
799 "A disabled subsystem should not emit statistics snapshots"));
802 "NULL SimCtx should never emit periodic snapshots"));
803 PetscFunctionReturn(0);
811 char tmpdir[PETSC_MAX_PATH_LEN];
812 char allow_path[PETSC_MAX_PATH_LEN];
813 char dual_log_path[PETSC_MAX_PATH_LEN];
818 PetscReal distances[6] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0};
822 PetscFunctionBeginUser;
823 PetscCall(PetscMemzero(&cell,
sizeof(cell)));
825 PetscCall(PetscSNPrintf(allow_path,
sizeof(allow_path),
"%s/allowed_functions.txt", tmpdir));
826 PetscCall(PetscSNPrintf(dual_log_path,
sizeof(dual_log_path),
"%s/dual-monitor.log", tmpdir));
828 file = fopen(allow_path,
"w");
829 PetscCheck(file != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to create allow-list file '%s'.", allow_path);
830 fputs(
" ComputeSpecificKE \n", file);
831 fputs(
"# comment-only line\n", file);
832 for (PetscInt i = 0; i < 17; ++i) {
833 fprintf(file,
"Helper_%02d # trailing comment\n", (
int)i);
839 PetscCall(
PicurvAssertIntEqual(18, nfuncs,
"LoadAllowedFunctionsFromFile should trim comments and keep all identifiers"));
840 PetscCall(
PicurvAssertBool((PetscBool)(strcmp(funcs[0],
"ComputeSpecificKE") == 0),
841 "LoadAllowedFunctionsFromFile should trim leading and trailing whitespace"));
842 PetscCall(
PicurvAssertBool((PetscBool)(strcmp(funcs[17],
"Helper_16") == 0),
843 "LoadAllowedFunctionsFromFile should grow past the initial pointer capacity"));
846 for (PetscInt i = 0; i < 8; ++i) {
854 PetscCall(PetscCalloc1(1, &monctx));
856 PetscCheck(monctx->
file_handle != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to create dual-monitor log '%s'.", dual_log_path);
860 "DualMonitorDestroy should clear the caller-owned context pointer"));
865 PetscCall(PetscPrintf(PETSC_COMM_SELF,
"\n"));
868 PetscFunctionReturn(0);
878 char tmpdir[PETSC_MAX_PATH_LEN];
879 char continuity_path[PETSC_MAX_PATH_LEN];
880 PetscReal ***p = NULL;
883 PetscErrorCode ierr_minmax = 0;
885 PetscFunctionBeginUser;
888 PetscCall(PetscStrncpy(simCtx->
log_dir, tmpdir,
sizeof(simCtx->
log_dir)));
909 PetscCall(PetscSNPrintf(continuity_path,
sizeof(continuity_path),
"%s/Continuity_Metrics.log", simCtx->
log_dir));
911 PetscCall(
AssertFileContains(continuity_path,
"Timestep",
"continuity metrics log should include the header"));
912 PetscCall(
AssertFileContains(continuity_path,
"([3][2][1] = 17)",
"continuity metrics log should include the divergence location"));
913 PetscCall(
AssertFileContains(continuity_path,
"2 | 0",
"continuity metrics log should append later timesteps"));
915 PetscCall(DMDAVecGetArray(user->
da, user->
P, &p));
916 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
917 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucont, &ucont));
918 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
919 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
920 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
921 p[k][j][i] = (PetscReal)(i + j + k);
922 ucat[k][j][i].
x = (PetscReal)i;
923 ucat[k][j][i].
y = (PetscReal)(-j);
924 ucat[k][j][i].
z = (PetscReal)(2 * k);
925 ucont[k][j][i].
x = (PetscReal)(10 + i);
926 ucont[k][j][i].
y = (PetscReal)(20 + j);
927 ucont[k][j][i].
z = (PetscReal)(30 + k);
931 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucont, &ucont));
932 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
933 PetscCall(DMDAVecRestoreArray(user->
da, user->
P, &p));
935 PetscCall(DMGlobalToLocalBegin(user->
da, user->
P, INSERT_VALUES, user->
lP));
936 PetscCall(DMGlobalToLocalEnd(user->
da, user->
P, INSERT_VALUES, user->
lP));
937 PetscCall(DMGlobalToLocalBegin(user->
fda, user->
Ucat, INSERT_VALUES, user->
lUcat));
938 PetscCall(DMGlobalToLocalEnd(user->
fda, user->
Ucat, INSERT_VALUES, user->
lUcat));
939 PetscCall(DMGlobalToLocalBegin(user->
fda, user->
Ucont, INSERT_VALUES, user->
lUcont));
940 PetscCall(DMGlobalToLocalEnd(user->
fda, user->
Ucont, INSERT_VALUES, user->
lUcont));
947 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
949 PetscCall(PetscPopErrorHandler());
951 "LOG_FIELD_MIN_MAX should reject invalid field IDs"));
955 PetscFunctionReturn(0);
965 PetscReal (*pos_arr)[3] = NULL;
966 PetscReal (*vel_arr)[3] = NULL;
967 Vec position_vec = NULL;
968 Vec analytical_vec = NULL;
969 const PetscScalar *analytical_arr = NULL;
970 char tmpdir[PETSC_MAX_PATH_LEN];
971 char metrics_path[PETSC_MAX_PATH_LEN];
973 PetscFunctionBeginUser;
986 PetscCall(DMSwarmGetField(user->
swarm,
"position", NULL, NULL, (
void *)&pos_arr));
987 pos_arr[0][0] = 0.5 * PETSC_PI; pos_arr[0][1] = 0.0; pos_arr[0][2] = 0.0;
988 pos_arr[1][0] = 0.0; pos_arr[1][1] = 0.5 * PETSC_PI; pos_arr[1][2] = 0.0;
989 PetscCall(DMSwarmRestoreField(user->
swarm,
"position", NULL, NULL, (
void *)&pos_arr));
991 PetscCall(DMSwarmCreateGlobalVectorFromField(user->
swarm,
"position", &position_vec));
992 PetscCall(VecDuplicate(position_vec, &analytical_vec));
993 PetscCall(VecCopy(position_vec, analytical_vec));
996 PetscCall(DMSwarmGetField(user->
swarm,
"velocity", NULL, NULL, (
void *)&vel_arr));
997 PetscCall(VecGetArrayRead(analytical_vec, &analytical_arr));
998 for (PetscInt particle = 0; particle < 2; ++particle) {
999 vel_arr[particle][0] = PetscRealPart(analytical_arr[3 * particle + 0]);
1000 vel_arr[particle][1] = PetscRealPart(analytical_arr[3 * particle + 1]);
1001 vel_arr[particle][2] = PetscRealPart(analytical_arr[3 * particle + 2]);
1003 PetscCall(VecRestoreArrayRead(analytical_vec, &analytical_arr));
1004 PetscCall(DMSwarmRestoreField(user->
swarm,
"velocity", NULL, NULL, (
void *)&vel_arr));
1006 PetscCall(VecDestroy(&analytical_vec));
1007 PetscCall(DMSwarmDestroyGlobalVectorFromField(user->
swarm,
"position", &position_vec));
1010 PetscCall(PetscSNPrintf(metrics_path,
sizeof(metrics_path),
"%s/interpolation_error.csv", simCtx->
analysis_dir));
1011 PetscCall(
PicurvAssertFileExists(metrics_path,
"LOG_INTERPOLATION_ERROR should write interpolation_error.csv"));
1013 "interpolation_error.csv should record physical time, not time multiplied by dt"));
1016 PetscFunctionReturn(0);
1026 char tmpdir[PETSC_MAX_PATH_LEN];
1027 char metrics_path[PETSC_MAX_PATH_LEN];
1028 PetscReal *positions = NULL;
1029 PetscReal *psi = NULL;
1030 PetscInt *cell_ids = NULL;
1031 PetscInt *status = NULL;
1032 PetscInt particle = 0;
1034 PetscFunctionBeginUser;
1038 PetscCall(PetscStrncpy(simCtx->
log_dir, tmpdir,
sizeof(simCtx->
log_dir)));
1051 PetscCall(DMSwarmGetField(user->
swarm,
"position", NULL, NULL, (
void **)&positions));
1052 PetscCall(DMSwarmGetField(user->
swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&cell_ids));
1053 PetscCall(DMSwarmGetField(user->
swarm,
"DMSwarm_location_status", NULL, NULL, (
void **)&status));
1054 PetscCall(DMSwarmGetField(user->
swarm,
"Psi", NULL, NULL, (
void **)&psi));
1056 for (PetscInt k = 0; k < 3; ++k) {
1057 for (PetscInt j = 0; j < 3; ++j) {
1058 for (PetscInt i = 0; i < 3; ++i) {
1059 positions[3 * particle + 0] = (i + 0.5) / 4.0;
1060 positions[3 * particle + 1] = (j + 0.5) / 4.0;
1061 positions[3 * particle + 2] = (k + 0.5) / 4.0;
1062 cell_ids[3 * particle + 0] = i;
1063 cell_ids[3 * particle + 1] = j;
1064 cell_ids[3 * particle + 2] = k;
1066 psi[particle] = 2.0;
1072 PetscCall(DMSwarmRestoreField(user->
swarm,
"Psi", NULL, NULL, (
void **)&psi));
1073 PetscCall(DMSwarmRestoreField(user->
swarm,
"DMSwarm_location_status", NULL, NULL, (
void **)&status));
1074 PetscCall(DMSwarmRestoreField(user->
swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&cell_ids));
1075 PetscCall(DMSwarmRestoreField(user->
swarm,
"position", NULL, NULL, (
void **)&positions));
1080 PetscCall(PetscSNPrintf(metrics_path,
sizeof(metrics_path),
"%s/scatter_metrics.csv", simCtx->
analysis_dir));
1083 "Scatter metrics CSV header should include relative_L2_error"));
1085 "3,3.000000e-01,27,27,27,1.000000e+00,1.000000e+00,5.400000e+01,5.400000e+01,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00,0.000000e+00",
1086 "Scatter metrics CSV should record the expected constant-field zero-error row"));
1090 PetscFunctionReturn(0);
1100 PetscInt print_interval = 1;
1101 char captured[8192];
1103 PetscFunctionBeginUser;
1106 PetscCall(
PicurvAssertBool((PetscBool)(strstr(captured,
"Position (x,y,z)") != NULL),
1107 "LOG_PARTICLE_FIELDS should print the particle table header"));
1108 PetscCall(
PicurvAssertBool((PetscBool)(strstr(captured,
"Weights (a1,a2,a3)") != NULL),
1109 "LOG_PARTICLE_FIELDS should print the weight-column header"));
1111 PetscFunctionReturn(0);
1122 char captured[8192];
1124 PetscFunctionBeginUser;
1127 PetscCall(
PicurvAssertBool((PetscBool)(strstr(captured,
"Particle states at step 4") != NULL),
1128 "EmitParticleConsoleSnapshot should print the step banner"));
1129 PetscCall(
PicurvAssertBool((PetscBool)(strstr(captured,
"Position (x,y,z)") != NULL),
1130 "EmitParticleConsoleSnapshot should reuse the particle table output"));
1132 PetscFunctionReturn(0);
1151 char captured[8192];
1153 PetscFunctionBeginUser;
1155 PetscCall(VecSet(user->
Nvert, 0.0));
1167 for (PetscInt offered = 0; offered <= step; ++offered) {
1172 captured,
sizeof(captured)));
1173 PetscCall(
PicurvAssertBool((PetscBool)(strstr(captured,
"Statistics windows at step 2") != NULL),
1174 "EmitStatisticsConsoleSnapshot should print the step banner"));
1175 PetscCall(
PicurvAssertBool((PetscBool)(strstr(captured,
"console_window") != NULL),
1176 "EmitStatisticsConsoleSnapshot should name each configured window"));
1177 PetscCall(
PicurvAssertBool((PetscBool)(strstr(captured,
"samples=2") != NULL),
1178 "EmitStatisticsConsoleSnapshot should report the accepted sample count"));
1179 PetscCall(
PicurvAssertBool((PetscBool)(strstr(captured,
"valid=[") != NULL),
1180 "EmitStatisticsConsoleSnapshot should report mask coverage once storage carries samples"));
1184 captured,
sizeof(captured)));
1186 "a disabled subsystem emits no statistics console output"));
1193 PetscFunctionReturn(0);
1200 PetscReal ***p = NULL;
1201 const DMDALocalInfo info = user->
info;
1203 PetscFunctionBeginUser;
1204 PetscCall(DMDAVecGetArray(user->
da, user->
P, &p));
1205 for (PetscInt k = info.zs; k < info.zs + info.zm; ++k)
1206 for (PetscInt j = info.ys; j < info.ys + info.ym; ++j)
1207 for (PetscInt i = info.xs; i < info.xs + info.xm; ++i) p[k][j][i] = value;
1208 PetscCall(DMDAVecRestoreArray(user->
da, user->
P, &p));
1209 PetscFunctionReturn(0);
1221 PetscInt console_frequency)
1223 PetscFunctionBeginUser;
1231 for (PetscInt step = 0; step <= 3; ++step) {
1238 PetscFunctionReturn(0);
1245 PetscBool equal = PETSC_FALSE;
1247 PetscFunctionBeginUser;
1248 PetscCall(VecEqual(expected, actual, &equal));
1250 PetscFunctionReturn(0);
1269 char captured[8192];
1272 PetscFunctionBeginUser;
1275 PetscCall(VecSet(user->
Nvert, 0.0));
1283 "both cadences accept the same states"));
1285 "both cadences accumulate the same total weight"));
1287 "per-point sample counts are independent of the console cadence"));
1289 "per-point weights are independent of the console cadence"));
1291 "means are independent of the console cadence"));
1293 "second moments are independent of the console cadence"));
1301 captured,
sizeof(captured)));
1302 PetscCall(
PicurvAssertBool((PetscBool)(strstr(captured,
"console_window") != NULL),
1303 "the reporting cadence emits console output at this log level"));
1312 PetscFunctionReturn(0);
1322 char tmpdir[PETSC_MAX_PATH_LEN];
1323 char metrics_path[PETSC_MAX_PATH_LEN];
1325 PetscFunctionBeginUser;
1328 PetscCall(PetscStrncpy(simCtx->
log_dir, tmpdir,
sizeof(simCtx->
log_dir)));
1340 PetscCall(PetscSNPrintf(metrics_path,
sizeof(metrics_path),
"%s/Particle_Metrics.log", simCtx->
log_dir));
1341 PetscCall(
PicurvAssertFileExists(metrics_path,
"LOG_PARTICLE_METRICS should write Particle_Metrics.log"));
1342 PetscCall(
AssertFileContains(metrics_path,
"Timestep Metrics",
"Particle metrics log should include the caller-provided stage label"));
1343 PetscCall(
AssertFileContains(metrics_path,
"Occupied Cells",
"Particle metrics log should include the metrics table header"));
1344 PetscCall(
AssertFileContains(metrics_path,
"Lost Total",
"Particle metrics log should include the cumulative-loss column"));
1345 PetscCall(
AssertFileContains(metrics_path,
"| 1 | 7 | 2",
"Particle metrics log should record both per-step and cumulative loss values"));
1348 PetscFunctionReturn(0);
1358 char tmpdir[PETSC_MAX_PATH_LEN];
1359 char metrics_path[PETSC_MAX_PATH_LEN];
1361 PetscFunctionBeginUser;
1364 PetscCall(PetscStrncpy(simCtx->
log_dir, tmpdir,
sizeof(simCtx->
log_dir)));
1388 PetscCall(PetscSNPrintf(metrics_path,
sizeof(metrics_path),
"%s/search_metrics.csv", simCtx->
analysis_dir));
1390 PetscCall(
AssertFileContains(metrics_path,
"search_attempts",
"Search metrics CSV header should include search_attempts"));
1391 PetscCall(
AssertFileContains(metrics_path,
"search_population",
"Search metrics CSV header should include search_population"));
1392 PetscCall(
AssertFileContains(metrics_path,
"max_particle_pass_depth",
"Search metrics CSV header should include max_particle_pass_depth"));
1393 PetscCall(
AssertFileContains(metrics_path,
"search_work_index",
"Search metrics CSV header should include search_work_index"));
1394 PetscCall(
AssertFileContains(metrics_path,
"re_search_fraction",
"Search metrics CSV header should include re_search_fraction"));
1395 PetscCall(
AssertFileContains(metrics_path,
"lost_cumulative",
"Search metrics CSV header should include the cumulative-loss column"));
1396 PetscCall(
AssertFileContains(metrics_path,
"2,2.000000e-01,2,1,7,2,3,4,2.500000e+00,6,1,2,3,1,3,1.500000e+00,2,1,1,10,2,1,5.000000e-01,5.000000e+00,1.000000e+00",
"Search metrics CSV should record the V2 raw and derived search metrics"));
1399 PetscFunctionReturn(0);
1409 char captured[8192];
1412 PetscFunctionBeginUser;
1414 PetscCall(VecSet(user->
P, 7.0));
1415 PetscCall(DMGlobalToLocalBegin(user->
da, user->
P, INSERT_VALUES, user->
lP));
1416 PetscCall(DMGlobalToLocalEnd(user->
da, user->
P, INSERT_VALUES, user->
lP));
1418 PetscCall(
PicurvAssertBool((PetscBool)(strstr(captured,
"Field Anatomy Log: [P]") != NULL),
1419 "LOG_FIELD_ANATOMY should print the requested field name"));
1420 PetscCall(
PicurvAssertBool((PetscBool)(strstr(captured,
"Layout: [Cell-Centered]") != NULL),
1421 "LOG_FIELD_ANATOMY should report the inferred data layout"));
1423 PetscFunctionReturn(0);
1432 char tmpdir[PETSC_MAX_PATH_LEN];
1433 char timestep_path[PETSC_MAX_PATH_LEN];
1434 char summary_path[PETSC_MAX_PATH_LEN];
1435 static char selected_name[] =
"FlowSolver";
1436 char *selected_funcs[] = {selected_name};
1438 PetscFunctionBeginUser;
1439 PetscCall(PetscMemzero(&simCtx,
sizeof(simCtx)));
1441 PetscCall(PetscStrncpy(simCtx.
log_dir, tmpdir,
sizeof(simCtx.
log_dir)));
1466 PetscCall(PetscSNPrintf(summary_path,
sizeof(summary_path),
"%s/ProfilingSummary_Solver.log", simCtx.
log_dir));
1470 "profiling timestep summary should contain the CSV header"));
1472 "profiling timestep summary should log selected functions"));
1474 "profiling timestep summary should omit unselected functions in selected mode"));
1476 "profiling final summary should include its table banner"));
1478 "profiling final summary should include selected functions"));
1480 "profiling final summary should include total-time entries for unselected functions"));
1482 PetscFunctionReturn(0);
1491 char tmpdir[PETSC_MAX_PATH_LEN];
1492 char memory_path[PETSC_MAX_PATH_LEN];
1494 PetscFunctionBeginUser;
1495 PetscCall(PetscMemzero(&simCtx,
sizeof(simCtx)));
1497 PetscCall(PetscStrncpy(simCtx.
log_dir, tmpdir,
sizeof(simCtx.
log_dir)));
1505 PetscCall(PetscMemorySetGetMaximumUsage());
1512 "runtime memory log should contain readable column labels"));
1514 "runtime memory log should contain a step row"));
1516 "runtime memory log should contain a final row"));
1518 "runtime memory log should record final reason"));
1525 "disabled runtime memory log should not create a file"));
1527 PetscFunctionReturn(0);
1537 char tmpdir[PETSC_MAX_PATH_LEN];
1538 char log_path[PETSC_MAX_PATH_LEN];
1539 PetscBool exists = PETSC_FALSE;
1541 PetscFunctionBeginUser;
1544 PetscCall(PetscStrncpy(simCtx->
log_dir, tmpdir,
sizeof(simCtx->
log_dir)));
1549 PetscCall(PetscSNPrintf(log_path,
sizeof(log_path),
"%s/solution_convergence.log", simCtx->
log_dir));
1550 PetscCall(PetscTestFile(log_path,
'r', &exists));
1552 "disabled solution convergence must not create a log"));
1556 PetscFunctionReturn(0);
1566 char tmpdir[PETSC_MAX_PATH_LEN];
1567 char log_path[PETSC_MAX_PATH_LEN];
1573 PetscReal ***nvert = NULL;
1574 PetscReal mean_speed = NAN;
1575 PetscReal mean_speed_ref = NAN;
1576 PetscReal mean_speed_abs = NAN;
1577 PetscReal p_abs = NAN;
1578 PetscInt has_reference_1 = 0;
1579 PetscInt has_reference_2 = 0;
1581 PetscFunctionBeginUser;
1584 PetscCall(PetscStrncpy(simCtx->
log_dir, tmpdir,
sizeof(simCtx->
log_dir)));
1593 PetscCall(DMDAVecGetArray(user->
da, user->
Nvert, &nvert));
1594 nvert[1][1][1] = 1.0;
1595 PetscCall(DMDAVecRestoreArray(user->
da, user->
Nvert, &nvert));
1596 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
1597 ucat[1][1][1].
x = 999.0;
1598 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
1607 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
1608 ucat[1][1][1].
x = 999.0;
1609 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
1612 PetscCall(PetscSNPrintf(log_path,
sizeof(log_path),
"%s/solution_convergence.log", simCtx->
log_dir));
1624 PetscCall(
PicurvAssertBool((PetscBool)(strcmp(mode,
"steady_deterministic") == 0),
1625 "steady solution convergence row should record the mode name"));
1627 "the first steady solution-convergence row should be a warmup row"));
1629 "steady solution convergence should compare against the previous solved step"));
1631 "steady solution convergence should mask IBM-marked solid cells"));
1633 "steady solution convergence should report the previous-step mean speed"));
1635 "steady solution convergence should report mean-speed drift"));
1637 "steady solution convergence pressure drift should be gauge invariant"));
1641 PetscFunctionReturn(0);
1651 char tmpdir[PETSC_MAX_PATH_LEN];
1652 char log_path[PETSC_MAX_PATH_LEN];
1657 PetscInt has_reference_1 = 0;
1658 PetscInt has_reference_2 = 0;
1659 PetscInt has_reference_3 = 0;
1660 PetscInt phase_step_1 = -1;
1661 PetscInt phase_step_2 = -1;
1662 PetscInt phase_step_3 = -1;
1663 PetscReal mean_speed_ref_2 = NAN;
1664 PetscReal mean_speed_abs_2 = NAN;
1666 PetscFunctionBeginUser;
1669 PetscCall(PetscStrncpy(simCtx->
log_dir, tmpdir,
sizeof(simCtx->
log_dir)));
1693 PetscCall(PetscSNPrintf(log_path,
sizeof(log_path),
"%s/solution_convergence.log", simCtx->
log_dir));
1694 PetscCall(
PicurvAssertFileExists(log_path,
"periodic solution-convergence logging should write the log"));
1708 "the first periodic phase visit should log warmup without a reference"));
1710 "the first periodic cycle should fully warm up before comparisons begin"));
1712 "the repeated periodic phase visit should compare against the stored reference"));
1714 "periodic solution convergence should log the current phase slot"));
1716 "periodic solution convergence should log distinct phase slots during warmup"));
1718 "periodic solution convergence should reuse the same phase slot on later cycles"));
1720 "periodic solution convergence should report the stored phase-aligned reference"));
1722 "periodic solution convergence should report the phase-aligned drift"));
1726 PetscFunctionReturn(0);
1736 char tmpdir[PETSC_MAX_PATH_LEN];
1737 char log_path[PETSC_MAX_PATH_LEN];
1740 PetscReal mean_speed_window = NAN;
1741 PetscReal mean_speed_window_prev = NAN;
1742 PetscReal mean_speed_window_abs = NAN;
1743 PetscReal mean_speed_rms_window = NAN;
1744 PetscReal mean_ke_window = NAN;
1745 PetscReal mean_ke_window_prev = NAN;
1746 PetscReal mean_ke_window_abs = NAN;
1747 PetscReal mean_ke_rms_window_abs = NAN;
1748 PetscInt has_reference = 0;
1749 const PetscReal speed_samples[4] = {1.0, 3.0, 2.0, 4.0};
1751 PetscFunctionBeginUser;
1754 PetscCall(PetscStrncpy(simCtx->
log_dir, tmpdir,
sizeof(simCtx->
log_dir)));
1759 for (PetscInt step = 0; step < 4; ++step) {
1760 simCtx->
step = step + 1;
1761 simCtx->
ti = 0.1 * (PetscReal)(step + 1);
1766 PetscCall(PetscSNPrintf(log_path,
sizeof(log_path),
"%s/solution_convergence.log", simCtx->
log_dir));
1767 PetscCall(
PicurvAssertFileExists(log_path,
"statistical solution-convergence logging should write the log"));
1771 PetscCall(
LogGetColumnReal(header, row,
"spd_win_prev", &mean_speed_window_prev));
1772 PetscCall(
LogGetColumnReal(header, row,
"spd_win_abs", &mean_speed_window_abs));
1773 PetscCall(
LogGetColumnReal(header, row,
"spd_rms_win", &mean_speed_rms_window));
1775 PetscCall(
LogGetColumnReal(header, row,
"ke_win_prev", &mean_ke_window_prev));
1776 PetscCall(
LogGetColumnReal(header, row,
"ke_win_abs", &mean_ke_window_abs));
1777 PetscCall(
LogGetColumnReal(header, row,
"ke_rms_abs", &mean_ke_rms_window_abs));
1780 "statistical solution convergence should emit adjacent-window drift once two windows exist"));
1782 "statistical solution convergence should report the current mean-speed window"));
1784 "statistical solution convergence should report the previous mean-speed window"));
1786 "statistical solution convergence should report mean-speed window drift"));
1788 "statistical solution convergence should report current mean-speed RMS"));
1790 "statistical solution convergence should report the current kinetic-energy window"));
1792 "statistical solution convergence should report the previous kinetic-energy window"));
1794 "statistical solution convergence should report kinetic-energy window drift"));
1796 "statistical solution convergence should report RMS kinetic-energy drift"));
1800 PetscFunctionReturn(0);
1813 char tmpdir[PETSC_MAX_PATH_LEN];
1814 char log_path[PETSC_MAX_PATH_LEN];
1817 PetscReal mean_speed = NAN;
1820 PetscFunctionBeginUser;
1823 PetscCall(PetscStrncpy(simCtx->
log_dir, tmpdir,
sizeof(simCtx->
log_dir)));
1825 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &arr));
1826 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
1827 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
1828 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
1829 const PetscBool ghost = (PetscBool)(i == 0 || j == 0 || k == 0 || i == user->
info.mx - 1 ||
1830 j == user->
info.my - 1 || k == user->
info.mz - 1);
1831 arr[k][j][i].
x = 0.0;
1832 arr[k][j][i].
y = 0.0;
1833 arr[k][j][i].
z = ghost ? 100.0 : 1.0;
1837 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &arr));
1845 PetscCall(PetscSNPrintf(log_path,
sizeof(log_path),
"%s/solution_convergence.log", simCtx->
log_dir));
1849 "mean speed must average physical cells only, not wall ghost images"));
1853 PetscFunctionReturn(0);
1868 const PetscInt km_values[] = {8, 16};
1869 const PetscInt n_cases = (PetscInt)(
sizeof(km_values) /
sizeof(km_values[0]));
1871 PetscFunctionBeginUser;
1872 for (PetscInt t = 0; t < n_cases; ++t) {
1873 const PetscInt km = km_values[t];
1876 char tmpdir[PETSC_MAX_PATH_LEN];
1877 char log_path[PETSC_MAX_PATH_LEN];
1880 PetscReal mean_ke = NAN;
1883 PETSC_TRUE, PETSC_TRUE, PETSC_TRUE));
1885 PetscCall(PetscStrncpy(simCtx->
log_dir, tmpdir,
sizeof(simCtx->
log_dir)));
1897 PetscCall(PetscSNPrintf(log_path,
sizeof(log_path),
"%s/solution_convergence.log", simCtx->
log_dir));
1901 "periodic sinusoidal field mean KE must equal 0.5025 (no duplicate endpoint)"));
1906 PetscFunctionReturn(0);
1915 PetscErrorCode ierr;
1943 (void)setenv(
"LOG_LEVEL",
"INFO", 1);
1945 ierr = PetscInitialize(&argc, &argv, NULL,
"PICurv logging tests");
1950 ierr =
PicurvRunTests(
"unit-logging", cases,
sizeof(cases) /
sizeof(cases[0]));
1958 ierr = PetscFinalize();
PetscErrorCode SetAnalyticalSolutionForParticles(Vec tempVec, SimCtx *simCtx)
Applies the analytical solution to particle velocity vector.
PetscErrorCode CalculateParticleCountPerCell(UserCtx *user)
Counts particles in each cell of the DMDA 'da' and stores the result in user->ParticleCount.
FieldId
Compile-time identity for a catalogued Eulerian field.
PetscErrorCode ScatterAllParticleFieldsToEulerFields(UserCtx *user)
Scatters a predefined set of particle fields to their corresponding Eulerian fields.
Logging utilities and macros for PETSc-based applications.
PetscErrorCode LOG_FIELD_MIN_MAX(UserCtx *user, FieldId field_id)
Computes and logs the local and global min/max values of a 3-component vector field.
void set_allowed_functions(const char **functionList, int count)
Sets the global list of function names that are allowed to log.
PetscErrorCode LOG_PARTICLE_METRICS(UserCtx *user, const char *stageName)
Logs particle swarm metrics, adapting its behavior based on a boolean flag in SimCtx.
PetscBool ShouldEmitPeriodicStatisticsConsoleSnapshot(const struct SimCtx *simCtx, PetscInt completed_step)
Reports whether a completed step falls on the console snapshot cadence.
const char * BCHandlerTypeToString(BCHandlerType handler_type)
Converts a BCHandlerType enum to its string representation.
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
PetscErrorCode DualMonitorDestroy(void **ctx)
Destroys the DualMonitorCtx.
PetscBool IsStatisticsConsoleSnapshotEnabled(const struct SimCtx *simCtx)
Reports whether the periodic statistics console snapshot is enabled.
PetscErrorCode LOG_INTERPOLATION_ERROR(UserCtx *user)
Logs the interpolation error between the analytical and computed solutions.
PetscBool ShouldEmitPeriodicParticleConsoleSnapshot(const SimCtx *simCtx, PetscInt completed_step)
Returns whether a particle console snapshot should be emitted for the.
const char * BCFaceToString(BCFace face)
Returns the canonical log token for a boundary-face enum value.
PetscErrorCode FreeAllowedFunctions(char **funcs, PetscInt n)
Free an array previously returned by LoadAllowedFunctionsFromFile().
PetscBool IsParticleConsoleSnapshotEnabled(const SimCtx *simCtx)
Returns whether periodic particle console snapshots are enabled.
PetscErrorCode print_log_level(void)
Prints the current logging level to the console.
PetscErrorCode EmitParticleConsoleSnapshot(UserCtx *user, SimCtx *simCtx, PetscInt step)
Emits one particle console snapshot into the main solver log.
PetscErrorCode ProfilingFinalize(SimCtx *simCtx)
the profiling excercise and build a profiling summary which is then printed to a log file.
PetscErrorCode LoadAllowedFunctionsFromFile(const char filename[], char ***funcsOut, PetscInt *nOut)
Load function names from a text file.
PetscErrorCode EmitStatisticsConsoleSnapshot(UserCtx *user, const struct SimCtx *simCtx, PetscInt step)
Emits one console snapshot of window progress.
void PrintProgressBar(PetscInt step, PetscInt startStep, PetscInt totalSteps, PetscReal currentTime)
Prints a progress bar to the console.
PetscErrorCode RuntimeMemoryLogSample(SimCtx *simCtx, PetscInt step, const char *event, const char *reason)
Append a reduced runtime memory sample to the configured memory log.
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
PetscErrorCode ProfilingLogTimestepSummary(SimCtx *simCtx, PetscInt step)
Logs the performance summary for the current timestep and resets timers.
PetscErrorCode LOG_FACE_DISTANCES(PetscReal *d)
Prints the signed distances to each face of the cell.
PetscErrorCode LOG_PARTICLE_FIELDS(UserCtx *user, PetscInt printInterval)
Prints particle fields in a table that automatically adjusts its column widths.
void _ProfilingEnd(const char *func_name)
Internal profiling hook invoked by PROFILE_FUNCTION_END.
const char * BCTypeToString(BCType type)
Returns the canonical log token for a boundary mathematical type.
PetscErrorCode CalculateAdvancedParticleMetrics(UserCtx *user)
Computes advanced particle statistics and stores them in SimCtx.
const char * ParticleLocationStatusToString(ParticleLocationStatus level)
A function that outputs the name of the current level in the ParticleLocation enum.
PetscErrorCode LOG_SCATTER_METRICS(UserCtx *user)
Logs particle-to-grid scatter verification metrics for the prescribed scalar truth path.
PetscErrorCode LOG_SOLUTION_CONVERGENCE(SimCtx *simCtx)
Logs physical solution-convergence metrics once per completed timestep.
PetscErrorCode LOG_CONTINUITY_METRICS(UserCtx *user)
Logs continuity metrics for a single block to a file.
PetscErrorCode LOG_FIELD_ANATOMY(UserCtx *user, FieldId field_id, const char *stage_name)
Logs the anatomy of a specified field at key boundary locations, respecting the solver's specific gri...
PetscErrorCode LOG_SEARCH_METRICS(UserCtx *user)
Writes compact runtime search metrics to CSV and optionally to console.
const char * InitialConditionModeToString(InitialConditionMode mode)
Convert an initial-condition mode to a string representation.
PetscErrorCode ProfilingInitialize(SimCtx *simCtx)
Initializes the custom profiling system using configuration from SimCtx.
@ LOG_INFO
Informational messages about program execution.
const char * LESModelToString(LESModelType LESFlag)
Returns the canonical log token for an LES model selector.
PetscErrorCode LOG_CELL_VERTICES(const Cell *cell, PetscMPIInt rank)
Prints the coordinates of a cell's vertices.
PetscErrorCode ProfilingResetTimestepCounters(void)
Resets per-timestep profiling counters for the next solver step.
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.
void _ProfilingStart(const char *func_name)
Internal profiling hook invoked by PROFILE_FUNCTION_BEGIN.
Context for a dual-purpose KSP monitor.
PetscErrorCode InitializeSolutionConvergenceState(SimCtx *simCtx)
Allocates any runtime storage required by solution-convergence logging.
Per-window PETSc accumulator storage and pointwise application.
Vec weight
Per-point valid weight.
Vec * mean
One per field, matching that field's layout.
PetscErrorCode PicurvWindowStorageCreate(UserCtx *user, const PicurvWindowDefinition *definition, PicurvWindowStorage *storage)
Allocates the accumulator state one window owns on one block.
Vec * m2
One per field; NULL when no second moment was requested.
Vec count
Per-point accepted sample count.
PetscErrorCode PicurvWindowStorageDestroy(PicurvWindowStorage *storage)
Releases accumulator state previously created for one window.
Independent accumulator state for one window on one block.
Window lifecycle, scheduling, and weighting for the field-statistics pipeline.
PicurvWindowFieldRequest fields[16]
PetscErrorCode FieldStatisticsUpdateWindows(struct SimCtx *simCtx, PetscInt step, PetscReal time)
Offers one completed state to every configured window.
PetscReal end_time
Requested end; ignored when bounded is false.
PicurvCadenceKind cadence_kind
PetscInt step_cadence
Used when cadence_kind is step; must be positive.
#define PICURV_WINDOW_NAME_LENGTH
Maximum stored length of a window name, including the terminator.
PetscErrorCode PicurvWindowInit(PicurvWindow *window, const PicurvWindowDefinition *definition)
Validates a definition and initializes a window to the pending state.
PetscBool want_second
Also keep the centered second moment.
PetscBool bounded
False for an open-ended window.
PetscInt field_id
Catalogued Eulerian field identity.
@ PICURV_WEIGHTING_SAMPLE
Equal weight per accepted state.
@ PICURV_CADENCE_STEP
Every n completed steps from activation.
PicurvWeighting weighting
Runtime state of one window.
The scientifically immutable definition of one window.
static PetscErrorCode TestParticleConsoleSnapshotCadence(void)
Tests periodic particle console snapshot enablement and cadence.
static PetscErrorCode SetUniformScalarField(UserCtx *user, Vec field, PetscReal value)
Fills one scalar field with a uniform constant state.
static PetscErrorCode TestFieldAnatomyLogging(void)
Tests stdout field-anatomy logging on the corrected production-like DM fixture.
static PetscErrorCode LogGetColumnText(const char *header, const char *row, const char *column_name, char *value, size_t value_len)
Extracts one pipe-delimited log cell as text by header name.
static PetscErrorCode InvokeParticleConsoleSnapshot(UserCtx *user, SimCtx *simCtx, void *ctx)
Adapts EmitParticleConsoleSnapshot() to the generic stdout-capture callback shape.
static PetscErrorCode TestStatisticsConsoleSnapshotLogging(void)
Tests statistics console snapshot content, and its silence when disabled.
static PetscErrorCode TestParticleConsoleSnapshotLogging(void)
Tests console snapshot logging against the public periodic-snapshot helper.
static PetscErrorCode CsvGetColumnText(const char *header, const char *row, const char *column_name, char *value, size_t value_len)
Extracts one CSV cell as text by header name.
static PetscErrorCode TestStatisticsConsoleSnapshotCadence(void)
Tests periodic statistics console snapshot enablement and cadence.
static PetscErrorCode CaptureLoggingOutput(UserCtx *user, SimCtx *simCtx, CapturedLoggingFn fn, void *ctx, char *captured, size_t captured_len)
Captures stdout emitted by one logging helper into a temporary file-backed buffer.
static PetscErrorCode ReadCsvHeaderAndRow(const char *path, PetscInt row_index, char *header, size_t header_len, char *row, size_t row_len)
Reads the CSV header and the requested 1-based data row from a text file.
static PetscErrorCode TestGetLogLevelFromEnvironment(void)
Tests that log level selection honors the environment variable.
int main(int argc, char **argv)
Runs the unit-logging PETSc test binary.
static PetscErrorCode TestLoggingContinuityAndFieldDiagnostics(void)
Tests continuity, min/max, and anatomy logging helpers on minimal runtime fixtures.
static PetscErrorCode AssertVecsIdentical(Vec expected, Vec actual, const char *context)
Asserts two accumulator vectors are bit-identical.
static PetscErrorCode TestPeriodicSinusoidalMeanKE(void)
Regression test: volume-averaged mean KE of a sinusoidal field in a fully periodic domain.
PetscErrorCode(* CapturedLoggingFn)(UserCtx *user, SimCtx *simCtx, void *ctx)
static PetscErrorCode TestSolutionConvergenceStatisticalLogging(void)
Tests statistical solution-convergence sliding-window metrics.
static PetscErrorCode SetUniformPressure(UserCtx *user, PetscReal value)
Sets the pressure field to a uniform value across the owned range.
static PetscErrorCode AssertFileNotContains(const char *path, const char *needle, const char *context)
Asserts that one text file does not contain an excluded substring.
static PetscErrorCode AccumulateAtConsoleCadence(SimCtx *simCtx, UserCtx *user, PicurvWindow *window, PicurvWindowStorage *storage, const PicurvWindowDefinition *definition, PetscInt console_frequency)
Drives one accumulation run at a given console cadence, in the runloop's order.
static PicurvWindowDefinition LoggingStatisticsDefinition(void)
Builds the window definition backing this suite's statistics console fixture.
static PetscErrorCode InvokeFieldAnatomyLog(UserCtx *user, SimCtx *simCtx, void *ctx)
Adapts LOG_FIELD_ANATOMY() to the generic stdout-capture callback shape.
static PetscErrorCode TestSolutionConvergenceMeansExcludeGhostLayers(void)
Regression test: convergence observables ignore the ghost layers of a walled box.
static PetscErrorCode TestSolutionConvergencePeriodicLogging(void)
Tests periodic solution-convergence warmup and phase-aligned reference reuse.
static PetscErrorCode TestStringConversionHelpers(void)
Tests string-conversion helpers for configured enums and unknown values.
static PetscErrorCode SetSinusoidalVZField(UserCtx *user, Vec field, PetscReal v_amp, PetscReal w_const)
Fills one Cartesian velocity field with u=0, v=v_amp*sin(2π*k/km), w=w_const.
static PetscErrorCode TestLoggingFileParsingAndFormattingHelpers(void)
Tests logging-side file parsing, helper formatting, and progress utilities.
static PetscErrorCode TestAllowedFunctionsFilter(void)
Tests the function allow-list filter used by the logging layer.
static PetscErrorCode TestInterpolationErrorLogging(void)
Tests interpolation-error logging against an analytically matched particle field.
static PetscErrorCode SeedLoggingParticleFixture(SimCtx **simCtx_out, UserCtx **user_out)
Creates a small particle-bearing runtime fixture used by logging tests.
static PetscErrorCode TestScatterMetricsLogging(void)
Tests file-backed scatter metrics logging against a fully occupied constant field.
static PetscErrorCode TestParticleMetricsLogging(void)
Tests file-backed particle metrics logging after derived metrics are computed.
static PetscErrorCode CsvGetColumnReal(const char *header, const char *row, const char *column_name, PetscReal *value_out)
Extracts one CSV cell as a real by header name.
static PetscErrorCode TestSearchMetricsLogging(void)
Tests file-backed search metrics logging with the compact CSV contract.
static PetscErrorCode InvokeStatisticsConsoleSnapshot(UserCtx *user, SimCtx *simCtx, void *ctx)
Adapts EmitStatisticsConsoleSnapshot() to the generic stdout-capture callback shape.
static PetscErrorCode TestParticleFieldTableLogging(void)
Tests stdout particle-table logging on a production-like swarm fixture.
static PetscErrorCode CsvFindColumnIndex(const char *header, const char *column_name, PetscInt *index_out)
Returns the zero-based column index for one CSV header field.
static PetscErrorCode TestSolutionConvergenceDisabled(void)
Verifies -solution_convergence_enabled=false suppresses the convergence writer.
static PetscErrorCode LogFindColumnIndex(const char *header, const char *column_name, PetscInt *index_out)
Returns the zero-based column index for one pipe-delimited header field.
static PetscErrorCode SetUniformVelocityField(UserCtx *user, Vec field, PetscReal ux, PetscReal uy, PetscReal uz)
Fills one Cartesian velocity field with a uniform constant state.
static PetscErrorCode ReadLogHeaderAndRow(const char *path, PetscInt row_index, char *header, size_t header_len, char *row, size_t row_len)
Reads the column header and the requested 1-based data row from a pipe-delimited solution-convergence...
static PetscErrorCode AssertFileContains(const char *path, const char *needle, const char *context)
Asserts that one text file contains a required substring.
static PetscErrorCode CsvGetColumnInt(const char *header, const char *row, const char *column_name, PetscInt *value_out)
Extracts one CSV cell as an integer by header name.
static PetscErrorCode LogGetColumnReal(const char *header, const char *row, const char *column_name, PetscReal *value_out)
Extracts one pipe-delimited log cell as a real by header name.
static PetscErrorCode TestSolutionConvergenceSteadyLogging(void)
Tests steady solution-convergence log output, IBM masking, and gauge-invariant pressure drift.
static PetscErrorCode TestProfilingLifecycleHelpers(void)
Tests profiling helper lifecycle logging for timestep and final-summary outputs.
static PetscErrorCode LogGetColumnInt(const char *header, const char *row, const char *column_name, PetscInt *value_out)
Extracts one pipe-delimited log cell as an integer by header name.
static PetscErrorCode TestConsoleCadenceDoesNotChangeAccumulation(void)
Tests that the console cadence has no effect on any accumulated result.
static PetscErrorCode InvokeParticleFieldLog(UserCtx *user, SimCtx *simCtx, void *ctx)
Adapts LOG_PARTICLE_FIELDS() to the generic stdout-capture callback shape.
static PetscErrorCode TestRuntimeMemoryLogHelpers(void)
Tests runtime memory log header, step rows, final rows, and disabled mode.
PetscErrorCode PicurvMakeTempDir(char *path, size_t path_len)
Creates a unique temporary directory for one test case.
PetscErrorCode PicurvCreateMinimalContexts(SimCtx **simCtx_out, UserCtx **user_out, PetscInt mx, PetscInt my, PetscInt mz)
Builds minimal SimCtx and UserCtx fixtures for C unit tests.
PetscErrorCode PicurvAssertRealNear(PetscReal expected, PetscReal actual, PetscReal tol, const char *context)
Asserts that two real values agree within tolerance.
PetscErrorCode PicurvDestroyMinimalContexts(SimCtx **simCtx_ptr, UserCtx **user_ptr)
Destroys minimal SimCtx/UserCtx fixtures and all owned PETSc objects.
PetscErrorCode PicurvCreateMinimalContextsWithPeriodicity(SimCtx **simCtx_out, UserCtx **user_out, PetscInt mx, PetscInt my, PetscInt mz, PetscBool x_periodic, PetscBool y_periodic, PetscBool z_periodic)
Builds minimal SimCtx and UserCtx fixtures for C unit tests with configurable periodicity.
PetscErrorCode PicurvCreateSwarmPair(UserCtx *user, PetscInt nlocal, const char *post_field_name)
Creates matched solver and post-processing swarms for tests.
PetscErrorCode PicurvRunTests(const char *suite_name, const PicurvTestCase *cases, size_t case_count)
Runs a named C test suite and prints pass/fail progress markers.
PetscErrorCode PicurvAssertFileExists(const char *path, const char *context)
Asserts that a filesystem path exists as a readable file.
PetscErrorCode PicurvAssertIntEqual(PetscInt expected, PetscInt actual, const char *context)
Asserts that two integer values are equal.
PetscErrorCode PicurvPopulateIdentityMetrics(UserCtx *user)
Populates identity metric vectors on the minimal grid fixture.
PetscErrorCode PicurvAssertBool(PetscBool value, const char *context)
Asserts that one boolean condition is true.
PetscErrorCode PicurvRemoveTempDir(const char *path)
Recursively removes a temporary directory created by PicurvMakeTempDir.
Shared declarations for the PICurv C test fixture and assertion layer.
Named test case descriptor consumed by PicurvRunTests.
PetscInt fieldStatisticsWindowCount
PetscBool profilingFinalSummary
char profilingTimestepFile[PETSC_MAX_PATH_LEN]
PetscInt64 searchLocatedCount
PetscInt statisticsConsoleOutputFreq
PetscInt64 searchLostCount
@ PARTICLE_INIT_VOLUME
Random volumetric distribution across the domain.
PetscBool runtimeMemoryLogEnabled
Enable the rank-reduced runtime memory log.
PetscInt64 boundaryClampCount
PetscInt particlesLostLastStep
PetscInt64 traversalStepsSum
@ BC_HANDLER_PERIODIC_DRIVEN_CONSTANT_FLUX
PetscReal poissonSourceImbalance
PetscInt64 searchPopulation
PetscBool solutionConvergenceEnabled
char runtimeMemoryLogFile[PETSC_MAX_PATH_LEN]
File name written under log_dir.
PetscBool runtimeMemoryLogStarted
True after rank 0 writes the log header.
char profilingTimestepMode[32]
PetscBool fieldStatisticsEnabled
@ MOMENTUM_SOLVER_EXPLICIT_RK
@ MOMENTUM_SOLVER_NEWTON_KRYLOV
PetscInt solutionConvergencePeriodSteps
PetscInt64 bboxGuessFallbackCount
VerificationScalarConfig verificationScalar
char analysis_dir[PETSC_MAX_PATH_LEN]
PetscInt64 bboxGuessSuccessCount
struct PicurvWindow * fieldStatisticsWindows
char log_dir[PETSC_MAX_PATH_LEN]
PetscInt64 maxParticlePassDepth
PetscInt64 maxTraversalSteps
PetscBool runtimeMemoryLogHasPrevious
True after the first process-memory sample.
char ** profilingSelectedFuncs
PetscInt solutionConvergenceWindowSteps
PetscInt particlesLostCumulative
PetscInt nProfilingSelectedFuncs
PetscInt particlesMigratedLastStep
struct PicurvWindowStorage * fieldStatisticsStorage
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
InitialConditionMode
Selects the algorithm used to populate a fresh Eulerian velocity field.
@ IC_MODE_CONSTANT_CARTESIAN
@ IC_MODE_CONSTANT_STREAMWISE
PetscInt particleConsoleOutputFreq
SearchMetricsState searchMetrics
PetscInt migrationPassesLastStep
@ SOLUTION_CONVERGENCE_PERIODIC_DETERMINISTIC
@ SOLUTION_CONVERGENCE_STATISTICAL_STEADY
@ SOLUTION_CONVERGENCE_STEADY_DETERMINISTIC
SolutionConvergenceMode solutionConvergenceMode
PetscInt64 searchAttempts
PetscInt64 maxTraversalFailCount
Cmpnts vertices[8]
Coordinates of the eight vertices of the cell.
PetscReal particleLoadImbalance
Defines the vertices of a single hexahedral grid cell.
A 3D point or vector with PetscScalar components.
The master context for the entire simulation.
User-defined context containing data specific to a single computational grid level.