PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
Macros | Functions
Internal Scattering Helpers

Lower-level functions used by the main scattering routines. More...

Collaboration diagram for Internal Scattering Helpers:

Macros

#define __FUNCT__   "InterpolateFieldFromCornerToCenter_Vector"
 
#define __FUNCT__   "InterpolateFieldFromCornerToCenter_Scalar"
 
#define __FUNCT__   "TestCornerToCenterInterpolation"
 
#define __FUNCT__   "InterpolateFieldFromCenterToCorner_Vector"
 
#define __FUNCT__   "InterpolateFieldFromCenterToCorner_Scalar"
 
#define __FUNCT__   "InterpolateEulerFieldFromCenterToSwarm"
 
#define __FUNCT__   "InterpolateEulerFieldFromCornerToSwarm"
 
#define __FUNCT__   "InterpolateEulerFieldToSwarm"
 
#define __FUNCT__   "InterpolateAllFieldsToSwarm"
 
#define __FUNCT__   "AccumulateParticleField"
 
#define __FUNCT__   "NormalizeGridVectorByCount"
 
#define __FUNCT__   "ScatterParticleFieldToEulerField_Internal"
 
#define __FUNCT__   "ScatterParticleFieldToEulerField"
 
#define __FUNCT__   "ScatterAllParticleFieldsToEulerFields"
 
#define __FUNCT__   "InterpolateCornerToFaceCenter_Scalar"
 
#define __FUNCT__   "InterpolateCornerToFaceCenter_Vector"
 

Functions

PetscErrorCode AccumulateParticleField (DM swarm, ParticleFieldId particle_field_id, DM gridSumDM, Vec gridSumVec)
 Accumulates a particle field (scalar or vector) into a target grid sum vector.
 
PetscErrorCode NormalizeGridVectorByCount (DM countDM, Vec countVec, DM dataDM, Vec sumVec, Vec avgVec)
 Normalizes a grid vector of sums by a grid vector of counts to produce an average.
 

Detailed Description

Lower-level functions used by the main scattering routines.

Macro Definition Documentation

◆ __FUNCT__ [1/16]

#define __FUNCT__   "InterpolateFieldFromCornerToCenter_Vector"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [2/16]

#define __FUNCT__   "InterpolateFieldFromCornerToCenter_Scalar"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [3/16]

#define __FUNCT__   "TestCornerToCenterInterpolation"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [4/16]

#define __FUNCT__   "InterpolateFieldFromCenterToCorner_Vector"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [5/16]

#define __FUNCT__   "InterpolateFieldFromCenterToCorner_Scalar"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [6/16]

#define __FUNCT__   "InterpolateEulerFieldFromCenterToSwarm"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [7/16]

#define __FUNCT__   "InterpolateEulerFieldFromCornerToSwarm"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [8/16]

#define __FUNCT__   "InterpolateEulerFieldToSwarm"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [9/16]

#define __FUNCT__   "InterpolateAllFieldsToSwarm"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [10/16]

#define __FUNCT__   "AccumulateParticleField"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [11/16]

#define __FUNCT__   "NormalizeGridVectorByCount"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [12/16]

#define __FUNCT__   "ScatterParticleFieldToEulerField_Internal"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [13/16]

#define __FUNCT__   "ScatterParticleFieldToEulerField"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [14/16]

#define __FUNCT__   "ScatterAllParticleFieldsToEulerFields"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [15/16]

#define __FUNCT__   "InterpolateCornerToFaceCenter_Scalar"

Definition at line 20 of file interpolation.c.

◆ __FUNCT__ [16/16]

#define __FUNCT__   "InterpolateCornerToFaceCenter_Vector"

Definition at line 20 of file interpolation.c.

Function Documentation

◆ AccumulateParticleField()

PetscErrorCode AccumulateParticleField ( DM  swarm,
ParticleFieldId  particle_field_id,
DM  gridSumDM,
Vec  gridSumVec 
)

Accumulates a particle field (scalar or vector) into a target grid sum vector.

This function iterates through local particles, identifies their cell using the "DMSwarm_CellID" field, and adds the particle's field value (particleFieldName) to the corresponding cell location in the gridSumVec. It handles both scalar (DOF=1) and vector (DOF=3) fields automatically based on the DOF of gridSumDM.

IMPORTANT: The caller must ensure gridSumVec is zeroed before calling this function if a fresh sum calculation is desired.

Parameters
[in]swarmThe DMSwarm containing particles.
[in]particle_field_idTyped identity of the particle field (must match DOF).
[in]gridSumDMThe DMDA associated with gridSumVec. Its DOF determines how many components are accumulated.
[in,out]gridSumVecThe Vec (associated with gridSumDM) to accumulate sums into.
Returns
PetscErrorCode 0 on success. Errors if fields don't exist or DMs are incompatible.

Definition at line 1478 of file interpolation.c.

1480{
1481 PetscErrorCode ierr;
1482 PetscInt dof;
1483 PetscInt nlocal, p;
1484 const PetscReal *particle_arr = NULL;
1485 const PetscInt *cell_id_arr = NULL;
1486
1487 // DMDA Accessors
1488 PetscScalar ***arr_1d = NULL; // For scalar fields
1489 PetscScalar ****arr_3d = NULL; // For vector fields
1490
1491 // Ghosted dimension variables
1492 PetscInt gxs, gys, gzs, gxm, gym, gzm;
1493 PetscMPIInt rank;
1494 char msg[ERROR_MSG_BUFFER_SIZE];
1495 const ParticleFieldDescriptor *descriptor = NULL;
1496 const char *particleFieldName = NULL;
1497
1498 PetscFunctionBeginUser;
1500
1501 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1502
1503 ierr = ParticleFieldGetDescriptor(particle_field_id, &descriptor); CHKERRQ(ierr);
1504 PetscCheck(descriptor->data_type == PETSC_REAL, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
1505 "Particle-to-grid accumulation requires PETSC_REAL data; field '%s' uses %s.",
1506 descriptor->canonical_name, PetscDataTypes[descriptor->data_type]);
1507 particleFieldName = descriptor->canonical_name;
1508
1509 // --- 1. Validation & Setup ---
1510 if (!swarm || !gridSumDM || !localAccumulatorVec)
1511 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null input in AccumulateParticleField.");
1512
1513 // Get DMDA information
1514 ierr = DMDAGetInfo(gridSumDM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
1515 // Get Ghosted Corners (Global indices of the ghosted patch start, and its dimensions)
1516 ierr = DMDAGetGhostCorners(gridSumDM, &gxs, &gys, &gzs, &gxm, &gym, &gzm); CHKERRQ(ierr);
1517
1518 // --- 2. Verify Vector Type (Global vs Local) ---
1519 {
1520 PetscInt vecSize;
1521 PetscInt expectedLocalSize = gxm * gym * gzm * dof;
1522 ierr = VecGetSize(localAccumulatorVec, &vecSize); CHKERRQ(ierr);
1523
1524 if (vecSize != expectedLocalSize) {
1525 PetscSNPrintf(msg, sizeof(msg),
1526 "Vector dimension mismatch! Expected Ghosted Local Vector size %d (gxm*gym*gzm*dof), got %d. "
1527 "Did you pass a Global Vector instead of a Local Vector?",
1528 expectedLocalSize, vecSize);
1529 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "%s", msg);
1530 }
1531 }
1532
1533 // --- 3. Acquire Particle Data ---
1534 ierr = DMSwarmGetLocalSize(swarm, &nlocal); CHKERRQ(ierr);
1535 // These calls will fail nicely if the field doesn't exist
1536 ierr = DMSwarmGetField(swarm, particleFieldName, NULL, NULL, (void **)&particle_arr); CHKERRQ(ierr);
1537 ierr = DMSwarmGetField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_CELL_ID), NULL, NULL, (void **)&cell_id_arr); CHKERRQ(ierr);
1538
1539 // --- 4. Acquire Grid Accessors ---
1540 // DMDAVecGetArray* handles the mapping from Global (i,j,k) to the underlying Local Array index
1541 if (dof == 1) {
1542 ierr = DMDAVecGetArray(gridSumDM, localAccumulatorVec, &arr_1d); CHKERRQ(ierr);
1543 } else if (dof == 3) {
1544 ierr = DMDAVecGetArrayDOF(gridSumDM, localAccumulatorVec, &arr_3d); CHKERRQ(ierr);
1545 } else {
1546 PetscSNPrintf(msg, sizeof(msg), "Unsupported DOF=%d. AccumulateParticleField supports DOF 1 or 3.", dof);
1547 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "%s", msg);
1548 }
1549
1550 // --- 5. Accumulate Loop ---
1551 // Iterate through all local particles
1552 for (p = 0; p < nlocal; ++p) {
1553 // Retrieve Geometric Grid Index (0-based)
1554 PetscInt i_geom = cell_id_arr[p * 3 + 0];
1555 PetscInt j_geom = cell_id_arr[p * 3 + 1];
1556 PetscInt k_geom = cell_id_arr[p * 3 + 2];
1557
1558 // Apply Shift (+1) to match Memory Layout (Index 0 is boundary/ghost)
1559 PetscInt i = i_geom + 1;
1560 PetscInt j = j_geom + 1;
1561 PetscInt k = k_geom + 1;
1562
1563 // Bounds Check: Ensure (i,j,k) falls within the Local Ghosted Patch.
1564 // This allows writing to ghost slots which will later be reduced to the owner rank.
1565 if (i >= gxs && i < gxs + gxm &&
1566 j >= gys && j < gys + gym &&
1567 k >= gzs && k < gzs + gzm)
1568 {
1569 if (dof == 1) {
1570 arr_1d[k][j][i] += particle_arr[p];
1571 } else {
1572 // For DOF=3, unroll the loop for slight optimization
1573 arr_3d[k][j][i][0] += particle_arr[p * 3 + 0];
1574 arr_3d[k][j][i][1] += particle_arr[p * 3 + 1];
1575 arr_3d[k][j][i][2] += particle_arr[p * 3 + 2];
1576 }
1577 }
1578 // Note: Particles outside the ghost layer are skipped. This is expected behavior
1579 // if particles have not yet been migrated or localized correctly.
1580 }
1581
1582 // --- 6. Restore Arrays and Fields ---
1583 if (dof == 1) {
1584 ierr = DMDAVecRestoreArray(gridSumDM, localAccumulatorVec, &arr_1d); CHKERRQ(ierr);
1585 } else {
1586 ierr = DMDAVecRestoreArrayDOF(gridSumDM, localAccumulatorVec, &arr_3d); CHKERRQ(ierr);
1587 }
1588
1589 ierr = DMSwarmRestoreField(swarm, particleFieldName, NULL, NULL, (void **)&particle_arr); CHKERRQ(ierr);
1590 ierr = DMSwarmRestoreField(swarm, ParticleFieldName(PARTICLE_FIELD_ID_CELL_ID), NULL, NULL, (void **)&cell_id_arr); CHKERRQ(ierr);
1591
1593 PetscFunctionReturn(0);
1594}
#define ERROR_MSG_BUFFER_SIZE
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:859
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:850
const char * ParticleFieldName(ParticleFieldId field_id)
Return the canonical PETSc DMSwarm name for an ID.
@ PARTICLE_FIELD_ID_CELL_ID
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:

◆ NormalizeGridVectorByCount()

PetscErrorCode NormalizeGridVectorByCount ( DM  countDM,
Vec  countVec,
DM  dataDM,
Vec  sumVec,
Vec  avgVec 
)

Normalizes a grid vector of sums by a grid vector of counts to produce an average.

Calculates avgVec[i] = sumVec[i] / countVec[i] for each component of each OWNED cell where countVec[i] > 0. Sets avgVec[i] = 0 otherwise. Handles both scalar (DOF=1) and vector (DOF=3) data fields based on dataDM. Uses basic VecGetArray/VecGetArrayRead and manual index calculation.

Parameters
[in]countDMThe DMDA associated with countVec (must have DOF=1).
[in]countVecThe Vec containing particle counts per cell (read-only).
[in]dataDMThe DMDA associated with sumVec and avgVec (must have DOF=1 or DOF=3).
[in]sumVecThe Vec containing the accumulated sums per cell (read-only).
[in,out]avgVecThe Vec where the calculated averages will be stored (overwritten).
Returns
PetscErrorCode 0 on success.

Definition at line 1600 of file interpolation.c.

1602{
1603 PetscErrorCode ierr;
1604 PetscInt data_dof;
1605 PetscInt count_dof;
1606 PetscMPIInt rank;
1607 char msg[ERROR_MSG_BUFFER_SIZE];
1608
1609 // Pointers for DMDA array accessors - declare specific types
1610 PetscScalar ***count_arr_3d = NULL; // For DOF=1 count vector (3D DMDA)
1611 PetscScalar ***sum_arr_scalar = NULL; // For DOF=1 sum vector (3D DMDA)
1612 PetscScalar ***avg_arr_scalar = NULL; // For DOF=1 avg vector (3D DMDA)
1613 PetscScalar ****sum_arr_vector = NULL; // For DOF=3 sum vector (3D DMDA + DOF)
1614 PetscScalar ****avg_arr_vector = NULL; // For DOF=3 avg vector (3D DMDA + DOF)
1615
1616
1617 PetscFunctionBeginUser;
1618
1620
1621 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1622
1623 // --- Validation ---
1624 ierr = DMDAGetInfo(countDM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &count_dof, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
1625 ierr = DMDAGetInfo(dataDM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &data_dof, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
1626 if (count_dof != 1) { PetscSNPrintf(msg, sizeof(msg), "countDM must have DOF=1, got %d.", count_dof); SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "%s", msg); }
1627 if (data_dof != 1 && data_dof != 3) { PetscSNPrintf(msg, sizeof(msg), "dataDM DOF must be 1 or 3, got %d.", data_dof); SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "%s", msg); }
1628
1629 // --- Get Array Access using appropriate DMDA accessors ---
1630 ierr = DMDAVecGetArrayRead(countDM, countVec, &count_arr_3d); CHKERRQ(ierr);
1631
1632 if (data_dof == 1) {
1633 ierr = DMDAVecGetArrayRead(dataDM, sumVec, &sum_arr_scalar); CHKERRQ(ierr);
1634 ierr = DMDAVecGetArray(dataDM, avgVec, &avg_arr_scalar); CHKERRQ(ierr);
1635 } else { // data_dof == 3
1636 ierr = DMDAVecGetArrayDOFRead(dataDM, sumVec, &sum_arr_vector); CHKERRQ(ierr);
1637 ierr = DMDAVecGetArrayDOF(dataDM, avgVec, &avg_arr_vector); CHKERRQ(ierr);
1638 }
1639
1640 // Get the corners (global start indices) and dimensions of the *local owned* region
1641 PetscInt xs, ys, zs, xm, ym, zm;
1642 ierr = DMDAGetCorners(countDM, &xs, &ys, &zs, &xm, &ym, &zm); CHKERRQ(ierr);
1643
1644 // --- Normalize Over Owned Cells ---
1645 LOG_ALLOW(LOCAL, LOG_DEBUG, "(Rank %d): Normalizing DOF=%d data over owned range [%d:%d, %d:%d, %d:%d].\n",
1646 rank, data_dof, xs, xs+xm, ys, ys+ym, zs, zs+zm);
1647
1648 // Loop using GLOBAL indices (i, j, k) over the range owned by this process
1649 for (PetscInt k = zs; k < zs + zm; ++k) {
1650 for (PetscInt j = ys; j < ys + ym; ++j) {
1651 for (PetscInt i = xs; i < xs + xm; ++i) {
1652
1653 // Access the count using standard 3D indexing
1654 PetscScalar count = count_arr_3d[k][j][i];
1655
1656 if (PetscRealPart(count) > 0.5) { // Use tolerance for float comparison
1657 if (data_dof == 1) {
1658 // Access scalar sum/avg using standard 3D indexing
1659 avg_arr_scalar[k][j][i] = sum_arr_scalar[k][j][i] / count;
1660 } else { // data_dof == 3
1661 // Access vector components using DOF indexing on the last dimension
1662 for (PetscInt c = 0; c < data_dof; ++c) {
1663 avg_arr_vector[k][j][i][c] = sum_arr_vector[k][j][i][c] / count;
1664 }
1665 }
1666 } else { // count is zero or negative
1667 // Set average to zero
1668 if (data_dof == 1) {
1669 avg_arr_scalar[k][j][i] = 0.0;
1670 } else { // data_dof == 3
1671 for (PetscInt c = 0; c < data_dof; ++c) {
1672 avg_arr_vector[k][j][i][c] = 0.0;
1673 }
1674 }
1675 } // end if count > 0.5
1676 } // end i loop
1677 } // end j loop
1678 } // end k loop
1679
1680 // --- Restore Arrays using appropriate functions ---
1681 ierr = DMDAVecRestoreArrayRead(countDM, countVec, &count_arr_3d); CHKERRQ(ierr);
1682 if (data_dof == 1) {
1683 ierr = DMDAVecRestoreArrayRead(dataDM, sumVec, &sum_arr_scalar); CHKERRQ(ierr);
1684 ierr = DMDAVecRestoreArray(dataDM, avgVec, &avg_arr_scalar); CHKERRQ(ierr);
1685 } else { // data_dof == 3
1686 ierr = DMDAVecRestoreArrayDOFRead(dataDM, sumVec, &sum_arr_vector); CHKERRQ(ierr);
1687 ierr = DMDAVecRestoreArrayDOF(dataDM, avgVec, &avg_arr_vector); CHKERRQ(ierr);
1688 }
1689
1690 // --- Assemble Final Average Vector ---
1691 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Assembling final average vector (DOF=%d).\n", data_dof);
1692 ierr = VecAssemblyBegin(avgVec); CHKERRQ(ierr);
1693 ierr = VecAssemblyEnd(avgVec); CHKERRQ(ierr);
1694
1695
1697
1698 PetscFunctionReturn(0);
1699}
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:45
#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_DEBUG
Detailed debugging information.
Definition logging.h:32
Here is the caller graph for this function: