PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
Modules | Functions
Particle-to-Grid Scattering

Functions for scattering particle data (scalar or vector) onto Eulerian grid fields by averaging contributions within each cell. More...

Collaboration diagram for Particle-to-Grid Scattering:

Modules

 Internal Scattering Helpers
 Lower-level functions used by the main scattering routines.
 

Functions

PetscErrorCode GetScatterTargetInfo (UserCtx *user, const char *particleFieldName, DM *targetDM, PetscInt *expected_dof)
 Determines the target Eulerian DM and expected DOF for scattering a given particle field.
 
PetscErrorCode ScatterParticleFieldToEulerField (UserCtx *user, const char *particleFieldName, Vec eulerFieldAverageVec)
 Scatters a particle field (scalar or vector) to the corresponding Eulerian field average.
 
PetscErrorCode ScatterAllParticleFieldsToEulerFields (UserCtx *user)
 Scatters a predefined set of particle fields to their corresponding Eulerian fields.
 
static PetscErrorCode ScatterParticleFieldToEulerField_Internal (UserCtx *user, const char *particleFieldName, DM targetDM, PetscInt expected_dof, Vec eulerFieldAverageVec)
 Internal helper implementation: ScatterParticleFieldToEulerField_Internal().
 

Detailed Description

Functions for scattering particle data (scalar or vector) onto Eulerian grid fields by averaging contributions within each cell.

This file provides a modular set of functions to perform particle-to-grid projection, specifically calculating cell-averaged quantities from particle properties. It assumes a PETSc environment using DMDA for the grids and DMSwarm for particles.

Key Features:

Dependencies:

Function Documentation

◆ GetScatterTargetInfo()

PetscErrorCode GetScatterTargetInfo ( UserCtx user,
const char *  particleFieldName,
DM *  targetDM,
PetscInt *  expected_dof 
)

Determines the target Eulerian DM and expected DOF for scattering a given particle field.

Based on hardcoded rules mapping particle field names to user context DMs (da/fda). This function encapsulates the policy of where different fields should be scattered.

Parameters
[in]userPointer to the UserCtx containing da and fda.
[in]particleFieldNameName of the particle field (e.g., "P", "Ucat").
[out]targetDMPointer to store the determined target DM (da or fda).
[out]expected_dofPointer to store the expected DOF (1 or 3) for this field.
Returns
PetscErrorCode Returns 0 on success, PETSC_ERR_ARG_UNKNOWN if field name is not recognized, or PETSC_ERR_ARG_NULL for NULL inputs.

Definition at line 1486 of file interpolation.c.

1488{
1489 char msg[ERROR_MSG_BUFFER_SIZE]; // Buffer for formatted error messages
1490 PetscFunctionBeginUser;
1491
1493
1494 // --- Input Validation ---
1495 // Check for NULL pointers in essential inputs
1496 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx pointer is NULL.");
1497 if (!user->da) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx->da is NULL.");
1498 if (!user->fda) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx->fda is NULL."); // Needed for vector fields
1499 if (!particleFieldName) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "particleFieldName is NULL.");
1500 if (!targetDM) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output targetDM pointer is NULL.");
1501 if (!expected_dof) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output expected_dof pointer is NULL.");
1502
1503 // --- Determine Target DM and DOF based on Field Name ---
1504 // Compare the input field name with known scalar fields targeting 'da'
1505 if (strcmp(particleFieldName, "Psi") == 0 || strcmp(particleFieldName, "Nvert") == 0) {
1506 *expected_dof = 1; // Scalar fields have DOF 1
1507 *targetDM = user->da; // Target the primary scalar DMDA
1508 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Field '%s' targets DM 'da' (DOF=1).\n", particleFieldName);
1509 }
1510 // Compare with known vector fields targeting 'fda'
1511 else if (strcmp(particleFieldName, "Ucat") == 0 || strcmp(particleFieldName, "Ucont") == 0) {
1512 *expected_dof = 3; // Vector fields have DOF 3
1513 *targetDM = user->fda; // Target the vector DMDA (often node-based)
1514 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Field '%s' targets DM 'fda' (DOF=3).\n", particleFieldName);
1515 }
1516 // --- Add rules for other fields here ---
1517 // else if (strcmp(particleFieldName, "SomeOtherScalar") == 0) { *expected_dof = 1; *targetDM = user->da; }
1518 // else if (strcmp(particleFieldName, "SomeOtherVector") == 0) { *expected_dof = 3; *targetDM = user->someOtherDM; }
1519 else {
1520 // The provided field name doesn't match any known rules
1521 *targetDM = NULL; // Indicate failure
1522 *expected_dof = 0;
1523 // Format the error message manually
1524 PetscSNPrintf(msg, sizeof(msg), "Field name '%s' is not recognized for automatic DM selection.", particleFieldName);
1525 // Use SETERRQ with the formatted message and appropriate error code
1526 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "%s", msg); // Use WRONG argument error code
1527 }
1528
1530
1531 PetscFunctionReturn(0);
1532}
#define ERROR_MSG_BUFFER_SIZE
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:45
#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:199
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:779
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:31
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:770
Here is the caller graph for this function:

◆ ScatterParticleFieldToEulerField()

PetscErrorCode ScatterParticleFieldToEulerField ( UserCtx user,
const char *  particleFieldName,
Vec  eulerFieldAverageVec 
)

Scatters a particle field (scalar or vector) to the corresponding Eulerian field average.

This is the main user-facing function. It determines the target Eulerian DM based on the particleFieldName, validates the provided eulerFieldAverageVec against the target DM, and then orchestrates the scatter operation by calling the internal helper function ScatterParticleFieldToEulerField_Internal. The final averaged result is stored IN-PLACE in eulerFieldAverageVec.

Parameters
[in]userPointer to UserCtx containing da, fda, swarm, ParticleCount.
[in]particleFieldNameName of the field in the DMSwarm (e.g., "P", "Ucat").
[in,out]eulerFieldAverageVecPre-created Vec associated with the correct target DM (implicitly da or fda). Result stored here.
Returns
PetscErrorCode 0 on success. Errors on NULL input, unrecognized field name, or incompatible target vector.

Definition at line 1895 of file interpolation.c.

1898{
1899 PetscErrorCode ierr;
1900 DM targetDM = NULL; // Will point to user->da or user->fda
1901 PetscInt expected_dof = 0; // Will be 1 or 3
1902 char msg[ERROR_MSG_BUFFER_SIZE]; // Buffer for formatted error messages
1903
1904 PetscFunctionBeginUser;
1905
1907
1908 // --- Essential Input Validation ---
1909 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx pointer is NULL.");
1910 if (!user->swarm) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx->swarm is NULL.");
1911 if (!user->ParticleCount) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx->ParticleCount is NULL.");
1912 if (!eulerFieldAverageVec) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output eulerFieldAverageVec is NULL.");
1913 // particleFieldName validity checked within GetScatterTargetInfo
1914
1915 // --- Determine Target DM & DOF using the helper function ---
1916 ierr = GetScatterTargetInfo(user, particleFieldName, &targetDM, &expected_dof); CHKERRQ(ierr);
1917 // If GetScatterTargetInfo failed (e.g., unknown name), CHKERRQ would have returned.
1918
1919 // --- Validate the provided Target Vec's Compatibility ---
1920 DM vec_dm;
1921 PetscInt vec_dof;
1922 // Check that the provided average vector has a DM associated with it
1923 ierr = VecGetDM(eulerFieldAverageVec, &vec_dm); CHKERRQ(ierr);
1924 if (!vec_dm) {
1925 PetscSNPrintf(msg, sizeof(msg), "Provided eulerFieldAverageVec for field '%s' does not have an associated DM.", particleFieldName);
1926 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "%s", msg);
1927 }
1928 // Get the block size (DOF) of the provided vector
1929 ierr = VecGetBlockSize(eulerFieldAverageVec, &vec_dof); CHKERRQ(ierr);
1930 // Compare the vector's associated DM with the one determined by the field name
1931 if (vec_dm != targetDM) {
1932 const char *target_dm_name = "targetDM", *vec_dm_name = "vec_dm";
1933 // Get actual names if possible for a more informative error message
1934 PetscObjectGetName((PetscObject)targetDM, &target_dm_name);
1935 PetscObjectGetName((PetscObject)vec_dm, &vec_dm_name);
1936 PetscSNPrintf(msg, sizeof(msg), "Provided eulerFieldAverageVec associated with DM '%s', but field '%s' requires scatter to DM '%s'.", vec_dm_name, particleFieldName, target_dm_name);
1937 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "%s", msg);
1938 }
1939 // Compare the vector's DOF with the one expected for the field name
1940 if (vec_dof != expected_dof) {
1941 PetscSNPrintf(msg, sizeof(msg), "Field '%s' requires DOF %d, but provided eulerFieldAverageVec has DOF %d.", particleFieldName, expected_dof, vec_dof);
1942 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "%s", msg);
1943 }
1944
1945 // --- Perform Scatter using Internal Helper ---
1946 // Log intent before calling the core logic
1947 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Scattering field '%s' (DOF=%d).\n", particleFieldName, expected_dof);
1948 ierr = ScatterParticleFieldToEulerField_Internal(user, // Pass user context
1949 particleFieldName, // Name of particle field
1950 targetDM, // Determined target DM (da or fda)
1951 expected_dof, // Determined DOF (1 or 3)
1952 eulerFieldAverageVec); // The output vector
1953 CHKERRQ(ierr); // Handle potential errors from the internal function
1954
1955 LOG_ALLOW(GLOBAL, LOG_INFO, "Successfully scattered field '%s'.\n", particleFieldName);
1956
1958
1959 PetscFunctionReturn(0);
1960}
PetscErrorCode GetScatterTargetInfo(UserCtx *user, const char *particleFieldName, DM *targetDM, PetscInt *expected_dof)
Determines the target Eulerian DM and expected DOF for scattering a given particle field.
static PetscErrorCode ScatterParticleFieldToEulerField_Internal(UserCtx *user, const char *particleFieldName, DM targetDM, PetscInt expected_dof, Vec eulerFieldAverageVec)
Internal helper implementation: ScatterParticleFieldToEulerField_Internal().
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:30
Vec ParticleCount
Definition variables.h:882
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ScatterAllParticleFieldsToEulerFields()

PetscErrorCode ScatterAllParticleFieldsToEulerFields ( UserCtx user)

Scatters a predefined set of particle fields to their corresponding Eulerian fields.

This convenience function calls the unified ScatterParticleFieldToEulerField for a standard set of fields ("P", potentially others). It assumes the target Eulerian Vec objects (e.g., user->P, user->Ucat) exist in the UserCtx structure and are correctly associated with their respective DMs (user->da or user->fda). It zeros the target Vecs before scattering.

Parameters
[in,out]userPointer to the UserCtx structure containing all required DMs, Vecs (ParticleCount, target Eulerian fields like P, Ucat), and swarm.
Returns
PetscErrorCode 0 on success. Errors if prerequisites (like ParticleCount) are missing or if underlying scatter calls fail.

Definition at line 1965 of file interpolation.c.

1966{
1967 PetscErrorCode ierr;
1968 PetscFunctionBeginUser;
1970
1971 LOG_ALLOW(GLOBAL, LOG_INFO, "Starting scattering of specified particle fields to Eulerian grids.\n");
1972
1973 // --- Pre-computation Check: Ensure Particle Counts are Ready ---
1974 if (!user->ParticleCount) {
1975 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "UserCtx->ParticleCount is NULL. Compute counts before calling ScatterAllParticleFieldsToEulerFields.");
1976 }
1977
1978 // --- Scatter Particle Field "Psi" -> Eulerian Field user->Psi (on da) ---
1979 // Check if the target Eulerian vector 'user->Psi' exists.
1980 if (user->Psi) {
1981
1982 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Scattering particle field 'Psi' to user->Psi.\n");
1983 // Zero the target vector before accumulating the new average for this step/call.
1984
1985 // Debug Verification ------------------------------------------------
1986 Vec swarm_Psi;
1987 PetscReal Avg_Psi,Avg_swarm_Psi;
1988
1989 ierr = VecMean(user->Psi,&Avg_Psi);
1990 LOG_ALLOW(GLOBAL,LOG_DEBUG," Average of Scalar(Psi) before scatter: %.4f.\n",Avg_Psi);
1991
1992 ierr = DMSwarmCreateGlobalVectorFromField(user->swarm,"Psi",&swarm_Psi);
1993 ierr = VecMean(swarm_Psi,&Avg_swarm_Psi);
1994
1995 LOG_ALLOW(GLOBAL,LOG_DEBUG," Average of Particle Scalar(Psi): %.4f.\n",Avg_swarm_Psi);
1996
1997 ierr = DMSwarmDestroyGlobalVectorFromField(user->swarm,"Psi",&swarm_Psi);
1998 // Debug----------------------------------------------------------------
1999
2000 //ierr = VecSet(user->P, 0.0); CHKERRQ(ierr);
2001 // Call the unified scatter function. It will handle DM determination and validation.
2002 // It will also error out if the *particle* field "Psi" doesn't exist in the swarm.
2003 ierr = ScatterParticleFieldToEulerField(user, "Psi", user->Psi); CHKERRQ(ierr);
2004 ierr = VecMean(user->Psi,&Avg_Psi);
2005
2006 LOG_ALLOW(GLOBAL,LOG_DEBUG," Average of Scalar(Psi) after scatter: %.4f.\n",Avg_Psi);
2007 } else {
2008 // Only log a warning if the target Eulerian field is missing in the context.
2009 LOG_ALLOW(GLOBAL, LOG_WARNING, "Skipping scatter for 'Psi': UserCtx->Psi is NULL.\n");
2010 }
2011
2012 // --- (Commented Out) Scatter Other Fields ---
2013 // To enable scattering for other fields, uncomment the relevant block
2014 // AND ensure:
2015 // 1. The corresponding particle field (e.g., "Nvert", "Ucat") exists in user->swarm.
2016 // 2. The corresponding target Eulerian Vec (e.g., user->Nvert, user->Ucat) exists in user->ctx.
2017 // 3. The target Eulerian Vec is associated with the correct DM (da for Nvert, fda for Ucat).
2018
2019 /*
2020 // Scatter Particle Field "Nvert" -> Eulerian Field user->Nvert (on da)
2021 if (user->Nvert) {
2022 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Scattering particle field 'Nvert' to user->Nvert.\n");
2023 ierr = VecSet(user->Nvert, 0.0); CHKERRQ(ierr);
2024 ierr = ScatterParticleFieldToEulerField(user, "Nvert", user->Nvert); CHKERRQ(ierr);
2025 } else {
2026 LOG_ALLOW(GLOBAL, LOG_WARNING, "Skipping scatter for 'Nvert': UserCtx->Nvert is NULL.\n");
2027 }
2028 */
2029
2030 /*
2031 // Scatter Particle Field "Ucat" -> Eulerian Field user->Ucat (on fda)
2032 if (user->Ucat) {
2033 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Scattering particle field 'Ucat' to user->Ucat.\n");
2034 ierr = VecSet(user->Ucat, 0.0); CHKERRQ(ierr);
2035 ierr = ScatterParticleFieldToEulerField(user, "Ucat", user->Ucat); CHKERRQ(ierr);
2036 } else {
2037 LOG_ALLOW(GLOBAL, LOG_WARNING, "Skipping scatter for 'Ucat': UserCtx->Ucat is NULL.\n");
2038 }
2039 */
2040
2041 /*
2042 // Scatter Particle Field "Ucont" -> Eulerian Field user->Ucont (on fda)
2043 if (user->Ucont) {
2044 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Scattering particle field 'Ucont' to user->Ucont.\n");
2045 ierr = VecSet(user->Ucont, 0.0); CHKERRQ(ierr);
2046 ierr = ScatterParticleFieldToEulerField(user, "Ucont", user->Ucont); CHKERRQ(ierr);
2047 } else {
2048 LOG_ALLOW(GLOBAL, LOG_WARNING, "Skipping scatter for 'Ucont': UserCtx->Ucont is NULL.\n");
2049 }
2050 */
2051
2052 // Add more fields as needed following the pattern above...
2053
2054 LOG_ALLOW(GLOBAL, LOG_INFO, "Finished scattering specified particle fields.\n");
2056 PetscFunctionReturn(0);
2057}
PetscErrorCode ScatterParticleFieldToEulerField(UserCtx *user, const char *particleFieldName, Vec eulerFieldAverageVec)
Scatters a particle field (scalar or vector) to the corresponding Eulerian field average.
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:29
Vec Psi
Definition variables.h:883
Here is the call graph for this function:
Here is the caller graph for this function:

◆ ScatterParticleFieldToEulerField_Internal()

static PetscErrorCode ScatterParticleFieldToEulerField_Internal ( UserCtx user,
const char *  particleFieldName,
DM  targetDM,
PetscInt  expected_dof,
Vec  eulerFieldAverageVec 
)
static

Internal helper implementation: ScatterParticleFieldToEulerField_Internal().

Local to this translation unit.

Definition at line 1809 of file interpolation.c.

1814{
1815 PetscErrorCode ierr;
1816 PetscInt target_dof = 0;
1817 Vec globalsumVec = NULL;
1818 Vec localsumVec = NULL;
1819 char msg[ERROR_MSG_BUFFER_SIZE]; // Buffer for formatted error messages
1820
1821 PetscFunctionBeginUser;
1822
1824
1825 if (!user || !user->swarm || !user->ParticleCount || !particleFieldName || !targetDM || !eulerFieldAverageVec)
1826 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "NULL input provided to ScatterParticleFieldToEulerField_Internal.");
1827
1828 ierr = DMDAGetInfo(targetDM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &target_dof, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
1829 if (target_dof != expected_dof) {
1830 PetscSNPrintf(msg, sizeof(msg),
1831 "Field '%s' expects DOF %d but targetDM reports DOF %d.",
1832 particleFieldName, expected_dof, target_dof);
1833 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "%s", msg);
1834 }
1835
1836 // --- Check if Particle Field Exists ---
1837 // Attempt a GetField call; if it fails, the field doesn't exist.
1838 // We let CHKERRQ handle the error directly if the field doesn't exist OR
1839 // we catch it specifically to provide a more tailored message.
1840
1841 /*
1842 LOG_ALLOW(GLOBAL,LOG_DEBUG,"Field %s being accessed to check existence \n",particleFieldName);
1843 ierr = DMSwarmGetField(user->swarm, particleFieldName, NULL, NULL, NULL);
1844 if (ierr) { // If GetField returns an error
1845 PetscSNPrintf(msg, sizeof(msg), "Particle field '%s' not found in DMSwarm for scattering.", particleFieldName);
1846 // Directly set the error, overwriting the one from GetField
1847 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, msg);
1848 }
1849 ierr = DMSwarmRestoreField(user->swarm, particleFieldName, NULL, NULL, NULL);
1850 */
1851
1852 // --- Setup Temporary Sum Vector ---
1853 ierr = VecDuplicate(eulerFieldAverageVec, &globalsumVec); CHKERRQ(ierr);
1854 ierr = VecSet(globalsumVec, 0.0); CHKERRQ(ierr);
1855 ierr = PetscSNPrintf(msg, sizeof(msg), "TempSum_%s", particleFieldName); CHKERRQ(ierr);
1856 ierr = PetscObjectSetName((PetscObject)globalsumVec, msg); CHKERRQ(ierr);
1857
1858 // create local vector for accumulation
1859 ierr = DMGetLocalVector(targetDM, &localsumVec); CHKERRQ(ierr);
1860 ierr = VecSet(localsumVec, 0.0); CHKERRQ(ierr); // Must be zeroed before accumulation
1861 ierr = PetscSNPrintf(msg, sizeof(msg), "LocalTempSum_%s", particleFieldName); CHKERRQ(ierr);
1862 ierr = PetscObjectSetName((PetscObject)localsumVec, msg); CHKERRQ(ierr);
1863
1864 // --- Accumulate ---
1865 // This will call DMSwarmGetField again. If it failed above, it will likely fail here too,
1866 // unless the error was cleared somehow between the check and here (unlikely).
1867 // If the check above was skipped (Option 1), this is where the error for non-existent
1868 // field will be caught by CHKERRQ.
1869 ierr = AccumulateParticleField(user->swarm, particleFieldName, targetDM, localsumVec); CHKERRQ(ierr);
1870
1871 // --- Local to Global Sum ---
1872 ierr = DMLocalToGlobalBegin(targetDM, localsumVec, ADD_VALUES, globalsumVec); CHKERRQ(ierr);
1873 ierr = DMLocalToGlobalEnd(targetDM, localsumVec, ADD_VALUES, globalsumVec); CHKERRQ(ierr);
1874 // Return local vector to DM
1875 ierr = DMRestoreLocalVector(targetDM, &localsumVec); CHKERRQ(ierr);
1876
1877 // Calculate the number of particles per cell.
1878 ierr = CalculateParticleCountPerCell(user); CHKERRQ(ierr);
1879 // --- Normalize ---
1880 ierr = NormalizeGridVectorByCount(user->da, user->ParticleCount, targetDM, globalsumVec, eulerFieldAverageVec); CHKERRQ(ierr);
1881
1882 // --- Cleanup ---
1883 ierr = VecDestroy(&globalsumVec); CHKERRQ(ierr);
1884
1885
1887
1888 PetscFunctionReturn(0);
1889}
PetscErrorCode CalculateParticleCountPerCell(UserCtx *user)
Counts particles in each cell of the DMDA 'da' and stores the result in user->ParticleCount.
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.
PetscErrorCode AccumulateParticleField(DM swarm, const char *particleFieldName, DM gridSumDM, Vec gridSumVec)
Accumulates a particle field (scalar or vector) into a target grid sum vector.
Here is the call graph for this function:
Here is the caller graph for this function: