PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
Macros | Functions
interpolation.h File Reference
#include <petscpf.h>
#include <petscdmswarm.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <petsctime.h>
#include <petscdmcomposite.h>
#include <petscerror.h>
#include <petscsys.h>
#include "variables.h"
#include "ParticleSwarm.h"
#include "walkingsearch.h"
#include "grid.h"
#include "logging.h"
#include "io.h"
#include "setup.h"
Include dependency graph for interpolation.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define NUM_WEIGHTS   8
 
#define InterpolateFieldFromCornerToCenter(field, centfield, user)
 Generic macro to call the appropriate interpolation function based on the field type.
 
#define InterpolateFieldFromCenterToCorner(blockSize, centfield_ptr, corner_ptr, user_ctx)
 Macro to dispatch to the correct scalar or vector center-to-corner function based on a runtime block size variable.
 
#define InterpolateCornerToFaceCenter(corner_arr, faceX_arr, faceY_arr, faceZ_arr, user_ctx)
 A type-generic macro that interpolates a field from corner nodes to all face centers.
 
#define PieceWiseLinearInterpolation(fieldName, fieldPtr, i, j, k, outPtr)
 Macro that calls either the scalar or vector piecewise interpolation function based on the type of the fieldPtr parameter (3D array).
 
#define TrilinearInterpolation(fieldName, fieldPtr, i, j, k, a1, a2, a3, outPtr)
 Macro that calls either the scalar or vector trilinear interpolation function based on the type of the fieldPtr parameter (3D array).
 

Functions

PetscErrorCode PieceWiseLinearInterpolation_Scalar (const char *fieldName, PetscReal ***fieldScal, PetscInt iCell, PetscInt jCell, PetscInt kCell, PetscReal *val)
 Returns the scalar value from the input cell index without blending.
 
PetscErrorCode PieceWiseLinearInterpolation_Vector (const char *fieldName, Cmpnts ***fieldVec, PetscInt iCell, PetscInt jCell, PetscInt kCell, Cmpnts *vec)
 Returns the vector value from the input cell index without blending.
 
PetscErrorCode TrilinearInterpolation_Scalar (const char *fieldName, PetscReal ***fieldScal, PetscInt i, PetscInt j, PetscInt k, PetscReal a1, PetscReal a2, PetscReal a3, PetscReal *val)
 Computes the trilinear interpolated scalar at a given point.
 
PetscErrorCode TrilinearInterpolation_Vector (const char *fieldName, Cmpnts ***fieldVec, PetscInt i, PetscInt j, PetscInt k, PetscReal a1, PetscReal a2, PetscReal a3, Cmpnts *vec)
 Computes the trilinear interpolated vector (e.g., velocity) at a given point.
 
PetscErrorCode InterpolateEulerFieldToSwarm (UserCtx *user, FieldId source_field_id, ParticleFieldId target_field_id)
 Interpolates a cell-centered field (scalar or vector) onto DMSwarm particles, using a robust, PETSc-idiomatic two-stage process.
 
PetscErrorCode InterpolateAllFieldsToSwarm (UserCtx *user)
 Interpolates all relevant fields from the DMDA to the DMSwarm.
 
PetscErrorCode InterpolateParticleVelocities (UserCtx *user)
 Interpolates particle velocities using trilinear interpolation.
 
PetscErrorCode InterpolateFieldFromCornerToCenter_Scalar (PetscReal ***field_arr, PetscReal ***centfield_arr, UserCtx *user)
 Safely interpolate a scalar field from corner nodes (from the coordinate DM) to cell centers (from the cell-centered DM) using the provided UserCtx.
 
PetscErrorCode InterpolateFieldFromCornerToCenter_Vector (Cmpnts ***field_arr, Cmpnts ***centfield_arr, UserCtx *user)
 Safely interpolate a vector field from corner nodes (from the coordinate DM) to cell centers (from the cell-centered DM) using the provided UserCtx.
 
PetscErrorCode TestCornerToCenterInterpolation (UserCtx *user)
 Tests the InterpolateFieldFromCornerToCenter function by reproducing the Cent vector.
 
PetscErrorCode InterpolateFieldFromCenterToCorner_Vector (Cmpnts ***centfield_arr, Cmpnts ***corner_arr, UserCtx *user)
 Interpolates a vector field from cell centers to corner nodes.
 
PetscErrorCode InterpolateFieldFromCenterToCorner_Scalar (PetscReal ***centfield_arr, PetscReal ***corner_arr, UserCtx *user)
 Interpolates a scalar field from cell centers to corner nodes.
 
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.
 
PetscErrorCode ScatterParticleFieldToEulerField (UserCtx *user, ParticleFieldId particle_field_id, 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.
 
PetscErrorCode InterpolateCornerToFaceCenter_Scalar (PetscReal ***corner_arr, PetscReal ***faceX_arr, PetscReal ***faceY_arr, PetscReal ***faceZ_arr, UserCtx *user)
 Interpolates a scalar field from corner nodes to all face centers.
 
PetscErrorCode InterpolateCornerToFaceCenter_Vector (Cmpnts ***corner_arr, Cmpnts ***faceX_arr, Cmpnts ***faceY_arr, Cmpnts ***faceZ_arr, UserCtx *user)
 Interpolates a vector field from corner nodes to all face centers.
 

Macro Definition Documentation

◆ NUM_WEIGHTS

#define NUM_WEIGHTS   8

Definition at line 24 of file interpolation.h.

◆ InterpolateFieldFromCornerToCenter

#define InterpolateFieldFromCornerToCenter (   field,
  centfield,
  user 
)
Value:
( (void)sizeof(char[1 - 2*!!(!__builtin_types_compatible_p(typeof(field), typeof(centfield)))]),\
_Generic((field), \
)(field, centfield, user) )
PetscErrorCode InterpolateFieldFromCornerToCenter_Vector(Cmpnts ***field_arr, Cmpnts ***centfield_arr, UserCtx *user)
Safely interpolate a vector field from corner nodes (from the coordinate DM) to cell centers (from th...
PetscErrorCode InterpolateFieldFromCornerToCenter_Scalar(PetscReal ***field_arr, PetscReal ***centfield_arr, UserCtx *user)
Safely interpolate a scalar field from corner nodes (from the coordinate DM) to cell centers (from th...
A 3D point or vector with PetscScalar components.
Definition variables.h:102

Generic macro to call the appropriate interpolation function based on the field type.

This macro will select either the scalar or vector interpolation function based on the type of the 'field' pointer. It also performs a compile-time check that 'centfield' is of the same type as 'field'. If the types are not the same, a compile-time error is produced.

Usage: InterpolateFieldFromCornerToCenter(field, centfield, user);

Definition at line 36 of file interpolation.h.

◆ InterpolateFieldFromCenterToCorner

#define InterpolateFieldFromCenterToCorner (   blockSize,
  centfield_ptr,
  corner_ptr,
  user_ctx 
)
Value:
( (blockSize) == 1 ? \
InterpolateFieldFromCenterToCorner_Scalar((PetscReal***)(centfield_ptr), (PetscReal***)(corner_ptr), (user_ctx)) : \
InterpolateFieldFromCenterToCorner_Vector((Cmpnts***)(centfield_ptr), (Cmpnts***)(corner_ptr), (user_ctx)) \
)
PetscErrorCode InterpolateFieldFromCenterToCorner_Vector(Cmpnts ***centfield_arr, Cmpnts ***corner_arr, UserCtx *user)
Interpolates a vector field from cell centers to corner nodes.
PetscErrorCode InterpolateFieldFromCenterToCorner_Scalar(PetscReal ***centfield_arr, PetscReal ***corner_arr, UserCtx *user)
Interpolates a scalar field from cell centers to corner nodes.

Macro to dispatch to the correct scalar or vector center-to-corner function based on a runtime block size variable.

This macro uses a ternary operator to inspect the runtime value of 'blockSize' and select the appropriate implementation. It expects the input and output pointers to be void* and handles casting them to the correct, strongly-typed pointers.

Parameters
blockSizeThe runtime block size (1 for scalar, 3 for vector).
centfield_ptrThe input void* pointer to the 3D cell-centered data array.
corner_ptrThe output void* pointer to the 3D corner data array.
user_ctxThe UserCtx structure.

Definition at line 56 of file interpolation.h.

58 : \
59 InterpolateFieldFromCenterToCorner_Vector((Cmpnts***)(centfield_ptr), (Cmpnts***)(corner_ptr), (user_ctx)) \
60 )

◆ InterpolateCornerToFaceCenter

#define InterpolateCornerToFaceCenter (   corner_arr,
  faceX_arr,
  faceY_arr,
  faceZ_arr,
  user_ctx 
)
Value:
_Generic((corner_arr), \
)(corner_arr, faceX_arr, faceY_arr, faceZ_arr, user_ctx)
PetscErrorCode InterpolateCornerToFaceCenter_Vector(Cmpnts ***corner_arr, Cmpnts ***faceX_arr, Cmpnts ***faceY_arr, Cmpnts ***faceZ_arr, UserCtx *user)
Interpolates a vector field from corner nodes to all face centers.
PetscErrorCode InterpolateCornerToFaceCenter_Scalar(PetscReal ***corner_arr, PetscReal ***faceX_arr, PetscReal ***faceY_arr, PetscReal ***faceZ_arr, UserCtx *user)
Interpolates a scalar field from corner nodes to all face centers.

A type-generic macro that interpolates a field from corner nodes to all face centers.

This macro uses C11's _Generic feature to dispatch to the appropriate underlying function based on the type of the input corner_arr.

  • If corner_arr is of type PetscReal***, it calls InterpolateCornerToFaceCenter_Scalar.
  • If corner_arr is of type Cmpnts***, it calls InterpolateCornerToFaceCenter_Vector.
Parameters
corner_arrGhosted node-centered array (global indexing). The type of this argument determines which function is called.
faceX_arrLocal array for X-faces.
faceY_arrLocal array for Y-faces.
faceZ_arrLocal array for Z-faces.
user_ctxUser context containing DMDA 'fda'.

Definition at line 79 of file interpolation.h.

83 )(corner_arr, faceX_arr, faceY_arr, faceZ_arr, user_ctx)

◆ PieceWiseLinearInterpolation

#define PieceWiseLinearInterpolation (   fieldName,
  fieldPtr,
  i,
  j,
  k,
  outPtr 
)
Value:
_Generic((fieldPtr), \
)(fieldName, fieldPtr, i, j, k, outPtr)
PetscErrorCode PieceWiseLinearInterpolation_Scalar(const char *fieldName, PetscReal ***fieldScal, PetscInt iCell, PetscInt jCell, PetscInt kCell, PetscReal *val)
Returns the scalar value from the input cell index without blending.
PetscErrorCode PieceWiseLinearInterpolation_Vector(const char *fieldName, Cmpnts ***fieldVec, PetscInt iCell, PetscInt jCell, PetscInt kCell, Cmpnts *vec)
Returns the vector value from the input cell index without blending.

Macro that calls either the scalar or vector piecewise interpolation function based on the type of the fieldPtr parameter (3D array).

Usage example:

// For scalar: PetscReal ***fieldScal; PetscReal outVal; PieceWiseLinearInterpolation(fieldName, fieldScal, i, j, k, &outVal);

// For vector: Cmpnts ***fieldVec; Cmpnts vec; PieceWiseLinearInterpolation(fieldName, fieldVec, i, j, k, &vec);

Definition at line 101 of file interpolation.h.

105 )(fieldName, fieldPtr, i, j, k, outPtr)

◆ TrilinearInterpolation

#define TrilinearInterpolation (   fieldName,
  fieldPtr,
  i,
  j,
  k,
  a1,
  a2,
  a3,
  outPtr 
)
Value:
_Generic((fieldPtr), \
)(fieldName, fieldPtr, i, j, k, a1, a2, a3, outPtr)
PetscErrorCode TrilinearInterpolation_Vector(const char *fieldName, Cmpnts ***fieldVec, PetscInt i, PetscInt j, PetscInt k, PetscReal a1, PetscReal a2, PetscReal a3, Cmpnts *vec)
Computes the trilinear interpolated vector (e.g., velocity) at a given point.
PetscErrorCode TrilinearInterpolation_Scalar(const char *fieldName, PetscReal ***fieldScal, PetscInt i, PetscInt j, PetscInt k, PetscReal a1, PetscReal a2, PetscReal a3, PetscReal *val)
Computes the trilinear interpolated scalar at a given point.

Macro that calls either the scalar or vector trilinear interpolation function based on the type of the fieldPtr parameter (3D array).

Usage example:

PetscReal result; Cmpnts vec;

// For scalars: TrilinearInterpolation(fieldName, fieldScal, i, j, k, a1, a2, a3, &result);

// For vectors: TrilinearInterpolation(fieldName, fieldVec, i, j, k, a1, a2, a3, &vec);

Definition at line 166 of file interpolation.h.

170 )(fieldName, fieldPtr, i, j, k, a1, a2, a3, outPtr)

Function Documentation

◆ PieceWiseLinearInterpolation_Scalar()

PetscErrorCode PieceWiseLinearInterpolation_Scalar ( const char *  fieldName,
PetscReal ***  fieldScal,
PetscInt  iCell,
PetscInt  jCell,
PetscInt  kCell,
PetscReal *  val 
)

Returns the scalar value from the input cell index without blending.

This is a first-order piecewise-constant lookup helper used in workflows that intentionally disable trilinear blending.

Parameters
[in]fieldNameField label used for diagnostics.
[in]fieldScalScalar field array indexed as [k][j][i].
[in]iCellCell i-index.
[in]jCellCell j-index.
[in]kCellCell k-index.
[out]valOutput scalar value.
Returns
PetscErrorCode 0 on success.

Returns the scalar value from the input cell index without blending.

Local to this translation unit.

Definition at line 462 of file interpolation.c.

469{
470 PetscFunctionBegin;
471 *val = fieldScal[kCell][jCell][iCell];
472
473 // Optional logging
475 "Field '%s' at (i=%d, j=%d, k=%d) => val=%.6f\n",
476 fieldName, iCell, jCell, kCell, *val);
477
478 PetscFunctionReturn(0);
479}
#define LOCAL
Logging scope definitions for controlling message output.
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:200
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
Definition logging.h:34

◆ PieceWiseLinearInterpolation_Vector()

PetscErrorCode PieceWiseLinearInterpolation_Vector ( const char *  fieldName,
Cmpnts ***  fieldVec,
PetscInt  iCell,
PetscInt  jCell,
PetscInt  kCell,
Cmpnts vec 
)

Returns the vector value from the input cell index without blending.

This is a first-order piecewise-constant lookup helper used in workflows that intentionally disable trilinear blending.

Parameters
[in]fieldNameField label used for diagnostics.
[in]fieldVecVector field array indexed as [k][j][i].
[in]iCellCell i-index.
[in]jCellCell j-index.
[in]kCellCell k-index.
[out]vecOutput vector value.
Returns
PetscErrorCode 0 on success.

Returns the vector value from the input cell index without blending.

Local to this translation unit.

Definition at line 487 of file interpolation.c.

494{
495 PetscFunctionBegin;
496 vec->x = fieldVec[kCell][jCell][iCell].x;
497 vec->y = fieldVec[kCell][jCell][iCell].y;
498 vec->z = fieldVec[kCell][jCell][iCell].z;
499
500 // Optional logging
502 "Field '%s' at (i=%d, j=%d, k=%d) => (x=%.6f, y=%.6f, z=%.6f)\n",
503 fieldName, iCell, jCell, kCell, vec->x, vec->y, vec->z);
504
505 PetscFunctionReturn(0);
506}
PetscScalar x
Definition variables.h:103
PetscScalar z
Definition variables.h:103
PetscScalar y
Definition variables.h:103

◆ TrilinearInterpolation_Scalar()

PetscErrorCode TrilinearInterpolation_Scalar ( const char *  fieldName,
PetscReal ***  fieldScal,
PetscInt  i,
PetscInt  j,
PetscInt  k,
PetscReal  a1,
PetscReal  a2,
PetscReal  a3,
PetscReal *  val 
)

Computes the trilinear interpolated scalar at a given point.

each cell a PetscReal. This function uses the standard 8-corner trilinear formula via ComputeTrilinearWeights(). If a different scheme is desired, implement a new function with the same interface.

Parameters
fieldNameA
fieldScal3D
iIntegral
jIntegral
kIntegral
a1Normalized
a2Normalized
a3Normalized
valPointer
Returns
PetscErrorCode 0 on success.

Computes the trilinear interpolated scalar at a given point.

Local to this translation unit.

Definition at line 576 of file interpolation.c.

586{
587 PetscFunctionBegin; // PETSc macro for error/stack tracing
588
589 // Compute the 8 corner weights
590 PetscReal wcorner[8];
591 ComputeTrilinearWeights(a1, a2, a3, wcorner);
592
593 // Offsets for cell corners
594 PetscInt i1 = i + 1;
595 PetscInt j1 = j + 1;
596 PetscInt k1 = k + 1;
597
598 // Initialize the output scalar
599 PetscReal sum = 0.0;
600
601 // Corner 0 => (i, j, k)
602 sum += wcorner[0] * fieldScal[k ][j ][i ];
603 // Corner 1 => (i+1, j, k)
604 sum += wcorner[1] * fieldScal[k ][j ][i1];
605 // Corner 2 => (i, j+1, k)
606 sum += wcorner[2] * fieldScal[k ][j1][i ];
607 // Corner 3 => (i+1, j+1, k)
608 sum += wcorner[3] * fieldScal[k ][j1][i1];
609 // Corner 4 => (i, j, k+1)
610 sum += wcorner[4] * fieldScal[k1][j ][i ];
611 // Corner 5 => (i+1, j, k+1)
612 sum += wcorner[5] * fieldScal[k1][j ][i1];
613 // Corner 6 => (i, j+1, k+1)
614 sum += wcorner[6] * fieldScal[k1][j1][i ];
615 // Corner 7 => (i+1, j+1, k+1)
616 sum += wcorner[7] * fieldScal[k1][j1][i1];
617
618 *val = sum;
619
620 // Logging (optional)
622 "Field '%s' at (i=%d, j=%d, k=%d), "
623 "a1=%.6f, a2=%.6f, a3=%.6f -> val=%.6f.\n",
624 fieldName, i, j, k, a1, a2, a3, *val);
625
626 // LOG_ALLOW_SYNC(GLOBAL, LOG_INFO,
627 // "TrilinearInterpolation_Scalar: Completed interpolation for field '%s' across local cells.\n",
628 // fieldName);
629
630 PetscFunctionReturn(0);
631}
static void ComputeTrilinearWeights(PetscReal a1, PetscReal a2, PetscReal a3, PetscReal *w)
Compute the eight trilinear interpolation weights for a particle's local coordinates.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TrilinearInterpolation_Vector()

PetscErrorCode TrilinearInterpolation_Vector ( const char *  fieldName,
Cmpnts ***  fieldVec,
PetscInt  i,
PetscInt  j,
PetscInt  k,
PetscReal  a1,
PetscReal  a2,
PetscReal  a3,
Cmpnts vec 
)

Computes the trilinear interpolated vector (e.g., velocity) at a given point.

each cell of type Cmpnts. This function uses the standard 8-corner trilinear formula via ComputeTrilinearWeights(). If a different scheme is desired, implement a new function with the same interface.

Parameters
fieldNameA
fieldVec3D
iIntegral
jIntegral
kIntegral
a1Normalized
a2Normalized
a3Normalized
vecPointer
Returns
PetscErrorCode 0 on success.

Computes the trilinear interpolated vector (e.g., velocity) at a given point.

Local to this translation unit.

Definition at line 640 of file interpolation.c.

650{
651 PetscFunctionBegin; // PETSc macro for error/stack tracing
652
653 // Compute the 8 corner weights
654 PetscErrorCode ierr;
655 PetscReal wcorner[8];
656 PetscMPIInt rank;
657
658 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
659
660 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d] Computing Trilinear Weights.\n",rank);
661 ComputeTrilinearWeights(a1, a2, a3, wcorner);
662
663 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d] Trilinear weights computed for local cell %d,%d,%d.\n",rank,i,j,k);
664
665 // For partial interpolation, we'll keep track of how many corners are valid
666 // and how much sum of weights is used. Then we do a final normalization.
667 PetscReal sumW = 0.0;
668 Cmpnts accum = {0.0, 0.0, 0.0};
669
670 // The eight corner indices, with their weights:
671 // corners: (i,j,k), (i+1,j,k), (i,j+1,k), (i+1,j+1,k), etc.
672 // We store them in an array to iterate cleanly.
673 const PetscInt cornerOffsets[8][3] = {
674 {0, 0, 0},
675 {1, 0, 0},
676 {0, 1, 0},
677 {1, 1, 0},
678 {0, 0, 1},
679 {1, 0, 1},
680 {0, 1, 1},
681 {1, 1, 1}
682 };
683
684 // Weighted partial sum
685 for (PetscInt c = 0; c < 8; c++) {
686 const PetscInt di = cornerOffsets[c][0];
687 const PetscInt dj = cornerOffsets[c][1];
688 const PetscInt dk = cornerOffsets[c][2];
689 PetscInt iC = i + di;
690 PetscInt jC = j + dj;
691 PetscInt kC = k + dk;
692
693 /*
694 // skip if out of domain
695 // (Assuming you know global domain is [0..mx), [0..my), [0..mz).)
696 if (iC < 0 || iC >= (PetscInt)userGlobalMx ||
697 jC < 0 || jC >= (PetscInt)userGlobalMy ||
698 kC < 0 || kC >= (PetscInt)userGlobalMz)
699 {
700 // skip this corner
701 continue;
702 }
703
704 */
705
706 LOG_ALLOW(LOCAL,LOG_VERBOSE,"[Rank %d] %s[%d][%d][%d] = (%.4f,%.4f,%.4f).\n",rank,fieldName,kC,jC,iC,fieldVec[kC][jC][iC].x,fieldVec[kC][jC][iC].y,fieldVec[kC][jC][iC].z);
707
708 // Otherwise, accumulate
709 accum.x += wcorner[c] * fieldVec[kC][jC][iC].x;
710 accum.y += wcorner[c] * fieldVec[kC][jC][iC].y;
711 accum.z += wcorner[c] * fieldVec[kC][jC][iC].z;
712 sumW += wcorner[c];
713 }
714
715 // If sumW=0 => out-of-range or zero weighting => set (0,0,0)
716 if (sumW > 1.0e-14) {
717 vec->x = accum.x / sumW;
718 vec->y = accum.y / sumW;
719 vec->z = accum.z / sumW;
720 } else {
721 vec->x = 0.0; vec->y = 0.0; vec->z = 0.0;
722 }
723
724 PetscFunctionReturn(0);
725}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ InterpolateEulerFieldToSwarm()

PetscErrorCode InterpolateEulerFieldToSwarm ( UserCtx user,
FieldId  source_field_id,
ParticleFieldId  target_field_id 
)

Interpolates a cell-centered field (scalar or vector) onto DMSwarm particles, using a robust, PETSc-idiomatic two-stage process.

This function first converts the cell-centered input data to corner-node data, storing this intermediate result in a PETSc Vec to correctly handle the communication of ghost-point information across parallel ranks. It then performs a final trilinear interpolation from the ghosted corner data to each particle's location.

Workflow:

  1. Create temporary PETSc Vecs (cornerGlobal, cornerLocal) to manage the intermediate corner-node data, using the existing nodal DMDA (user->fda).
  2. Call a dispatch macro that uses the runtime block size (bs) to select the correct underlying center-to-corner function, writing results into cornerGlobal.
  3. Perform a ghost-point exchange (DMGlobalToLocal) to transfer the boundary data from cornerGlobal into the ghost regions of cornerLocal.
  4. Loop over all local particles. For each particle: a. Convert its global cell index to a local index relative to the ghosted array. b. Check if the particle's interpolation stencil is fully contained within the owned+ghost region. If not, log a warning and set the result to zero. c. Perform the final trilinear interpolation using the ghosted cornerLocal data.
  5. Restore all PETSc objects to prevent memory leaks.
Parameters
[in]userUser context with DMDA, DMSwarm, etc.
[in]source_field_idTyped identity of the cell-centered Eulerian source.
[in]target_field_idTyped identity of the PETSC_REAL particle destination.
Returns
PetscErrorCode 0 on success.

Interpolates a cell-centered field (scalar or vector) onto DMSwarm particles, using a robust, PETSc-idiomatic two-stage process.

Routes to InterpolateEulerFieldFromCenterToSwarm (direct trilinear, second-order) or InterpolateEulerFieldFromCornerToSwarm (corner-averaged, legacy) based on user->simCtx->interpolationMethod.

Definition at line 1353 of file interpolation.c.

1357{
1358 PetscErrorCode ierr;
1359 FieldView source_view;
1360 const ParticleFieldDescriptor *target_descriptor = NULL;
1361
1362 PetscFunctionBegin;
1363
1364 ierr = FieldGetView(user, source_field_id, &source_view); CHKERRQ(ierr);
1365 ierr = ParticleFieldGetDescriptor(target_field_id, &target_descriptor); CHKERRQ(ierr);
1366 PetscCheck(source_view.descriptor->layout == FIELD_LAYOUT_CELL_CENTERED,
1367 PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
1368 "Eulerian-to-particle interpolation requires a cell-centered source; '%s' uses layout %s.",
1369 source_view.descriptor->canonical_name,
1370 FieldLayoutName(source_view.descriptor->layout));
1371 PetscCheck(target_descriptor->data_type == PETSC_REAL,
1372 PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
1373 "Eulerian interpolation destination '%s' must use PETSC_REAL storage.",
1374 target_descriptor->canonical_name);
1375 PetscCheck(source_view.descriptor->dof == target_descriptor->components,
1376 PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
1377 "Eulerian source '%s' has %d components but particle destination '%s' has %d.",
1378 source_view.descriptor->canonical_name, source_view.descriptor->dof,
1379 target_descriptor->canonical_name, target_descriptor->components);
1380
1382 ierr = InterpolateEulerFieldFromCenterToSwarm(user, source_view.local_vec,
1383 source_view.descriptor->canonical_name,
1384 target_descriptor->canonical_name); CHKERRQ(ierr);
1385 } else {
1386 ierr = InterpolateEulerFieldFromCornerToSwarm(user, source_view.local_vec,
1387 source_view.descriptor->canonical_name,
1388 target_descriptor->canonical_name); CHKERRQ(ierr);
1389 }
1390
1391 PetscFunctionReturn(0);
1392}
FieldLayout layout
const FieldDescriptor * descriptor
PetscErrorCode FieldGetView(UserCtx *user, FieldId field_id, FieldView *view)
Resolve the existing DM and global/local vectors for one field.
@ FIELD_LAYOUT_CELL_CENTERED
const char * canonical_name
const char * FieldLayoutName(FieldLayout layout)
Return a stable printable label for a field layout.
Non-owning runtime objects resolved for one field and UserCtx.
static PetscErrorCode InterpolateEulerFieldFromCornerToSwarm(UserCtx *user, Vec fieldLocal_cellCentered, const char *fieldName, const char *swarmOutFieldName)
Corner-averaged interpolation path (legacy).
static PetscErrorCode InterpolateEulerFieldFromCenterToSwarm(UserCtx *user, Vec fieldLocal_cellCentered, const char *fieldName, const char *swarmOutFieldName)
Direct cell-center trilinear interpolation (second-order on curvilinear grids).
PetscErrorCode ParticleFieldGetDescriptor(ParticleFieldId field_id, const ParticleFieldDescriptor **descriptor)
Return immutable metadata for a valid particle field ID.
Immutable metadata for one persistent particle field.
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:909
InterpolationMethod interpolationMethod
Definition variables.h:832
@ INTERP_TRILINEAR
Definition variables.h:565
Here is the call graph for this function:
Here is the caller graph for this function:

◆ InterpolateAllFieldsToSwarm()

PetscErrorCode InterpolateAllFieldsToSwarm ( UserCtx user)

Interpolates all relevant fields from the DMDA to the DMSwarm.

Currently, it interpolates:

  • user->Ucat (vector field) into the DMSwarm field "swarmVelocity".

To add more fields, duplicate the call to InterpolateOneFieldOverSwarm and provide:

  • The global Vec for that field (e.g. user->Tcat for temperature),
  • A human-readable field name (for logging),
  • A DMSwarm output field name (e.g. "swarmTemperature").
Parameters
[in,out]userPointer to a UserCtx containing:
  • user->da (DM for the grid),
  • user->swarm (DMSwarm for particles),
  • user->Ucat (Vec for the vector field),
  • possibly more fields like user->Tcat, user->Pcat, etc.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

Interpolates all relevant fields from the DMDA to the DMSwarm.

Local to this translation unit.

Definition at line 1400 of file interpolation.c.

1401{
1402 PetscErrorCode ierr;
1403 PetscMPIInt rank;
1404 PetscFunctionBegin;
1405
1407
1408 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
1409
1411 " Interpolation of ucat to velocity begins on rank %d.\n",rank);
1413 PARTICLE_FIELD_ID_VELOCITY); CHKERRQ(ierr);
1415 PARTICLE_FIELD_ID_DIFFUSIVITY); CHKERRQ(ierr);
1418 /* Add fields as necessary here*/
1419
1420 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRQ(ierr);
1422 "[rank %d]Completed Interpolateting all fields to the swarm.\n",rank);
1423
1425
1426 PetscFunctionReturn(0);
1427}
@ FIELD_ID_UCAT
@ FIELD_ID_DIFFUSIVITY_GRADIENT
@ FIELD_ID_DIFFUSIVITY
PetscErrorCode InterpolateEulerFieldToSwarm(UserCtx *user, FieldId source_field_id, ParticleFieldId target_field_id)
Dispatches grid-to-particle interpolation to the method selected in the control file.
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:859
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:31
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:32
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:850
@ PARTICLE_FIELD_ID_DIFFUSIVITY_GRADIENT
@ PARTICLE_FIELD_ID_DIFFUSIVITY
@ PARTICLE_FIELD_ID_VELOCITY
Here is the call graph for this function:
Here is the caller graph for this function:

◆ InterpolateParticleVelocities()

PetscErrorCode InterpolateParticleVelocities ( UserCtx user)

Interpolates particle velocities using trilinear interpolation.

Parameters
[in]userPointer to the user-defined context containing grid and swarm information.
Returns
PetscErrorCode Returns 0 on success, non-zero on failure.

◆ InterpolateFieldFromCornerToCenter_Scalar()

PetscErrorCode InterpolateFieldFromCornerToCenter_Scalar ( PetscReal ***  field_arr,
PetscReal ***  centfield_arr,
UserCtx user 
)

Safely interpolate a scalar field from corner nodes (from the coordinate DM) to cell centers (from the cell-centered DM) using the provided UserCtx.

For each cell center in the physical region of the cell-centered DM (fda), this function averages the up to 8 surrounding scalar values from the coordinate DM (da). On boundaries, where fewer corners are available, a partial average is computed.

The coordinate DM (da) is built on corners (IM+1 x JM+1 x KM+1) while the cell-centered DM (fda) covers the physical cells (IM x JM x KM). Index offsets are adjusted via DMDAGetLocalInfo.

Parameters
[in]field_arr3D array of corner-based scalar data (from user->da).
[out]centfield_arr3D array for interpolated cell-center scalar data (for user->fda).
[in]userUser context containing:
  • da : DM for the coordinate (corner) data.
  • fda : DM for the cell-centered data.
Returns
PetscErrorCode 0 on success.

Safely interpolate a scalar field from corner nodes (from the coordinate DM) to cell centers (from the cell-centered DM) using the provided UserCtx.

Local to this translation unit.

Definition at line 86 of file interpolation.c.

90{
91 PetscErrorCode ierr;
92 DMDALocalInfo info;
93
94 PetscFunctionBeginUser;
95
96 ierr = DMDAGetLocalInfo(user->da, &info); CHKERRQ(ierr);
97
98 // Get local and global grid dimensions
99 PetscInt xs = info.xs, xe = info.xs + info.xm;
100 PetscInt ys = info.ys, ye = info.ys + info.ym;
101 PetscInt zs = info.zs, ze = info.zs + info.zm;
102 PetscInt mx = info.mx, my = info.my, mz = info.mz;
103
104 // Determine loop bounds to compute for interior cells only, matching the code's convention.
105 // Start at index 1 if the process owns the global boundary at index 0.
106 PetscInt is = (xs == 0) ? 1 : xs;
107 PetscInt js = (ys == 0) ? 1 : ys;
108 PetscInt ks = (zs == 0) ? 1 : zs;
109
110 // Stop one cell short if the process owns the global boundary at the max index.
111 PetscInt ie = (xe == mx) ? xe - 1 : xe;
112 PetscInt je = (ye == my) ? ye - 1 : ye;
113 PetscInt ke = (ze == mz) ? ze - 1 : ze;
114
115 // Loop over the locally owned INTERIOR cells.
116 for (PetscInt k = ks; k < ke; k++) {
117 for (PetscInt j = js; j < je; j++) {
118 for (PetscInt i = is; i < ie; i++) {
119 // Calculate cell center value as the average of its 8 corner nodes
120 centfield_arr[k][j][i] = 0.125 * (field_arr[k][j][i] + field_arr[k][j-1][i] +
121 field_arr[k-1][j][i] + field_arr[k-1][j-1][i] +
122 field_arr[k][j][i-1] + field_arr[k][j-1][i-1] +
123 field_arr[k-1][j][i-1] + field_arr[k-1][j-1][i-1]);
124 }
125 }
126 }
127
128 PetscFunctionReturn(0);
129}
Here is the caller graph for this function:

◆ InterpolateFieldFromCornerToCenter_Vector()

PetscErrorCode InterpolateFieldFromCornerToCenter_Vector ( Cmpnts ***  field_arr,
Cmpnts ***  centfield_arr,
UserCtx user 
)

Safely interpolate a vector field from corner nodes (from the coordinate DM) to cell centers (from the cell-centered DM) using the provided UserCtx.

For each cell center in the physical region of the cell-centered DM (fda), this function averages the 8 surrounding corner values from the coordinate DM (da). The coordinate DM (da) is built on corners (IM+1 x JM+1 x KM+1) while the cell-centered DM (fda) covers the physical cells (IM x JM x KM). Index offsets are adjusted using DMDAGetLocalInfo.

Parameters
[in]field_arr3D array of corner-based vector data (from user->da).
[out]centfield_arr3D array for interpolated cell-center vector data (for user->fda).
[in]userUser context containing:
  • da : DM for the coordinate (corner) data.
  • fda : DM for the cell-centered data.
Returns
PetscErrorCode 0 on success.

Safely interpolate a vector field from corner nodes (from the coordinate DM) to cell centers (from the cell-centered DM) using the provided UserCtx.

Local to this translation unit.

Definition at line 25 of file interpolation.c.

29{
30 PetscErrorCode ierr;
31 DMDALocalInfo info;
32
33 PetscFunctionBeginUser;
34
35 ierr = DMDAGetLocalInfo(user->fda, &info); CHKERRQ(ierr);
36
37 // Get local and global grid dimensions
38 PetscInt xs = info.xs, xe = info.xs + info.xm;
39 PetscInt ys = info.ys, ye = info.ys + info.ym;
40 PetscInt zs = info.zs, ze = info.zs + info.zm;
41 PetscInt mx = info.mx, my = info.my, mz = info.mz;
42
43 // Determine loop bounds to compute for interior cells only, matching the code's convention.
44 // Start at index 1 if the process owns the global boundary at index 0.
45 PetscInt is = (xs == 0) ? 1 : xs;
46 PetscInt js = (ys == 0) ? 1 : ys;
47 PetscInt ks = (zs == 0) ? 1 : zs;
48
49 // Stop one cell short if the process owns the global boundary at the max index.
50 PetscInt ie = (xe == mx) ? xe - 1 : xe;
51 PetscInt je = (ye == my) ? ye - 1 : ye;
52 PetscInt ke = (ze == mz) ? ze - 1 : ze;
53
54 // Loop over the locally owned INTERIOR cells.
55 for (PetscInt k = ks; k < ke; k++) {
56 for (PetscInt j = js; j < je; j++) {
57 for (PetscInt i = is; i < ie; i++) {
58 // Calculate cell center value as the average of its 8 corner nodes
59 centfield_arr[k][j][i].x = 0.125 * (field_arr[k][j][i].x + field_arr[k][j-1][i].x +
60 field_arr[k-1][j][i].x + field_arr[k-1][j-1][i].x +
61 field_arr[k][j][i-1].x + field_arr[k][j-1][i-1].x +
62 field_arr[k-1][j][i-1].x + field_arr[k-1][j-1][i-1].x);
63
64 centfield_arr[k][j][i].y = 0.125 * (field_arr[k][j][i].y + field_arr[k][j-1][i].y +
65 field_arr[k-1][j][i].y + field_arr[k-1][j-1][i].y +
66 field_arr[k][j][i-1].y + field_arr[k][j-1][i-1].y +
67 field_arr[k-1][j][i-1].y + field_arr[k-1][j-1][i-1].y);
68
69 centfield_arr[k][j][i].z = 0.125 * (field_arr[k][j][i].z + field_arr[k][j-1][i].z +
70 field_arr[k-1][j][i].z + field_arr[k-1][j-1][i].z +
71 field_arr[k][j][i-1].z + field_arr[k][j-1][i-1].z +
72 field_arr[k-1][j][i-1].z + field_arr[k-1][j-1][i-1].z);
73 }
74 }
75 }
76
77 PetscFunctionReturn(0);
78}
Here is the caller graph for this function:

◆ TestCornerToCenterInterpolation()

PetscErrorCode TestCornerToCenterInterpolation ( UserCtx user)

Tests the InterpolateFieldFromCornerToCenter function by reproducing the Cent vector.

This function serves as a unit test. It performs the following steps:

  1. Takes the corner-centered nodal coordinates (from DMGetCoordinatesLocal) as input.
  2. Uses the InterpolateFieldFromCornerToCenter macro to interpolate these coordinates to the cell centers, storing the result in a new temporary vector.
  3. Compares this new vector with the user->Cent vector, which is assumed to have been computed by ComputeCellCentersAndSpacing and serves as the ground truth.
  4. A 2-norm of the difference is computed. If it is below a small tolerance, the test passes.
Note
This function should be called immediately after ComputeCellCentersAndSpacing has been successfully executed.
Parameters
userThe UserCtx for a specific grid level.
Returns
PetscErrorCode 0 on success, or a PETSc error code on failure.

Tests the InterpolateFieldFromCornerToCenter function by reproducing the Cent vector.

Local to this translation unit.

Definition at line 137 of file interpolation.c.

138{
139 PetscErrorCode ierr;
140 Vec lCoords, TestCent;
141 Cmpnts ***coor_arr, ***test_cent_arr;
142 PetscReal diff_norm;
143
144 PetscFunctionBeginUser;
145
146 // 1. Create a temporary vector to hold the result of our interpolation.
147 // It must have the same layout and size as the ground-truth user->Cent vector.
148 ierr = VecDuplicate(user->Cent, &TestCent); CHKERRQ(ierr);
149
150 // 2. Get the input (corner coordinates) and output (our test vector) arrays.
151 ierr = DMGetCoordinatesLocal(user->da, &lCoords); CHKERRQ(ierr);
152 ierr = DMDAVecGetArrayRead(user->fda, lCoords, &coor_arr); CHKERRQ(ierr);
153 ierr = DMDAVecGetArray(user->fda, TestCent, &test_cent_arr); CHKERRQ(ierr);
154
155 // 3. Call the generic interpolation macro.
156 // The macro will see that `coor_arr` is of type `Cmpnts***` and correctly
157 // call the `InterpolateFieldFromCornerToCenter_Vector` function.
158 ierr = InterpolateFieldFromCornerToCenter(coor_arr, test_cent_arr, user); CHKERRQ(ierr);
159
160 // 4. Restore the arrays.
161 ierr = DMDAVecRestoreArrayRead(user->fda, lCoords, &coor_arr); CHKERRQ(ierr);
162 ierr = DMDAVecRestoreArray(user->fda, TestCent, &test_cent_arr); CHKERRQ(ierr);
163
164 // 5. IMPORTANT: Assemble the vector so its values are communicated across processors
165 // and it's ready for global operations like VecNorm.
166 ierr = VecAssemblyBegin(TestCent); CHKERRQ(ierr);
167 ierr = VecAssemblyEnd(TestCent); CHKERRQ(ierr);
168
169 // 6. Compare the result with the ground truth.
170 // We compute TestCent = -1.0 * user->Cent + 1.0 * TestCent.
171 // This calculates the difference vector: TestCent - user->Cent.
172 ierr = VecAXPY(TestCent, -1.0, user->Cent); CHKERRQ(ierr);
173
174 // Now, compute the L2 norm of the difference vector. If the functions are
175 // identical, the norm should be zero (or very close due to floating point).
176 ierr = VecNorm(TestCent, NORM_2, &diff_norm); CHKERRQ(ierr);
177
178 // 7. Report the result and clean up.
179 if (diff_norm < 1.0e-12) {
180 LOG_ALLOW(GLOBAL,LOG_DEBUG,"[SUCCESS] Test passed. Norm of difference is %g.\n", (double)diff_norm);
181 } else {
182 LOG_ALLOW(GLOBAL,LOG_DEBUG, "[FAILURE] Test failed. Norm of difference is %g.\n", (double)diff_norm);
183 }
184
185 ierr = VecDestroy(&TestCent); CHKERRQ(ierr);
186
187 PetscFunctionReturn(0);
188}
#define InterpolateFieldFromCornerToCenter(field, centfield, user)
Generic macro to call the appropriate interpolation function based on the field type.
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:46
Vec Cent
Definition variables.h:974

◆ InterpolateFieldFromCenterToCorner_Vector()

PetscErrorCode InterpolateFieldFromCenterToCorner_Vector ( Cmpnts ***  centfield_arr,
Cmpnts ***  corner_arr,
UserCtx user 
)

Interpolates a vector field from cell centers to corner nodes.

This version is adapted to write directly into a ghosted local array obtained from DMDAVecGetArray(), which allows using GLOBAL indices for writing to the OWNED portion of the array.

Parameters
[in]centfield_arrInput: 3D array (ghosted) of cell-centered data, accessed via GLOBAL indices.
[out]corner_arrOutput: 3D array (ghosted) where interpolated node values are stored, also accessed via GLOBAL indices for the owned part.
[in]userUser context containing DMDA information.
Returns
PetscErrorCode 0 on success.

Interpolates a vector field from cell centers to corner nodes.

Local to this translation unit.

Definition at line 196 of file interpolation.c.

200{
201 PetscErrorCode ierr;
202 DMDALocalInfo info;
203 PetscMPIInt rank;
205 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
206 ierr = DMDAGetLocalInfo(user->fda, &info); CHKERRQ(ierr);
207
208 // Node ownership range (GLOBAL indices)
209 PetscInt xs_node = info.xs, xm_node = info.xm, xe_node = xs_node + xm_node;
210 PetscInt ys_node = info.ys, ym_node = info.ym, ye_node = ys_node + ym_node;
211 PetscInt zs_node = info.zs, zm_node = info.zm, ze_node = zs_node + zm_node;
212
213 PetscInt nCellsX = info.mx - 2; // Number of cells in x-direction
214 PetscInt nCellsY = info.my - 2; // Number of cells in y-direction
215 PetscInt nCellsZ = info.mz - 2; // Number of cells in z-direction
216
217
218 // Global grid dimensions (used for valid cell check)
219 PetscInt IM = info.mx - 1; // Total nodes in i-direction
220 PetscInt JM = info.my - 1; // Total nodes in j-direction
221 PetscInt KM = info.mz - 1; // Total nodes in k-direction
222
224 "[Rank %d] Starting -- Node ownership k=%d..%d, j=%d..%d, i=%d..%d\n",
225 rank, zs_node, ze_node-1, ys_node, ye_node-1, xs_node, xe_node-1);
226
227 // Loop over the GLOBAL indices of the NODES owned by this processor
228 for (PetscInt k = zs_node; k < ze_node; k++) {
229 for (PetscInt j = ys_node; j < ye_node; j++) {
230 for (PetscInt i = xs_node; i < xe_node; i++) {
231 Cmpnts sum = {0.0, 0.0, 0.0};
232 PetscInt count = 0;
233
234 // DEBUG 1 TEST
235 /*
236 if(rank == 1 && i == 24 && j == 12 && k == 49){
237 PetscInt i_cell_A = i - 1;
238 PetscInt i_cell_B = i;
239
240 Cmpnts ucat_A = centfield_arr[k][j][i_cell_A]; // 23
241 Cmpnts ucat_B = centfield_arr[k][j][i_cell_B]; // 24 (out-of-bounds if IM=25)
242
243 PetscPrintf(PETSC_COMM_WORLD,"[Rank %d] DEBUG TEST at Node(k,j,i)=%d,%d,%d: Read { Valid Cell }Ucat[%d][%d][%d]=(%.2f,%.2f,%.2f) and {Out-of-Bounds Cell}Ucat[%d][%d][%d]=(%.2f,%.2f,%.2f)\n",
244 rank, k, j, i,
245 k, j, i_cell_A, ucat_A.x, ucat_A.y, ucat_A.z,
246 k, j, i_cell_B, ucat_B.x, ucat_B.y, ucat_B.z);
247
248 }
249 */
250
251 // Skip processing the unused last node in each dimension.
252 if(i >= IM || j >= JM || k >= KM){
253 continue;
254 }
255 // Loop over the 8 potential cells surrounding node N(k,j,i) and accumulate values.
256 // The index offsets correspond to the relative position of the indices(shifted) that represent cell-centered field values of cells that share the node N(k,j,i) as a corner
257 for (PetscInt dk_offset = -1; dk_offset <= 0; dk_offset++) {
258 for (PetscInt dj_offset = -1; dj_offset <= 0; dj_offset++) {
259 for (PetscInt di_offset = -1; di_offset <= 0; di_offset++) {
260
261 // These are still GLOBAL cell indices
262 PetscInt global_cell_k = k + dk_offset;
263 PetscInt global_cell_j = j + dj_offset;
264 PetscInt global_cell_i = i + di_offset;
265
266 // Check if this corresponds to a valid GLOBAL cell index
267 if (global_cell_i >= 0 && global_cell_i < nCellsX &&
268 global_cell_j >= 0 && global_cell_j < nCellsY &&
269 global_cell_k >= 0 && global_cell_k < nCellsZ)
270 {
271 Cmpnts cell_val = centfield_arr[global_cell_k + 1][global_cell_j + 1][global_cell_i + 1];
272
273 LOG_LOOP_ALLOW_EXACT(LOCAL, LOG_VERBOSE,k,49,"[Rank %d] successful read from [%d][%d][%d] -> (%.2f, %.2f, %.2f)\n",
274 rank,global_cell_k,global_cell_j,global_cell_i,cell_val.x, cell_val.y, cell_val.z);
275
276 sum.x += cell_val.x;
277 sum.y += cell_val.y;
278 sum.z += cell_val.z;
279 count++;
280 }
281 }
282 }
283 }
284
285 PetscInt i_global_write = i; // Global index in GLOBAL array.
286 PetscInt j_global_write = j;
287 PetscInt k_global_write = k;
288
289 // We write directly into the array using the global loop indices.
290 if (count > 0) {
291 corner_arr[k_global_write][j_global_write][i_global_write].x = sum.x / (PetscReal)count;
292 corner_arr[k_global_write][j_global_write][i_global_write].y = sum.y / (PetscReal)count;
293 corner_arr[k_global_write][j_global_write][i_global_write].z = sum.z / (PetscReal)count;
294 } else {
295 // This case should ideally not happen for a valid owned node, but as a failsafe:
296 corner_arr[k_global_write][j_global_write][i_global_write] = (Cmpnts){0.0, 0.0, 0.0};
297 }
298
299 // DEBUG 2
300 /*
301 if(rank == 1){
302 if(i == 11 && j == 11 && k == 49){
303 Cmpnts ucat_node = corner_arr[k][j][i];
304 PetscPrintf(PETSC_COMM_WORLD,"[Rank %d] DEBUG TEST at Node(k,j,i)=%d,%d,%d: Wrote CornerUcat[%d][%d][%d]=(%.2f,%.2f,%.2f)\n",
305 rank, k, j, i,
306 k, j, i, ucat_node.x, ucat_node.y, ucat_node.z);
307 }
308 }
309
310 if(rank == 0 && i == 24 && j == 12 && k == 0){
311 Cmpnts ucat_node = corner_arr[k][j][i];
312 PetscPrintf(PETSC_COMM_WORLD,"[Rank %d] DEBUG TEST at Node(k,j,i)=%d,%d,%d: Wrote CornerUcat[%d][%d][%d]=(%.2f,%.2f,%.2f)\n",
313 rank, k, j, i,
314 k, j, i, ucat_node.x, ucat_node.y, ucat_node.z);
315 }
316 */
317 // LOG_LOOP_ALLOW_EXACT(LOCAL, LOG_VERBOSE,k,48,"[Rank %d] Node(k,j,i)=%d,%d,%d finished loops and write.\n", rank, k, j, i);
318 }
319 }
320 }
322 return 0;
323}
#define LOG_ALLOW_SYNC(scope, level, fmt,...)
Synchronized logging macro that checks both the log level and whether the calling function is in the ...
Definition logging.h:253
#define LOG_LOOP_ALLOW_EXACT(scope, level, var, val, fmt,...)
Logs a custom message if a variable equals a specific value.
Definition logging.h:335

◆ InterpolateFieldFromCenterToCorner_Scalar()

PetscErrorCode InterpolateFieldFromCenterToCorner_Scalar ( PetscReal ***  centfield_arr,
PetscReal ***  corner_arr,
UserCtx user 
)

Interpolates a scalar field from cell centers to corner nodes.

This version is adapted to write directly into a ghosted local array obtained from DMDAVecGetArray(), which allows using GLOBAL indices for writing to the OWNED portion of the array.

Parameters
[in]centfield_arrInput: 3D array (ghosted) of scalar data at cell centers, accessed via GLOBAL indices.
[out]corner_arrOutput: 3D array (ghosted) where interpolated node values are stored, also accessed via GLOBAL indices for the owned part.
[in]userUser context containing DMDA information.
Returns
PetscErrorCode 0 on success.

Interpolates a scalar field from cell centers to corner nodes.

Local to this translation unit.

Definition at line 331 of file interpolation.c.

335{
336 PetscErrorCode ierr;
337 DMDALocalInfo info;
338 PetscMPIInt rank;
340 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
341 ierr = DMDAGetLocalInfo(user->fda, &info); CHKERRQ(ierr);
342
343 // Node ownership range (GLOBAL indices)
344 PetscInt xs_node = info.xs, xm_node = info.xm, xe_node = xs_node + xm_node;
345 PetscInt ys_node = info.ys, ym_node = info.ym, ye_node = ys_node + ym_node;
346 PetscInt zs_node = info.zs, zm_node = info.zm, ze_node = zs_node + zm_node;
347
348 PetscInt nCellsX = info.mx - 2; // Number of cells in x-direction
349 PetscInt nCellsY = info.my - 2; // Number of cells in y-direction
350 PetscInt nCellsZ = info.mz - 2; // Number of cells in z-direction
351
352
353 // Global grid dimensions (used for valid cell check)
354 PetscInt IM = info.mx - 1; // Total nodes in i-direction
355 PetscInt JM = info.my - 1; // Total nodes in j-direction
356 PetscInt KM = info.mz - 1; // Total nodes in k-direction
357
359 "[Rank %d] Starting -- Node ownership k=%d..%d, j=%d..%d, i=%d..%d\n",
360 rank, zs_node, ze_node-1, ys_node, ye_node-1, xs_node, xe_node-1);
361
362 // Loop over the GLOBAL indices of the NODES owned by this processor
363 for (PetscInt k = zs_node; k < ze_node; k++) {
364 for (PetscInt j = ys_node; j < ye_node; j++) {
365 for (PetscInt i = xs_node; i < xe_node; i++) {
366 PetscReal sum = 0.0;
367 PetscInt count = 0;
368
369 // DEBUG 1 TEST
370 /*
371 if(rank == 1 && i == 24 && j == 12 && k == 49){
372 PetscInt i_cell_A = i - 1;
373 PetscInt i_cell_B = i;
374
375 Cmpnts ucat_A = centfield_arr[k][j][i_cell_A]; // 23
376 Cmpnts ucat_B = centfield_arr[k][j][i_cell_B]; // 24 (out-of-bounds if IM=25)
377
378 PetscPrintf(PETSC_COMM_WORLD,"[Rank %d] DEBUG TEST at Node(k,j,i)=%d,%d,%d: Read { Valid Cell }Ucat[%d][%d][%d]=(%.2f,%.2f,%.2f) and {Out-of-Bounds Cell}Ucat[%d][%d][%d]=(%.2f,%.2f,%.2f)\n",
379 rank, k, j, i,
380 k, j, i_cell_A, ucat_A.x, ucat_A.y, ucat_A.z,
381 k, j, i_cell_B, ucat_B.x, ucat_B.y, ucat_B.z);
382
383 }
384 */
385
386 // Skip processing the unused last node in each dimension.
387 if(i >= IM || j >= JM || k >= KM){
388 continue;
389 }
390 // Loop over the 8 potential cells surrounding node N(k,j,i) and accumulate values.
391 // The index offsets correspond to the relative position of the indices(shifted) that represent cell-centered field values of cells that share the node N(k,j,i) as a corner
392 for (PetscInt dk_offset = -1; dk_offset <= 0; dk_offset++) {
393 for (PetscInt dj_offset = -1; dj_offset <= 0; dj_offset++) {
394 for (PetscInt di_offset = -1; di_offset <= 0; di_offset++) {
395
396 // These are still GLOBAL cell indices
397 PetscInt global_cell_k = k + dk_offset;
398 PetscInt global_cell_j = j + dj_offset;
399 PetscInt global_cell_i = i + di_offset;
400
401 // Check if this corresponds to a valid GLOBAL cell index
402 if (global_cell_i >= 0 && global_cell_i < nCellsX &&
403 global_cell_j >= 0 && global_cell_j < nCellsY &&
404 global_cell_k >= 0 && global_cell_k < nCellsZ)
405 {
406 PetscReal cell_val = centfield_arr[global_cell_k + 1][global_cell_j + 1][global_cell_i + 1];
407
408 LOG_LOOP_ALLOW_EXACT(LOCAL, LOG_VERBOSE,k,49,"[Rank %d] successful read from [%d][%d][%d] -> (%.2f)\n",
409 rank,global_cell_k,global_cell_j,global_cell_i,cell_val);
410
411 sum += cell_val;
412 count++;
413 }
414 }
415 }
416 }
417
418 PetscInt i_global_write = i; // Global index in GLOBAL array.
419 PetscInt j_global_write = j;
420 PetscInt k_global_write = k;
421
422 // We write directly into the array using the global loop indices.
423 if (count > 0) {
424 corner_arr[k_global_write][j_global_write][i_global_write] = sum / (PetscReal)count;
425 } else {
426 // This case should ideally not happen for a valid owned node, but as a failsafe:
427 corner_arr[k_global_write][j_global_write][i_global_write] = 0.0;
428 }
429
430 // DEBUG 2
431 /*
432 if(rank == 1){
433 if(i == 11 && j == 11 && k == 49){
434 Cmpnts ucat_node = corner_arr[k][j][i];
435 PetscPrintf(PETSC_COMM_WORLD,"[Rank %d] DEBUG TEST at Node(k,j,i)=%d,%d,%d: Wrote CornerUcat[%d][%d][%d]=(%.2f,%.2f,%.2f)\n",
436 rank, k, j, i,
437 k, j, i, ucat_node.x, ucat_node.y, ucat_node.z);
438 }
439 }
440
441 if(rank == 0 && i == 24 && j == 12 && k == 0){
442 Cmpnts ucat_node = corner_arr[k][j][i];
443 PetscPrintf(PETSC_COMM_WORLD,"[Rank %d] DEBUG TEST at Node(k,j,i)=%d,%d,%d: Wrote CornerUcat[%d][%d][%d]=(%.2f,%.2f,%.2f)\n",
444 rank, k, j, i,
445 k, j, i, ucat_node.x, ucat_node.y, ucat_node.z);
446 }
447 */
448 // LOG_LOOP_ALLOW_EXACT(LOCAL, LOG_VERBOSE,k,48,"[Rank %d] Node(k,j,i)=%d,%d,%d finished loops and write.\n", rank, k, j, i);
449 }
450 }
451 }
453 return 0;
454}

◆ InterpolateCornerToFaceCenter_Scalar()

PetscErrorCode InterpolateCornerToFaceCenter_Scalar ( PetscReal ***  corner_arr,
PetscReal ***  faceX_arr,
PetscReal ***  faceY_arr,
PetscReal ***  faceZ_arr,
UserCtx user 
)

Interpolates a scalar field from corner nodes to all face centers.

This routine computes the average of the four corner-node values defining each face of a hexahedral cell:

  • X-faces (perpendicular to X): face between (i-1,i) in X-dir
  • Y-faces (perpendicular to Y): face between (j-1,j) in Y-dir
  • Z-faces (perpendicular to Z): face between (k-1,k) in Z-dir
Parameters
[in]corner_arrGhosted node-centered array (global indexing) from user->fda.
[out]faceX_arrLocal array for X-faces sized [zm][ym][xm+1].
[out]faceY_arrLocal array for Y-faces sized [zm][ym+1][xm].
[out]faceZ_arrLocal array for Z-faces sized [zm+1][ym][xm].
[in]userUser context containing DMDA 'fda' and GetOwnedCellRange.
Returns
PetscErrorCode 0 on success, non-zero on failure.

Interpolates a scalar field from corner nodes to all face centers.

Local to this translation unit.

Definition at line 1953 of file interpolation.c.

1959{
1960 PetscErrorCode ierr;
1961 DMDALocalInfo info;
1962
1963 PetscFunctionBeginUser;
1964
1966
1967 ierr = DMDAGetLocalInfo(user->fda, &info); CHKERRQ(ierr);
1968
1969 // Determine owned-cell ranges based on corner-node ownership
1970 PetscInt xs, xm, ys, ym, zs, zm;
1971 ierr = GetOwnedCellRange(&info, 0, &xs, &xm); CHKERRQ(ierr);
1972 ierr = GetOwnedCellRange(&info, 1, &ys, &ym); CHKERRQ(ierr);
1973 ierr = GetOwnedCellRange(&info, 2, &zs, &zm); CHKERRQ(ierr);
1974
1975 // Global exclusive end indices for cells
1976 PetscInt xe = xs + xm;
1977 PetscInt ye = ys + ym;
1978 PetscInt ze = zs + zm;
1979
1980 // --- X‐faces: loops k=zs..ze-1, j=ys..ye-1, i=xs..xe (xm+1 faces per row) ---
1981 for (PetscInt k = zs; k < ze; ++k) {
1982 PetscInt k_loc = k - zs;
1983 for (PetscInt j = ys; j < ye; ++j) {
1984 PetscInt j_loc = j - ys;
1985 for (PetscInt i = xs; i <= xe; ++i) {
1986 PetscInt i_loc = i - xs; // 0..xm
1987 // Average the four corners of the Y-Z face at X = i
1988 PetscReal sum = corner_arr[k ][j ][i]
1989 + corner_arr[k+1][j ][i]
1990 + corner_arr[k ][j+1][i]
1991 + corner_arr[k+1][j+1][i];
1992 faceX_arr[k_loc][j_loc][i_loc] = sum * 0.25;
1993 }
1994 }
1995 }
1996
1997 // --- Y‐faces: loops k=zs..ze-1, j=ys..ye (ym+1 faces), i=xs..xe-1 ---
1998 for (PetscInt k = zs; k < ze; ++k) {
1999 PetscInt k_loc = k - zs;
2000 for (PetscInt j = ys; j <= ye; ++j) {
2001 PetscInt j_loc = j - ys; // 0..ym
2002 for (PetscInt i = xs; i < xe; ++i) {
2003 PetscInt i_loc = i - xs;
2004 // Average the four corners of the X-Z face at Y = j
2005 PetscReal sum = corner_arr[k ][j][i ]
2006 + corner_arr[k+1][j][i ]
2007 + corner_arr[k ][j][i+1]
2008 + corner_arr[k+1][j][i+1];
2009 faceY_arr[k_loc][j_loc][i_loc] = sum * 0.25;
2010 }
2011 }
2012 }
2013
2014 // --- Z‐faces: loops k=zs..ze (zm+1), j=ys..ye-1, i=xs..xe-1 ---
2015 for (PetscInt k = zs; k <= ze; ++k) {
2016 PetscInt k_loc = k - zs;
2017 for (PetscInt j = ys; j < ye; ++j) {
2018 PetscInt j_loc = j - ys;
2019 for (PetscInt i = xs; i < xe; ++i) {
2020 PetscInt i_loc = i - xs;
2021 // Average the four corners of the X-Y face at Z = k
2022 PetscReal sum = corner_arr[k][j ][i ]
2023 + corner_arr[k][j ][i+1]
2024 + corner_arr[k][j+1][i ]
2025 + corner_arr[k][j+1][i+1];
2026 faceZ_arr[k_loc][j_loc][i_loc] = sum * 0.25;
2027 }
2028 }
2029 }
2030
2032
2033 PetscFunctionReturn(0);
2034}
PetscErrorCode GetOwnedCellRange(const DMDALocalInfo *info_nodes, PetscInt dim, PetscInt *xs_cell_global_out, PetscInt *xm_cell_local_out)
Determines the global starting index and number of CELLS owned by the current processor in a specifie...
Definition setup.c:2285
Here is the call graph for this function:

◆ InterpolateCornerToFaceCenter_Vector()

PetscErrorCode InterpolateCornerToFaceCenter_Vector ( Cmpnts ***  corner_arr,
Cmpnts ***  faceX_arr,
Cmpnts ***  faceY_arr,
Cmpnts ***  faceZ_arr,
UserCtx user 
)

Interpolates a vector field from corner nodes to all face centers.

Identical to the scalar version, except it averages each component of the Cmpnts struct at the four corner-nodes per face.

Parameters
[in]corner_arrGhosted 3-component array (global node indices).
[out]faceX_arrLocal array of Cmpnts for X-faces sized [zm][ym][xm+1].
[out]faceY_arrLocal array of Cmpnts for Y-faces sized [zm][ym+1][xm].
[out]faceZ_arrLocal array of Cmpnts for Z-faces sized [zm+1][ym][xm].
[in]userUser context containing DMDA 'fda'.
Returns
PetscErrorCode 0 on success.

Interpolates a vector field from corner nodes to all face centers.

Local to this translation unit.

Definition at line 2043 of file interpolation.c.

2049{
2050 PetscErrorCode ierr;
2051 DMDALocalInfo info;
2052 PetscMPIInt rank;
2053
2054 PetscFunctionBeginUser;
2055
2057
2058 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2060 "Rank %d starting InterpolateFieldFromCornerToFaceCenter_Vector.\n", rank);
2061
2062 ierr = DMDAGetLocalInfo(user->fda, &info); CHKERRQ(ierr);
2063
2064 PetscInt xs, xm, ys, ym, zs, zm;
2065 ierr = GetOwnedCellRange(&info, 0, &xs, &xm); CHKERRQ(ierr);
2066 ierr = GetOwnedCellRange(&info, 1, &ys, &ym); CHKERRQ(ierr);
2067 ierr = GetOwnedCellRange(&info, 2, &zs, &zm); CHKERRQ(ierr);
2068
2069 PetscInt xe = xs + xm;
2070 PetscInt ye = ys + ym;
2071 PetscInt ze = zs + zm;
2072
2073 // X-faces
2074 for (PetscInt k = zs; k < ze; ++k) {
2075 PetscInt k_loc = k - zs;
2076 for (PetscInt j = ys; j < ye; ++j) {
2077 PetscInt j_loc = j - ys;
2078 for (PetscInt i = xs; i <= xe; ++i) {
2079 PetscInt i_loc = i - xs;
2080 Cmpnts sum = {0,0,0};
2081 sum.x = corner_arr[k ][j ][i].x + corner_arr[k+1][j ][i].x
2082 + corner_arr[k ][j+1][i].x + corner_arr[k+1][j+1][i].x;
2083 sum.y = corner_arr[k ][j ][i].y + corner_arr[k+1][j ][i].y
2084 + corner_arr[k ][j+1][i].y + corner_arr[k+1][j+1][i].y;
2085 sum.z = corner_arr[k ][j ][i].z + corner_arr[k+1][j ][i].z
2086 + corner_arr[k ][j+1][i].z + corner_arr[k+1][j+1][i].z;
2087 faceX_arr[k_loc][j_loc][i_loc].x = sum.x * 0.25;
2088 faceX_arr[k_loc][j_loc][i_loc].y = sum.y * 0.25;
2089 faceX_arr[k_loc][j_loc][i_loc].z = sum.z * 0.25;
2090 }
2091 }
2092 }
2093
2095 "Rank %d x-face Interpolation complete.\n", rank);
2096
2097 // Y-faces
2098 for (PetscInt k = zs; k < ze; ++k) {
2099 PetscInt k_loc = k - zs;
2100 for (PetscInt j = ys; j <= ye; ++j) {
2101 PetscInt j_loc = j - ys;
2102 for (PetscInt i = xs; i < xe; ++i) {
2103 PetscInt i_loc = i - xs;
2104 Cmpnts sum = {0,0,0};
2105 sum.x = corner_arr[k ][j][i ].x + corner_arr[k+1][j][i ].x
2106 + corner_arr[k ][j][i+1].x + corner_arr[k+1][j][i+1].x;
2107 sum.y = corner_arr[k ][j][i ].y + corner_arr[k+1][j][i ].y
2108 + corner_arr[k ][j][i+1].y + corner_arr[k+1][j][i+1].y;
2109 sum.z = corner_arr[k ][j][i ].z + corner_arr[k+1][j][i ].z
2110 + corner_arr[k ][j][i+1].z + corner_arr[k+1][j][i+1].z;
2111 faceY_arr[k_loc][j_loc][i_loc].x = sum.x * 0.25;
2112 faceY_arr[k_loc][j_loc][i_loc].y = sum.y * 0.25;
2113 faceY_arr[k_loc][j_loc][i_loc].z = sum.z * 0.25;
2114 }
2115 }
2116 }
2117
2119 "Rank %d y-face Interpolation complete.\n", rank);
2120
2121 // Z-faces
2122 for (PetscInt k = zs; k <= ze; ++k) {
2123 PetscInt k_loc = k - zs;
2124 for (PetscInt j = ys; j < ye; ++j) {
2125 PetscInt j_loc = j - ys;
2126 for (PetscInt i = xs; i < xe; ++i) {
2127 PetscInt i_loc = i - xs;
2128 Cmpnts sum = {0,0,0};
2129 sum.x = corner_arr[k][j ][i ].x + corner_arr[k][j ][i+1].x
2130 + corner_arr[k][j+1][i ].x + corner_arr[k][j+1][i+1].x;
2131 sum.y = corner_arr[k][j ][i ].y + corner_arr[k][j ][i+1].y
2132 + corner_arr[k][j+1][i ].y + corner_arr[k][j+1][i+1].y;
2133 sum.z = corner_arr[k][j ][i ].z + corner_arr[k][j ][i+1].z
2134 + corner_arr[k][j+1][i ].z + corner_arr[k][j+1][i+1].z;
2135 faceZ_arr[k_loc][j_loc][i_loc].x = sum.x * 0.25;
2136 faceZ_arr[k_loc][j_loc][i_loc].y = sum.y * 0.25;
2137 faceZ_arr[k_loc][j_loc][i_loc].z = sum.z * 0.25;
2138 }
2139 }
2140 }
2141
2143 "Rank %d z-face Interpolation complete.\n", rank);
2144
2146 PetscFunctionReturn(0);
2147}
@ LOG_TRACE
Very fine-grained tracing information for in-depth debugging.
Definition logging.h:33
Here is the call graph for this function: