PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
statistics_moments.c
Go to the documentation of this file.
1/**
2 * @file statistics_moments.c
3 * @brief Weighted centered-moment kernels for the field-statistics pipeline.
4 *
5 * Full API contract is documented with the declarations in
6 * `include/statistics_moments.h`.
7 */
8
10
11/**
12 * @brief Implementation of \ref PicurvMomentStateReset().
13 * @see PicurvMomentStateReset()
14 */
16{
17 if (state == NULL) return;
18 state->count = 0.0;
19 state->weight = 0.0;
20 state->weight_sq = 0.0;
21 state->mean = 0.0;
22 state->m2 = 0.0;
23}
24
25/**
26 * @brief Implementation of \ref PicurvCoMomentStateReset().
27 * @see PicurvCoMomentStateReset()
28 */
30{
31 if (state == NULL) return;
32 state->count = 0.0;
33 state->weight = 0.0;
34 state->weight_sq = 0.0;
35 state->mean_x = 0.0;
36 state->mean_y = 0.0;
37 state->cm = 0.0;
38}
39
40/**
41 * @brief Implementation of \ref PicurvMomentStateUpdate().
42 * @see PicurvMomentStateUpdate()
43 */
44PetscErrorCode PicurvMomentStateUpdate(PicurvMomentState *state, PetscReal value, PetscReal weight)
45{
46 PetscReal new_weight = 0.0;
47 PetscReal delta = 0.0;
48
49 PetscFunctionBeginUser;
50 PetscCheck(state != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
51 "Moment accumulator is required.");
52 PetscCheck(weight > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
53 "Sample weight must be strictly positive, got %g.", (double)weight);
54
55 new_weight = state->weight + weight;
56 delta = value - state->mean;
57 state->mean += (weight / new_weight) * delta;
58 /* Uses the post-update mean deliberately: this is the pairing that keeps the
59 * centered sum stable when the mean is large relative to the fluctuation. */
60 state->m2 += weight * delta * (value - state->mean);
61 state->weight = new_weight;
62 state->weight_sq += weight * weight;
63 state->count += 1.0;
64 PetscFunctionReturn(0);
65}
66
67/**
68 * @brief Implementation of \ref PicurvCoMomentStateUpdate().
69 * @see PicurvCoMomentStateUpdate()
70 */
72 PetscReal value_x, PetscReal value_y, PetscReal weight)
73{
74 PetscReal new_weight = 0.0;
75 PetscReal delta_x = 0.0;
76
77 PetscFunctionBeginUser;
78 PetscCheck(state != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
79 "Co-moment accumulator is required.");
80 PetscCheck(weight > 0.0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
81 "Sample weight must be strictly positive, got %g.", (double)weight);
82
83 new_weight = state->weight + weight;
84 delta_x = value_x - state->mean_x;
85 state->mean_x += (weight / new_weight) * delta_x;
86 state->mean_y += (weight / new_weight) * (value_y - state->mean_y);
87 /* Pre-update mean of x against post-update mean of y. With x == y this
88 * reduces exactly to the M2 update, which the unit tests assert. */
89 state->cm += weight * delta_x * (value_y - state->mean_y);
90 state->weight = new_weight;
91 state->weight_sq += weight * weight;
92 state->count += 1.0;
93 PetscFunctionReturn(0);
94}
95
96/**
97 * @brief Implementation of \ref PicurvMomentStateMerge().
98 * @see PicurvMomentStateMerge()
99 */
101 const PicurvMomentState *a, const PicurvMomentState *b)
102{
103 PetscReal total_weight = 0.0;
104 PetscReal delta = 0.0;
105 PicurvMomentState merged;
106
107 PetscFunctionBeginUser;
108 PetscCheck(result != NULL && a != NULL && b != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
109 "Merge requires a destination and two source accumulators.");
110
111 if (b->weight == 0.0) { *result = *a; PetscFunctionReturn(0); }
112 if (a->weight == 0.0) { *result = *b; PetscFunctionReturn(0); }
113
114 total_weight = a->weight + b->weight;
115 delta = b->mean - a->mean;
116 merged.count = a->count + b->count;
117 merged.weight = total_weight;
118 merged.weight_sq = a->weight_sq + b->weight_sq;
119 merged.mean = a->mean + (b->weight / total_weight) * delta;
120 merged.m2 = a->m2 + b->m2 + (a->weight * b->weight / total_weight) * delta * delta;
121 *result = merged;
122 PetscFunctionReturn(0);
123}
124
125/**
126 * @brief Implementation of \ref PicurvCoMomentStateMerge().
127 * @see PicurvCoMomentStateMerge()
128 */
130 const PicurvCoMomentState *a, const PicurvCoMomentState *b)
131{
132 PetscReal total_weight = 0.0;
133 PetscReal delta_x = 0.0;
134 PetscReal delta_y = 0.0;
135 PicurvCoMomentState merged;
136
137 PetscFunctionBeginUser;
138 PetscCheck(result != NULL && a != NULL && b != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
139 "Merge requires a destination and two source accumulators.");
140
141 if (b->weight == 0.0) { *result = *a; PetscFunctionReturn(0); }
142 if (a->weight == 0.0) { *result = *b; PetscFunctionReturn(0); }
143
144 total_weight = a->weight + b->weight;
145 delta_x = b->mean_x - a->mean_x;
146 delta_y = b->mean_y - a->mean_y;
147 merged.count = a->count + b->count;
148 merged.weight = total_weight;
149 merged.weight_sq = a->weight_sq + b->weight_sq;
150 merged.mean_x = a->mean_x + (b->weight / total_weight) * delta_x;
151 merged.mean_y = a->mean_y + (b->weight / total_weight) * delta_y;
152 merged.cm = a->cm + b->cm + (a->weight * b->weight / total_weight) * delta_x * delta_y;
153 *result = merged;
154 PetscFunctionReturn(0);
155}
156
157/**
158 * @brief Implementation of \ref PicurvMomentStateVariance().
159 * @see PicurvMomentStateVariance()
160 */
162{
163 if (state == NULL || state->weight == 0.0) return 0.0;
164 return state->m2 / state->weight;
165}
166
167/**
168 * @brief Implementation of \ref PicurvCoMomentStateCovariance().
169 * @see PicurvCoMomentStateCovariance()
170 */
172{
173 if (state == NULL || state->weight == 0.0) return 0.0;
174 return state->cm / state->weight;
175}
176
177/**
178 * @brief Implementation of \ref PicurvMomentStateEffectiveCount().
179 * @see PicurvMomentStateEffectiveCount()
180 */
182{
183 if (state == NULL || state->weight_sq == 0.0) return 0.0;
184 return (state->weight * state->weight) / state->weight_sq;
185}
PetscErrorCode PicurvMomentStateMerge(PicurvMomentState *result, const PicurvMomentState *a, const PicurvMomentState *b)
Implementation of PicurvMomentStateMerge().
PetscErrorCode PicurvCoMomentStateUpdate(PicurvCoMomentState *state, PetscReal value_x, PetscReal value_y, PetscReal weight)
Implementation of PicurvCoMomentStateUpdate().
PetscErrorCode PicurvCoMomentStateMerge(PicurvCoMomentState *result, const PicurvCoMomentState *a, const PicurvCoMomentState *b)
Implementation of PicurvCoMomentStateMerge().
PetscReal PicurvMomentStateEffectiveCount(const PicurvMomentState *state)
Implementation of PicurvMomentStateEffectiveCount().
void PicurvCoMomentStateReset(PicurvCoMomentState *state)
Implementation of PicurvCoMomentStateReset().
PetscReal PicurvMomentStateVariance(const PicurvMomentState *state)
Implementation of PicurvMomentStateVariance().
PetscReal PicurvCoMomentStateCovariance(const PicurvCoMomentState *state)
Implementation of PicurvCoMomentStateCovariance().
void PicurvMomentStateReset(PicurvMomentState *state)
Implementation of PicurvMomentStateReset().
PetscErrorCode PicurvMomentStateUpdate(PicurvMomentState *state, PetscReal value, PetscReal weight)
Implementation of PicurvMomentStateUpdate().
Weighted centered-moment kernels for the field-statistics pipeline.
PetscReal weight_sq
Sum of squared weights W2.
PetscReal weight_sq
Sum of squared weights W2.
PetscReal mean_y
Weighted mean of the second member.
PetscReal weight
Total weight W.
PetscReal count
Number of accepted samples.
PetscReal cm
Centered co-moment sum C.
PetscReal m2
Centered second-moment sum M2.
PetscReal mean
Weighted mean mu.
PetscReal mean_x
Weighted mean of the first member.
PetscReal weight
Total weight W.
PetscReal count
Number of accepted samples.
Weighted centered co-moment state for one ordered pair of quantities.
Weighted centered state for one scalar quantity at one point.