PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
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 "AnalyticalSolution.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, ...)
 ----— DEBUG ---------------------------------------— #define LOG_ALLOW(scope, level, fmt, ...) \ do { \ MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \ PetscInt current_level_val = get_log_level(); \ PetscBool __allowed_func_val = is_function_allowed(__func); \ Print BEFORE the check \ if (strcmp(func, "LocateAllParticlesInGrid") == 0) { \ printf("[DEBUG LOG_ALLOW in %s] Checking: level=%d, get_log_level() returned %d, func_allowed=%d\n", \ func, (int)level, (int)__current_level_val, (int)__allowed_func_val); \ } \ if ((int)(level) <= (int)__current_level_val && allowed_func_val) { \ Print AFTER passing the check // \ if (strcmp(__func, "LocateAllParticlesInGrid") == 0) { \ printf("[DEBUG LOG_ALLOW in %s] Check PASSED. Printing log.\n", func); \ } \ PetscPrintf(comm, "[%s] " fmt, func, ##__VA_ARGS__); \ } \
 
#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 LOG_FUNC_TIMER_BEGIN_EVENT(eventID, scope)
 Begins timing a function by:
 
#define LOG_FUNC_TIMER_END_EVENT(eventID, scope)
 Ends timing a function by:
 
#define LOG_PROFILE_MSG(scope, fmt, ...)
 
#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_PROFILE , LOG_INFO ,
  LOG_DEBUG
}
 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.
 
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)
 Helper function to convert BCFace enum to a string representation.
 
const char * BCTypeToString (BCType type)
 Helper function to convert BCType enum to a string representation.
 
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.
 
const char * ParticleLocationStatusToString (ParticleLocationStatus level)
 A function that outputs the name of the current level in the ParticleLocation enum.
 
PetscErrorCode ProfilingInitialize (SimCtx *simCtx)
 Initializes the custom profiling system using configuration from SimCtx.
 
PetscErrorCode ProfilingLogTimestepSummary (PetscInt step)
 Logs the performance summary for the current timestep and resets timers.
 
PetscErrorCode ProfilingFinalize (void)
 Prints the final, cumulative performance summary and cleans up resources.
 
void _ProfilingStart (const char *func_name)
 
void _ProfilingEnd (const char *func_name)
 

Variables

PetscLogEvent EVENT_Individualwalkingsearch
 
PetscLogEvent EVENT_walkingsearch
 
PetscLogEvent EVENT_GlobalParticleLocation
 
PetscLogEvent EVENT_IndividualLocation
 

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 63 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 44 of file logging.h.

◆ GLOBAL

#define GLOBAL   1

Scope for global logging across all processes.

Definition at line 45 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:44
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:49

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 91 of file logging.h.

92 { \
93 /* Determine the MPI communicator based on the scope */ \
94 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
95 /* Check if the log level is within the allowed range */ \
96 if ((int)(level) <= (int)get_log_level()) { \
97 /* Print the message to the specified communicator */ \
98 PetscPrintf(comm, fmt, ##__VA_ARGS__); \
99 } \
100 } 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 122 of file logging.h.

123 { \
124 /* Set the communicator to global (MPI_COMM_WORLD) by default */ \
125 MPI_Comm comm = MPI_COMM_WORLD; \
126 /* Check if the log level is within the allowed range */ \
127 if ((int)(level) <= (int)get_log_level()) { \
128 /* Print the message using PetscPrintf with the global communicator */ \
129 PetscPrintf(comm, fmt, ##__VA_ARGS__); \
130 } \
131 } 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 152 of file logging.h.

153 { \
154 /* Determine the MPI communicator based on the scope */ \
155 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
156 /* Check if the log level is within the allowed range */ \
157 if ((int)(level) <= (int)get_log_level()) { \
158 /* Synchronized print (collective) on the specified communicator */ \
159 PetscSynchronizedPrintf(comm, fmt, ##__VA_ARGS__); \
160 /* Ensure all ranks have finished printing before continuing */ \
161 PetscSynchronizedFlush(comm, PETSC_STDOUT); \
162 } \
163 } 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 185 of file logging.h.

186 { \
187 if ((int)(level) <= (int)get_log_level()) { \
188 PetscSynchronizedPrintf(MPI_COMM_WORLD, fmt, ##__VA_ARGS__); \
189 PetscSynchronizedFlush(MPI_COMM_WORLD, PETSC_STDOUT); \
190 } \
191 } 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:159

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 207 of file logging.h.

208 { \
209 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
210 if ((int)(level) <= (int)get_log_level() && is_function_allowed(__func__)) { \
211 PetscPrintf(comm, "[%s] " fmt, __func__, ##__VA_ARGS__); \
212 } \
213 } 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:45

----— DEBUG ---------------------------------------— #define LOG_ALLOW(scope, level, fmt, ...) \ do { \ MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \ PetscInt current_level_val = get_log_level(); \ PetscBool __allowed_func_val = is_function_allowed(__func); \ Print BEFORE the check \ if (strcmp(func, "LocateAllParticlesInGrid") == 0) { \ printf("[DEBUG LOG_ALLOW in %s] Checking: level=%d, get_log_level() returned %d, func_allowed=%d\n", \ func, (int)level, (int)__current_level_val, (int)__allowed_func_val); \ } \ if ((int)(level) <= (int)__current_level_val && allowed_func_val) { \ Print AFTER passing the check // \ if (strcmp(__func, "LocateAllParticlesInGrid") == 0) { \ printf("[DEBUG LOG_ALLOW in %s] Check PASSED. Printing log.\n", func); \ } \ PetscPrintf(comm, "[%s] " fmt, func, ##__VA_ARGS__); \ } \

} while (0)

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,...)
----— DEBUG ---------------------------------------— #define LOG_ALLOW(scope, level,...
Definition logging.h:274
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:32
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:33

Definition at line 274 of file logging.h.

275 { \
276 /* ------------------------------------------------------------------ */ \
277 /* Validate scope and pick communicator *before* any early exits. */ \
278 /* ------------------------------------------------------------------ */ \
279 MPI_Comm _comm; \
280 if ((scope) == LOCAL) _comm = MPI_COMM_SELF; \
281 else if ((scope) == GLOBAL) _comm = MPI_COMM_WORLD; \
282 else { \
283 fprintf(stderr, "LOG_ALLOW_SYNC ERROR: invalid scope (%d) at %s:%d\n", \
284 (scope), __FILE__, __LINE__); \
285 MPI_Abort(MPI_COMM_WORLD, 1); \
286 } \
287 \
288 /* ------------------------------------------------------------------ */ \
289 /* Decide whether *this* rank should actually print. */ \
290 /* ------------------------------------------------------------------ */ \
291 PetscBool _doPrint = \
292 is_function_allowed(__func__) && ((int)(level) <= (int)get_log_level()); \
293 \
294 if (_doPrint) { \
295 PetscSynchronizedPrintf(_comm, "[%s] " fmt, __func__, ##__VA_ARGS__); \
296 } \
297 \
298 /* ------------------------------------------------------------------ */ \
299 /* ALL ranks call the flush, even if they printed nothing. */ \
300 /* ------------------------------------------------------------------ */ \
301 PetscSynchronizedFlush(_comm, PETSC_STDOUT); \
302} 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 319 of file logging.h.

320 { \
321 if (is_function_allowed(__func__) && (int)(level) <= (int)get_log_level()) { \
322 if ((iterVar) % (interval) == 0) { \
323 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
324 PetscPrintf(comm, "[%s] [%s=%d] " fmt, \
325 __func__, #iterVar, (iterVar), ##__VA_ARGS__); \
326 } \
327 } \
328 } 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.
...A printf-style format string and its corresponding arguments.

Definition at line 355 of file logging.h.

356 { \
357 /* First, perform the cheap, standard gatekeeper checks. */ \
358 if (is_function_allowed(__func__) && (int)(level) <= (int)get_log_level()) { \
359 /* Only if those pass, check the user's specific condition. */ \
360 if ((var) == (val)) { \
361 MPI_Comm comm = ((scope) == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
362 /* Print the standard prefix, then the user's custom message. */ \
363 PetscPrintf(comm, "[%s] [%s=%d] " fmt, \
364 __func__, #var, (var), ##__VA_ARGS__); \
365 } \
366 } \
367 } 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 384 of file logging.h.

385 { \
386 if (is_function_allowed(__func__) && (int)(level) <= (int)get_log_level()) { \
387 if ((idx) >= 0 && (idx) < (length)) { \
388 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
389 PetscPrintf(comm, "[%s] arr[%d] = " fmt "\n", \
390 __func__, (idx), (arr)[idx]); \
391 } \
392 } \
393 } 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 408 of file logging.h.

409 { \
410 if (is_function_allowed(__func__) && (int)(level) <= (int)get_log_level()) { \
411 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
412 PetscInt _start = (start) < 0 ? 0 : (start); \
413 PetscInt _end = (end) >= (length) ? (length) - 1 : (end); \
414 for (PetscInt i = _start; i <= _end; i++) { \
415 PetscPrintf(comm, "[%s] arr[%d] = " fmt "\n", __func__, i, (arr)[i]); \
416 } \
417 } \
418 } while (0)

◆ LOG_FUNC_TIMER_BEGIN_EVENT

#define LOG_FUNC_TIMER_BEGIN_EVENT (   eventID,
  scope 
)
Value:
double __funcTimerStart = 0.0; \
PetscBool __funcTimerActive = PETSC_FALSE; \
do { \
if (is_function_allowed(__func__) && (int)(LOG_PROFILE) == (int)get_log_level()) { \
PetscLogDouble _timeStamp = 0.0; \
PetscTime(&_timeStamp); \
__funcTimerStart = (double)_timeStamp; \
__funcTimerActive = PETSC_TRUE; \
/* Start the PETSc log event (rank-wide). */ \
(void)PetscLogEventBegin(eventID, 0, 0, 0, 0); \
} \
} while (0)
@ LOG_PROFILE
Exclusive log level for performance timing and profiling.
Definition logging.h:31

Begins timing a function by:

  1. Starting a wall-clock timer (PetscTime).
  2. Beginning a PETSc log event.
Parameters
eventIDA previously registered PetscLogEvent (e.g., EVENT_EvalPosition).
scopeLOCAL or GLOBAL (for potential later usage in logging).
levelLOG_ERROR, LOG_WARNING, LOG_INFO, LOG_DEBUG.

Example usage:

// ... function body ...
#define LOG_FUNC_TIMER_END_EVENT(eventID, scope)
Ends timing a function by:
Definition logging.h:462
#define LOG_FUNC_TIMER_BEGIN_EVENT(eventID, scope)
Begins timing a function by:
Definition logging.h:436

Definition at line 436 of file logging.h.

439 { \
440 if (is_function_allowed(__func__) && (int)(LOG_PROFILE) == (int)get_log_level()) { \
441 PetscLogDouble _timeStamp = 0.0; \
442 PetscTime(&_timeStamp); \
443 __funcTimerStart = (double)_timeStamp; \
444 __funcTimerActive = PETSC_TRUE; \
445 /* Start the PETSc log event (rank-wide). */ \
446 (void)PetscLogEventBegin(eventID, 0, 0, 0, 0); \
447 } \
448 } while (0)

◆ LOG_FUNC_TIMER_END_EVENT

#define LOG_FUNC_TIMER_END_EVENT (   eventID,
  scope 
)
Value:
do { \
if (__funcTimerActive == PETSC_TRUE) { \
/* End the PETSc log event */ \
(void)PetscLogEventEnd(eventID, 0, 0, 0, 0); \
/* Log the wall-clock elapsed time */ \
if (is_function_allowed(__func__) && (int)(LOG_PROFILE) == (int)get_log_level()) { \
PetscLogDouble _timeEnd = 0.0; \
PetscTime(&_timeEnd); \
double elapsed = (double)_timeEnd - __funcTimerStart; \
MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
PetscPrintf(comm, "[%s] Elapsed Time: %f seconds\n", __func__, elapsed); \
} \
} \
} while (0)

Ends timing a function by:

  1. Ending a PETSc log event.
  2. Logging the wall-clock elapsed time, if active.
Parameters
eventIDThe same PetscLogEvent handle passed to LOG_FUNC_TIMER_BEGIN_EVENT.
scopeLOCAL or GLOBAL for possible MPI_Comm usage.
levelThe log level at which to print the timing message.

The log message is only printed if the function is in the allow-list and the current log level is >= the requested level.

Definition at line 462 of file logging.h.

463 { \
464 if (__funcTimerActive == PETSC_TRUE) { \
465 /* End the PETSc log event */ \
466 (void)PetscLogEventEnd(eventID, 0, 0, 0, 0); \
467 /* Log the wall-clock elapsed time */ \
468 if (is_function_allowed(__func__) && (int)(LOG_PROFILE) == (int)get_log_level()) { \
469 PetscLogDouble _timeEnd = 0.0; \
470 PetscTime(&_timeEnd); \
471 double elapsed = (double)_timeEnd - __funcTimerStart; \
472 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
473 PetscPrintf(comm, "[%s] Elapsed Time: %f seconds\n", __func__, elapsed); \
474 } \
475 } \
476 } while (0)

◆ LOG_PROFILE_MSG

#define LOG_PROFILE_MSG (   scope,
  fmt,
  ... 
)
Value:
do { \
if ((int)(LOG_PROFILE) <= (int)get_log_level()) { \
MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
PetscPrintf(comm, "[PROFILE] " fmt, ##__VA_ARGS__); \
} \
} while (0)

Definition at line 479 of file logging.h.

480 { \
481 if ((int)(LOG_PROFILE) <= (int)get_log_level()) { \
482 MPI_Comm comm = (scope == LOCAL) ? MPI_COMM_SELF : MPI_COMM_WORLD; \
483 PetscPrintf(comm, "[PROFILE] " fmt, ##__VA_ARGS__); \
484 } \
485 } 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 758 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 767 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_PROFILE 

Exclusive log level for performance timing and profiling.

LOG_INFO 

Informational messages about program execution.

LOG_DEBUG 

Detailed debugging information.

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_PROFILE, /**< Exclusive log level for performance timing and profiling */
32 LOG_INFO, /**< Informational messages about program execution */
33 LOG_DEBUG, /**< Detailed debugging information */
34} LogLevel;
LogLevel
Enumeration of logging levels.
Definition logging.h:28
@ LOG_ERROR
Critical errors that may halt the program.
Definition logging.h:29
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:30

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 "DEBUG", "INFO", "WARNING", and defaults to "ERROR" if not set or unrecognized.

Returns
LogLevel The current logging level.

The function checks the LOG_LEVEL environment variable and sets the logging level accordingly. Supported levels are "DEBUG", "INFO", "WARNING", and defaults to "ERROR" if not set or unrecognized. The log level is cached after the first call to avoid repeated environment variable checks.

Returns
LogLevel The current logging level.

Definition at line 49 of file logging.c.

49 {
50 if (current_log_level == -1) { // Log level not set yet
51 const char *env = getenv("LOG_LEVEL");
52 if (!env) {
53 current_log_level = LOG_ERROR; // Default level
54 }
55 else if (strcmp(env, "DEBUG") == 0) {
57 }
58 else if (strcmp(env, "INFO") == 0) {
60 }
61 else if (strcmp(env, "WARNING") == 0) {
63 }
64 else if (strcmp(env, "PROFILE") == 0) { // <-- New profile level
66 }
67 else {
68 current_log_level = LOG_ERROR; // Default if unrecognized
69 }
70 }
71 return current_log_level;
72}
static LogLevel current_log_level
Static variable to cache the current logging level.
Definition logging.c:14
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_PROFILE (0) : Logs performance profiling details.
  • LOG_ERROR (1) : Logs only critical errors.
  • LOG_WARNING (2) : Logs warnings and errors.
  • LOG_INFO (3) : Logs general information, warnings, and errors.
  • LOG_DEBUG (4) : Logs debugging information, info, warnings, and errors.
Note
The log level is determined from the LOG_LEVEL environment variable. If LOG_LEVEL is not set, it defaults to LOG_INFO.
See also
get_log_level()

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.

Note
The log level is determined from the LOG_LEVEL environment variable. If LOG_LEVEL is not set, it defaults to LOG_INFO.
See also
get_log_level()

Definition at line 86 of file logging.c.

87{
88 PetscMPIInt rank;
89 PetscErrorCode ierr;
90 int level;
91 const char *level_name;
92
93 PetscFunctionBeginUser;
94 /* get MPI rank */
95 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRMPI(ierr);
96
97 /* decide level name */
98 level = get_log_level();
99 level_name = (level == LOG_ERROR) ? "ERROR" :
100 (level == LOG_WARNING) ? "WARNING" :
101 (level == LOG_INFO) ? "INFO" :
102 (level == LOG_DEBUG) ? "DEBUG" :
103 (level == LOG_PROFILE) ? "PROFILE" : "UNKNOWN";
104
105 /* print it out */
106 ierr = PetscPrintf(PETSC_COMM_SELF,
107 "Current log level: %s (%d) | rank: %d\n",
108 level_name, level, (int)rank);
109 CHKERRMPI(ierr);
110
111 PetscFunctionReturn(PETSC_SUCCESS);
112}
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:49
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
functionListAn array of function name strings (e.g., {"foo", "bar"}).
countThe number of entries in the array.

The existing allow-list is cleared and replaced by the new one. If you pass an empty list (count = 0), then no function will be allowed unless you change it later.

Definition at line 124 of file logging.c.

125{
126 // 1. Free any existing entries
127 if (gAllowedFunctions) {
128 for (int i = 0; i < gNumAllowed; ++i) {
129 free(gAllowedFunctions[i]); // each was strdup'ed
130 }
131 free(gAllowedFunctions);
132 gAllowedFunctions = NULL;
133 gNumAllowed = 0;
134 }
135
136 // 2. Allocate new array
137 if (count > 0) {
138 gAllowedFunctions = (char**)malloc(sizeof(char*) * count);
139 }
140
141 // 3. Copy the new entries
142 for (int i = 0; i < count; ++i) {
143 // strdup is a POSIX function. If not available, implement your own string copy.
144 gAllowedFunctions[i] = strdup(functionList[i]);
145 }
146 gNumAllowed = count;
147}
static char ** gAllowedFunctions
Global/static array of function names allowed to log.
Definition logging.c:21
static int gNumAllowed
Number of entries in the gAllowedFunctions array.
Definition logging.c:26
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.

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

Parameters
functionNameThe name of the function to check.
Returns
PETSC_TRUE if functionName is allowed, otherwise PETSC_FALSE.

If no functions are in the list, nothing is allowed by default. You can reverse this logic if you prefer to allow everything unless specified otherwise.

Definition at line 159 of file logging.c.

160{
161 /* no list ⇒ allow all */
162 if (gNumAllowed == 0) {
163 return PETSC_TRUE;
164 }
165
166 /* otherwise only the listed functions are allowed */
167 for (int i = 0; i < gNumAllowed; ++i) {
168 if (strcmp(gAllowedFunctions[i], functionName) == 0) {
169 return PETSC_TRUE;
170 }
171 }
172 return PETSC_FALSE;
173}
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..

Definition at line 189 of file logging.c.

190{
191
192 // Validate input pointers
193 if (cell == NULL) {
194 LOG_ALLOW(LOCAL,LOG_ERROR, "LOG_CELL_VERTICES - 'cell' is NULL.\n");
195 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "LOG_CELL_VERTICES - Input parameter 'cell' is NULL.");
196 }
197
198 LOG_ALLOW(LOCAL,LOG_DEBUG, "LOG_CELL_VERTICES - Rank %d, Cell Vertices:\n", rank);
199 for(int i = 0; i < 8; i++){
200 LOG_ALLOW(LOCAL,LOG_DEBUG, " Vertex[%d]: (%.2f, %.2f, %.2f)\n",
201 i, cell->vertices[i].x, cell->vertices[i].y, cell->vertices[i].z);
202 }
203
204 return 0; // Indicate successful execution
205}
#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:207
PetscScalar x
Definition variables.h:100
PetscScalar z
Definition variables.h:100
PetscScalar y
Definition variables.h:100
Cmpnts vertices[8]
Coordinates of the eight vertices of the cell.
Definition variables.h:160
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.

Definition at line 229 of file logging.c.

230{
231
232 // Validate input array
233 if (d == NULL) {
234 LOG_ALLOW(LOCAL,LOG_ERROR, " LOG_FACE_DISTANCES - 'd' is NULL.\n");
235 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, " LOG_FACE_DISTANCES - Input array 'd' is NULL.");
236 }
237
238 PetscPrintf(PETSC_COMM_SELF, " LOG_FACE_DISTANCES - Face Distances:\n");
239 PetscPrintf(PETSC_COMM_SELF, " LEFT(%d): %.15f\n", LEFT, d[LEFT]);
240 PetscPrintf(PETSC_COMM_SELF, " RIGHT(%d): %.15f\n", RIGHT, d[RIGHT]);
241 PetscPrintf(PETSC_COMM_SELF, " BOTTOM(%d): %.15f\n", BOTTOM, d[BOTTOM]);
242 PetscPrintf(PETSC_COMM_SELF, " TOP(%d): %.15f\n", TOP, d[TOP]);
243 PetscPrintf(PETSC_COMM_SELF, " FRONT(%d): %.15f\n", FRONT, d[FRONT]);
244 PetscPrintf(PETSC_COMM_SELF, " BACK(%d): %.15f\n", BACK, d[BACK]);
245
246 return 0; // Indicate successful execution
247}
@ TOP
Definition variables.h:144
@ FRONT
Definition variables.h:144
@ BOTTOM
Definition variables.h:144
@ BACK
Definition variables.h:144
@ LEFT
Definition variables.h:144
@ RIGHT
Definition variables.h:144
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.

Definition at line 402 of file logging.c.

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

Definition at line 627 of file logging.c.

628{
629 PetscErrorCode ierr;
630 PetscFunctionBegin;
631 if (funcs) {
632 for (PetscInt i = 0; i < n; ++i) {
633 ierr = PetscFree(funcs[i]); CHKERRQ(ierr);
634 }
635 ierr = PetscFree(funcs); CHKERRQ(ierr);
636 }
637 PetscFunctionReturn(0);
638}

◆ 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)
Definition picsolver.c:24

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).

Definition at line 568 of file logging.c.

571{
572 FILE *fp = NULL;
573 char **funcs = NULL;
574 size_t cap = 16; /* initial capacity */
575 size_t n = 0; /* number of names */
576 char line[PETSC_MAX_PATH_LEN];
577 PetscErrorCode ierr;
578
579 PetscFunctionBegin;
580
581 /* ---------------------------------------------------------------------- */
582 /* 1. Open file */
583 fp = fopen(filename, "r");
584 if (!fp) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
585 "Cannot open %s", filename);
586
587 /* 2. Allocate initial pointer array */
588 ierr = PetscMalloc1(cap, &funcs); CHKERRQ(ierr);
589
590 /* 3. Read file line by line */
591 while (fgets(line, sizeof line, fp)) {
592 /* Strip everything after a comment character '#'. */
593 char *hash = strchr(line, '#');
594 if (hash) *hash = '\0';
595
596 trim(line); /* remove leading/trailing blanks */
597 if (!*line) continue; /* skip if empty */
598
599 /* Grow the array if necessary */
600 if (n == cap) {
601 cap *= 2;
602 ierr = PetscRealloc(cap * sizeof(*funcs), (void **)&funcs); CHKERRQ(ierr);
603 }
604
605 /* Deep‑copy the cleaned identifier */
606 ierr = PetscStrallocpy(line, &funcs[n++]); CHKERRQ(ierr);
607 }
608 fclose(fp);
609
610 /* 4. Return results to caller */
611 *funcsOut = funcs;
612 *nOut = (PetscInt)n;
613
614 PetscFunctionReturn(0);
615}
static void trim(char *s)
Definition logging.c:524
Here is the call graph for this function:
Here is the caller graph for this function:

◆ BCFaceToString()

const char * BCFaceToString ( BCFace  face)

Helper function to convert BCFace enum to a string representation.

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

Definition at line 645 of file logging.c.

645 {
646 switch (face) {
647 case BC_FACE_NEG_X: return "-Xi (I-Min)";
648 case BC_FACE_POS_X: return "+Xi (I-Max)";
649 case BC_FACE_NEG_Y: return "-Eta (J-Min)";
650 case BC_FACE_POS_Y: return "+Eta (J-Max)";
651 case BC_FACE_NEG_Z: return "-Zeta (K-Min)";
652 case BC_FACE_POS_Z: return "+Zeta (K-Max)";
653 default: return "Unknown Face";
654 }
655}
@ BC_FACE_NEG_X
Definition variables.h:200
@ BC_FACE_POS_Z
Definition variables.h:202
@ BC_FACE_POS_Y
Definition variables.h:201
@ BC_FACE_NEG_Z
Definition variables.h:202
@ BC_FACE_POS_X
Definition variables.h:200
@ BC_FACE_NEG_Y
Definition variables.h:201
Here is the caller graph for this function:

◆ BCTypeToString()

const char * BCTypeToString ( BCType  type)

Helper function to convert BCType enum to a string representation.

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

Definition at line 662 of file logging.c.

662 {
663 switch (type) {
664 // case DIRICHLET: return "DIRICHLET";
665 // case NEUMANN: return "NEUMANN";
666 case WALL: return "WALL";
667 case INLET: return "INLET";
668 case OUTLET: return "OUTLET";
669 case FARFIELD: return "FARFIELD";
670 case PERIODIC: return "PERIODIC";
671 case INTERFACE: return "INTERFACE";
672 case NOGRAD: return "NOGRAD";
673
674 // case CUSTOM: return "CUSTOM";
675 default: return "Unknown BC Type";
676 }
677}
@ INLET
Definition variables.h:210
@ NOGRAD
Definition variables.h:216
@ INTERFACE
Definition variables.h:208
@ FARFIELD
Definition variables.h:211
@ OUTLET
Definition variables.h:211
@ PERIODIC
Definition variables.h:211
@ WALL
Definition variables.h:209
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.

Definition at line 689 of file logging.c.

689 {
690 switch (handler_type) {
691 // Wall & Symmetry Handlers
692 case BC_HANDLER_WALL_NOSLIP: return "noslip";
693 case BC_HANDLER_WALL_MOVING: return "moving";
694 case BC_HANDLER_SYMMETRY_PLANE: return "symmetry_plane";
695
696 // Inlet Handlers
697 case BC_HANDLER_INLET_CONSTANT_VELOCITY: return "constant_velocity";
698 case BC_HANDLER_INLET_PULSANTILE_FLUX: return "pulsatile_flux";
699 case BC_HANDLER_INLET_PARABOLIC: return "parabolic";
700
701 // Outlet Handlers
702 case BC_HANDLER_OUTLET_CONSERVATION: return "conservation";
703 case BC_HANDLER_OUTLET_PRESSURE: return "pressure";
704
705 // Other Physical Handlers
706 case BC_HANDLER_FARFIELD_NONREFLECTING: return "nonreflecting";
707 case BC_HANDLER_NOGRAD_COPY_GHOST: return "no_gradient";
708
709 // Multi-Block / Interface Handlers
710 case BC_HANDLER_PERIODIC: return "periodic";
711 case BC_HANDLER_INTERFACE_OVERSET: return "overset";
712
713 // Default case
715 default: return "UNKNOWN_HANDLER";
716 }
717}
@ BC_HANDLER_INLET_PULSANTILE_FLUX
Definition variables.h:224
@ BC_HANDLER_INLET_PARABOLIC
Definition variables.h:223
@ BC_HANDLER_INLET_CONSTANT_VELOCITY
Definition variables.h:224
@ BC_HANDLER_INTERFACE_OVERSET
Definition variables.h:227
@ BC_HANDLER_WALL_MOVING
Definition variables.h:222
@ BC_HANDLER_NOGRAD_COPY_GHOST
Definition variables.h:221
@ BC_HANDLER_WALL_NOSLIP
Definition variables.h:222
@ BC_HANDLER_OUTLET_CONSERVATION
Definition variables.h:225
@ BC_HANDLER_PERIODIC
Definition variables.h:227
@ BC_HANDLER_FARFIELD_NONREFLECTING
Definition variables.h:226
@ BC_HANDLER_OUTLET_PRESSURE
Definition variables.h:225
@ BC_HANDLER_SYMMETRY_PLANE
Definition variables.h:223
@ BC_HANDLER_UNDEFINED
Definition variables.h:221
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.

Definition at line 759 of file logging.c.

760{
761 DualMonitorCtx *monctx = (DualMonitorCtx*)ctx;
762 PetscErrorCode ierr;
763 PetscReal trnorm, relnorm;
764 Vec r;
765 char norm_buf[256];
766 PetscMPIInt rank;
767
768 PetscFunctionBeginUser;
769 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
770
771 // 1. Calculate the true residual norm.
772 ierr = KSPBuildResidual(ksp, NULL, NULL, &r); CHKERRQ(ierr);
773 ierr = VecNorm(r, NORM_2, &trnorm); CHKERRQ(ierr);
774
775 // 2. On the first iteration, compute and store the norm of the RHS vector `b`.
776 if (it == 0) {
777 Vec b;
778 ierr = KSPGetRhs(ksp, &b); CHKERRQ(ierr);
779 ierr = VecNorm(b, NORM_2, &monctx->bnorm); CHKERRQ(ierr);
780 }
781
782 if(!rank){
783 // 3. Compute the relative norm and format the output string.
784 if (monctx->bnorm > 1.e-15) {
785 relnorm = trnorm / monctx->bnorm;
786 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);
787 } else {
788 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);
789 }
790
791 // 4. Log to the file viewer (unconditionally).
792 if(monctx->file_handle){
793 ierr = PetscFPrintf(PETSC_COMM_SELF,monctx->file_handle,"%s\n", norm_buf); CHKERRQ(ierr);
794 }
795 // 5. Log to the console (conditionally).
796 if (monctx->log_to_console) {
797 PetscFPrintf(PETSC_COMM_SELF,stdout, "%s\n", norm_buf); CHKERRQ(ierr);
798 }
799
800 } //rank
801
802 PetscFunctionReturn(0);
803}
PetscBool log_to_console
Definition logging.h:65
PetscReal bnorm
Definition logging.h:66
PetscInt step
Definition logging.h:67
FILE * file_handle
Definition logging.h:64
PetscInt block_id
Definition logging.h:68
Context for a dual-purpose KSP monitor.
Definition logging.h:63
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

Definition at line 727 of file logging.c.

728{
729 DualMonitorCtx *monctx = (DualMonitorCtx*)*ctx;
730 PetscErrorCode ierr;
731 PetscMPIInt rank;
732
733 PetscFunctionBeginUser;
734 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
735 if(!rank && monctx->file_handle){
736 fclose(monctx->file_handle);
737 }
738
739 ierr = PetscFree(monctx); CHKERRQ(ierr);
740 *ctx = NULL;
741 PetscFunctionReturn(0);
742}
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.

Definition at line 819 of file logging.c.

820{
821 PetscErrorCode ierr;
822 PetscMPIInt rank;
823 SimCtx *simCtx = user->simCtx; // Get the shared SimCtx
824 const PetscInt bi = user->_this; // Get this block's specific ID
825 const PetscInt ti = simCtx->step; // Get the current timestep
826
827 PetscFunctionBeginUser;
828 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
829
830 // Only rank 0 performs file I/O.
831 if (!rank) {
832 FILE *f;
833 char filen[128];
834 sprintf(filen, "logs/Continuity_Metrics.log");
835
836 // Open the log file in append mode.
837 f = fopen(filen, "a");
838 if (!f) {
839 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open log file: %s", filen);
840 }
841
842 // Write a header only for the very first block (bi=0) on the very
843 // first timestep (ti=StartStep). This ensures it's written only once.
844 if (ti == simCtx->StartStep && bi == 0) {
845 PetscFPrintf(PETSC_COMM_SELF, f, "%-10s | %-6s | %-18s | %-30s | %-18s | %-18s | %-18s | %-18s\n",
846 "Timestep", "Block", "Max Divergence", "Max Divergence Location ([k][j][i]=idx)", "Sum(RHS)","Total Flux In", "Total Flux Out", "Net Flux");
847 PetscFPrintf(PETSC_COMM_SELF, f, "------------------------------------------------------------------------------------------------------------------------------------------\n");
848 }
849
850 // Prepare the data strings and values for the current block.
851 PetscReal net_flux = simCtx->FluxInSum - simCtx->FluxOutSum;
852 char location_str[64];
853 sprintf(location_str, "([%d][%d][%d] = %d)", (int)simCtx->MaxDivz, (int)simCtx->MaxDivy, (int)simCtx->MaxDivx, (int)simCtx->MaxDivFlatArg);
854
855 // Write the formatted line for the current block.
856 PetscFPrintf(PETSC_COMM_SELF, f, "%-10d | %-6d | %-18.10e | %-39s | %-18.10e | %-18.10e | %-18.10e | %-18.10e\n",
857 (int)ti,
858 (int)bi,
859 (double)simCtx->MaxDiv,
860 location_str,
861 (double)simCtx->summationRHS,
862 (double)simCtx->FluxInSum,
863 (double)simCtx->FluxOutSum,
864 (double)net_flux);
865
866 fclose(f);
867 }
868
869 PetscFunctionReturn(0);
870}
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:633
PetscReal FluxOutSum
Definition variables.h:571
PetscInt _this
Definition variables.h:643
PetscInt StartStep
Definition variables.h:523
PetscReal MaxDiv
Definition variables.h:606
PetscInt MaxDivx
Definition variables.h:607
PetscInt MaxDivy
Definition variables.h:607
PetscInt MaxDivz
Definition variables.h:607
PetscInt MaxDivFlatArg
Definition variables.h:607
PetscReal FluxInSum
Definition variables.h:571
PetscInt step
Definition variables.h:521
PetscReal summationRHS
Definition variables.h:605
The master context for the entire simulation.
Definition variables.h:513
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.

Definition at line 878 of file logging.c.

879{
880 switch (level) {
881 case NEEDS_LOCATION: return "NEEDS_LOCATION";
882 case ACTIVE_AND_LOCATED: return "ACTIVE_AND_LOCATED";
883 case MIGRATING_OUT: return "MIGRATING_OUT";
884 case LOST: return "LOST";
885 case UNINITIALIZED: return "UNINITIALIZED";
886 default: return "UNKNOWN_LEVEL";
887 }
888}
@ LOST
Definition variables.h:138
@ NEEDS_LOCATION
Definition variables.h:135
@ ACTIVE_AND_LOCATED
Definition variables.h:136
@ UNINITIALIZED
Definition variables.h:139
@ MIGRATING_OUT
Definition variables.h:137

◆ 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

Definition at line 955 of file logging.c.

956{
957 PetscFunctionBeginUser;
958 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "SimCtx cannot be null for ProfilingInitialize");
959
960 // Iterate through the list of critical functions provided in SimCtx
961 for (PetscInt i = 0; i < simCtx->nCriticalFuncs; ++i) {
962 PetscInt idx;
963 const char *func_name = simCtx->criticalFuncs[i];
964 PetscErrorCode ierr = _FindOrCreateEntry(func_name, &idx); CHKERRQ(ierr);
965 g_profiler_registry[idx].always_log = PETSC_TRUE;
966
967 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Marked '%s' as a critical function for profiling.\n", func_name);
968 }
969 PetscFunctionReturn(0);
970}
PetscBool always_log
Definition logging.c:900
static PetscErrorCode _FindOrCreateEntry(const char *func_name, PetscInt *idx)
Definition logging.c:909
static ProfiledFunction * g_profiler_registry
Definition logging.c:904
char ** criticalFuncs
Definition variables.h:611
PetscInt nCriticalFuncs
Definition variables.h:612
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ProfilingLogTimestepSummary()

PetscErrorCode ProfilingLogTimestepSummary ( PetscInt  step)

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

Depending on the current log level, this function will print:

  • LOG_PROFILE: Timings for ALL functions called during the step.
  • LOG_INFO/LOG_DEBUG: Timings for only the "always log" functions.

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
stepThe current simulation step number, for logging context.
Returns
PetscErrorCode

Definition at line 994 of file logging.c.

995{
996 LogLevel log_level = get_log_level();
997 PetscBool should_print = PETSC_FALSE;
998
999 PetscFunctionBeginUser;
1000
1001 // Decide if we should print anything at all
1002 if (log_level >= LOG_INFO) {
1003 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1004 if (g_profiler_registry[i].current_step_call_count > 0) {
1005 if (log_level == LOG_PROFILE || g_profiler_registry[i].always_log) {
1006 should_print = PETSC_TRUE;
1007 break;
1008 }
1009 }
1010 }
1011 }
1012
1013 if (should_print) {
1014 PetscPrintf(MPI_COMM_WORLD, "[PROFILE] ----- Timestep %d Summary -----\n", step);
1015 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1016 if (g_profiler_registry[i].current_step_call_count > 0) {
1017 if (log_level == LOG_PROFILE || g_profiler_registry[i].always_log) {
1018 PetscPrintf(MPI_COMM_WORLD, "[PROFILE] %-25s: %.6f s (%lld calls)\n",
1019 g_profiler_registry[i].name,
1020 g_profiler_registry[i].current_step_time,
1021 g_profiler_registry[i].current_step_call_count);
1022 }
1023 }
1024 }
1025 }
1026
1027 // Reset per-step counters for the next iteration
1028 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1031 }
1032 PetscFunctionReturn(0);
1033}
static PetscInt g_profiler_count
Definition logging.c:905
double current_step_time
Definition logging.c:896
long long current_step_call_count
Definition logging.c:898
Here is the call graph for this function:

◆ ProfilingFinalize()

PetscErrorCode ProfilingFinalize ( void  )

Prints the final, cumulative performance summary and cleans up resources.

This should be called once at the end of the simulation, before PetscFinalize(). It prints a table with total time, call count, and average time per call for every function that was profiled. This summary is only printed if the log level is LOG_PROFILE.

Returns
PetscErrorCode

Definition at line 1046 of file logging.c.

1047{
1048 PetscFunctionBeginUser;
1049 if (get_log_level() >= LOG_PROFILE) {
1050
1051 // --- Step 1: Sort the data for readability ---
1053
1054 // --- Step 2: Dynamically determine the width for the function name column ---
1055 PetscInt max_name_len = strlen("Function"); // Start with the header's length
1056 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1057 if (g_profiler_registry[i].total_call_count > 0) {
1058 PetscInt len = strlen(g_profiler_registry[i].name);
1059 if (len > max_name_len) {
1060 max_name_len = len;
1061 }
1062 }
1063 }
1064 // Add a little padding
1065 max_name_len += 2;
1066
1067 // --- Step 3: Define fixed widths for numeric columns for consistent alignment ---
1068 const int time_width = 18;
1069 const int count_width = 15;
1070 const int avg_width = 22;
1071
1072 // --- Step 4: Print the formatted table ---
1073 PetscPrintf(MPI_COMM_WORLD, "\n=======================================================================================\n");
1074 PetscPrintf(MPI_COMM_WORLD, " FINAL PROFILING SUMMARY (Sorted by Total Time)\n");
1075 PetscPrintf(MPI_COMM_WORLD, "=======================================================================================\n");
1076
1077 // Header Row
1078 PetscPrintf(MPI_COMM_WORLD, "%-*s | %-*s | %-*s | %-*s\n",
1079 max_name_len, "Function",
1080 time_width, "Total Time (s)",
1081 count_width, "Call Count",
1082 avg_width, "Avg. Time/Call (ms)");
1083
1084 // Separator Line (dynamically sized)
1085 for (int i = 0; i < max_name_len; i++) PetscPrintf(MPI_COMM_WORLD, "-");
1086 PetscPrintf(MPI_COMM_WORLD, "-|-");
1087 for (int i = 0; i < time_width; i++) PetscPrintf(MPI_COMM_WORLD, "-");
1088 PetscPrintf(MPI_COMM_WORLD, "-|-");
1089 for (int i = 0; i < count_width; i++) PetscPrintf(MPI_COMM_WORLD, "-");
1090 PetscPrintf(MPI_COMM_WORLD, "-|-");
1091 for (int i = 0; i < avg_width; i++) PetscPrintf(MPI_COMM_WORLD, "-");
1092 PetscPrintf(MPI_COMM_WORLD, "\n");
1093
1094 // Data Rows
1095 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1096 if (g_profiler_registry[i].total_call_count > 0) {
1097 double avg_time_ms = (g_profiler_registry[i].total_time / g_profiler_registry[i].total_call_count) * 1000.0;
1098 PetscPrintf(MPI_COMM_WORLD, "%-*s | %*.*f | %*lld | %*.*f\n",
1099 max_name_len, g_profiler_registry[i].name,
1100 time_width, 6, g_profiler_registry[i].total_time,
1101 count_width, g_profiler_registry[i].total_call_count,
1102 avg_width, 6, avg_time_ms);
1103 }
1104 }
1105 PetscPrintf(MPI_COMM_WORLD, "=======================================================================================\n");
1106 }
1107
1108 // --- Final Cleanup ---
1109 PetscFree(g_profiler_registry);
1110 g_profiler_registry = NULL;
1111 g_profiler_count = 0;
1113 PetscFunctionReturn(0);
1114}
long long total_call_count
Definition logging.c:897
static PetscInt g_profiler_capacity
Definition logging.c:906
double total_time
Definition logging.c:895
static int _CompareProfiledFunctions(const void *a, const void *b)
Definition logging.c:1036
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _ProfilingStart()

void _ProfilingStart ( const char *  func_name)

Definition at line 972 of file logging.c.

973{
974 PetscInt idx;
975 if (_FindOrCreateEntry(func_name, &idx) != 0) return; // Fail silently
976 PetscTime(&g_profiler_registry[idx].start_time);
977}
Here is the call graph for this function:

◆ _ProfilingEnd()

void _ProfilingEnd ( const char *  func_name)

Definition at line 979 of file logging.c.

980{
981 double end_time;
982 PetscTime(&end_time);
983
984 PetscInt idx;
985 if (_FindOrCreateEntry(func_name, &idx) != 0) return; // Fail silently
986
987 double elapsed = end_time - g_profiler_registry[idx].start_time;
988 g_profiler_registry[idx].total_time += elapsed;
992}
double start_time
Definition logging.c:899
Here is the call graph for this function:

Variable Documentation

◆ EVENT_Individualwalkingsearch

PetscLogEvent EVENT_Individualwalkingsearch
extern

Definition at line 33 of file logging.c.

◆ EVENT_walkingsearch

PetscLogEvent EVENT_walkingsearch
extern

Definition at line 34 of file logging.c.

◆ EVENT_GlobalParticleLocation

PetscLogEvent EVENT_GlobalParticleLocation
extern

Definition at line 35 of file logging.c.

◆ EVENT_IndividualLocation

PetscLogEvent EVENT_IndividualLocation
extern

Definition at line 36 of file logging.c.