PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions
logging.h File Reference

Logging utilities and macros for PETSc-based applications. More...

#include <petsc.h>
#include <stdlib.h>
#include <string.h>
#include <petscsys.h>
#include <ctype.h>
#include "variables.h"
#include "statistics_window.h"
#include "Boundaries.h"
Include dependency graph for logging.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  DualMonitorCtx
 Context for a dual-purpose KSP monitor. More...
 

Macros

#define LOCAL   0
 Logging scope definitions for controlling message output.
 
#define GLOBAL   1
 Scope for global logging across all processes.
 
#define LOG(scope, level, fmt, ...)
 Logging macro for PETSc-based applications with scope control.
 
#define LOG_DEFAULT(level, fmt, ...)
 Default logging macro for PETSc-based applications.
 
#define LOG_SYNC(scope, level, fmt, ...)
 Logging macro for PETSc-based applications with scope control, using synchronized output across processes.
 
#define LOG_SYNC_DEFAULT(level, fmt, ...)
 Default synchronized logging macro for PETSc-based applications.
 
#define LOG_ALLOW(scope, level, fmt, ...)
 Logging macro that checks both the log level and whether the calling function is in the allowed-function list before printing.
 
#define LOG_ALLOW_SYNC(scope, level, fmt, ...)
 Synchronized logging macro that checks both the log level and whether the calling function is in the allow-list.
 
#define LOG_LOOP_ALLOW(scope, level, iterVar, interval, fmt, ...)
 Logs a message inside a loop, but only every interval iterations.
 
#define LOG_LOOP_ALLOW_EXACT(scope, level, var, val, fmt, ...)
 Logs a custom message if a variable equals a specific value.
 
#define LOG_ARRAY_ELEMENT_ALLOW(scope, level, arr, length, idx, fmt)
 Logs a single element of an array, given an index.
 
#define LOG_ARRAY_SUBRANGE_ALLOW(scope, level, arr, length, start, end, fmt)
 Logs a consecutive subrange of an array.
 
#define PROFILE_FUNCTION_BEGIN    _ProfilingStart(__FUNCT__)
 Marks the beginning of a profiled code block (typically a function).
 
#define PROFILE_FUNCTION_END    _ProfilingEnd(__FUNCT__)
 Marks the end of a profiled code block.
 

Enumerations

enum  LogLevel {
  LOG_ERROR = 0 , LOG_WARNING , LOG_INFO , LOG_DEBUG ,
  LOG_TRACE , LOG_VERBOSE
}
 Enumeration of logging levels. More...
 

Functions

LogLevel get_log_level ()
 Retrieves the current logging level from the environment variable LOG_LEVEL.
 
PetscErrorCode print_log_level (void)
 Prints the current logging level to the console.
 
void set_allowed_functions (const char **functionList, int count)
 Sets the global list of function names that are allowed to log.
 
PetscBool is_function_allowed (const char *functionName)
 Checks if a given function is in the allow-list.
 
PetscErrorCode LOG_CELL_VERTICES (const Cell *cell, PetscMPIInt rank)
 Prints the coordinates of a cell's vertices.
 
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.
 
PetscBool IsParticleConsoleSnapshotEnabled (const SimCtx *simCtx)
 Returns whether periodic particle console snapshots are enabled.
 
PetscBool ShouldEmitPeriodicParticleConsoleSnapshot (const SimCtx *simCtx, PetscInt completed_step)
 Returns whether a particle console snapshot should be emitted for the.
 
PetscErrorCode EmitParticleConsoleSnapshot (UserCtx *user, SimCtx *simCtx, PetscInt step)
 Emits one particle console snapshot into the main solver log.
 
PetscBool IsStatisticsConsoleSnapshotEnabled (const struct SimCtx *simCtx)
 Reports whether the periodic statistics console snapshot is enabled.
 
PetscBool ShouldEmitPeriodicStatisticsConsoleSnapshot (const struct SimCtx *simCtx, PetscInt completed_step)
 Reports whether a completed step falls on the console snapshot cadence.
 
PetscErrorCode EmitStatisticsConsoleSnapshot (UserCtx *user, const struct SimCtx *simCtx, PetscInt step)
 Emits one console snapshot of window progress.
 
PetscErrorCode FreeAllowedFunctions (char **funcs, PetscInt n)
 Free an array previously returned by LoadAllowedFunctionsFromFile().
 
PetscErrorCode LoadAllowedFunctionsFromFile (const char filename[], char ***funcsOut, PetscInt *nOut)
 Load function names from a text file.
 
const char * BCFaceToString (BCFace face)
 Returns the canonical log token for a boundary-face enum value.
 
const char * InitialConditionModeToString (InitialConditionMode mode)
 Convert an initial-condition mode to a string representation.
 
const char * FlowDirectionToString (FlowDirection fd)
 Convert a FlowDirection enum value to its YAML token string.
 
const char * ParticleInitializationToString (ParticleInitializationType ParticleInitialization)
 Returns the canonical log token for a particle-initialization mode.
 
const char * LESModelToString (LESModelType LESFlag)
 Returns the canonical log token for an LES model selector.
 
const char * MomentumSolverTypeToString (MomentumSolverType SolverFlag)
 Returns the canonical log token for a momentum-solver selector.
 
const char * BCTypeToString (BCType type)
 Returns the canonical log token for a boundary mathematical type.
 
const char * BCHandlerTypeToString (BCHandlerType handler_type)
 Converts a BCHandlerType enum to its string representation.
 
PetscErrorCode DualKSPMonitor (KSP ksp, PetscInt it, PetscReal rnorm, void *ctx)
 A custom KSP monitor that logs to a file and optionally to the console.
 
PetscErrorCode DualMonitorDestroy (void **ctx)
 Destroys the DualMonitorCtx.
 
PetscErrorCode LOG_CONTINUITY_METRICS (UserCtx *user)
 Logs continuity metrics for a single block to a file.
 
PetscErrorCode LOG_SOLUTION_CONVERGENCE (SimCtx *simCtx)
 Logs physical solution-convergence metrics once per completed timestep.
 
const char * ParticleLocationStatusToString (ParticleLocationStatus level)
 A function that outputs the name of the current level in the ParticleLocation enum.
 
void PrintProgressBar (PetscInt step, PetscInt startStep, PetscInt totalSteps, PetscReal currentTime)
 Prints a progress bar to the console.
 
PetscErrorCode ProfilingInitialize (SimCtx *simCtx)
 Initializes the custom profiling system using configuration from SimCtx.
 
PetscErrorCode ProfilingResetTimestepCounters (void)
 Resets per-timestep profiling counters for the next solver step.
 
PetscErrorCode ProfilingLogTimestepSummary (SimCtx *simCtx, PetscInt step)
 Logs the performance summary for the current timestep and resets timers.
 
PetscErrorCode RuntimeMemoryLogSample (SimCtx *simCtx, PetscInt step, const char *event, const char *reason)
 Append a reduced runtime memory sample to the configured memory log.
 
PetscErrorCode ProfilingFinalize (SimCtx *simCtx)
 the profiling excercise and build a profiling summary which is then printed to a log file.
 
void _ProfilingStart (const char *func_name)
 Internal profiling hook invoked by PROFILE_FUNCTION_BEGIN.
 
void _ProfilingEnd (const char *func_name)
 Internal profiling hook invoked by PROFILE_FUNCTION_END.
 
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.
 
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 grid and variable architecture.
 
PetscErrorCode LOG_CORNER_FIELD_ANATOMY (UserCtx *user, FieldId corner_field_id, const char *stage_name)
 Logs the node-layout anatomy of the transient center-to-corner interpolation field.
 
PetscErrorCode LOG_INTERPOLATION_ERROR (UserCtx *user)
 Logs the interpolation error between the analytical and computed solutions.
 
PetscErrorCode LOG_SCATTER_METRICS (UserCtx *user)
 Logs particle-to-grid scatter verification metrics for the prescribed scalar truth path.
 
PetscErrorCode ResetSearchMetrics (SimCtx *simCtx)
 Resets the aggregate per-timestep search instrumentation counters.
 
PetscErrorCode CalculateAdvancedParticleMetrics (UserCtx *user)
 Computes advanced particle statistics and stores them in SimCtx.
 
PetscErrorCode LOG_SEARCH_METRICS (UserCtx *user)
 Writes compact runtime search metrics to CSV and optionally to console.
 
PetscErrorCode LOG_PARTICLE_METRICS (UserCtx *user, const char *stageName)
 Logs particle swarm metrics, adapting its behavior based on a boolean flag in SimCtx.
 

Detailed Description

Logging utilities and macros for PETSc-based applications.

This header defines logging levels, scopes, and macros for consistent logging throughout the application. It provides functions to retrieve the current logging level and macros to simplify logging with scope control.

Definition in file logging.h.


Data Structure Documentation

◆ DualMonitorCtx

struct DualMonitorCtx

Context for a dual-purpose KSP monitor.

This struct holds a file viewer for unconditional logging and a boolean flag to enable/disable optional logging to the console.

Definition at line 56 of file logging.h.

Data Fields
FILE * file_handle
PetscBool log_to_console
PetscReal bnorm
PetscInt step
PetscInt block_id

Macro Definition Documentation

◆ LOCAL

#define LOCAL   0

Logging scope definitions for controlling message output.

  • LOCAL: Logs on the current process using MPI_COMM_SELF.
  • GLOBAL: Logs across all processes using MPI_COMM_WORLD. Scope for local logging on the current process.

Definition at line 45 of file logging.h.

◆ GLOBAL

#define GLOBAL   1

Scope for global logging across all processes.

Definition at line 46 of file logging.h.

◆ LOG

#define LOG (   scope,
  level,
  fmt,
  ... 
)
Value:
do { \
/* Determine the MPI communicator based on the scope */ \
MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
/* Check if the log level is within the allowed range */ \
if ((int)(level) <= (int)get_log_level()) { \
/* Print the message to the specified communicator */ \
PetscPrintf(comm, fmt, ##__VA_ARGS__); \
} \
} while (0)
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:45
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:87

Logging macro for PETSc-based applications with scope control.

This macro provides a convenient way to log messages with different scopes (LOCAL or GLOBAL) and severity levels. It utilizes PETSc's PetscPrintf function for message output.

Parameters
scopeSpecifies the logging scope:
  • LOCAL: Logs on the current process using MPI_COMM_SELF.
  • GLOBAL: Logs on all processes using MPI_COMM_WORLD.
levelThe severity level of the message (e.g., LOG_INFO, LOG_ERROR).
fmtThe format string for the message (similar to printf).
...Additional arguments for the format string (optional).

Example usage: LOG(LOCAL, LOG_ERROR, "An error occurred at index %ld.\n", idx); LOG(GLOBAL, LOG_INFO, "Grid size: %ld x %ld x %ld.\n", nx, ny, nz);

Definition at line 84 of file logging.h.

85 { \
86 /* Determine the MPI communicator based on the scope */ \
87 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
88 /* Check if the log level is within the allowed range */ \
89 if ((int)(level) <= (int)get_log_level()) { \
90 /* Print the message to the specified communicator */ \
91 PetscPrintf(comm, fmt, ##__VA_ARGS__); \
92 } \
93 } while (0)

◆ LOG_DEFAULT

#define LOG_DEFAULT (   level,
  fmt,
  ... 
)
Value:
do { \
/* Set the communicator to global (MPI_COMM_WORLD) by default */ \
MPI_Comm comm = MPI_COMM_WORLD; \
/* Check if the log level is within the allowed range */ \
if ((int)(level) <= (int)get_log_level()) { \
/* Print the message using PetscPrintf with the global communicator */ \
PetscPrintf(comm, fmt, ##__VA_ARGS__); \
} \
} while (0)

Default logging macro for PETSc-based applications.

This macro simplifies logging by defaulting the scope to GLOBAL (i.e., MPI_COMM_WORLD) and providing a convenient interface for common logging needs.

Parameters
levelThe severity level of the message (e.g., LOG_ERROR, LOG_INFO).
fmtThe format string for the log message (similar to printf).
...Additional arguments for the format string (optional).

Example usage: LOG_DEFAULT(LOG_ERROR, "Error occurred at index %ld.\n", idx); LOG_DEFAULT(LOG_INFO, "Grid size: %ld x %ld x %ld.\n", nx, ny, nz);

Note
  • By default, this macro logs across all MPI processes using MPI_COMM_WORLD.
  • If finer control (e.g., local logging) is required, use the more general LOG macro.
  • The log level is filtered based on the value returned by get_log_level().

Definition at line 115 of file logging.h.

116 { \
117 /* Set the communicator to global (MPI_COMM_WORLD) by default */ \
118 MPI_Comm comm = MPI_COMM_WORLD; \
119 /* Check if the log level is within the allowed range */ \
120 if ((int)(level) <= (int)get_log_level()) { \
121 /* Print the message using PetscPrintf with the global communicator */ \
122 PetscPrintf(comm, fmt, ##__VA_ARGS__); \
123 } \
124 } while (0)

◆ LOG_SYNC

#define LOG_SYNC (   scope,
  level,
  fmt,
  ... 
)
Value:
do { \
/* Determine the MPI communicator based on the scope */ \
MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
/* Check if the log level is within the allowed range */ \
if ((int)(level) <= (int)get_log_level()) { \
/* Synchronized print (collective) on the specified communicator */ \
PetscSynchronizedPrintf(comm, fmt, ##__VA_ARGS__); \
/* Ensure all ranks have finished printing before continuing */ \
PetscSynchronizedFlush(comm, PETSC_STDOUT); \
} \
} while (0)

Logging macro for PETSc-based applications with scope control, using synchronized output across processes.

This macro uses PetscSynchronizedPrintf and PetscSynchronizedFlush to ensure messages from different ranks are printed in a synchronized (rank-by-rank) manner, preventing interleaved outputs.

Parameters
scopeSpecifies the logging scope:
  • LOCAL: Logs on the current process using MPI_COMM_SELF.
  • GLOBAL: Logs on all processes using MPI_COMM_WORLD.
levelThe severity level of the message (e.g., LOG_INFO, LOG_ERROR).
fmtThe format string for the message (similar to printf).
...Additional arguments for the format string (optional).

Example usage: LOG_SYNC(LOCAL, LOG_ERROR, "An error occurred at index %ld.\n", idx); LOG_SYNC(GLOBAL, LOG_INFO, "Synchronized info: rank = %ld.\n", rank);

Definition at line 145 of file logging.h.

146 { \
147 /* Determine the MPI communicator based on the scope */ \
148 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
149 /* Check if the log level is within the allowed range */ \
150 if ((int)(level) <= (int)get_log_level()) { \
151 /* Synchronized print (collective) on the specified communicator */ \
152 PetscSynchronizedPrintf(comm, fmt, ##__VA_ARGS__); \
153 /* Ensure all ranks have finished printing before continuing */ \
154 PetscSynchronizedFlush(comm, PETSC_STDOUT); \
155 } \
156 } while (0)

◆ LOG_SYNC_DEFAULT

#define LOG_SYNC_DEFAULT (   level,
  fmt,
  ... 
)
Value:
do { \
if ((int)(level) <= (int)get_log_level()) { \
PetscSynchronizedPrintf(MPI_COMM_WORLD, fmt, ##__VA_ARGS__); \
PetscSynchronizedFlush(MPI_COMM_WORLD, PETSC_STDOUT); \
} \
} while (0)

Default synchronized logging macro for PETSc-based applications.

This macro simplifies logging by defaulting the scope to GLOBAL (i.e., MPI_COMM_WORLD) and provides synchronized output across all processes.

Parameters
levelThe severity level of the message (e.g., LOG_ERROR, LOG_INFO).
fmtThe format string for the log message (similar to printf).
...Additional arguments for the format string (optional).

Example usage: LOG_SYNC_DEFAULT(LOG_ERROR, "Error at index %ld.\n", idx); LOG_SYNC_DEFAULT(LOG_INFO, "Process rank: %ld.\n", rank);

Note
  • By default, this macro logs across all MPI processes using MPI_COMM_WORLD.
  • If local (per-process) logging is required, use the more general LOG_SYNC macro.
  • The log level is filtered based on the value returned by get_log_level().

Definition at line 178 of file logging.h.

179 { \
180 if ((int)(level) <= (int)get_log_level()) { \
181 PetscSynchronizedPrintf(MPI_COMM_WORLD, fmt, ##__VA_ARGS__); \
182 PetscSynchronizedFlush(MPI_COMM_WORLD, PETSC_STDOUT); \
183 } \
184 } while (0)

◆ LOG_ALLOW

#define LOG_ALLOW (   scope,
  level,
  fmt,
  ... 
)
Value:
do { \
MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
if ((int)(level) <= (int)get_log_level() && is_function_allowed(__func__)) { \
PetscPrintf(comm, "[%s] " fmt, __func__, ##__VA_ARGS__); \
} \
} while (0)
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:186

Logging macro that checks both the log level and whether the calling function is in the allowed-function list before printing.

Useful for selective, per-function logging.

Parameters
scopeSpecifies the logging scope (LOCAL or GLOBAL).
levelThe severity level of the message (e.g., LOG_INFO, LOG_ERROR).
fmtThe format string for the message (similar to printf).
...Additional arguments for the format string (optional).

Example usage: LOG_ALLOW(LOCAL, LOG_DEBUG, "Debugging info in function: %s\n", func);

Definition at line 200 of file logging.h.

201 { \
202 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
203 if ((int)(level) <= (int)get_log_level() && is_function_allowed(__func__)) { \
204 PetscPrintf(comm, "[%s] " fmt, __func__, ##__VA_ARGS__); \
205 } \
206 } while (0)

◆ LOG_ALLOW_SYNC

#define LOG_ALLOW_SYNC (   scope,
  level,
  fmt,
  ... 
)
Value:
do { \
/* ------------------------------------------------------------------ */ \
/* Validate scope and pick communicator *before* any early exits. */ \
/* ------------------------------------------------------------------ */ \
MPI_Comm _comm; \
if ((scope) == LOCAL) _comm = MPI_COMM_SELF; \
else if ((scope) == GLOBAL) _comm = MPI_COMM_WORLD; \
else { \
fprintf(stderr, "LOG_ALLOW_SYNC ERROR: invalid scope (%d) at %s:%d\n", \
(scope), __FILE__, __LINE__); \
MPI_Abort(MPI_COMM_WORLD, 1); \
} \
\
/* ------------------------------------------------------------------ */ \
/* Decide whether *this* rank should actually print. */ \
/* ------------------------------------------------------------------ */ \
PetscBool _doPrint = \
is_function_allowed(__func__) && ((int)(level) <= (int)get_log_level()); \
\
if (_doPrint) { \
PetscSynchronizedPrintf(_comm, "[%s] " fmt, __func__, ##__VA_ARGS__); \
} \
\
/* ------------------------------------------------------------------ */ \
/* ALL ranks call the flush, even if they printed nothing. */ \
/* ------------------------------------------------------------------ */ \
PetscSynchronizedFlush(_comm, PETSC_STDOUT); \
} while (0)
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:46

Synchronized logging macro that checks both the log level and whether the calling function is in the allow-list.

This macro uses PetscSynchronizedPrintf and PetscSynchronizedFlush to ensure messages from different ranks are printed in a rank-ordered fashion (i.e., to avoid interleaving). It also filters out messages if the current function is not in the allow-list (is_function_allowed(__func__)) or the requested log level is higher than get_log_level().

Parameters
scopeEither LOCAL (MPI_COMM_SELF) or GLOBAL (MPI_COMM_WORLD).
levelOne of LOG_ERROR, LOG_WARNING, LOG_INFO, LOG_DEBUG.
fmtA printf-style format string (e.g., "Message: %ld\n").
...Variadic arguments to fill in fmt.

Example usage:

LOG_ALLOW_SYNC(LOCAL, LOG_DEBUG, "Debug info: rank = %ld\n", rank);
LOG_ALLOW_SYNC(GLOBAL, LOG_INFO, "Synchronized info in %s\n", __func__);
#define LOG_ALLOW_SYNC(scope, level, fmt,...)
Synchronized logging macro that checks both the log level and whether the calling function is in the ...
Definition logging.h:253
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:31
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:32

Definition at line 253 of file logging.h.

254 { \
255 /* ------------------------------------------------------------------ */ \
256 /* Validate scope and pick communicator *before* any early exits. */ \
257 /* ------------------------------------------------------------------ */ \
258 MPI_Comm _comm; \
259 if ((scope) == LOCAL) _comm = MPI_COMM_SELF; \
260 else if ((scope) == GLOBAL) _comm = MPI_COMM_WORLD; \
261 else { \
262 fprintf(stderr, "LOG_ALLOW_SYNC ERROR: invalid scope (%d) at %s:%d\n", \
263 (scope), __FILE__, __LINE__); \
264 MPI_Abort(MPI_COMM_WORLD, 1); \
265 } \
266 \
267 /* ------------------------------------------------------------------ */ \
268 /* Decide whether *this* rank should actually print. */ \
269 /* ------------------------------------------------------------------ */ \
270 PetscBool _doPrint = \
271 is_function_allowed(__func__) && ((int)(level) <= (int)get_log_level()); \
272 \
273 if (_doPrint) { \
274 PetscSynchronizedPrintf(_comm, "[%s] " fmt, __func__, ##__VA_ARGS__); \
275 } \
276 \
277 /* ------------------------------------------------------------------ */ \
278 /* ALL ranks call the flush, even if they printed nothing. */ \
279 /* ------------------------------------------------------------------ */ \
280 PetscSynchronizedFlush(_comm, PETSC_STDOUT); \
281} while (0)

◆ LOG_LOOP_ALLOW

#define LOG_LOOP_ALLOW (   scope,
  level,
  iterVar,
  interval,
  fmt,
  ... 
)
Value:
do { \
if (is_function_allowed(__func__) && (int)(level) <= (int)get_log_level()) { \
if ((iterVar) % (interval) == 0) { \
MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
PetscPrintf(comm, "[%s] [%s=%d] " fmt, \
__func__, #iterVar, (iterVar), ##__VA_ARGS__); \
} \
} \
} while (0)

Logs a message inside a loop, but only every interval iterations.

Parameters
scopeLOCAL or GLOBAL.
levelLOG_* level.
iterVarThe loop variable (e.g., i).
intervalOnly log when (iterVar % interval == 0).
fmtprintf-style format string.
...Variadic arguments to include in the formatted message.

Example: for (int i = 0; i < 100; i++) { LOG_LOOP_ALLOW(LOCAL, LOG_DEBUG, i, 10, "Value of i=%d\n", i); }

Definition at line 298 of file logging.h.

299 { \
300 if (is_function_allowed(__func__) && (int)(level) <= (int)get_log_level()) { \
301 if ((iterVar) % (interval) == 0) { \
302 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
303 PetscPrintf(comm, "[%s] [%s=%d] " fmt, \
304 __func__, #iterVar, (iterVar), ##__VA_ARGS__); \
305 } \
306 } \
307 } while (0)

◆ LOG_LOOP_ALLOW_EXACT

#define LOG_LOOP_ALLOW_EXACT (   scope,
  level,
  var,
  val,
  fmt,
  ... 
)
Value:
do { \
/* First, perform the cheap, standard gatekeeper checks. */ \
if (is_function_allowed(__func__) && (int)(level) <= (int)get_log_level()) { \
/* Only if those pass, check the user's specific condition. */ \
if ((var) == (val)) { \
MPI_Comm comm = ((scope) == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
/* Print the standard prefix, then the user's custom message. */ \
PetscPrintf(comm, "[%s] [%s=%d] " fmt, \
__func__, #var, (var), ##__VA_ARGS__); \
} \
} \
} while (0)

Logs a custom message if a variable equals a specific value.

This is a variadic macro for logging a single event when a condition is met. It is extremely useful for printing debug information at a specific iteration of a loop or when a state variable reaches a certain value.

Parameters
scopeEither LOCAL or GLOBAL.
levelThe logging level.
varThe variable to check (e.g., a loop counter 'k').
valThe value that triggers the log (e.g., 6). The log prints if var == val.
fmtA printf-style format string.
...A printf-style format string and its corresponding arguments.

Definition at line 335 of file logging.h.

336 { \
337 /* First, perform the cheap, standard gatekeeper checks. */ \
338 if (is_function_allowed(__func__) && (int)(level) <= (int)get_log_level()) { \
339 /* Only if those pass, check the user's specific condition. */ \
340 if ((var) == (val)) { \
341 MPI_Comm comm = ((scope) == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
342 /* Print the standard prefix, then the user's custom message. */ \
343 PetscPrintf(comm, "[%s] [%s=%d] " fmt, \
344 __func__, #var, (var), ##__VA_ARGS__); \
345 } \
346 } \
347 } while (0)

◆ LOG_ARRAY_ELEMENT_ALLOW

#define LOG_ARRAY_ELEMENT_ALLOW (   scope,
  level,
  arr,
  length,
  idx,
  fmt 
)
Value:
do { \
if (is_function_allowed(__func__) && (int)(level) <= (int)get_log_level()) { \
if ((idx) >= 0 && (idx) < (length)) { \
MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
PetscPrintf(comm, "[%s] arr[%d] = " fmt "\n", \
__func__, (idx), (arr)[idx]); \
} \
} \
} while (0)

Logs a single element of an array, given an index.

Parameters
scopeEither LOCAL or GLOBAL.
levelLOG_ERROR, LOG_WARNING, LOG_INFO, or LOG_DEBUG.
arrPointer to the array to log from.
lengthThe length of the array (to prevent out-of-bounds).
idxThe index of the element to print.
fmtThe printf-style format specifier (e.g. "%g", "%f", etc.).

This macro only logs if: 1) The current function is in the allow-list (is_function_allowed(__func__)). 2) The requested logging level <= the current global get_log_level(). 3) The index idx is valid (0 <= idx < length).

Definition at line 364 of file logging.h.

365 { \
366 if (is_function_allowed(__func__) && (int)(level) <= (int)get_log_level()) { \
367 if ((idx) >= 0 && (idx) < (length)) { \
368 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
369 PetscPrintf(comm, "[%s] arr[%d] = " fmt "\n", \
370 __func__, (idx), (arr)[idx]); \
371 } \
372 } \
373 } while (0)

◆ LOG_ARRAY_SUBRANGE_ALLOW

#define LOG_ARRAY_SUBRANGE_ALLOW (   scope,
  level,
  arr,
  length,
  start,
  end,
  fmt 
)
Value:
do { \
if (is_function_allowed(__func__) && (int)(level) <= (int)get_log_level()) { \
MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
PetscInt _start = (start) < 0 ? 0 : (start); \
PetscInt _end = (end) >= (length) ? (length) - 1 : (end); \
for (PetscInt i = _start; i <= _end; i++) { \
PetscPrintf(comm, "[%s] arr[%d] = " fmt "\n", __func__, i, (arr)[i]); \
} \
} \
} while (0)

Logs a consecutive subrange of an array.

Parameters
scopeEither LOCAL or GLOBAL.
levelLOG_ERROR, LOG_WARNING, LOG_INFO, or LOG_DEBUG.
arrPointer to the array to log from.
lengthTotal length of the array.
startStarting index of the subrange.
endEnding index of the subrange (inclusive).
fmtThe printf-style format specifier (e.g., "%g", "%f").

This macro prints each element arr[i] for i in [start, end], bounded by [0, length-1].

Definition at line 388 of file logging.h.

389 { \
390 if (is_function_allowed(__func__) && (int)(level) <= (int)get_log_level()) { \
391 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
392 PetscInt _start = (start) < 0 ? 0 : (start); \
393 PetscInt _end = (end) >= (length) ? (length) - 1 : (end); \
394 for (PetscInt i = _start; i <= _end; i++) { \
395 PetscPrintf(comm, "[%s] arr[%d] = " fmt "\n", __func__, i, (arr)[i]); \
396 } \
397 } \
398 } while (0)

◆ PROFILE_FUNCTION_BEGIN

#define PROFILE_FUNCTION_BEGIN    _ProfilingStart(__FUNCT__)

Marks the beginning of a profiled code block (typically a function).

Place this macro at the very beginning of a function you wish to profile. It automatically captures the function's name and starts a wall-clock timer.

Definition at line 850 of file logging.h.

◆ PROFILE_FUNCTION_END

#define PROFILE_FUNCTION_END    _ProfilingEnd(__FUNCT__)

Marks the end of a profiled code block.

Place this macro just before every return point in a function that starts with PROFILE_FUNCTION_BEGIN. It stops the timer and accumulates the results.

Definition at line 859 of file logging.h.

Enumeration Type Documentation

◆ LogLevel

enum LogLevel

Enumeration of logging levels.

Defines various severity levels for logging messages.

Enumerator
LOG_ERROR 

Critical errors that may halt the program.

LOG_WARNING 

Non-critical issues that warrant attention.

LOG_INFO 

Informational messages about program execution.

LOG_DEBUG 

Detailed debugging information.

LOG_TRACE 

Very fine-grained tracing information for in-depth debugging.

LOG_VERBOSE 

Extremely detailed logs, typically for development use only.

Definition at line 28 of file logging.h.

28 {
29 LOG_ERROR = 0, /**< Critical errors that may halt the program */
30 LOG_WARNING, /**< Non-critical issues that warrant attention */
31 LOG_INFO, /**< Informational messages about program execution */
32 LOG_DEBUG, /**< Detailed debugging information */
33 LOG_TRACE, /**< Very fine-grained tracing information for in-depth debugging */
34 LOG_VERBOSE /**< Extremely detailed logs, typically for development use only */
35} LogLevel;
LogLevel
Enumeration of logging levels.
Definition logging.h:28
@ LOG_ERROR
Critical errors that may halt the program.
Definition logging.h:29
@ LOG_TRACE
Very fine-grained tracing information for in-depth debugging.
Definition logging.h:33
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:30
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
Definition logging.h:34

Function Documentation

◆ get_log_level()

LogLevel get_log_level ( )

Retrieves the current logging level from the environment variable LOG_LEVEL.

The function checks the LOG_LEVEL environment variable and sets the logging level accordingly. Supported levels are "ERROR", "WARNING", "INFO", "DEBUG", "TRACE", and "VERBOSE". Unset or unrecognized values default to "ERROR".

Returns
LogLevel The current logging level.

Retrieves the current logging level from the environment variable LOG_LEVEL.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
get_log_level()

Definition at line 87 of file logging.c.

87 {
88 if (current_log_level == -1) { // Log level not set yet
89 const char *env = getenv("LOG_LEVEL");
90 if (!env) {
91 current_log_level = LOG_ERROR; // Default level
92 }
93 else if (strcmp(env, "DEBUG") == 0) {
95 }
96 else if (strcmp(env, "INFO") == 0) {
98 }
99 else if (strcmp(env, "WARNING") == 0) {
101 }
102 else if (strcmp(env, "VERBOSE") == 0) {
104 }
105 else if (strcmp(env, "TRACE") == 0) {
107 }
108 else {
109 current_log_level = LOG_ERROR; // Default if unrecognized
110 }
111 }
112 return current_log_level;
113}
static LogLevel current_log_level
Static variable to cache the current logging level.
Definition logging.c:19
Here is the caller graph for this function:

◆ print_log_level()

PetscErrorCode print_log_level ( void  )

Prints the current logging level to the console.

This function retrieves the log level using get_log_level() and prints the corresponding log level name. It helps verify the logging configuration at runtime. The log levels supported are:

  • LOG_ERROR (0) : Logs only critical errors.
  • LOG_WARNING (1) : Logs warnings and errors.
  • LOG_INFO (2) : Logs general information, warnings, and errors.
  • LOG_DEBUG (3) : Logs debugging information, info, warnings, and errors.
  • LOG_TRACE (4) : Logs fine-grained trace information.
  • LOG_VERBOSE (5) : Logs very detailed developer output. If LOG_LEVEL is not set, it defaults to LOG_ERROR.

    Returns
    PetscErrorCode 0 on success.

    Prints the current logging level to the console.

    Local to this translation unit.

Definition at line 119 of file logging.c.

120{
121 PetscMPIInt rank;
122 PetscErrorCode ierr;
123 int level;
124 const char *level_name;
125
126 PetscFunctionBeginUser;
127 /* get MPI rank */
128 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRMPI(ierr);
129
130 /* decide level name */
131 level = get_log_level();
132 level_name = (level == LOG_ERROR) ? "ERROR" :
133 (level == LOG_WARNING) ? "WARNING" :
134 (level == LOG_INFO) ? "INFO" :
135 (level == LOG_DEBUG) ? "DEBUG" :
136 (level == LOG_VERBOSE) ? "VERBOSE" :
137 (level == LOG_TRACE) ? "TRACE" :
138 "UNKNOWN";
139
140 /* print it out */
141 ierr = PetscPrintf(PETSC_COMM_SELF,
142 "Current log level: %s (%d) | rank: %d\n",
143 level_name, level, (int)rank);
144 CHKERRMPI(ierr);
145
146 PetscFunctionReturn(PETSC_SUCCESS);
147}
LogLevel get_log_level()
Implementation of get_log_level().
Definition logging.c:87
Here is the call graph for this function:
Here is the caller graph for this function:

◆ set_allowed_functions()

void set_allowed_functions ( const char **  functionList,
int  count 
)

Sets the global list of function names that are allowed to log.

You can replace the entire list of allowed function names at runtime.

Parameters
functionListReplacement array of permitted function names.
countNumber of entries in functionList.

Sets the global list of function names that are allowed to log.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
set_allowed_functions()

Definition at line 155 of file logging.c.

156{
157 // 1. Free any existing entries
158 if (gAllowedFunctions) {
159 for (int i = 0; i < gNumAllowed; ++i) {
160 free(gAllowedFunctions[i]); // each was strdup'ed
161 }
162 free(gAllowedFunctions);
163 gAllowedFunctions = NULL;
164 gNumAllowed = 0;
165 }
166
167 // 2. Allocate new array
168 if (count > 0) {
169 gAllowedFunctions = (char**)malloc(sizeof(char*) * count);
170 }
171
172 // 3. Copy the new entries
173 for (int i = 0; i < count; ++i) {
174 // strdup is a POSIX function. If not available, implement your own string copy.
175 gAllowedFunctions[i] = strdup(functionList[i]);
176 }
177 gNumAllowed = count;
178}
static char ** gAllowedFunctions
Global/static array of function names allowed to log.
Definition logging.c:26
static int gNumAllowed
Number of entries in the gAllowedFunctions array.
Definition logging.c:31
Here is the caller graph for this function:

◆ is_function_allowed()

PetscBool is_function_allowed ( const char *  functionName)

Checks if a given function is in the allow-list.

This helper is used internally by the LOG_ALLOW macro.

Parameters
functionNameFunction name to query.
Returns
PETSC_TRUE when the name is enabled by the allow-list.

Checks if a given function is in the allow-list.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
is_function_allowed()

Definition at line 186 of file logging.c.

187{
188 /* no list ⇒ allow all */
189 if (gNumAllowed == 0) {
190 return PETSC_TRUE;
191 }
192
193 /* otherwise only the listed functions are allowed */
194 for (int i = 0; i < gNumAllowed; ++i) {
195 if (strcmp(gAllowedFunctions[i], functionName) == 0) {
196 return PETSC_TRUE;
197 }
198 }
199 return PETSC_FALSE;
200}
Here is the caller graph for this function:

◆ LOG_CELL_VERTICES()

PetscErrorCode LOG_CELL_VERTICES ( const Cell cell,
PetscMPIInt  rank 
)

Prints the coordinates of a cell's vertices.

This function iterates through the eight vertices of a given cell and prints their coordinates. It is primarily used for debugging purposes to verify the correctness of cell vertex assignments.

Parameters
[in]cellPointer to a Cell structure representing the cell, containing its vertices.
[in]rankMPI rank for identification (useful in parallel environments).
Returns
PetscErrorCode Returns 0 to indicate successful execution. Non-zero on failure.
Note
  • Ensure that the cell pointer is not NULL before calling this function..

Prints the coordinates of a cell's vertices.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
LOG_CELL_VERTICES()

Definition at line 208 of file logging.c.

209{
210
211 // Validate input pointers
212 if (cell == NULL) {
213 LOG_ALLOW(LOCAL,LOG_ERROR, "'cell' is NULL.\n");
214 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "LOG_CELL_VERTICES - Input parameter 'cell' is NULL.");
215 }
216
217 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Rank %d, Cell Vertices:\n", rank);
218 for(int i = 0; i < 8; i++){
219 LOG_ALLOW(LOCAL,LOG_VERBOSE, " Vertex[%d]: (%.2f, %.2f, %.2f)\n",
220 i, cell->vertices[i].x, cell->vertices[i].y, cell->vertices[i].z);
221 }
222
223 return 0; // Indicate successful execution
224}
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
Definition logging.h:200
PetscScalar x
Definition variables.h:103
PetscScalar z
Definition variables.h:103
PetscScalar y
Definition variables.h:103
Cmpnts vertices[8]
Coordinates of the eight vertices of the cell.
Definition variables.h:178
Here is the caller graph for this function:

◆ LOG_FACE_DISTANCES()

PetscErrorCode LOG_FACE_DISTANCES ( PetscReal *  d)

Prints the signed distances to each face of the cell.

This function iterates through the six signed distances from a point to each face of a given cell and prints their values. It is primarily used for debugging purposes to verify the correctness of distance calculations.

Parameters
[in]dAn array of six PetscReal values representing the signed distances. The indices correspond to:
  • d[LEFT]: Left Face
  • d[RIGHT]: Right Face
  • d[BOTTOM]: Bottom Face
  • d[TOP]: Top Face
  • d[FRONT]: Front Face
  • d[BACK]: Back Face
Returns
PetscErrorCode Returns 0 to indicate successful execution. Non-zero on failure.
Note
  • Ensure that the d array is correctly populated with signed distances before calling this function.

Prints the signed distances to each face of the cell.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
LOG_FACE_DISTANCES()

Definition at line 233 of file logging.c.

234{
235
236 // Validate input array
237 if (d == NULL) {
238 LOG_ALLOW(LOCAL,LOG_ERROR, " 'd' is NULL.\n");
239 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, " Input array 'd' is NULL.");
240 }
241
242 PetscPrintf(PETSC_COMM_SELF, " Face Distances:\n");
243 PetscPrintf(PETSC_COMM_SELF, " LEFT(%d): %.15f\n", LEFT, d[LEFT]);
244 PetscPrintf(PETSC_COMM_SELF, " RIGHT(%d): %.15f\n", RIGHT, d[RIGHT]);
245 PetscPrintf(PETSC_COMM_SELF, " BOTTOM(%d): %.15f\n", BOTTOM, d[BOTTOM]);
246 PetscPrintf(PETSC_COMM_SELF, " TOP(%d): %.15f\n", TOP, d[TOP]);
247 PetscPrintf(PETSC_COMM_SELF, " FRONT(%d): %.15f\n", FRONT, d[FRONT]);
248 PetscPrintf(PETSC_COMM_SELF, " BACK(%d): %.15f\n", BACK, d[BACK]);
249
250 return 0; // Indicate successful execution
251}
@ TOP
Definition variables.h:147
@ FRONT
Definition variables.h:147
@ BOTTOM
Definition variables.h:147
@ BACK
Definition variables.h:147
@ LEFT
Definition variables.h:147
@ RIGHT
Definition variables.h:147
Here is the caller graph for this function:

◆ LOG_PARTICLE_FIELDS()

PetscErrorCode LOG_PARTICLE_FIELDS ( UserCtx user,
PetscInt  printInterval 
)

Prints particle fields in a table that automatically adjusts its column widths.

This function retrieves data from the particle swarm and prints a table where the width of each column is determined by the maximum width needed to display the data. Only every 'printInterval'-th particle is printed.

Parameters
[in]userPointer to the UserCtx structure.
[in]printIntervalOnly every printInterval‑th particle is printed.
Returns
PetscErrorCode Returns 0 on success.

Prints particle fields in a table that automatically adjusts its column widths.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
LOG_PARTICLE_FIELDS()

Definition at line 400 of file logging.c.

401{
402 DM swarm = user->swarm;
403 PetscErrorCode ierr;
404 PetscInt localNumParticles;
405 PetscReal *positions = NULL;
406 PetscInt64 *particleIDs = NULL;
407 PetscMPIInt *particleRanks = NULL;
408 PetscInt *cellIDs = NULL;
409 PetscReal *weights = NULL;
410 PetscReal *velocities = NULL;
411 PetscMPIInt rank;
412
413 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
414 LOG_ALLOW(LOCAL,LOG_INFO, "Rank %d is retrieving particle data.\n", rank);
415
416 ierr = DMSwarmGetLocalSize(swarm, &localNumParticles); CHKERRQ(ierr);
417 LOG_ALLOW(LOCAL,LOG_DEBUG,"Rank %d has %d particles.\n", rank, localNumParticles);
418
419 ierr = DMSwarmGetField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_POSITION), NULL, NULL, (void**)&positions); CHKERRQ(ierr);
420 ierr = DMSwarmGetField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_PID), NULL, NULL, (void**)&particleIDs); CHKERRQ(ierr);
421 ierr = DMSwarmGetField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_RANK), NULL, NULL, (void**)&particleRanks); CHKERRQ(ierr);
422 ierr = DMSwarmGetField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_CELL_ID), NULL, NULL, (void**)&cellIDs); CHKERRQ(ierr);
423 ierr = DMSwarmGetField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_WEIGHT), NULL, NULL, (void**)&weights); CHKERRQ(ierr);
424 ierr = DMSwarmGetField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_VELOCITY), NULL, NULL, (void**)&velocities); CHKERRQ(ierr);
425
426 /* Compute maximum column widths. */
427 int wRank, wPID, wCell, wPos, wVel, wWt;
428 wRank = wPID = wCell = wPos = wVel = wWt = 0;
429 ierr = ComputeMaxColumnWidths(localNumParticles, particleRanks, particleIDs, cellIDs,
430 positions, velocities, weights,
431 &wRank, &wPID, &wCell, &wPos, &wVel, &wWt); CHKERRQ(ierr);
432
433 /* Build a header string and a row format string. */
434 char headerFmt[256];
435 char rowFmt[256];
436 BuildHeaderString(headerFmt, sizeof(headerFmt), wRank, wPID, wCell, wPos, wVel, wWt);
437 BuildRowFormatString(wRank, wPID, wCell, wPos, wVel, wWt, rowFmt, sizeof(rowFmt));
438
439 /* Print header (using synchronized printing for parallel output). */
440 ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, "--------------------------------------------------------------------------------------------------------------\n"); CHKERRQ(ierr);
441 ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, "%s", headerFmt); CHKERRQ(ierr);
442 ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, "--------------------------------------------------------------------------------------------------------------\n"); CHKERRQ(ierr);
443
444 /* Loop over particles and print every printInterval-th row. */
445 char rowStr[256];
446 for (PetscInt i = 0; i < localNumParticles; i++) {
447 if (i % printInterval == 0) {
448 // ------- DEBUG
449 //char cellStr[TMP_BUF_SIZE], posStr[TMP_BUF_SIZE], velStr[TMP_BUF_SIZE], wtStr[TMP_BUF_SIZE];
450 //CellToStr(&cellIDs[3*i], cellStr, TMP_BUF_SIZE);
451 //TripleRealToStr(&positions[3*i], posStr, TMP_BUF_SIZE);
452 //TripleRealToStr(&velocities[3*i], velStr, TMP_BUF_SIZE);
453 // TripleRealToStr(&weights[3*i], wtStr, TMP_BUF_SIZE);
454
455 // if (rank == 0) { // Or whatever rank is Rank 0
456 //PetscPrintf(PETSC_COMM_SELF, "[Rank 0 DEBUG LPF] Particle %lld: PID=%lld, Rank=%d\n", (long long)i, (long long)particleIDs[i], particleRanks[i]);
457 //PetscPrintf(PETSC_COMM_SELF, "[Rank 0 DEBUG LPF] Raw Pos: (%.10e, %.10e, %.10e)\n", positions[3*i+0], positions[3*i+1], positions[3*i+2]);
458 //PetscPrintf(PETSC_COMM_SELF, "[Rank 0 DEBUG LPF] Str Pos: %s\n", posStr);
459 //PetscPrintf(PETSC_COMM_SELF, "[Rank 0 DEBUG LPF] Raw Vel: (%.10e, %.10e, %.10e)\n", velocities[3*i+0], velocities[3*i+1], velocities[3*i+2]);
460 // PetscPrintf(PETSC_COMM_SELF, "[Rank 0 DEBUG LPF] Str Vel: %s\n", velStr);
461 // Add similar for cell, weights
462 // PetscPrintf(PETSC_COMM_SELF, "[Rank 0 DEBUG LPF] About to build rowStr for particle %lld\n", (long long)i);
463 // fflush(stdout);
464 // }
465
466 // snprintf(rowStr, sizeof(rowStr), rowFmt,
467 // particleRanks[i],
468 // particleIDs[i],
469 // cellStr,
470 // posStr,
471 // velStr,
472 // wtStr);
473
474
475 // ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, "%s", rowStr); CHKERRQ(ierr);
476
477 // ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, "%s", rowStr); CHKERRQ(ierr);
478
479 // -------- DEBUG
480 /* Format the row by converting each field to a string first.
481 * We use temporary buffers and then build the row string.
482 */
483
484 char cellStr[TMP_BUF_SIZE], posStr[TMP_BUF_SIZE], velStr[TMP_BUF_SIZE], wtStr[TMP_BUF_SIZE];
485 CellToStr(&cellIDs[3*i], cellStr, TMP_BUF_SIZE);
486 TripleRealToStr(&positions[3*i], posStr, TMP_BUF_SIZE);
487 TripleRealToStr(&velocities[3*i], velStr, TMP_BUF_SIZE);
488 TripleRealToStr(&weights[3*i], wtStr, TMP_BUF_SIZE);
489
490 /* Build the row string. Note that for the integer fields we can use the row format string. */
491 snprintf(rowStr, sizeof(rowStr), rowFmt,
492 particleRanks[i],
493 particleIDs[i],
494 cellStr,
495 posStr,
496 velStr,
497 wtStr);
498 ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, "%s", rowStr); CHKERRQ(ierr);
499 }
500 }
501
502
503 ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, "--------------------------------------------------------------------------------------------------------------\n"); CHKERRQ(ierr);
504 ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, "\n"); CHKERRQ(ierr);
505 ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT); CHKERRQ(ierr);
506
507 LOG_ALLOW_SYNC(GLOBAL,LOG_DEBUG,"Completed printing on Rank %d.\n", rank);
508
509 /* Restore fields */
510 ierr = DMSwarmRestoreField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_POSITION), NULL, NULL, (void**)&positions); CHKERRQ(ierr);
511 ierr = DMSwarmRestoreField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_PID), NULL, NULL, (void**)&particleIDs); CHKERRQ(ierr);
512 ierr = DMSwarmRestoreField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_RANK), NULL, NULL, (void**)&particleRanks); CHKERRQ(ierr);
513 ierr = DMSwarmRestoreField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_CELL_ID), NULL, NULL, (void**)&cellIDs); CHKERRQ(ierr);
514 ierr = DMSwarmRestoreField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_WEIGHT), NULL, NULL, (void**)&weights); CHKERRQ(ierr);
515 ierr = DMSwarmRestoreField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_VELOCITY), NULL, NULL, (void**)&velocities); CHKERRQ(ierr);
516
517 LOG_ALLOW(LOCAL,LOG_DEBUG, "Restored all particle fields.\n");
518 return 0;
519}
#define TMP_BUF_SIZE
Definition logging.c:10
static void BuildRowFormatString(PetscMPIInt wRank, PetscInt wPID, PetscInt wCell, PetscInt wPos, PetscInt wVel, PetscInt wWt, char *fmtStr, size_t bufSize)
Definition logging.c:369
static void BuildHeaderString(char *headerStr, size_t bufSize, PetscMPIInt wRank, PetscInt wPID, PetscInt wCell, PetscInt wPos, PetscInt wVel, PetscInt wWt)
Definition logging.c:382
static void CellToStr(const PetscInt *cell, char *buf, size_t bufsize)
Definition logging.c:272
static void TripleRealToStr(const PetscReal *arr, char *buf, size_t bufsize)
Definition logging.c:280
static PetscErrorCode ComputeMaxColumnWidths(PetscInt nParticles, const PetscMPIInt *ranks, const PetscInt64 *pids, const PetscInt *cellIDs, const PetscReal *positions, const PetscReal *velocities, const PetscReal *weights, int *wRank, int *wPID, int *wCell, int *wPos, int *wVel, int *wWt)
Definition logging.c:305
const char * ParticleFieldName(ParticleFieldId field_id)
Return the canonical PETSc DMSwarm name for an ID.
@ PARTICLE_FIELD_ID_WEIGHT
@ PARTICLE_FIELD_ID_POSITION
@ PARTICLE_FIELD_ID_PID
@ PARTICLE_FIELD_ID_CELL_ID
@ PARTICLE_FIELD_ID_RANK
@ PARTICLE_FIELD_ID_VELOCITY
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsParticleConsoleSnapshotEnabled()

PetscBool IsParticleConsoleSnapshotEnabled ( const SimCtx simCtx)

Returns whether periodic particle console snapshots are enabled.

This checks only the reporting contract (particles exist, cadence is enabled, and the global log level is at least INFO).

Parameters
simCtxSimulation context controlling the operation.
Returns
PetscBool indicating the result of IsParticleConsoleSnapshotEnabled().

Returns whether periodic particle console snapshots are enabled.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
IsParticleConsoleSnapshotEnabled()

Definition at line 528 of file logging.c.

529{
530 if (!simCtx) {
531 return PETSC_FALSE;
532 }
533 return (PetscBool)(simCtx->np > 0 &&
534 simCtx->particleConsoleOutputFreq > 0 &&
536}
PetscInt np
Definition variables.h:827
PetscInt particleConsoleOutputFreq
Definition variables.h:708
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ShouldEmitPeriodicParticleConsoleSnapshot()

PetscBool ShouldEmitPeriodicParticleConsoleSnapshot ( const SimCtx simCtx,
PetscInt  completed_step 
)

Returns whether a particle console snapshot should be emitted for the.

completed timestep.

Parameters
simCtxSimulation context controlling the operation.
completed_stepCompleted step index used by the decision helper.
Returns
PetscBool indicating the result of ShouldEmitPeriodicParticleConsoleSnapshot().

Returns whether a particle console snapshot should be emitted for the.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
ShouldEmitPeriodicParticleConsoleSnapshot()

Definition at line 545 of file logging.c.

546{
547 return (PetscBool)(IsParticleConsoleSnapshotEnabled(simCtx) &&
548 completed_step > 0 &&
549 completed_step % simCtx->particleConsoleOutputFreq == 0);
550}
PetscBool IsParticleConsoleSnapshotEnabled(const SimCtx *simCtx)
Implementation of IsParticleConsoleSnapshotEnabled().
Definition logging.c:528
Here is the call graph for this function:
Here is the caller graph for this function:

◆ EmitParticleConsoleSnapshot()

PetscErrorCode EmitParticleConsoleSnapshot ( UserCtx user,
SimCtx simCtx,
PetscInt  step 
)

Emits one particle console snapshot into the main solver log.

Parameters
userPrimary UserCtx input for the operation.
simCtxSimulation context controlling the operation.
stepStep index associated with the operation.
Returns
PetscErrorCode 0 on success.

Emits one particle console snapshot into the main solver log.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
EmitParticleConsoleSnapshot()

Definition at line 559 of file logging.c.

560{
561 PetscErrorCode ierr;
562
563 PetscFunctionBeginUser;
564 LOG(GLOBAL, LOG_INFO, "Particle states at step %d:\n", step);
565 ierr = LOG_PARTICLE_FIELDS(user, simCtx->LoggingFrequency); CHKERRQ(ierr);
566 PetscFunctionReturn(0);
567}
PetscErrorCode LOG_PARTICLE_FIELDS(UserCtx *user, PetscInt printInterval)
Implementation of LOG_PARTICLE_FIELDS().
Definition logging.c:400
#define LOG(scope, level, fmt,...)
Logging macro for PETSc-based applications with scope control.
Definition logging.h:84
PetscInt LoggingFrequency
Definition variables.h:857
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsStatisticsConsoleSnapshotEnabled()

PetscBool IsStatisticsConsoleSnapshotEnabled ( const struct SimCtx simCtx)

Reports whether the periodic statistics console snapshot is enabled.

Mirrors the particle console gate: the subsystem must be active, the configured cadence positive, and the effective log level at least LOG_INFO.

Parameters
[in]simCtxSimulation context to inspect.
Returns
PETSC_TRUE when snapshots should be emitted.
Here is the caller graph for this function:

◆ ShouldEmitPeriodicStatisticsConsoleSnapshot()

PetscBool ShouldEmitPeriodicStatisticsConsoleSnapshot ( const struct SimCtx simCtx,
PetscInt  completed_step 
)

Reports whether a completed step falls on the console snapshot cadence.

Parameters
[in]simCtxSimulation context to inspect.
[in]completed_stepStep that has just completed.
Returns
PETSC_TRUE when a snapshot is due for this step.
Here is the caller graph for this function:

◆ EmitStatisticsConsoleSnapshot()

PetscErrorCode EmitStatisticsConsoleSnapshot ( UserCtx user,
const struct SimCtx simCtx,
PetscInt  step 
)

Emits one console snapshot of window progress.

Reports window-level scalars only; it never dumps field data.

Parameters
[in]userFinest-level block array supplying accumulator state.
[in]simCtxSimulation context carrying the window array.
[in]stepStep the snapshot describes.
Returns
Zero on success.
Here is the caller graph for this function:

◆ FreeAllowedFunctions()

PetscErrorCode FreeAllowedFunctions ( char **  funcs,
PetscInt  n 
)

Free an array previously returned by LoadAllowedFunctionsFromFile().

Parameters
[in,out]funcsArray of strings to release (may be NULL).
[in]nNumber of entries in funcs. Ignored if funcs is NULL.
Returns
0 on success or a PETSc error code.

Free an array previously returned by LoadAllowedFunctionsFromFile().

Local to this translation unit.

Definition at line 652 of file logging.c.

653{
654 PetscErrorCode ierr;
655 PetscFunctionBegin;
656 if (funcs) {
657 for (PetscInt i = 0; i < n; ++i) {
658 ierr = PetscFree(funcs[i]); CHKERRQ(ierr);
659 }
660 ierr = PetscFree(funcs); CHKERRQ(ierr);
661 }
662 PetscFunctionReturn(0);
663}
Here is the caller graph for this function:

◆ LoadAllowedFunctionsFromFile()

PetscErrorCode LoadAllowedFunctionsFromFile ( const char  filename[],
char ***  funcsOut,
PetscInt *  nOut 
)

Load function names from a text file.

The file is expected to contain one identifier per line. Blank lines and lines whose first non‑blank character is a # are silently skipped so the file can include comments. Example:

# Allowed function list
InitializeSimulation
InterpolateAllFieldsToSwarm # inline comments are OK, too
PetscErrorCode InterpolateAllFieldsToSwarm(UserCtx *user)
Interpolates all relevant fields from the DMDA to the DMSwarm.
int main(int argc, char **argv)
Entry point for the postprocessor executable.

The routine allocates memory as needed (growing an internal buffer with PetscRealloc()) and returns the resulting array and its length to the caller. Use FreeAllowedFunctions() to clean up when done.

Parameters
[in]filenamePath of the configuration file to read.
[out]funcsOutOn success, points to a freshly‑allocated array of char* (size nOut).
[out]nOutNumber of valid entries in funcsOut.
Returns
0 on success, or a PETSc error code on failure (e.g. I/O error, OOM).

Load function names from a text file.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
LoadAllowedFunctionsFromFile()

Definition at line 598 of file logging.c.

601{
602 FILE *fp = NULL;
603 char **funcs = NULL;
604 size_t cap = 16; /* initial capacity */
605 size_t n = 0; /* number of names */
606 char line[PETSC_MAX_PATH_LEN];
607 PetscErrorCode ierr;
608
609 PetscFunctionBegin;
610
611 /* ---------------------------------------------------------------------- */
612 /* 1. Open file */
613 fp = fopen(filename, "r");
614 if (!fp) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
615 "Cannot open %s", filename);
616
617 /* 2. Allocate initial pointer array */
618 ierr = PetscMalloc1(cap, &funcs); CHKERRQ(ierr);
619
620 /* 3. Read file line by line */
621 while (fgets(line, sizeof line, fp)) {
622 /* Strip everything after a comment character '#'. */
623 char *hash = strchr(line, '#');
624 if (hash) *hash = '\0';
625
626 trim(line); /* remove leading/trailing blanks */
627 if (!*line) continue; /* skip if empty */
628
629 /* Grow the array if necessary */
630 if (n == cap) {
631 cap *= 2;
632 ierr = PetscRealloc(cap * sizeof(*funcs), (void **)&funcs); CHKERRQ(ierr);
633 }
634
635 /* Deep‑copy the cleaned identifier */
636 ierr = PetscStrallocpy(line, &funcs[n++]); CHKERRQ(ierr);
637 }
638 fclose(fp);
639
640 /* 4. Return results to caller */
641 *funcsOut = funcs;
642 *nOut = (PetscInt)n;
643
644 PetscFunctionReturn(0);
645}
static void trim(char *s)
Remove leading and trailing whitespace from a mutable configuration string.
Definition logging.c:573
Here is the call graph for this function:
Here is the caller graph for this function:

◆ BCFaceToString()

const char * BCFaceToString ( BCFace  face)

Returns the canonical log token for a boundary-face enum value.

Parameters
[in]faceThe BCFace enum value.
Returns
Pointer to a constant string representing the face.

Returns the canonical log token for a boundary-face enum value.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
BCFaceToString()

Definition at line 671 of file logging.c.

671 {
672 switch (face) {
673 case BC_FACE_NEG_X: return "-Xi (I-Min)";
674 case BC_FACE_POS_X: return "+Xi (I-Max)";
675 case BC_FACE_NEG_Y: return "-Eta (J-Min)";
676 case BC_FACE_POS_Y: return "+Eta (J-Max)";
677 case BC_FACE_NEG_Z: return "-Zeta (K-Min)";
678 case BC_FACE_POS_Z: return "+Zeta (K-Max)";
679 default: return "Unknown Face";
680 }
681}
@ BC_FACE_NEG_X
Definition variables.h:262
@ BC_FACE_POS_Z
Definition variables.h:264
@ BC_FACE_POS_Y
Definition variables.h:263
@ BC_FACE_NEG_Z
Definition variables.h:264
@ BC_FACE_POS_X
Definition variables.h:262
@ BC_FACE_NEG_Y
Definition variables.h:263
Here is the caller graph for this function:

◆ InitialConditionModeToString()

const char * InitialConditionModeToString ( InitialConditionMode  mode)

Convert an initial-condition mode to a string representation.

Parameters
[in]modeInitial-condition mode value.
Returns
Pointer to a constant string representing the initial-condition mode.

Convert an initial-condition mode to a string representation.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
InitialConditionModeToString()

Definition at line 689 of file logging.c.

690{
691 switch(mode){
692 case IC_MODE_ZERO: return "Zero";
693 case IC_MODE_CONSTANT_CARTESIAN: return "Cartesian Constant";
694 case IC_MODE_POISEUILLE: return "Poiseuille";
695 case IC_MODE_CONSTANT_STREAMWISE: return "Streamwise Constant";
696 case IC_MODE_FILE: return "File";
697 default: return "Unknown Initial Condition";
698 }
699}
@ IC_MODE_CONSTANT_CARTESIAN
Definition variables.h:153
@ IC_MODE_POISEUILLE
Definition variables.h:154
@ IC_MODE_CONSTANT_STREAMWISE
Definition variables.h:155
@ IC_MODE_FILE
Definition variables.h:156
@ IC_MODE_ZERO
Definition variables.h:152
Here is the caller graph for this function:

◆ FlowDirectionToString()

const char * FlowDirectionToString ( FlowDirection  fd)

Convert a FlowDirection enum value to its YAML token string.

Parameters
[in]fdFlowDirection value.
Returns
Token string such as "+Zeta", or "from INLET" when FLOW_DIR_UNSET.

Definition at line 705 of file logging.c.

706{
707 switch ((int)fd) {
708 case FLOW_DIR_POS_XI: return "+Xi";
709 case FLOW_DIR_NEG_XI: return "-Xi";
710 case FLOW_DIR_POS_ETA: return "+Eta";
711 case FLOW_DIR_NEG_ETA: return "-Eta";
712 case FLOW_DIR_POS_ZETA: return "+Zeta";
713 case FLOW_DIR_NEG_ZETA: return "-Zeta";
714 default: return "from INLET";
715 }
716}
@ FLOW_DIR_NEG_ZETA
Definition variables.h:278
@ FLOW_DIR_NEG_ETA
Definition variables.h:276
@ FLOW_DIR_POS_ZETA
Definition variables.h:277
@ FLOW_DIR_POS_XI
Definition variables.h:273
@ FLOW_DIR_NEG_XI
Definition variables.h:274
@ FLOW_DIR_POS_ETA
Definition variables.h:275
Here is the caller graph for this function:

◆ ParticleInitializationToString()

const char * ParticleInitializationToString ( ParticleInitializationType  ParticleInitialization)

Returns the canonical log token for a particle-initialization mode.

Parameters
[in]ParticleInitializationThe ParticleInitialization enum value.
Returns
Pointer to a constant string representing the particle initialization type.

Returns the canonical log token for a particle-initialization mode.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
ParticleInitializationToString()

Definition at line 724 of file logging.c.

725{
726 switch(ParticleInitialization){
727 case PARTICLE_INIT_SURFACE_RANDOM: return "Surface: Random";
728 case PARTICLE_INIT_VOLUME: return "Volume";
729 case PARTICLE_INIT_POINT_SOURCE: return "Point Source";
730 case PARTICLE_INIT_SURFACE_EDGES: return "Surface: At edges";
731 default: return "Unknown Particle Initialization";
732 }
733}
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
Definition variables.h:552
@ PARTICLE_INIT_SURFACE_EDGES
Deterministic placement at inlet face edges.
Definition variables.h:555
@ PARTICLE_INIT_POINT_SOURCE
All particles at a fixed (psrc_x,psrc_y,psrc_z) — for validation.
Definition variables.h:554
@ PARTICLE_INIT_VOLUME
Random volumetric distribution across the domain.
Definition variables.h:553
Here is the caller graph for this function:

◆ LESModelToString()

const char * LESModelToString ( LESModelType  LESFlag)

Returns the canonical log token for an LES model selector.

Parameters
[in]LESFlagThe LES flag value.
Returns
Pointer to a constant string representing the LES Flag.

Returns the canonical log token for an LES model selector.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
LESModelToString()

Definition at line 741 of file logging.c.

742{
743 switch(LESFlag){
744 case NO_LES_MODEL: return "No LES";
745 case CONSTANT_SMAGORINSKY: return "Constant Smagorinsky";
746 case DYNAMIC_SMAGORINSKY: return "Dynamic Smagorinsky";
747 default: return "Unknown LES Flag";
748 }
749}
@ DYNAMIC_SMAGORINSKY
Definition variables.h:523
@ NO_LES_MODEL
Definition variables.h:521
@ CONSTANT_SMAGORINSKY
Definition variables.h:522
Here is the caller graph for this function:

◆ MomentumSolverTypeToString()

const char * MomentumSolverTypeToString ( MomentumSolverType  SolverFlag)

Returns the canonical log token for a momentum-solver selector.

Parameters
[in]SolverFlagThe Momentum Solver flag value.
Returns
Pointer to a constant string representing the MomentumSolverType.

Returns the canonical log token for a momentum-solver selector.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
MomentumSolverTypeToString()

Definition at line 757 of file logging.c.

758{
759 switch(SolverFlag){
760 case MOMENTUM_SOLVER_EXPLICIT_RK: return "Explicit 4 stage Runge-Kutta ";
761 case MOMENTUM_SOLVER_DUALTIME_PICARD_JAMESON_RK: return "Dual Time Picard with 4-stage Jameson RK Smoothing";
762 case MOMENTUM_SOLVER_NEWTON_KRYLOV: return "Newton Krylov";
763 default: return "Unknown Momentum Solver Type";
764 }
765}
@ MOMENTUM_SOLVER_DUALTIME_PICARD_JAMESON_RK
Definition variables.h:536
@ MOMENTUM_SOLVER_EXPLICIT_RK
Definition variables.h:535
@ MOMENTUM_SOLVER_NEWTON_KRYLOV
Definition variables.h:537
Here is the caller graph for this function:

◆ BCTypeToString()

const char * BCTypeToString ( BCType  type)

Returns the canonical log token for a boundary mathematical type.

Parameters
[in]typeThe BCType enum value.
Returns
Pointer to a constant string representing the BC type.

Returns the canonical log token for a boundary mathematical type.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
BCTypeToString()

Definition at line 773 of file logging.c.

773 {
774 switch (type) {
775 // case DIRICHLET: return "DIRICHLET";
776 // case NEUMANN: return "NEUMANN";
777 case WALL: return "WALL";
778 case INLET: return "INLET";
779 case OUTLET: return "OUTLET";
780 case FARFIELD: return "FARFIELD";
781 case PERIODIC: return "PERIODIC";
782 case INTERFACE: return "INTERFACE";
783
784 // case CUSTOM: return "CUSTOM";
785 default: return "Unknown BC Type";
786 }
787}
@ INLET
Definition variables.h:290
@ INTERFACE
Definition variables.h:285
@ FARFIELD
Definition variables.h:291
@ OUTLET
Definition variables.h:289
@ PERIODIC
Definition variables.h:292
@ WALL
Definition variables.h:286
Here is the caller graph for this function:

◆ BCHandlerTypeToString()

const char * BCHandlerTypeToString ( BCHandlerType  handler_type)

Converts a BCHandlerType enum to its string representation.

Provides a descriptive string for a specific boundary condition implementation strategy. This is crucial for logging the exact behavior configured for a face.

Parameters
handler_typeThe BCHandlerType enum value (e.g., BC_HANDLER_WALL_NOSLIP).
Returns
A constant character string corresponding to the enum. Returns "UNKNOWN_HANDLER" if the enum value is not recognized.

Converts a BCHandlerType enum to its string representation.

Local to this translation unit.

Definition at line 793 of file logging.c.

793 {
794 switch (handler_type) {
795 // Wall & Symmetry Handlers
796 case BC_HANDLER_WALL_NOSLIP: return "noslip";
797 case BC_HANDLER_WALL_MOVING: return "moving";
798 case BC_HANDLER_SYMMETRY_PLANE: return "symmetry_plane";
799
800 // Inlet Handlers
801 case BC_HANDLER_INLET_CONSTANT_VELOCITY: return "constant_velocity";
802 case BC_HANDLER_INLET_PULSATILE_FLUX: return "pulsatile_flux";
803 case BC_HANDLER_INLET_PARABOLIC: return "parabolic";
804 case BC_HANDLER_INLET_PROFILE_FROM_FILE: return "prescribed_flow";
805
806 // Outlet Handlers
807 case BC_HANDLER_OUTLET_CONSERVATION: return "conservation";
808 case BC_HANDLER_OUTLET_PRESSURE: return "pressure";
809
810 // Other Physical Handlers
811 case BC_HANDLER_FARFIELD_NONREFLECTING: return "nonreflecting";
812
813 // Multi-Block / Interface Handlers
814 case BC_HANDLER_PERIODIC_GEOMETRIC: return "geometric";
815 case BC_HANDLER_PERIODIC_DRIVEN_CONSTANT_FLUX: return "constant flux";
816 case BC_HANDLER_PERIODIC_DRIVEN_INITIAL_FLUX: return "initial flux";
817 case BC_HANDLER_INTERFACE_OVERSET: return "overset";
818
819 // Default case
821 default: return "UNKNOWN_HANDLER";
822 }
823}
@ BC_HANDLER_INLET_PULSATILE_FLUX
Definition variables.h:312
@ BC_HANDLER_PERIODIC_GEOMETRIC
Definition variables.h:316
@ BC_HANDLER_INLET_PARABOLIC
Definition variables.h:309
@ BC_HANDLER_INLET_CONSTANT_VELOCITY
Definition variables.h:308
@ BC_HANDLER_PERIODIC_DRIVEN_INITIAL_FLUX
Definition variables.h:319
@ BC_HANDLER_INTERFACE_OVERSET
Definition variables.h:317
@ BC_HANDLER_PERIODIC_DRIVEN_CONSTANT_FLUX
Definition variables.h:318
@ BC_HANDLER_WALL_MOVING
Definition variables.h:306
@ BC_HANDLER_INLET_PROFILE_FROM_FILE
Definition variables.h:310
@ BC_HANDLER_WALL_NOSLIP
Definition variables.h:305
@ BC_HANDLER_OUTLET_CONSERVATION
Definition variables.h:314
@ BC_HANDLER_FARFIELD_NONREFLECTING
Definition variables.h:313
@ BC_HANDLER_OUTLET_PRESSURE
Definition variables.h:315
@ BC_HANDLER_SYMMETRY_PLANE
Definition variables.h:307
@ BC_HANDLER_UNDEFINED
Definition variables.h:304
Here is the caller graph for this function:

◆ DualKSPMonitor()

PetscErrorCode DualKSPMonitor ( KSP  ksp,
PetscInt  it,
PetscReal  rnorm,
void *  ctx 
)

A custom KSP monitor that logs to a file and optionally to the console.

This function unconditionally calls the standard true residual monitor to log to a file viewer provided in the context. It also checks a flag in the context and, if true, calls the monitor again to log to standard output.

Parameters
kspThe Krylov subspace context.
itThe current iteration number.
rnormThe preconditioned residual norm.
ctxA pointer to the DualMonitorCtx structure.
Returns
PetscErrorCode 0 on success.

A custom KSP monitor that logs to a file and optionally to the console.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
DualKSPMonitor()

Definition at line 870 of file logging.c.

871{
872 DualMonitorCtx *monctx = (DualMonitorCtx*)ctx;
873 PetscErrorCode ierr;
874 PetscReal trnorm, relnorm;
875 Vec r;
876 char norm_buf[256];
877 PetscMPIInt rank;
878
879 PetscFunctionBeginUser;
880 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
881
882 // 1. Calculate the true residual norm.
883 ierr = KSPBuildResidual(ksp, NULL, NULL, &r); CHKERRQ(ierr);
884 ierr = VecNorm(r, NORM_2, &trnorm); CHKERRQ(ierr);
885 ierr = VecDestroy(&r); CHKERRQ(ierr);
886
887 // 2. On the first iteration, compute and store the norm of the RHS vector `b`.
888 if (it == 0) {
889 Vec b;
890 ierr = KSPGetRhs(ksp, &b); CHKERRQ(ierr);
891 ierr = VecNorm(b, NORM_2, &monctx->bnorm); CHKERRQ(ierr);
892 }
893
894 if(!rank){
895 // 3. Compute the relative norm and format the output string.
896 if (monctx->bnorm > 1.e-15) {
897 relnorm = trnorm / monctx->bnorm;
898 sprintf(norm_buf, "ts: %-5d | block: %-2d | iter: %-3d | Unprecond Norm: %12.5e | True Norm: %12.5e | Rel Norm: %12.5e",(int)monctx->step, (int)monctx->block_id, (int)it, (double)rnorm, (double)trnorm, (double)relnorm);
899 } else {
900 sprintf(norm_buf,"ts: %-5d | block: %-2d | iter: %-3d | Unprecond Norm: %12.5e | True Norm: %12.5e",(int)monctx->step, (int)monctx->block_id, (int)it, (double)rnorm, (double)trnorm);
901 }
902
903 // 4. Log to the file viewer (unconditionally).
904 if(monctx->file_handle){
905 ierr = PetscFPrintf(PETSC_COMM_SELF,monctx->file_handle,"%s\n", norm_buf); CHKERRQ(ierr);
906 }
907 // 5. Log to the console (conditionally).
908 if (monctx->log_to_console) {
909 PetscFPrintf(PETSC_COMM_SELF,stdout, "%s\n", norm_buf); CHKERRQ(ierr);
910 }
911
912 } //rank
913
914 PetscFunctionReturn(0);
915}
PetscBool log_to_console
Definition logging.h:58
PetscReal bnorm
Definition logging.h:59
PetscInt step
Definition logging.h:60
FILE * file_handle
Definition logging.h:57
PetscInt block_id
Definition logging.h:61
Context for a dual-purpose KSP monitor.
Definition logging.h:56
Here is the caller graph for this function:

◆ DualMonitorDestroy()

PetscErrorCode DualMonitorDestroy ( void **  ctx)

Destroys the DualMonitorCtx.

This function is passed to KSPMonitorSet to ensure the viewer is properly destroyed and the context memory is freed when the KSP is destroyed.

Parameters
ctxa pointer to the context pointer to be destroyed
Returns
PetscErrorCode

Destroys the DualMonitorCtx.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
DualMonitorDestroy()

Definition at line 831 of file logging.c.

832{
833 DualMonitorCtx *monctx = (DualMonitorCtx*)*ctx;
834 PetscErrorCode ierr;
835 PetscMPIInt rank;
836
837 PetscFunctionBeginUser;
838 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
839 if(!rank && monctx->file_handle){
840 fclose(monctx->file_handle);
841 }
842
843 ierr = PetscFree(monctx); CHKERRQ(ierr);
844 *ctx = NULL;
845 PetscFunctionReturn(0);
846}
Here is the caller graph for this function:

◆ LOG_CONTINUITY_METRICS()

PetscErrorCode LOG_CONTINUITY_METRICS ( UserCtx user)

Logs continuity metrics for a single block to a file.

This function should be called for each block, once per timestep. It opens a central log file in append mode. To ensure the header is written only once, it checks if it is processing block 0 on the simulation's start step.

Parameters
userA pointer to the UserCtx for the specific block whose metrics are to be logged. The function accesses both global (SimCtx) and local (user->...) data.
Returns
PetscErrorCode 0 on success.

Logs continuity metrics for a single block to a file.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
LOG_CONTINUITY_METRICS()

Definition at line 1796 of file logging.c.

1797{
1798 PetscErrorCode ierr;
1799 PetscMPIInt rank;
1800 SimCtx *simCtx = user->simCtx; // Get the shared SimCtx
1801 const PetscInt bi = user->_this; // Get this block's specific ID
1802 const PetscInt ti = simCtx->step; // Get the current timestep
1803
1804 PetscFunctionBeginUser;
1805 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1806
1807 // Only rank 0 performs file I/O.
1808 if (!rank) {
1809 FILE *f;
1810 char filen[PETSC_MAX_PATH_LEN + 64];
1811 ierr = PetscSNPrintf(filen, sizeof(filen), "%s/Continuity_Metrics.log", simCtx->log_dir); CHKERRQ(ierr);
1812
1813 // Open the log file in append mode.
1814 f = fopen(filen, "a");
1815 if (!f) {
1816 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open log file: %s", filen);
1817 }
1818
1819 // Write a header only when the file is empty and it's the first block (bi=0).
1820 // Using ftell() instead of step comparison ensures correctness across continuations.
1821 if (ftell(f) == 0 && bi == 0) {
1822 PetscFPrintf(PETSC_COMM_SELF, f, "%-10s | %-6s | %-18s | %-30s | %-18s | %-18s | %-18s | %-18s\n",
1823 "Timestep", "Block", "Max Divergence", "Max Divergence Location ([k][j][i]=idx)", "Sum(RHS)","Total Flux In", "Total Flux Out", "Net Flux");
1824 PetscFPrintf(PETSC_COMM_SELF, f, "------------------------------------------------------------------------------------------------------------------------------------------\n");
1825 }
1826 if (simCtx->continueMode && ti == simCtx->StartStep + 1 && bi == 0) {
1827 PetscFPrintf(PETSC_COMM_SELF, f, "# Continuation from step %" PetscInt_FMT "\n", simCtx->StartStep);
1828 }
1829
1830 // Prepare the data strings and values for the current block.
1831 PetscReal net_flux = simCtx->FluxInSum - simCtx->FluxOutSum;
1832 char location_str[64];
1833 sprintf(location_str, "([%d][%d][%d] = %d)", (int)simCtx->MaxDivz, (int)simCtx->MaxDivy, (int)simCtx->MaxDivx, (int)simCtx->MaxDivFlatArg);
1834
1835 // Write the formatted line for the current block.
1836 PetscFPrintf(PETSC_COMM_SELF, f, "%-10d | %-6d | %-18.10e | %-39s | %-18.10e | %-18.10e | %-18.10e | %-18.10e\n",
1837 (int)ti,
1838 (int)bi,
1839 (double)simCtx->MaxDiv,
1840 location_str,
1841 (double)simCtx->summationRHS,
1842 (double)simCtx->FluxInSum,
1843 (double)simCtx->FluxOutSum,
1844 (double)net_flux);
1845
1846 fclose(f);
1847 }
1848
1849 PetscFunctionReturn(0);
1850}
PetscBool continueMode
Definition variables.h:712
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:909
PetscReal FluxOutSum
Definition variables.h:799
PetscInt _this
Definition variables.h:924
PetscInt StartStep
Definition variables.h:705
PetscReal MaxDiv
Definition variables.h:859
PetscInt MaxDivx
Definition variables.h:860
PetscInt MaxDivy
Definition variables.h:860
PetscInt MaxDivz
Definition variables.h:860
char log_dir[PETSC_MAX_PATH_LEN]
Definition variables.h:718
PetscInt MaxDivFlatArg
Definition variables.h:860
PetscReal FluxInSum
Definition variables.h:799
PetscInt step
Definition variables.h:703
PetscReal summationRHS
Definition variables.h:858
The master context for the entire simulation.
Definition variables.h:695
Here is the caller graph for this function:

◆ LOG_SOLUTION_CONVERGENCE()

PetscErrorCode LOG_SOLUTION_CONVERGENCE ( SimCtx simCtx)

Logs physical solution-convergence metrics once per completed timestep.

This logger is intentionally separate from the detailed inner solver-health logs. Depending on the configured mode, it records deterministic step drift, periodic phase-aligned drift, or statistical window drift into logs/solution_convergence.log.

The logger is solver-mode only and is intended to run after a completed flow-solve / projection step but before history vectors are shifted forward. Warmup rows are handled internally:

  • steady/transient mode: the first logged step has has_reference = 0
  • periodic mode: the first cycle fills the phase reference ring
  • statistical mode: window-drift fields remain zero until enough samples exist to form the requested windows

Existing detailed inner logs remain the authoritative source for momentum, Poisson, and continuity health. This logger only summarizes physical solution-drift metrics.

Parameters
[in,out]simCtxMaster simulation context controlling the logging mode and owning any supporting runtime buffers.
Returns
PetscErrorCode 0 on success.

Logs physical solution-convergence metrics once per completed timestep.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
LOG_SOLUTION_CONVERGENCE()

Definition at line 1600 of file logging.c.

1601{
1602 PetscMPIInt rank = 0;
1603 PetscBool has_reference = PETSC_FALSE;
1604 PetscInt phase_step = -1;
1605 PetscInt samples_before = 0;
1606 PetscReal u_abs_l2 = 0.0, u_rel_l2 = 0.0, p_abs_l2 = 0.0, p_rel_l2 = 0.0;
1607 PetscReal mean_speed = 0.0, mean_speed_reference = 0.0, mean_speed_abs_drift = 0.0, mean_speed_rel_drift = 0.0;
1608 PetscReal mean_ke = 0.0, mean_ke_reference = 0.0, mean_ke_abs_drift = 0.0, mean_ke_rel_drift = 0.0;
1609 PetscReal mean_speed_window = 0.0, mean_speed_window_prev = 0.0, mean_speed_window_abs_drift = 0.0, mean_speed_window_rel_drift = 0.0;
1610 PetscReal mean_speed_rms_window = 0.0, mean_speed_rms_window_prev = 0.0, mean_speed_rms_window_abs_drift = 0.0, mean_speed_rms_window_rel_drift = 0.0;
1611 PetscReal mean_ke_window = 0.0, mean_ke_window_prev = 0.0, mean_ke_window_abs_drift = 0.0, mean_ke_window_rel_drift = 0.0;
1612 PetscReal mean_ke_rms_window = 0.0, mean_ke_rms_window_prev = 0.0, mean_ke_rms_window_abs_drift = 0.0, mean_ke_rms_window_rel_drift = 0.0;
1613
1614 PetscFunctionBeginUser;
1615 if (!simCtx) PetscFunctionReturn(0);
1616 if (simCtx->exec_mode != EXEC_MODE_SOLVER) PetscFunctionReturn(0);
1617 if (!simCtx->solutionConvergenceEnabled) PetscFunctionReturn(0);
1618
1619 samples_before = simCtx->solutionConvergenceSamplesRecorded;
1620
1621 switch (simCtx->solutionConvergenceMode) {
1624 PetscCall(ComputeDeterministicSolutionMetrics(simCtx, PETSC_FALSE, -1, samples_before,
1625 &has_reference,
1626 &u_abs_l2, &u_rel_l2,
1627 &p_abs_l2, &p_rel_l2,
1628 &mean_speed, &mean_speed_reference,
1629 &mean_speed_abs_drift, &mean_speed_rel_drift,
1630 &mean_ke, &mean_ke_reference,
1631 &mean_ke_abs_drift, &mean_ke_rel_drift));
1632 break;
1634 phase_step = simCtx->solutionConvergencePeriodSteps > 0 ? (simCtx->step % simCtx->solutionConvergencePeriodSteps) : -1;
1635 PetscCall(ComputeDeterministicSolutionMetrics(simCtx, PETSC_TRUE, phase_step, samples_before,
1636 &has_reference,
1637 &u_abs_l2, &u_rel_l2,
1638 &p_abs_l2, &p_rel_l2,
1639 &mean_speed, &mean_speed_reference,
1640 &mean_speed_abs_drift, &mean_speed_rel_drift,
1641 &mean_ke, &mean_ke_reference,
1642 &mean_ke_abs_drift, &mean_ke_rel_drift));
1643 break;
1645 PetscCall(ComputeCurrentFlowObservables(simCtx, &mean_speed, &mean_ke));
1646 PetscCall(AppendStatisticalObservableSample(simCtx, samples_before, mean_speed, mean_ke));
1647 PetscCall(ComputeStatisticalWindowMetrics(simCtx, samples_before + 1,
1648 &has_reference,
1649 &mean_speed_window, &mean_speed_window_prev,
1650 &mean_speed_window_abs_drift, &mean_speed_window_rel_drift,
1651 &mean_speed_rms_window, &mean_speed_rms_window_prev,
1652 &mean_speed_rms_window_abs_drift, &mean_speed_rms_window_rel_drift,
1653 &mean_ke_window, &mean_ke_window_prev,
1654 &mean_ke_window_abs_drift, &mean_ke_window_rel_drift,
1655 &mean_ke_rms_window, &mean_ke_rms_window_prev,
1656 &mean_ke_rms_window_abs_drift, &mean_ke_rms_window_rel_drift));
1657 break;
1658 default:
1659 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown solution convergence mode %d.", (int)simCtx->solutionConvergenceMode);
1660 }
1661
1662 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1663 if (rank == 0) {
1664 char log_path[PETSC_MAX_PATH_LEN + 32];
1665 FILE *f = NULL;
1666 const char *mode_str = SolutionConvergenceModeToString(simCtx->solutionConvergenceMode);
1667
1668 PetscCall(PetscSNPrintf(log_path, sizeof(log_path), "%s/solution_convergence.log", simCtx->log_dir));
1669 f = fopen(log_path, "a");
1670 if (!f) {
1671 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open solution convergence log: %s", log_path);
1672 }
1673
1674 if (ftell(f) == 0) {
1675 switch (simCtx->solutionConvergenceMode) {
1678 fprintf(f, "==================== Solution Convergence Log [mode: %s] ====================\n", mode_str);
1679 /* 16 columns; header width = 314 chars */
1680 fprintf(f, "%-10s | %-18s | %-22s | %-3s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s\n",
1681 "step", "time", "mode", "ref",
1682 "u_abs_l2", "u_rel_l2", "p_abs_l2", "p_rel_l2",
1683 "mean_speed", "spd_ref", "spd_abs", "spd_rel",
1684 "mean_ke", "ke_ref", "ke_abs", "ke_rel");
1685 fprintf(f, "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
1686 break;
1688 fprintf(f, "==================== Solution Convergence Log [mode: %s | period_steps: %d] ====================\n",
1689 mode_str, (int)simCtx->solutionConvergencePeriodSteps);
1690 /* 18 columns; header width = 330 chars */
1691 fprintf(f, "%-10s | %-18s | %-22s | %-3s | %-5s | %-5s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s\n",
1692 "step", "time", "mode", "ref", "ph", "per",
1693 "u_abs_l2", "u_rel_l2", "p_abs_l2", "p_rel_l2",
1694 "mean_speed", "spd_ref", "spd_abs", "spd_rel",
1695 "mean_ke", "ke_ref", "ke_abs", "ke_rel");
1696 fprintf(f, "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
1697 break;
1699 fprintf(f, "==================== Solution Convergence Log [mode: %s | window_steps: %d] ====================\n",
1700 mode_str, (int)simCtx->solutionConvergenceWindowSteps);
1701 /* 21 columns; header width = 406 chars */
1702 fprintf(f, "%-10s | %-18s | %-22s | %-3s | %-5s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s | %-18s\n",
1703 "step", "time", "mode", "ref", "win",
1704 "mean_speed", "mean_ke",
1705 "spd_win", "spd_win_prev", "spd_win_abs", "spd_win_rel",
1706 "spd_rms_win", "spd_rms_abs", "spd_rms_rel",
1707 "ke_win", "ke_win_prev", "ke_win_abs", "ke_win_rel",
1708 "ke_rms_win", "ke_rms_abs", "ke_rms_rel");
1709 fprintf(f, "------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n");
1710 break;
1711 default: break;
1712 }
1713 }
1714 if (simCtx->continueMode && simCtx->step == simCtx->StartStep + 1) {
1715 fprintf(f, "# Continuation from step %" PetscInt_FMT "\n", simCtx->StartStep);
1716 }
1717
1718 switch (simCtx->solutionConvergenceMode) {
1721 fprintf(f,
1722 "%-10d | %-18.10e | %-22s | %-3d | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e\n",
1723 (int)simCtx->step, (double)simCtx->ti, mode_str, has_reference ? 1 : 0,
1724 (double)u_abs_l2, (double)u_rel_l2, (double)p_abs_l2, (double)p_rel_l2,
1725 (double)mean_speed, (double)mean_speed_reference,
1726 (double)mean_speed_abs_drift, (double)mean_speed_rel_drift,
1727 (double)mean_ke, (double)mean_ke_reference,
1728 (double)mean_ke_abs_drift, (double)mean_ke_rel_drift);
1729 break;
1731 fprintf(f,
1732 "%-10d | %-18.10e | %-22s | %-3d | %-5d | %-5d | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e\n",
1733 (int)simCtx->step, (double)simCtx->ti, mode_str, has_reference ? 1 : 0,
1734 (int)phase_step, (int)simCtx->solutionConvergencePeriodSteps,
1735 (double)u_abs_l2, (double)u_rel_l2, (double)p_abs_l2, (double)p_rel_l2,
1736 (double)mean_speed, (double)mean_speed_reference,
1737 (double)mean_speed_abs_drift, (double)mean_speed_rel_drift,
1738 (double)mean_ke, (double)mean_ke_reference,
1739 (double)mean_ke_abs_drift, (double)mean_ke_rel_drift);
1740 break;
1742 fprintf(f,
1743 "%-10d | %-18.10e | %-22s | %-3d | %-5d | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e | %-18.10e\n",
1744 (int)simCtx->step, (double)simCtx->ti, mode_str, has_reference ? 1 : 0,
1745 (int)simCtx->solutionConvergenceWindowSteps,
1746 (double)mean_speed, (double)mean_ke,
1747 (double)mean_speed_window, (double)mean_speed_window_prev,
1748 (double)mean_speed_window_abs_drift, (double)mean_speed_window_rel_drift,
1749 (double)mean_speed_rms_window,
1750 (double)mean_speed_rms_window_abs_drift, (double)mean_speed_rms_window_rel_drift,
1751 (double)mean_ke_window, (double)mean_ke_window_prev,
1752 (double)mean_ke_window_abs_drift, (double)mean_ke_window_rel_drift,
1753 (double)mean_ke_rms_window,
1754 (double)mean_ke_rms_window_abs_drift, (double)mean_ke_rms_window_rel_drift);
1755 break;
1756 default: break;
1757 }
1758 fclose(f);
1759 }
1760
1762 phase_step >= 0 && phase_step < simCtx->solutionConvergencePeriodSteps) {
1763 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
1764 for (PetscInt bi = 0; bi < simCtx->block_number; ++bi) {
1765 PetscCall(VecCopy(user[bi].Ucat, user[bi].solutionConvergencePeriodicUcatRef[phase_step]));
1766 PetscCall(VecCopy(user[bi].P, user[bi].solutionConvergencePeriodicPRef[phase_step]));
1767 }
1768 }
1769
1770 simCtx->solutionConvergenceSamplesRecorded = samples_before + 1;
1771
1772 PetscFunctionReturn(0);
1773}
static PetscErrorCode AppendStatisticalObservableSample(SimCtx *simCtx, PetscInt samples_before, PetscReal mean_speed, PetscReal mean_ke)
Appends one timestep's scalar observables to the statistical history.
Definition logging.c:1370
static const char * SolutionConvergenceModeToString(SolutionConvergenceMode mode)
Maps the internal solution-convergence mode enum to its log label.
Definition logging.c:1583
static PetscErrorCode ComputeStatisticalWindowMetrics(const SimCtx *simCtx, PetscInt samples_available, PetscBool *has_reference_out, PetscReal *mean_speed_window_out, PetscReal *mean_speed_window_prev_out, PetscReal *mean_speed_window_abs_out, PetscReal *mean_speed_window_rel_out, PetscReal *mean_speed_rms_window_out, PetscReal *mean_speed_rms_window_prev_out, PetscReal *mean_speed_rms_window_abs_out, PetscReal *mean_speed_rms_window_rel_out, PetscReal *mean_ke_window_out, PetscReal *mean_ke_window_prev_out, PetscReal *mean_ke_window_abs_out, PetscReal *mean_ke_window_rel_out, PetscReal *mean_ke_rms_window_out, PetscReal *mean_ke_rms_window_prev_out, PetscReal *mean_ke_rms_window_abs_out, PetscReal *mean_ke_rms_window_rel_out)
Computes adjacent-window drift metrics for statistical steady mode.
Definition logging.c:1450
static PetscErrorCode ComputeDeterministicSolutionMetrics(SimCtx *simCtx, PetscBool periodic_mode, PetscInt phase_step, PetscInt samples_before, PetscBool *has_reference_out, PetscReal *u_abs_l2_out, PetscReal *u_rel_l2_out, PetscReal *p_abs_l2_out, PetscReal *p_rel_l2_out, PetscReal *mean_speed_out, PetscReal *mean_speed_ref_out, PetscReal *mean_speed_abs_out, PetscReal *mean_speed_rel_out, PetscReal *mean_ke_out, PetscReal *mean_ke_ref_out, PetscReal *mean_ke_abs_out, PetscReal *mean_ke_rel_out)
Computes deterministic solution-drift metrics for the current step.
Definition logging.c:1092
static PetscErrorCode ComputeCurrentFlowObservables(SimCtx *simCtx, PetscReal *mean_speed_out, PetscReal *mean_ke_out)
Computes instantaneous global flow observables for statistical mode.
Definition logging.c:976
UserCtx * user
Definition variables.h:571
PetscInt block_number
Definition variables.h:790
UserMG usermg
Definition variables.h:852
PetscInt solutionConvergenceSamplesRecorded
Definition variables.h:765
PetscBool solutionConvergenceEnabled
Definition variables.h:761
PetscInt solutionConvergencePeriodSteps
Definition variables.h:763
PetscInt mglevels
Definition variables.h:578
PetscInt solutionConvergenceWindowSteps
Definition variables.h:764
@ EXEC_MODE_SOLVER
Definition variables.h:668
MGCtx * mgctx
Definition variables.h:581
@ SOLUTION_CONVERGENCE_TRANSIENT
Definition variables.h:547
@ SOLUTION_CONVERGENCE_PERIODIC_DETERMINISTIC
Definition variables.h:545
@ SOLUTION_CONVERGENCE_STATISTICAL_STEADY
Definition variables.h:546
@ SOLUTION_CONVERGENCE_STEADY_DETERMINISTIC
Definition variables.h:544
SolutionConvergenceMode solutionConvergenceMode
Definition variables.h:762
ExecutionMode exec_mode
Definition variables.h:714
PetscReal ti
Definition variables.h:704
User-defined context containing data specific to a single computational grid level.
Definition variables.h:906
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ParticleLocationStatusToString()

const char * ParticleLocationStatusToString ( ParticleLocationStatus  level)

A function that outputs the name of the current level in the ParticleLocation enum.

Parameters
levelThe ParticleLocation enum value.
Returns
A constant character string corresponding to the enum. Returns "UNKNOWN_LEVEL" if the enum value is not recognized.

A function that outputs the name of the current level in the ParticleLocation enum.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
ParticleLocationStatusToString()

Definition at line 1858 of file logging.c.

1859{
1860 switch (level) {
1861 case NEEDS_LOCATION: return "NEEDS_LOCATION";
1862 case ACTIVE_AND_LOCATED: return "ACTIVE_AND_LOCATED";
1863 case MIGRATING_OUT: return "MIGRATING_OUT";
1864 case LOST: return "LOST";
1865 case UNINITIALIZED: return "UNINITIALIZED";
1866 default: return "UNKNOWN_LEVEL";
1867 }
1868}
@ LOST
Definition variables.h:141
@ NEEDS_LOCATION
Definition variables.h:138
@ ACTIVE_AND_LOCATED
Definition variables.h:139
@ UNINITIALIZED
Definition variables.h:142
@ MIGRATING_OUT
Definition variables.h:140
Here is the caller graph for this function:

◆ PrintProgressBar()

void PrintProgressBar ( PetscInt  step,
PetscInt  startStep,
PetscInt  totalSteps,
PetscReal  currentTime 
)

Prints a progress bar to the console.

This function should only be called by the root process (rank 0). It uses a carriage return \r to overwrite the same line in the terminal, creating a dynamic progress bar.

Parameters
stepThe current step index from the loop (e.g., from 0 to N-1).
startStepThe global starting step number of the simulation.
totalStepsThe total number of steps to be run in this simulation instance.
currentTimeThe current simulation time to display.

Prints a progress bar to the console.

Local to this translation unit.

Definition at line 2302 of file logging.c.

2303{
2304 if (totalSteps <= 0) return;
2305
2306 // --- Configuration ---
2307 const int barWidth = 50;
2308
2309 // --- Calculation ---
2310 // Calculate progress as a fraction from 0.0 to 1.0
2311 PetscReal progress = (PetscReal)(step - startStep + 1) / totalSteps;
2312 // Ensure progress doesn't exceed 1.0 due to floating point inaccuracies
2313 if (progress > 1.0) progress = 1.0;
2314
2315 int pos = (int)(barWidth * progress);
2316
2317 // --- Printing ---
2318 // Carriage return moves cursor to the beginning of the line
2319 PetscPrintf(PETSC_COMM_SELF, "\rProgress: [");
2320
2321 for (int i = 0; i < barWidth; ++i) {
2322 if (i < pos) {
2323 PetscPrintf(PETSC_COMM_SELF, "=");
2324 } else if (i == pos) {
2325 PetscPrintf(PETSC_COMM_SELF, ">");
2326 } else {
2327 PetscPrintf(PETSC_COMM_SELF, " ");
2328 }
2329 }
2330
2331 // Print percentage, step count, and current time
2332 PetscPrintf(PETSC_COMM_SELF, "] %3d%% (Step %" PetscInt_FMT "/%" PetscInt_FMT ", t=%.4f)",
2333 (int)(progress * 100.0),
2334 step + 1,
2335 startStep + totalSteps,
2336 currentTime);
2337
2338 // Flush the output buffer to ensure the bar is displayed immediately
2339 fflush(stdout);
2340}
Here is the caller graph for this function:

◆ ProfilingInitialize()

PetscErrorCode ProfilingInitialize ( SimCtx simCtx)

Initializes the custom profiling system using configuration from SimCtx.

This function sets up the internal data structures for tracking function performance. It reads the list of "critical functions" from the provided SimCtx and marks them for per-step logging at LOG_INFO level.

It should be called once at the beginning of the application, after CreateSimulationContext() but before the main time loop.

Parameters
simCtxThe master simulation context, which contains the list of critical function names to always log.
Returns
PetscErrorCode

Initializes the custom profiling system using configuration from SimCtx.

Local to this translation unit.

Definition at line 1928 of file logging.c.

1929{
1930 PetscFunctionBeginUser;
1931 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "SimCtx cannot be null for ProfilingInitialize");
1932
1933 // Iterate through the list of critical functions provided in SimCtx
1934 for (PetscInt i = 0; i < simCtx->nProfilingSelectedFuncs; ++i) {
1935 PetscInt idx;
1936 const char *func_name = simCtx->profilingSelectedFuncs[i];
1937 PetscErrorCode ierr = _FindOrCreateEntry(func_name, &idx); CHKERRQ(ierr);
1938 g_profiler_registry[idx].always_log = PETSC_TRUE;
1939
1940 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Marked '%s' as a critical function for profiling.\n", func_name);
1941 }
1942 PetscFunctionReturn(0);
1943}
PetscBool always_log
Definition logging.c:1880
static PetscErrorCode _FindOrCreateEntry(const char *func_name, PetscInt *idx)
Find a profiling record by name or allocate and register a new record.
Definition logging.c:1892
static ProfiledFunction * g_profiler_registry
Definition logging.c:1884
char ** profilingSelectedFuncs
Definition variables.h:864
PetscInt nProfilingSelectedFuncs
Definition variables.h:865
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ProfilingResetTimestepCounters()

PetscErrorCode ProfilingResetTimestepCounters ( void  )

Resets per-timestep profiling counters for the next solver step.

This clears transient counters without discarding cumulative totals used by final profiling summaries.

Returns
PetscErrorCode 0 on success.

Resets per-timestep profiling counters for the next solver step.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
ProfilingResetTimestepCounters()

Definition at line 1988 of file logging.c.

1989{
1990 PetscFunctionBeginUser;
1991 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1994 }
1995 PetscFunctionReturn(0);
1996}
static PetscInt g_profiler_count
Definition logging.c:1885
double current_step_time
Definition logging.c:1876
long long current_step_call_count
Definition logging.c:1878
Here is the caller graph for this function:

◆ ProfilingLogTimestepSummary()

PetscErrorCode ProfilingLogTimestepSummary ( SimCtx simCtx,
PetscInt  step 
)

Logs the performance summary for the current timestep and resets timers.

Depending on the configured profiling timestep mode, this function writes per-step profiling rows to the configured profiling log file:

  • off: writes nothing
  • selected: writes only functions marked for per-step reporting
  • all: writes every instrumented function that ran in the timestep

It must be called once per timestep, typically at the end of the main loop. After logging, it resets the per-step counters and timers.

Parameters
simCtxThe simulation context holding profiling output settings.
stepThe current simulation step number, for logging context.
Returns
PetscErrorCode

Logs the performance summary for the current timestep and resets timers.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
ProfilingLogTimestepSummary()

Definition at line 2005 of file logging.c.

2006{
2007 PetscBool should_write = PETSC_FALSE;
2008 FILE *f = NULL;
2009 char filen[(2 * PETSC_MAX_PATH_LEN) + 16];
2010
2011 PetscFunctionBeginUser;
2012 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "SimCtx cannot be null for ProfilingLogTimestepSummary");
2013
2014 if (strcmp(simCtx->profilingTimestepMode, "off") == 0) {
2015 for (PetscInt i = 0; i < g_profiler_count; ++i) {
2018 }
2019 PetscFunctionReturn(0);
2020 }
2021
2022 for (PetscInt i = 0; i < g_profiler_count; ++i) {
2023 if (g_profiler_registry[i].current_step_call_count <= 0) {
2024 continue;
2025 }
2026 if (strcmp(simCtx->profilingTimestepMode, "all") == 0 || g_profiler_registry[i].always_log) {
2027 should_write = PETSC_TRUE;
2028 break;
2029 }
2030 }
2031
2032 if (should_write && simCtx->rank == 0) {
2033 snprintf(filen, sizeof(filen), "%s/%s", simCtx->log_dir, simCtx->profilingTimestepFile);
2034 if (step == simCtx->StartStep + 1 && !simCtx->continueMode) {
2035 f = fopen(filen, "w");
2036 if (!f) {
2037 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open profiling timestep log file: %s", filen);
2038 }
2039 PetscFPrintf(PETSC_COMM_SELF, f, "step,function,calls,step_time_s\n");
2040 } else {
2041 f = fopen(filen, "a");
2042 if (!f) {
2043 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open profiling timestep log file: %s", filen);
2044 }
2045 if (step == simCtx->StartStep + 1 && ftell(f) == 0) {
2046 PetscFPrintf(PETSC_COMM_SELF, f, "step,function,calls,step_time_s\n");
2047 }
2048 }
2049 if (simCtx->continueMode && step == simCtx->StartStep + 1) {
2050 PetscFPrintf(PETSC_COMM_SELF, f, "# Continuation from step %" PetscInt_FMT "\n", simCtx->StartStep);
2051 }
2052
2053 for (PetscInt i = 0; i < g_profiler_count; ++i) {
2054 if (g_profiler_registry[i].current_step_call_count <= 0) {
2055 continue;
2056 }
2057 if (strcmp(simCtx->profilingTimestepMode, "all") == 0 || g_profiler_registry[i].always_log) {
2058 PetscFPrintf(
2059 PETSC_COMM_SELF,
2060 f,
2061 "%d,%s,%lld,%.6f\n",
2062 (int)step,
2063 g_profiler_registry[i].name,
2064 g_profiler_registry[i].current_step_call_count,
2065 g_profiler_registry[i].current_step_time
2066 );
2067 }
2068 }
2069 fclose(f);
2070 }
2071
2072 // Reset per-step counters for the next iteration
2073 for (PetscInt i = 0; i < g_profiler_count; ++i) {
2076 }
2077 PetscFunctionReturn(0);
2078}
PetscMPIInt rank
Definition variables.h:698
char profilingTimestepFile[PETSC_MAX_PATH_LEN]
Definition variables.h:867
char profilingTimestepMode[32]
Definition variables.h:866
Here is the caller graph for this function:

◆ RuntimeMemoryLogSample()

PetscErrorCode RuntimeMemoryLogSample ( SimCtx simCtx,
PetscInt  step,
const char *  event,
const char *  reason 
)

Append a reduced runtime memory sample to the configured memory log.

The log is intentionally compact: every rank samples process/PETSc allocator memory, one max reduction summarizes the job, and rank 0 appends one terminal-readable row.

Parameters
simCtxThe simulation context holding log directory and memory log settings.
stepThe solver/post step associated with the sample.
eventHuman-readable event label such as "Step", "Post", "Shutdown", or "Final".
reasonHuman-readable reason, or NULL/"-" when not applicable.
Returns
PetscErrorCode

Append a reduced runtime memory sample to the configured memory log.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
RuntimeMemoryLogSample()

Definition at line 2086 of file logging.c.

2087{
2088 PetscErrorCode ierr;
2089 PetscLogDouble process_current_bytes = 0.0;
2090 PetscLogDouble process_peak_bytes = 0.0;
2091 PetscLogDouble petsc_current_bytes = 0.0;
2092 PetscLogDouble petsc_peak_bytes = 0.0;
2093 PetscReal local_values[5];
2094 PetscReal global_values[5];
2095 PetscReal process_current_mb = 0.0;
2096 PetscReal process_peak_mb = 0.0;
2097 PetscReal petsc_current_mb = 0.0;
2098 PetscReal petsc_peak_mb = 0.0;
2099 PetscReal process_change_mb = 0.0;
2100 char path[(2 * PETSC_MAX_PATH_LEN) + 16];
2101 FILE *f = NULL;
2102
2103 PetscFunctionBeginUser;
2104 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "SimCtx cannot be null for RuntimeMemoryLogSample");
2105 if (!simCtx->runtimeMemoryLogEnabled) PetscFunctionReturn(0);
2106
2107 ierr = PetscMemoryGetCurrentUsage(&process_current_bytes); CHKERRQ(ierr);
2108 ierr = PetscMemoryGetMaximumUsage(&process_peak_bytes); CHKERRQ(ierr);
2109 ierr = PetscMallocGetCurrentUsage(&petsc_current_bytes); CHKERRQ(ierr);
2110 ierr = PetscMallocGetMaximumUsage(&petsc_peak_bytes); CHKERRQ(ierr);
2111
2112 process_current_mb = (PetscReal)(process_current_bytes / (1024.0 * 1024.0));
2113 process_peak_mb = (PetscReal)(process_peak_bytes / (1024.0 * 1024.0));
2114 petsc_current_mb = (PetscReal)(petsc_current_bytes / (1024.0 * 1024.0));
2115 petsc_peak_mb = (PetscReal)(petsc_peak_bytes / (1024.0 * 1024.0));
2116 if (simCtx->runtimeMemoryLogHasPrevious) {
2117 process_change_mb = process_current_mb - simCtx->runtimeMemoryLogPreviousProcessMB;
2118 }
2119
2120 local_values[0] = process_current_mb;
2121 local_values[1] = process_peak_mb;
2122 local_values[2] = petsc_current_mb;
2123 local_values[3] = petsc_peak_mb;
2124 local_values[4] = process_change_mb;
2125 ierr = MPI_Allreduce(local_values, global_values, 5, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD); CHKERRMPI(ierr);
2126
2127 simCtx->runtimeMemoryLogPreviousProcessMB = process_current_mb;
2128 simCtx->runtimeMemoryLogHasPrevious = PETSC_TRUE;
2129
2130 if (simCtx->rank == 0) {
2131 ierr = PetscSNPrintf(path, sizeof(path), "%s/%s", simCtx->log_dir, simCtx->runtimeMemoryLogFile); CHKERRQ(ierr);
2132 f = fopen(path, "a");
2133 if (!f) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open runtime memory log file: %s", path);
2134
2135 if (!simCtx->runtimeMemoryLogStarted) {
2136 fprintf(f, "# PICurv runtime memory log\n");
2137 if (simCtx->continueMode) {
2138 fprintf(f, "# Continuation from step %" PetscInt_FMT "\n", simCtx->StartStep);
2139 }
2140 fprintf(
2141 f,
2142 "%-8s %-10s %22s %20s %22s %28s %22s %-18s\n",
2143 "Step",
2144 "Event",
2145 "Process Current MB Max",
2146 "Process Peak MB Max",
2147 "PETSc Allocated MB Max",
2148 "PETSc Peak Allocated MB Max",
2149 "Process Change MB Max",
2150 "Reason"
2151 );
2152 simCtx->runtimeMemoryLogStarted = PETSC_TRUE;
2153 }
2154
2155 fprintf(
2156 f,
2157 "%-8" PetscInt_FMT " %-10s %22.3f %20.3f %22.3f %28.3f %22.3f %-18s\n",
2158 step,
2159 event ? event : "-",
2160 (double)global_values[0],
2161 (double)global_values[1],
2162 (double)global_values[2],
2163 (double)global_values[3],
2164 (double)global_values[4],
2165 (reason && reason[0]) ? reason : "-"
2166 );
2167 if ((event && (strcmp(event, "Shutdown") == 0 || strcmp(event, "Final") == 0))) {
2168 fflush(f);
2169 }
2170 fclose(f);
2171 }
2172
2173 PetscFunctionReturn(0);
2174}
PetscBool runtimeMemoryLogEnabled
Enable the rank-reduced runtime memory log.
Definition variables.h:883
char runtimeMemoryLogFile[PETSC_MAX_PATH_LEN]
File name written under log_dir.
Definition variables.h:884
PetscBool runtimeMemoryLogStarted
True after rank 0 writes the log header.
Definition variables.h:885
PetscBool runtimeMemoryLogHasPrevious
True after the first process-memory sample.
Definition variables.h:886
PetscReal runtimeMemoryLogPreviousProcessMB
Previous local process memory sample in MB.
Definition variables.h:887
Here is the caller graph for this function:

◆ ProfilingFinalize()

PetscErrorCode ProfilingFinalize ( SimCtx simCtx)

the profiling excercise and build a profiling summary which is then printed to a log file.

Parameters
simCtxThe Simulation Context Structure that can contains all the data regarding the simulation.
Returns
PetscErrorCode 0 on success.

the profiling excercise and build a profiling summary which is then printed to a log file.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
ProfilingFinalize()

Definition at line 2196 of file logging.c.

2197{
2198 PetscErrorCode ierr;
2199 PetscInt rank = simCtx->rank;
2200 PetscFunctionBeginUser;
2201 if (!simCtx->profilingFinalSummary) PetscFunctionReturn(0);
2202 if (!rank) {
2203
2204 char exec_mode_modifier[32] = "Unknown";
2205 if(simCtx->exec_mode == EXEC_MODE_SOLVER) PetscCall(PetscStrncpy(exec_mode_modifier, "Solver", sizeof(exec_mode_modifier)));
2206 else if(simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR) PetscCall(PetscStrncpy(exec_mode_modifier, "PostProcessor", sizeof(exec_mode_modifier)));
2207 //--- Step 0: Create a file viewer for log file
2208 FILE *f;
2209 char filen[PETSC_MAX_PATH_LEN + 128];
2210 ierr = PetscSNPrintf(filen, sizeof(filen), "%s/ProfilingSummary_%s.log",simCtx->log_dir,exec_mode_modifier); CHKERRQ(ierr);
2211
2212 // Open the log file: append with section label in continue mode, truncate otherwise.
2213 if (simCtx->continueMode) {
2214 f = fopen(filen, "a");
2215 if (!f) {
2216 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open log file: %s", filen);
2217 }
2218 fprintf(f, "\n=== Continuation from step %" PetscInt_FMT " ===\n", simCtx->StartStep);
2219 } else {
2220 f = fopen(filen, "w");
2221 if (!f) {
2222 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open log file: %s", filen);
2223 }
2224 }
2225
2226 // --- Step 1: Sort the data for readability ---
2228
2229 // --- Step 2: Dynamically determine the width for the function name column ---
2230 PetscInt max_name_len = strlen("Function"); // Start with the header's length
2231 for (PetscInt i = 0; i < g_profiler_count; ++i) {
2232 if (g_profiler_registry[i].total_call_count > 0) {
2233 PetscInt len = strlen(g_profiler_registry[i].name);
2234 if (len > max_name_len) {
2235 max_name_len = len;
2236 }
2237 }
2238 }
2239 // Add a little padding
2240 max_name_len += 2;
2241
2242 // --- Step 3: Define fixed widths for numeric columns for consistent alignment ---
2243 const int time_width = 18;
2244 const int count_width = 15;
2245 const int avg_width = 22;
2246
2247 // --- Step 4: Print the formatted table ---
2248 PetscFPrintf(PETSC_COMM_SELF, f, "=================================================================================================================\n");
2249 PetscFPrintf(PETSC_COMM_SELF, f, " FINAL PROFILING SUMMARY (Sorted by Total Time)\n");
2250 PetscFPrintf(PETSC_COMM_SELF, f, "=================================================================================================================\n");
2251
2252 // Header Row
2253 PetscFPrintf(PETSC_COMM_SELF, f, "%-*s | %-*s | %-*s | %-*s\n",
2254 max_name_len, "Function",
2255 time_width, "Total Time (s)",
2256 count_width, "Call Count",
2257 avg_width, "Avg. Time/Call (ms)");
2258
2259 // Separator Line (dynamically sized)
2260 for (int i = 0; i < max_name_len; i++) PetscFPrintf(PETSC_COMM_SELF, f, "-");
2261 PetscFPrintf(PETSC_COMM_SELF, f, "-|-");
2262 for (int i = 0; i < time_width; i++) PetscFPrintf(PETSC_COMM_SELF, f, "-");
2263 PetscFPrintf(PETSC_COMM_SELF, f, "-|-");
2264 for (int i = 0; i < count_width; i++) PetscFPrintf(PETSC_COMM_SELF, f, "-");
2265 PetscFPrintf(PETSC_COMM_SELF, f, "-|-");
2266 for (int i = 0; i < avg_width; i++) PetscFPrintf(PETSC_COMM_SELF, f, "-");
2267 PetscFPrintf(PETSC_COMM_SELF, f, "\n");
2268
2269 // Data Rows
2270 for (PetscInt i = 0; i < g_profiler_count; ++i) {
2271 if (g_profiler_registry[i].total_call_count > 0) {
2272 double avg_time_ms = (g_profiler_registry[i].total_time / g_profiler_registry[i].total_call_count) * 1000.0;
2273 PetscFPrintf(PETSC_COMM_SELF, f, "%-*s | %*.*f | %*lld | %*.*f\n",
2274 max_name_len, g_profiler_registry[i].name,
2275 time_width, 6, g_profiler_registry[i].total_time,
2276 count_width, g_profiler_registry[i].total_call_count,
2277 avg_width, 6, avg_time_ms);
2278 PetscFPrintf(PETSC_COMM_SELF, f, "------------------------------------------------------------------------------------------------------------------\n");
2279 }
2280 }
2281 PetscFPrintf(PETSC_COMM_SELF, f, "==================================================================================================================\n");
2282
2283 fclose(f);
2284 }
2285
2286 // --- Final Cleanup ---
2287 PetscFree(g_profiler_registry);
2288 g_profiler_registry = NULL;
2289 g_profiler_count = 0;
2291 PetscFunctionReturn(0);
2292}
long long total_call_count
Definition logging.c:1877
static PetscInt g_profiler_capacity
Definition logging.c:1886
double total_time
Definition logging.c:1875
static int _CompareProfiledFunctions(const void *a, const void *b)
Order profiling records by their accumulated execution time.
Definition logging.c:2180
PetscBool profilingFinalSummary
Definition variables.h:868
@ EXEC_MODE_POSTPROCESSOR
Definition variables.h:669
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _ProfilingStart()

void _ProfilingStart ( const char *  func_name)

Internal profiling hook invoked by PROFILE_FUNCTION_BEGIN.

Parameters
func_nameFunction name used by the profiling helper.

Internal profiling hook invoked by PROFILE_FUNCTION_BEGIN.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
_ProfilingStart()

Definition at line 1952 of file logging.c.

1953{
1954 PetscInt idx;
1955 if (_FindOrCreateEntry(func_name, &idx) != 0) return; // Fail silently
1956 PetscTime(&g_profiler_registry[idx].start_time);
1957}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _ProfilingEnd()

void _ProfilingEnd ( const char *  func_name)

Internal profiling hook invoked by PROFILE_FUNCTION_END.

Parameters
func_nameFunction name used by the profiling helper.

Internal profiling hook invoked by PROFILE_FUNCTION_END.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
_ProfilingEnd()

Definition at line 1966 of file logging.c.

1967{
1968 double end_time;
1969 PetscTime(&end_time);
1970
1971 PetscInt idx;
1972 if (_FindOrCreateEntry(func_name, &idx) != 0) return; // Fail silently
1973
1974 double elapsed = end_time - g_profiler_registry[idx].start_time;
1975 g_profiler_registry[idx].total_time += elapsed;
1976 g_profiler_registry[idx].current_step_time += elapsed;
1979}
double start_time
Definition logging.c:1879
Here is the call graph for this function:
Here is the caller graph for this function:

◆ LOG_FIELD_MIN_MAX()

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.

This utility function inspects a PETSc Vec associated with a DMDA and calculates the minimum and maximum values for each of its three components (e.g., x, y, z) both for the local data on the current MPI rank and for the entire global domain.

It uses the same "smart" logic as the flow solver, ignoring the padding nodes at the IM, JM, and KM boundaries of the grid. The results are printed to the standard output in a formatted, easy-to-read table.

Parameters
[in]userPointer to the user-defined context. Used for grid information (IM, JM, KM) and MPI rank.
[in]field_idTyped identity of the field being analyzed.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Computes and logs the local and global min/max values of a 3-component vector field.

Full API contract is documented with the header declaration in include/logging.h.

See also
LOG_FIELD_MIN_MAX()

Definition at line 2349 of file logging.c.

2350{
2351 PetscErrorCode ierr;
2352 PetscInt i, j, k;
2353 DMDALocalInfo info;
2354
2355 FieldView view;
2356 Vec fieldVec = NULL;
2357 DM dm = NULL;
2358 PetscInt dof;
2359 FieldLayout layout;
2360 const char *fieldName = NULL;
2361 const char *data_layout = NULL;
2362
2363 PetscFunctionBeginUser;
2364
2365 ierr = FieldGetView(user, field_id, &view); CHKERRQ(ierr);
2366 fieldName = view.descriptor->canonical_name;
2367 dm = view.dm;
2368 dof = view.descriptor->dof;
2369 layout = view.descriptor->layout;
2370 data_layout = FieldLayoutName(layout);
2371 fieldVec = (layout == FIELD_LAYOUT_COMPONENT_STAGGERED) ? view.local_vec : view.global_vec;
2372
2373 ierr = DMDAGetLocalInfo(dm, &info); CHKERRQ(ierr);
2374
2375 // --- 2. Define Architecture-Aware Loop Bounds ---
2376 PetscInt i_start, i_end, j_start, j_end, k_start, k_end;
2377
2378 if (layout == FIELD_LAYOUT_CELL_CENTERED) {
2379 // For cell-centered data, the physical values are stored from index 1 to N-1.
2380 // We find the intersection of the rank's owned range [xs, xe) with the
2381 // physical data range [1, IM-1).
2382 i_start = PetscMax(info.xs, 1); i_end = PetscMin(info.xs + info.xm, user->IM);
2383 j_start = PetscMax(info.ys, 1); j_end = PetscMin(info.ys + info.ym, user->JM);
2384 k_start = PetscMax(info.zs, 1); k_end = PetscMin(info.zs + info.zm, user->KM);
2385 } else { // For Node- or Face-Centered data
2386 // The physical values are stored from index 0 to N-1.
2387 // We find the intersection of the rank's owned range [xs, xe) with the
2388 // physical data range [0, IM-1].
2389 i_start = PetscMax(info.xs, 0); i_end = PetscMin(info.xs + info.xm, user->IM);
2390 j_start = PetscMax(info.ys, 0); j_end = PetscMin(info.ys + info.ym, user->JM);
2391 k_start = PetscMax(info.zs, 0); k_end = PetscMin(info.zs + info.zm, user->KM);
2392 }
2393
2394 // --- 3. Barrier for clean, grouped output ---
2395 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRQ(ierr);
2396 if (user->simCtx->rank == 0) {
2397 PetscPrintf(PETSC_COMM_SELF, "\n--- Field Ranges: [%s] (Layout: %s) ---\n", fieldName, data_layout);
2398 }
2399
2400 // --- 4. Branch on DoF and perform calculation with correct bounds ---
2401 if (dof == 1) {
2402 PetscReal localMin = PETSC_MAX_REAL, localMax = PETSC_MIN_REAL;
2403 PetscReal globalMin, globalMax;
2404 const PetscScalar ***array;
2405
2406 ierr = DMDAVecGetArrayRead(dm, fieldVec, &array); CHKERRQ(ierr);
2407 for (k = k_start; k < k_end; k++) {
2408 for (j = j_start; j < j_end; j++) {
2409 for (i = i_start; i < i_end; i++) {
2410 localMin = PetscMin(localMin, array[k][j][i]);
2411 localMax = PetscMax(localMax, array[k][j][i]);
2412 }
2413 }
2414 }
2415 ierr = DMDAVecRestoreArrayRead(dm, fieldVec, &array); CHKERRQ(ierr);
2416
2417 ierr = MPI_Allreduce(&localMin, &globalMin, 1, MPIU_REAL, MPI_MIN, PETSC_COMM_WORLD); CHKERRQ(ierr);
2418 ierr = MPI_Allreduce(&localMax, &globalMax, 1, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD); CHKERRQ(ierr);
2419
2420 PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [Rank %d] Local Range: [ %11.4e , %11.4e ]\n", user->simCtx->rank, localMin, localMax);
2421 ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT); CHKERRQ(ierr);
2422 if (user->simCtx->rank == 0) {
2423 PetscPrintf(PETSC_COMM_SELF, " Global Range: [ %11.4e , %11.4e ]\n", globalMin, globalMax);
2424 }
2425
2426 } else if (dof == 3) {
2427 Cmpnts localMin = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL};
2428 Cmpnts localMax = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
2429 Cmpnts globalMin, globalMax;
2430 const Cmpnts ***array;
2431
2432 ierr = DMDAVecGetArrayRead(dm, fieldVec, &array); CHKERRQ(ierr);
2433 for (k = k_start; k < k_end; k++) {
2434 for (j = j_start; j < j_end; j++) {
2435 for (i = i_start; i < i_end; i++) {
2436 localMin.x = PetscMin(localMin.x, array[k][j][i].x);
2437 localMin.y = PetscMin(localMin.y, array[k][j][i].y);
2438 localMin.z = PetscMin(localMin.z, array[k][j][i].z);
2439 localMax.x = PetscMax(localMax.x, array[k][j][i].x);
2440 localMax.y = PetscMax(localMax.y, array[k][j][i].y);
2441 localMax.z = PetscMax(localMax.z, array[k][j][i].z);
2442 }
2443 }
2444 }
2445 ierr = DMDAVecRestoreArrayRead(dm, fieldVec, &array); CHKERRQ(ierr);
2446
2447 ierr = MPI_Allreduce(&localMin, &globalMin, 3, MPIU_REAL, MPI_MIN, PETSC_COMM_WORLD); CHKERRQ(ierr);
2448 ierr = MPI_Allreduce(&localMax, &globalMax, 3, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD); CHKERRQ(ierr);
2449
2450 ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [Rank %d] Local X-Range: [ %11.4e , %11.4e ]\n", user->simCtx->rank, localMin.x, localMax.x);
2451 ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [Rank %d] Local Y-Range: [ %11.4e , %11.4e ]\n", user->simCtx->rank, localMin.y, localMax.y);
2452 ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [Rank %d] Local Z-Range: [ %11.4e , %11.4e ]\n", user->simCtx->rank, localMin.z, localMax.z);
2453 ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT); CHKERRQ(ierr);
2454
2455 if (user->simCtx->rank == 0) {
2456 PetscPrintf(PETSC_COMM_SELF, " [Global] X-Range: [ %11.4e , %11.4e ]\n", globalMin.x, globalMax.x);
2457 PetscPrintf(PETSC_COMM_SELF, " [Global] Y-Range: [ %11.4e , %11.4e ]\n", globalMin.y, globalMax.y);
2458 PetscPrintf(PETSC_COMM_SELF, " [Global] Z-Range: [ %11.4e , %11.4e ]\n", globalMin.z, globalMax.z);
2459 }
2460
2461 } else {
2462 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "LogFieldStatistics only supports fields with 1 or 3 components, but field '%s' has %" PetscInt_FMT ".", fieldName, dof);
2463 }
2464
2465 // --- 5. Final barrier for clean output ordering ---
2466 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRQ(ierr);
2467 if (user->simCtx->rank == 0) {
2468 PetscPrintf(PETSC_COMM_SELF, "--------------------------------------------\n\n");
2469 }
2470
2471 PetscFunctionReturn(0);
2472}
FieldLayout layout
const FieldDescriptor * descriptor
PetscErrorCode FieldGetView(UserCtx *user, FieldId field_id, FieldView *view)
Resolve the existing DM and global/local vectors for one field.
FieldLayout
Logical storage topology of a field.
@ FIELD_LAYOUT_CELL_CENTERED
@ FIELD_LAYOUT_COMPONENT_STAGGERED
const char * canonical_name
const char * FieldLayoutName(FieldLayout layout)
Return a stable printable label for a field layout.
Non-owning runtime objects resolved for one field and UserCtx.
PetscInt KM
Definition variables.h:920
PetscInt JM
Definition variables.h:920
PetscInt IM
Definition variables.h:920
A 3D point or vector with PetscScalar components.
Definition variables.h:102
Here is the call graph for this function:
Here is the caller graph for this function:

◆ LOG_FIELD_ANATOMY()

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 grid and variable architecture.

This intelligent diagnostic function inspects a PETSc Vec and prints its values at critical boundary locations (-Xi/+Xi, -Eta/+Eta, -Zeta/+Zeta). It is "architecture-aware":

  • Cell-Centered Fields ("Ucat", "P"): It correctly applies the "Shifted Index Architecture," where the value for geometric Cell i is stored at array index i+1. It labels the output to clearly distinguish between true physical values and ghost values.
  • Single-Face-Family Fields: Csi/ICsi/IEta/IZet/Centx belong to the I-face family, with corresponding J- and K-face families.
  • Component-Staggered Fields ("Ucont" and histories): x/y/z components live on I/J/K faces respectively.
  • Node-Centered Fields ("Coordinates"): It uses a direct index mapping, where the value for Node i is stored at index i.

The output is synchronized across MPI ranks to ensure readability and focuses on a slice through the center of the domain to be concise.

Parameters
userA pointer to the UserCtx structure containing the DMs and Vecs.
field_idTyped identity of the persistent Eulerian field to log.
stage_nameA string identifier for the current simulation stage (e.g., "After Advection").
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Logs the anatomy of a specified field at key boundary locations, respecting the solver's specific grid and variable architecture.

See also
LOG_FIELD_ANATOMY()

Definition at line 2752 of file logging.c.

2753{
2754 FieldView view;
2755
2756 PetscFunctionBeginUser;
2757 PetscCall(FieldGetView(user, field_id, &view));
2758 PetscCall(LogFieldAnatomyView(user, view.descriptor->canonical_name, stage_name,
2759 view.dm, view.local_vec, view.descriptor->dof,
2760 view.descriptor->layout));
2761 PetscFunctionReturn(0);
2762}
static PetscErrorCode LogFieldAnatomyView(UserCtx *user, const char *field_name, const char *stage_name, DM dm, Vec vec_local, PetscInt dof, FieldLayout layout)
Shared architecture-aware anatomy logger for catalog and transient fields.
Definition logging.c:2479
Here is the call graph for this function:
Here is the caller graph for this function:

◆ LOG_CORNER_FIELD_ANATOMY()

PetscErrorCode LOG_CORNER_FIELD_ANATOMY ( UserCtx user,
FieldId  corner_field_id,
const char *  stage_name 
)

Logs the node-layout anatomy of the transient center-to-corner interpolation field.

Parameters
userContext owning the corner-staging workspace.
corner_field_idWhich corner workspace the caller populated.
stage_namePrintable simulation stage.
Returns
Zero on success.

Logs the node-layout anatomy of the transient center-to-corner interpolation field.

See also
LOG_CORNER_FIELD_ANATOMY()

Definition at line 2838 of file logging.c.

2839{
2840 FieldView view;
2841
2842 PetscFunctionBeginUser;
2843 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx cannot be NULL.");
2844 PetscCheck(corner_field_id == FIELD_ID_CELL_SCALAR_AT_CORNER ||
2845 corner_field_id == FIELD_ID_CELL_VECTOR_AT_CORNER,
2846 PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
2847 "Corner anatomy logging expects a corner-staging field identity.");
2848 /* The caller states which workspace it used, so the degree of freedom and DM
2849 * come from the catalog instead of being inferred from a cached vector. */
2850 PetscCall(FieldGetView(user, corner_field_id, &view));
2851 PetscCall(LogFieldAnatomyView(user, view.descriptor->canonical_name, stage_name, view.dm,
2852 view.local_vec, view.descriptor->dof,
2853 view.descriptor->layout));
2854 PetscFunctionReturn(0);
2855}
@ FIELD_ID_CELL_SCALAR_AT_CORNER
@ FIELD_ID_CELL_VECTOR_AT_CORNER
Here is the call graph for this function:
Here is the caller graph for this function:

◆ LOG_INTERPOLATION_ERROR()

PetscErrorCode LOG_INTERPOLATION_ERROR ( UserCtx user)

Logs the interpolation error between the analytical and computed solutions.

Parameters
userPrimary UserCtx input for the operation.
Returns
PetscErrorCode 0 on success.

Logs the interpolation error between the analytical and computed solutions.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
LOG_INTERPOLATION_ERROR()

Definition at line 2865 of file logging.c.

2866{
2867 SimCtx *simCtx = user->simCtx;
2868 PetscErrorCode ierr;
2869 DM swarm = user->swarm;
2870 Vec positionVec, analyticalvelocityVec, velocityVec, errorVec;
2871 PetscReal Interpolation_error = 0.0;
2872 PetscReal Maximum_Interpolation_error = 0.0;
2873 PetscReal AnalyticalSolution_magnitude = 0.0;
2874 PetscReal ErrorPercentage = 0.0;
2875
2876 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Creating global vectors.\n");
2877 ierr = DMSwarmCreateGlobalVectorFromField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_POSITION), &positionVec); CHKERRQ(ierr);
2878 ierr = DMSwarmCreateGlobalVectorFromField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_VELOCITY), &velocityVec); CHKERRQ(ierr);
2879
2880 ierr = VecDuplicate(positionVec, &analyticalvelocityVec); CHKERRQ(ierr);
2881 ierr = VecCopy(positionVec, analyticalvelocityVec); CHKERRQ(ierr);
2882
2883 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Computing analytical solution.\n");
2884 ierr = SetAnalyticalSolutionForParticles(analyticalvelocityVec, simCtx); CHKERRQ(ierr);
2885
2886 ierr = VecDuplicate(analyticalvelocityVec, &errorVec); CHKERRQ(ierr);
2887 ierr = VecCopy(analyticalvelocityVec, errorVec); CHKERRQ(ierr);
2888
2889 ierr = VecNorm(analyticalvelocityVec, NORM_2, &AnalyticalSolution_magnitude); CHKERRQ(ierr);
2890
2891 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Computing error.\n");
2892 ierr = VecAXPY(errorVec, -1.0, velocityVec); CHKERRQ(ierr);
2893 ierr = VecNorm(errorVec, NORM_2, &Interpolation_error); CHKERRQ(ierr);
2894 ierr = VecNorm(errorVec,NORM_INFINITY,&Maximum_Interpolation_error); CHKERRQ(ierr);
2895
2896 ErrorPercentage = (AnalyticalSolution_magnitude > 0) ?
2897 (Interpolation_error / AnalyticalSolution_magnitude * 100.0) : 0.0;
2898
2899 /* --- CSV output (always, rank 0 only) --- */
2900 if (simCtx->rank == 0) {
2901 char csv_path[PETSC_MAX_PATH_LEN + 32];
2902 ierr = PetscSNPrintf(csv_path, sizeof(csv_path), "%s/interpolation_error.csv", simCtx->log_dir); CHKERRQ(ierr);
2903 FILE *f = fopen(csv_path, "a");
2904 if (f) {
2905 if (ftell(f) == 0) {
2906 fprintf(f, "step,time,L2_error,Linf_error,L2_analytical,error_pct\n");
2907 }
2908 if (simCtx->continueMode && simCtx->step == simCtx->StartStep + 1) {
2909 fprintf(f, "# Continuation from step %" PetscInt_FMT "\n", simCtx->StartStep);
2910 }
2911 PetscReal t = (PetscReal)simCtx->ti * simCtx->dt;
2912 fprintf(f, "%d,%.6e,%.6e,%.6e,%.6e,%.4f\n",
2913 (int)simCtx->step, t,
2914 Interpolation_error, Maximum_Interpolation_error,
2915 AnalyticalSolution_magnitude, ErrorPercentage);
2916 fclose(f);
2917 }
2918 }
2919
2920 /* --- Console output (only at INFO level or above) --- */
2921 if (get_log_level() >= LOG_INFO) {
2922 LOG_ALLOW(GLOBAL, LOG_INFO, "Interpolation error (%%): %g\n", ErrorPercentage);
2923 PetscPrintf(PETSC_COMM_WORLD, "Interpolation error (%%): %g\n", ErrorPercentage);
2924 LOG_ALLOW(GLOBAL, LOG_INFO, "Maximum Interpolation error: %g\n", Maximum_Interpolation_error);
2925 PetscPrintf(PETSC_COMM_WORLD, "Maximum Interpolation error: %g\n", Maximum_Interpolation_error);
2926 }
2927
2928 ierr = VecDestroy(&analyticalvelocityVec); CHKERRQ(ierr);
2929 ierr = VecDestroy(&errorVec); CHKERRQ(ierr);
2930 ierr = DMSwarmDestroyGlobalVectorFromField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_POSITION), &positionVec); CHKERRQ(ierr);
2931 ierr = DMSwarmDestroyGlobalVectorFromField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_VELOCITY), &velocityVec); CHKERRQ(ierr);
2932
2933 return 0;
2934}
PetscErrorCode SetAnalyticalSolutionForParticles(Vec tempVec, SimCtx *simCtx)
Applies the analytical solution to particle velocity vector.
PetscReal dt
Definition variables.h:710
Here is the call graph for this function:
Here is the caller graph for this function:

◆ LOG_SCATTER_METRICS()

PetscErrorCode LOG_SCATTER_METRICS ( UserCtx user)

Logs particle-to-grid scatter verification metrics for the prescribed scalar truth path.

Parameters
userPrimary UserCtx input for the operation.
Returns
PetscErrorCode 0 on success.

Logs particle-to-grid scatter verification metrics for the prescribed scalar truth path.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
LOG_SCATTER_METRICS()

Definition at line 2944 of file logging.c.

2945{
2946 PetscErrorCode ierr;
2947 SimCtx *simCtx = NULL;
2948 DMDALocalInfo info;
2949 PetscInt xs, xe, ys, ye, zs, ze, mx, my, mz;
2950 PetscInt lxs, lxe, lys, lye, lzs, lze;
2951 Vec reference_vec = NULL;
2952 PetscReal ***psi = NULL;
2953 PetscReal ***psi_ref = NULL;
2954 PetscReal ***aj = NULL;
2955 PetscReal ***count = NULL;
2956 PetscReal *particle_psi = NULL;
2957 PetscInt nlocal = 0;
2958 PetscReal local_l1 = 0.0, global_l1 = 0.0;
2959 PetscReal local_l2_sq = 0.0, global_l2_sq = 0.0;
2960 PetscReal local_linf = 0.0, global_linf = 0.0;
2961 PetscReal local_ref_l2_sq = 0.0, global_ref_l2_sq = 0.0;
2962 PetscReal local_grid_integral = 0.0, global_grid_integral = 0.0;
2963 PetscReal local_domain_volume = 0.0, global_domain_volume = 0.0;
2964 PetscReal local_particle_sum = 0.0, global_particle_sum = 0.0;
2965 PetscInt64 local_particle_count = 0, global_particle_count = 0;
2966 PetscInt64 local_cell_count = 0, global_cell_count = 0;
2967 PetscInt64 local_occupied_count = 0, global_occupied_count = 0;
2968 PetscReal particle_integral = 0.0;
2969 PetscReal occupancy_fraction = 0.0;
2970 PetscReal mean_particles_per_occupied_cell = 0.0;
2971 PetscReal l2_error = 0.0;
2972 PetscReal relative_l2_error = 0.0;
2973
2974 PetscFunctionBeginUser;
2975 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx cannot be NULL.");
2976 simCtx = user->simCtx;
2977 if (!VerificationScalarOverrideActive(simCtx) || !user->swarm || !user->Psi || !user->ParticleCount) {
2978 PetscFunctionReturn(0);
2979 }
2980
2981 info = user->info;
2982 xs = info.xs; xe = info.xs + info.xm;
2983 ys = info.ys; ye = info.ys + info.ym;
2984 zs = info.zs; ze = info.zs + info.zm;
2985 mx = info.mx; my = info.my; mz = info.mz;
2986 lxs = (xs == 0) ? xs + 1 : xs; lxe = (xe == mx) ? xe - 1 : xe;
2987 lys = (ys == 0) ? ys + 1 : ys; lye = (ye == my) ? ye - 1 : ye;
2988 lzs = (zs == 0) ? zs + 1 : zs; lze = (ze == mz) ? ze - 1 : ze;
2989
2990 ierr = VecDuplicate(user->Psi, &reference_vec); CHKERRQ(ierr);
2991 ierr = SetAnalyticalScalarFieldAtCellCenters(user, reference_vec); CHKERRQ(ierr);
2992
2993 ierr = DMDAVecGetArrayRead(user->da, user->Psi, &psi); CHKERRQ(ierr);
2994 ierr = DMDAVecGetArrayRead(user->da, reference_vec, &psi_ref); CHKERRQ(ierr);
2995 ierr = DMDAVecGetArrayRead(user->da, user->Aj, &aj); CHKERRQ(ierr);
2996 ierr = DMDAVecGetArrayRead(user->da, user->ParticleCount, &count); CHKERRQ(ierr);
2997
2998 for (PetscInt k = lzs; k < lze; ++k) {
2999 for (PetscInt j = lys; j < lye; ++j) {
3000 for (PetscInt i = lxs; i < lxe; ++i) {
3001 const PetscReal cell_volume = (PetscAbsReal(aj[k][j][i]) > 1.0e-14) ? (1.0 / aj[k][j][i]) : 0.0;
3002 const PetscReal err = psi[k][j][i] - psi_ref[k][j][i];
3003 local_cell_count += 1;
3004 local_domain_volume += cell_volume;
3005 local_grid_integral += psi[k][j][i] * cell_volume;
3006 local_l1 += PetscAbsReal(err) * cell_volume;
3007 local_l2_sq += err * err * cell_volume;
3008 local_ref_l2_sq += psi_ref[k][j][i] * psi_ref[k][j][i] * cell_volume;
3009 local_linf = PetscMax(local_linf, PetscAbsReal(err));
3010 if (count[k][j][i] > 0.0) local_occupied_count += 1;
3011 }
3012 }
3013 }
3014
3015 ierr = DMDAVecRestoreArrayRead(user->da, user->ParticleCount, &count); CHKERRQ(ierr);
3016 ierr = DMDAVecRestoreArrayRead(user->da, user->Aj, &aj); CHKERRQ(ierr);
3017 ierr = DMDAVecRestoreArrayRead(user->da, reference_vec, &psi_ref); CHKERRQ(ierr);
3018 ierr = DMDAVecRestoreArrayRead(user->da, user->Psi, &psi); CHKERRQ(ierr);
3019 ierr = VecDestroy(&reference_vec); CHKERRQ(ierr);
3020
3021 ierr = DMSwarmGetLocalSize(user->swarm, &nlocal); CHKERRQ(ierr);
3022 local_particle_count = (PetscInt64)nlocal;
3023 if (nlocal > 0) {
3024 ierr = DMSwarmGetField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_PSI), NULL, NULL, (void **)&particle_psi); CHKERRQ(ierr);
3025 for (PetscInt p = 0; p < nlocal; ++p) local_particle_sum += particle_psi[p];
3026 ierr = DMSwarmRestoreField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_PSI), NULL, NULL, (void **)&particle_psi); CHKERRQ(ierr);
3027 }
3028
3029 ierr = MPI_Allreduce(&local_l1, &global_l1, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3030 ierr = MPI_Allreduce(&local_l2_sq, &global_l2_sq, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3031 ierr = MPI_Allreduce(&local_linf, &global_linf, 1, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3032 ierr = MPI_Allreduce(&local_ref_l2_sq, &global_ref_l2_sq, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3033 ierr = MPI_Allreduce(&local_grid_integral, &global_grid_integral, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3034 ierr = MPI_Allreduce(&local_domain_volume, &global_domain_volume, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3035 ierr = MPI_Allreduce(&local_particle_sum, &global_particle_sum, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3036 ierr = MPI_Allreduce(&local_particle_count, &global_particle_count, 1, MPIU_INT64, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3037 ierr = MPI_Allreduce(&local_cell_count, &global_cell_count, 1, MPIU_INT64, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3038 ierr = MPI_Allreduce(&local_occupied_count, &global_occupied_count, 1, MPIU_INT64, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3039
3040 l2_error = PetscSqrtReal(global_l2_sq);
3041 relative_l2_error = (global_ref_l2_sq > 0.0) ? (l2_error / PetscSqrtReal(global_ref_l2_sq)) : 0.0;
3042 occupancy_fraction = (global_cell_count > 0) ? ((PetscReal)global_occupied_count / (PetscReal)global_cell_count) : 0.0;
3043 mean_particles_per_occupied_cell =
3044 (global_occupied_count > 0) ? ((PetscReal)global_particle_count / (PetscReal)global_occupied_count) : 0.0;
3045 particle_integral =
3046 (global_particle_count > 0) ? (global_domain_volume * global_particle_sum / (PetscReal)global_particle_count) : 0.0;
3047
3048 if (simCtx->rank == 0) {
3049 char csv_path[PETSC_MAX_PATH_LEN + 32];
3050 FILE *f = NULL;
3051 ierr = PetscSNPrintf(csv_path, sizeof(csv_path), "%s/scatter_metrics.csv", simCtx->log_dir); CHKERRQ(ierr);
3052 f = fopen(csv_path, "a");
3053 if (f) {
3054 if (ftell(f) == 0) {
3055 fprintf(f,
3056 "step,time,total_particles,total_cells,occupied_cells,occupancy_fraction,"
3057 "mean_particles_per_occupied_cell,particle_integral,grid_integral,"
3058 "conservation_error_abs,L1_error,L2_error,Linf_error,relative_L2_error\n");
3059 }
3060 if (simCtx->continueMode && simCtx->step == simCtx->StartStep + 1) {
3061 fprintf(f, "# Continuation from step %" PetscInt_FMT "\n", simCtx->StartStep);
3062 }
3063 fprintf(f, "%d,%.6e,%lld,%lld,%lld,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e\n",
3064 (int)simCtx->step,
3065 (double)simCtx->ti,
3066 (long long)global_particle_count,
3067 (long long)global_cell_count,
3068 (long long)global_occupied_count,
3069 (double)occupancy_fraction,
3070 (double)mean_particles_per_occupied_cell,
3071 (double)particle_integral,
3072 (double)global_grid_integral,
3073 (double)PetscAbsReal(global_grid_integral - particle_integral),
3074 (double)global_l1,
3075 (double)l2_error,
3076 (double)global_linf,
3077 (double)relative_l2_error);
3078 fclose(f);
3079 }
3080 }
3081
3082 if (get_log_level() >= LOG_INFO) {
3083 LOG_ALLOW(GLOBAL, LOG_INFO, "Scatter relative L2 error: %.6e\n", (double)relative_l2_error);
3084 LOG_ALLOW(GLOBAL, LOG_INFO, "Scatter occupancy fraction: %.6e\n", (double)occupancy_fraction);
3085 }
3086
3087 PetscFunctionReturn(0);
3088}
PetscErrorCode SetAnalyticalScalarFieldAtCellCenters(UserCtx *user, Vec targetVec)
Writes the configured verification scalar profile at physical cell centers into a scalar Vec.
@ PARTICLE_FIELD_ID_PSI
Vec ParticleCount
Definition variables.h:996
DMDALocalInfo info
Definition variables.h:918
Vec Psi
Definition variables.h:997
PetscBool VerificationScalarOverrideActive(const SimCtx *simCtx)
Reports whether a verification-only scalar override is active.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ResetSearchMetrics()

PetscErrorCode ResetSearchMetrics ( SimCtx simCtx)

Resets the aggregate per-timestep search instrumentation counters.

Parameters
simCtxSimulation context whose search metrics should be zeroed.
Returns
PetscErrorCode 0 on success.

Resets the aggregate per-timestep search instrumentation counters.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
ResetSearchMetrics()

Definition at line 3098 of file logging.c.

3099{
3100 PetscFunctionBeginUser;
3101 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "SimCtx cannot be NULL for ResetSearchMetrics.");
3102
3103 simCtx->searchMetrics.searchAttempts = 0;
3104 simCtx->searchMetrics.searchPopulation = 0;
3106 simCtx->searchMetrics.searchLostCount = 0;
3107 simCtx->searchMetrics.traversalStepsSum = 0;
3108 simCtx->searchMetrics.reSearchCount = 0;
3109 simCtx->searchMetrics.maxTraversalSteps = 0;
3111 simCtx->searchMetrics.tieBreakCount = 0;
3117
3118 PetscFunctionReturn(0);
3119}
PetscInt64 searchLocatedCount
Definition variables.h:241
PetscInt64 searchLostCount
Definition variables.h:242
PetscInt64 boundaryClampCount
Definition variables.h:248
PetscInt64 traversalStepsSum
Definition variables.h:243
PetscInt64 searchPopulation
Definition variables.h:240
PetscInt currentSettlementPass
Definition variables.h:252
PetscInt64 reSearchCount
Definition variables.h:244
PetscInt64 bboxGuessFallbackCount
Definition variables.h:250
PetscInt64 bboxGuessSuccessCount
Definition variables.h:249
PetscInt64 maxParticlePassDepth
Definition variables.h:251
PetscInt64 maxTraversalSteps
Definition variables.h:245
SearchMetricsState searchMetrics
Definition variables.h:840
PetscInt64 searchAttempts
Definition variables.h:239
PetscInt64 tieBreakCount
Definition variables.h:247
PetscInt64 maxTraversalFailCount
Definition variables.h:246
Here is the caller graph for this function:

◆ CalculateAdvancedParticleMetrics()

PetscErrorCode CalculateAdvancedParticleMetrics ( UserCtx user)

Computes advanced particle statistics and stores them in SimCtx.

This function calculates:

  • Particle load imbalance across MPI ranks.
  • The total number of grid cells occupied by at least one particle.

It requires that CalculateParticleCountPerCell() has been called prior to its execution. It uses collective MPI operations and must be called by all ranks.

Parameters
userPointer to the UserCtx.
Returns
PetscErrorCode 0 on success.

Computes advanced particle statistics and stores them in SimCtx.

Local to this translation unit.

Definition at line 3283 of file logging.c.

3284{
3285 PetscErrorCode ierr;
3286 SimCtx *simCtx = user->simCtx;
3287 PetscMPIInt size, rank;
3288
3289 PetscFunctionBeginUser;
3290 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
3291 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
3292
3293 // --- 1. Particle Load Imbalance ---
3294 PetscInt nLocal, nGlobal, nLocalMax;
3295 ierr = DMSwarmGetLocalSize(user->swarm, &nLocal); CHKERRQ(ierr);
3296 ierr = DMSwarmGetSize(user->swarm, &nGlobal); CHKERRQ(ierr);
3297 ierr = MPI_Allreduce(&nLocal, &nLocalMax, 1, MPIU_INT, MPI_MAX, PETSC_COMM_WORLD); CHKERRQ(ierr);
3298
3299 PetscReal avg_per_rank = (size > 0) ? ((PetscReal)nGlobal / size) : 0.0;
3300 // Handle division by zero if there are no particles
3301 simCtx->particleLoadImbalance = (avg_per_rank > 1e-9) ? (nLocalMax / avg_per_rank) : 1.0;
3302
3303
3304 // --- 2. Number of Occupied Cells ---
3305 // This part requires access to the user->ParticleCount vector.
3306 PetscInt local_occupied_cells = 0;
3307 PetscInt global_occupied_cells;
3308 const PetscScalar *count_array;
3309 PetscInt vec_local_size;
3310
3311 ierr = VecGetLocalSize(user->ParticleCount, &vec_local_size); CHKERRQ(ierr);
3312 ierr = VecGetArrayRead(user->ParticleCount, &count_array); CHKERRQ(ierr);
3313
3314 for (PetscInt i = 0; i < vec_local_size; ++i) {
3315 if (count_array[i] > 0.5) { // Use 0.5 to be safe with floating point
3316 local_occupied_cells++;
3317 }
3318 }
3319 ierr = VecRestoreArrayRead(user->ParticleCount, &count_array); CHKERRQ(ierr);
3320
3321 ierr = MPI_Allreduce(&local_occupied_cells, &global_occupied_cells, 1, MPIU_INT, MPI_SUM, PETSC_COMM_WORLD); CHKERRQ(ierr);
3322 simCtx->occupiedCellCount = global_occupied_cells;
3323
3324 LOG_ALLOW_SYNC(GLOBAL, LOG_INFO, "[Rank %d] Advanced Metrics: Imbalance=%.2f, OccupiedCells=%d\n", rank, simCtx->particleLoadImbalance, simCtx->occupiedCellCount);
3325
3326 PetscFunctionReturn(0);
3327}
PetscInt occupiedCellCount
Definition variables.h:838
PetscReal particleLoadImbalance
Definition variables.h:839
Here is the caller graph for this function:

◆ LOG_SEARCH_METRICS()

PetscErrorCode LOG_SEARCH_METRICS ( UserCtx user)

Writes compact runtime search metrics to CSV and optionally to console.

The CSV artifact is always written for particle-enabled runs. Console output remains gated by normal logging level and function allow-listing.

Parameters
userPointer to the UserCtx.
Returns
PetscErrorCode 0 on success.

Writes compact runtime search metrics to CSV and optionally to console.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
LOG_SEARCH_METRICS()

Definition at line 3129 of file logging.c.

3130{
3131 PetscErrorCode ierr;
3132 SimCtx *simCtx = NULL;
3133 PetscInt totalParticles = 0;
3134 PetscReal local_metrics[SEARCH_METRIC_REDUCTION_LEN] = {0.0};
3135 PetscReal global_metrics[SEARCH_METRIC_REDUCTION_LEN] = {0.0};
3136 PetscReal meanTraversalSteps = 0.0;
3137 PetscReal searchFailureFraction = 0.0;
3138 PetscReal searchWorkIndex = 0.0;
3139 PetscReal reSearchFraction = 0.0;
3140 long long searchAttempts = 0;
3141 long long searchPopulation = 0;
3142 long long searchLocatedCount = 0;
3143 long long searchLostCount = 0;
3144 long long traversalStepsSum = 0;
3145 long long reSearchCount = 0;
3146 long long tieBreakCount = 0;
3147 long long boundaryClampCount = 0;
3148 long long bboxGuessSuccessCount = 0;
3149 long long bboxGuessFallbackCount = 0;
3150 long long maxTraversalFailCount = 0;
3151 long long maxTraversalSteps = 0;
3152 long long maxPassDepth = 0;
3153 MPI_Op reduction_op = MPI_OP_NULL;
3154
3155 PetscFunctionBeginUser;
3156 if (!user || !user->simCtx) {
3157 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx and SimCtx are required for LOG_SEARCH_METRICS.");
3158 }
3159 simCtx = user->simCtx;
3160
3161 if (simCtx->np <= 0) {
3162 PetscFunctionReturn(0);
3163 }
3164
3165 ierr = DMSwarmGetSize(user->swarm, &totalParticles); CHKERRQ(ierr);
3166
3167 local_metrics[SEARCH_METRIC_SUM_SEARCH_ATTEMPTS] = (PetscReal)simCtx->searchMetrics.searchAttempts;
3168 local_metrics[SEARCH_METRIC_SUM_SEARCH_POPULATION] = (PetscReal)simCtx->searchMetrics.searchPopulation;
3169 local_metrics[SEARCH_METRIC_SUM_SEARCH_LOCATED] = (PetscReal)simCtx->searchMetrics.searchLocatedCount;
3170 local_metrics[SEARCH_METRIC_SUM_SEARCH_LOST] = (PetscReal)simCtx->searchMetrics.searchLostCount;
3171 local_metrics[SEARCH_METRIC_SUM_TRAVERSAL_STEPS] = (PetscReal)simCtx->searchMetrics.traversalStepsSum;
3172 local_metrics[SEARCH_METRIC_SUM_RESEARCH] = (PetscReal)simCtx->searchMetrics.reSearchCount;
3173 local_metrics[SEARCH_METRIC_SUM_TIE_BREAKS] = (PetscReal)simCtx->searchMetrics.tieBreakCount;
3174 local_metrics[SEARCH_METRIC_SUM_BOUNDARY_CLAMPS] = (PetscReal)simCtx->searchMetrics.boundaryClampCount;
3175 local_metrics[SEARCH_METRIC_SUM_BBOX_GUESS_SUCCESS] = (PetscReal)simCtx->searchMetrics.bboxGuessSuccessCount;
3176 local_metrics[SEARCH_METRIC_SUM_BBOX_GUESS_FALLBACK] = (PetscReal)simCtx->searchMetrics.bboxGuessFallbackCount;
3177 local_metrics[SEARCH_METRIC_SUM_MAX_TRAVERSAL_FAILS] = (PetscReal)simCtx->searchMetrics.maxTraversalFailCount;
3178 local_metrics[SEARCH_METRIC_MAX_TRAVERSAL_STEPS] = (PetscReal)simCtx->searchMetrics.maxTraversalSteps;
3179 local_metrics[SEARCH_METRIC_MAX_PASS_DEPTH] = (PetscReal)simCtx->searchMetrics.maxParticlePassDepth;
3180
3181 ierr = MPI_Op_create(SearchMetricsReduceOp, PETSC_TRUE, &reduction_op); CHKERRMPI(ierr);
3182 ierr = MPI_Allreduce(local_metrics, global_metrics, SEARCH_METRIC_REDUCTION_LEN, MPIU_REAL, reduction_op, PETSC_COMM_WORLD); CHKERRMPI(ierr);
3183 ierr = MPI_Op_free(&reduction_op); CHKERRMPI(ierr);
3184 reduction_op = MPI_OP_NULL;
3185
3186 searchAttempts = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_SEARCH_ATTEMPTS] + 0.5);
3187 searchPopulation = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_SEARCH_POPULATION] + 0.5);
3188 searchLocatedCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_SEARCH_LOCATED] + 0.5);
3189 searchLostCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_SEARCH_LOST] + 0.5);
3190 traversalStepsSum = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_TRAVERSAL_STEPS] + 0.5);
3191 reSearchCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_RESEARCH] + 0.5);
3192 tieBreakCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_TIE_BREAKS] + 0.5);
3193 boundaryClampCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_BOUNDARY_CLAMPS] + 0.5);
3194 bboxGuessSuccessCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_BBOX_GUESS_SUCCESS] + 0.5);
3195 bboxGuessFallbackCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_BBOX_GUESS_FALLBACK] + 0.5);
3196 maxTraversalFailCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_MAX_TRAVERSAL_FAILS] + 0.5);
3197 maxTraversalSteps = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_MAX_TRAVERSAL_STEPS] + 0.5);
3198 maxPassDepth = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_MAX_PASS_DEPTH] + 0.5);
3199
3200 if (searchAttempts > 0) {
3201 meanTraversalSteps = (PetscReal)traversalStepsSum / (PetscReal)searchAttempts;
3202 }
3203 if (searchPopulation > 0) {
3204 searchFailureFraction = (PetscReal)searchLostCount / (PetscReal)searchPopulation;
3205 searchWorkIndex = (PetscReal)traversalStepsSum / (PetscReal)searchPopulation;
3206 reSearchFraction = (PetscReal)reSearchCount / (PetscReal)searchPopulation;
3207 }
3208
3209 if (simCtx->rank == 0) {
3210 char csv_path[PETSC_MAX_PATH_LEN + 32];
3211 FILE *f = NULL;
3212
3213 ierr = PetscSNPrintf(csv_path, sizeof(csv_path), "%s/search_metrics.csv", simCtx->log_dir); CHKERRQ(ierr);
3214 f = fopen(csv_path, "a");
3215 if (!f) {
3216 LOG_ALLOW(GLOBAL, LOG_WARNING, "LOG_SEARCH_METRICS: could not open '%s' for writing.\n", csv_path);
3217 } else {
3218 if (ftell(f) == 0) {
3219 fprintf(f,
3220 "step,time,total_particles,lost,lost_cumulative,migrated,migration_passes,search_attempts,"
3221 "mean_traversal_steps,max_traversal_steps,tie_break_count,boundary_clamp_count,"
3222 "bbox_guess_success_count,bbox_guess_fallback_count,max_particle_pass_depth,load_imbalance,"
3223 "search_population,search_located_count,search_lost_count,traversal_steps_sum,re_search_count,"
3224 "max_traversal_fail_count,search_failure_fraction,search_work_index,re_search_fraction\n");
3225 }
3226 if (simCtx->continueMode && simCtx->step == simCtx->StartStep + 1) {
3227 fprintf(f, "# Continuation from step %" PetscInt_FMT "\n", simCtx->StartStep);
3228 }
3229 fprintf(f,
3230 "%d,%.6e,%d,%d,%d,%d,%d,%lld,%.6e,%lld,%lld,%lld,%lld,%lld,%lld,%.6e,%lld,%lld,%lld,%lld,%lld,%lld,%.6e,%.6e,%.6e\n",
3231 (int)simCtx->step,
3232 (double)simCtx->ti,
3233 (int)totalParticles,
3234 (int)simCtx->particlesLostLastStep,
3235 (int)simCtx->particlesLostCumulative,
3236 (int)simCtx->particlesMigratedLastStep,
3237 (int)simCtx->migrationPassesLastStep,
3238 searchAttempts,
3239 (double)meanTraversalSteps,
3240 maxTraversalSteps,
3241 tieBreakCount,
3242 boundaryClampCount,
3243 bboxGuessSuccessCount,
3244 bboxGuessFallbackCount,
3245 maxPassDepth,
3246 (double)simCtx->particleLoadImbalance,
3247 searchPopulation,
3248 searchLocatedCount,
3249 searchLostCount,
3250 traversalStepsSum,
3251 reSearchCount,
3252 maxTraversalFailCount,
3253 (double)searchFailureFraction,
3254 (double)searchWorkIndex,
3255 (double)reSearchFraction);
3256 fclose(f);
3257 }
3258 }
3259
3261 "Search metrics: sff=%.3e swi=%.3e re_search=%.3e lost(step/total)=%d/%d migrated=%d passes=%d traversal(mean/max)=%.2f/%lld tie_breaks=%lld max_pass_depth=%lld\n",
3262 (double)searchFailureFraction,
3263 (double)searchWorkIndex,
3264 (double)reSearchFraction,
3265 (int)simCtx->particlesLostLastStep,
3266 (int)simCtx->particlesLostCumulative,
3267 (int)simCtx->particlesMigratedLastStep,
3268 (int)simCtx->migrationPassesLastStep,
3269 (double)meanTraversalSteps,
3270 maxTraversalSteps,
3271 tieBreakCount,
3272 maxPassDepth);
3273
3274 PetscFunctionReturn(0);
3275}
@ SEARCH_METRIC_SUM_SEARCH_LOCATED
Definition logging.c:36
@ SEARCH_METRIC_SUM_MAX_TRAVERSAL_FAILS
Definition logging.c:44
@ SEARCH_METRIC_REDUCTION_LEN
Definition logging.c:47
@ SEARCH_METRIC_SUM_BBOX_GUESS_FALLBACK
Definition logging.c:43
@ SEARCH_METRIC_SUM_RESEARCH
Definition logging.c:39
@ SEARCH_METRIC_SUM_TRAVERSAL_STEPS
Definition logging.c:38
@ SEARCH_METRIC_MAX_TRAVERSAL_STEPS
Definition logging.c:45
@ SEARCH_METRIC_SUM_BOUNDARY_CLAMPS
Definition logging.c:41
@ SEARCH_METRIC_SUM_SEARCH_POPULATION
Definition logging.c:35
@ SEARCH_METRIC_MAX_PASS_DEPTH
Definition logging.c:46
@ SEARCH_METRIC_SUM_TIE_BREAKS
Definition logging.c:40
@ SEARCH_METRIC_SUM_SEARCH_LOST
Definition logging.c:37
@ SEARCH_METRIC_SUM_BBOX_GUESS_SUCCESS
Definition logging.c:42
@ SEARCH_METRIC_SUM_SEARCH_ATTEMPTS
Definition logging.c:34
static void SearchMetricsReduceOp(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype)
Internal reduction callback for packed search metrics.
Definition logging.c:54
Here is the call graph for this function:
Here is the caller graph for this function:

◆ LOG_PARTICLE_METRICS()

PetscErrorCode LOG_PARTICLE_METRICS ( UserCtx user,
const char *  stageName 
)

Logs particle swarm metrics, adapting its behavior based on a boolean flag in SimCtx.

This function serves a dual purpose:

  1. If simCtx->isInitializationPhase is PETSC_TRUE, it logs settlement diagnostics to "Initialization_Metrics.log", using the provided stageName.
  2. If simCtx->isInitializationPhase is PETSC_FALSE, it logs regular timestep metrics to "Particle_Metrics.log".
Parameters
userA pointer to the UserCtx.
stageNameA descriptive label recorded in the metrics log (for example, initialization stage name or "Timestep Metrics").
Returns
PetscErrorCode 0 on success.

Logs particle swarm metrics, adapting its behavior based on a boolean flag in SimCtx.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/logging.h.

See also
LOG_PARTICLE_METRICS()

Definition at line 3337 of file logging.c.

3338{
3339 PetscErrorCode ierr;
3340 PetscMPIInt rank;
3341 SimCtx *simCtx = user->simCtx;
3342 const char *stage_label = (stageName && stageName[0] != '\0') ? stageName : "N/A";
3343
3344 PetscFunctionBeginUser;
3345 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
3346
3347 PetscInt totalParticles;
3348 ierr = DMSwarmGetSize(user->swarm, &totalParticles); CHKERRQ(ierr);
3349
3350 if (!rank) {
3351 FILE *f;
3352 char filen[PETSC_MAX_PATH_LEN + 64];
3353 ierr = PetscSNPrintf(filen, sizeof(filen), "%s/Particle_Metrics.log", simCtx->log_dir); CHKERRQ(ierr);
3354 f = fopen(filen, "a");
3355 if (!f) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open particle log file: %s", filen);
3356
3357 if (ftell(f) == 0) {
3358 PetscFPrintf(PETSC_COMM_SELF, f, "%-18s | %-10s | %-12s | %-10s | %-10s | %-10s | %-15s | %-10s | %-10s\n",
3359 "Stage", "Timestep", "Total Ptls", "Lost", "Lost Total", "Migrated", "Occupied Cells", "Imbalance", "Mig Passes");
3360 PetscFPrintf(PETSC_COMM_SELF, f, "-------------------------------------------------------------------------------------------------------------------------------------------\n");
3361 }
3362 if (simCtx->continueMode && simCtx->step == simCtx->StartStep + 1) {
3363 PetscFPrintf(PETSC_COMM_SELF, f, "# Continuation from step %" PetscInt_FMT "\n", simCtx->StartStep);
3364 }
3365
3366 PetscFPrintf(PETSC_COMM_SELF, f, "%-18s | %-10d | %-12d | %-10d | %-10d | %-10d | %-15d | %-10.2f | %-10d\n",
3367 stage_label, (int)simCtx->step, (int)totalParticles, (int)simCtx->particlesLostLastStep,
3368 (int)simCtx->particlesLostCumulative, (int)simCtx->particlesMigratedLastStep, (int)simCtx->occupiedCellCount,
3369 (double)simCtx->particleLoadImbalance, (int)simCtx->migrationPassesLastStep);
3370 fclose(f);
3371 }
3372 PetscFunctionReturn(0);
3373}
PetscInt particlesLostLastStep
Definition variables.h:834
PetscInt particlesLostCumulative
Definition variables.h:835
PetscInt particlesMigratedLastStep
Definition variables.h:837
PetscInt migrationPassesLastStep
Definition variables.h:836
Here is the caller graph for this function: