PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Macros | Functions | Variables
statistics_window.c File Reference

Window lifecycle, scheduling, and weighting for the field-statistics pipeline. More...

#include "statistics_window.h"
#include "variables.h"
#include "logging.h"
#include "statistics_accumulator.h"
#include "field_catalog.h"
#include "checksum.h"
Include dependency graph for statistics_window.c:

Go to the source code of this file.

Macros

#define WINDOW_TIME_EPSILON   1.0e-12
 Tolerance for treating two physical times as the same instant.
 
#define __FUNCT__   "PicurvWindowInit"
 
#define __FUNCT__   "PicurvWindowComputeHash"
 
#define __FUNCT__   "FieldStatisticsUpdateWindows"
 

Functions

const char * PicurvWindowStateName (PicurvWindowState state)
 Implementation of PicurvWindowStateName().
 
PetscErrorCode PicurvWindowInit (PicurvWindow *window, const PicurvWindowDefinition *definition)
 Implementation of PicurvWindowInit().
 
static PetscBool WindowStateIsDue (const PicurvWindow *window, PetscInt step, PetscReal time)
 Internal helper: reports whether a state is due under the window's schedule.
 
static void WindowAdvanceTimeTarget (PicurvWindow *window, PetscReal time)
 Internal helper: advances the time-cadence target past the accepted time.
 
PetscErrorCode PicurvWindowOfferState (PicurvWindow *window, PetscInt step, PetscReal time, PetscBool *accepted, PetscReal *weight)
 Implementation of PicurvWindowOfferState().
 
const char * PicurvWindowHashGroupName (PetscInt group)
 Implementation of PicurvWindowHashGroupName().
 
static void SortRequestOrder (PetscInt count, const PetscInt *primary, const PetscInt *secondary, PetscInt *order)
 Internal helper: orders request indices so listing order cannot change the hash.
 
PetscErrorCode PicurvWindowComputeHash (const PicurvWindowDefinition *definition, char digest_hex[65], char group_digest_hex[][PICURV_WINDOW_HASH_GROUP_LENGTH])
 Implementation of PicurvWindowComputeHash().
 
PetscErrorCode PicurvWindowFirstHashDifference (const PicurvWindowDefinition *definition, const char *saved_group_digests, PetscInt *group)
 Implementation of PicurvWindowFirstHashDifference().
 
PetscReal PicurvWindowProgress (const PicurvWindow *window)
 Implementation of PicurvWindowProgress().
 
PetscBool FieldStatisticsIsActive (const SimCtx *simCtx)
 Implementation of FieldStatisticsIsActive().
 
PetscErrorCode FieldStatisticsUpdateWindows (SimCtx *simCtx, PetscInt step, PetscReal time)
 Implementation of FieldStatisticsUpdateWindows().
 

Variables

static const char *const kHashGroupNames [PICURV_WINDOW_HASH_GROUP_COUNT]
 Stable names of the hashed property groups, in serialization order.
 

Detailed Description

Window lifecycle, scheduling, and weighting for the field-statistics pipeline.

Full API contract is documented with the declarations in include/statistics_window.h.

Definition in file statistics_window.c.

Macro Definition Documentation

◆ WINDOW_TIME_EPSILON

#define WINDOW_TIME_EPSILON   1.0e-12

Tolerance for treating two physical times as the same instant.

Definition at line 17 of file statistics_window.c.

◆ __FUNCT__ [1/3]

#define __FUNCT__   "PicurvWindowInit"

Definition at line 34 of file statistics_window.c.

◆ __FUNCT__ [2/3]

#define __FUNCT__   "PicurvWindowComputeHash"

Definition at line 34 of file statistics_window.c.

◆ __FUNCT__ [3/3]

#define __FUNCT__   "FieldStatisticsUpdateWindows"

Definition at line 34 of file statistics_window.c.

Function Documentation

◆ PicurvWindowStateName()

const char * PicurvWindowStateName ( PicurvWindowState  state)

Implementation of PicurvWindowStateName().

Returns a stable human-readable name for a window state.

See also
PicurvWindowStateName()

Definition at line 23 of file statistics_window.c.

24{
25 switch (state) {
26 case PICURV_WINDOW_PENDING: return "pending";
27 case PICURV_WINDOW_ACTIVE: return "active";
28 case PICURV_WINDOW_COMPLETE: return "complete";
29 default: return "unknown";
30 }
31}
@ PICURV_WINDOW_PENDING
Requested start not yet reached.
@ PICURV_WINDOW_COMPLETE
Bounded end reached; accepts nothing further.
@ PICURV_WINDOW_ACTIVE
Accepting due states.
Here is the caller graph for this function:

◆ PicurvWindowInit()

PetscErrorCode PicurvWindowInit ( PicurvWindow *  window,
const PicurvWindowDefinition *  definition 
)

Implementation of PicurvWindowInit().

Validates a definition and initializes a window to the pending state.

See also
PicurvWindowInit()

Definition at line 39 of file statistics_window.c.

40{
41 PetscFunctionBeginUser;
43 PetscCheck(window != NULL && definition != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
44 "Window and definition are required.");
45 PetscCheck(definition->name[0] != '\0', PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
46 "Window name must not be empty.");
47 if (definition->cadence_kind == PICURV_CADENCE_STEP) {
48 PetscCheck(definition->step_cadence > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
49 "Window '%s' needs a positive step cadence, got %" PetscInt_FMT ".",
50 definition->name, definition->step_cadence);
51 } else {
52 PetscCheck(definition->time_cadence > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
53 "Window '%s' needs a positive time cadence, got %g.",
54 definition->name, (double)definition->time_cadence);
55 }
56 PetscCheck(!definition->bounded || definition->end_time > definition->start_time,
57 PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
58 "Window '%s' must end after it starts.", definition->name);
59
60 PetscCall(PetscMemzero(window, sizeof(*window)));
61 window->definition = *definition;
63 /* Anchoring the interval origin at the requested start, rather than at the
64 * first accepted state, is what lets the first sample represent the interval
65 * back to the requested bound instead of silently dropping it. */
66 window->effective_start = definition->start_time;
67 window->effective_end = definition->start_time;
68 window->last_accepted_time = definition->start_time;
69 window->activation_step = -1;
70 window->last_event_step = PETSC_MIN_INT;
71 window->next_time_target = 0;
73 PetscFunctionReturn(0);
74}
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:894
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:885
PetscInt last_event_step
Guards against a step being offered twice.
PetscReal effective_start
Origin of the first represented interval.
PetscReal last_accepted_time
Right edge of the last represented interval.
PicurvWindowState state
PetscReal time_cadence
Used when cadence_kind is time; must be positive.
PetscReal effective_end
End of the last represented interval.
PetscReal end_time
Requested end; ignored when bounded is false.
PicurvCadenceKind cadence_kind
PetscInt step_cadence
Used when cadence_kind is step; must be positive.
PetscBool bounded
False for an open-ended window.
PicurvWindowDefinition definition
PetscInt next_time_target
k in effective_start + k*time_cadence.
PetscReal start_time
Requested start.
PetscInt activation_step
Step at which the window became active.
@ PICURV_CADENCE_STEP
Every n completed steps from activation.
Here is the caller graph for this function:

◆ WindowStateIsDue()

static PetscBool WindowStateIsDue ( const PicurvWindow *  window,
PetscInt  step,
PetscReal  time 
)
static

Internal helper: reports whether a state is due under the window's schedule.

Local to this translation unit. Advances no state.

Definition at line 80 of file statistics_window.c.

81{
83 /* The activation step is itself due; subsequent ones follow the stride. */
84 if (window->activation_step < 0) return PETSC_TRUE;
85 return (PetscBool)(((step - window->activation_step) % window->definition.step_cadence) == 0);
86 }
87 /* Time cadence: targets sit on the absolute grid effective_start + k*cadence, so
88 * the schedule cannot drift as dt varies. A state is due once it reaches the
89 * next outstanding target. */
90 {
91 const PetscReal target = window->effective_start +
92 (PetscReal)window->next_time_target * window->definition.time_cadence;
93 return (PetscBool)(time >= target - WINDOW_TIME_EPSILON);
94 }
95}
#define WINDOW_TIME_EPSILON
Tolerance for treating two physical times as the same instant.
Here is the caller graph for this function:

◆ WindowAdvanceTimeTarget()

static void WindowAdvanceTimeTarget ( PicurvWindow *  window,
PetscReal  time 
)
static

Internal helper: advances the time-cadence target past the accepted time.

Local to this translation unit. A single large step may overshoot several targets; they are consumed at once, because the accepted state's weight is the actual elapsed interval and so already accounts for the whole span.

Definition at line 103 of file statistics_window.c.

104{
105 if (window->definition.cadence_kind != PICURV_CADENCE_TIME) return;
106 while (window->effective_start +
107 (PetscReal)window->next_time_target * window->definition.time_cadence
108 <= time + WINDOW_TIME_EPSILON) {
109 window->next_time_target += 1;
110 }
111}
@ PICURV_CADENCE_TIME
First state at or past each nominal time target.
Here is the caller graph for this function:

◆ PicurvWindowOfferState()

PetscErrorCode PicurvWindowOfferState ( PicurvWindow *  window,
PetscInt  step,
PetscReal  time,
PetscBool *  accepted,
PetscReal *  weight 
)

Implementation of PicurvWindowOfferState().

Offers one completed state to a window and reports the decision.

See also
PicurvWindowOfferState()

Definition at line 117 of file statistics_window.c.

119{
120 PetscReal interval = 0.0;
121 PetscReal right_edge = 0.0;
122 PetscBool closes = PETSC_FALSE;
123
124 PetscFunctionBeginUser;
125 PetscCheck(window != NULL && accepted != NULL && weight != NULL,
126 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
127 "Window, acceptance flag, and weight output are required.");
128 *accepted = PETSC_FALSE;
129 *weight = 0.0;
130
131 if (window->state == PICURV_WINDOW_COMPLETE) PetscFunctionReturn(0);
132 /* A completed state is accepted at most once, so a step already seen is
133 * rejected outright rather than double counted. */
134 if (step == window->last_event_step) PetscFunctionReturn(0);
135 if (time < window->definition.start_time - WINDOW_TIME_EPSILON) PetscFunctionReturn(0);
136
137 /* First observation: a window resumed later than its requested start cannot
138 * claim represented time it never saw, so the origin moves forward. */
139 if (window->state == PICURV_WINDOW_PENDING) {
140 if (time > window->definition.start_time + WINDOW_TIME_EPSILON) {
141 window->effective_start = time;
142 window->last_accepted_time = time;
143 }
144 window->state = PICURV_WINDOW_ACTIVE;
145 window->activation_step = step;
146 window->effective_end = window->effective_start;
147 window->next_time_target = 0;
149 }
150
151 if (!WindowStateIsDue(window, step, time)) {
152 /* An active off-schedule state changes no scientific state. */
153 PetscFunctionReturn(0);
154 }
155 window->last_event_step = step;
156
157 /* Clip the final represented interval to the requested bound. */
158 right_edge = time;
159 if (window->definition.bounded && time >= window->definition.end_time - WINDOW_TIME_EPSILON) {
160 right_edge = window->definition.end_time;
161 closes = PETSC_TRUE;
162 }
163
164 interval = right_edge - window->last_accepted_time;
165 WindowAdvanceTimeTarget(window, time);
166
167 if (interval <= WINDOW_TIME_EPSILON) {
168 /* A zero-length interval is not a sample. It still anchors the origin, which
169 * is what makes initial-state handling identical under both weightings. */
170 window->last_accepted_time = right_edge;
171 window->effective_end = right_edge;
172 if (closes) window->state = PICURV_WINDOW_COMPLETE;
173 PetscFunctionReturn(0);
174 }
175
176 *weight = (window->definition.weighting == PICURV_WEIGHTING_SAMPLE) ? 1.0 : interval;
177 *accepted = PETSC_TRUE;
178
179 window->last_accepted_time = right_edge;
180 window->effective_end = right_edge;
181 window->sample_count += 1;
182 window->total_weight += *weight;
183 window->represented_time += interval;
184 if (closes) window->state = PICURV_WINDOW_COMPLETE;
185 PetscFunctionReturn(0);
186}
static void WindowAdvanceTimeTarget(PicurvWindow *window, PetscReal time)
Internal helper: advances the time-cadence target past the accepted time.
static PetscBool WindowStateIsDue(const PicurvWindow *window, PetscInt step, PetscReal time)
Internal helper: reports whether a state is due under the window's schedule.
PetscInt sample_count
PetscReal total_weight
@ PICURV_WEIGHTING_SAMPLE
Equal weight per accepted state.
PetscReal represented_time
Physical time the window covers.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvWindowHashGroupName()

const char * PicurvWindowHashGroupName ( PetscInt  group)

Implementation of PicurvWindowHashGroupName().

Returns the stable name of one hashed property group.

See also
PicurvWindowHashGroupName()

Definition at line 197 of file statistics_window.c.

198{
199 if (group < 0 || group >= PICURV_WINDOW_HASH_GROUP_COUNT) return "unknown";
200 return kHashGroupNames[group];
201}
static const char *const kHashGroupNames[PICURV_WINDOW_HASH_GROUP_COUNT]
Stable names of the hashed property groups, in serialization order.
#define PICURV_WINDOW_HASH_GROUP_COUNT
Number of independently hashed property groups in a window definition.
Here is the caller graph for this function:

◆ SortRequestOrder()

static void SortRequestOrder ( PetscInt  count,
const PetscInt *  primary,
const PetscInt *  secondary,
PetscInt *  order 
)
static

Internal helper: orders request indices so listing order cannot change the hash.

Local to this translation unit. Insertion sort over at most PICURV_WINDOW_MAX_REQUESTS entries, keyed on a primary and secondary integer so the same routine serves both fields and covariance pairs.

Definition at line 209 of file statistics_window.c.

211{
212 for (PetscInt n = 0; n < count; ++n) order[n] = n;
213 for (PetscInt n = 1; n < count; ++n) {
214 const PetscInt candidate = order[n];
215 PetscInt m = n - 1;
216
217 while (m >= 0 &&
218 (primary[order[m]] > primary[candidate] ||
219 (primary[order[m]] == primary[candidate] &&
220 secondary[order[m]] > secondary[candidate]))) {
221 order[m + 1] = order[m];
222 --m;
223 }
224 order[m + 1] = candidate;
225 }
226}
Here is the caller graph for this function:

◆ PicurvWindowComputeHash()

PetscErrorCode PicurvWindowComputeHash ( const PicurvWindowDefinition *  definition,
char  digest_hex[65],
char  group_digest_hex[][PICURV_WINDOW_HASH_GROUP_LENGTH] 
)

Implementation of PicurvWindowComputeHash().

See also
PicurvWindowComputeHash()

Definition at line 234 of file statistics_window.c.

237{
239 PetscInt field_primary[PICURV_WINDOW_MAX_REQUESTS];
240 PetscInt field_secondary[PICURV_WINDOW_MAX_REQUESTS];
241 PetscInt field_order[PICURV_WINDOW_MAX_REQUESTS];
242 PetscInt pair_primary[PICURV_WINDOW_MAX_REQUESTS];
243 PetscInt pair_secondary[PICURV_WINDOW_MAX_REQUESTS];
244 PetscInt pair_order[PICURV_WINDOW_MAX_REQUESTS];
245
246 PetscFunctionBeginUser;
248 PetscCheck(definition != NULL && digest_hex != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
249 "Definition and digest output are required.");
250 PetscCheck(definition->field_count >= 0 && definition->field_count <= PICURV_WINDOW_MAX_REQUESTS,
251 PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
252 "Window '%s' requests %" PetscInt_FMT " fields; at most %d are supported.",
253 definition->name, definition->field_count, PICURV_WINDOW_MAX_REQUESTS);
254 PetscCheck(definition->covariance_count >= 0 &&
256 PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
257 "Window '%s' requests %" PetscInt_FMT " covariances; at most %d are supported.",
258 definition->name, definition->covariance_count, PICURV_WINDOW_MAX_REQUESTS);
259
260 for (PetscInt field_index = 0; field_index < definition->field_count; ++field_index) {
261 field_primary[field_index] = definition->fields[field_index].field_id;
262 field_secondary[field_index] = 0;
263 }
264 SortRequestOrder(definition->field_count, field_primary, field_secondary, field_order);
265 for (PetscInt pair_index = 0; pair_index < definition->covariance_count; ++pair_index) {
266 const PetscInt a = definition->covariances[pair_index].first;
267 const PetscInt b = definition->covariances[pair_index].second;
268
269 /* Covariance is symmetric, so the pair is canonicalized here rather than
270 * requiring the user to list its members in catalog order. */
271 pair_primary[pair_index] = PetscMin(a, b);
272 pair_secondary[pair_index] = PetscMax(a, b);
273 }
274 SortRequestOrder(definition->covariance_count, pair_primary, pair_secondary, pair_order);
275
276 PicurvSHA256Init(&whole);
277 for (PetscInt group = 0; group < PICURV_WINDOW_HASH_GROUP_COUNT; ++group) {
278 char text[1024];
279 char group_digest[65];
281 size_t used = 0;
282 size_t length = 0;
283
284 text[0] = '\0';
285 switch (group) {
286 case 0:
287 PetscCall(PetscSNPrintf(text, sizeof(text), "name=%s\n", definition->name));
288 break;
289 case 1:
290 PetscCall(PetscSNPrintf(text, sizeof(text), "start_time=%.17g\n",
291 (double)definition->start_time));
292 break;
293 case 2:
294 PetscCall(PetscSNPrintf(text, sizeof(text), "weighting=%s\n",
296 ? "sample" : "physical_time"));
297 break;
298 case 3:
299 if (definition->cadence_kind == PICURV_CADENCE_STEP) {
300 PetscCall(PetscSNPrintf(text, sizeof(text), "cadence=step:%" PetscInt_FMT "\n",
301 definition->step_cadence));
302 } else {
303 PetscCall(PetscSNPrintf(text, sizeof(text), "cadence=time:%.17g\n",
304 (double)definition->time_cadence));
305 }
306 break;
307 case 4:
308 for (PetscInt n = 0; n < definition->field_count; ++n) {
309 const PicurvWindowFieldRequest *request = &definition->fields[field_order[n]];
310 const char *name = FieldCanonicalName((FieldId)request->field_id);
311
312 PetscCheck(name != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
313 "Window '%s' requests unknown field id %" PetscInt_FMT ".",
314 definition->name, request->field_id);
315 PetscCall(PetscStrlen(text, &used));
316 PetscCall(PetscSNPrintf(text + used, sizeof(text) - used, "field=%s:%s\n",
317 name, request->want_second ? "first,second" : "first"));
318 }
319 break;
320 case 5:
321 for (PetscInt n = 0; n < definition->covariance_count; ++n) {
322 const PetscInt index = pair_order[n];
323 const char *first = FieldCanonicalName((FieldId)pair_primary[index]);
324 const char *second = FieldCanonicalName((FieldId)pair_secondary[index]);
325
326 PetscCheck(first != NULL && second != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
327 "Window '%s' requests a covariance over an unknown field id.",
328 definition->name);
329 PetscCall(PetscStrlen(text, &used));
330 PetscCall(PetscSNPrintf(text + used, sizeof(text) - used, "covariance=%s,%s\n",
331 first, second));
332 }
333 break;
334 case 6:
335 /* Exactly one mask is resolved, so this group hashes a constant. It
336 * exists so that a future mask key extends this group instead of
337 * renumbering every group after it and invalidating saved state. */
338 PetscCall(PetscSNPrintf(text, sizeof(text), "mask=fluid\n"));
339 break;
340 default:
341 PetscCall(PetscSNPrintf(text, sizeof(text), "target=pointwise\n"));
342 for (PetscInt n = 0; n < definition->field_count; ++n) {
343 const PicurvWindowFieldRequest *request = &definition->fields[field_order[n]];
344 const FieldDescriptor *descriptor = NULL;
345
346 PetscCall(FieldGetDescriptor((FieldId)request->field_id, &descriptor));
347 PetscCall(PetscStrlen(text, &used));
348 PetscCall(PetscSNPrintf(text + used, sizeof(text) - used, "layout=%s:%s\n",
349 descriptor->canonical_name,
350 FieldLayoutName(descriptor->layout)));
351 }
352 break;
353 }
354
355 PetscCall(PetscStrlen(text, &length));
356 PicurvSHA256Update(&whole, text, length);
357 if (group_digest_hex) {
358 PicurvSHA256Init(&part);
359 PicurvSHA256Update(&part, text, length);
360 PicurvSHA256FinalHex(&part, group_digest);
361 PetscCall(PetscStrncpy(group_digest_hex[group], group_digest,
363 }
364 }
365 PicurvSHA256FinalHex(&whole, digest_hex);
367 PetscFunctionReturn(0);
368}
void PicurvSHA256Init(PicurvSHA256Context *context)
Initialize an incremental SHA-256 calculation.
Definition checksum.c:62
void PicurvSHA256Update(PicurvSHA256Context *context, const void *data, size_t length)
Add bytes to an incremental SHA-256 calculation.
Definition checksum.c:74
void PicurvSHA256FinalHex(PicurvSHA256Context *context, char digest_hex[65])
Finish a SHA-256 calculation and return a lowercase hexadecimal digest.
Definition checksum.c:98
Incremental SHA-256 state.
Definition checksum.h:14
FieldLayout layout
const char * FieldCanonicalName(FieldId field_id)
Return the canonical printable name for an ID.
const char * canonical_name
const char * FieldLayoutName(FieldLayout layout)
Return a stable printable label for a field layout.
PetscErrorCode FieldGetDescriptor(FieldId field_id, const FieldDescriptor **descriptor)
Return immutable metadata for a valid field identifier.
FieldId
Compile-time identity for a catalogued Eulerian field.
Immutable metadata for one field identity.
static void SortRequestOrder(PetscInt count, const PetscInt *primary, const PetscInt *secondary, PetscInt *order)
Internal helper: orders request indices so listing order cannot change the hash.
#define PICURV_WINDOW_HASH_GROUP_LENGTH
Stored length of one truncated group digest, including the terminator.
PetscInt first
First member; must also appear in the field list.
PicurvWindowFieldRequest fields[16]
PetscBool want_second
Also keep the centered second moment.
PetscInt second
Second member; must also appear in the field list.
PicurvWindowCovarianceRequest covariances[16]
PetscInt field_id
Catalogued Eulerian field identity.
#define PICURV_WINDOW_MAX_REQUESTS
Maximum fields or covariance pairs one window may request.
One field a window accumulates.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvWindowFirstHashDifference()

PetscErrorCode PicurvWindowFirstHashDifference ( const PicurvWindowDefinition *  definition,
const char *  saved_group_digests,
PetscInt *  group 
)

Implementation of PicurvWindowFirstHashDifference().

Reports which hashed property group first differs from saved group digests.

See also
PicurvWindowFirstHashDifference()

Definition at line 374 of file statistics_window.c.

377{
378 char digest[65];
380 const char *cursor = saved_group_digests;
381
382 PetscFunctionBeginUser;
383 PetscCheck(definition != NULL && group != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
384 "Definition and group output are required.");
385 *group = -1;
386 if (!saved_group_digests) PetscFunctionReturn(0);
387 PetscCall(PicurvWindowComputeHash(definition, digest, current));
388
389 for (PetscInt index = 0; index < PICURV_WINDOW_HASH_GROUP_COUNT; ++index) {
390 const char *comma = strchr(cursor, ',');
391 const size_t length = comma ? (size_t)(comma - cursor) : strlen(cursor);
392 size_t expected = 0;
393
394 PetscCall(PetscStrlen(current[index], &expected));
395 /* Every well-formed digest is fixed width, so a short segment means the
396 * saved list is malformed rather than that this property changed. A
397 * malformed list localizes to nothing: reporting the wrong property would
398 * be worse than reporting none. */
399 if (length != expected) PetscFunctionReturn(0);
400 if (strncmp(cursor, current[index], length)) {
401 *group = index;
402 PetscFunctionReturn(0);
403 }
404 if (!comma) PetscFunctionReturn(0);
405 cursor = comma + 1;
406 }
407 PetscFunctionReturn(0);
408}
PetscErrorCode PicurvWindowComputeHash(const PicurvWindowDefinition *definition, char digest_hex[65], char group_digest_hex[][PICURV_WINDOW_HASH_GROUP_LENGTH])
Implementation of PicurvWindowComputeHash().
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PicurvWindowProgress()

PetscReal PicurvWindowProgress ( const PicurvWindow *  window)

Implementation of PicurvWindowProgress().

Reports the fraction of a bounded window's span that has been represented.

See also
PicurvWindowProgress()

Definition at line 414 of file statistics_window.c.

415{
416 PetscReal span = 0.0;
417
418 if (window == NULL || !window->definition.bounded) return 0.0;
419 span = window->definition.end_time - window->effective_start;
420 if (span <= 0.0) return 0.0;
421 return PetscMin(1.0, window->represented_time / span);
422}
Here is the caller graph for this function:

◆ FieldStatisticsIsActive()

PetscBool FieldStatisticsIsActive ( const SimCtx *  simCtx)

Implementation of FieldStatisticsIsActive().

See also
FieldStatisticsIsActive()

Definition at line 428 of file statistics_window.c.

429{
430 if (!simCtx || !simCtx->fieldStatisticsEnabled) return PETSC_FALSE;
431 return (PetscBool)(simCtx->fieldStatisticsWindowCount > 0 &&
432 simCtx->fieldStatisticsWindows != NULL);
433}
PetscInt fieldStatisticsWindowCount
Definition variables.h:939
PetscBool fieldStatisticsEnabled
Definition variables.h:938
struct PicurvWindow * fieldStatisticsWindows
Definition variables.h:940
Here is the caller graph for this function:

◆ FieldStatisticsUpdateWindows()

PetscErrorCode FieldStatisticsUpdateWindows ( SimCtx *  simCtx,
PetscInt  step,
PetscReal  time 
)

Implementation of FieldStatisticsUpdateWindows().

Offers one completed state to every configured window.

See also
FieldStatisticsUpdateWindows()

Definition at line 441 of file statistics_window.c.

442{
443 PetscFunctionBeginUser;
445 PetscCheck(simCtx != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "SimCtx cannot be NULL.");
446 if (!FieldStatisticsIsActive(simCtx)) { PROFILE_FUNCTION_END; PetscFunctionReturn(0); }
447
448 for (PetscInt window_index = 0; window_index < simCtx->fieldStatisticsWindowCount; ++window_index) {
449 PicurvWindow *window = &simCtx->fieldStatisticsWindows[window_index];
450 const PicurvWindowState before = window->state;
451 PetscBool accepted = PETSC_FALSE;
452 PetscReal weight = 0.0;
453
454 PetscCall(PicurvWindowOfferState(window, step, time, &accepted, &weight));
455
456 if (before == PICURV_WINDOW_PENDING && window->state == PICURV_WINDOW_ACTIVE) {
458 "Statistics window '%s' active from t=%.6g.\n",
459 window->definition.name, (double)window->effective_start);
460 }
461 if (accepted) {
462 /* Apply the accepted weight to every block's accumulators. Windows share
463 * the source state but own independent accumulator state. */
464 for (PetscInt bi = 0; bi < simCtx->block_number; ++bi) {
465 UserCtx *user = &simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user[bi];
466 if (!user->fieldStatisticsStorage) continue;
467 PetscCall(PicurvWindowAccumulate(user, &window->definition,
468 &user->fieldStatisticsStorage[window_index], weight));
469 }
471 "Statistics window '%s' accepted step %d at t=%.6g with weight %.6g "
472 "(samples=%d, represented=%.6g).\n",
473 window->definition.name, step, (double)time, (double)weight,
474 window->sample_count, (double)window->represented_time);
475 } else if (window->state == PICURV_WINDOW_ACTIVE) {
476 /* An active window that took nothing was either off schedule or offered a
477 * zero-length interval. Both are expected, so this is the level that
478 * explains a sample count without implying anything is wrong. */
480 "Statistics window '%s' did not sample step %d at t=%.6g "
481 "(last accepted t=%.6g, samples=%d).\n",
482 window->definition.name, step, (double)time,
483 (double)window->last_accepted_time, window->sample_count);
484 }
485 if (before != PICURV_WINDOW_COMPLETE && window->state == PICURV_WINDOW_COMPLETE) {
487 "Statistics window '%s' complete: %d sample(s), total weight %.6g, "
488 "represented time %.6g.\n",
489 window->definition.name, window->sample_count,
490 (double)window->total_weight, (double)window->represented_time);
491 if (window->sample_count == 0) {
493 "Statistics window '%s' completed without accepting any sample.\n",
494 window->definition.name);
495 } else {
496 UserCtx *user = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
497
498 /* A point that was never valid carries no average at all, which a
499 * reader of the mean field cannot see. Report it once, at the only
500 * moment the final coverage is known. The reduction is collective and
501 * runs once per window, not per step. */
502 if (user && user->fieldStatisticsStorage) {
503 PetscReal lowest = 1.0, highest = 0.0;
504
505 PetscCall(PicurvWindowValidFractionRange(user, &window->definition,
506 &user->fieldStatisticsStorage[window_index],
507 window->sample_count, &lowest, &highest));
508 if (lowest <= 0.0) {
510 "Statistics window '%s' completed with points that were never "
511 "valid; their mean and moments are undefined.\n",
512 window->definition.name);
513 } else {
515 "Statistics window '%s' per-point valid fraction spans [%.3f, %.3f].\n",
516 window->definition.name, (double)lowest, (double)highest);
517 }
518 }
519 }
520 }
521 }
523 PetscFunctionReturn(0);
524}
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:46
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
Definition logging.h:200
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:31
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:30
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:32
PetscErrorCode PicurvWindowValidFractionRange(UserCtx *user, const PicurvWindowDefinition *definition, const PicurvWindowStorage *storage, PetscInt sample_count, PetscReal *minimum, PetscReal *maximum)
Reports the range of per-point valid fraction across a window's domain.
PetscErrorCode PicurvWindowAccumulate(UserCtx *user, const PicurvWindowDefinition *definition, PicurvWindowStorage *storage, PetscReal weight)
Applies one accepted completed state to a window's accumulators.
PetscBool FieldStatisticsIsActive(const SimCtx *simCtx)
Implementation of FieldStatisticsIsActive().
PetscErrorCode PicurvWindowOfferState(PicurvWindow *window, PetscInt step, PetscReal time, PetscBool *accepted, PetscReal *weight)
Implementation of PicurvWindowOfferState().
PicurvWindowState
Lifecycle state of one window.
Runtime state of one window.
UserCtx * user
Definition variables.h:736
PetscInt block_number
Definition variables.h:960
UserMG usermg
Definition variables.h:1019
PetscInt mglevels
Definition variables.h:743
struct PicurvWindowStorage * fieldStatisticsStorage
Definition variables.h:1136
MGCtx * mgctx
Definition variables.h:746
User-defined context containing data specific to a single computational grid level.
Definition variables.h:1073
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ kHashGroupNames

const char* const kHashGroupNames[PICURV_WINDOW_HASH_GROUP_COUNT]
static
Initial value:
= {
"name", "start_time", "weighting", "cadence", "fields", "covariances", "mask", "target"
}

Stable names of the hashed property groups, in serialization order.

Definition at line 189 of file statistics_window.c.

189 {
190 "name", "start_time", "weighting", "cadence", "fields", "covariances", "mask", "target"
191};