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

Configured initial values of particle-carried fields. More...

#include "ParticleInitialConditions.h"
#include <math.h>
#include <stdint.h>
#include "logging.h"
Include dependency graph for ParticleInitialConditions.c:

Go to the source code of this file.

Data Structures

struct  ParticleFieldBinding
 One configured field: its identity and one expression per component. More...
 
struct  ParticleFieldPlan
 

Macros

#define PARTICLE_VARIABLE_PID   ((PetscInt)PICURV_SOURCE_VAR_CELL_COUNT)
 
#define PARTICLE_VARIABLE_COUNT   (PARTICLE_VARIABLE_PID + 1)
 
#define PARTICLE_FIELD_MAX_COMPONENTS   3
 
#define PARTICLE_FIELD_EXPRESSION_LENGTH   4096
 
#define PARTICLE_FIELD_HISTOGRAM_BINS   10
 

Functions

PetscErrorCode ParticleFieldPlanCreate (const char *prefix, ParticleFieldPlan **plan)
 Implementation of ParticleFieldPlanCreate().
 
static PetscErrorCode PlanReadsGridLines (const ParticleFieldPlan *plan, PetscBool *reads)
 Whether any configured expression reads a grid line's fraction or length.
 
PetscErrorCode ParticleFieldPlanApply (UserCtx *user, ParticleFieldPlan *plan, const ParticleFieldEvent *event, PetscInt first, PetscInt end)
 Implementation of ParticleFieldPlanApply().
 
PetscErrorCode ParticleFieldPlanSummarize (UserCtx *user, const ParticleFieldPlan *plan)
 Implementation of ParticleFieldPlanSummarize().
 
PetscErrorCode ParticleFieldPlanDestroy (ParticleFieldPlan **plan)
 Implementation of ParticleFieldPlanDestroy().
 

Variables

static const char *const kParticleVariables [] = {"x", "y", "z", "t", "xi", "eta", "zeta", "L_xi", "L_eta", "L_zeta", "pid"}
 Names a particle expression may use: those of every source (PicurvSourceVariable), then pid.
 

Detailed Description

Configured initial values of particle-carried fields.

Each field's expressions are compiled once by the shared engine (expression.c) and evaluated per particle. Draws are keyed on the particle's identity, so a value does not depend on rank count, particle order, or how often it is evaluated.

Definition in file ParticleInitialConditions.c.


Data Structure Documentation

◆ ParticleFieldBinding

struct ParticleFieldBinding

One configured field: its identity and one expression per component.

Definition at line 30 of file ParticleInitialConditions.c.

Collaboration diagram for ParticleFieldBinding:
[legend]
Data Fields
ParticleFieldId field
PetscInt components
PicurvExpression * component[3]

◆ ParticleFieldPlan

struct ParticleFieldPlan

Definition at line 36 of file ParticleInitialConditions.c.

Collaboration diagram for ParticleFieldPlan:
[legend]
Data Fields
PetscInt count
ParticleFieldBinding * bindings
Vec local_fraction Grid-line fractions, computed once when an expression first reads them.
Vec local_length Grid-line lengths, likewise.

Macro Definition Documentation

◆ PARTICLE_VARIABLE_PID

#define PARTICLE_VARIABLE_PID   ((PetscInt)PICURV_SOURCE_VAR_CELL_COUNT)

Definition at line 23 of file ParticleInitialConditions.c.

◆ PARTICLE_VARIABLE_COUNT

#define PARTICLE_VARIABLE_COUNT   (PARTICLE_VARIABLE_PID + 1)

Definition at line 24 of file ParticleInitialConditions.c.

◆ PARTICLE_FIELD_MAX_COMPONENTS

#define PARTICLE_FIELD_MAX_COMPONENTS   3

Definition at line 25 of file ParticleInitialConditions.c.

◆ PARTICLE_FIELD_EXPRESSION_LENGTH

#define PARTICLE_FIELD_EXPRESSION_LENGTH   4096

Definition at line 26 of file ParticleInitialConditions.c.

◆ PARTICLE_FIELD_HISTOGRAM_BINS

#define PARTICLE_FIELD_HISTOGRAM_BINS   10

Definition at line 27 of file ParticleInitialConditions.c.

Function Documentation

◆ ParticleFieldPlanCreate()

PetscErrorCode ParticleFieldPlanCreate ( const char *  prefix,
ParticleFieldPlan **  plan 
)

Implementation of ParticleFieldPlanCreate().

Read a plan from the options database.

See also
ParticleFieldPlanCreate()

Definition at line 47 of file ParticleInitialConditions.c.

48{
49 PetscInt count = 0;
50 PetscBool found = PETSC_FALSE;
51 char option[256];
52
53 PetscFunctionBeginUser;
55 PetscCheck(plan, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Plan output is required.");
56 *plan = NULL;
57 PetscCall(PetscSNPrintf(option, sizeof(option), "-%s_count", prefix));
58 PetscCall(PetscOptionsGetInt(NULL, NULL, option, &count, &found));
59 if (!found || count == 0) { PROFILE_FUNCTION_END; PetscFunctionReturn(0); }
60 PetscCheck(count > 0 && count <= PARTICLE_FIELD_ID_COUNT, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
61 "%s must be between 0 and %d (got %" PetscInt_FMT ").", option, (int)PARTICLE_FIELD_ID_COUNT, count);
62
63 PetscCall(PetscNew(plan));
64 PetscCall(PetscCalloc1(count, &(*plan)->bindings));
65 (*plan)->count = count;
66 for (PetscInt i = 0; i < count; ++i) {
67 ParticleFieldBinding *binding = &(*plan)->bindings[i];
68 const ParticleFieldDescriptor *descriptor = NULL;
69 char name[64];
70
71 PetscCall(PetscSNPrintf(option, sizeof(option), "-%s_%" PetscInt_FMT "_name", prefix, i));
72 PetscCall(PetscOptionsGetString(NULL, NULL, option, name, sizeof(name), &found));
73 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "%s is missing.", option);
74 PetscCall(ParticleFieldIdFromName(name, &binding->field));
75 PetscCall(ParticleFieldGetDescriptor(binding->field, &descriptor));
76 PetscCheck(descriptor->capabilities & PARTICLE_FIELD_CAPABILITY_USER_INITIALIZE, PETSC_COMM_WORLD,
77 PETSC_ERR_ARG_WRONG,
78 "Particle field '%s' cannot be given an initial value: the runtime sets it from the "
79 "Eulerian fields or from particle location.", name);
80 PetscCheck(descriptor->dimension.kind == FIELD_DIMENSION_FIXED && descriptor->data_type == PETSC_REAL,
81 PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Settable particle field '%s' must be a real quantity.", name);
82 for (PetscInt j = 0; j < i; ++j) {
83 PetscCheck((*plan)->bindings[j].field != binding->field, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
84 "Particle field '%s' is configured twice.", name);
85 }
86 binding->components = descriptor->components;
87 PetscCheck(binding->components <= PARTICLE_FIELD_MAX_COMPONENTS, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
88 "Particle field '%s' has more components than an initial value supports.", name);
89 for (PetscInt c = 0; c < binding->components; ++c) {
91
92 PetscCall(PetscSNPrintf(option, sizeof(option), "-%s_%" PetscInt_FMT "_expr_%" PetscInt_FMT, prefix, i, c));
93 PetscCall(PetscOptionsGetString(NULL, NULL, option, text, sizeof(text), &found));
94 PetscCheck(found, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "%s is missing.", option);
96 &binding->component[c]));
97 }
98 }
100 PetscFunctionReturn(0);
101}
static const char *const kParticleVariables[]
Names a particle expression may use: those of every source (PicurvSourceVariable),...
#define PARTICLE_VARIABLE_COUNT
#define PARTICLE_FIELD_MAX_COMPONENTS
PicurvExpression * component[3]
#define PARTICLE_FIELD_EXPRESSION_LENGTH
One configured field: its identity and one expression per component.
PetscErrorCode PicurvExpressionCompile(const char *text, const char *const *names, PetscInt name_count, PetscBool allow_random, PicurvExpression **expression)
Compile one expression against a list of variable names.
Definition expression.c:551
@ FIELD_DIMENSION_FIXED
The exponents are the field's dimension.
FieldDimensionKind kind
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:1029
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled function: an always-on aggregate timer.
Definition logging.h:1000
@ PARTICLE_FIELD_ID_COUNT
PetscErrorCode ParticleFieldIdFromName(const char *field_name, ParticleFieldId *field_id)
Resolve a canonical name or registered alias at a text-ingress boundary.
@ PARTICLE_FIELD_CAPABILITY_USER_INITIALIZE
The particle carries the value, so a configured initial value survives: nothing re-derives it from th...
PetscErrorCode ParticleFieldGetDescriptor(ParticleFieldId field_id, const ParticleFieldDescriptor **descriptor)
Return immutable metadata for a valid particle field ID.
Immutable metadata for one persistent particle field.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PlanReadsGridLines()

static PetscErrorCode PlanReadsGridLines ( const ParticleFieldPlan *  plan,
PetscBool *  reads 
)
static

Whether any configured expression reads a grid line's fraction or length.

Definition at line 104 of file ParticleInitialConditions.c.

105{
106 PetscFunctionBeginUser;
108 *reads = PETSC_FALSE;
109 for (PetscInt b = 0; b < plan->count; ++b)
110 for (PetscInt c = 0; c < plan->bindings[b].components; ++c)
111 for (PetscInt var = PICURV_SOURCE_VAR_XI; var <= PICURV_SOURCE_VAR_L_ZETA; ++var) {
112 PetscBool uses = PETSC_FALSE;
113 PetscCall(PicurvExpressionUsesVariable(plan->bindings[b].component[c], var, &uses));
114 if (uses) *reads = PETSC_TRUE;
115 }
117 PetscFunctionReturn(0);
118}
ParticleFieldBinding * bindings
@ PICURV_SOURCE_VAR_L_ZETA
Physical length of that zeta grid line [m].
Definition expression.h:168
@ PICURV_SOURCE_VAR_XI
Arc-length fraction along the xi grid line, 0 at the - face.
Definition expression.h:163
PetscErrorCode PicurvExpressionUsesVariable(const PicurvExpression *expression, PetscInt index, PetscBool *uses)
Whether a compiled expression reads one of its variables.
Definition expression.c:847
#define PROFILE_HELPER_BEGIN
Marks the beginning of a profiled helper: timed only when enabled by name.
Definition logging.h:1014
#define PROFILE_HELPER_END
Alias of PROFILE_FUNCTION_END for a function that began with PROFILE_HELPER_BEGIN.
Definition logging.h:1033
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ParticleFieldPlanApply()

PetscErrorCode ParticleFieldPlanApply ( UserCtx *  user,
ParticleFieldPlan *  plan,
const ParticleFieldEvent *  event,
PetscInt  first,
PetscInt  end 
)

Implementation of ParticleFieldPlanApply().

Write the plan's values into swarm entries [first, end) of this rank.

See also
ParticleFieldPlanApply()

Definition at line 124 of file ParticleInitialConditions.c.

126{
127 SimCtx *simCtx = NULL;
128 const PetscReal *positions = NULL, *weights = NULL;
129 const PetscInt64 *pids = NULL;
130 const PetscInt *cells = NULL;
131 PetscBool grid_lines = PETSC_FALSE;
132 const Cmpnts ***frac = NULL, ***len = NULL, ***csi = NULL, ***eta = NULL, ***zet = NULL;
133 const PetscReal ***aj = NULL;
134
135 PetscFunctionBeginUser;
137 if (!plan) { PROFILE_FUNCTION_END; PetscFunctionReturn(0); }
138 PetscCheck(user && event, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Context and event are required.");
139 simCtx = user->simCtx;
140 /* Before the empty-range return: the fractions are collective, and a rank may hold no particle. */
141 PetscCall(PlanReadsGridLines(plan, &grid_lines));
142 if (grid_lines && !plan->local_fraction) {
143 Vec fraction = NULL, length = NULL;
144 PetscCall(DMCreateGlobalVector(user->fda, &fraction));
145 PetscCall(DMCreateGlobalVector(user->fda, &length));
146 PetscCall(ComputeGridLineFractions(user, fraction, length));
147 PetscCall(DMCreateLocalVector(user->fda, &plan->local_fraction));
148 PetscCall(DMCreateLocalVector(user->fda, &plan->local_length));
149 PetscCall(DMGlobalToLocalBegin(user->fda, fraction, INSERT_VALUES, plan->local_fraction));
150 PetscCall(DMGlobalToLocalEnd(user->fda, fraction, INSERT_VALUES, plan->local_fraction));
151 PetscCall(DMGlobalToLocalBegin(user->fda, length, INSERT_VALUES, plan->local_length));
152 PetscCall(DMGlobalToLocalEnd(user->fda, length, INSERT_VALUES, plan->local_length));
153 PetscCall(VecDestroy(&length));
154 PetscCall(VecDestroy(&fraction));
155 }
156 if (end > first) {
157 PetscCheck(user->swarm, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Swarm is required.");
158 PetscCall(DMSwarmGetField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_POSITION), NULL, NULL, (void **)&positions));
159 PetscCall(DMSwarmGetField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_PID), NULL, NULL, (void **)&pids));
160 if (grid_lines) {
161 PetscCall(DMSwarmGetField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_CELL_ID), NULL, NULL, (void **)&cells));
162 PetscCall(DMSwarmGetField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_WEIGHT), NULL, NULL, (void **)&weights));
163 PetscCall(DMDAVecGetArrayRead(user->fda, plan->local_fraction, &frac));
164 PetscCall(DMDAVecGetArrayRead(user->fda, plan->local_length, &len));
165 PetscCall(DMDAVecGetArrayRead(user->fda, user->lCsi, &csi));
166 PetscCall(DMDAVecGetArrayRead(user->fda, user->lEta, &eta));
167 PetscCall(DMDAVecGetArrayRead(user->fda, user->lZet, &zet));
168 PetscCall(DMDAVecGetArrayRead(user->da, user->lAj, &aj));
169 }
170 for (PetscInt b = 0; b < plan->count; ++b) {
171 const ParticleFieldBinding *binding = &plan->bindings[b];
172 const ParticleFieldDescriptor *descriptor = NULL;
173 PetscReal *field = NULL, scale = 1.0;
174
175 PetscCall(ParticleFieldGetDescriptor(binding->field, &descriptor));
176 /* A value is physical; the swarm stores solver units. */
177 PetscCall(FieldDimensionReferenceScale(&simCtx->scaling, descriptor->dimension, &scale));
178 PetscCall(DMSwarmGetField(user->swarm, descriptor->canonical_name, NULL, NULL, (void **)&field));
179 for (PetscInt p = first; p < end; ++p) {
180 const PetscReal *position = &positions[3 * p];
181 const Cmpnts point = {position[0], position[1], position[2]};
182 const PicurvExpressionDrawKey key = {
183 (PetscInt64)simCtx->particleRandomSeed, pids[p], event->salt, (PetscInt64)binding->field,
184 };
185 PetscReal values[PARTICLE_VARIABLE_COUNT] = {0.0};
186
187 values[PICURV_SOURCE_VAR_X] = position[0] * simCtx->scaling.L_ref;
188 values[PICURV_SOURCE_VAR_Y] = position[1] * simCtx->scaling.L_ref;
189 values[PICURV_SOURCE_VAR_Z] = position[2] * simCtx->scaling.L_ref;
190 if (grid_lines) {
191 /* The host cell in cell-centred numbering; a line's fraction is known at the
192 cell's centre, and moves with the particle by its share of the cell's edge. */
193 const PetscInt i = cells[3 * p] + 1, j = cells[3 * p + 1] + 1, k = cells[3 * p + 2] + 1;
194 const PetscReal lengths[3] = {len[k][j][i].x, len[k][j][i].y, len[k][j][i].z};
195 Cmpnts edges[3];
196
197 PicurvSourceSetVariables(values, point, frac[k][j][i], len[k][j][i], simCtx->scaling.L_ref);
198 PetscCall(ComputeCellEdgeVectors(aj[k][j][i], csi[k][j][i], eta[k][j][i], zet[k][j][i], edges));
199 for (PetscInt a = 0; a < 3; ++a) {
200 const PetscReal ds = PetscSqrtReal(edges[a].x * edges[a].x + edges[a].y * edges[a].y + edges[a].z * edges[a].z);
201 values[PICURV_SOURCE_VAR_XI + a] += (weights[3 * p + a] - 0.5) * ds / lengths[a];
202 }
203 }
204 values[PICURV_SOURCE_VAR_T] = event->physical_time;
205 values[PARTICLE_VARIABLE_PID] = (PetscReal)pids[p];
206 for (PetscInt c = 0; c < binding->components; ++c) {
207 PetscReal value = 0.0;
208
209 PetscCall(PicurvExpressionEvaluate(binding->component[c], values, &key, &value));
210 PetscCheck(!PetscIsInfOrNanReal(value), PETSC_COMM_SELF, PETSC_ERR_FP,
211 "The initial value of '%s' is not finite for particle %lld at (%g, %g, %g).",
212 descriptor->canonical_name, (long long)pids[p], (double)values[0],
213 (double)values[1], (double)values[2]);
214 field[binding->components * p + c] = value / scale;
215 }
216 }
217 PetscCall(DMSwarmRestoreField(user->swarm, descriptor->canonical_name, NULL, NULL, (void **)&field));
218 }
219 if (grid_lines) {
220 PetscCall(DMDAVecRestoreArrayRead(user->da, user->lAj, &aj));
221 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lZet, &zet));
222 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lEta, &eta));
223 PetscCall(DMDAVecRestoreArrayRead(user->fda, user->lCsi, &csi));
224 PetscCall(DMDAVecRestoreArrayRead(user->fda, plan->local_length, &len));
225 PetscCall(DMDAVecRestoreArrayRead(user->fda, plan->local_fraction, &frac));
226 PetscCall(DMSwarmRestoreField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_WEIGHT), NULL, NULL, (void **)&weights));
227 PetscCall(DMSwarmRestoreField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_CELL_ID), NULL, NULL, (void **)&cells));
228 }
229 PetscCall(DMSwarmRestoreField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_PID), NULL, NULL, (void **)&pids));
230 PetscCall(DMSwarmRestoreField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_POSITION), NULL, NULL, (void **)&positions));
231 }
233 PetscFunctionReturn(0);
234}
PetscErrorCode ComputeCellEdgeVectors(PetscReal ajc, Cmpnts csi, Cmpnts eta, Cmpnts zet, Cmpnts edges[3])
Computes a cell's edge vectors along its three grid directions.
Definition Metric.c:749
PetscErrorCode ComputeGridLineFractions(UserCtx *user, Vec fraction, Vec length)
Arc-length position of every owned cell centre along its three grid lines.
Definition Metric.c:1362
#define PARTICLE_VARIABLE_PID
static PetscErrorCode PlanReadsGridLines(const ParticleFieldPlan *plan, PetscBool *reads)
Whether any configured expression reads a grid line's fraction or length.
Vec local_fraction
Grid-line fractions, computed once when an expression first reads them.
Vec local_length
Grid-line lengths, likewise.
PetscInt64 salt
Event identity keying random draws: 0 for the t=0 population.
PetscErrorCode PicurvExpressionEvaluate(const PicurvExpression *expression, const PetscReal *values, const PicurvExpressionDrawKey *key, PetscReal *result)
Evaluate a compiled expression.
Definition expression.c:724
@ PICURV_SOURCE_VAR_T
Physical time [s].
Definition expression.h:162
@ PICURV_SOURCE_VAR_Y
Physical y [m].
Definition expression.h:160
@ PICURV_SOURCE_VAR_X
Physical x of the point [m].
Definition expression.h:159
@ PICURV_SOURCE_VAR_Z
Physical z [m].
Definition expression.h:161
static void PicurvSourceSetVariables(PetscReal *values, Cmpnts point, Cmpnts fraction, Cmpnts length, PetscReal L_ref)
Fill a source's position and grid-line variables at one point.
Definition expression.h:252
What a random draw is keyed on, besides its stream.
Definition expression.h:85
PetscErrorCode FieldDimensionReferenceScale(const ScalingCtx *scaling, FieldDimension dimension, PetscReal *scale)
Return the factor that turns a solver value of one dimension into physical units.
const char * ParticleFieldName(ParticleFieldId field_id)
Return the canonical PETSc DMSwarm name for an ID.
@ PARTICLE_FIELD_ID_WEIGHT
@ PARTICLE_FIELD_ID_POSITION
@ PARTICLE_FIELD_ID_PID
@ PARTICLE_FIELD_ID_CELL_ID
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:1160
PetscReal L_ref
Definition variables.h:898
ScalingCtx scaling
Definition variables.h:1003
PetscInt particleRandomSeed
Base seed for every particle RNG stream (-particle_random_seed).
Definition variables.h:1050
A 3D point or vector with PetscScalar components.
Definition variables.h:144
The master context for the entire simulation.
Definition variables.h:916
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ParticleFieldPlanSummarize()

PetscErrorCode ParticleFieldPlanSummarize ( UserCtx *  user,
const ParticleFieldPlan *  plan 
)

Implementation of ParticleFieldPlanSummarize().

Log and record the realized initial values of every planned field.

See also
ParticleFieldPlanSummarize()

Definition at line 240 of file ParticleInitialConditions.c.

241{
242 SimCtx *simCtx = NULL;
243 FILE *csv = NULL;
244 PetscInt nlocal = 0;
245
246 PetscFunctionBeginUser;
248 if (!plan) { PROFILE_FUNCTION_END; PetscFunctionReturn(0); }
249 simCtx = user->simCtx;
250 PetscCall(DMSwarmGetLocalSize(user->swarm, &nlocal));
251 if (simCtx->rank == 0) {
252 char path[PETSC_MAX_PATH_LEN];
253
254 PetscCall(PetscSNPrintf(path, sizeof(path), "%s/particle_initial_fields.csv", simCtx->analysis_dir));
255 csv = fopen(path, "w");
256 if (!csv) {
257 LOG_ALLOW(GLOBAL, LOG_WARNING, "Could not write '%s'.\n", path);
258 } else {
259 fprintf(csv, "field,component,count,mean,variance,min,max");
260 for (int bin = 0; bin < PARTICLE_FIELD_HISTOGRAM_BINS; ++bin) fprintf(csv, ",bin_%d", bin);
261 fprintf(csv, "\n");
262 }
263 }
264
265 for (PetscInt b = 0; b < plan->count; ++b) {
266 const ParticleFieldBinding *binding = &plan->bindings[b];
267 const ParticleFieldDescriptor *descriptor = NULL;
268 const PetscReal *field = NULL;
269 PetscReal scale = 1.0;
270
271 PetscCall(ParticleFieldGetDescriptor(binding->field, &descriptor));
272 PetscCall(FieldDimensionReferenceScale(&simCtx->scaling, descriptor->dimension, &scale));
273 PetscCall(DMSwarmGetField(user->swarm, descriptor->canonical_name, NULL, NULL, (void **)&field));
274 for (PetscInt c = 0; c < binding->components; ++c) {
275 /* Sums and extremes in one reduction, then a histogram over the global range. */
276 PetscReal sums[3] = {0.0, 0.0, 0.0}, extremes[2] = {PETSC_MAX_REAL, PETSC_MAX_REAL};
277 PetscReal bins_local[PARTICLE_FIELD_HISTOGRAM_BINS] = {0.0}, bins[PARTICLE_FIELD_HISTOGRAM_BINS];
278
279 for (PetscInt p = 0; p < nlocal; ++p) {
280 const PetscReal value = field[binding->components * p + c] * scale;
281 sums[0] += 1.0;
282 sums[1] += value;
283 sums[2] += value * value;
284 extremes[0] = PetscMin(extremes[0], value);
285 extremes[1] = PetscMin(extremes[1], -value);
286 }
287 PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, sums, 3, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD));
288 PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, extremes, 2, MPIU_REAL, MPI_MIN, PETSC_COMM_WORLD));
289 const PetscReal count = sums[0], lowest = extremes[0], highest = -extremes[1];
290 const PetscReal mean = (count > 0.0) ? sums[1] / count : 0.0;
291 const PetscReal variance = (count > 0.0) ? PetscMax(sums[2] / count - mean * mean, 0.0) : 0.0;
292 const PetscReal width = (highest > lowest) ? (highest - lowest) / PARTICLE_FIELD_HISTOGRAM_BINS : 1.0;
293
294 for (PetscInt p = 0; p < nlocal; ++p) {
295 const PetscReal value = field[binding->components * p + c] * scale;
296 PetscInt bin = (PetscInt)((value - lowest) / width);
297 bins_local[PetscMax(0, PetscMin(bin, PARTICLE_FIELD_HISTOGRAM_BINS - 1))] += 1.0;
298 }
299 PetscCallMPI(MPI_Allreduce(bins_local, bins, PARTICLE_FIELD_HISTOGRAM_BINS, MPIU_REAL, MPI_SUM,
300 PETSC_COMM_WORLD));
302 "[Particle IC] %s[%" PetscInt_FMT "]: n=%.0f mean=%.6g var=%.6g min=%.6g max=%.6g\n",
303 descriptor->canonical_name, c, (double)count, (double)mean, (double)variance,
304 (double)(count > 0.0 ? lowest : 0.0), (double)(count > 0.0 ? highest : 0.0));
305 if (csv) {
306 fprintf(csv, "%s,%d,%.0f,%.10e,%.10e,%.10e,%.10e", descriptor->canonical_name, (int)c,
307 (double)count, (double)mean, (double)variance,
308 (double)(count > 0.0 ? lowest : 0.0), (double)(count > 0.0 ? highest : 0.0));
309 for (int bin = 0; bin < PARTICLE_FIELD_HISTOGRAM_BINS; ++bin) fprintf(csv, ",%.0f", (double)bins[bin]);
310 fprintf(csv, "\n");
311 }
312 }
313 PetscCall(DMSwarmRestoreField(user->swarm, descriptor->canonical_name, NULL, NULL, (void **)&field));
314 }
315 if (csv) fclose(csv);
317 PetscFunctionReturn(0);
318}
#define PARTICLE_FIELD_HISTOGRAM_BINS
#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:214
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:31
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:30
PetscMPIInt rank
Definition variables.h:919
char analysis_dir[PETSC_MAX_PATH_LEN]
Definition variables.h:942
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ParticleFieldPlanDestroy()

PetscErrorCode ParticleFieldPlanDestroy ( ParticleFieldPlan **  plan)

Implementation of ParticleFieldPlanDestroy().

Free a plan and its compiled expressions.

See also
ParticleFieldPlanDestroy()

Definition at line 324 of file ParticleInitialConditions.c.

325{
326 PetscFunctionBeginUser;
328 if (!plan || !*plan) { PROFILE_HELPER_END; PetscFunctionReturn(0); }
329 for (PetscInt b = 0; b < (*plan)->count; ++b) {
330 for (PetscInt c = 0; c < PARTICLE_FIELD_MAX_COMPONENTS; ++c) {
331 PetscCall(PicurvExpressionDestroy(&(*plan)->bindings[b].component[c]));
332 }
333 }
334 PetscCall(VecDestroy(&(*plan)->local_length));
335 PetscCall(VecDestroy(&(*plan)->local_fraction));
336 PetscCall(PetscFree((*plan)->bindings));
337 PetscCall(PetscFree(*plan));
339 PetscFunctionReturn(0);
340}
PetscErrorCode PicurvExpressionDestroy(PicurvExpression **expression)
Free a compiled expression.
Definition expression.c:818
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ kParticleVariables

const char* const kParticleVariables[] = {"x", "y", "z", "t", "xi", "eta", "zeta", "L_xi", "L_eta", "L_zeta", "pid"}
static

Names a particle expression may use: those of every source (PicurvSourceVariable), then pid.

Definition at line 22 of file ParticleInitialConditions.c.

22{"x", "y", "z", "t", "xi", "eta", "zeta", "L_xi", "L_eta", "L_zeta", "pid"};