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"
520 a1 = PetscMax(0.0, PetscMin(1.0, a1));
521 a2 = PetscMax(0.0, PetscMin(1.0, a2));
522 a3 = PetscMax(0.0, PetscMin(1.0, a3));
524 const PetscReal oa1 = 1.0 - a1;
525 const PetscReal oa2 = 1.0 - a2;
526 const PetscReal oa3 = 1.0 - a3;
528 w[0] = oa1 * oa2 * oa3;
529 w[1] = a1 * oa2 * oa3;
530 w[2] = oa1 * a2 * oa3;
531 w[3] = a1 * a2 * oa3;
532 w[4] = oa1 * oa2 * a3;
533 w[5] = a1 * oa2 * a3;
534 w[6] = oa1 * a2 * a3;
539 "w0=%f, w1=%f, w2=%f, w3=%f, w4=%f, w5=%f, w6=%f, w7=%f. \n",
540 w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]);
552 const PetscReal oa1 = 1.0 - a1;
553 const PetscReal oa2 = 1.0 - a2;
554 const PetscReal oa3 = 1.0 - a3;
556 w[0] = oa1 * oa2 * oa3;
557 w[1] = a1 * oa2 * oa3;
558 w[2] = oa1 * a2 * oa3;
559 w[3] = a1 * a2 * oa3;
560 w[4] = oa1 * oa2 * a3;
561 w[5] = a1 * oa2 * a3;
562 w[6] = oa1 * a2 * a3;
566 "w0=%f, w1=%f, w2=%f, w3=%f, w4=%f, w5=%f, w6=%f, w7=%f.\n",
567 w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7]);
571#define __FUNCT "TrilinearInterpolation_Scalar"
578 const char *fieldName,
579 PetscReal ***fieldScal,
591 PetscReal wcorner[8];
603 sum += wcorner[0] * fieldScal[k ][j ][i ];
605 sum += wcorner[1] * fieldScal[k ][j ][i1];
607 sum += wcorner[2] * fieldScal[k ][j1][i ];
609 sum += wcorner[3] * fieldScal[k ][j1][i1];
611 sum += wcorner[4] * fieldScal[k1][j ][i ];
613 sum += wcorner[5] * fieldScal[k1][j ][i1];
615 sum += wcorner[6] * fieldScal[k1][j1][i ];
617 sum += wcorner[7] * fieldScal[k1][j1][i1];
623 "Field '%s' at (i=%d, j=%d, k=%d), "
624 "a1=%.6f, a2=%.6f, a3=%.6f -> val=%.6f.\n",
625 fieldName, i, j, k, a1, a2, a3, *val);
631 PetscFunctionReturn(0);
636#define __FUNCT "TrilinearInterpolation_Vector"
642 const char *fieldName,
656 PetscReal wcorner[8];
659 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr);
668 PetscReal sumW = 0.0;
669 Cmpnts accum = {0.0, 0.0, 0.0};
674 const PetscInt cornerOffsets[8][3] = {
686 for (PetscInt c = 0; c < 8; c++) {
687 const PetscInt di = cornerOffsets[c][0];
688 const PetscInt dj = cornerOffsets[c][1];
689 const PetscInt dk = cornerOffsets[c][2];
690 PetscInt iC = i + di;
691 PetscInt jC = j + dj;
692 PetscInt kC = k + dk;
707 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);
710 accum.
x += wcorner[c] * fieldVec[kC][jC][iC].
x;
711 accum.
y += wcorner[c] * fieldVec[kC][jC][iC].
y;
712 accum.
z += wcorner[c] * fieldVec[kC][jC][iC].
z;
717 if (sumW > 1.0e-14) {
718 vec->
x = accum.
x / sumW;
719 vec->
y = accum.
y / sumW;
720 vec->
z = accum.
z / sumW;
722 vec->
x = 0.0; vec->
y = 0.0; vec->
z = 0.0;
725 PetscFunctionReturn(0);
730#define __FUNCT "InterpolateEulerFieldToSwarmForParticle"
736 const char *fieldName,
746 PetscInt iCell = particle->
cell[0];
747 PetscInt jCell = particle->
cell[1];
748 PetscInt kCell = particle->
cell[2];
757 "field='%s', blockSize=%d, "
758 "cell IDs=(%d,%d,%d), weights=(%.4f,%.4f,%.4f)\n",
759 fieldName, blockSize, iCell, jCell, kCell, a1, a2, a3);
765 if (blockSize == 1) {
767 PetscReal ***fieldScal = (PetscReal ***) fieldPtr;
785 ((PetscReal*)swarmOut)[p] = val;
788 "field='%s', result=%.6f "
789 "stored at swarmOut index p=%d.\n", fieldName, val, (PetscInt)p);
791 else if (blockSize == 3) {
814 ((PetscReal*)swarmOut)[3*p + 0] = vec.
x;
815 ((PetscReal*)swarmOut)[3*p + 1] = vec.
y;
816 ((PetscReal*)swarmOut)[3*p + 2] = vec.
z;
819 "field='%s', result=(%.6f,%.6f,%.6f) "
820 "stored at swarmOut[3p..3p+2], p=%d.\n",
821 fieldName, vec.
x, vec.
y, vec.
z, (PetscInt)p);
831 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
832 "InterpolateEulerFieldToSwarmForParticle: only blockSize=1 or 3 supported, got %d.",
833 (PetscInt)blockSize);
837 PetscFunctionReturn(0);
841#define __FUNCT__ "InterpolateEulerFieldFromCenterToSwarm"
855 Vec fieldLocal_cellCentered,
856 const char *fieldName,
857 const char *swarmOutFieldName)
860 DM swarm = user->
swarm;
864 void *fieldPtr = NULL;
867 PetscInt *cellIDs = NULL;
868 PetscReal *weights = NULL;
869 PetscInt64 *pids = NULL;
870 void *swarmOut = NULL;
871 PetscReal *pos = NULL;
872 PetscInt *status = NULL;
877 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
878 ierr = DMDAGetLocalInfo(user->
fda, &info); CHKERRQ(ierr);
879 ierr = VecGetBlockSize(fieldLocal_cellCentered, &bs); CHKERRQ(ierr);
880 if (bs != 1 && bs != 3) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
"BlockSize must be 1 or 3.");
885 PetscInt nCellsX = info.mx - 2;
886 PetscInt nCellsY = info.my - 2;
887 PetscInt nCellsZ = info.mz - 2;
895 DM dm_field = (bs == 3) ? user->
fda : user->
da;
896 ierr = DMDAVecGetArrayRead(dm_field, fieldLocal_cellCentered, &fieldPtr); CHKERRQ(ierr);
897 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCent, (
void *)¢); CHKERRQ(ierr);
900 ierr = DMSwarmGetLocalSize(swarm, &nLocal); CHKERRQ(ierr);
901 ierr = DMSwarmGetField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cellIDs); CHKERRQ(ierr);
902 ierr = DMSwarmGetField(swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&pids); CHKERRQ(ierr);
903 ierr = DMSwarmGetField(swarm,
"weight", NULL, NULL, (
void**)&weights); CHKERRQ(ierr);
904 ierr = DMSwarmGetField(swarm,
"position", NULL, NULL, (
void**)&pos); CHKERRQ(ierr);
905 ierr = DMSwarmGetField(swarm,
"DMSwarm_location_status", NULL, NULL, (
void**)&status); CHKERRQ(ierr);
906 ierr = DMSwarmGetField(swarm, swarmOutFieldName, NULL, NULL, &swarmOut); CHKERRQ(ierr);
909 for (PetscInt p = 0; p < nLocal; p++) {
912 ierr =
UnpackSwarmFields(p, pids, weights, pos, cellIDs, NULL, status, NULL, NULL, NULL, &particle); CHKERRQ(ierr);
915 PetscInt ci = particle.
cell[0];
916 PetscInt cj = particle.
cell[1];
917 PetscInt ck = particle.
cell[2];
923 PetscInt oi = (a1 < 0.5) ? -1 : 0;
924 PetscInt oj = (a2 < 0.5) ? -1 : 0;
925 PetscInt ok = (a3 < 0.5) ? -1 : 0;
926 PetscInt bi = ci + oi;
927 PetscInt bj = cj + oj;
928 PetscInt bk = ck + ok;
931 PetscBool needs_unclamped = PETSC_FALSE;
934 if (bi < 0) { bi = 0; needs_unclamped = PETSC_TRUE; }
935 if (bi + 1 >= nCellsX) { bi = nCellsX - 2; needs_unclamped = PETSC_TRUE; }
938 if (bj < 0) { bj = 0; needs_unclamped = PETSC_TRUE; }
939 if (bj + 1 >= nCellsY) { bj = nCellsY - 2; needs_unclamped = PETSC_TRUE; }
942 if (bk < 0) { bk = 0; needs_unclamped = PETSC_TRUE; }
943 if (bk + 1 >= nCellsZ) { bk = nCellsZ - 2; needs_unclamped = PETSC_TRUE; }
947 if (bi + 1 < info.gxs || bi + 1 >= info.gxs + info.gxm - 1 ||
948 bj + 1 < info.gys || bj + 1 >= info.gys + info.gym - 1 ||
949 bk + 1 < info.gzs || bk + 1 >= info.gzs + info.gzm - 1)
952 "[Rank %d] Particle PID %lld: dual cell (%d,%d,%d) out of ghosted region. Zeroing '%s'.\n",
953 rank, (
long long)particle.
PID, bi, bj, bk, fieldName);
955 ((PetscReal*)swarmOut)[3*p + 0] = 0.0;
956 ((PetscReal*)swarmOut)[3*p + 1] = 0.0;
957 ((PetscReal*)swarmOut)[3*p + 2] = 0.0;
959 ((PetscReal*)swarmOut)[p] = 0.0;
967 dual_cell.
vertices[0] = cent[bk + 1][bj + 1][bi + 1];
968 dual_cell.
vertices[1] = cent[bk + 1][bj + 1][bi + 2];
969 dual_cell.
vertices[2] = cent[bk + 1][bj + 2][bi + 2];
970 dual_cell.
vertices[3] = cent[bk + 1][bj + 2][bi + 1];
971 dual_cell.
vertices[4] = cent[bk + 2][bj + 2][bi + 1];
972 dual_cell.
vertices[5] = cent[bk + 2][bj + 2][bi + 2];
973 dual_cell.
vertices[6] = cent[bk + 2][bj + 1][bi + 2];
974 dual_cell.
vertices[7] = cent[bk + 2][bj + 1][bi + 1];
986 "[Rank %d] PID %lld: dual base=(%d,%d,%d), new weights=(%.4f,%.4f,%.4f), unclamped=%d\n",
987 rank, (
long long)particle.
PID, bi, bj, bk, a1_new, a2_new, a3_new, (
int)needs_unclamped);
993 PetscReal ***fieldScal = (PetscReal ***)fieldPtr;
995 if (needs_unclamped) {
998 val = w[0] * fieldScal[bk+1][bj+1][bi+1] + w[1] * fieldScal[bk+1][bj+1][bi+2]
999 + w[2] * fieldScal[bk+1][bj+2][bi+1] + w[3] * fieldScal[bk+1][bj+2][bi+2]
1000 + w[4] * fieldScal[bk+2][bj+1][bi+1] + w[5] * fieldScal[bk+2][bj+1][bi+2]
1001 + w[6] * fieldScal[bk+2][bj+2][bi+1] + w[7] * fieldScal[bk+2][bj+2][bi+2];
1004 bi + 1, bj + 1, bk + 1, a1_new, a2_new, a3_new, &val); CHKERRQ(ierr);
1006 ((PetscReal*)swarmOut)[p] = val;
1010 if (needs_unclamped) {
1013 vec.
x = w[0]*fieldVec[bk+1][bj+1][bi+1].
x + w[1]*fieldVec[bk+1][bj+1][bi+2].
x
1014 + w[2]*fieldVec[bk+1][bj+2][bi+1].
x + w[3]*fieldVec[bk+1][bj+2][bi+2].
x
1015 + w[4]*fieldVec[bk+2][bj+1][bi+1].
x + w[5]*fieldVec[bk+2][bj+1][bi+2].
x
1016 + w[6]*fieldVec[bk+2][bj+2][bi+1].
x + w[7]*fieldVec[bk+2][bj+2][bi+2].
x;
1017 vec.
y = w[0]*fieldVec[bk+1][bj+1][bi+1].
y + w[1]*fieldVec[bk+1][bj+1][bi+2].
y
1018 + w[2]*fieldVec[bk+1][bj+2][bi+1].
y + w[3]*fieldVec[bk+1][bj+2][bi+2].
y
1019 + w[4]*fieldVec[bk+2][bj+1][bi+1].
y + w[5]*fieldVec[bk+2][bj+1][bi+2].
y
1020 + w[6]*fieldVec[bk+2][bj+2][bi+1].
y + w[7]*fieldVec[bk+2][bj+2][bi+2].
y;
1021 vec.
z = w[0]*fieldVec[bk+1][bj+1][bi+1].
z + w[1]*fieldVec[bk+1][bj+1][bi+2].
z
1022 + w[2]*fieldVec[bk+1][bj+2][bi+1].
z + w[3]*fieldVec[bk+1][bj+2][bi+2].
z
1023 + w[4]*fieldVec[bk+2][bj+1][bi+1].
z + w[5]*fieldVec[bk+2][bj+1][bi+2].
z
1024 + w[6]*fieldVec[bk+2][bj+2][bi+1].
z + w[7]*fieldVec[bk+2][bj+2][bi+2].
z;
1027 bi + 1, bj + 1, bk + 1, a1_new, a2_new, a3_new, &vec); CHKERRQ(ierr);
1029 ((PetscReal*)swarmOut)[3*p + 0] = vec.
x;
1030 ((PetscReal*)swarmOut)[3*p + 1] = vec.
y;
1031 ((PetscReal*)swarmOut)[3*p + 2] = vec.
z;
1036 ierr = DMDAVecRestoreArrayRead(dm_field, fieldLocal_cellCentered, &fieldPtr); CHKERRQ(ierr);
1037 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCent, (
void *)¢); CHKERRQ(ierr);
1038 ierr = DMSwarmRestoreField(swarm, swarmOutFieldName, NULL, NULL, &swarmOut); CHKERRQ(ierr);
1039 ierr = DMSwarmRestoreField(swarm,
"weight", NULL, NULL, (
void**)&weights); CHKERRQ(ierr);
1040 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&pids); CHKERRQ(ierr);
1041 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cellIDs); CHKERRQ(ierr);
1042 ierr = DMSwarmRestoreField(swarm,
"position", NULL, NULL, (
void**)&pos); CHKERRQ(ierr);
1043 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_location_status", NULL, NULL, (
void**)&status); CHKERRQ(ierr);
1047 PetscFunctionReturn(0);
1051#define __FUNCT__ "InterpolateEulerFieldFromCornerToSwarm"
1061 Vec fieldLocal_cellCentered,
1062 const char *fieldName,
1063 const char *swarmOutFieldName)
1065 PetscErrorCode ierr;
1067 DM swarm = user->
swarm;
1073 void *cellCenterPtr_read;
1074 void *cornerPtr_read_with_ghosts;
1077 PetscInt *cellIDs = NULL;
1078 PetscReal *weights = NULL;
1079 PetscInt64 *pids = NULL;
1080 void *swarmOut = NULL;
1081 PetscReal *pos = NULL;
1082 PetscInt *status = NULL;
1087 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1088 ierr = DMDAGetLocalInfo(fda, &info); CHKERRQ(ierr);
1089 ierr = VecGetBlockSize(fieldLocal_cellCentered, &bs); CHKERRQ(ierr);
1090 if (bs != 1 && bs != 3) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
"BlockSize must be 1 or 3.");
1094 DM dm_corner = (bs == 3) ? user->
fda : user->
da;
1102 if(cached_bs != bs){
1103 LOG_ALLOW(
LOCAL,
LOG_WARNING,
"[Rank %d] Block size mismatch for existing corner vector and current field %s(Cached: %d, New: %d). Replacing.\n", rank, fieldName, cached_bs, bs);
1112 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Creating new global corner vector for field '%s'.\n", rank, fieldName);
1113 ierr = DMCreateGlobalVector(dm_corner, &user->
CellFieldAtCorner); CHKERRQ(ierr);
1115 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Reusing existing global corner vector for field '%s'.\n", rank, fieldName);
1125 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Reusing existing local corner vector for field '%s'.\n", rank, fieldName);
1132 ierr = DMDAVecGetArrayRead(dm_corner, fieldLocal_cellCentered, &cellCenterPtr_read); CHKERRQ(ierr);
1135 ierr = VecGetSize(cornerGlobal, &size); CHKERRQ(ierr);
1136 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Corner global vector size for field '%s': %d.\n", rank, fieldName, (PetscInt)size);
1140 ierr = VecGetSize(cornerLocal, &size); CHKERRQ(ierr);
1141 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Corner local vector size for field '%s': %d.\n", rank, fieldName, (PetscInt)size);
1145 ierr = VecGetSize(fieldLocal_cellCentered, &size); CHKERRQ(ierr);
1146 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Cell-centered local vector size for field '%s': %d.\n", rank, fieldName, (PetscInt)size);
1148 PetscInt xs,ys,zs,gxs,gys,gzs;
1150 ierr = DMDAGetCorners(dm_corner,&xs,&ys,&zs,NULL,NULL,NULL); CHKERRQ(ierr);
1151 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);
1153 ierr = DMDAGetGhostCorners(dm_corner,&gxs,&gys,&gzs,NULL,NULL,NULL); CHKERRQ(ierr);
1154 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);
1213 void *cornerPtr_write = NULL;
1214 ierr = DMDAVecGetArray(dm_corner, cornerGlobal, &cornerPtr_write); CHKERRQ(ierr);
1216 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Starting center-to-corner interpolation for '%s'.\n", rank, fieldName);
1221 LOG_ALLOW(
LOCAL,
LOG_TRACE,
"[Rank %d] Finished center-to-corner interpolation for '%s'.\n", rank, fieldName);
1222 ierr = DMDAVecRestoreArray(dm_corner, cornerGlobal, &cornerPtr_write); CHKERRQ(ierr);
1224 ierr = DMDAVecRestoreArrayRead(dm_corner, fieldLocal_cellCentered, &cellCenterPtr_read); CHKERRQ(ierr);
1226 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRQ(ierr);
1249 ierr = DMGlobalToLocalBegin(dm_corner, cornerGlobal, INSERT_VALUES, cornerLocal); CHKERRQ(ierr);
1250 ierr = DMGlobalToLocalEnd(dm_corner, cornerGlobal, INSERT_VALUES, cornerLocal); CHKERRQ(ierr);
1258 ierr =
LOG_FIELD_ANATOMY(user,
"CornerField",
"After Corner Velocity Interpolated"); CHKERRQ(ierr);
1295 ierr = DMDAVecGetArrayRead(dm_corner, cornerLocal, &cornerPtr_read_with_ghosts); CHKERRQ(ierr);
1298 ierr = DMSwarmGetLocalSize(swarm, &nLocal); CHKERRQ(ierr);
1299 ierr = DMSwarmGetField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cellIDs); CHKERRQ(ierr);
1300 ierr = DMSwarmGetField(swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&pids); CHKERRQ(ierr);
1301 ierr = DMSwarmGetField(swarm,
"weight", NULL, NULL, (
void**)&weights); CHKERRQ(ierr);
1302 ierr = DMSwarmGetField(swarm,
"position", NULL, NULL, (
void**)&pos); CHKERRQ(ierr);
1303 ierr = DMSwarmGetField(swarm,
"DMSwarm_location_status", NULL, NULL, (
void**)&status); CHKERRQ(ierr);
1304 ierr = DMSwarmGetField(swarm, swarmOutFieldName, NULL, NULL, &swarmOut); CHKERRQ(ierr);
1306 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);
1309 for (PetscInt p = 0; p < nLocal; p++) {
1313 ierr =
UnpackSwarmFields(p,pids,weights,pos,cellIDs,NULL,status,NULL,NULL,NULL,&particle); CHKERRQ(ierr);
1316 "[Rank %d] Particle PID %lld: global cell=(%d,%d,%d), weights=(%.4f,%.4f,%.4f)\n",
1317 rank, (
long long)particle.
PID, particle.
cell[0], particle.
cell[1], particle.
cell[2],
1322 if (particle.
cell[0] < info.gxs || particle.
cell[0] >= info.gxs + info.gxm - 1 ||
1323 particle.
cell[1] < info.gys || particle.
cell[1] >= info.gys + info.gym - 1 ||
1324 particle.
cell[2] < info.gzs || particle.
cell[2] >= info.gzs + info.gzm - 1)
1327 "[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",
1328 rank, (
long long)particle.
PID, particle.
cell[0], particle.
cell[1], particle.
cell[2], fieldName);
1330 ((PetscReal*)swarmOut)[3*p + 0] = 0.0;
1331 ((PetscReal*)swarmOut)[3*p + 1] = 0.0;
1332 ((PetscReal*)swarmOut)[3*p + 2] = 0.0;
1334 ((PetscReal*)swarmOut)[p] = 0.0;
1341 cornerPtr_read_with_ghosts,
1348 ierr = DMDAVecRestoreArrayRead(dm_corner, cornerLocal, &cornerPtr_read_with_ghosts); CHKERRQ(ierr);
1351 ierr = DMSwarmRestoreField(swarm, swarmOutFieldName, NULL, NULL, &swarmOut); CHKERRQ(ierr);
1352 ierr = DMSwarmRestoreField(swarm,
"weight", NULL, NULL, (
void**)&weights); CHKERRQ(ierr);
1353 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_pid", NULL, NULL, (
void**)&pids); CHKERRQ(ierr);
1354 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void**)&cellIDs); CHKERRQ(ierr);
1355 ierr = DMSwarmRestoreField(swarm,
"position", NULL, NULL, (
void**)&pos); CHKERRQ(ierr);
1356 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_location_status", NULL, NULL, (
void**)&status); CHKERRQ(ierr);
1359 PetscFunctionReturn(0);
1363#define __FUNCT__ "InterpolateEulerFieldToSwarm"
1373 Vec fieldLocal_cellCentered,
1374 const char *fieldName,
1375 const char *swarmOutFieldName)
1377 PetscErrorCode ierr;
1382 fieldName, swarmOutFieldName); CHKERRQ(ierr);
1385 fieldName, swarmOutFieldName); CHKERRQ(ierr);
1388 PetscFunctionReturn(0);
1392#define __FUNCT__ "InterpolateAllFieldsToSwarm"
1399 PetscErrorCode ierr;
1405 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank); CHKERRQ(ierr);
1419 " Interpolation of ucat to velocity begins on rank %d.\n",rank);
1423 "velocity"); CHKERRQ(ierr);
1425 "Diffusivity",
"Diffusivity"); CHKERRQ(ierr);
1428 "DiffusivityGradient",
"DiffusivityGradient"); CHKERRQ(ierr);
1431 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRQ(ierr);
1433 "[rank %d]Completed Interpolateting all fields to the swarm.\n",rank);
1437 PetscFunctionReturn(0);
1484#define __FUNCT__ "GetScatterTargetInfo"
1487 DM *targetDM, PetscInt *expected_dof)
1490 PetscFunctionBeginUser;
1496 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx pointer is NULL.");
1497 if (!user->
da) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx->da is NULL.");
1498 if (!user->
fda) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx->fda is NULL.");
1499 if (!particleFieldName) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"particleFieldName is NULL.");
1500 if (!targetDM) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output targetDM pointer is NULL.");
1501 if (!expected_dof) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output expected_dof pointer is NULL.");
1505 if (strcmp(particleFieldName,
"Psi") == 0 || strcmp(particleFieldName,
"Nvert") == 0) {
1507 *targetDM = user->
da;
1511 else if (strcmp(particleFieldName,
"Ucat") == 0 || strcmp(particleFieldName,
"Ucont") == 0) {
1513 *targetDM = user->
fda;
1524 PetscSNPrintf(msg,
sizeof(msg),
"Field name '%s' is not recognized for automatic DM selection.", particleFieldName);
1526 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"%s", msg);
1531 PetscFunctionReturn(0);
1535#define __FUNCT__ "GetPersistentLocalVector"
1542 PetscFunctionBeginUser;
1544 if (!user || !fieldName || !localVec)
1545 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Null input in GetPersistentLocalVector");
1547 if (strcmp(fieldName,
"Psi") == 0) {
1548 if (!user->
lPsi) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"user->lPsi is not initialized");
1549 *localVec = user->
lPsi;
1551 else if (strcmp(fieldName,
"Ucat") == 0) {
1552 if (!user->
lUcat) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"user->lUcat is not initialized");
1553 *localVec = user->
lUcat;
1555 else if (strcmp(fieldName,
"Ucont") == 0) {
1556 if (!user->
lUcont) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"user->lUcont is not initialized");
1557 *localVec = user->
lUcont;
1559 else if (strcmp(fieldName,
"Nvert") == 0) {
1560 if (!user->
lNvert) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"user->lNvert is not initialized");
1561 *localVec = user->
lNvert;
1565 PetscSNPrintf(msg,
sizeof(msg),
"Field '%s' does not have a mapped persistent local vector.", fieldName);
1566 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"%s", msg);
1569 PetscFunctionReturn(0);
1573#define __FUNCT__ "AccumulateParticleField"
1580 DM gridSumDM, Vec localAccumulatorVec)
1582 PetscErrorCode ierr;
1585 const PetscReal *particle_arr = NULL;
1586 const PetscInt *cell_id_arr = NULL;
1589 PetscScalar ***arr_1d = NULL;
1590 PetscScalar ****arr_3d = NULL;
1593 PetscInt gxs, gys, gzs, gxm, gym, gzm;
1597 PetscFunctionBeginUser;
1600 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1603 if (!swarm || !gridSumDM || !localAccumulatorVec)
1604 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Null input in AccumulateParticleField.");
1607 ierr = DMDAGetInfo(gridSumDM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dof, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
1609 ierr = DMDAGetGhostCorners(gridSumDM, &gxs, &gys, &gzs, &gxm, &gym, &gzm); CHKERRQ(ierr);
1614 PetscInt expectedLocalSize = gxm * gym * gzm * dof;
1615 ierr = VecGetSize(localAccumulatorVec, &vecSize); CHKERRQ(ierr);
1617 if (vecSize != expectedLocalSize) {
1618 PetscSNPrintf(msg,
sizeof(msg),
1619 "Vector dimension mismatch! Expected Ghosted Local Vector size %d (gxm*gym*gzm*dof), got %d. "
1620 "Did you pass a Global Vector instead of a Local Vector?",
1621 expectedLocalSize, vecSize);
1622 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"%s", msg);
1627 ierr = DMSwarmGetLocalSize(swarm, &nlocal); CHKERRQ(ierr);
1629 ierr = DMSwarmGetField(swarm, particleFieldName, NULL, NULL, (
void **)&particle_arr); CHKERRQ(ierr);
1630 ierr = DMSwarmGetField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&cell_id_arr); CHKERRQ(ierr);
1635 ierr = DMDAVecGetArray(gridSumDM, localAccumulatorVec, &arr_1d); CHKERRQ(ierr);
1636 }
else if (dof == 3) {
1637 ierr = DMDAVecGetArrayDOF(gridSumDM, localAccumulatorVec, &arr_3d); CHKERRQ(ierr);
1639 PetscSNPrintf(msg,
sizeof(msg),
"Unsupported DOF=%d. AccumulateParticleField supports DOF 1 or 3.", dof);
1640 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,
"%s", msg);
1645 for (p = 0; p < nlocal; ++p) {
1647 PetscInt i_geom = cell_id_arr[p * 3 + 0];
1648 PetscInt j_geom = cell_id_arr[p * 3 + 1];
1649 PetscInt k_geom = cell_id_arr[p * 3 + 2];
1652 PetscInt i = i_geom + 1;
1653 PetscInt j = j_geom + 1;
1654 PetscInt k = k_geom + 1;
1658 if (i >= gxs && i < gxs + gxm &&
1659 j >= gys && j < gys + gym &&
1660 k >= gzs && k < gzs + gzm)
1663 arr_1d[k][j][i] += particle_arr[p];
1666 arr_3d[k][j][i][0] += particle_arr[p * 3 + 0];
1667 arr_3d[k][j][i][1] += particle_arr[p * 3 + 1];
1668 arr_3d[k][j][i][2] += particle_arr[p * 3 + 2];
1677 ierr = DMDAVecRestoreArray(gridSumDM, localAccumulatorVec, &arr_1d); CHKERRQ(ierr);
1679 ierr = DMDAVecRestoreArrayDOF(gridSumDM, localAccumulatorVec, &arr_3d); CHKERRQ(ierr);
1682 ierr = DMSwarmRestoreField(swarm, particleFieldName, NULL, NULL, (
void **)&particle_arr); CHKERRQ(ierr);
1683 ierr = DMSwarmRestoreField(swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&cell_id_arr); CHKERRQ(ierr);
1686 PetscFunctionReturn(0);
1690#define __FUNCT__ "NormalizeGridVectorByCount"
1694 DM dataDM, Vec sumVec, Vec avgVec)
1696 PetscErrorCode ierr;
1703 PetscScalar ***count_arr_3d = NULL;
1704 PetscScalar ***sum_arr_scalar = NULL;
1705 PetscScalar ***avg_arr_scalar = NULL;
1706 PetscScalar ****sum_arr_vector = NULL;
1707 PetscScalar ****avg_arr_vector = NULL;
1710 PetscFunctionBeginUser;
1714 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1717 ierr = DMDAGetInfo(countDM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &count_dof, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
1718 ierr = DMDAGetInfo(dataDM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &data_dof, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
1719 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); }
1720 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); }
1723 ierr = DMDAVecGetArrayRead(countDM, countVec, &count_arr_3d); CHKERRQ(ierr);
1725 if (data_dof == 1) {
1726 ierr = DMDAVecGetArrayRead(dataDM, sumVec, &sum_arr_scalar); CHKERRQ(ierr);
1727 ierr = DMDAVecGetArray(dataDM, avgVec, &avg_arr_scalar); CHKERRQ(ierr);
1729 ierr = DMDAVecGetArrayDOFRead(dataDM, sumVec, &sum_arr_vector); CHKERRQ(ierr);
1730 ierr = DMDAVecGetArrayDOF(dataDM, avgVec, &avg_arr_vector); CHKERRQ(ierr);
1734 PetscInt xs, ys, zs, xm, ym, zm;
1735 ierr = DMDAGetCorners(countDM, &xs, &ys, &zs, &xm, &ym, &zm); CHKERRQ(ierr);
1739 rank, data_dof, xs, xs+xm, ys, ys+ym, zs, zs+zm);
1742 for (PetscInt k = zs; k < zs + zm; ++k) {
1743 for (PetscInt j = ys; j < ys + ym; ++j) {
1744 for (PetscInt i = xs; i < xs + xm; ++i) {
1747 PetscScalar count = count_arr_3d[k][j][i];
1749 if (PetscRealPart(count) > 0.5) {
1750 if (data_dof == 1) {
1752 avg_arr_scalar[k][j][i] = sum_arr_scalar[k][j][i] / count;
1755 for (PetscInt c = 0; c < data_dof; ++c) {
1756 avg_arr_vector[k][j][i][c] = sum_arr_vector[k][j][i][c] / count;
1761 if (data_dof == 1) {
1762 avg_arr_scalar[k][j][i] = 0.0;
1764 for (PetscInt c = 0; c < data_dof; ++c) {
1765 avg_arr_vector[k][j][i][c] = 0.0;
1774 ierr = DMDAVecRestoreArrayRead(countDM, countVec, &count_arr_3d); CHKERRQ(ierr);
1775 if (data_dof == 1) {
1776 ierr = DMDAVecRestoreArrayRead(dataDM, sumVec, &sum_arr_scalar); CHKERRQ(ierr);
1777 ierr = DMDAVecRestoreArray(dataDM, avgVec, &avg_arr_scalar); CHKERRQ(ierr);
1779 ierr = DMDAVecRestoreArrayDOFRead(dataDM, sumVec, &sum_arr_vector); CHKERRQ(ierr);
1780 ierr = DMDAVecRestoreArrayDOF(dataDM, avgVec, &avg_arr_vector); CHKERRQ(ierr);
1785 ierr = VecAssemblyBegin(avgVec); CHKERRQ(ierr);
1786 ierr = VecAssemblyEnd(avgVec); CHKERRQ(ierr);
1791 PetscFunctionReturn(0);
1804#define __FUNCT__ "ScatterParticleFieldToEulerField_Internal"
1810 const char *particleFieldName,
1812 PetscInt expected_dof,
1813 Vec eulerFieldAverageVec)
1815 PetscErrorCode ierr;
1816 PetscInt target_dof = 0;
1817 Vec globalsumVec = NULL;
1818 Vec localsumVec = NULL;
1821 PetscFunctionBeginUser;
1825 if (!user || !user->
swarm || !user->
ParticleCount || !particleFieldName || !targetDM || !eulerFieldAverageVec)
1826 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"NULL input provided to ScatterParticleFieldToEulerField_Internal.");
1828 ierr = DMDAGetInfo(targetDM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &target_dof, NULL, NULL, NULL, NULL, NULL); CHKERRQ(ierr);
1829 if (target_dof != expected_dof) {
1830 PetscSNPrintf(msg,
sizeof(msg),
1831 "Field '%s' expects DOF %d but targetDM reports DOF %d.",
1832 particleFieldName, expected_dof, target_dof);
1833 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
"%s", msg);
1853 ierr = VecDuplicate(eulerFieldAverageVec, &globalsumVec); CHKERRQ(ierr);
1854 ierr = VecSet(globalsumVec, 0.0); CHKERRQ(ierr);
1855 ierr = PetscSNPrintf(msg,
sizeof(msg),
"TempSum_%s", particleFieldName); CHKERRQ(ierr);
1856 ierr = PetscObjectSetName((PetscObject)globalsumVec, msg); CHKERRQ(ierr);
1859 ierr = DMGetLocalVector(targetDM, &localsumVec); CHKERRQ(ierr);
1860 ierr = VecSet(localsumVec, 0.0); CHKERRQ(ierr);
1861 ierr = PetscSNPrintf(msg,
sizeof(msg),
"LocalTempSum_%s", particleFieldName); CHKERRQ(ierr);
1862 ierr = PetscObjectSetName((PetscObject)localsumVec, msg); CHKERRQ(ierr);
1872 ierr = DMLocalToGlobalBegin(targetDM, localsumVec, ADD_VALUES, globalsumVec); CHKERRQ(ierr);
1873 ierr = DMLocalToGlobalEnd(targetDM, localsumVec, ADD_VALUES, globalsumVec); CHKERRQ(ierr);
1875 ierr = DMRestoreLocalVector(targetDM, &localsumVec); CHKERRQ(ierr);
1883 ierr = VecDestroy(&globalsumVec); CHKERRQ(ierr);
1888 PetscFunctionReturn(0);
1892#define __FUNCT__ "ScatterParticleFieldToEulerField"
1896 const char *particleFieldName,
1897 Vec eulerFieldAverageVec)
1899 PetscErrorCode ierr;
1901 PetscInt expected_dof = 0;
1904 PetscFunctionBeginUser;
1909 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx pointer is NULL.");
1910 if (!user->
swarm) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx->swarm is NULL.");
1911 if (!user->
ParticleCount) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx->ParticleCount is NULL.");
1912 if (!eulerFieldAverageVec) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output eulerFieldAverageVec is NULL.");
1923 ierr = VecGetDM(eulerFieldAverageVec, &vec_dm); CHKERRQ(ierr);
1925 PetscSNPrintf(msg,
sizeof(msg),
"Provided eulerFieldAverageVec for field '%s' does not have an associated DM.", particleFieldName);
1926 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"%s", msg);
1929 ierr = VecGetBlockSize(eulerFieldAverageVec, &vec_dof); CHKERRQ(ierr);
1931 if (vec_dm != targetDM) {
1932 const char *target_dm_name =
"targetDM", *vec_dm_name =
"vec_dm";
1934 PetscObjectGetName((PetscObject)targetDM, &target_dm_name);
1935 PetscObjectGetName((PetscObject)vec_dm, &vec_dm_name);
1936 PetscSNPrintf(msg,
sizeof(msg),
"Provided eulerFieldAverageVec associated with DM '%s', but field '%s' requires scatter to DM '%s'.", vec_dm_name, particleFieldName, target_dm_name);
1937 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
"%s", msg);
1940 if (vec_dof != expected_dof) {
1941 PetscSNPrintf(msg,
sizeof(msg),
"Field '%s' requires DOF %d, but provided eulerFieldAverageVec has DOF %d.", particleFieldName, expected_dof, vec_dof);
1942 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
"%s", msg);
1952 eulerFieldAverageVec);
1959 PetscFunctionReturn(0);
1963#define __FUNCT__ "ScatterAllParticleFieldsToEulerFields"
1967 PetscErrorCode ierr;
1968 PetscFunctionBeginUser;
1975 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"UserCtx->ParticleCount is NULL. Compute counts before calling ScatterAllParticleFieldsToEulerFields.");
1987 PetscReal Avg_Psi,Avg_swarm_Psi;
1989 ierr = VecMean(user->
Psi,&Avg_Psi);
1992 ierr = DMSwarmCreateGlobalVectorFromField(user->
swarm,
"Psi",&swarm_Psi);
1993 ierr = VecMean(swarm_Psi,&Avg_swarm_Psi);
1997 ierr = DMSwarmDestroyGlobalVectorFromField(user->
swarm,
"Psi",&swarm_Psi);
2004 ierr = VecMean(user->
Psi,&Avg_Psi);
2056 PetscFunctionReturn(0);
2063#define __FUNCT__ "InterpolateCornerToFaceCenter_Scalar"
2070 PetscReal ***corner_arr,
2071 PetscReal ***faceX_arr,
2072 PetscReal ***faceY_arr,
2073 PetscReal ***faceZ_arr,
2076 PetscErrorCode ierr;
2079 PetscFunctionBeginUser;
2083 ierr = DMDAGetLocalInfo(user->
fda, &info); CHKERRQ(ierr);
2086 PetscInt xs, xm, ys, ym, zs, zm;
2092 PetscInt xe = xs + xm;
2093 PetscInt ye = ys + ym;
2094 PetscInt ze = zs + zm;
2097 for (PetscInt k = zs; k < ze; ++k) {
2098 PetscInt k_loc = k - zs;
2099 for (PetscInt j = ys; j < ye; ++j) {
2100 PetscInt j_loc = j - ys;
2101 for (PetscInt i = xs; i <= xe; ++i) {
2102 PetscInt i_loc = i - xs;
2104 PetscReal sum = corner_arr[k ][j ][i]
2105 + corner_arr[k+1][j ][i]
2106 + corner_arr[k ][j+1][i]
2107 + corner_arr[k+1][j+1][i];
2108 faceX_arr[k_loc][j_loc][i_loc] = sum * 0.25;
2114 for (PetscInt k = zs; k < ze; ++k) {
2115 PetscInt k_loc = k - zs;
2116 for (PetscInt j = ys; j <= ye; ++j) {
2117 PetscInt j_loc = j - ys;
2118 for (PetscInt i = xs; i < xe; ++i) {
2119 PetscInt i_loc = i - xs;
2121 PetscReal sum = corner_arr[k ][j][i ]
2122 + corner_arr[k+1][j][i ]
2123 + corner_arr[k ][j][i+1]
2124 + corner_arr[k+1][j][i+1];
2125 faceY_arr[k_loc][j_loc][i_loc] = sum * 0.25;
2131 for (PetscInt k = zs; k <= ze; ++k) {
2132 PetscInt k_loc = k - zs;
2133 for (PetscInt j = ys; j < ye; ++j) {
2134 PetscInt j_loc = j - ys;
2135 for (PetscInt i = xs; i < xe; ++i) {
2136 PetscInt i_loc = i - xs;
2138 PetscReal sum = corner_arr[k][j ][i ]
2139 + corner_arr[k][j ][i+1]
2140 + corner_arr[k][j+1][i ]
2141 + corner_arr[k][j+1][i+1];
2142 faceZ_arr[k_loc][j_loc][i_loc] = sum * 0.25;
2149 PetscFunctionReturn(0);
2153#define __FUNCT__ "InterpolateCornerToFaceCenter_Vector"
2166 PetscErrorCode ierr;
2170 PetscFunctionBeginUser;
2174 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2176 "Rank %d starting InterpolateFieldFromCornerToFaceCenter_Vector.\n", rank);
2178 ierr = DMDAGetLocalInfo(user->
fda, &info); CHKERRQ(ierr);
2180 PetscInt xs, xm, ys, ym, zs, zm;
2185 PetscInt xe = xs + xm;
2186 PetscInt ye = ys + ym;
2187 PetscInt ze = zs + zm;
2190 for (PetscInt k = zs; k < ze; ++k) {
2191 PetscInt k_loc = k - zs;
2192 for (PetscInt j = ys; j < ye; ++j) {
2193 PetscInt j_loc = j - ys;
2194 for (PetscInt i = xs; i <= xe; ++i) {
2195 PetscInt i_loc = i - xs;
2197 sum.
x = corner_arr[k ][j ][i].
x + corner_arr[k+1][j ][i].
x
2198 + corner_arr[k ][j+1][i].
x + corner_arr[k+1][j+1][i].
x;
2199 sum.
y = corner_arr[k ][j ][i].
y + corner_arr[k+1][j ][i].
y
2200 + corner_arr[k ][j+1][i].
y + corner_arr[k+1][j+1][i].
y;
2201 sum.
z = corner_arr[k ][j ][i].
z + corner_arr[k+1][j ][i].
z
2202 + corner_arr[k ][j+1][i].
z + corner_arr[k+1][j+1][i].
z;
2203 faceX_arr[k_loc][j_loc][i_loc].
x = sum.
x * 0.25;
2204 faceX_arr[k_loc][j_loc][i_loc].
y = sum.
y * 0.25;
2205 faceX_arr[k_loc][j_loc][i_loc].
z = sum.
z * 0.25;
2211 "Rank %d x-face Interpolation complete.\n", rank);
2214 for (PetscInt k = zs; k < ze; ++k) {
2215 PetscInt k_loc = k - zs;
2216 for (PetscInt j = ys; j <= ye; ++j) {
2217 PetscInt j_loc = j - ys;
2218 for (PetscInt i = xs; i < xe; ++i) {
2219 PetscInt i_loc = i - xs;
2221 sum.
x = corner_arr[k ][j][i ].
x + corner_arr[k+1][j][i ].
x
2222 + corner_arr[k ][j][i+1].
x + corner_arr[k+1][j][i+1].
x;
2223 sum.
y = corner_arr[k ][j][i ].
y + corner_arr[k+1][j][i ].
y
2224 + corner_arr[k ][j][i+1].
y + corner_arr[k+1][j][i+1].
y;
2225 sum.
z = corner_arr[k ][j][i ].
z + corner_arr[k+1][j][i ].
z
2226 + corner_arr[k ][j][i+1].
z + corner_arr[k+1][j][i+1].
z;
2227 faceY_arr[k_loc][j_loc][i_loc].
x = sum.
x * 0.25;
2228 faceY_arr[k_loc][j_loc][i_loc].
y = sum.
y * 0.25;
2229 faceY_arr[k_loc][j_loc][i_loc].
z = sum.
z * 0.25;
2235 "Rank %d y-face Interpolation complete.\n", rank);
2238 for (PetscInt k = zs; k <= ze; ++k) {
2239 PetscInt k_loc = k - zs;
2240 for (PetscInt j = ys; j < ye; ++j) {
2241 PetscInt j_loc = j - ys;
2242 for (PetscInt i = xs; i < xe; ++i) {
2243 PetscInt i_loc = i - xs;
2245 sum.
x = corner_arr[k][j ][i ].
x + corner_arr[k][j ][i+1].
x
2246 + corner_arr[k][j+1][i ].
x + corner_arr[k][j+1][i+1].
x;
2247 sum.
y = corner_arr[k][j ][i ].
y + corner_arr[k][j ][i+1].
y
2248 + corner_arr[k][j+1][i ].
y + corner_arr[k][j+1][i+1].
y;
2249 sum.
z = corner_arr[k][j ][i ].
z + corner_arr[k][j ][i+1].
z
2250 + corner_arr[k][j+1][i ].
z + corner_arr[k][j+1][i+1].
z;
2251 faceZ_arr[k_loc][j_loc][i_loc].
x = sum.
x * 0.25;
2252 faceZ_arr[k_loc][j_loc][i_loc].
y = sum.
y * 0.25;
2253 faceZ_arr[k_loc][j_loc][i_loc].
z = sum.
z * 0.25;
2259 "Rank %d z-face Interpolation complete.\n", rank);
2262 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.
PetscErrorCode GetScatterTargetInfo(UserCtx *user, const char *particleFieldName, DM *targetDM, PetscInt *expected_dof)
Determines the target Eulerian DM and expected DOF for scattering a given particle field.
PetscErrorCode 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 GetPersistentLocalVector(UserCtx *user, const char *fieldName, Vec *localVec)
Internal helper implementation: GetPersistentLocalVector().
PetscErrorCode AccumulateParticleField(DM swarm, const char *particleFieldName, DM gridSumDM, Vec gridSumVec)
Accumulates a particle field (scalar or vector) into a target grid sum vector.
PetscErrorCode ScatterAllParticleFieldsToEulerFields(UserCtx *user)
Scatters a predefined set of particle fields to their corresponding Eulerian fields.
PetscErrorCode ScatterParticleFieldToEulerField(UserCtx *user, const char *particleFieldName, Vec eulerFieldAverageVec)
Scatters a particle field (scalar or vector) to the corresponding Eulerian field average.
static PetscErrorCode ScatterParticleFieldToEulerField_Internal(UserCtx *user, const char *particleFieldName, DM targetDM, PetscInt expected_dof, Vec eulerFieldAverageVec)
Internal helper implementation: ScatterParticleFieldToEulerField_Internal().
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)
Internal helper implementation: InterpolateEulerFieldToSwarmForParticle().
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().
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)
Internal helper implementation: ComputeTrilinearWeights().
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 InterpolateEulerFieldToSwarm(UserCtx *user, Vec fieldLocal_cellCentered, const char *fieldName, const char *swarmOutFieldName)
Dispatches grid-to-particle interpolation to the method selected in the control file.
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.
PetscErrorCode LOG_FIELD_ANATOMY(UserCtx *user, const char *field_name, const char *stage_name)
Logs the anatomy of a specified field at key boundary locations, respecting the solver's specific gri...
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.
@ 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).
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...
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.