8#define __FUNCT__ "DimensionalizeField"
19 Vec target_vec = NULL;
20 PetscReal scale_factor = 1.0;
21 char field_type[64] =
"Unknown";
22 PetscBool is_swarm_field = PETSC_FALSE;
23 const char *swarm_field_name = NULL;
25 PetscFunctionBeginUser;
27 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx is NULL.");
28 if (!field_name) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"field_name is NULL.");
31 if (strcasecmp(field_name,
"Ucat") == 0) {
32 target_vec = user->
Ucat;
34 strcpy(field_type,
"Cartesian Velocity (L/T)");
35 }
else if (strcasecmp(field_name,
"Ucont") == 0) {
36 target_vec = user->
Ucont;
38 strcpy(field_type,
"Contravariant Volume Flux (L^3/T)");
39 }
else if (strcasecmp(field_name,
"P") == 0) {
42 strcpy(field_type,
"Pressure (M L^-1 T^-2)");
43 }
else if (strcasecmp(field_name,
"Coordinates") == 0) {
44 ierr = DMGetCoordinates(user->
da, &target_vec); CHKERRQ(ierr);
46 strcpy(field_type,
"Grid Coordinates (L)");
47 }
else if (strcasecmp(field_name,
"ParticlePosition") == 0) {
48 is_swarm_field = PETSC_TRUE;
49 swarm_field_name =
"position";
51 strcpy(field_type,
"Particle Position (L)");
52 }
else if (strcasecmp(field_name,
"ParticleVelocity") == 0) {
53 is_swarm_field = PETSC_TRUE;
54 swarm_field_name =
"velocity";
56 strcpy(field_type,
"Particle Velocity (L/T)");
58 LOG(
GLOBAL,
LOG_WARNING,
"DimensionalizeField: Unknown or unhandled field_name '%s'. Field will not be scaled.\n", field_name);
60 PetscFunctionReturn(0);
64 if (PetscAbsReal(scale_factor - 1.0) < PETSC_MACHINE_EPSILON) {
65 LOG(
GLOBAL,
LOG_DEBUG,
"DimensionalizeField: Scaling factor for '%s' is 1.0. Skipping operation.\n", field_name);
67 PetscFunctionReturn(0);
71 LOG(
GLOBAL,
LOG_INFO,
"Scaling '%s' field (%s) by factor %.4e.\n", field_name, field_type, scale_factor);
75 ierr = DMSwarmCreateGlobalVectorFromField(user->
swarm, swarm_field_name, &target_vec); CHKERRQ(ierr);
76 ierr = VecScale(target_vec, scale_factor); CHKERRQ(ierr);
77 ierr = DMSwarmDestroyGlobalVectorFromField(user->
swarm, swarm_field_name, &target_vec); CHKERRQ(ierr);
81 ierr = VecScale(target_vec, scale_factor); CHKERRQ(ierr);
83 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
"Target vector for field '%s' was not found or is NULL.", field_name);
88 if (strcasecmp(field_name,
"Coordinates") == 0) {
93 PetscFunctionReturn(0);
97#define __FUNCT__ "DimensionalizeAllLoadedFields"
107 PetscFunctionBeginUser;
110 LOG(
GLOBAL,
LOG_INFO,
"--- Converting all loaded fields to dimensional units ---\n");
121 if (simCtx->
np > 0 && user->
swarm) {
129 PetscFunctionReturn(0);
135#define __FUNCT__ "ExtendToLayoutBoundary"
147 PetscInt periodic[3];
149 PetscFunctionBeginUser;
151 PetscCheck(user != NULL && global != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
152 "Context and field are required.");
153 PetscCheck(components == 1 || components == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
154 "ExtendToLayoutBoundary handles 1- or 3-component fields; got %d.", (
int)components);
156 dm = (components == 1) ? user->
da : user->
fda;
161 if (!periodic[0] && !periodic[1] && !periodic[2]) {
166 PetscFunctionReturn(0);
169 PetscCall(DMGetLocalVector(dm, &local));
173 for (PetscInt dir = 0; dir < 3; ++dir) {
175 const PetscReal ****source = NULL;
176 PetscReal ****target = NULL;
179 if (!periodic[dir])
continue;
181 PetscCall(DMGlobalToLocalBegin(dm, global, INSERT_VALUES, local));
182 PetscCall(DMGlobalToLocalEnd(dm, global, INSERT_VALUES, local));
183 PetscCall(DMDAGetLocalInfo(dm, &info));
184 extent = (dir == 0) ? info.mx : ((dir == 1) ? info.my : info.mz);
186 PetscCall(DMDAVecGetArrayDOFRead(dm, local, &source));
187 PetscCall(DMDAVecGetArrayDOF(dm, global, &target));
188 for (PetscInt k = info.zs; k < info.zs + info.zm; ++k) {
189 for (PetscInt j = info.ys; j < info.ys + info.ym; ++j) {
190 for (PetscInt i = info.xs; i < info.xs + info.xm; ++i) {
191 const PetscInt index = (dir == 0) ? i : ((dir == 1) ? j : k);
192 PetscInt ss = i, sj = j, sk = k;
199 if (dir == 0) ss = extent - 2;
200 else if (dir == 1) sj = extent - 2;
201 else sk = extent - 2;
202 }
else if (index == extent - 1) {
203 if (dir == 0) ss = extent + 1;
204 else if (dir == 1) sj = extent + 1;
205 else sk = extent + 1;
209 for (PetscInt c = 0; c < components; ++c) {
210 target[k][j][i][c] = source[sk][sj][ss][c];
215 PetscCall(DMDAVecRestoreArrayDOF(dm, global, &target));
216 PetscCall(DMDAVecRestoreArrayDOFRead(dm, local, &source));
218 PetscCall(DMRestoreLocalVector(dm, &local));
221 "-> KERNEL: Extended %d-component field across the periodic layout boundary "
222 "(i=%d, j=%d, k=%d).\n", (
int)components,
223 (
int)periodic[0], (
int)periodic[1], (
int)periodic[2]);
225 PetscFunctionReturn(0);
229#define __FUNCT__ "ComputeNodalAverage"
240 Vec in_vec_local = NULL, out_vec_global = NULL;
241 DM dm_in = NULL, dm_out = NULL;
244 PetscFunctionBeginUser;
246 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"-> KERNEL: Running ComputeNodalAverage on '%s' -> '%s'.\n", in_field_name, out_field_name);
249 if (strcasecmp(in_field_name,
"P") == 0) { in_vec_local = user->
lP; dm_in = user->
da; dof = 1; }
250 else if (strcasecmp(in_field_name,
"Ucat") == 0) { in_vec_local = user->
lUcat; dm_in = user->
fda; dof = 3; }
251 else if (strcasecmp(in_field_name,
"Psi") == 0) { in_vec_local = user->
lPsi; dm_in = user->
da; dof = 1; }
254 else if (strcasecmp(in_field_name,
"PostScalar") == 0) { in_vec_local = user->
lPostScalar; dm_in = user->
da; dof = 1; }
255 else if (strcasecmp(in_field_name,
"PostVector") == 0) { in_vec_local = user->
lPostVector; dm_in = user->
fda; dof = 3; }
257 else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
"Unknown input field name for nodal averaging: %s", in_field_name);
259 if (strcasecmp(out_field_name,
"P_nodal") == 0) { out_vec_global = user->
P_nodal; dm_out = user->
da; }
260 else if (strcasecmp(out_field_name,
"Ucat_nodal") == 0) { out_vec_global = user->
Ucat_nodal; dm_out = user->
fda; }
261 else if (strcasecmp(out_field_name,
"Psi_nodal") == 0) { out_vec_global = user->
Psi_nodal; dm_out = user->
da; }
262 else if (strcasecmp(out_field_name,
"PostScalarNodal") == 0) { out_vec_global = user->
PostScalarNodal; dm_out = user->
da; }
263 else if (strcasecmp(out_field_name,
"PostVectorNodal") == 0) { out_vec_global = user->
PostVectorNodal; dm_out = user->
fda; }
265 else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
"Unknown output field name for nodal averaging: %s", out_field_name);
273 ierr = DMDAGetLocalInfo(dm_out, &info); CHKERRQ(ierr);
276 const PetscInt i_end = PetscMin(info.xs + info.xm, info.mx - 1);
277 const PetscInt j_end = PetscMin(info.ys + info.ym, info.my - 1);
278 const PetscInt k_end = PetscMin(info.zs + info.zm, info.mz - 1);
281 const PetscReal ***l_in_arr;
282 PetscReal ***g_out_arr;
283 ierr = DMDAVecGetArrayRead(dm_in,in_vec_local, (
void*)&l_in_arr); CHKERRQ(ierr);
284 ierr = DMDAVecGetArray(dm_out,out_vec_global, (
void*)&g_out_arr); CHKERRQ(ierr);
288 for (PetscInt k = info.zs; k < k_end; k++) {
289 for (PetscInt j = info.ys; j < j_end; j++) {
290 for (PetscInt i = info.xs; i < i_end; i++) {
291 g_out_arr[k][j][i] = 0.125 * (l_in_arr[k][j][i] + l_in_arr[k][j][i+1] +
292 l_in_arr[k][j+1][i] + l_in_arr[k][j+1][i+1] +
293 l_in_arr[k+1][j][i] + l_in_arr[k+1][j][i+1] +
294 l_in_arr[k+1][j+1][i] + l_in_arr[k+1][j+1][i+1]);
298 ierr = DMDAVecRestoreArrayRead(dm_in,in_vec_local, (
void*)&l_in_arr); CHKERRQ(ierr);
299 ierr = DMDAVecRestoreArray(dm_out,out_vec_global, (
void*)&g_out_arr); CHKERRQ(ierr);
301 }
else if (dof == 3) {
304 ierr = DMDAVecGetArrayRead(dm_in,in_vec_local, (
void*)&l_in_arr); CHKERRQ(ierr);
305 ierr = DMDAVecGetArray(dm_out,out_vec_global, (
void*)&g_out_arr); CHKERRQ(ierr);
307 for (PetscInt k = info.zs; k < k_end; k++) {
308 for (PetscInt j = info.ys; j < j_end; j++) {
309 for (PetscInt i = info.xs; i < i_end; i++) {
310 g_out_arr[k][j][i].
x = 0.125 * (l_in_arr[k][j][i].
x + l_in_arr[k][j][i+1].
x +
311 l_in_arr[k][j+1][i].
x + l_in_arr[k][j+1][i+1].
x +
312 l_in_arr[k+1][j][i].
x + l_in_arr[k+1][j][i+1].
x +
313 l_in_arr[k+1][j+1][i].
x + l_in_arr[k+1][j+1][i+1].
x);
315 g_out_arr[k][j][i].
y = 0.125 * (l_in_arr[k][j][i].
y + l_in_arr[k][j][i+1].
y +
316 l_in_arr[k][j+1][i].
y + l_in_arr[k][j+1][i+1].
y +
317 l_in_arr[k+1][j][i].
y + l_in_arr[k+1][j][i+1].
y +
318 l_in_arr[k+1][j+1][i].
y + l_in_arr[k+1][j+1][i+1].
y);
320 g_out_arr[k][j][i].
z = 0.125 * (l_in_arr[k][j][i].
z + l_in_arr[k][j][i+1].
z +
321 l_in_arr[k][j+1][i].
z + l_in_arr[k][j+1][i+1].
z +
322 l_in_arr[k+1][j][i].
z + l_in_arr[k+1][j][i+1].
z +
323 l_in_arr[k+1][j+1][i].
z + l_in_arr[k+1][j+1][i+1].
z);
327 ierr = DMDAVecRestoreArrayRead(dm_in,in_vec_local, (
void*)&l_in_arr); CHKERRQ(ierr);
328 ierr = DMDAVecRestoreArray(dm_out,out_vec_global, (
void*)&g_out_arr); CHKERRQ(ierr);
331 PetscFunctionReturn(0);
336#define __FUNCT__ "ComputeWindowStatisticNodal"
344 const char *outputs, PetscInt output_index,
345 char *out_name,
size_t name_size,
346 Vec *out_vec, PetscInt *out_components)
353 PetscFunctionBeginUser;
355 PetscCheck(user != NULL && out_name != NULL && out_vec != NULL && out_components != NULL,
356 PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Context and outputs are required.");
359 PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
360 "No accumulated window state exists to derive.");
368 &derived); CHKERRQ(ierr);
384 ierr = PetscStrncpy(out_name, derived.
name, name_size); CHKERRQ(ierr);
389 PetscFunctionReturn(0);
393#define __FUNCT__ "ComputeWindowStatisticsSummary"
401 const char *output_prefix, PetscInt ti)
407 PetscReal lowest = 1.0, highest = 0.0;
408 PetscReal mean_tke = 0.0;
409 PetscBool has_tke = PETSC_FALSE;
410 PetscInt derived_count = 0;
411 char path[PETSC_MAX_PATH_LEN];
413 PetscFunctionBeginUser;
415 PetscCheck(user != NULL && output_prefix != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
416 "Context and output prefix are required.");
419 PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
420 "No accumulated window state exists to summarize.");
425 window->
sample_count, &lowest, &highest); CHKERRQ(ierr);
431 if (derived_count > 0) {
441 has_tke = PETSC_TRUE;
444 if (simCtx->
rank == 0) {
446 PetscBool exists = PETSC_FALSE;
448 ierr = PetscSNPrintf(path,
sizeof(path),
"%s_statistics_%s.csv",
450 ierr = PetscTestFile(path,
'r', &exists); CHKERRQ(ierr);
451 csv = fopen(path, exists ?
"a" :
"w");
452 PetscCheck(csv != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
453 "Unable to open statistics summary '%s'.", path);
455 fprintf(csv,
"step,state,samples,total_weight,represented_time,"
456 "valid_fraction_min,valid_fraction_max,mean_tke\n");
458 fprintf(csv,
"%" PetscInt_FMT
",%s,%d,%.10e,%.10e,%.6f,%.6f,",
461 (
double)lowest, (
double)highest);
462 if (has_tke) fprintf(csv,
"%.10e\n", (
double)mean_tke);
463 else fprintf(csv,
"\n");
464 PetscCheck(fclose(csv) == 0, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE,
465 "Unable to close statistics summary '%s'.", path);
470 PetscFunctionReturn(0);
474#define __FUNCT__ "ComputeQCriterion"
485 const Cmpnts ***lucat, ***lcsi, ***leta, ***lzet;
486 const PetscReal***laj, ***lnvert;
489 PetscFunctionBeginUser;
502 ierr = DMDAGetLocalInfo(user->
da, &info); CHKERRQ(ierr);
504 ierr = DMDAVecGetArrayRead(user->
fda, user->
lUcat, (
void*)&lucat); CHKERRQ(ierr);
505 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCsi, (
void*)&lcsi); CHKERRQ(ierr);
506 ierr = DMDAVecGetArrayRead(user->
fda, user->
lEta, (
void*)&leta); CHKERRQ(ierr);
507 ierr = DMDAVecGetArrayRead(user->
fda, user->
lZet, (
void*)&lzet); CHKERRQ(ierr);
508 ierr = DMDAVecGetArrayRead(user->
da, user->
lAj, (
void*)&laj); CHKERRQ(ierr);
509 ierr = DMDAVecGetArrayRead(user->
da, user->
lNvert, (
void*)&lnvert); CHKERRQ(ierr);
510 ierr = DMDAVecGetArray(user->
da, user->
Qcrit, (
void*)&gq); CHKERRQ(ierr);
513 PetscInt i_start = (info.xs == 0) ? 1 : info.xs;
514 PetscInt i_end = (info.xs + info.xm == info.mx) ? info.mx - 1 : info.xs + info.xm;
515 PetscInt j_start = (info.ys == 0) ? 1 : info.ys;
516 PetscInt j_end = (info.ys + info.ym == info.my) ? info.my - 1 : info.ys + info.ym;
517 PetscInt k_start = (info.zs == 0) ? 1 : info.zs;
518 PetscInt k_end = (info.zs + info.zm == info.mz) ? info.mz - 1 : info.zs + info.zm;
521 for (PetscInt k = k_start; k < k_end; k++) {
522 for (PetscInt j = j_start; j < j_end; j++) {
523 for (PetscInt i = i_start; i < i_end; i++) {
526 PetscReal uc = 0.5 * (lucat[k][j][i+1].
x - lucat[k][j][i-1].
x);
527 PetscReal vc = 0.5 * (lucat[k][j][i+1].
y - lucat[k][j][i-1].
y);
528 PetscReal wc = 0.5 * (lucat[k][j][i+1].
z - lucat[k][j][i-1].
z);
530 PetscReal ue = 0.5 * (lucat[k][j+1][i].
x - lucat[k][j-1][i].
x);
531 PetscReal ve = 0.5 * (lucat[k][j+1][i].
y - lucat[k][j-1][i].
y);
532 PetscReal we = 0.5 * (lucat[k][j+1][i].
z - lucat[k][j-1][i].
z);
534 PetscReal uz = 0.5 * (lucat[k+1][j][i].
x - lucat[k-1][j][i].
x);
535 PetscReal vz = 0.5 * (lucat[k+1][j][i].
y - lucat[k-1][j][i].
y);
536 PetscReal wz = 0.5 * (lucat[k+1][j][i].
z - lucat[k-1][j][i].
z);
539 PetscReal csi1 = 0.5 * (lcsi[k][j][i].
x + lcsi[k][j][i-1].
x) * laj[k][j][i];
540 PetscReal csi2 = 0.5 * (lcsi[k][j][i].
y + lcsi[k][j][i-1].
y) * laj[k][j][i];
541 PetscReal csi3 = 0.5 * (lcsi[k][j][i].
z + lcsi[k][j][i-1].
z) * laj[k][j][i];
543 PetscReal eta1 = 0.5 * (leta[k][j][i].
x + leta[k][j-1][i].
x) * laj[k][j][i];
544 PetscReal eta2 = 0.5 * (leta[k][j][i].
y + leta[k][j-1][i].
y) * laj[k][j][i];
545 PetscReal eta3 = 0.5 * (leta[k][j][i].
z + leta[k][j-1][i].
z) * laj[k][j][i];
547 PetscReal zet1 = 0.5 * (lzet[k][j][i].
x + lzet[k-1][j][i].
x) * laj[k][j][i];
548 PetscReal zet2 = 0.5 * (lzet[k][j][i].
y + lzet[k-1][j][i].
y) * laj[k][j][i];
549 PetscReal zet3 = 0.5 * (lzet[k][j][i].
z + lzet[k-1][j][i].
z) * laj[k][j][i];
552 PetscReal d11 = uc * csi1 + ue * eta1 + uz * zet1;
553 PetscReal d12 = uc * csi2 + ue * eta2 + uz * zet2;
554 PetscReal d13 = uc * csi3 + ue * eta3 + uz * zet3;
556 PetscReal d21 = vc * csi1 + ve * eta1 + vz * zet1;
557 PetscReal d22 = vc * csi2 + ve * eta2 + vz * zet2;
558 PetscReal d23 = vc * csi3 + ve * eta3 + vz * zet3;
560 PetscReal d31 = wc * csi1 + we * eta1 + wz * zet1;
561 PetscReal d32 = wc * csi2 + we * eta2 + wz * zet2;
562 PetscReal d33 = wc * csi3 + we * eta3 + wz * zet3;
566 PetscReal s12 = 0.5 * (d12 + d21);
567 PetscReal s13 = 0.5 * (d13 + d31);
569 PetscReal s23 = 0.5 * (d23 + d32);
573 PetscReal w12 = 0.5 * (d12 - d21);
574 PetscReal w13 = 0.5 * (d13 - d31);
575 PetscReal w23 = 0.5 * (d23 - d32);
578 PetscReal s_norm_sq = s11*s11 + s22*s22 + s33*s33 + 2.0*(s12*s12 + s13*s13 + s23*s23);
579 PetscReal w_norm_sq = 2.0 * (w12*w12 + w13*w13 + w23*w23);
581 gq[k][j][i] = 0.5 * (w_norm_sq - s_norm_sq);
583 if (lnvert[k][j][i] > 0.1) {
591 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lUcat, (
void*)&lucat); CHKERRQ(ierr);
592 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCsi, (
void*)&lcsi); CHKERRQ(ierr);
593 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lEta, (
void*)&leta); CHKERRQ(ierr);
594 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lZet, (
void*)&lzet); CHKERRQ(ierr);
595 ierr = DMDAVecRestoreArrayRead(user->
da, user->
lAj, (
void*)&laj); CHKERRQ(ierr);
596 ierr = DMDAVecRestoreArrayRead(user->
da, user->
lNvert, (
void*)&lnvert); CHKERRQ(ierr);
597 ierr = DMDAVecRestoreArray(user->
da, user->
Qcrit, (
void*)&gq); CHKERRQ(ierr);
605 PetscFunctionReturn(0);
609#define __FUNCT__ "NormalizeRelativeField"
621 PetscInt ip=1, jp=1, kp=1;
622 PetscReal p_ref = 0.0;
623 PetscReal p_ref_local = 0.0;
624 PetscInt found_local = 0, found_global = 0;
632 PetscFunctionBeginUser;
637 if (strcasecmp(relative_field_name,
"P") == 0) {
640 SETERRQ(PETSC_COMM_SELF, 1,
"NormalizeRelativeField only supports the primary 'P' field , not '%s' currently.", relative_field_name);
644 ierr = DMDAGetLocalInfo(user->
da, &info); CHKERRQ(ierr);
645 PetscCheck(ip >= 0 && ip < info.mx && jp >= 0 && jp < info.my &&
646 kp >= 0 && kp < info.mz,
647 PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
648 "Reference point (%" PetscInt_FMT
", %" PetscInt_FMT
", %" PetscInt_FMT
649 ") lies outside the %" PetscInt_FMT
"x%" PetscInt_FMT
"x%" PetscInt_FMT
650 " pressure layout.", ip, jp, kp, info.mx, info.my, info.mz);
651 if (ip >= info.xs && ip < info.xs + info.xm &&
652 jp >= info.ys && jp < info.ys + info.ym &&
653 kp >= info.zs && kp < info.zs + info.zm) {
654 const PetscReal ***pressure = NULL;
656 ierr = DMDAVecGetArrayRead(user->
da, P_vec, &pressure); CHKERRQ(ierr);
657 p_ref_local = pressure[kp][jp][ip];
658 ierr = DMDAVecRestoreArrayRead(user->
da, P_vec, &pressure); CHKERRQ(ierr);
661 ierr = MPI_Allreduce(&p_ref_local, &p_ref, 1, MPIU_REAL, MPI_SUM,
662 PETSC_COMM_WORLD); CHKERRQ(ierr);
663 ierr = MPI_Allreduce(&found_local, &found_global, 1, MPIU_INT, MPI_SUM,
664 PETSC_COMM_WORLD); CHKERRQ(ierr);
665 PetscCheck(found_global == 1, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
666 "Reference pressure point must have exactly one owner; found %" PetscInt_FMT
".",
669 "%s reference point (%" PetscInt_FMT
", %" PetscInt_FMT
", %" PetscInt_FMT
670 ") has value %g.\n", relative_field_name, ip, jp, kp, (
double)p_ref);
673 ierr = VecShift(P_vec, -p_ref); CHKERRQ(ierr);
677 PetscFunctionReturn(0);
684#define __FUNCT__ "ComputeSpecificKE"
693 const PetscScalar (*vel_arr)[3];
694 PetscScalar *ske_arr;
696 PetscFunctionBeginUser;
698 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"-> KERNEL: Running ComputeSpecificKE ('%s' -> '%s').\n", velocity_field, ske_field);
701 ierr = DMSwarmGetLocalSize(user->
swarm, &n_local); CHKERRQ(ierr);
705 ierr = DMSwarmGetField(user->
swarm, velocity_field, NULL, NULL, (
void**)&vel_arr); CHKERRQ(ierr);
706 ierr = DMSwarmGetField(user->
post_swarm, ske_field, NULL, NULL, (
void**)&ske_arr); CHKERRQ(ierr);
709 for (PetscInt p = 0; p < n_local; p++) {
710 const PetscScalar u = vel_arr[p][0];
711 const PetscScalar v = vel_arr[p][1];
712 const PetscScalar w = vel_arr[p][2];
713 const PetscScalar vel_sq = u*u + v*v + w*w;
714 ske_arr[p] = 0.5 * vel_sq;
718 ierr = DMSwarmRestoreField(user->
swarm, velocity_field, NULL, NULL, (
void**)&vel_arr); CHKERRQ(ierr);
719 ierr = DMSwarmRestoreField(user->
post_swarm, ske_field, NULL, NULL, (
void**)&ske_arr); CHKERRQ(ierr);
722 PetscFunctionReturn(0);
726#define __FUNCT__ "ComputeDisplacement"
735 const PetscReal (*pos_arr)[3];
736 PetscScalar *disp_out;
739 PetscFunctionBeginUser;
743 ierr = DMSwarmGetLocalSize(user->
swarm, &n_local); CHKERRQ(ierr);
746 const PetscReal x0 = simCtx->
psrc_x;
747 const PetscReal y0 = simCtx->
psrc_y;
748 const PetscReal z0 = simCtx->
psrc_z;
751 ierr = DMSwarmGetField(user->
post_swarm, disp_field, NULL, NULL, (
void**)&disp_out); CHKERRQ(ierr);
753 for (PetscInt p = 0; p < n_local; p++) {
754 const PetscReal dx = pos_arr[p][0] - x0;
755 const PetscReal dy = pos_arr[p][1] - y0;
756 const PetscReal dz = pos_arr[p][2] - z0;
757 disp_out[p] = PetscSqrtReal(dx*dx + dy*dy + dz*dz);
761 ierr = DMSwarmRestoreField(user->
post_swarm, disp_field, NULL, NULL, (
void**)&disp_out); CHKERRQ(ierr);
764 PetscFunctionReturn(0);
PetscErrorCode FieldIdFromName(const char *field_name, FieldId *field_id)
Resolve a user-facing field name once into its typed identity.
FieldId
Compile-time identity for a catalogued Eulerian field.
#define GLOBAL
Scope for global logging across all processes.
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
#define LOG(scope, level, fmt,...)
Logging macro for PETSc-based applications with scope control.
@ LOG_INFO
Informational messages about program execution.
@ LOG_WARNING
Non-critical issues that warrant attention.
@ LOG_DEBUG
Detailed debugging information.
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Typed identities and metadata for persistent solver-particle fields.
const char * ParticleFieldName(ParticleFieldId field_id)
Return the canonical PETSc DMSwarm name for an ID.
@ PARTICLE_FIELD_ID_POSITION
PetscErrorCode ComputeQCriterion(UserCtx *user)
Implementation of ComputeQCriterion().
PetscErrorCode ComputeSpecificKE(UserCtx *user, const char *velocity_field, const char *ske_field)
Internal helper implementation: ComputeSpecificKE().
PetscErrorCode ExtendToLayoutBoundary(UserCtx *user, Vec global, PetscInt components)
Implementation of ExtendToLayoutBoundary().
PetscErrorCode ComputeDisplacement(UserCtx *user, const char *disp_field)
Internal helper implementation: ComputeDisplacement().
PetscErrorCode NormalizeRelativeField(UserCtx *user, const char *relative_field_name)
Implementation of NormalizeRelativeField().
PetscErrorCode ComputeWindowStatisticsSummary(UserCtx *user, PetscInt window_index, const char *output_prefix, PetscInt ti)
Implementation of ComputeWindowStatisticsSummary().
PetscErrorCode DimensionalizeField(UserCtx *user, const char *field_name)
Implementation of DimensionalizeField().
PetscErrorCode DimensionalizeAllLoadedFields(UserCtx *user)
Internal helper implementation: DimensionalizeAllLoadedFields().
PetscErrorCode ComputeNodalAverage(UserCtx *user, const char *in_field_name, const char *out_field_name)
Implementation of ComputeNodalAverage().
PetscErrorCode ComputeWindowStatisticNodal(UserCtx *user, PetscInt window_index, const char *outputs, PetscInt output_index, char *out_name, size_t name_size, Vec *out_vec, PetscInt *out_components)
Implementation of ComputeWindowStatisticNodal().
PetscErrorCode UpdateLocalGhosts(UserCtx *user, FieldId field_id)
Updates the local vector (including ghost points) from its corresponding global vector.
Per-window PETSc accumulator storage and pointwise application.
PetscInt components
One or three.
char name[96]
Output field name, window qualified.
PetscErrorCode PicurvWindowDerive(UserCtx *user, const PicurvWindowDefinition *definition, const PicurvWindowStorage *storage, const char *outputs, PetscInt index, Vec scalar_target, Vec vector_target, PicurvDerivedField *field)
Derives one output field from centered accumulator state.
PetscErrorCode PicurvWindowDerivedCount(const PicurvWindowDefinition *definition, const PicurvWindowStorage *storage, const char *outputs, PetscInt *count)
Reports how many derived fields a requested output set produces.
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 PicurvWindowSpatialMean(UserCtx *user, const PicurvWindowDefinition *definition, const PicurvWindowStorage *storage, Vec field, PetscReal *mean)
Reports the spatial mean of a derived field over the points a window sampled.
One derived output field, resolved by enumeration index.
Independent accumulator state for one window on one block.
Window lifecycle, scheduling, and weighting for the field-statistics pipeline.
const char * PicurvWindowStateName(PicurvWindowState state)
Returns a stable human-readable name for a window state.
PicurvWindowDefinition definition
PetscBool FieldStatisticsIsActive(const struct SimCtx *simCtx)
Reports whether this run has live field-statistics state.
PetscReal represented_time
Physical time the window covers.
Runtime state of one window.
The scientifically immutable definition of one window.
SimCtx * simCtx
Back-pointer to the master simulation context.
PetscReal psrc_z
Point source location for PARTICLE_INIT_POINT_SOURCE.
struct PicurvWindow * fieldStatisticsWindows
struct PicurvWindowStorage * fieldStatisticsStorage
A 3D point or vector with PetscScalar components.
Holds all configuration parameters for a post-processing run.
The master context for the entire simulation.
User-defined context containing data specific to a single computational grid level.