15#ifndef ERROR_MSG_BUFFER_SIZE
16#define ERROR_MSG_BUFFER_SIZE 256
20#define __FUNCT__ "InterpolateFieldFromCornerToCenter_Vector"
33 PetscFunctionBeginUser;
35 ierr = DMDAGetLocalInfo(user->
fda, &info); CHKERRQ(ierr);
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;
45 PetscInt is = (xs == 0) ? 1 : xs;
46 PetscInt js = (ys == 0) ? 1 : ys;
47 PetscInt ks = (zs == 0) ? 1 : zs;
50 PetscInt ie = (xe == mx) ? xe - 1 : xe;
51 PetscInt je = (ye == my) ? ye - 1 : ye;
52 PetscInt ke = (ze == mz) ? ze - 1 : ze;
55 for (PetscInt k = ks; k < ke; k++) {
56 for (PetscInt j = js; j < je; j++) {
57 for (PetscInt i = is; i < ie; i++) {
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);
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);
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);
77 PetscFunctionReturn(0);
81#define __FUNCT__ "InterpolateFieldFromCornerToCenter_Scalar"
87 PetscReal ***field_arr,
88 PetscReal ***centfield_arr,
94 PetscFunctionBeginUser;
96 ierr = DMDAGetLocalInfo(user->
da, &info); CHKERRQ(ierr);
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;
106 PetscInt is = (xs == 0) ? 1 : xs;
107 PetscInt js = (ys == 0) ? 1 : ys;
108 PetscInt ks = (zs == 0) ? 1 : zs;
111 PetscInt ie = (xe == mx) ? xe - 1 : xe;
112 PetscInt je = (ye == my) ? ye - 1 : ye;
113 PetscInt ke = (ze == mz) ? ze - 1 : ze;
116 for (PetscInt k = ks; k < ke; k++) {
117 for (PetscInt j = js; j < je; j++) {
118 for (PetscInt i = is; i < ie; i++) {
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]);
128 PetscFunctionReturn(0);
132#define __FUNCT__ "TestCornerToCenterInterpolation"
140 Vec lCoords, TestCent;
141 Cmpnts ***coor_arr, ***test_cent_arr;
144 PetscFunctionBeginUser;
148 ierr = VecDuplicate(user->
Cent, &TestCent); CHKERRQ(ierr);
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);
161 ierr = DMDAVecRestoreArrayRead(user->
fda, lCoords, &coor_arr); CHKERRQ(ierr);
162 ierr = DMDAVecRestoreArray(user->
fda, TestCent, &test_cent_arr); CHKERRQ(ierr);
166 ierr = VecAssemblyBegin(TestCent); CHKERRQ(ierr);
167 ierr = VecAssemblyEnd(TestCent); CHKERRQ(ierr);
172 ierr = VecAXPY(TestCent, -1.0, user->
Cent); CHKERRQ(ierr);
176 ierr = VecNorm(TestCent, NORM_2, &diff_norm); CHKERRQ(ierr);
179 if (diff_norm < 1.0e-12) {
185 ierr = VecDestroy(&TestCent); CHKERRQ(ierr);
187 PetscFunctionReturn(0);
191#define __FUNCT__ "InterpolateFieldFromCenterToCorner_Vector"
205 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
206 ierr = DMDAGetLocalInfo(user->
fda, &info); CHKERRQ(ierr);
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;
213 PetscInt nCellsX = info.mx - 2;
214 PetscInt nCellsY = info.my - 2;
215 PetscInt nCellsZ = info.mz - 2;
219 PetscInt IM = info.mx - 1;
220 PetscInt JM = info.my - 1;
221 PetscInt KM = info.mz - 1;
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);
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};
252 if(i >= IM || j >= JM || k >= KM){
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++) {
262 PetscInt global_cell_k = k + dk_offset;
263 PetscInt global_cell_j = j + dj_offset;
264 PetscInt global_cell_i = i + di_offset;
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)
271 Cmpnts cell_val = centfield_arr[global_cell_k + 1][global_cell_j + 1][global_cell_i + 1];
274 rank,global_cell_k,global_cell_j,global_cell_i,cell_val.
x, cell_val.
y, cell_val.
z);
285 PetscInt i_global_write = i;
286 PetscInt j_global_write = j;
287 PetscInt k_global_write = k;
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;
296 corner_arr[k_global_write][j_global_write][i_global_write] = (
Cmpnts){0.0, 0.0, 0.0};
326#define __FUNCT__ "InterpolateFieldFromCenterToCorner_Scalar"
332 PetscReal ***centfield_arr,
333 PetscReal ***corner_arr,
340 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
341 ierr = DMDAGetLocalInfo(user->
fda, &info); CHKERRQ(ierr);
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;
348 PetscInt nCellsX = info.mx - 2;
349 PetscInt nCellsY = info.my - 2;
350 PetscInt nCellsZ = info.mz - 2;
354 PetscInt IM = info.mx - 1;
355 PetscInt JM = info.my - 1;
356 PetscInt KM = info.mz - 1;
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);
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++) {
387 if(i >= IM || j >= JM || k >= KM){
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++) {
397 PetscInt global_cell_k = k + dk_offset;
398 PetscInt global_cell_j = j + dj_offset;
399 PetscInt global_cell_i = i + di_offset;
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)
406 PetscReal cell_val = centfield_arr[global_cell_k + 1][global_cell_j + 1][global_cell_i + 1];
409 rank,global_cell_k,global_cell_j,global_cell_i,cell_val);
418 PetscInt i_global_write = i;
419 PetscInt j_global_write = j;
420 PetscInt k_global_write = k;
424 corner_arr[k_global_write][j_global_write][i_global_write] = sum / (PetscReal)count;
427 corner_arr[k_global_write][j_global_write][i_global_write] = 0.0;
457#define __FUNCT "PiecWiseLinearInterpolation_Scalar"
463 const char *fieldName,
464 PetscReal ***fieldScal,
471 *val = fieldScal[kCell][jCell][iCell];
475 "Field '%s' at (i=%d, j=%d, k=%d) => val=%.6f\n",
476 fieldName, iCell, jCell, kCell, *val);
478 PetscFunctionReturn(0);
482#define __FUNCT "PiecWiseLinearInterpolation_Vector"
488 const char *fieldName,
496 vec->
x = fieldVec[kCell][jCell][iCell].
x;
497 vec->
y = fieldVec[kCell][jCell][iCell].
y;
498 vec->
z = fieldVec[kCell][jCell][iCell].
z;
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);
505 PetscFunctionReturn(0);
510#define __FUNCT "ComputeTrilinearWeights"
519 a1 = PetscMax(0.0, PetscMin(1.0, a1));
520 a2 = PetscMax(0.0, PetscMin(1.0, a2));
521 a3 = PetscMax(0.0, PetscMin(1.0, a3));
523 const PetscReal oa1 = 1.0 - a1;
524 const PetscReal oa2 = 1.0 - a2;
525 const PetscReal oa3 = 1.0 - a3;
527 w[0] = oa1 * oa2 * oa3;
528 w[1] = a1 * oa2 * oa3;
529 w[2] = oa1 * a2 * oa3;
530 w[3] = a1 * a2 * oa3;
531 w[4] = oa1 * oa2 * a3;
532 w[5] = a1 * oa2 * a3;
533 w[6] = oa1 * a2 * a3;
538 "w0=%f, w1=%f, w2=%f, w3=%f, w4=%f, w5=%f, w6=%f, w7=%f. \n",
539 w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]);
551 const PetscReal oa1 = 1.0 - a1;
552 const PetscReal oa2 = 1.0 - a2;
553 const PetscReal oa3 = 1.0 - a3;
555 w[0] = oa1 * oa2 * oa3;
556 w[1] = a1 * oa2 * oa3;
557 w[2] = oa1 * a2 * oa3;
558 w[3] = a1 * a2 * oa3;
559 w[4] = oa1 * oa2 * a3;
560 w[5] = a1 * oa2 * a3;
561 w[6] = oa1 * a2 * a3;
565 "w0=%f, w1=%f, w2=%f, w3=%f, w4=%f, w5=%f, w6=%f, w7=%f.\n",
566 w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]);
570#define __FUNCT "TrilinearInterpolation_Scalar"
577 const char *fieldName,
578 PetscReal ***fieldScal,
590 PetscReal wcorner[8];
602 sum += wcorner[0] * fieldScal[k ][j ][i ];
604 sum += wcorner[1] * fieldScal[k ][j ][i1];
606 sum += wcorner[2] * fieldScal[k ][j1][i ];
608 sum += wcorner[3] * fieldScal[k ][j1][i1];
610 sum += wcorner[4] * fieldScal[k1][j ][i ];
612 sum += wcorner[5] * fieldScal[k1][j ][i1];
614 sum += wcorner[6] * fieldScal[k1][j1][i ];
616 sum += wcorner[7] * fieldScal[k1][j1][i1];
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);
630 PetscFunctionReturn(0);
635#define __FUNCT "TrilinearInterpolation_Vector"
641 const char *fieldName,
655 PetscReal wcorner[8];
658 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
667 PetscReal sumW = 0.0;
668 Cmpnts accum = {0.0, 0.0, 0.0};
673 const PetscInt cornerOffsets[8][3] = {
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;
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);
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;
716 if (sumW > 1.0e-14) {
717 vec->
x = accum.
x / sumW;
718 vec->
y = accum.
y / sumW;
719 vec->
z = accum.
z / sumW;
721 vec->
x = 0.0; vec->
y = 0.0; vec->
z = 0.0;
724 PetscFunctionReturn(0);
729#define __FUNCT "InterpolateEulerFieldToSwarmForParticle"
734 const char *fieldName,
744 PetscInt iCell = particle->
cell[0];
745 PetscInt jCell = particle->
cell[1];
746 PetscInt kCell = particle->
cell[2];
755 "field='%s', blockSize=%d, "
756 "cell IDs=(%d,%d,%d), weights=(%.4f,%.4f,%.4f)\n",
757 fieldName, blockSize, iCell, jCell, kCell, a1, a2, a3);
763 if (blockSize == 1) {
765 PetscReal ***fieldScal = (PetscReal ***) fieldPtr;
783 ((PetscReal*)swarmOut)[p] = val;
786 "field='%s', result=%.6f "
787 "stored at swarmOut index p=%d.\n", fieldName, val, (PetscInt)p);
789 else if (blockSize == 3) {
812 ((PetscReal*)swarmOut)[3*p + 0] = vec.
x;
813 ((PetscReal*)swarmOut)[3*p + 1] = vec.
y;
814 ((PetscReal*)swarmOut)[3*p + 2] = vec.
z;
817 "field='%s', result=(%.6f,%.6f,%.6f) "
818 "stored at swarmOut[3p..3p+2], p=%d.\n",
819 fieldName, vec.
x, vec.
y, vec.
z, (PetscInt)p);
829 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
830 "InterpolateEulerFieldToSwarmForParticle: only blockSize=1 or 3 supported, got %d.",
831 (PetscInt)blockSize);
835 PetscFunctionReturn(0);
839#define __FUNCT__ "InterpolateEulerFieldFromCenterToSwarm"
853 Vec fieldLocal_cellCentered,
854 const char *fieldName,
855 const char *swarmOutFieldName)
858 DM swarm = user->
swarm;
862 void *fieldPtr = NULL;
865 PetscInt *cellIDs = NULL;
866 PetscReal *weights = NULL;
867 PetscInt64 *pids = NULL;
868 void *swarmOut = NULL;
869 PetscReal *pos = NULL;
870 PetscInt *status = NULL;
875 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
876 ierr = DMDAGetLocalInfo(user->
fda, &info); CHKERRQ(ierr);
877 ierr = VecGetBlockSize(fieldLocal_cellCentered, &bs); CHKERRQ(ierr);
878 if (bs != 1 && bs != 3) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
"BlockSize must be 1 or 3.");
883 PetscInt nCellsX = info.mx - 2;
884 PetscInt nCellsY = info.my - 2;
885 PetscInt nCellsZ = info.mz - 2;
893 DM dm_field = (bs == 3) ? user->
fda : user->
da;
894 ierr = DMDAVecGetArrayRead(dm_field, fieldLocal_cellCentered, &fieldPtr); CHKERRQ(ierr);
895 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCent, (
void *)¢); CHKERRQ(ierr);
898 ierr = DMSwarmGetLocalSize(swarm, &nLocal); CHKERRQ(ierr);
904 ierr = DMSwarmGetField(swarm, swarmOutFieldName, NULL, NULL, &swarmOut); CHKERRQ(ierr);
907 for (PetscInt p = 0; p < nLocal; p++) {
910 ierr =
UnpackSwarmFields(p, pids, weights, pos, cellIDs, NULL, status, NULL, NULL, NULL, &particle); CHKERRQ(ierr);
913 PetscInt ci = particle.
cell[0];
914 PetscInt cj = particle.
cell[1];
915 PetscInt ck = particle.
cell[2];
921 PetscInt oi = (a1 < 0.5) ? -1 : 0;
922 PetscInt oj = (a2 < 0.5) ? -1 : 0;
923 PetscInt ok = (a3 < 0.5) ? -1 : 0;
924 PetscInt bi = ci + oi;
925 PetscInt bj = cj + oj;
926 PetscInt bk = ck + ok;
929 PetscBool needs_unclamped = PETSC_FALSE;
932 if (bi < 0) { bi = 0; needs_unclamped = PETSC_TRUE; }
933 if (bi + 1 >= nCellsX) { bi = nCellsX - 2; needs_unclamped = PETSC_TRUE; }
936 if (bj < 0) { bj = 0; needs_unclamped = PETSC_TRUE; }
937 if (bj + 1 >= nCellsY) { bj = nCellsY - 2; needs_unclamped = PETSC_TRUE; }
940 if (bk < 0) { bk = 0; needs_unclamped = PETSC_TRUE; }
941 if (bk + 1 >= nCellsZ) { bk = nCellsZ - 2; needs_unclamped = PETSC_TRUE; }
945 if (bi + 1 < info.gxs || bi + 1 >= info.gxs + info.gxm - 1 ||
946 bj + 1 < info.gys || bj + 1 >= info.gys + info.gym - 1 ||
947 bk + 1 < info.gzs || bk + 1 >= info.gzs + info.gzm - 1)
950 "[Rank %d] Particle PID %lld: dual cell (%d,%d,%d) out of ghosted region. Zeroing '%s'.\n",
951 rank, (
long long)particle.
PID, bi, bj, bk, fieldName);
953 ((PetscReal*)swarmOut)[3*p + 0] = 0.0;
954 ((PetscReal*)swarmOut)[3*p + 1] = 0.0;
955 ((PetscReal*)swarmOut)[3*p + 2] = 0.0;
957 ((PetscReal*)swarmOut)[p] = 0.0;
965 dual_cell.
vertices[0] = cent[bk + 1][bj + 1][bi + 1];
966 dual_cell.
vertices[1] = cent[bk + 1][bj + 1][bi + 2];
967 dual_cell.
vertices[2] = cent[bk + 1][bj + 2][bi + 2];
968 dual_cell.
vertices[3] = cent[bk + 1][bj + 2][bi + 1];
969 dual_cell.
vertices[4] = cent[bk + 2][bj + 2][bi + 1];
970 dual_cell.
vertices[5] = cent[bk + 2][bj + 2][bi + 2];
971 dual_cell.
vertices[6] = cent[bk + 2][bj + 1][bi + 2];
972 dual_cell.
vertices[7] = cent[bk + 2][bj + 1][bi + 1];
984 "[Rank %d] PID %lld: dual base=(%d,%d,%d), new weights=(%.4f,%.4f,%.4f), unclamped=%d\n",
985 rank, (
long long)particle.
PID, bi, bj, bk, a1_new, a2_new, a3_new, (
int)needs_unclamped);
991 PetscReal ***fieldScal = (PetscReal ***)fieldPtr;
993 if (needs_unclamped) {
996 val = w[0] * fieldScal[bk+1][bj+1][bi+1] + w[1] * fieldScal[bk+1][bj+1][bi+2]
997 + w[2] * fieldScal[bk+1][bj+2][bi+1] + w[3] * fieldScal[bk+1][bj+2][bi+2]
998 + w[4] * fieldScal[bk+2][bj+1][bi+1] + w[5] * fieldScal[bk+2][bj+1][bi+2]
999 + w[6] * fieldScal[bk+2][bj+2][bi+1] + w[7] * fieldScal[bk+2][bj+2][bi+2];
1002 bi + 1, bj + 1, bk + 1, a1_new, a2_new, a3_new, &val); CHKERRQ(ierr);
1004 ((PetscReal*)swarmOut)[p] = val;
1008 if (needs_unclamped) {
1011 vec.
x = w[0]*fieldVec[bk+1][bj+1][bi+1].
x + w[1]*fieldVec[bk+1][bj+1][bi+2].
x
1012 + w[2]*fieldVec[bk+1][bj+2][bi+1].
x + w[3]*fieldVec[bk+1][bj+2][bi+2].
x
1013 + w[4]*fieldVec[bk+2][bj+1][bi+1].
x + w[5]*fieldVec[bk+2][bj+1][bi+2].
x
1014 + w[6]*fieldVec[bk+2][bj+2][bi+1].
x + w[7]*fieldVec[bk+2][bj+2][bi+2].
x;
1015 vec.
y = w[0]*fieldVec[bk+1][bj+1][bi+1].
y + w[1]*fieldVec[bk+1][bj+1][bi+2].
y
1016 + w[2]*fieldVec[bk+1][bj+2][bi+1].
y + w[3]*fieldVec[bk+1][bj+2][bi+2].
y
1017 + w[4]*fieldVec[bk+2][bj+1][bi+1].
y + w[5]*fieldVec[bk+2][bj+1][bi+2].
y
1018 + w[6]*fieldVec[bk+2][bj+2][bi+1].
y + w[7]*fieldVec[bk+2][bj+2][bi+2].
y;
1019 vec.
z = w[0]*fieldVec[bk+1][bj+1][bi+1].
z + w[1]*fieldVec[bk+1][bj+1][bi+2].
z
1020 + w[2]*fieldVec[bk+1][bj+2][bi+1].
z + w[3]*fieldVec[bk+1][bj+2][bi+2].
z
1021 + w[4]*fieldVec[bk+2][bj+1][bi+1].
z + w[5]*fieldVec[bk+2][bj+1][bi+2].
z
1022 + w[6]*fieldVec[bk+2][bj+2][bi+1].
z + w[7]*fieldVec[bk+2][bj+2][bi+2].
z;
1025 bi + 1, bj + 1, bk + 1, a1_new, a2_new, a3_new, &vec); CHKERRQ(ierr);
1027 ((PetscReal*)swarmOut)[3*p + 0] = vec.
x;
1028 ((PetscReal*)swarmOut)[3*p + 1] = vec.
y;
1029 ((PetscReal*)swarmOut)[3*p + 2] = vec.
z;
1034 ierr = DMDAVecRestoreArrayRead(dm_field, fieldLocal_cellCentered, &fieldPtr); CHKERRQ(ierr);
1035 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCent, (
void *)¢); CHKERRQ(ierr);
1036 ierr = DMSwarmRestoreField(swarm, swarmOutFieldName, NULL, NULL, &swarmOut); CHKERRQ(ierr);
1045 PetscFunctionReturn(0);
1049#define __FUNCT__ "InterpolateEulerFieldFromCornerToSwarm"
1059 Vec fieldLocal_cellCentered,
1060 const char *fieldName,
1061 const char *swarmOutFieldName)
1063 PetscErrorCode ierr;
1065 DM swarm = user->
swarm;
1071 void *cellCenterPtr_read;
1072 void *cornerPtr_read_with_ghosts;
1075 PetscInt *cellIDs = NULL;
1076 PetscReal *weights = NULL;
1077 PetscInt64 *pids = NULL;
1078 void *swarmOut = NULL;
1079 PetscReal *pos = NULL;
1080 PetscInt *status = NULL;
1085 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1086 ierr = DMDAGetLocalInfo(fda, &info); CHKERRQ(ierr);
1087 ierr = VecGetBlockSize(fieldLocal_cellCentered, &bs); CHKERRQ(ierr);
1088 if (bs != 1 && bs != 3) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
"BlockSize must be 1 or 3.");
1092 DM dm_corner = (bs == 3) ? user->
fda : user->
da;
1102 ierr =
FieldGetView(user, corner_field_id, &corner_view); CHKERRQ(ierr);
1108 Vec cornerLocal = corner_view.
local_vec;
1109 ierr = VecSet(cornerGlobal, 0.0); CHKERRQ(ierr);
1110 ierr = VecSet(cornerLocal, 0.0); CHKERRQ(ierr);
1113 ierr = DMDAVecGetArrayRead(dm_corner, fieldLocal_cellCentered, &cellCenterPtr_read); CHKERRQ(ierr);
1116 ierr = VecGetSize(cornerGlobal, &size); CHKERRQ(ierr);
1117 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Corner global vector size for field '%s': %d.\n", rank, fieldName, (PetscInt)size);
1121 ierr = VecGetSize(cornerLocal, &size); CHKERRQ(ierr);
1122 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Corner local vector size for field '%s': %d.\n", rank, fieldName, (PetscInt)size);
1126 ierr = VecGetSize(fieldLocal_cellCentered, &size); CHKERRQ(ierr);
1127 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Cell-centered local vector size for field '%s': %d.\n", rank, fieldName, (PetscInt)size);
1129 PetscInt xs,ys,zs,gxs,gys,gzs;
1131 ierr = DMDAGetCorners(dm_corner,&xs,&ys,&zs,NULL,NULL,NULL); CHKERRQ(ierr);
1132 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] DMDAGetCorners for field '%s': xs=%d, ys=%d, zs=%d.\n", rank, fieldName, (PetscInt)xs, (PetscInt)ys, (PetscInt)zs);
1134 ierr = DMDAGetGhostCorners(dm_corner,&gxs,&gys,&gzs,NULL,NULL,NULL); CHKERRQ(ierr);
1135 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] DMDAGetGhostCorners for field '%s': gxs=%d, gys=%d, gzs=%d.\n", rank, fieldName, (PetscInt)gxs, (PetscInt)gys, (PetscInt)gzs);
1194 void *cornerPtr_write = NULL;
1195 ierr = DMDAVecGetArray(dm_corner, cornerGlobal, &cornerPtr_write); CHKERRQ(ierr);
1197 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Starting center-to-corner interpolation for '%s'.\n", rank, fieldName);
1202 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Finished center-to-corner interpolation for '%s'.\n", rank, fieldName);
1203 ierr = DMDAVecRestoreArray(dm_corner, cornerGlobal, &cornerPtr_write); CHKERRQ(ierr);
1205 ierr = DMDAVecRestoreArrayRead(dm_corner, fieldLocal_cellCentered, &cellCenterPtr_read); CHKERRQ(ierr);
1207 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRQ(ierr);
1277 ierr = DMDAVecGetArrayRead(dm_corner, cornerLocal, &cornerPtr_read_with_ghosts); CHKERRQ(ierr);
1280 ierr = DMSwarmGetLocalSize(swarm, &nLocal); CHKERRQ(ierr);
1286 ierr = DMSwarmGetField(swarm, swarmOutFieldName, NULL, NULL, &swarmOut); CHKERRQ(ierr);
1288 LOG_ALLOW(
LOCAL,
LOG_TRACE,
" Rank %d holds data upto & including %d,%d,%d.\n",rank,info.gxs + info.gxm,info.gys+info.gym,info.gzs+info.gzm);
1291 for (PetscInt p = 0; p < nLocal; p++) {
1295 ierr =
UnpackSwarmFields(p,pids,weights,pos,cellIDs,NULL,status,NULL,NULL,NULL,&particle); CHKERRQ(ierr);
1298 "[Rank %d] Particle PID %lld: global cell=(%d,%d,%d), weights=(%.4f,%.4f,%.4f)\n",
1299 rank, (
long long)particle.
PID, particle.
cell[0], particle.
cell[1], particle.
cell[2],
1304 if (particle.
cell[0] < info.gxs || particle.
cell[0] >= info.gxs + info.gxm - 1 ||
1305 particle.
cell[1] < info.gys || particle.
cell[1] >= info.gys + info.gym - 1 ||
1306 particle.
cell[2] < info.gzs || particle.
cell[2] >= info.gzs + info.gzm - 1)
1309 "[Rank %d] Particle PID %lld in global cell (%d,%d,%d) is in an un-interpolatable region (requires ghosts of ghosts or is out of bounds). Zeroing field '%s'.\n",
1310 rank, (
long long)particle.
PID, particle.
cell[0], particle.
cell[1], particle.
cell[2], fieldName);
1312 ((PetscReal*)swarmOut)[3*p + 0] = 0.0;
1313 ((PetscReal*)swarmOut)[3*p + 1] = 0.0;
1314 ((PetscReal*)swarmOut)[3*p + 2] = 0.0;
1316 ((PetscReal*)swarmOut)[p] = 0.0;
1323 cornerPtr_read_with_ghosts,
1330 ierr = DMDAVecRestoreArrayRead(dm_corner, cornerLocal, &cornerPtr_read_with_ghosts); CHKERRQ(ierr);
1333 ierr = DMSwarmRestoreField(swarm, swarmOutFieldName, NULL, NULL, &swarmOut); CHKERRQ(ierr);
1341 PetscFunctionReturn(0);
1345#define __FUNCT__ "InterpolateEulerFieldToSwarm"
1358 PetscErrorCode ierr;
1364 ierr =
FieldGetView(user, source_field_id, &source_view); CHKERRQ(ierr);
1367 PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
1368 "Eulerian-to-particle interpolation requires a cell-centered source; '%s' uses layout %s.",
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.",
1376 PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
1377 "Eulerian source '%s' has %d components but particle destination '%s' has %d.",
1391 PetscFunctionReturn(0);
1395#define __FUNCT__ "InterpolateAllFieldsToSwarm"
1402 PetscErrorCode ierr;
1408 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
1411 " Interpolation of ucat to velocity begins on rank %d.\n",rank);
1420 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRQ(ierr);
1422 "[rank %d]Completed Interpolateting all fields to the swarm.\n",rank);
1426 PetscFunctionReturn(0);
1472#define __FUNCT__ "AccumulateParticleField"
1479 DM gridSumDM, Vec localAccumulatorVec)
1481 PetscErrorCode ierr;
1484 const PetscReal *particle_arr = NULL;
1485 const PetscInt *cell_id_arr = NULL;
1488 PetscScalar ***arr_1d = NULL;
1489 PetscScalar ****arr_3d = NULL;
1492 PetscInt gxs, gys, gzs, gxm, gym, gzm;
1496 const char *particleFieldName = NULL;
1498 PetscFunctionBeginUser;
1501 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); 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.",
1510 if (!swarm || !gridSumDM || !localAccumulatorVec)
1511 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Null input in AccumulateParticleField.");
1514 ierr = DMDAGetInfo(gridSumDM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
1516 ierr = DMDAGetGhostCorners(gridSumDM, &gxs, &gys, &gzs, &gxm, &gym, &gzm); CHKERRQ(ierr);
1521 PetscInt expectedLocalSize = gxm * gym * gzm * dof;
1522 ierr = VecGetSize(localAccumulatorVec, &vecSize); CHKERRQ(ierr);
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);
1534 ierr = DMSwarmGetLocalSize(swarm, &nlocal); CHKERRQ(ierr);
1536 ierr = DMSwarmGetField(swarm, particleFieldName, NULL, NULL, (
void **)&particle_arr); CHKERRQ(ierr);
1542 ierr = DMDAVecGetArray(gridSumDM, localAccumulatorVec, &arr_1d); CHKERRQ(ierr);
1543 }
else if (dof == 3) {
1544 ierr = DMDAVecGetArrayDOF(gridSumDM, localAccumulatorVec, &arr_3d); CHKERRQ(ierr);
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);
1552 for (p = 0; p < nlocal; ++p) {
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];
1559 PetscInt i = i_geom + 1;
1560 PetscInt j = j_geom + 1;
1561 PetscInt k = k_geom + 1;
1565 if (i >= gxs && i < gxs + gxm &&
1566 j >= gys && j < gys + gym &&
1567 k >= gzs && k < gzs + gzm)
1570 arr_1d[k][j][i] += particle_arr[p];
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];
1584 ierr = DMDAVecRestoreArray(gridSumDM, localAccumulatorVec, &arr_1d); CHKERRQ(ierr);
1586 ierr = DMDAVecRestoreArrayDOF(gridSumDM, localAccumulatorVec, &arr_3d); CHKERRQ(ierr);
1589 ierr = DMSwarmRestoreField(swarm, particleFieldName, NULL, NULL, (
void **)&particle_arr); CHKERRQ(ierr);
1593 PetscFunctionReturn(0);
1597#define __FUNCT__ "NormalizeGridVectorByCount"
1601 DM dataDM, Vec sumVec, Vec avgVec)
1603 PetscErrorCode ierr;
1610 PetscScalar ***count_arr_3d = NULL;
1611 PetscScalar ***sum_arr_scalar = NULL;
1612 PetscScalar ***avg_arr_scalar = NULL;
1613 PetscScalar ****sum_arr_vector = NULL;
1614 PetscScalar ****avg_arr_vector = NULL;
1617 PetscFunctionBeginUser;
1621 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
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); }
1630 ierr = DMDAVecGetArrayRead(countDM, countVec, &count_arr_3d); CHKERRQ(ierr);
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);
1636 ierr = DMDAVecGetArrayDOFRead(dataDM, sumVec, &sum_arr_vector); CHKERRQ(ierr);
1637 ierr = DMDAVecGetArrayDOF(dataDM, avgVec, &avg_arr_vector); CHKERRQ(ierr);
1641 PetscInt xs, ys, zs, xm, ym, zm;
1642 ierr = DMDAGetCorners(countDM, &xs, &ys, &zs, &xm, &ym, &zm); CHKERRQ(ierr);
1646 rank, data_dof, xs, xs+xm, ys, ys+ym, zs, zs+zm);
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) {
1654 PetscScalar count = count_arr_3d[k][j][i];
1656 if (PetscRealPart(count) > 0.5) {
1657 if (data_dof == 1) {
1659 avg_arr_scalar[k][j][i] = sum_arr_scalar[k][j][i] / count;
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;
1668 if (data_dof == 1) {
1669 avg_arr_scalar[k][j][i] = 0.0;
1671 for (PetscInt c = 0; c < data_dof; ++c) {
1672 avg_arr_vector[k][j][i][c] = 0.0;
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);
1686 ierr = DMDAVecRestoreArrayDOFRead(dataDM, sumVec, &sum_arr_vector); CHKERRQ(ierr);
1687 ierr = DMDAVecRestoreArrayDOF(dataDM, avgVec, &avg_arr_vector); CHKERRQ(ierr);
1692 ierr = VecAssemblyBegin(avgVec); CHKERRQ(ierr);
1693 ierr = VecAssemblyEnd(avgVec); CHKERRQ(ierr);
1698 PetscFunctionReturn(0);
1711#define __FUNCT__ "ScatterParticleFieldToEulerField_Internal"
1718 PetscInt expected_dof,
1719 Vec eulerFieldAverageVec)
1721 PetscErrorCode ierr;
1722 PetscInt target_dof = 0;
1723 Vec globalsumVec = NULL;
1724 Vec localsumVec = NULL;
1728 PetscFunctionBeginUser;
1732 if (!user || !user->
swarm || !user->
ParticleCount || !targetDM || !eulerFieldAverageVec)
1733 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"NULL input provided to ScatterParticleFieldToEulerField_Internal.");
1735 ierr = DMDAGetInfo(targetDM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &target_dof, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
1736 if (target_dof != expected_dof) {
1737 PetscSNPrintf(msg,
sizeof(msg),
1738 "Field '%s' expects DOF %d but targetDM reports DOF %d.",
1739 particleFieldName, expected_dof, target_dof);
1740 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
"%s", msg);
1760 ierr = VecDuplicate(eulerFieldAverageVec, &globalsumVec); CHKERRQ(ierr);
1761 ierr = VecSet(globalsumVec, 0.0); CHKERRQ(ierr);
1762 ierr = PetscSNPrintf(msg,
sizeof(msg),
"TempSum_%s", particleFieldName); CHKERRQ(ierr);
1763 ierr = PetscObjectSetName((PetscObject)globalsumVec, msg); CHKERRQ(ierr);
1766 ierr = DMGetLocalVector(targetDM, &localsumVec); CHKERRQ(ierr);
1767 ierr = VecSet(localsumVec, 0.0); CHKERRQ(ierr);
1768 ierr = PetscSNPrintf(msg,
sizeof(msg),
"LocalTempSum_%s", particleFieldName); CHKERRQ(ierr);
1769 ierr = PetscObjectSetName((PetscObject)localsumVec, msg); CHKERRQ(ierr);
1779 ierr = DMLocalToGlobalBegin(targetDM, localsumVec, ADD_VALUES, globalsumVec); CHKERRQ(ierr);
1780 ierr = DMLocalToGlobalEnd(targetDM, localsumVec, ADD_VALUES, globalsumVec); CHKERRQ(ierr);
1782 ierr = DMRestoreLocalVector(targetDM, &localsumVec); CHKERRQ(ierr);
1790 ierr = VecDestroy(&globalsumVec); CHKERRQ(ierr);
1795 PetscFunctionReturn(0);
1799#define __FUNCT__ "ScatterParticleFieldToEulerField"
1804 Vec eulerFieldAverageVec)
1806 PetscErrorCode ierr;
1808 PetscInt expected_dof = 0;
1813 const char *particleFieldName = NULL;
1815 PetscFunctionBeginUser;
1820 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx pointer is NULL.");
1821 if (!user->
swarm) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx->swarm is NULL.");
1822 if (!user->
ParticleCount) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx->ParticleCount is NULL.");
1823 if (!eulerFieldAverageVec) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output eulerFieldAverageVec is NULL.");
1826 PETSC_COMM_SELF, PETSC_ERR_SUP,
1827 "Particle field '%s' has no registered Eulerian scatter target.",
1830 PETSC_COMM_SELF, PETSC_ERR_PLIB,
1831 "Particle field '%s' advertises scatter support without an Eulerian target.",
1834 expected_dof = particle_descriptor->
components;
1836 PetscCheck(eulerian_descriptor->
dof == expected_dof, PETSC_COMM_SELF, PETSC_ERR_PLIB,
1837 "Particle field '%s' has %d components but Eulerian target '%s' has %d.",
1838 particleFieldName, expected_dof, eulerian_descriptor->
canonical_name, eulerian_descriptor->
dof);
1840 targetDM = target_view.
dm;
1846 ierr = VecGetDM(eulerFieldAverageVec, &vec_dm); CHKERRQ(ierr);
1848 PetscSNPrintf(msg,
sizeof(msg),
"Provided eulerFieldAverageVec for field '%s' does not have an associated DM.", particleFieldName);
1849 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"%s", msg);
1852 ierr = VecGetBlockSize(eulerFieldAverageVec, &vec_dof); CHKERRQ(ierr);
1854 if (vec_dm != targetDM) {
1855 const char *target_dm_name =
"targetDM", *vec_dm_name =
"vec_dm";
1857 PetscObjectGetName((PetscObject)targetDM, &target_dm_name);
1858 PetscObjectGetName((PetscObject)vec_dm, &vec_dm_name);
1859 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);
1860 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
"%s", msg);
1863 if (vec_dof != expected_dof) {
1864 PetscSNPrintf(msg,
sizeof(msg),
"Field '%s' requires DOF %d, but provided eulerFieldAverageVec has DOF %d.", particleFieldName, expected_dof, vec_dof);
1865 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
"%s", msg);
1875 eulerFieldAverageVec);
1882 PetscFunctionReturn(0);
1886#define __FUNCT__ "ScatterAllParticleFieldsToEulerFields"
1890 PetscErrorCode ierr;
1891 PetscFunctionBeginUser;
1898 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"UserCtx->ParticleCount is NULL. Compute counts before calling ScatterAllParticleFieldsToEulerFields.");
1910 PetscReal Avg_Psi,Avg_swarm_Psi;
1912 ierr = VecMean(user->
Psi,&Avg_Psi);
1916 ierr = VecMean(swarm_Psi,&Avg_swarm_Psi);
1927 ierr = VecMean(user->
Psi,&Avg_Psi);
1940 PetscFunctionReturn(0);
1947#define __FUNCT__ "InterpolateCornerToFaceCenter_Scalar"
1954 PetscReal ***corner_arr,
1955 PetscReal ***faceX_arr,
1956 PetscReal ***faceY_arr,
1957 PetscReal ***faceZ_arr,
1960 PetscErrorCode ierr;
1963 PetscFunctionBeginUser;
1967 ierr = DMDAGetLocalInfo(user->
fda, &info); CHKERRQ(ierr);
1970 PetscInt xs, xm, ys, ym, zs, zm;
1976 PetscInt xe = xs + xm;
1977 PetscInt ye = ys + ym;
1978 PetscInt ze = zs + zm;
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;
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;
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;
2002 for (PetscInt i = xs; i < xe; ++i) {
2003 PetscInt i_loc = i - xs;
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;
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;
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;
2033 PetscFunctionReturn(0);
2037#define __FUNCT__ "InterpolateCornerToFaceCenter_Vector"
2050 PetscErrorCode ierr;
2054 PetscFunctionBeginUser;
2058 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2060 "Rank %d starting InterpolateFieldFromCornerToFaceCenter_Vector.\n", rank);
2062 ierr = DMDAGetLocalInfo(user->
fda, &info); CHKERRQ(ierr);
2064 PetscInt xs, xm, ys, ym, zs, zm;
2069 PetscInt xe = xs + xm;
2070 PetscInt ye = ys + ym;
2071 PetscInt ze = zs + zm;
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;
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;
2095 "Rank %d x-face Interpolation complete.\n", rank);
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;
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;
2119 "Rank %d y-face Interpolation complete.\n", rank);
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;
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;
2143 "Rank %d z-face Interpolation complete.\n", rank);
2146 PetscFunctionReturn(0);
PetscErrorCode CalculateParticleCountPerCell(UserCtx *user)
Counts particles in each cell of the DMDA 'da' and stores the result in user->ParticleCount.
PetscErrorCode UnpackSwarmFields(PetscInt i, const PetscInt64 *PIDs, const PetscReal *weights, const PetscReal *positions, const PetscInt *cellIndices, PetscReal *velocities, PetscInt *LocStatus, PetscReal *diffusivity, Cmpnts *diffusivitygradient, PetscReal *psi, Particle *particle)
Initializes a Particle struct with data from DMSwarm fields.
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.
PetscErrorCode FieldGetDescriptor(FieldId field_id, const FieldDescriptor **descriptor)
Return immutable metadata for a valid field identifier.
FieldId
Compile-time identity for a catalogued Eulerian field.
@ FIELD_ID_CELL_SCALAR_AT_CORNER
@ FIELD_ID_CELL_VECTOR_AT_CORNER
@ FIELD_ID_DIFFUSIVITY_GRADIENT
Immutable metadata for one field identity.
Non-owning runtime objects resolved for one field and UserCtx.
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.
static PetscErrorCode ScatterParticleFieldToEulerField_Internal(UserCtx *user, ParticleFieldId particle_field_id, DM targetDM, PetscInt expected_dof, Vec eulerFieldAverageVec)
Accumulate one particle field onto the Eulerian grid using the selected scatter stencil.
PetscErrorCode InterpolateFieldFromCornerToCenter_Vector(Cmpnts ***field_arr, Cmpnts ***centfield_arr, UserCtx *user)
Internal helper implementation: InterpolateFieldFromCornerToCenter_Vector().
PetscErrorCode InterpolateCornerToFaceCenter_Vector(Cmpnts ***corner_arr, Cmpnts ***faceX_arr, Cmpnts ***faceY_arr, Cmpnts ***faceZ_arr, UserCtx *user)
Internal helper implementation: InterpolateCornerToFaceCenter_Vector().
PetscErrorCode InterpolateFieldFromCornerToCenter_Scalar(PetscReal ***field_arr, PetscReal ***centfield_arr, UserCtx *user)
Internal helper implementation: InterpolateFieldFromCornerToCenter_Scalar().
PetscErrorCode InterpolateAllFieldsToSwarm(UserCtx *user)
Internal helper implementation: InterpolateAllFieldsToSwarm().
static PetscErrorCode InterpolateEulerFieldToSwarmForParticle(const char *fieldName, void *fieldPtr, Particle *particle, void *swarmOut, PetscInt p, PetscInt blockSize)
Interpolate one Eulerian field to a single located swarm particle.
PetscErrorCode TrilinearInterpolation_Vector(const char *fieldName, Cmpnts ***fieldVec, PetscInt i, PetscInt j, PetscInt k, PetscReal a1, PetscReal a2, PetscReal a3, Cmpnts *vec)
Internal helper implementation: TrilinearInterpolation_Vector().
PetscErrorCode TrilinearInterpolation_Scalar(const char *fieldName, PetscReal ***fieldScal, PetscInt i, PetscInt j, PetscInt k, PetscReal a1, PetscReal a2, PetscReal a3, PetscReal *val)
Internal helper implementation: TrilinearInterpolation_Scalar().
PetscErrorCode PieceWiseLinearInterpolation_Scalar(const char *fieldName, PetscReal ***fieldScal, PetscInt iCell, PetscInt jCell, PetscInt kCell, PetscReal *val)
Internal helper implementation: PieceWiseLinearInterpolation_Scalar().
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.
static void ComputeTrilinearWeightsUnclamped(PetscReal a1, PetscReal a2, PetscReal a3, PetscReal *w)
Unclamped trilinear weights for boundary extrapolation.
#define ERROR_MSG_BUFFER_SIZE
PetscErrorCode TestCornerToCenterInterpolation(UserCtx *user)
Internal helper implementation: TestCornerToCenterInterpolation().
static PetscErrorCode InterpolateEulerFieldFromCornerToSwarm(UserCtx *user, Vec fieldLocal_cellCentered, const char *fieldName, const char *swarmOutFieldName)
Corner-averaged interpolation path (legacy).
PetscErrorCode InterpolateFieldFromCenterToCorner_Vector(Cmpnts ***centfield_arr, Cmpnts ***corner_arr, UserCtx *user)
Internal helper implementation: InterpolateFieldFromCenterToCorner_Vector().
static void ComputeTrilinearWeights(PetscReal a1, PetscReal a2, PetscReal a3, PetscReal *w)
Compute the eight trilinear interpolation weights for a particle's local coordinates.
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 InterpolateCornerToFaceCenter_Scalar(PetscReal ***corner_arr, PetscReal ***faceX_arr, PetscReal ***faceY_arr, PetscReal ***faceZ_arr, UserCtx *user)
Internal helper implementation: InterpolateCornerToFaceCenter_Scalar().
PetscErrorCode PieceWiseLinearInterpolation_Vector(const char *fieldName, Cmpnts ***fieldVec, PetscInt iCell, PetscInt jCell, PetscInt kCell, Cmpnts *vec)
Internal helper implementation: PieceWiseLinearInterpolation_Vector().
PetscErrorCode InterpolateFieldFromCenterToCorner_Scalar(PetscReal ***centfield_arr, PetscReal ***corner_arr, UserCtx *user)
Internal helper implementation: InterpolateFieldFromCenterToCorner_Scalar().
#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 th...
#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 ...
#define InterpolateFieldFromCornerToCenter(field, centfield, user)
Generic macro to call the appropriate interpolation function based on the field type.
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
#define LOG_ALLOW_SYNC(scope, level, fmt,...)
Synchronized logging macro that checks both the log level and whether the calling function is in the ...
#define LOCAL
Logging scope definitions for controlling message output.
#define GLOBAL
Scope for global logging across all processes.
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
#define LOG_LOOP_ALLOW_EXACT(scope, level, var, val, fmt,...)
Logs a custom message if a variable equals a specific value.
PetscErrorCode LOG_CORNER_FIELD_ANATOMY(UserCtx *user, FieldId corner_field_id, const char *stage_name)
Logs the node-layout anatomy of the transient center-to-corner interpolation field.
@ LOG_TRACE
Very fine-grained tracing information for in-depth debugging.
@ LOG_INFO
Informational messages about program execution.
@ LOG_WARNING
Non-critical issues that warrant attention.
@ LOG_DEBUG
Detailed debugging information.
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
const char * ParticleFieldName(ParticleFieldId field_id)
Return the canonical PETSc DMSwarm name for an ID.
ParticleFieldId
Compile-time identity for a persistent solver-particle field.
@ PARTICLE_FIELD_ID_LOCATION_STATUS
@ PARTICLE_FIELD_ID_WEIGHT
@ PARTICLE_FIELD_ID_POSITION
@ PARTICLE_FIELD_ID_CELL_ID
@ PARTICLE_FIELD_ID_DIFFUSIVITY_GRADIENT
@ PARTICLE_FIELD_ID_DIFFUSIVITY
@ PARTICLE_FIELD_ID_VELOCITY
unsigned int capabilities
@ PARTICLE_FIELD_CAPABILITY_EULERIAN_SCATTER
PetscErrorCode ParticleFieldGetDescriptor(ParticleFieldId field_id, const ParticleFieldDescriptor **descriptor)
Return immutable metadata for a valid particle field ID.
const char * canonical_name
FieldId eulerian_scatter_target
Immutable metadata for one persistent particle field.
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...
PetscErrorCode UpdateLocalGhosts(UserCtx *user, FieldId field_id)
Updates the local vector (including ghost points) from its corresponding global vector.
BoundaryFaceConfig boundary_faces[6]
SimCtx * simCtx
Back-pointer to the master simulation context.
InterpolationMethod interpolationMethod
Cmpnts vertices[8]
Coordinates of the eight vertices of the cell.
Defines the vertices of a single hexahedral grid cell.
A 3D point or vector with PetscScalar components.
Defines a particle's core properties for Lagrangian tracking.
User-defined context containing data specific to a single computational grid level.
PetscErrorCode CalculateDistancesToCellFaces(const Cmpnts p, const Cell *cell, PetscReal *d, const PetscReal threshold)
Computes the signed distances from a point to each face of a cubic cell.