246 PetscInt N_full_coords;
247 PetscScalar *full_coords_arr = NULL;
249 PetscFunctionBeginUser;
250 ierr = DMDAGetInfo(user->
da, NULL, &IM, &JM, &KM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
256 *out_npoints = (*out_nx) * (*out_ny) * (*out_nz);
258 LOG_ALLOW(
GLOBAL,
LOG_DEBUG,
"Preparing subsampled coordinates for a %" PetscInt_FMT
"x%" PetscInt_FMT
"x%" PetscInt_FMT
" grid.\n", *out_nx, *out_ny, *out_nz);
261 ierr = DMGetCoordinates(user->
da, &coords_global); CHKERRQ(ierr);
263 ierr =
VecToArrayOnRank0(coords_global, &N_full_coords, &full_coords_arr); CHKERRQ(ierr);
268 if (N_full_coords != IM * JM * KM * 3) {
269 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED,
"Gathered coordinate array has wrong size. Expected %" PetscInt_FMT
", got %" PetscInt_FMT, IM * JM * KM * 3, N_full_coords);
273 ierr = PetscMalloc1(3 * (*out_npoints), out_coords); CHKERRQ(ierr);
277 for (PetscInt k = 0; k < *out_nz; k++) {
278 for (PetscInt j = 0; j < *out_ny; j++) {
279 for (PetscInt i = 0; i < *out_nx; i++) {
281 PetscInt p_in = 3 * (k * (JM * IM) + j * IM + i);
283 (*out_coords)[p_out++] = full_coords_arr[p_in + 0];
284 (*out_coords)[p_out++] = full_coords_arr[p_in + 1];
285 (*out_coords)[p_out++] = full_coords_arr[p_in + 2];
290 ierr = PetscFree(full_coords_arr); CHKERRQ(ierr);
296 LOG_ALLOW(
GLOBAL,
LOG_DEBUG,
"Subsampled coordinates prepared on rank 0 with total %" PetscInt_FMT
" points.\n", *out_npoints);
298 PetscFunctionReturn(0);
380 PetscInt IM, JM, KM, nx, ny, nz, npoints;
381 PetscInt N_full_field = 0;
382 PetscScalar *full_field_arr = NULL;
384 PetscFunctionBeginUser;
385 ierr = DMDAGetInfo(user->
da, NULL, &IM, &JM, &KM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
386 nx = IM - 1; ny = JM - 1; nz = KM - 1;
387 npoints = nx * ny * nz;
390 "Preparing subsampled field data (dof=%" PetscInt_FMT
") for a %" PetscInt_FMT
"x%" PetscInt_FMT
"x%" PetscInt_FMT
" grid.\n",
391 num_components, nx, ny, nz);
394 ierr =
VecToArrayOnRank0(field_vec, &N_full_field, &full_field_arr); CHKERRQ(ierr);
399 if (N_full_field != IM * JM * KM * num_components) {
400 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FILE_UNEXPECTED,
401 "Gathered field array has wrong size. Expected %" PetscInt_FMT
", got %" PetscInt_FMT,
402 IM * JM * KM * num_components, N_full_field);
406 ierr = PetscMalloc1(num_components * npoints, out_data); CHKERRQ(ierr);
458 for (PetscInt k = 0; k < nz; k++) {
459 for (PetscInt j = 0; j < ny; j++) {
460 for (PetscInt i = 0; i < nx; i++) {
461 const PetscInt p_in_start = num_components * (k * (JM * IM) + j * IM + i);
462 for (PetscInt c = 0; c < num_components; c++) {
463 (*out_data)[p_out++] = full_field_arr[p_in_start + c];
471 ierr = PetscFree(full_field_arr); CHKERRQ(ierr);
477 LOG_ALLOW(
GLOBAL,
LOG_DEBUG,
"Subsampled field data prepared on rank 0 with total %" PetscInt_FMT
" points.\n", npoints);
479 PetscFunctionReturn(0);
489 PetscInt n_total_particles, n_components;
492 PetscFunctionBeginUser;
501 PetscReal *full_coords_arr = NULL;
502 PetscDataType coordinate_type;
506 &n_total_particles, &n_components, &coordinate_type,
507 (
void**)&full_coords_arr); CHKERRQ(ierr);
508 PetscCheck(coordinate_type == PETSC_REAL,
509 PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
510 "Particle position field must use PETSC_REAL storage, not %s.",
511 PetscDataTypes[coordinate_type]);
513 *p_n_total = n_total_particles;
514 if (n_total_particles == 0) {
515 ierr = PetscFree(full_coords_arr); CHKERRQ(ierr);
516 PetscFunctionReturn(0);
518 PetscCheck(n_components == 3,
519 PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
520 "Coordinate field position must have 3 components, but has %" PetscInt_FMT,
526 meta->
npoints = (n_total_particles > 0) ? (n_total_particles - 1) / stride + 1 : 0;
528 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Subsampling %" PetscInt_FMT
" total particles with stride %" PetscInt_FMT
" -> %" PetscInt_FMT
" output particles.\n",
529 n_total_particles, stride, meta->
npoints);
532 ierr = PetscMalloc1(3 * meta->
npoints, &meta->
coords); CHKERRQ(ierr);
533 for (PetscInt i = 0; i < meta->
npoints; i++) {
534 PetscInt source_idx = i * stride;
535 for (
int d = 0; d < 3; d++) meta->
coords[3 * i + d] = full_coords_arr[3 * source_idx + d];
538 ierr = PetscFree(full_coords_arr); CHKERRQ(ierr);
541 char *fields_copy, *field_name;
542 PetscInt num_fields = 0;
543 ierr = PetscStrallocpy(pps->
particle_fields, &fields_copy); CHKERRQ(ierr);
544 field_name = strtok(fields_copy,
",");
547 if (!*field_name || strcasecmp(field_name,
"position") == 0) {
548 field_name = strtok(NULL,
",");
continue;
552 DM swarm_to_use = user->
swarm;
553 const char* internal_name = field_name;
555 PetscErrorCode check_ierr;
556 ierr = PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL); CHKERRQ(ierr);
557 check_ierr = DMSwarmGetField(user->
post_swarm, field_name, NULL, NULL, NULL);
558 ierr = PetscPopErrorHandler(); CHKERRQ(ierr);
561 ierr = DMSwarmRestoreField(user->
post_swarm, field_name, NULL, NULL, NULL); CHKERRQ(ierr);
569 if (strcasecmp(field_name,
"pid") == 0) internal_name =
"DMSwarm_pid";
570 else if (strcasecmp(field_name,
"CellID") == 0) internal_name =
"DMSwarm_CellID";
571 else if (strcasecmp(field_name,
"Migration Status") == 0) internal_name =
"DMSwarm_location_status";
576 void* full_field_arr_void = NULL;
577 PetscInt field_total_particles, field_num_components;
578 PetscDataType field_data_type;
581 &field_total_particles, &field_num_components,
582 &field_data_type, &full_field_arr_void); CHKERRQ(ierr);
584 if (field_total_particles != n_total_particles) {
586 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"Field '%s' has %" PetscInt_FMT
" particles, but expected %" PetscInt_FMT
". Skipping.\n", field_name, field_total_particles, n_total_particles);
588 ierr = PetscFree(full_field_arr_void); CHKERRQ(ierr);
589 field_name = strtok(NULL,
",");
continue;
600 PetscScalar* final_data_arr = (PetscScalar*)current_field->
data;
603 if (field_data_type == PETSC_INT64) {
604 PetscInt64* source_arr = (PetscInt64*)full_field_arr_void;
605 for (PetscInt i = 0; i < meta->
npoints; i++) {
606 final_data_arr[i] = (PetscScalar)source_arr[i * stride];
608 }
else if (field_data_type == PETSC_INT) {
609 PetscInt* source_arr = (PetscInt*)full_field_arr_void;
610 for (PetscInt i = 0; i < meta->
npoints; i++) {
611 PetscInt source_idx = i * stride;
616 }
else if (field_data_type == PETSC_REAL) {
617 PetscReal* source_arr = (PetscReal*)full_field_arr_void;
618 for (PetscInt i = 0; i < meta->
npoints; i++) {
619 PetscInt source_idx = i * stride;
624#if defined(PETSC_USE_COMPLEX)
625 }
else if (field_data_type == PETSC_SCALAR) {
626 PetscScalar* source_arr = (PetscScalar*)full_field_arr_void;
627 for (PetscInt i = 0; i < meta->
npoints; i++) {
628 PetscInt source_idx = i * stride;
634 }
else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
635 "VTK particle output does not support field '%s' with PETSc type %s.",
636 field_name, PetscDataTypes[field_data_type]);
640 ierr = PetscFree(full_field_arr_void); CHKERRQ(ierr);
642 field_name = strtok(NULL,
",");
644 ierr = PetscFree(fields_copy); CHKERRQ(ierr);
651 ierr = PetscMalloc1(meta->
npoints, &meta->
offsets); CHKERRQ(ierr);
652 for (PetscInt i = 0; i < meta->
npoints; i++) {
659 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRQ(ierr);
661 PetscFunctionReturn(0);
Typed identities and metadata for persistent solver-particle fields.
const char * ParticleFieldName(ParticleFieldId field_id)
Return the canonical PETSc DMSwarm name for an ID.
Holds all configuration parameters for a post-processing run.