PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
Data Structures | Macros | Enumerations | Functions | Variables
logging.c File Reference
#include "logging.h"
#include "AnalyticalSolutions.h"
#include "verification_sources.h"
Include dependency graph for logging.c:

Go to the source code of this file.

Data Structures

struct  ProfiledFunction
 

Macros

#define TMP_BUF_SIZE   128
 
#define __FUNCT__   "DualKSPMonitor"
 A custom KSP monitor that logs the true residual to a file and optionally to the console.
 
#define __FUNCT__   "LOG_CONTINUITY_METRICS"
 A custom KSP monitor that logs the true residual to a file and optionally to the console.
 
#define __FUNCT__   "LOG_FIELD_MIN_MAX"
 A custom KSP monitor that logs the true residual to a file and optionally to the console.
 
#define __FUNCT__   "LOG_FIELD_ANATOMY"
 A custom KSP monitor that logs the true residual to a file and optionally to the console.
 
#define __FUNCT__   "LOG_INTERPOLATION_ERROR"
 A custom KSP monitor that logs the true residual to a file and optionally to the console.
 
#define __FUNCT__   "LOG_SCATTER_METRICS"
 A custom KSP monitor that logs the true residual to a file and optionally to the console.
 
#define __FUNCT__   "ResetSearchMetrics"
 A custom KSP monitor that logs the true residual to a file and optionally to the console.
 
#define __FUNCT__   "LOG_SEARCH_METRICS"
 A custom KSP monitor that logs the true residual to a file and optionally to the console.
 
#define __FUNCT__   "CalculateAdvancedParticleMetrics"
 A custom KSP monitor that logs the true residual to a file and optionally to the console.
 
#define __FUNCT__   "LOG_PARTICLE_METRICS"
 A custom KSP monitor that logs the true residual to a file and optionally to the console.
 

Enumerations

enum  {
  SEARCH_METRIC_SUM_SEARCH_ATTEMPTS = 0 , SEARCH_METRIC_SUM_SEARCH_POPULATION , SEARCH_METRIC_SUM_SEARCH_LOCATED , SEARCH_METRIC_SUM_SEARCH_LOST ,
  SEARCH_METRIC_SUM_TRAVERSAL_STEPS , SEARCH_METRIC_SUM_RESEARCH , SEARCH_METRIC_SUM_TIE_BREAKS , SEARCH_METRIC_SUM_BOUNDARY_CLAMPS ,
  SEARCH_METRIC_SUM_BBOX_GUESS_SUCCESS , SEARCH_METRIC_SUM_BBOX_GUESS_FALLBACK , SEARCH_METRIC_SUM_MAX_TRAVERSAL_FAILS , SEARCH_METRIC_MAX_TRAVERSAL_STEPS ,
  SEARCH_METRIC_MAX_PASS_DEPTH , SEARCH_METRIC_REDUCTION_LEN
}
 

Functions

static void SearchMetricsReduceOp (void *invec, void *inoutvec, int *len, MPI_Datatype *datatype)
 Internal reduction callback for packed search metrics.
 
LogLevel get_log_level ()
 Implementation of get_log_level().
 
PetscErrorCode print_log_level (void)
 Internal helper implementation: print_log_level().
 
void set_allowed_functions (const char **functionList, int count)
 Implementation of set_allowed_functions().
 
PetscBool is_function_allowed (const char *functionName)
 Implementation of is_function_allowed().
 
PetscErrorCode LOG_CELL_VERTICES (const Cell *cell, PetscMPIInt rank)
 Implementation of LOG_CELL_VERTICES().
 
PetscErrorCode LOG_FACE_DISTANCES (PetscReal *d)
 Implementation of LOG_FACE_DISTANCES().
 
static void IntToStr (int value, char *buf, size_t bufsize)
 
static void Int64ToStr (PetscInt64 value, char *buf, size_t bufsize)
 
static void CellToStr (const PetscInt *cell, char *buf, size_t bufsize)
 
static void TripleRealToStr (const PetscReal *arr, char *buf, size_t bufsize)
 
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)
 
static void BuildRowFormatString (PetscMPIInt wRank, PetscInt wPID, PetscInt wCell, PetscInt wPos, PetscInt wVel, PetscInt wWt, char *fmtStr, size_t bufSize)
 
static void BuildHeaderString (char *headerStr, size_t bufSize, PetscMPIInt wRank, PetscInt wPID, PetscInt wCell, PetscInt wPos, PetscInt wVel, PetscInt wWt)
 
PetscErrorCode LOG_PARTICLE_FIELDS (UserCtx *user, PetscInt printInterval)
 Implementation of LOG_PARTICLE_FIELDS().
 
PetscBool IsParticleConsoleSnapshotEnabled (const SimCtx *simCtx)
 Implementation of IsParticleConsoleSnapshotEnabled().
 
PetscBool ShouldEmitPeriodicParticleConsoleSnapshot (const SimCtx *simCtx, PetscInt completed_step)
 Implementation of ShouldEmitPeriodicParticleConsoleSnapshot().
 
PetscErrorCode EmitParticleConsoleSnapshot (UserCtx *user, SimCtx *simCtx, PetscInt step)
 Implementation of EmitParticleConsoleSnapshot().
 
static void trim (char *s)
 Internal helper implementation: trim().
 
PetscErrorCode LoadAllowedFunctionsFromFile (const char filename[], char ***funcsOut, PetscInt *nOut)
 Implementation of LoadAllowedFunctionsFromFile().
 
PetscErrorCode FreeAllowedFunctions (char **funcs, PetscInt n)
 Internal helper implementation: FreeAllowedFunctions().
 
const char * BCFaceToString (BCFace face)
 Implementation of BCFaceToString().
 
const char * FieldInitializationToString (PetscInt FieldInitialization)
 Implementation of FieldInitializationToString().
 
const char * ParticleInitializationToString (ParticleInitializationType ParticleInitialization)
 Implementation of ParticleInitializationToString().
 
const char * LESModelToString (LESModelType LESFlag)
 Implementation of LESModelToString().
 
const char * MomentumSolverTypeToString (MomentumSolverType SolverFlag)
 Implementation of MomentumSolverTypeToString().
 
const char * BCTypeToString (BCType type)
 Implementation of BCTypeToString().
 
const char * BCHandlerTypeToString (BCHandlerType handler_type)
 Internal helper implementation: BCHandlerTypeToString().
 
PetscErrorCode DualMonitorDestroy (void **ctx)
 Implementation of DualMonitorDestroy().
 
PetscErrorCode DualKSPMonitor (KSP ksp, PetscInt it, PetscReal rnorm, void *ctx)
 Implementation of DualKSPMonitor().
 
PetscErrorCode LOG_CONTINUITY_METRICS (UserCtx *user)
 Implementation of LOG_CONTINUITY_METRICS().
 
const char * ParticleLocationStatusToString (ParticleLocationStatus level)
 Implementation of ParticleLocationStatusToString().
 
static PetscErrorCode _FindOrCreateEntry (const char *func_name, PetscInt *idx)
 Internal helper implementation: _FindOrCreateEntry().
 
PetscErrorCode ProfilingInitialize (SimCtx *simCtx)
 Internal helper implementation: ProfilingInitialize().
 
void _ProfilingStart (const char *func_name)
 Implementation of _ProfilingStart().
 
void _ProfilingEnd (const char *func_name)
 Implementation of _ProfilingEnd().
 
PetscErrorCode ProfilingResetTimestepCounters (void)
 Implementation of ProfilingResetTimestepCounters().
 
PetscErrorCode ProfilingLogTimestepSummary (SimCtx *simCtx, PetscInt step)
 Implementation of ProfilingLogTimestepSummary().
 
static int _CompareProfiledFunctions (const void *a, const void *b)
 Internal helper implementation: _CompareProfiledFunctions().
 
PetscErrorCode ProfilingFinalize (SimCtx *simCtx)
 Implementation of ProfilingFinalize().
 
void PrintProgressBar (PetscInt step, PetscInt startStep, PetscInt totalSteps, PetscReal currentTime)
 Internal helper implementation: PrintProgressBar().
 
PetscErrorCode LOG_FIELD_MIN_MAX (UserCtx *user, const char *fieldName)
 Implementation of LOG_FIELD_MIN_MAX().
 
PetscErrorCode LOG_FIELD_ANATOMY (UserCtx *user, const char *field_name, const char *stage_name)
 Implementation of LOG_FIELD_ANATOMY().
 
PetscErrorCode LOG_INTERPOLATION_ERROR (UserCtx *user)
 Implementation of LOG_INTERPOLATION_ERROR().
 
PetscErrorCode LOG_SCATTER_METRICS (UserCtx *user)
 Implementation of LOG_SCATTER_METRICS().
 
PetscErrorCode ResetSearchMetrics (SimCtx *simCtx)
 Implementation of ResetSearchMetrics().
 
PetscErrorCode LOG_SEARCH_METRICS (UserCtx *user)
 Implementation of LOG_SEARCH_METRICS().
 
PetscErrorCode CalculateAdvancedParticleMetrics (UserCtx *user)
 Internal helper implementation: CalculateAdvancedParticleMetrics().
 
PetscErrorCode LOG_PARTICLE_METRICS (UserCtx *user, const char *stageName)
 Implementation of LOG_PARTICLE_METRICS().
 

Variables

static LogLevel current_log_level = -1
 Static variable to cache the current logging level.
 
static char ** gAllowedFunctions = NULL
 Global/static array of function names allowed to log.
 
static int gNumAllowed = 0
 Number of entries in the gAllowedFunctions array.
 
static ProfiledFunctiong_profiler_registry = NULL
 
static PetscInt g_profiler_count = 0
 
static PetscInt g_profiler_capacity = 0
 

Data Structure Documentation

◆ ProfiledFunction

struct ProfiledFunction

Definition at line 988 of file logging.c.

Data Fields
const char * name
double total_time
double current_step_time
long long total_call_count
long long current_step_call_count
double start_time
PetscBool always_log

Macro Definition Documentation

◆ TMP_BUF_SIZE

#define TMP_BUF_SIZE   128

Definition at line 7 of file logging.c.

◆ __FUNCT__ [1/10]

#define __FUNCT__   "DualKSPMonitor"

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

Logs continuity metrics for a single block to a file.

This function replicates the behavior of KSPMonitorTrueResidualNorm by calculating the true residual norm ||b - Ax|| itself. It unconditionally logs to a file viewer and conditionally logs to the console based on a flag in the context.

Parameters
kspThe Krylov subspace context.
itThe current iteration number.
rnormThe preconditioned residual norm (ignored, we compute our own).
ctxA pointer to the DualMonitorCtx structure.
Returns
PetscErrorCode 0 on success.

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 839 of file logging.c.

◆ __FUNCT__ [2/10]

#define __FUNCT__   "LOG_CONTINUITY_METRICS"

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

Logs continuity metrics for a single block to a file.

This function replicates the behavior of KSPMonitorTrueResidualNorm by calculating the true residual norm ||b - Ax|| itself. It unconditionally logs to a file viewer and conditionally logs to the console based on a flag in the context.

Parameters
kspThe Krylov subspace context.
itThe current iteration number.
rnormThe preconditioned residual norm (ignored, we compute our own).
ctxA pointer to the DualMonitorCtx structure.
Returns
PetscErrorCode 0 on success.

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 839 of file logging.c.

◆ __FUNCT__ [3/10]

#define __FUNCT__   "LOG_FIELD_MIN_MAX"

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

Logs continuity metrics for a single block to a file.

This function replicates the behavior of KSPMonitorTrueResidualNorm by calculating the true residual norm ||b - Ax|| itself. It unconditionally logs to a file viewer and conditionally logs to the console based on a flag in the context.

Parameters
kspThe Krylov subspace context.
itThe current iteration number.
rnormThe preconditioned residual norm (ignored, we compute our own).
ctxA pointer to the DualMonitorCtx structure.
Returns
PetscErrorCode 0 on success.

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 839 of file logging.c.

◆ __FUNCT__ [4/10]

#define __FUNCT__   "LOG_FIELD_ANATOMY"

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

Logs continuity metrics for a single block to a file.

This function replicates the behavior of KSPMonitorTrueResidualNorm by calculating the true residual norm ||b - Ax|| itself. It unconditionally logs to a file viewer and conditionally logs to the console based on a flag in the context.

Parameters
kspThe Krylov subspace context.
itThe current iteration number.
rnormThe preconditioned residual norm (ignored, we compute our own).
ctxA pointer to the DualMonitorCtx structure.
Returns
PetscErrorCode 0 on success.

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 839 of file logging.c.

◆ __FUNCT__ [5/10]

#define __FUNCT__   "LOG_INTERPOLATION_ERROR"

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

Logs continuity metrics for a single block to a file.

This function replicates the behavior of KSPMonitorTrueResidualNorm by calculating the true residual norm ||b - Ax|| itself. It unconditionally logs to a file viewer and conditionally logs to the console based on a flag in the context.

Parameters
kspThe Krylov subspace context.
itThe current iteration number.
rnormThe preconditioned residual norm (ignored, we compute our own).
ctxA pointer to the DualMonitorCtx structure.
Returns
PetscErrorCode 0 on success.

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 839 of file logging.c.

◆ __FUNCT__ [6/10]

#define __FUNCT__   "LOG_SCATTER_METRICS"

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

Logs continuity metrics for a single block to a file.

This function replicates the behavior of KSPMonitorTrueResidualNorm by calculating the true residual norm ||b - Ax|| itself. It unconditionally logs to a file viewer and conditionally logs to the console based on a flag in the context.

Parameters
kspThe Krylov subspace context.
itThe current iteration number.
rnormThe preconditioned residual norm (ignored, we compute our own).
ctxA pointer to the DualMonitorCtx structure.
Returns
PetscErrorCode 0 on success.

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 839 of file logging.c.

◆ __FUNCT__ [7/10]

#define __FUNCT__   "ResetSearchMetrics"

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

Logs continuity metrics for a single block to a file.

This function replicates the behavior of KSPMonitorTrueResidualNorm by calculating the true residual norm ||b - Ax|| itself. It unconditionally logs to a file viewer and conditionally logs to the console based on a flag in the context.

Parameters
kspThe Krylov subspace context.
itThe current iteration number.
rnormThe preconditioned residual norm (ignored, we compute our own).
ctxA pointer to the DualMonitorCtx structure.
Returns
PetscErrorCode 0 on success.

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 839 of file logging.c.

◆ __FUNCT__ [8/10]

#define __FUNCT__   "LOG_SEARCH_METRICS"

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

Logs continuity metrics for a single block to a file.

This function replicates the behavior of KSPMonitorTrueResidualNorm by calculating the true residual norm ||b - Ax|| itself. It unconditionally logs to a file viewer and conditionally logs to the console based on a flag in the context.

Parameters
kspThe Krylov subspace context.
itThe current iteration number.
rnormThe preconditioned residual norm (ignored, we compute our own).
ctxA pointer to the DualMonitorCtx structure.
Returns
PetscErrorCode 0 on success.

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 839 of file logging.c.

◆ __FUNCT__ [9/10]

#define __FUNCT__   "CalculateAdvancedParticleMetrics"

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

Logs continuity metrics for a single block to a file.

This function replicates the behavior of KSPMonitorTrueResidualNorm by calculating the true residual norm ||b - Ax|| itself. It unconditionally logs to a file viewer and conditionally logs to the console based on a flag in the context.

Parameters
kspThe Krylov subspace context.
itThe current iteration number.
rnormThe preconditioned residual norm (ignored, we compute our own).
ctxA pointer to the DualMonitorCtx structure.
Returns
PetscErrorCode 0 on success.

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 839 of file logging.c.

◆ __FUNCT__ [10/10]

#define __FUNCT__   "LOG_PARTICLE_METRICS"

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

Logs continuity metrics for a single block to a file.

This function replicates the behavior of KSPMonitorTrueResidualNorm by calculating the true residual norm ||b - Ax|| itself. It unconditionally logs to a file viewer and conditionally logs to the console based on a flag in the context.

Parameters
kspThe Krylov subspace context.
itThe current iteration number.
rnormThe preconditioned residual norm (ignored, we compute our own).
ctxA pointer to the DualMonitorCtx structure.
Returns
PetscErrorCode 0 on success.

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 839 of file logging.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
SEARCH_METRIC_SUM_SEARCH_ATTEMPTS 
SEARCH_METRIC_SUM_SEARCH_POPULATION 
SEARCH_METRIC_SUM_SEARCH_LOCATED 
SEARCH_METRIC_SUM_SEARCH_LOST 
SEARCH_METRIC_SUM_TRAVERSAL_STEPS 
SEARCH_METRIC_SUM_RESEARCH 
SEARCH_METRIC_SUM_TIE_BREAKS 
SEARCH_METRIC_SUM_BOUNDARY_CLAMPS 
SEARCH_METRIC_SUM_BBOX_GUESS_SUCCESS 
SEARCH_METRIC_SUM_BBOX_GUESS_FALLBACK 
SEARCH_METRIC_SUM_MAX_TRAVERSAL_FAILS 
SEARCH_METRIC_MAX_TRAVERSAL_STEPS 
SEARCH_METRIC_MAX_PASS_DEPTH 
SEARCH_METRIC_REDUCTION_LEN 

Definition at line 30 of file logging.c.

30 {
45};
@ SEARCH_METRIC_SUM_SEARCH_LOCATED
Definition logging.c:33
@ SEARCH_METRIC_SUM_MAX_TRAVERSAL_FAILS
Definition logging.c:41
@ SEARCH_METRIC_REDUCTION_LEN
Definition logging.c:44
@ SEARCH_METRIC_SUM_BBOX_GUESS_FALLBACK
Definition logging.c:40
@ SEARCH_METRIC_SUM_RESEARCH
Definition logging.c:36
@ SEARCH_METRIC_SUM_TRAVERSAL_STEPS
Definition logging.c:35
@ SEARCH_METRIC_MAX_TRAVERSAL_STEPS
Definition logging.c:42
@ SEARCH_METRIC_SUM_BOUNDARY_CLAMPS
Definition logging.c:38
@ SEARCH_METRIC_SUM_SEARCH_POPULATION
Definition logging.c:32
@ SEARCH_METRIC_MAX_PASS_DEPTH
Definition logging.c:43
@ SEARCH_METRIC_SUM_TIE_BREAKS
Definition logging.c:37
@ SEARCH_METRIC_SUM_SEARCH_LOST
Definition logging.c:34
@ SEARCH_METRIC_SUM_BBOX_GUESS_SUCCESS
Definition logging.c:39
@ SEARCH_METRIC_SUM_SEARCH_ATTEMPTS
Definition logging.c:31

Function Documentation

◆ SearchMetricsReduceOp()

static void SearchMetricsReduceOp ( void *  invec,
void *  inoutvec,
int *  len,
MPI_Datatype *  datatype 
)
static

Internal reduction callback for packed search metrics.

Local to this translation unit.

Definition at line 51 of file logging.c.

52{
53 PetscReal *in = (PetscReal *)invec;
54 PetscReal *inout = (PetscReal *)inoutvec;
55 (void)datatype;
56
57 for (int idx = 0; idx < *len; idx += SEARCH_METRIC_REDUCTION_LEN) {
71 inout[idx + SEARCH_METRIC_MAX_PASS_DEPTH] = PetscMax(inout[idx + SEARCH_METRIC_MAX_PASS_DEPTH],
73 }
74}
Here is the caller graph for this function:

◆ get_log_level()

LogLevel get_log_level ( )

Implementation of get_log_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 84 of file logging.c.

84 {
85 if (current_log_level == -1) { // Log level not set yet
86 const char *env = getenv("LOG_LEVEL");
87 if (!env) {
88 current_log_level = LOG_ERROR; // Default level
89 }
90 else if (strcmp(env, "DEBUG") == 0) {
92 }
93 else if (strcmp(env, "INFO") == 0) {
95 }
96 else if (strcmp(env, "WARNING") == 0) {
98 }
99 else if (strcmp(env, "VERBOSE") == 0) {
101 }
102 else if (strcmp(env, "TRACE") == 0) {
104 }
105 else {
106 current_log_level = LOG_ERROR; // Default if unrecognized
107 }
108 }
109 return current_log_level;
110}
static LogLevel current_log_level
Static variable to cache the current logging level.
Definition logging.c:16
@ LOG_ERROR
Critical errors that may halt the program.
Definition logging.h:28
@ LOG_TRACE
Very fine-grained tracing information for in-depth debugging.
Definition logging.h:32
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:30
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:29
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:31
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
Definition logging.h:33
Here is the caller graph for this function:

◆ print_log_level()

PetscErrorCode print_log_level ( void  )

Internal helper implementation: print_log_level().

Prints the current logging level to the console.

Local to this translation unit.

Definition at line 116 of file logging.c.

117{
118 PetscMPIInt rank;
119 PetscErrorCode ierr;
120 int level;
121 const char *level_name;
122
123 PetscFunctionBeginUser;
124 /* get MPI rank */
125 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRMPI(ierr);
126
127 /* decide level name */
128 level = get_log_level();
129 level_name = (level == LOG_ERROR) ? "ERROR" :
130 (level == LOG_WARNING) ? "WARNING" :
131 (level == LOG_INFO) ? "INFO" :
132 (level == LOG_DEBUG) ? "DEBUG" :
133 (level == LOG_VERBOSE) ? "VERBOSE" :
134 (level == LOG_TRACE) ? "TRACE" :
135 "UNKNOWN";
136
137 /* print it out */
138 ierr = PetscPrintf(PETSC_COMM_SELF,
139 "Current log level: %s (%d) | rank: %d\n",
140 level_name, level, (int)rank);
141 CHKERRMPI(ierr);
142
143 PetscFunctionReturn(PETSC_SUCCESS);
144}
LogLevel get_log_level()
Implementation of get_log_level().
Definition logging.c:84
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 
)

Implementation of set_allowed_functions().

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 152 of file logging.c.

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

◆ is_function_allowed()

PetscBool is_function_allowed ( const char *  functionName)

Implementation of is_function_allowed().

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 183 of file logging.c.

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

◆ LOG_CELL_VERTICES()

PetscErrorCode LOG_CELL_VERTICES ( const Cell cell,
PetscMPIInt  rank 
)

Implementation of LOG_CELL_VERTICES().

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 205 of file logging.c.

206{
207
208 // Validate input pointers
209 if (cell == NULL) {
210 LOG_ALLOW(LOCAL,LOG_ERROR, "'cell' is NULL.\n");
211 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "LOG_CELL_VERTICES - Input parameter 'cell' is NULL.");
212 }
213
214 LOG_ALLOW(LOCAL,LOG_VERBOSE, "Rank %d, Cell Vertices:\n", rank);
215 for(int i = 0; i < 8; i++){
216 LOG_ALLOW(LOCAL,LOG_VERBOSE, " Vertex[%d]: (%.2f, %.2f, %.2f)\n",
217 i, cell->vertices[i].x, cell->vertices[i].y, cell->vertices[i].z);
218 }
219
220 return 0; // Indicate successful execution
221}
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:44
#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:199
PetscScalar x
Definition variables.h:101
PetscScalar z
Definition variables.h:101
PetscScalar y
Definition variables.h:101
Cmpnts vertices[8]
Coordinates of the eight vertices of the cell.
Definition variables.h:161
Here is the caller graph for this function:

◆ LOG_FACE_DISTANCES()

PetscErrorCode LOG_FACE_DISTANCES ( PetscReal *  d)

Implementation of LOG_FACE_DISTANCES().

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 230 of file logging.c.

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

◆ IntToStr()

static void IntToStr ( int  value,
char *  buf,
size_t  bufsize 
)
static

Definition at line 253 of file logging.c.

254{
255 snprintf(buf, bufsize, "%d", value);
256}
Here is the caller graph for this function:

◆ Int64ToStr()

static void Int64ToStr ( PetscInt64  value,
char *  buf,
size_t  bufsize 
)
static

Definition at line 261 of file logging.c.

262{
263 snprintf(buf, bufsize, "%ld", value);
264}
Here is the caller graph for this function:

◆ CellToStr()

static void CellToStr ( const PetscInt *  cell,
char *  buf,
size_t  bufsize 
)
static

Definition at line 269 of file logging.c.

270{
271 snprintf(buf, bufsize, "(%d, %d, %d)", cell[0], cell[1], cell[2]);
272}
Here is the caller graph for this function:

◆ TripleRealToStr()

static void TripleRealToStr ( const PetscReal *  arr,
char *  buf,
size_t  bufsize 
)
static

Definition at line 277 of file logging.c.

278{
279 snprintf(buf, bufsize, "(%.4f, %.4f, %.4f)", arr[0], arr[1], arr[2]);
280}
Here is the caller graph for this function:

◆ ComputeMaxColumnWidths()

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

Definition at line 302 of file logging.c.

311{
312 char tmp[TMP_BUF_SIZE];
313
314 *wRank = strlen("Rank"); /* Start with the header label lengths */
315 *wPID = strlen("PID");
316 *wCell = strlen("Cell (i,j,k)");
317 *wPos = strlen("Position (x,y,z)");
318 *wVel = strlen("Velocity (x,y,z)");
319 *wWt = strlen("Weights (a1,a2,a3)");
320
321 for (PetscInt i = 0; i < nParticles; i++) {
322 /* Rank */
323 IntToStr(ranks[i], tmp, TMP_BUF_SIZE);
324 if ((int)strlen(tmp) > *wRank) *wRank = (int)strlen(tmp);
325
326 /* PID */
327 Int64ToStr(pids[i], tmp, TMP_BUF_SIZE);
328 if ((int)strlen(tmp) > *wPID) *wPID = (int)strlen(tmp);
329
330 /* Cell: use the three consecutive values */
331 CellToStr(&cellIDs[3 * i], tmp, TMP_BUF_SIZE);
332 if ((int)strlen(tmp) > *wCell) *wCell = (int)strlen(tmp);
333
334 /* Position */
335 TripleRealToStr(&positions[3 * i], tmp, TMP_BUF_SIZE);
336 if ((int)strlen(tmp) > *wPos) *wPos = (int)strlen(tmp);
337
338 /* Velocity */
339 TripleRealToStr(&velocities[3 * i], tmp, TMP_BUF_SIZE);
340 if ((int)strlen(tmp) > *wVel) *wVel = (int)strlen(tmp);
341
342 /* Weights */
343 TripleRealToStr(&weights[3 * i], tmp, TMP_BUF_SIZE);
344 if ((int)strlen(tmp) > *wWt) *wWt = (int)strlen(tmp);
345 }
346 return 0;
347}
#define TMP_BUF_SIZE
Definition logging.c:7
static void CellToStr(const PetscInt *cell, char *buf, size_t bufsize)
Definition logging.c:269
static void TripleRealToStr(const PetscReal *arr, char *buf, size_t bufsize)
Definition logging.c:277
static void Int64ToStr(PetscInt64 value, char *buf, size_t bufsize)
Definition logging.c:261
static void IntToStr(int value, char *buf, size_t bufsize)
Definition logging.c:253
Here is the call graph for this function:
Here is the caller graph for this function:

◆ BuildRowFormatString()

static void BuildRowFormatString ( PetscMPIInt  wRank,
PetscInt  wPID,
PetscInt  wCell,
PetscInt  wPos,
PetscInt  wVel,
PetscInt  wWt,
char *  fmtStr,
size_t  bufSize 
)
static

Definition at line 366 of file logging.c.

367{
368 // Build a format string using snprintf.
369 // We assume that the Rank is an int (%d), PID is a 64-bit int (%ld)
370 // and the remaining columns are strings (which have been formatted already).
371 snprintf(fmtStr, bufSize,
372 "| %%-%dd | %%-%dd | %%-%ds | %%-%ds | %%-%ds | %%-%ds |\n",
373 wRank, wPID, wCell, wPos, wVel, wWt);
374}
Here is the caller graph for this function:

◆ BuildHeaderString()

static void BuildHeaderString ( char *  headerStr,
size_t  bufSize,
PetscMPIInt  wRank,
PetscInt  wPID,
PetscInt  wCell,
PetscInt  wPos,
PetscInt  wVel,
PetscInt  wWt 
)
static

Definition at line 379 of file logging.c.

380{
381 snprintf(headerStr, bufSize,
382 "| %-*s | %-*s | %-*s | %-*s | %-*s | %-*s |\n",
383 (int)wRank, "Rank",
384 (int)wPID, "PID",
385 (int)wCell, "Cell (i,j,k)",
386 (int)wPos, "Position (x,y,z)",
387 (int)wVel, "Velocity (x,y,z)",
388 (int)wWt, "Weights (a1,a2,a3)");
389}
Here is the caller graph for this function:

◆ LOG_PARTICLE_FIELDS()

PetscErrorCode LOG_PARTICLE_FIELDS ( UserCtx user,
PetscInt  printInterval 
)

Implementation of LOG_PARTICLE_FIELDS().

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 397 of file logging.c.

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

◆ IsParticleConsoleSnapshotEnabled()

PetscBool IsParticleConsoleSnapshotEnabled ( const SimCtx simCtx)

Implementation 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 525 of file logging.c.

526{
527 if (!simCtx) {
528 return PETSC_FALSE;
529 }
530 return (PetscBool)(simCtx->np > 0 &&
531 simCtx->particleConsoleOutputFreq > 0 &&
533}
PetscInt np
Definition variables.h:739
PetscInt particleConsoleOutputFreq
Definition variables.h:656
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 
)

Implementation 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 542 of file logging.c.

543{
544 return (PetscBool)(IsParticleConsoleSnapshotEnabled(simCtx) &&
545 completed_step > 0 &&
546 completed_step % simCtx->particleConsoleOutputFreq == 0);
547}
PetscBool IsParticleConsoleSnapshotEnabled(const SimCtx *simCtx)
Implementation of IsParticleConsoleSnapshotEnabled().
Definition logging.c:525
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 
)

Implementation of EmitParticleConsoleSnapshot().

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 556 of file logging.c.

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

◆ trim()

static void trim ( char *  s)
static

Internal helper implementation: trim().

Local to this translation unit.

Definition at line 571 of file logging.c.

572{
573 if (!s) return;
574
575 /* ---- 1. strip leading blanks ----------------------------------- */
576 char *p = s;
577 while (*p && isspace((unsigned char)*p))
578 ++p;
579
580 if (p != s) /* move the trimmed text forward */
581 memmove(s, p, strlen(p) + 1); /* +1 to copy the final NUL */
582
583 /* ---- 2. strip trailing blanks ---------------------------------- */
584 size_t len = strlen(s);
585 while (len > 0 && isspace((unsigned char)s[len - 1]))
586 s[--len] = '\0';
587}
Here is the caller graph for this function:

◆ LoadAllowedFunctionsFromFile()

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

Implementation of LoadAllowedFunctionsFromFile().

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 596 of file logging.c.

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

◆ FreeAllowedFunctions()

PetscErrorCode FreeAllowedFunctions ( char **  funcs,
PetscInt  n 
)

Internal helper implementation: FreeAllowedFunctions().

Free an array previously returned by LoadAllowedFunctionsFromFile().

Local to this translation unit.

Definition at line 650 of file logging.c.

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

◆ BCFaceToString()

const char * BCFaceToString ( BCFace  face)

Implementation of BCFaceToString().

Helper function to convert BCFace enum to a string representation.

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

See also
BCFaceToString()

Definition at line 669 of file logging.c.

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

◆ FieldInitializationToString()

const char * FieldInitializationToString ( PetscInt  FieldInitialization)

Implementation of FieldInitializationToString().

Helper function to convert FieldInitialization to a string representation.

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

See also
FieldInitializationToString()

Definition at line 687 of file logging.c.

688{
689 switch(FieldInitialization){
690 case 0: return "Zero";
691 case 1: return "Constant Normal velocity";
692 case 2: return "Poiseuille Normal velocity";
693 default: return "Unknown Field Initialization";
694 }
695}
Here is the caller graph for this function:

◆ ParticleInitializationToString()

const char * ParticleInitializationToString ( ParticleInitializationType  ParticleInitialization)

Implementation of ParticleInitializationToString().

Helper function to convert ParticleInitialization to a string representation.

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

See also
ParticleInitializationToString()

Definition at line 703 of file logging.c.

704{
705 switch(ParticleInitialization){
706 case PARTICLE_INIT_SURFACE_RANDOM: return "Surface: Random";
707 case PARTICLE_INIT_VOLUME: return "Volume";
708 case PARTICLE_INIT_POINT_SOURCE: return "Point Source";
709 case PARTICLE_INIT_SURFACE_EDGES: return "Surface: At edges";
710 default: return "Unknown Particle Initialization";
711 }
712}
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
Definition variables.h:509
@ PARTICLE_INIT_SURFACE_EDGES
Deterministic placement at inlet face edges.
Definition variables.h:512
@ PARTICLE_INIT_POINT_SOURCE
All particles at a fixed (psrc_x,psrc_y,psrc_z) — for validation.
Definition variables.h:511
@ PARTICLE_INIT_VOLUME
Random volumetric distribution across the domain.
Definition variables.h:510
Here is the caller graph for this function:

◆ LESModelToString()

const char * LESModelToString ( LESModelType  LESFlag)

Implementation of LESModelToString().

Helper function to convert LES Flag to a string representation.

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

See also
LESModelToString()

Definition at line 720 of file logging.c.

721{
722 switch(LESFlag){
723 case NO_LES_MODEL: return "No LES";
724 case CONSTANT_SMAGORINSKY: return "Constant Smagorinsky";
725 case DYNAMIC_SMAGORINSKY: return "Dynamic Smagorinsky";
726 default: return "Unknown LES Flag";
727 }
728}
@ DYNAMIC_SMAGORINSKY
Definition variables.h:491
@ NO_LES_MODEL
Definition variables.h:489
@ CONSTANT_SMAGORINSKY
Definition variables.h:490
Here is the caller graph for this function:

◆ MomentumSolverTypeToString()

const char * MomentumSolverTypeToString ( MomentumSolverType  SolverFlag)

Implementation of MomentumSolverTypeToString().

Helper function to convert Momentum Solver flag to a string representation.

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

See also
MomentumSolverTypeToString()

Definition at line 736 of file logging.c.

737{
738 switch(SolverFlag){
739 case MOMENTUM_SOLVER_EXPLICIT_RK: return "Explicit 4 stage Runge-Kutta ";
740 case MOMENTUM_SOLVER_DUALTIME_PICARD_RK4: return "Dual Time Stepping with Picard Iterations and 4 stage Runge-Kutta Smoothing";
741 default: return "Unknown Momentum Solver Type";
742 }
743}
@ MOMENTUM_SOLVER_EXPLICIT_RK
Definition variables.h:503
@ MOMENTUM_SOLVER_DUALTIME_PICARD_RK4
Definition variables.h:504
Here is the caller graph for this function:

◆ BCTypeToString()

const char * BCTypeToString ( BCType  type)

Implementation of BCTypeToString().

Helper function to convert BCType enum to a string representation.

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

See also
BCTypeToString()

Definition at line 751 of file logging.c.

751 {
752 switch (type) {
753 // case DIRICHLET: return "DIRICHLET";
754 // case NEUMANN: return "NEUMANN";
755 case WALL: return "WALL";
756 case INLET: return "INLET";
757 case OUTLET: return "OUTLET";
758 case FARFIELD: return "FARFIELD";
759 case PERIODIC: return "PERIODIC";
760 case INTERFACE: return "INTERFACE";
761
762 // case CUSTOM: return "CUSTOM";
763 default: return "Unknown BC Type";
764 }
765}
@ INLET
Definition variables.h:258
@ INTERFACE
Definition variables.h:253
@ FARFIELD
Definition variables.h:259
@ OUTLET
Definition variables.h:257
@ PERIODIC
Definition variables.h:260
@ WALL
Definition variables.h:254
Here is the caller graph for this function:

◆ BCHandlerTypeToString()

const char * BCHandlerTypeToString ( BCHandlerType  handler_type)

Internal helper implementation: BCHandlerTypeToString().

Converts a BCHandlerType enum to its string representation.

Local to this translation unit.

Definition at line 771 of file logging.c.

771 {
772 switch (handler_type) {
773 // Wall & Symmetry Handlers
774 case BC_HANDLER_WALL_NOSLIP: return "noslip";
775 case BC_HANDLER_WALL_MOVING: return "moving";
776 case BC_HANDLER_SYMMETRY_PLANE: return "symmetry_plane";
777
778 // Inlet Handlers
779 case BC_HANDLER_INLET_CONSTANT_VELOCITY: return "constant_velocity";
780 case BC_HANDLER_INLET_PULSATILE_FLUX: return "pulsatile_flux";
781 case BC_HANDLER_INLET_PARABOLIC: return "parabolic";
782
783 // Outlet Handlers
784 case BC_HANDLER_OUTLET_CONSERVATION: return "conservation";
785 case BC_HANDLER_OUTLET_PRESSURE: return "pressure";
786
787 // Other Physical Handlers
788 case BC_HANDLER_FARFIELD_NONREFLECTING: return "nonreflecting";
789
790 // Multi-Block / Interface Handlers
791 case BC_HANDLER_PERIODIC_GEOMETRIC: return "geometric";
792 case BC_HANDLER_PERIODIC_DRIVEN_CONSTANT_FLUX: return "constant flux";
793 case BC_HANDLER_PERIODIC_DRIVEN_INITIAL_FLUX: return "initial flux";
794 case BC_HANDLER_INTERFACE_OVERSET: return "overset";
795
796 // Default case
798 default: return "UNKNOWN_HANDLER";
799 }
800}
@ BC_HANDLER_INLET_PULSATILE_FLUX
Definition variables.h:280
@ BC_HANDLER_PERIODIC_GEOMETRIC
Definition variables.h:284
@ BC_HANDLER_INLET_PARABOLIC
Definition variables.h:277
@ BC_HANDLER_INLET_CONSTANT_VELOCITY
Definition variables.h:276
@ BC_HANDLER_PERIODIC_DRIVEN_INITIAL_FLUX
Definition variables.h:287
@ BC_HANDLER_INTERFACE_OVERSET
Definition variables.h:285
@ BC_HANDLER_PERIODIC_DRIVEN_CONSTANT_FLUX
Definition variables.h:286
@ BC_HANDLER_WALL_MOVING
Definition variables.h:274
@ BC_HANDLER_WALL_NOSLIP
Definition variables.h:273
@ BC_HANDLER_OUTLET_CONSERVATION
Definition variables.h:282
@ BC_HANDLER_FARFIELD_NONREFLECTING
Definition variables.h:281
@ BC_HANDLER_OUTLET_PRESSURE
Definition variables.h:283
@ BC_HANDLER_SYMMETRY_PLANE
Definition variables.h:275
@ BC_HANDLER_UNDEFINED
Definition variables.h:272
Here is the caller graph for this function:

◆ DualMonitorDestroy()

PetscErrorCode DualMonitorDestroy ( void **  ctx)

Implementation of DualMonitorDestroy().

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 808 of file logging.c.

809{
810 DualMonitorCtx *monctx = (DualMonitorCtx*)*ctx;
811 PetscErrorCode ierr;
812 PetscMPIInt rank;
813
814 PetscFunctionBeginUser;
815 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
816 if(!rank && monctx->file_handle){
817 fclose(monctx->file_handle);
818 }
819
820 ierr = PetscFree(monctx); CHKERRQ(ierr);
821 *ctx = NULL;
822 PetscFunctionReturn(0);
823}
FILE * file_handle
Definition logging.h:56
Context for a dual-purpose KSP monitor.
Definition logging.h:55
Here is the caller graph for this function:

◆ DualKSPMonitor()

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

Implementation of DualKSPMonitor().

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 847 of file logging.c.

848{
849 DualMonitorCtx *monctx = (DualMonitorCtx*)ctx;
850 PetscErrorCode ierr;
851 PetscReal trnorm, relnorm;
852 Vec r;
853 char norm_buf[256];
854 PetscMPIInt rank;
855
856 PetscFunctionBeginUser;
857 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
858
859 // 1. Calculate the true residual norm.
860 ierr = KSPBuildResidual(ksp, NULL, NULL, &r); CHKERRQ(ierr);
861 ierr = VecNorm(r, NORM_2, &trnorm); CHKERRQ(ierr);
862
863 // 2. On the first iteration, compute and store the norm of the RHS vector `b`.
864 if (it == 0) {
865 Vec b;
866 ierr = KSPGetRhs(ksp, &b); CHKERRQ(ierr);
867 ierr = VecNorm(b, NORM_2, &monctx->bnorm); CHKERRQ(ierr);
868 }
869
870 if(!rank){
871 // 3. Compute the relative norm and format the output string.
872 if (monctx->bnorm > 1.e-15) {
873 relnorm = trnorm / monctx->bnorm;
874 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);
875 } else {
876 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);
877 }
878
879 // 4. Log to the file viewer (unconditionally).
880 if(monctx->file_handle){
881 ierr = PetscFPrintf(PETSC_COMM_SELF,monctx->file_handle,"%s\n", norm_buf); CHKERRQ(ierr);
882 }
883 // 5. Log to the console (conditionally).
884 if (monctx->log_to_console) {
885 PetscFPrintf(PETSC_COMM_SELF,stdout, "%s\n", norm_buf); CHKERRQ(ierr);
886 }
887
888 } //rank
889
890 PetscFunctionReturn(0);
891}
PetscBool log_to_console
Definition logging.h:57
PetscReal bnorm
Definition logging.h:58
PetscInt step
Definition logging.h:59
PetscInt block_id
Definition logging.h:60
Here is the caller graph for this function:

◆ LOG_CONTINUITY_METRICS()

PetscErrorCode LOG_CONTINUITY_METRICS ( UserCtx user)

Implementation of LOG_CONTINUITY_METRICS().

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 914 of file logging.c.

915{
916 PetscErrorCode ierr;
917 PetscMPIInt rank;
918 SimCtx *simCtx = user->simCtx; // Get the shared SimCtx
919 const PetscInt bi = user->_this; // Get this block's specific ID
920 const PetscInt ti = simCtx->step; // Get the current timestep
921
922 PetscFunctionBeginUser;
923 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
924
925 // Only rank 0 performs file I/O.
926 if (!rank) {
927 FILE *f;
928 char filen[PETSC_MAX_PATH_LEN + 64];
929 ierr = PetscSNPrintf(filen, sizeof(filen), "%s/Continuity_Metrics.log", simCtx->log_dir); CHKERRQ(ierr);
930
931 // Open the log file in append mode.
932 f = fopen(filen, "a");
933 if (!f) {
934 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open log file: %s", filen);
935 }
936
937 // Write a header only when the file is empty and it's the first block (bi=0).
938 // Using ftell() instead of step comparison ensures correctness across continuations.
939 if (ftell(f) == 0 && bi == 0) {
940 PetscFPrintf(PETSC_COMM_SELF, f, "%-10s | %-6s | %-18s | %-30s | %-18s | %-18s | %-18s | %-18s\n",
941 "Timestep", "Block", "Max Divergence", "Max Divergence Location ([k][j][i]=idx)", "Sum(RHS)","Total Flux In", "Total Flux Out", "Net Flux");
942 PetscFPrintf(PETSC_COMM_SELF, f, "------------------------------------------------------------------------------------------------------------------------------------------\n");
943 }
944
945 // Prepare the data strings and values for the current block.
946 PetscReal net_flux = simCtx->FluxInSum - simCtx->FluxOutSum;
947 char location_str[64];
948 sprintf(location_str, "([%d][%d][%d] = %d)", (int)simCtx->MaxDivz, (int)simCtx->MaxDivy, (int)simCtx->MaxDivx, (int)simCtx->MaxDivFlatArg);
949
950 // Write the formatted line for the current block.
951 PetscFPrintf(PETSC_COMM_SELF, f, "%-10d | %-6d | %-18.10e | %-39s | %-18.10e | %-18.10e | %-18.10e | %-18.10e\n",
952 (int)ti,
953 (int)bi,
954 (double)simCtx->MaxDiv,
955 location_str,
956 (double)simCtx->summationRHS,
957 (double)simCtx->FluxInSum,
958 (double)simCtx->FluxOutSum,
959 (double)net_flux);
960
961 fclose(f);
962 }
963
964 PetscFunctionReturn(0);
965}
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:814
PetscReal FluxOutSum
Definition variables.h:721
PetscInt _this
Definition variables.h:824
PetscReal MaxDiv
Definition variables.h:771
PetscInt MaxDivx
Definition variables.h:772
PetscInt MaxDivy
Definition variables.h:772
PetscInt MaxDivz
Definition variables.h:772
char log_dir[PETSC_MAX_PATH_LEN]
Definition variables.h:668
PetscInt MaxDivFlatArg
Definition variables.h:772
PetscReal FluxInSum
Definition variables.h:721
PetscInt step
Definition variables.h:651
PetscReal summationRHS
Definition variables.h:770
The master context for the entire simulation.
Definition variables.h:643
Here is the caller graph for this function:

◆ ParticleLocationStatusToString()

const char * ParticleLocationStatusToString ( ParticleLocationStatus  level)

Implementation of ParticleLocationStatusToString().

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 973 of file logging.c.

974{
975 switch (level) {
976 case NEEDS_LOCATION: return "NEEDS_LOCATION";
977 case ACTIVE_AND_LOCATED: return "ACTIVE_AND_LOCATED";
978 case MIGRATING_OUT: return "MIGRATING_OUT";
979 case LOST: return "LOST";
980 case UNINITIALIZED: return "UNINITIALIZED";
981 default: return "UNKNOWN_LEVEL";
982 }
983}
@ LOST
Definition variables.h:139
@ NEEDS_LOCATION
Definition variables.h:136
@ ACTIVE_AND_LOCATED
Definition variables.h:137
@ UNINITIALIZED
Definition variables.h:140
@ MIGRATING_OUT
Definition variables.h:138
Here is the caller graph for this function:

◆ _FindOrCreateEntry()

static PetscErrorCode _FindOrCreateEntry ( const char *  func_name,
PetscInt *  idx 
)
static

Internal helper implementation: _FindOrCreateEntry().

Local to this translation unit.

Definition at line 1008 of file logging.c.

1009{
1010 PetscFunctionBeginUser;
1011 // Search for existing entry
1012 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1013 if (strcmp(g_profiler_registry[i].name, func_name) == 0) {
1014 *idx = i;
1015 PetscFunctionReturn(0);
1016 }
1017 }
1018
1019 // Not found, create a new entry
1021 PetscInt new_capacity = g_profiler_capacity == 0 ? 16 : g_profiler_capacity * 2;
1022 PetscErrorCode ierr = PetscRealloc(sizeof(ProfiledFunction) * new_capacity, &g_profiler_registry); CHKERRQ(ierr);
1023 g_profiler_capacity = new_capacity;
1024 }
1025
1026 *idx = g_profiler_count;
1027 g_profiler_registry[*idx].name = func_name;
1028 g_profiler_registry[*idx].total_time = 0.0;
1032 g_profiler_registry[*idx].start_time = 0.0;
1033 g_profiler_registry[*idx].always_log = PETSC_FALSE;
1035
1036 PetscFunctionReturn(0);
1037}
PetscBool always_log
Definition logging.c:995
static PetscInt g_profiler_count
Definition logging.c:1000
long long total_call_count
Definition logging.c:992
static PetscInt g_profiler_capacity
Definition logging.c:1001
double total_time
Definition logging.c:990
double current_step_time
Definition logging.c:991
long long current_step_call_count
Definition logging.c:993
static ProfiledFunction * g_profiler_registry
Definition logging.c:999
double start_time
Definition logging.c:994
const char * name
Definition logging.c:989
Here is the caller graph for this function:

◆ ProfilingInitialize()

PetscErrorCode ProfilingInitialize ( SimCtx simCtx)

Internal helper implementation: ProfilingInitialize().

Initializes the custom profiling system using configuration from SimCtx.

Local to this translation unit.

Definition at line 1044 of file logging.c.

1045{
1046 PetscFunctionBeginUser;
1047 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "SimCtx cannot be null for ProfilingInitialize");
1048
1049 // Iterate through the list of critical functions provided in SimCtx
1050 for (PetscInt i = 0; i < simCtx->nProfilingSelectedFuncs; ++i) {
1051 PetscInt idx;
1052 const char *func_name = simCtx->profilingSelectedFuncs[i];
1053 PetscErrorCode ierr = _FindOrCreateEntry(func_name, &idx); CHKERRQ(ierr);
1054 g_profiler_registry[idx].always_log = PETSC_TRUE;
1055
1056 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Marked '%s' as a critical function for profiling.\n", func_name);
1057 }
1058 PetscFunctionReturn(0);
1059}
static PetscErrorCode _FindOrCreateEntry(const char *func_name, PetscInt *idx)
Internal helper implementation: _FindOrCreateEntry().
Definition logging.c:1008
char ** profilingSelectedFuncs
Definition variables.h:776
PetscInt nProfilingSelectedFuncs
Definition variables.h:777
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _ProfilingStart()

void _ProfilingStart ( const char *  func_name)

Implementation of _ProfilingStart().

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 1068 of file logging.c.

1069{
1070 PetscInt idx;
1071 if (_FindOrCreateEntry(func_name, &idx) != 0) return; // Fail silently
1072 PetscTime(&g_profiler_registry[idx].start_time);
1073}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ _ProfilingEnd()

void _ProfilingEnd ( const char *  func_name)

Implementation of _ProfilingEnd().

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 1082 of file logging.c.

1083{
1084 double end_time;
1085 PetscTime(&end_time);
1086
1087 PetscInt idx;
1088 if (_FindOrCreateEntry(func_name, &idx) != 0) return; // Fail silently
1089
1090 double elapsed = end_time - g_profiler_registry[idx].start_time;
1091 g_profiler_registry[idx].total_time += elapsed;
1092 g_profiler_registry[idx].current_step_time += elapsed;
1095}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ProfilingResetTimestepCounters()

PetscErrorCode ProfilingResetTimestepCounters ( void  )

Implementation of ProfilingResetTimestepCounters().

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 1104 of file logging.c.

1105{
1106 PetscFunctionBeginUser;
1107 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1110 }
1111 PetscFunctionReturn(0);
1112}
Here is the caller graph for this function:

◆ ProfilingLogTimestepSummary()

PetscErrorCode ProfilingLogTimestepSummary ( SimCtx simCtx,
PetscInt  step 
)

Implementation of ProfilingLogTimestepSummary().

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 1121 of file logging.c.

1122{
1123 PetscBool should_write = PETSC_FALSE;
1124 FILE *f = NULL;
1125 char filen[(2 * PETSC_MAX_PATH_LEN) + 16];
1126
1127 PetscFunctionBeginUser;
1128 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "SimCtx cannot be null for ProfilingLogTimestepSummary");
1129
1130 if (strcmp(simCtx->profilingTimestepMode, "off") == 0) {
1131 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1134 }
1135 PetscFunctionReturn(0);
1136 }
1137
1138 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1139 if (g_profiler_registry[i].current_step_call_count <= 0) {
1140 continue;
1141 }
1142 if (strcmp(simCtx->profilingTimestepMode, "all") == 0 || g_profiler_registry[i].always_log) {
1143 should_write = PETSC_TRUE;
1144 break;
1145 }
1146 }
1147
1148 if (should_write && simCtx->rank == 0) {
1149 snprintf(filen, sizeof(filen), "%s/%s", simCtx->log_dir, simCtx->profilingTimestepFile);
1150 if (step == simCtx->StartStep + 1 && !simCtx->continueMode) {
1151 f = fopen(filen, "w");
1152 if (!f) {
1153 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open profiling timestep log file: %s", filen);
1154 }
1155 PetscFPrintf(PETSC_COMM_SELF, f, "step,function,calls,step_time_s\n");
1156 } else {
1157 f = fopen(filen, "a");
1158 if (!f) {
1159 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open profiling timestep log file: %s", filen);
1160 }
1161 if (step == simCtx->StartStep + 1 && ftell(f) == 0) {
1162 PetscFPrintf(PETSC_COMM_SELF, f, "step,function,calls,step_time_s\n");
1163 }
1164 }
1165
1166 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1167 if (g_profiler_registry[i].current_step_call_count <= 0) {
1168 continue;
1169 }
1170 if (strcmp(simCtx->profilingTimestepMode, "all") == 0 || g_profiler_registry[i].always_log) {
1171 PetscFPrintf(
1172 PETSC_COMM_SELF,
1173 f,
1174 "%d,%s,%lld,%.6f\n",
1175 (int)step,
1176 g_profiler_registry[i].name,
1177 g_profiler_registry[i].current_step_call_count,
1178 g_profiler_registry[i].current_step_time
1179 );
1180 }
1181 }
1182 fclose(f);
1183 }
1184
1185 // Reset per-step counters for the next iteration
1186 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1189 }
1190 PetscFunctionReturn(0);
1191}
PetscBool continueMode
Definition variables.h:660
PetscMPIInt rank
Definition variables.h:646
char profilingTimestepFile[PETSC_MAX_PATH_LEN]
Definition variables.h:779
char profilingTimestepMode[32]
Definition variables.h:778
PetscInt StartStep
Definition variables.h:653
Here is the caller graph for this function:

◆ _CompareProfiledFunctions()

static int _CompareProfiledFunctions ( const void *  a,
const void *  b 
)
static

Internal helper implementation: _CompareProfiledFunctions().

Local to this translation unit.

Definition at line 1198 of file logging.c.

1199{
1200 const ProfiledFunction *func_a = (const ProfiledFunction *)a;
1201 const ProfiledFunction *func_b = (const ProfiledFunction *)b;
1202
1203 if (func_a->total_time < func_b->total_time) return 1;
1204 if (func_a->total_time > func_b->total_time) return -1;
1205 return 0;
1206}
Here is the caller graph for this function:

◆ ProfilingFinalize()

PetscErrorCode ProfilingFinalize ( SimCtx simCtx)

Implementation of ProfilingFinalize().

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 1214 of file logging.c.

1215{
1216 PetscErrorCode ierr;
1217 PetscInt rank = simCtx->rank;
1218 PetscFunctionBeginUser;
1219 if (!simCtx->profilingFinalSummary) PetscFunctionReturn(0);
1220 if (!rank) {
1221
1222 char exec_mode_modifier[32] = "Unknown";
1223 if(simCtx->exec_mode == EXEC_MODE_SOLVER) PetscCall(PetscStrncpy(exec_mode_modifier, "Solver", sizeof(exec_mode_modifier)));
1224 else if(simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR) PetscCall(PetscStrncpy(exec_mode_modifier, "PostProcessor", sizeof(exec_mode_modifier)));
1225 //--- Step 0: Create a file viewer for log file
1226 FILE *f;
1227 char filen[PETSC_MAX_PATH_LEN + 128];
1228 ierr = PetscSNPrintf(filen, sizeof(filen), "%s/ProfilingSummary_%s.log",simCtx->log_dir,exec_mode_modifier); CHKERRQ(ierr);
1229
1230 // Open the log file: append with section label in continue mode, truncate otherwise.
1231 if (simCtx->continueMode) {
1232 f = fopen(filen, "a");
1233 if (!f) {
1234 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open log file: %s", filen);
1235 }
1236 fprintf(f, "\n=== Continuation from step %" PetscInt_FMT " ===\n", simCtx->StartStep);
1237 } else {
1238 f = fopen(filen, "w");
1239 if (!f) {
1240 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open log file: %s", filen);
1241 }
1242 }
1243
1244 // --- Step 1: Sort the data for readability ---
1246
1247 // --- Step 2: Dynamically determine the width for the function name column ---
1248 PetscInt max_name_len = strlen("Function"); // Start with the header's length
1249 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1250 if (g_profiler_registry[i].total_call_count > 0) {
1251 PetscInt len = strlen(g_profiler_registry[i].name);
1252 if (len > max_name_len) {
1253 max_name_len = len;
1254 }
1255 }
1256 }
1257 // Add a little padding
1258 max_name_len += 2;
1259
1260 // --- Step 3: Define fixed widths for numeric columns for consistent alignment ---
1261 const int time_width = 18;
1262 const int count_width = 15;
1263 const int avg_width = 22;
1264
1265 // --- Step 4: Print the formatted table ---
1266 PetscFPrintf(PETSC_COMM_SELF, f, "=================================================================================================================\n");
1267 PetscFPrintf(PETSC_COMM_SELF, f, " FINAL PROFILING SUMMARY (Sorted by Total Time)\n");
1268 PetscFPrintf(PETSC_COMM_SELF, f, "=================================================================================================================\n");
1269
1270 // Header Row
1271 PetscFPrintf(PETSC_COMM_SELF, f, "%-*s | %-*s | %-*s | %-*s\n",
1272 max_name_len, "Function",
1273 time_width, "Total Time (s)",
1274 count_width, "Call Count",
1275 avg_width, "Avg. Time/Call (ms)");
1276
1277 // Separator Line (dynamically sized)
1278 for (int i = 0; i < max_name_len; i++) PetscFPrintf(PETSC_COMM_SELF, f, "-");
1279 PetscFPrintf(PETSC_COMM_SELF, f, "-|-");
1280 for (int i = 0; i < time_width; i++) PetscFPrintf(PETSC_COMM_SELF, f, "-");
1281 PetscFPrintf(PETSC_COMM_SELF, f, "-|-");
1282 for (int i = 0; i < count_width; i++) PetscFPrintf(PETSC_COMM_SELF, f, "-");
1283 PetscFPrintf(PETSC_COMM_SELF, f, "-|-");
1284 for (int i = 0; i < avg_width; i++) PetscFPrintf(PETSC_COMM_SELF, f, "-");
1285 PetscFPrintf(PETSC_COMM_SELF, f, "\n");
1286
1287 // Data Rows
1288 for (PetscInt i = 0; i < g_profiler_count; ++i) {
1289 if (g_profiler_registry[i].total_call_count > 0) {
1290 double avg_time_ms = (g_profiler_registry[i].total_time / g_profiler_registry[i].total_call_count) * 1000.0;
1291 PetscFPrintf(PETSC_COMM_SELF, f, "%-*s | %*.*f | %*lld | %*.*f\n",
1292 max_name_len, g_profiler_registry[i].name,
1293 time_width, 6, g_profiler_registry[i].total_time,
1294 count_width, g_profiler_registry[i].total_call_count,
1295 avg_width, 6, avg_time_ms);
1296 PetscFPrintf(PETSC_COMM_SELF, f, "------------------------------------------------------------------------------------------------------------------\n");
1297 }
1298 }
1299 PetscFPrintf(PETSC_COMM_SELF, f, "==================================================================================================================\n");
1300
1301 fclose(f);
1302 }
1303
1304 // --- Final Cleanup ---
1305 PetscFree(g_profiler_registry);
1306 g_profiler_registry = NULL;
1307 g_profiler_count = 0;
1309 PetscFunctionReturn(0);
1310}
static int _CompareProfiledFunctions(const void *a, const void *b)
Internal helper implementation: _CompareProfiledFunctions().
Definition logging.c:1198
PetscBool profilingFinalSummary
Definition variables.h:780
@ EXEC_MODE_SOLVER
Definition variables.h:616
@ EXEC_MODE_POSTPROCESSOR
Definition variables.h:617
ExecutionMode exec_mode
Definition variables.h:662
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PrintProgressBar()

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

Internal helper implementation: PrintProgressBar().

Prints a progress bar to the console.

Local to this translation unit.

Definition at line 1320 of file logging.c.

1321{
1322 if (totalSteps <= 0) return;
1323
1324 // --- Configuration ---
1325 const int barWidth = 50;
1326
1327 // --- Calculation ---
1328 // Calculate progress as a fraction from 0.0 to 1.0
1329 PetscReal progress = (PetscReal)(step - startStep + 1) / totalSteps;
1330 // Ensure progress doesn't exceed 1.0 due to floating point inaccuracies
1331 if (progress > 1.0) progress = 1.0;
1332
1333 int pos = (int)(barWidth * progress);
1334
1335 // --- Printing ---
1336 // Carriage return moves cursor to the beginning of the line
1337 PetscPrintf(PETSC_COMM_SELF, "\rProgress: [");
1338
1339 for (int i = 0; i < barWidth; ++i) {
1340 if (i < pos) {
1341 PetscPrintf(PETSC_COMM_SELF, "=");
1342 } else if (i == pos) {
1343 PetscPrintf(PETSC_COMM_SELF, ">");
1344 } else {
1345 PetscPrintf(PETSC_COMM_SELF, " ");
1346 }
1347 }
1348
1349 // Print percentage, step count, and current time
1350 PetscPrintf(PETSC_COMM_SELF, "] %3d%% (Step %" PetscInt_FMT "/%" PetscInt_FMT ", t=%.4f)",
1351 (int)(progress * 100.0),
1352 step + 1,
1353 startStep + totalSteps,
1354 currentTime);
1355
1356 // Flush the output buffer to ensure the bar is displayed immediately
1357 fflush(stdout);
1358}
Here is the caller graph for this function:

◆ LOG_FIELD_MIN_MAX()

PetscErrorCode LOG_FIELD_MIN_MAX ( UserCtx user,
const char *  fieldName 
)

Implementation of LOG_FIELD_MIN_MAX().

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 1367 of file logging.c.

1368{
1369 PetscErrorCode ierr;
1370 PetscInt i, j, k;
1371 DMDALocalInfo info;
1372
1373 Vec fieldVec = NULL;
1374 DM dm = NULL;
1375 PetscInt dof;
1376 char data_layout[20];
1377
1378 PetscFunctionBeginUser;
1379
1380 // --- 1. Map string name to PETSc objects and determine data layout ---
1381 if (strcasecmp(fieldName, "Ucat") == 0) {
1382 fieldVec = user->Ucat; dm = user->fda; dof = 3; strcpy(data_layout, "Cell-Centered");
1383 } else if (strcasecmp(fieldName, "P") == 0) {
1384 fieldVec = user->P; dm = user->da; dof = 1; strcpy(data_layout, "Cell-Centered");
1385 } else if (strcasecmp(fieldName, "Diffusivity") == 0) {
1386 fieldVec = user->Diffusivity; dm = user->da; dof = 1; strcpy(data_layout, "Cell-Centered");
1387 } else if (strcasecmp(fieldName, "DiffusivityGradient") == 0) {
1388 fieldVec = user->DiffusivityGradient; dm = user->fda; dof = 3; strcpy(data_layout, "Cell-Centered");
1389 } else if (strcasecmp(fieldName, "Ucont") == 0) {
1390 fieldVec = user->lUcont; dm = user->fda; dof = 3; strcpy(data_layout, "Face-Centered");
1391 } else if (strcasecmp(fieldName, "Coordinates") == 0) {
1392 ierr = DMGetCoordinates(user->da, &fieldVec); CHKERRQ(ierr);
1393 dm = user->fda; dof = 3; strcpy(data_layout, "Node-Centered");
1394 } else if (strcasecmp(fieldName,"Psi") == 0) {
1395 fieldVec = user->Psi; dm = user->da; dof = 1; strcpy(data_layout, "Cell-Centered"); // Assuming Psi is cell-centered
1396 } else {
1397 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Field %s not recognized.", fieldName);
1398 }
1399
1400 if (!fieldVec) {
1401 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Vector for field '%s' is NULL.", fieldName);
1402 }
1403 if (!dm) {
1404 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM for field '%s' is NULL.", fieldName);
1405 }
1406
1407 ierr = DMDAGetLocalInfo(dm, &info); CHKERRQ(ierr);
1408
1409 // --- 2. Define Architecture-Aware Loop Bounds ---
1410 PetscInt i_start, i_end, j_start, j_end, k_start, k_end;
1411
1412 if (strcmp(data_layout, "Cell-Centered") == 0) {
1413 // For cell-centered data, the physical values are stored from index 1 to N-1.
1414 // We find the intersection of the rank's owned range [xs, xe) with the
1415 // physical data range [1, IM-1).
1416 i_start = PetscMax(info.xs, 1); i_end = PetscMin(info.xs + info.xm, user->IM);
1417 j_start = PetscMax(info.ys, 1); j_end = PetscMin(info.ys + info.ym, user->JM);
1418 k_start = PetscMax(info.zs, 1); k_end = PetscMin(info.zs + info.zm, user->KM);
1419 } else { // For Node- or Face-Centered data
1420 // The physical values are stored from index 0 to N-1.
1421 // We find the intersection of the rank's owned range [xs, xe) with the
1422 // physical data range [0, IM-1].
1423 i_start = PetscMax(info.xs, 0); i_end = PetscMin(info.xs + info.xm, user->IM);
1424 j_start = PetscMax(info.ys, 0); j_end = PetscMin(info.ys + info.ym, user->JM);
1425 k_start = PetscMax(info.zs, 0); k_end = PetscMin(info.zs + info.zm, user->KM);
1426 }
1427
1428 // --- 3. Barrier for clean, grouped output ---
1429 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRQ(ierr);
1430 if (user->simCtx->rank == 0) {
1431 PetscPrintf(PETSC_COMM_SELF, "\n--- Field Ranges: [%s] (Layout: %s) ---\n", fieldName, data_layout);
1432 }
1433
1434 // --- 4. Branch on DoF and perform calculation with correct bounds ---
1435 if (dof == 1) {
1436 PetscReal localMin = PETSC_MAX_REAL, localMax = PETSC_MIN_REAL;
1437 PetscReal globalMin, globalMax;
1438 const PetscScalar ***array;
1439
1440 ierr = DMDAVecGetArrayRead(dm, fieldVec, &array); CHKERRQ(ierr);
1441 for (k = k_start; k < k_end; k++) {
1442 for (j = j_start; j < j_end; j++) {
1443 for (i = i_start; i < i_end; i++) {
1444 localMin = PetscMin(localMin, array[k][j][i]);
1445 localMax = PetscMax(localMax, array[k][j][i]);
1446 }
1447 }
1448 }
1449 ierr = DMDAVecRestoreArrayRead(dm, fieldVec, &array); CHKERRQ(ierr);
1450
1451 ierr = MPI_Allreduce(&localMin, &globalMin, 1, MPIU_REAL, MPI_MIN, PETSC_COMM_WORLD); CHKERRQ(ierr);
1452 ierr = MPI_Allreduce(&localMax, &globalMax, 1, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD); CHKERRQ(ierr);
1453
1454 PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [Rank %d] Local Range: [ %11.4e , %11.4e ]\n", user->simCtx->rank, localMin, localMax);
1455 ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT); CHKERRQ(ierr);
1456 if (user->simCtx->rank == 0) {
1457 PetscPrintf(PETSC_COMM_SELF, " Global Range: [ %11.4e , %11.4e ]\n", globalMin, globalMax);
1458 }
1459
1460 } else if (dof == 3) {
1461 Cmpnts localMin = {PETSC_MAX_REAL, PETSC_MAX_REAL, PETSC_MAX_REAL};
1462 Cmpnts localMax = {PETSC_MIN_REAL, PETSC_MIN_REAL, PETSC_MIN_REAL};
1463 Cmpnts globalMin, globalMax;
1464 const Cmpnts ***array;
1465
1466 ierr = DMDAVecGetArrayRead(dm, fieldVec, &array); CHKERRQ(ierr);
1467 for (k = k_start; k < k_end; k++) {
1468 for (j = j_start; j < j_end; j++) {
1469 for (i = i_start; i < i_end; i++) {
1470 localMin.x = PetscMin(localMin.x, array[k][j][i].x);
1471 localMin.y = PetscMin(localMin.y, array[k][j][i].y);
1472 localMin.z = PetscMin(localMin.z, array[k][j][i].z);
1473 localMax.x = PetscMax(localMax.x, array[k][j][i].x);
1474 localMax.y = PetscMax(localMax.y, array[k][j][i].y);
1475 localMax.z = PetscMax(localMax.z, array[k][j][i].z);
1476 }
1477 }
1478 }
1479 ierr = DMDAVecRestoreArrayRead(dm, fieldVec, &array); CHKERRQ(ierr);
1480
1481 ierr = MPI_Allreduce(&localMin, &globalMin, 3, MPIU_REAL, MPI_MIN, PETSC_COMM_WORLD); CHKERRQ(ierr);
1482 ierr = MPI_Allreduce(&localMax, &globalMax, 3, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD); CHKERRQ(ierr);
1483
1484 ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [Rank %d] Local X-Range: [ %11.4e , %11.4e ]\n", user->simCtx->rank, localMin.x, localMax.x);
1485 ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [Rank %d] Local Y-Range: [ %11.4e , %11.4e ]\n", user->simCtx->rank, localMin.y, localMax.y);
1486 ierr = PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [Rank %d] Local Z-Range: [ %11.4e , %11.4e ]\n", user->simCtx->rank, localMin.z, localMax.z);
1487 ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT); CHKERRQ(ierr);
1488
1489 if (user->simCtx->rank == 0) {
1490 PetscPrintf(PETSC_COMM_SELF, " [Global] X-Range: [ %11.4e , %11.4e ]\n", globalMin.x, globalMax.x);
1491 PetscPrintf(PETSC_COMM_SELF, " [Global] Y-Range: [ %11.4e , %11.4e ]\n", globalMin.y, globalMax.y);
1492 PetscPrintf(PETSC_COMM_SELF, " [Global] Z-Range: [ %11.4e , %11.4e ]\n", globalMin.z, globalMax.z);
1493 }
1494
1495 } else {
1496 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);
1497 }
1498
1499 // --- 5. Final barrier for clean output ordering ---
1500 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRQ(ierr);
1501 if (user->simCtx->rank == 0) {
1502 PetscPrintf(PETSC_COMM_SELF, "--------------------------------------------\n\n");
1503 }
1504
1505 PetscFunctionReturn(0);
1506}
PetscInt KM
Definition variables.h:820
Vec DiffusivityGradient
Definition variables.h:841
Vec Ucat
Definition variables.h:837
PetscInt JM
Definition variables.h:820
Vec lUcont
Definition variables.h:837
Vec Diffusivity
Definition variables.h:840
PetscInt IM
Definition variables.h:820
Vec Psi
Definition variables.h:883
A 3D point or vector with PetscScalar components.
Definition variables.h:100
Here is the caller graph for this function:

◆ LOG_FIELD_ANATOMY()

PetscErrorCode LOG_FIELD_ANATOMY ( UserCtx user,
const char *  field_name,
const char *  stage_name 
)

Implementation of LOG_FIELD_ANATOMY().

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

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

See also
LOG_FIELD_ANATOMY()

Definition at line 1515 of file logging.c.

1516{
1517 PetscErrorCode ierr;
1518 DMDALocalInfo info;
1519 PetscMPIInt rank;
1520
1521 Vec vec_local = NULL;
1522 DM dm = NULL;
1523 PetscInt dof = 0;
1524 char data_layout[20];
1525 char dominant_dir = '\0'; // 'x', 'y', 'z' for face-centered, 'm' for mixed (Ucont)
1526
1527 PetscFunctionBeginUser;
1528 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1529
1530 // --- 1. Map string name to PETSc objects and determine data layout ---
1531 if (strcasecmp(field_name, "Ucat") == 0) {
1532 vec_local = user->lUcat; dm = user->fda; dof = 3; strcpy(data_layout, "Cell-Centered");
1533 } else if (strcasecmp(field_name, "P") == 0) {
1534 vec_local = user->lP; dm = user->da; dof = 1; strcpy(data_layout, "Cell-Centered");
1535 } else if (strcasecmp(field_name, "Diffusivity") == 0) {
1536 vec_local = user->lDiffusivity; dm = user->da; dof = 1; strcpy(data_layout, "Cell-Centered");
1537 } else if (strcasecmp(field_name, "DiffusivityGradient") == 0) {
1538 vec_local = user->lDiffusivityGradient; dm = user->fda; dof = 3; strcpy(data_layout, "Cell-Centered");
1539 } else if (strcasecmp(field_name, "Psi") == 0) {
1540 vec_local = user->lPsi; dm = user->da; dof = 1; strcpy(data_layout, "Cell-Centered");
1541 } else if (strcasecmp(field_name, "Center-Coordinates") == 0) {
1542 vec_local = user->lCent; dm = user->fda; dof = 3; strcpy(data_layout, "Cell-Centered");
1543 } else if (strcasecmp(field_name, "Ucont") == 0) {
1544 vec_local = user->lUcont; dm = user->fda; dof = 3; strcpy(data_layout, "Face-Centered"); dominant_dir = 'm'; // Mixed
1545 } else if (strcasecmp(field_name, "Csi") == 0 || strcasecmp(field_name, "X-Face-Centers") == 0) {
1546 vec_local = (strcasecmp(field_name, "Csi") == 0) ? user->lCsi : user->Centx;
1547 dm = user->fda; dof = 3; strcpy(data_layout, "Face-Centered"); dominant_dir = 'x';
1548 } else if (strcasecmp(field_name, "Eta") == 0 || strcasecmp(field_name, "Y-Face-Centers") == 0) {
1549 vec_local = (strcasecmp(field_name, "Eta") == 0) ? user->lEta : user->Centy;
1550 dm = user->fda; dof = 3; strcpy(data_layout, "Face-Centered"); dominant_dir = 'y';
1551 } else if (strcasecmp(field_name, "Zet") == 0 || strcasecmp(field_name, "Z-Face-Centers") == 0) {
1552 vec_local = (strcasecmp(field_name, "Zet") == 0) ? user->lZet : user->Centz;
1553 dm = user->fda; dof = 3; strcpy(data_layout, "Face-Centered"); dominant_dir = 'z';
1554 } else if (strcasecmp(field_name, "Coordinates") == 0) {
1555 ierr = DMGetCoordinatesLocal(user->da, &vec_local); CHKERRQ(ierr);
1556 dm = user->fda; dof = 3; strcpy(data_layout, "Node-Centered");
1557 } else if (strcasecmp(field_name, "CornerField")== 0){
1558 vec_local = user->lCellFieldAtCorner; strcpy(data_layout, "Node-Centered");
1559 PetscInt bs = 1;
1560 ierr = VecGetBlockSize(user->CellFieldAtCorner, &bs); CHKERRQ(ierr);
1561 dof = bs;
1562 if(dof == 1) dm = user->da;
1563 else dm = user->fda;
1564 } else {
1565 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Unknown field name for LOG_FIELD_ANATOMY: %s", field_name);
1566 }
1567
1568 // --- 2. Get Grid Info and Array Pointers ---
1569 ierr = DMDAGetLocalInfo(dm, &info); CHKERRQ(ierr);
1570
1571 ierr = PetscBarrier(NULL);
1572 PetscPrintf(PETSC_COMM_WORLD, "\n--- Field Anatomy Log: [%s] | Stage: [%s] | Layout: [%s] ---\n", field_name, stage_name, data_layout);
1573
1574 // Global physical dimensions (number of cells)
1575 PetscInt im_phys = user->IM;
1576 PetscInt jm_phys = user->JM;
1577 PetscInt km_phys = user->KM;
1578
1579 // Slice through the center of the local domain
1580 PetscInt i_mid = (PetscInt)(info.xs + 0.5 * info.xm) - 1;
1581 PetscInt j_mid = (PetscInt)(info.ys + 0.5 * info.ym) - 1;
1582 PetscInt k_mid = (PetscInt)(info.zs + 0.5 * info.zm) - 1;
1583
1584 // --- 3. Print Boundary Information based on Data Layout ---
1585
1586 // ======================================================================
1587 // === CASE 1: Cell-Centered Fields (Ucat, P) - USES SHIFTED INDEX ===
1588 // ======================================================================
1589 if (strcmp(data_layout, "Cell-Centered") == 0) {
1590 const void *l_arr;
1591 ierr = DMDAVecGetArrayRead(dm, vec_local, (void*)&l_arr); CHKERRQ(ierr);
1592
1593
1594 // --- I-Direction Boundaries ---
1595 if (info.xs == 0) { // Rank on -Xi boundary
1596 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (Ghost for Cell[k][j][0]) = ", rank, 0);
1597 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f)\n", ((const PetscReal***)l_arr)[k_mid][j_mid][0]);
1598 else PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f, %.5f, %.5f)\n", ((const Cmpnts***)l_arr)[k_mid][j_mid][0].x, ((const Cmpnts***)l_arr)[k_mid][j_mid][0].y, ((const Cmpnts***)l_arr)[k_mid][j_mid][0].z);
1599
1600 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (Value for Cell[k][j][0]) = ", rank, 1);
1601 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f)\n", ((const PetscReal***)l_arr)[k_mid][j_mid][1]);
1602 else PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f, %.5f, %.5f)\n", ((const Cmpnts***)l_arr)[k_mid][j_mid][1].x, ((const Cmpnts***)l_arr)[k_mid][j_mid][1].y, ((const Cmpnts***)l_arr)[k_mid][j_mid][1].z);
1603 }
1604 if (info.xs + info.xm == info.mx) { // Rank on +Xi boundary
1605 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (Value for Cell[k][j][%d]) = ", rank, im_phys - 1, im_phys - 2);
1606 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f)\n", ((const PetscReal***)l_arr)[k_mid][j_mid][im_phys - 1]);
1607 else PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f, %.5f, %.5f)\n", ((const Cmpnts***)l_arr)[k_mid][j_mid][im_phys - 1].x, ((const Cmpnts***)l_arr)[k_mid][j_mid][im_phys - 1].y, ((const Cmpnts***)l_arr)[k_mid][j_mid][im_phys - 1].z);
1608
1609 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (Ghost for Cell[k][j][%d]) = ", rank, im_phys, im_phys - 2);
1610 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f)\n", ((const PetscReal***)l_arr)[k_mid][j_mid][im_phys]);
1611 else PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f, %.5f, %.5f)\n", ((const Cmpnts***)l_arr)[k_mid][j_mid][im_phys].x, ((const Cmpnts***)l_arr)[k_mid][j_mid][im_phys].y, ((const Cmpnts***)l_arr)[k_mid][j_mid][im_phys].z);
1612 }
1613
1614 // --- J-Direction Boundaries ---
1615 if (info.ys == 0) { // Rank on -Eta boundary
1616 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (Ghost for Cell[k][0][i]) = ", rank, 0);
1617 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f)\n", ((const PetscReal***)l_arr)[k_mid][0][i_mid]);
1618 else PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f, %.5f, %.5f)\n", ((const Cmpnts***)l_arr)[k_mid][0][i_mid].x, ((const Cmpnts***)l_arr)[k_mid][0][i_mid].y, ((const Cmpnts***)l_arr)[k_mid][0][i_mid].z);
1619
1620 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (Value for Cell[k][0][i]) = ", rank, 1);
1621 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f)\n", ((const PetscReal***)l_arr)[k_mid][1][i_mid]);
1622 else PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f, %.5f, %.5f)\n", ((const Cmpnts***)l_arr)[k_mid][1][i_mid].x, ((const Cmpnts***)l_arr)[k_mid][1][i_mid].y, ((const Cmpnts***)l_arr)[k_mid][1][i_mid].z);
1623 }
1624
1625 if (info.ys + info.ym == info.my) { // Rank on +Eta boundary
1626 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (Value for Cell[k][%d][i]) = ", rank, jm_phys - 1, jm_phys - 2);
1627 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f)\n", ((const PetscReal***)l_arr)[k_mid][jm_phys - 1][i_mid]);
1628 else PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f, %.5f, %.5f)\n", ((const Cmpnts***)l_arr)[k_mid][jm_phys - 1][i_mid].x, ((const Cmpnts***)l_arr)[k_mid][jm_phys - 1][i_mid].y, ((const Cmpnts***)l_arr)[k_mid][jm_phys - 1][i_mid].z);
1629
1630 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (Ghost for Cell[k][%d][i]) = ", rank, jm_phys, jm_phys - 2);
1631 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f)\n", ((const PetscReal***)l_arr)[k_mid][jm_phys][i_mid]);
1632 else PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f, %.5f, %.5f)\n", ((const Cmpnts***)l_arr)[k_mid][jm_phys][i_mid].x, ((const Cmpnts***)l_arr)[k_mid][jm_phys][i_mid].y, ((const Cmpnts***)l_arr)[k_mid][jm_phys][i_mid].z);
1633 }
1634
1635 // --- K-Direction Boundaries ---
1636 if (info.zs == 0) { // Rank on -Zeta boundary
1637 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Kdx %2d (Ghost for Cell[0][j][i]) = ", rank, 0);
1638 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f)\n", ((const PetscReal***)l_arr)[0][j_mid][i_mid]);
1639 else PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f, %.5f, %.5f)\n", ((const Cmpnts***)l_arr)[0][j_mid][i_mid].x, ((const Cmpnts***)l_arr)[0][j_mid][i_mid].y, ((const Cmpnts***)l_arr)[0][j_mid][i_mid].z);
1640 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Kdx %2d (Value for Cell[0][j][i]) = ", rank, 1);
1641 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f)\n", ((const PetscReal***)l_arr)[1][j_mid][i_mid]);
1642 else PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f, %.5f, %.5f)\n", ((const Cmpnts***)l_arr)[1][j_mid][i_mid].x, ((const Cmpnts***)l_arr)[1][j_mid][i_mid].y, ((const Cmpnts***)l_arr)[1][j_mid][i_mid].z);
1643 }
1644 if (info.zs + info.zm == info.mz) { // Rank on +Zeta boundary
1645 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Kdx %2d (Value for Cell[%d][j][i]) = ", rank, km_phys - 1, km_phys - 2);
1646 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f)\n", ((const PetscReal***)l_arr)[km_phys - 1][j_mid][i_mid]);
1647 else PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f, %.5f, %.5f)\n", ((const Cmpnts***)l_arr)[km_phys - 1][j_mid][i_mid].x, ((const Cmpnts***)l_arr)[km_phys - 1][j_mid][i_mid].y, ((const Cmpnts***)l_arr)[km_phys - 1][j_mid][i_mid].z);
1648 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Kdx %2d (Ghost for Cell[%d][j][i]) = ", rank, km_phys, km_phys - 2);
1649 if(dof==1) PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f)\n", ((const PetscReal***)l_arr)[km_phys][j_mid][i_mid]);
1650 else PetscSynchronizedPrintf(PETSC_COMM_WORLD, "(%.5f, %.5f, %.5f)\n", ((const Cmpnts***)l_arr)[km_phys][j_mid][i_mid].x, ((const Cmpnts***)l_arr)[km_phys][j_mid][i_mid].y, ((const Cmpnts***)l_arr)[km_phys][j_mid][i_mid].z);
1651 }
1652 ierr = DMDAVecRestoreArrayRead(dm, vec_local, (void*)&l_arr); CHKERRQ(ierr);
1653 }
1654 // ======================================================================
1655 // === CASE 2: Face-Centered Fields - NUANCED DIRECTIONAL LOGIC ===
1656 // ======================================================================
1657 else if (strcmp(data_layout, "Face-Centered") == 0) {
1658 const Cmpnts ***l_arr;
1659 ierr = DMDAVecGetArrayRead(dm, vec_local, (void*)&l_arr); CHKERRQ(ierr);
1660
1661 // --- I-Direction Boundaries ---
1662 if (info.xs == 0) { // Rank on -Xi boundary
1663 if (dominant_dir == 'x') { // Node-like in I-dir
1664 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (First Phys. X-Face) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[k_mid][j_mid][0].x, l_arr[k_mid][j_mid][0].y, l_arr[k_mid][j_mid][0].z);
1665 } else if (dominant_dir == 'y' || dominant_dir == 'z') { // Cell-like in I-dir
1666 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (Ghost for Cell[k][j][0]) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[k_mid][j_mid][0].x, l_arr[k_mid][j_mid][0].y, l_arr[k_mid][j_mid][0].z);
1667 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (Value for Cell[k][j][0]) = (%.5f, %.5f, %.5f)\n", rank, 1, l_arr[k_mid][j_mid][1].x, l_arr[k_mid][j_mid][1].y, l_arr[k_mid][j_mid][1].z);
1668 } else if (dominant_dir == 'm') { // Ucont: Mixed
1669 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: u-comp @ Idx %2d (1st X-Face) = %.5f\n", rank, 0, l_arr[k_mid][j_mid][0].x);
1670 }
1671 }
1672 if (info.xs + info.xm == info.mx) { // Rank on +Xi boundary
1673 if (dominant_dir == 'x') { // Node-like in I-dir
1674 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (Last Phys. X-Face) = (%.5f, %.5f, %.5f)\n", rank, im_phys - 1, l_arr[k_mid][j_mid][im_phys - 1].x, l_arr[k_mid][j_mid][im_phys-1].y, l_arr[k_mid][j_mid][im_phys - 1].z);
1675 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (Ghost Location) = (%.5f, %.5f, %.5f)\n", rank, im_phys, l_arr[k_mid][j_mid][im_phys].x, l_arr[k_mid][j_mid][im_phys].y, l_arr[k_mid][j_mid][im_phys].z);
1676 } else if (dominant_dir == 'y' || dominant_dir == 'z') { // Cell-like in I-dir
1677 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (Value for Cell[k][j][%d]) = (%.5f, %.5f, %.5f)\n", rank, im_phys - 1, im_phys - 2, l_arr[k_mid][j_mid][im_phys - 1].x, l_arr[k_mid][j_mid][im_phys - 1].y, l_arr[k_mid][j_mid][im_phys-1].z);
1678 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (Ghost for Cell[k][j][%d]) = (%.5f, %.5f, %.5f)\n", rank, im_phys, im_phys - 2, l_arr[k_mid][j_mid][im_phys].x, l_arr[k_mid][j_mid][im_phys].y, l_arr[k_mid][j_mid][im_phys].z);
1679 } else if (dominant_dir == 'm') { // Ucont: Mixed
1680 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: u-comp @ Idx %2d (Last X-Face) = %.5f\n", rank, im_phys - 1, l_arr[k_mid][j_mid][im_phys - 1].x);
1681 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: u-comp @ Idx %2d (Ghost Location) = %.5f\n", rank, im_phys, l_arr[k_mid][j_mid][im_phys].x);
1682 }
1683 }
1684
1685 // --- J-Direction Boundaries ---
1686 if (info.ys == 0) { // Rank on -Eta boundary
1687 if (dominant_dir == 'y') { // Node-like in J-dir
1688 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (First Phys. Y-Face) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[k_mid][0][i_mid].x, l_arr[k_mid][0][i_mid].y, l_arr[k_mid][0][i_mid].z);
1689 } else if (dominant_dir == 'x' || dominant_dir == 'z') { // Cell-like in J-dir
1690 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (Ghost for Cell[k][0][i]) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[k_mid][0][i_mid].x, l_arr[k_mid][0][i_mid].y, l_arr[k_mid][0][i_mid].z);
1691 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (Value for Cell[k][0][i]) = (%.5f, %.5f, %.5f)\n", rank, 1, l_arr[k_mid][1][i_mid].x, l_arr[k_mid][1][i_mid].y, l_arr[k_mid][1][i_mid].z);
1692 } else if (dominant_dir == 'm') { // Ucont: Mixed
1693 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: v-comp @ Jdx %2d (1st Y-Face) = %.5f\n", rank, 0, l_arr[k_mid][0][i_mid].y);
1694 }
1695 }
1696 if (info.ys + info.ym == info.my) { // Rank on +Eta boundary
1697 if (dominant_dir == 'y') { // Node-like in J-dir
1698 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (Last Phys. Y-Face) = (%.5f, %.5f, %.5f)\n", rank, jm_phys - 1, l_arr[k_mid][jm_phys - 1][i_mid].x, l_arr[k_mid][jm_phys - 1][i_mid].y, l_arr[k_mid][jm_phys - 1][i_mid].z);
1699 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (Ghost Location) = (%.5f, %.5f, %.5f)\n", rank, jm_phys, l_arr[k_mid][jm_phys][i_mid].x, l_arr[k_mid][jm_phys][i_mid].y, l_arr[k_mid][jm_phys][i_mid].z);
1700 } else if (dominant_dir == 'x' || dominant_dir == 'z') { // Cell-like in J-dir
1701 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (Value for Cell[k][%d][i]) = (%.5f, %.5f, %.5f)\n", rank, jm_phys-1, jm_phys-2, l_arr[k_mid][jm_phys - 1][i_mid].x, l_arr[k_mid][jm_phys - 1][i_mid].y, l_arr[k_mid][jm_phys - 1][i_mid].z);
1702 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (Ghost for Cell[k][%d][i]) = (%.5f, %.5f, %.5f)\n", rank, jm_phys, jm_phys-2, l_arr[k_mid][jm_phys][i_mid].x, l_arr[k_mid][jm_phys][i_mid].y, l_arr[k_mid][jm_phys][i_mid].z);
1703 } else if (dominant_dir == 'm') { // Ucont: Mixed
1704 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: v-comp @ Jdx %2d (Last Y-Face) = %.5f\n", rank, jm_phys - 1, l_arr[k_mid][jm_phys - 1][i_mid].y);
1705 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: v-comp @ Jdx %2d (Ghost Location) = %.5f\n", rank, jm_phys, l_arr[k_mid][jm_phys][i_mid].y);
1706 }
1707 }
1708
1709 // --- K-Direction Boundaries ---
1710 if (info.zs == 0) { // Rank on -Zeta boundary
1711 if (dominant_dir == 'z') { // Node-like in K-dir
1712 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Kdx %2d (First Phys. Z-Face) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[0][j_mid][i_mid].x, l_arr[0][j_mid][i_mid].y, l_arr[0][j_mid][i_mid].z);
1713 } else if (dominant_dir == 'x' || dominant_dir == 'y') { // Cell-like in K-dir
1714 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Kdx %2d (Ghost for Cell[0][j][i]) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[0][j_mid][i_mid].x, l_arr[0][j_mid][i_mid].y, l_arr[0][j_mid][i_mid].z);
1715 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Kdx %2d (Value for Cell[0][j][i]) = (%.5f, %.5f, %.5f)\n", rank, 1, l_arr[1][j_mid][i_mid].x, l_arr[1][j_mid][i_mid].y, l_arr[1][j_mid][i_mid].z);
1716 } else if (dominant_dir == 'm') { // Ucont: Mixed
1717 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: w-comp @ Idx %2d (1st Z-Face) = %.5f\n", rank, 0, l_arr[0][j_mid][i_mid].z);
1718 }
1719 }
1720 if (info.zs + info.zm == info.mz) { // Rank on +Zeta boundary
1721 if (dominant_dir == 'z') { // Node-like in K-dir
1722 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Idx %2d (Last Phys. Z-Face) = (%.5f, %.5f, %.5f)\n", rank, km_phys - 1, l_arr[km_phys - 1][j_mid][i_mid].x, l_arr[km_phys - 1][j_mid][i_mid].y, l_arr[km_phys - 1][j_mid][i_mid].z);
1723 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Idx %2d (Ghost Location) = (%.5f, %.5f, %.5f)\n", rank, km_phys, l_arr[km_phys][j_mid][i_mid].x, l_arr[km_phys][j_mid][i_mid].y, l_arr[km_phys][j_mid][i_mid].z);
1724 } else if (dominant_dir == 'x' || dominant_dir == 'y') { // Cell-like in K-dir
1725 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Idx %2d (Value for Cell[%d][j][i]) = (%.5f, %.5f, %.5f)\n", rank, km_phys-1, km_phys-2, l_arr[km_phys-1][j_mid][i_mid].x, l_arr[km_phys-1][j_mid][i_mid].y, l_arr[km_phys - 1][j_mid][i_mid].z);
1726 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Idx %2d (Ghost for Cell[%d][j][i]) = (%.5f, %.5f, %.5f)\n", rank, km_phys, km_phys-2, l_arr[km_phys][j_mid][i_mid].x, l_arr[km_phys][j_mid][i_mid].y, l_arr[km_phys][j_mid][i_mid].z);
1727 } else if (dominant_dir == 'm') { // Ucont: Mixed
1728 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: w-comp @ Idx %2d (Last Z-Face) = %.5f\n", rank, km_phys - 1, l_arr[km_phys - 1][j_mid][i_mid].z);
1729 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: w-comp @ Idx %2d (Ghost Loc.) = %.5f\n", rank, km_phys, l_arr[km_phys][j_mid][i_mid].z);
1730
1731 }
1732 }
1733 ierr = DMDAVecRestoreArrayRead(dm, vec_local, (void*)&l_arr); CHKERRQ(ierr);
1734 }
1735 // ======================================================================
1736 // === CASE 3: Node-Centered Fields - USES DIRECT INDEX ===
1737 // ======================================================================
1738 else if (strcmp(data_layout, "Node-Centered") == 0) {
1739 const Cmpnts ***l_arr;
1740 ierr = DMDAVecGetArrayRead(dm, vec_local, (void*)&l_arr); CHKERRQ(ierr);
1741
1742 // --- I-Direction Boundaries ---
1743 if (info.xs == 0) {
1744 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (First Phys. Node) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[k_mid][j_mid][0].x, l_arr[k_mid][j_mid][0].y, l_arr[k_mid][j_mid][0].z);
1745 }
1746 if (info.xs + info.xm == info.mx) {
1747 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (Last Phys. Node) = (%.5f, %.5f, %.5f)\n", rank, im_phys - 1, l_arr[k_mid][j_mid][im_phys - 1].x, l_arr[k_mid][j_mid][im_phys - 1].y, l_arr[k_mid][j_mid][im_phys - 1].z);
1748 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, I-DIR]: Idx %2d (Unused/Ghost Loc) = (%.5f, %.5f, %.5f)\n", rank, im_phys, l_arr[k_mid][j_mid][im_phys].x, l_arr[k_mid][j_mid][im_phys].y, l_arr[k_mid][j_mid][im_phys].z);
1749 }
1750 // --- J-Direction Boundaries ---
1751 if (info.ys == 0) {
1752 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (First Phys. Node) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[k_mid][0][i_mid].x, l_arr[k_mid][0][i_mid].y, l_arr[k_mid][0][i_mid].z);
1753 }
1754 if (info.ys + info.ym == info.my) {
1755 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (Last Phys. Node) = (%.5f, %.5f, %.5f)\n", rank, jm_phys - 1, l_arr[k_mid][jm_phys - 1][i_mid].x, l_arr[k_mid][jm_phys - 1][i_mid].y, l_arr[k_mid][jm_phys - 1][i_mid].z);
1756 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, J-DIR]: Jdx %2d (Unused/Ghost Loc) = (%.5f, %.5f, %.5f)\n", rank, jm_phys, l_arr[k_mid][jm_phys][i_mid].x, l_arr[k_mid][jm_phys][i_mid].y, l_arr[k_mid][jm_phys][i_mid].z);
1757 }
1758 // --- K-Direction Boundaries ---
1759 if (info.zs == 0) {
1760 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Kdx %2d (First Phys. Node) = (%.5f, %.5f, %.5f)\n", rank, 0, l_arr[0][j_mid][i_mid].x, l_arr[0][j_mid][i_mid].y, l_arr[0][j_mid][i_mid].z);
1761 }
1762 if(info.zs + info.zm == info.mz) {
1763 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Kdx %2d (Last Phys. Node) = (%.5f, %.5f, %.5f)\n", rank, km_phys - 1, l_arr[km_phys - 1][j_mid][i_mid].x, l_arr[km_phys - 1][j_mid][i_mid].y, l_arr[km_phys - 1][j_mid][i_mid].z);
1764 PetscSynchronizedPrintf(PETSC_COMM_WORLD, "[Rank %d, K-DIR]: Kdx %2d (Unused/Ghost Loc) = (%.5f, %.5f, %.5f)\n", rank, km_phys, l_arr[km_phys][j_mid][i_mid].x, l_arr[km_phys][j_mid][i_mid].y, l_arr[km_phys][j_mid][i_mid].z);
1765 }
1766 ierr = DMDAVecRestoreArrayRead(dm, vec_local, (void*)&l_arr); CHKERRQ(ierr);
1767 }
1768 else {
1769 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "LOG_FIELD_ANATOMY encountered an unknown data layout: %s", data_layout);
1770 }
1771
1772 ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT); CHKERRQ(ierr);
1773 ierr = PetscBarrier(NULL);
1774 PetscFunctionReturn(0);
1775}
Vec lDiffusivityGradient
Definition variables.h:841
Vec lCent
Definition variables.h:858
Vec lZet
Definition variables.h:858
Vec lCellFieldAtCorner
Definition variables.h:846
Vec lPsi
Definition variables.h:883
Vec lCsi
Definition variables.h:858
Vec CellFieldAtCorner
Definition variables.h:846
Vec lUcat
Definition variables.h:837
Vec lEta
Definition variables.h:858
Vec lDiffusivity
Definition variables.h:840
Here is the caller graph for this function:

◆ LOG_INTERPOLATION_ERROR()

PetscErrorCode LOG_INTERPOLATION_ERROR ( UserCtx user)

Implementation of LOG_INTERPOLATION_ERROR().

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 1785 of file logging.c.

1786{
1787 SimCtx *simCtx = user->simCtx;
1788 PetscErrorCode ierr;
1789 DM swarm = user->swarm;
1790 Vec positionVec, analyticalvelocityVec, velocityVec, errorVec;
1791 PetscReal Interpolation_error = 0.0;
1792 PetscReal Maximum_Interpolation_error = 0.0;
1793 PetscReal AnalyticalSolution_magnitude = 0.0;
1794 PetscReal ErrorPercentage = 0.0;
1795
1796 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Creating global vectors.\n");
1797 ierr = DMSwarmCreateGlobalVectorFromField(swarm, "position", &positionVec); CHKERRQ(ierr);
1798 ierr = DMSwarmCreateGlobalVectorFromField(swarm, "velocity", &velocityVec); CHKERRQ(ierr);
1799
1800 ierr = VecDuplicate(positionVec, &analyticalvelocityVec); CHKERRQ(ierr);
1801 ierr = VecCopy(positionVec, analyticalvelocityVec); CHKERRQ(ierr);
1802
1803 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Computing analytical solution.\n");
1804 ierr = SetAnalyticalSolutionForParticles(analyticalvelocityVec, simCtx); CHKERRQ(ierr);
1805
1806 ierr = VecDuplicate(analyticalvelocityVec, &errorVec); CHKERRQ(ierr);
1807 ierr = VecCopy(analyticalvelocityVec, errorVec); CHKERRQ(ierr);
1808
1809 ierr = VecNorm(analyticalvelocityVec, NORM_2, &AnalyticalSolution_magnitude); CHKERRQ(ierr);
1810
1811 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Computing error.\n");
1812 ierr = VecAXPY(errorVec, -1.0, velocityVec); CHKERRQ(ierr);
1813 ierr = VecNorm(errorVec, NORM_2, &Interpolation_error); CHKERRQ(ierr);
1814 ierr = VecNorm(errorVec,NORM_INFINITY,&Maximum_Interpolation_error); CHKERRQ(ierr);
1815
1816 ErrorPercentage = (AnalyticalSolution_magnitude > 0) ?
1817 (Interpolation_error / AnalyticalSolution_magnitude * 100.0) : 0.0;
1818
1819 /* --- CSV output (always, rank 0 only) --- */
1820 if (simCtx->rank == 0) {
1821 char csv_path[PETSC_MAX_PATH_LEN + 32];
1822 ierr = PetscSNPrintf(csv_path, sizeof(csv_path), "%s/interpolation_error.csv", simCtx->log_dir); CHKERRQ(ierr);
1823 FILE *f = fopen(csv_path, "a");
1824 if (f) {
1825 if (ftell(f) == 0) {
1826 fprintf(f, "step,time,L2_error,Linf_error,L2_analytical,error_pct\n");
1827 }
1828 PetscReal t = (PetscReal)simCtx->ti * simCtx->dt;
1829 fprintf(f, "%d,%.6e,%.6e,%.6e,%.6e,%.4f\n",
1830 (int)simCtx->step, t,
1831 Interpolation_error, Maximum_Interpolation_error,
1832 AnalyticalSolution_magnitude, ErrorPercentage);
1833 fclose(f);
1834 }
1835 }
1836
1837 /* --- Console output (only at INFO level or above) --- */
1838 if (get_log_level() >= LOG_INFO) {
1839 LOG_ALLOW(GLOBAL, LOG_INFO, "Interpolation error (%%): %g\n", ErrorPercentage);
1840 PetscPrintf(PETSC_COMM_WORLD, "Interpolation error (%%): %g\n", ErrorPercentage);
1841 LOG_ALLOW(GLOBAL, LOG_INFO, "Maximum Interpolation error: %g\n", Maximum_Interpolation_error);
1842 PetscPrintf(PETSC_COMM_WORLD, "Maximum Interpolation error: %g\n", Maximum_Interpolation_error);
1843 }
1844
1845 ierr = VecDestroy(&analyticalvelocityVec); CHKERRQ(ierr);
1846 ierr = VecDestroy(&errorVec); CHKERRQ(ierr);
1847 ierr = DMSwarmDestroyGlobalVectorFromField(swarm, "position", &positionVec); CHKERRQ(ierr);
1848 ierr = DMSwarmDestroyGlobalVectorFromField(swarm, "velocity", &velocityVec); CHKERRQ(ierr);
1849
1850 return 0;
1851}
PetscErrorCode SetAnalyticalSolutionForParticles(Vec tempVec, SimCtx *simCtx)
Applies the analytical solution to particle velocity vector.
PetscReal dt
Definition variables.h:658
PetscReal ti
Definition variables.h:652
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)

Implementation of LOG_SCATTER_METRICS().

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 1861 of file logging.c.

1862{
1863 PetscErrorCode ierr;
1864 SimCtx *simCtx = NULL;
1865 DMDALocalInfo info;
1866 PetscInt xs, xe, ys, ye, zs, ze, mx, my, mz;
1867 PetscInt lxs, lxe, lys, lye, lzs, lze;
1868 Vec reference_vec = NULL;
1869 PetscReal ***psi = NULL;
1870 PetscReal ***psi_ref = NULL;
1871 PetscReal ***aj = NULL;
1872 PetscReal ***count = NULL;
1873 PetscReal *particle_psi = NULL;
1874 PetscInt nlocal = 0;
1875 PetscReal local_l1 = 0.0, global_l1 = 0.0;
1876 PetscReal local_l2_sq = 0.0, global_l2_sq = 0.0;
1877 PetscReal local_linf = 0.0, global_linf = 0.0;
1878 PetscReal local_ref_l2_sq = 0.0, global_ref_l2_sq = 0.0;
1879 PetscReal local_grid_integral = 0.0, global_grid_integral = 0.0;
1880 PetscReal local_domain_volume = 0.0, global_domain_volume = 0.0;
1881 PetscReal local_particle_sum = 0.0, global_particle_sum = 0.0;
1882 PetscInt64 local_particle_count = 0, global_particle_count = 0;
1883 PetscInt64 local_cell_count = 0, global_cell_count = 0;
1884 PetscInt64 local_occupied_count = 0, global_occupied_count = 0;
1885 PetscReal particle_integral = 0.0;
1886 PetscReal occupancy_fraction = 0.0;
1887 PetscReal mean_particles_per_occupied_cell = 0.0;
1888 PetscReal l2_error = 0.0;
1889 PetscReal relative_l2_error = 0.0;
1890
1891 PetscFunctionBeginUser;
1892 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx cannot be NULL.");
1893 simCtx = user->simCtx;
1894 if (!VerificationScalarOverrideActive(simCtx) || !user->swarm || !user->Psi || !user->ParticleCount) {
1895 PetscFunctionReturn(0);
1896 }
1897
1898 info = user->info;
1899 xs = info.xs; xe = info.xs + info.xm;
1900 ys = info.ys; ye = info.ys + info.ym;
1901 zs = info.zs; ze = info.zs + info.zm;
1902 mx = info.mx; my = info.my; mz = info.mz;
1903 lxs = (xs == 0) ? xs + 1 : xs; lxe = (xe == mx) ? xe - 1 : xe;
1904 lys = (ys == 0) ? ys + 1 : ys; lye = (ye == my) ? ye - 1 : ye;
1905 lzs = (zs == 0) ? zs + 1 : zs; lze = (ze == mz) ? ze - 1 : ze;
1906
1907 ierr = VecDuplicate(user->Psi, &reference_vec); CHKERRQ(ierr);
1908 ierr = SetAnalyticalScalarFieldAtCellCenters(user, reference_vec); CHKERRQ(ierr);
1909
1910 ierr = DMDAVecGetArrayRead(user->da, user->Psi, &psi); CHKERRQ(ierr);
1911 ierr = DMDAVecGetArrayRead(user->da, reference_vec, &psi_ref); CHKERRQ(ierr);
1912 ierr = DMDAVecGetArrayRead(user->da, user->Aj, &aj); CHKERRQ(ierr);
1913 ierr = DMDAVecGetArrayRead(user->da, user->ParticleCount, &count); CHKERRQ(ierr);
1914
1915 for (PetscInt k = lzs; k < lze; ++k) {
1916 for (PetscInt j = lys; j < lye; ++j) {
1917 for (PetscInt i = lxs; i < lxe; ++i) {
1918 const PetscReal cell_volume = (PetscAbsReal(aj[k][j][i]) > 1.0e-14) ? (1.0 / aj[k][j][i]) : 0.0;
1919 const PetscReal err = psi[k][j][i] - psi_ref[k][j][i];
1920 local_cell_count += 1;
1921 local_domain_volume += cell_volume;
1922 local_grid_integral += psi[k][j][i] * cell_volume;
1923 local_l1 += PetscAbsReal(err) * cell_volume;
1924 local_l2_sq += err * err * cell_volume;
1925 local_ref_l2_sq += psi_ref[k][j][i] * psi_ref[k][j][i] * cell_volume;
1926 local_linf = PetscMax(local_linf, PetscAbsReal(err));
1927 if (count[k][j][i] > 0.0) local_occupied_count += 1;
1928 }
1929 }
1930 }
1931
1932 ierr = DMDAVecRestoreArrayRead(user->da, user->ParticleCount, &count); CHKERRQ(ierr);
1933 ierr = DMDAVecRestoreArrayRead(user->da, user->Aj, &aj); CHKERRQ(ierr);
1934 ierr = DMDAVecRestoreArrayRead(user->da, reference_vec, &psi_ref); CHKERRQ(ierr);
1935 ierr = DMDAVecRestoreArrayRead(user->da, user->Psi, &psi); CHKERRQ(ierr);
1936 ierr = VecDestroy(&reference_vec); CHKERRQ(ierr);
1937
1938 ierr = DMSwarmGetLocalSize(user->swarm, &nlocal); CHKERRQ(ierr);
1939 local_particle_count = (PetscInt64)nlocal;
1940 if (nlocal > 0) {
1941 ierr = DMSwarmGetField(user->swarm, "Psi", NULL, NULL, (void **)&particle_psi); CHKERRQ(ierr);
1942 for (PetscInt p = 0; p < nlocal; ++p) local_particle_sum += particle_psi[p];
1943 ierr = DMSwarmRestoreField(user->swarm, "Psi", NULL, NULL, (void **)&particle_psi); CHKERRQ(ierr);
1944 }
1945
1946 ierr = MPI_Allreduce(&local_l1, &global_l1, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
1947 ierr = MPI_Allreduce(&local_l2_sq, &global_l2_sq, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
1948 ierr = MPI_Allreduce(&local_linf, &global_linf, 1, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD); CHKERRMPI(ierr);
1949 ierr = MPI_Allreduce(&local_ref_l2_sq, &global_ref_l2_sq, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
1950 ierr = MPI_Allreduce(&local_grid_integral, &global_grid_integral, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
1951 ierr = MPI_Allreduce(&local_domain_volume, &global_domain_volume, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
1952 ierr = MPI_Allreduce(&local_particle_sum, &global_particle_sum, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
1953 ierr = MPI_Allreduce(&local_particle_count, &global_particle_count, 1, MPIU_INT64, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
1954 ierr = MPI_Allreduce(&local_cell_count, &global_cell_count, 1, MPIU_INT64, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
1955 ierr = MPI_Allreduce(&local_occupied_count, &global_occupied_count, 1, MPIU_INT64, MPI_SUM, PETSC_COMM_WORLD); CHKERRMPI(ierr);
1956
1957 l2_error = PetscSqrtReal(global_l2_sq);
1958 relative_l2_error = (global_ref_l2_sq > 0.0) ? (l2_error / PetscSqrtReal(global_ref_l2_sq)) : 0.0;
1959 occupancy_fraction = (global_cell_count > 0) ? ((PetscReal)global_occupied_count / (PetscReal)global_cell_count) : 0.0;
1960 mean_particles_per_occupied_cell =
1961 (global_occupied_count > 0) ? ((PetscReal)global_particle_count / (PetscReal)global_occupied_count) : 0.0;
1962 particle_integral =
1963 (global_particle_count > 0) ? (global_domain_volume * global_particle_sum / (PetscReal)global_particle_count) : 0.0;
1964
1965 if (simCtx->rank == 0) {
1966 char csv_path[PETSC_MAX_PATH_LEN + 32];
1967 FILE *f = NULL;
1968 ierr = PetscSNPrintf(csv_path, sizeof(csv_path), "%s/scatter_metrics.csv", simCtx->log_dir); CHKERRQ(ierr);
1969 f = fopen(csv_path, "a");
1970 if (f) {
1971 if (ftell(f) == 0) {
1972 fprintf(f,
1973 "step,time,total_particles,total_cells,occupied_cells,occupancy_fraction,"
1974 "mean_particles_per_occupied_cell,particle_integral,grid_integral,"
1975 "conservation_error_abs,L1_error,L2_error,Linf_error,relative_L2_error\n");
1976 }
1977 fprintf(f, "%d,%.6e,%lld,%lld,%lld,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e,%.6e\n",
1978 (int)simCtx->step,
1979 (double)simCtx->ti,
1980 (long long)global_particle_count,
1981 (long long)global_cell_count,
1982 (long long)global_occupied_count,
1983 (double)occupancy_fraction,
1984 (double)mean_particles_per_occupied_cell,
1985 (double)particle_integral,
1986 (double)global_grid_integral,
1987 (double)PetscAbsReal(global_grid_integral - particle_integral),
1988 (double)global_l1,
1989 (double)l2_error,
1990 (double)global_linf,
1991 (double)relative_l2_error);
1992 fclose(f);
1993 }
1994 }
1995
1996 if (get_log_level() >= LOG_INFO) {
1997 LOG_ALLOW(GLOBAL, LOG_INFO, "Scatter relative L2 error: %.6e\n", (double)relative_l2_error);
1998 LOG_ALLOW(GLOBAL, LOG_INFO, "Scatter occupancy fraction: %.6e\n", (double)occupancy_fraction);
1999 }
2000
2001 PetscFunctionReturn(0);
2002}
PetscErrorCode SetAnalyticalScalarFieldAtCellCenters(UserCtx *user, Vec targetVec)
Writes the configured verification scalar profile at physical cell centers into a scalar Vec.
Vec ParticleCount
Definition variables.h:882
DMDALocalInfo info
Definition variables.h:818
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)

Implementation of ResetSearchMetrics().

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 2012 of file logging.c.

2013{
2014 PetscFunctionBeginUser;
2015 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "SimCtx cannot be NULL for ResetSearchMetrics.");
2016
2017 simCtx->searchMetrics.searchAttempts = 0;
2018 simCtx->searchMetrics.searchPopulation = 0;
2020 simCtx->searchMetrics.searchLostCount = 0;
2021 simCtx->searchMetrics.traversalStepsSum = 0;
2022 simCtx->searchMetrics.reSearchCount = 0;
2023 simCtx->searchMetrics.maxTraversalSteps = 0;
2025 simCtx->searchMetrics.tieBreakCount = 0;
2031
2032 PetscFunctionReturn(0);
2033}
PetscInt64 searchLocatedCount
Definition variables.h:224
PetscInt64 searchLostCount
Definition variables.h:225
PetscInt64 boundaryClampCount
Definition variables.h:231
PetscInt64 traversalStepsSum
Definition variables.h:226
PetscInt64 searchPopulation
Definition variables.h:223
PetscInt currentSettlementPass
Definition variables.h:235
PetscInt64 reSearchCount
Definition variables.h:227
PetscInt64 bboxGuessFallbackCount
Definition variables.h:233
PetscInt64 bboxGuessSuccessCount
Definition variables.h:232
PetscInt64 maxParticlePassDepth
Definition variables.h:234
PetscInt64 maxTraversalSteps
Definition variables.h:228
SearchMetricsState searchMetrics
Definition variables.h:752
PetscInt64 searchAttempts
Definition variables.h:222
PetscInt64 tieBreakCount
Definition variables.h:230
PetscInt64 maxTraversalFailCount
Definition variables.h:229
Here is the caller graph for this function:

◆ LOG_SEARCH_METRICS()

PetscErrorCode LOG_SEARCH_METRICS ( UserCtx user)

Implementation of LOG_SEARCH_METRICS().

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 2043 of file logging.c.

2044{
2045 PetscErrorCode ierr;
2046 SimCtx *simCtx = NULL;
2047 PetscInt totalParticles = 0;
2048 PetscReal local_metrics[SEARCH_METRIC_REDUCTION_LEN] = {0.0};
2049 PetscReal global_metrics[SEARCH_METRIC_REDUCTION_LEN] = {0.0};
2050 PetscReal meanTraversalSteps = 0.0;
2051 PetscReal searchFailureFraction = 0.0;
2052 PetscReal searchWorkIndex = 0.0;
2053 PetscReal reSearchFraction = 0.0;
2054 long long searchAttempts = 0;
2055 long long searchPopulation = 0;
2056 long long searchLocatedCount = 0;
2057 long long searchLostCount = 0;
2058 long long traversalStepsSum = 0;
2059 long long reSearchCount = 0;
2060 long long tieBreakCount = 0;
2061 long long boundaryClampCount = 0;
2062 long long bboxGuessSuccessCount = 0;
2063 long long bboxGuessFallbackCount = 0;
2064 long long maxTraversalFailCount = 0;
2065 long long maxTraversalSteps = 0;
2066 long long maxPassDepth = 0;
2067 MPI_Op reduction_op = MPI_OP_NULL;
2068
2069 PetscFunctionBeginUser;
2070 if (!user || !user->simCtx) {
2071 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx and SimCtx are required for LOG_SEARCH_METRICS.");
2072 }
2073 simCtx = user->simCtx;
2074
2075 if (simCtx->np <= 0) {
2076 PetscFunctionReturn(0);
2077 }
2078
2079 ierr = DMSwarmGetSize(user->swarm, &totalParticles); CHKERRQ(ierr);
2080
2081 local_metrics[SEARCH_METRIC_SUM_SEARCH_ATTEMPTS] = (PetscReal)simCtx->searchMetrics.searchAttempts;
2082 local_metrics[SEARCH_METRIC_SUM_SEARCH_POPULATION] = (PetscReal)simCtx->searchMetrics.searchPopulation;
2083 local_metrics[SEARCH_METRIC_SUM_SEARCH_LOCATED] = (PetscReal)simCtx->searchMetrics.searchLocatedCount;
2084 local_metrics[SEARCH_METRIC_SUM_SEARCH_LOST] = (PetscReal)simCtx->searchMetrics.searchLostCount;
2085 local_metrics[SEARCH_METRIC_SUM_TRAVERSAL_STEPS] = (PetscReal)simCtx->searchMetrics.traversalStepsSum;
2086 local_metrics[SEARCH_METRIC_SUM_RESEARCH] = (PetscReal)simCtx->searchMetrics.reSearchCount;
2087 local_metrics[SEARCH_METRIC_SUM_TIE_BREAKS] = (PetscReal)simCtx->searchMetrics.tieBreakCount;
2088 local_metrics[SEARCH_METRIC_SUM_BOUNDARY_CLAMPS] = (PetscReal)simCtx->searchMetrics.boundaryClampCount;
2089 local_metrics[SEARCH_METRIC_SUM_BBOX_GUESS_SUCCESS] = (PetscReal)simCtx->searchMetrics.bboxGuessSuccessCount;
2090 local_metrics[SEARCH_METRIC_SUM_BBOX_GUESS_FALLBACK] = (PetscReal)simCtx->searchMetrics.bboxGuessFallbackCount;
2091 local_metrics[SEARCH_METRIC_SUM_MAX_TRAVERSAL_FAILS] = (PetscReal)simCtx->searchMetrics.maxTraversalFailCount;
2092 local_metrics[SEARCH_METRIC_MAX_TRAVERSAL_STEPS] = (PetscReal)simCtx->searchMetrics.maxTraversalSteps;
2093 local_metrics[SEARCH_METRIC_MAX_PASS_DEPTH] = (PetscReal)simCtx->searchMetrics.maxParticlePassDepth;
2094
2095 ierr = MPI_Op_create(SearchMetricsReduceOp, PETSC_TRUE, &reduction_op); CHKERRMPI(ierr);
2096 ierr = MPI_Allreduce(local_metrics, global_metrics, SEARCH_METRIC_REDUCTION_LEN, MPIU_REAL, reduction_op, PETSC_COMM_WORLD); CHKERRMPI(ierr);
2097 ierr = MPI_Op_free(&reduction_op); CHKERRMPI(ierr);
2098 reduction_op = MPI_OP_NULL;
2099
2100 searchAttempts = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_SEARCH_ATTEMPTS] + 0.5);
2101 searchPopulation = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_SEARCH_POPULATION] + 0.5);
2102 searchLocatedCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_SEARCH_LOCATED] + 0.5);
2103 searchLostCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_SEARCH_LOST] + 0.5);
2104 traversalStepsSum = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_TRAVERSAL_STEPS] + 0.5);
2105 reSearchCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_RESEARCH] + 0.5);
2106 tieBreakCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_TIE_BREAKS] + 0.5);
2107 boundaryClampCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_BOUNDARY_CLAMPS] + 0.5);
2108 bboxGuessSuccessCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_BBOX_GUESS_SUCCESS] + 0.5);
2109 bboxGuessFallbackCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_BBOX_GUESS_FALLBACK] + 0.5);
2110 maxTraversalFailCount = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_SUM_MAX_TRAVERSAL_FAILS] + 0.5);
2111 maxTraversalSteps = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_MAX_TRAVERSAL_STEPS] + 0.5);
2112 maxPassDepth = (long long)PetscFloorReal(global_metrics[SEARCH_METRIC_MAX_PASS_DEPTH] + 0.5);
2113
2114 if (searchAttempts > 0) {
2115 meanTraversalSteps = (PetscReal)traversalStepsSum / (PetscReal)searchAttempts;
2116 }
2117 if (searchPopulation > 0) {
2118 searchFailureFraction = (PetscReal)searchLostCount / (PetscReal)searchPopulation;
2119 searchWorkIndex = (PetscReal)traversalStepsSum / (PetscReal)searchPopulation;
2120 reSearchFraction = (PetscReal)reSearchCount / (PetscReal)searchPopulation;
2121 }
2122
2123 if (simCtx->rank == 0) {
2124 char csv_path[PETSC_MAX_PATH_LEN + 32];
2125 FILE *f = NULL;
2126
2127 ierr = PetscSNPrintf(csv_path, sizeof(csv_path), "%s/search_metrics.csv", simCtx->log_dir); CHKERRQ(ierr);
2128 f = fopen(csv_path, "a");
2129 if (!f) {
2130 LOG_ALLOW(GLOBAL, LOG_WARNING, "LOG_SEARCH_METRICS: could not open '%s' for writing.\n", csv_path);
2131 } else {
2132 if (ftell(f) == 0) {
2133 fprintf(f,
2134 "step,time,total_particles,lost,lost_cumulative,migrated,migration_passes,search_attempts,"
2135 "mean_traversal_steps,max_traversal_steps,tie_break_count,boundary_clamp_count,"
2136 "bbox_guess_success_count,bbox_guess_fallback_count,max_particle_pass_depth,load_imbalance,"
2137 "search_population,search_located_count,search_lost_count,traversal_steps_sum,re_search_count,"
2138 "max_traversal_fail_count,search_failure_fraction,search_work_index,re_search_fraction\n");
2139 }
2140 fprintf(f,
2141 "%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",
2142 (int)simCtx->step,
2143 (double)simCtx->ti,
2144 (int)totalParticles,
2145 (int)simCtx->particlesLostLastStep,
2146 (int)simCtx->particlesLostCumulative,
2147 (int)simCtx->particlesMigratedLastStep,
2148 (int)simCtx->migrationPassesLastStep,
2149 searchAttempts,
2150 (double)meanTraversalSteps,
2151 maxTraversalSteps,
2152 tieBreakCount,
2153 boundaryClampCount,
2154 bboxGuessSuccessCount,
2155 bboxGuessFallbackCount,
2156 maxPassDepth,
2157 (double)simCtx->particleLoadImbalance,
2158 searchPopulation,
2159 searchLocatedCount,
2160 searchLostCount,
2161 traversalStepsSum,
2162 reSearchCount,
2163 maxTraversalFailCount,
2164 (double)searchFailureFraction,
2165 (double)searchWorkIndex,
2166 (double)reSearchFraction);
2167 fclose(f);
2168 }
2169 }
2170
2172 "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",
2173 (double)searchFailureFraction,
2174 (double)searchWorkIndex,
2175 (double)reSearchFraction,
2176 (int)simCtx->particlesLostLastStep,
2177 (int)simCtx->particlesLostCumulative,
2178 (int)simCtx->particlesMigratedLastStep,
2179 (int)simCtx->migrationPassesLastStep,
2180 (double)meanTraversalSteps,
2181 maxTraversalSteps,
2182 tieBreakCount,
2183 maxPassDepth);
2184
2185 PetscFunctionReturn(0);
2186}
static void SearchMetricsReduceOp(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype)
Internal reduction callback for packed search metrics.
Definition logging.c:51
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CalculateAdvancedParticleMetrics()

PetscErrorCode CalculateAdvancedParticleMetrics ( UserCtx user)

Internal helper implementation: CalculateAdvancedParticleMetrics().

Computes advanced particle statistics and stores them in SimCtx.

Local to this translation unit.

Definition at line 2194 of file logging.c.

2195{
2196 PetscErrorCode ierr;
2197 SimCtx *simCtx = user->simCtx;
2198 PetscMPIInt size, rank;
2199
2200 PetscFunctionBeginUser;
2201 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
2202 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2203
2204 // --- 1. Particle Load Imbalance ---
2205 PetscInt nLocal, nGlobal, nLocalMax;
2206 ierr = DMSwarmGetLocalSize(user->swarm, &nLocal); CHKERRQ(ierr);
2207 ierr = DMSwarmGetSize(user->swarm, &nGlobal); CHKERRQ(ierr);
2208 ierr = MPI_Allreduce(&nLocal, &nLocalMax, 1, MPIU_INT, MPI_MAX, PETSC_COMM_WORLD); CHKERRQ(ierr);
2209
2210 PetscReal avg_per_rank = (size > 0) ? ((PetscReal)nGlobal / size) : 0.0;
2211 // Handle division by zero if there are no particles
2212 simCtx->particleLoadImbalance = (avg_per_rank > 1e-9) ? (nLocalMax / avg_per_rank) : 1.0;
2213
2214
2215 // --- 2. Number of Occupied Cells ---
2216 // This part requires access to the user->ParticleCount vector.
2217 PetscInt local_occupied_cells = 0;
2218 PetscInt global_occupied_cells;
2219 const PetscScalar *count_array;
2220 PetscInt vec_local_size;
2221
2222 ierr = VecGetLocalSize(user->ParticleCount, &vec_local_size); CHKERRQ(ierr);
2223 ierr = VecGetArrayRead(user->ParticleCount, &count_array); CHKERRQ(ierr);
2224
2225 for (PetscInt i = 0; i < vec_local_size; ++i) {
2226 if (count_array[i] > 0.5) { // Use 0.5 to be safe with floating point
2227 local_occupied_cells++;
2228 }
2229 }
2230 ierr = VecRestoreArrayRead(user->ParticleCount, &count_array); CHKERRQ(ierr);
2231
2232 ierr = MPI_Allreduce(&local_occupied_cells, &global_occupied_cells, 1, MPIU_INT, MPI_SUM, PETSC_COMM_WORLD); CHKERRQ(ierr);
2233 simCtx->occupiedCellCount = global_occupied_cells;
2234
2235 LOG_ALLOW_SYNC(GLOBAL, LOG_INFO, "[Rank %d] Advanced Metrics: Imbalance=%.2f, OccupiedCells=%d\n", rank, simCtx->particleLoadImbalance, simCtx->occupiedCellCount);
2236
2237 PetscFunctionReturn(0);
2238}
PetscInt occupiedCellCount
Definition variables.h:750
PetscReal particleLoadImbalance
Definition variables.h:751
Here is the caller graph for this function:

◆ LOG_PARTICLE_METRICS()

PetscErrorCode LOG_PARTICLE_METRICS ( UserCtx user,
const char *  stageName 
)

Implementation of LOG_PARTICLE_METRICS().

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 2248 of file logging.c.

2249{
2250 PetscErrorCode ierr;
2251 PetscMPIInt rank;
2252 SimCtx *simCtx = user->simCtx;
2253 const char *stage_label = (stageName && stageName[0] != '\0') ? stageName : "N/A";
2254
2255 PetscFunctionBeginUser;
2256 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2257
2258 PetscInt totalParticles;
2259 ierr = DMSwarmGetSize(user->swarm, &totalParticles); CHKERRQ(ierr);
2260
2261 if (!rank) {
2262 FILE *f;
2263 char filen[PETSC_MAX_PATH_LEN + 64];
2264 ierr = PetscSNPrintf(filen, sizeof(filen), "%s/Particle_Metrics.log", simCtx->log_dir); CHKERRQ(ierr);
2265 f = fopen(filen, "a");
2266 if (!f) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open particle log file: %s", filen);
2267
2268 if (ftell(f) == 0) {
2269 PetscFPrintf(PETSC_COMM_SELF, f, "%-18s | %-10s | %-12s | %-10s | %-10s | %-10s | %-15s | %-10s | %-10s\n",
2270 "Stage", "Timestep", "Total Ptls", "Lost", "Lost Total", "Migrated", "Occupied Cells", "Imbalance", "Mig Passes");
2271 PetscFPrintf(PETSC_COMM_SELF, f, "-------------------------------------------------------------------------------------------------------------------------------------------\n");
2272 }
2273
2274 PetscFPrintf(PETSC_COMM_SELF, f, "%-18s | %-10d | %-12d | %-10d | %-10d | %-10d | %-15d | %-10.2f | %-10d\n",
2275 stage_label, (int)simCtx->step, (int)totalParticles, (int)simCtx->particlesLostLastStep,
2276 (int)simCtx->particlesLostCumulative, (int)simCtx->particlesMigratedLastStep, (int)simCtx->occupiedCellCount,
2277 (double)simCtx->particleLoadImbalance, (int)simCtx->migrationPassesLastStep);
2278 fclose(f);
2279 }
2280 PetscFunctionReturn(0);
2281}
PetscInt particlesLostLastStep
Definition variables.h:746
PetscInt particlesLostCumulative
Definition variables.h:747
PetscInt particlesMigratedLastStep
Definition variables.h:749
PetscInt migrationPassesLastStep
Definition variables.h:748
Here is the caller graph for this function:

Variable Documentation

◆ current_log_level

LogLevel current_log_level = -1
static

Static variable to cache the current logging level.

Initialized to -1 to indicate that the log level has not been set yet.

Definition at line 16 of file logging.c.

◆ gAllowedFunctions

char** gAllowedFunctions = NULL
static

Global/static array of function names allowed to log.

Definition at line 23 of file logging.c.

◆ gNumAllowed

int gNumAllowed = 0
static

Number of entries in the gAllowedFunctions array.

Definition at line 28 of file logging.c.

◆ g_profiler_registry

ProfiledFunction* g_profiler_registry = NULL
static

Definition at line 999 of file logging.c.

◆ g_profiler_count

PetscInt g_profiler_count = 0
static

Definition at line 1000 of file logging.c.

◆ g_profiler_capacity

PetscInt g_profiler_capacity = 0
static

Definition at line 1001 of file logging.c.