92 PetscInt block_index = user->
_this;
94 PetscFunctionBeginUser;
98 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
99 "SetAnalyticalGridInfo called for analytical type '%s' that does not require custom geometry.",
102 if (user->
IM <= 0 || user->
JM <= 0 || user->
KM <= 0) {
103 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
104 "Analytical grid resolution is not initialized. Ensure IM/JM/KM are preloaded before SetAnalyticalGridInfo.");
112 if (block_index == 0) {
115 user->
Min_X = 0.0; user->
Max_X = 2.0 * PETSC_PI;
116 user->
Min_Y = 0.0; user->
Max_Y = 2.0 * PETSC_PI;
117 user->
Min_Z = 0.0; user->
Max_Z = 0.2 * PETSC_PI;
120 PetscReal s = sqrt((PetscReal)nblk);
123 if (fabs(s - floor(s)) > 1e-9) {
124 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
125 "\n\n*** CONFIGURATION ERROR FOR TGV3D ***\n"
126 "For multi-block TGV3D cases, the number of blocks must be a perfect square (e.g., 4, 9, 16).\n"
127 "You have specified %d blocks. Please adjust `-block_number`.\n", nblk);
129 PetscInt blocks_per_dim = (PetscInt)s;
131 if (block_index == 0) {
132 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"%d blocks detected. Decomposing domain into a %d x %d grid in the X-Y plane.\n", nblk, blocks_per_dim, blocks_per_dim);
136 PetscInt row = block_index / blocks_per_dim;
137 PetscInt col = block_index % blocks_per_dim;
140 PetscReal block_width = (2.0 * PETSC_PI) / (PetscReal)blocks_per_dim;
141 PetscReal block_height = (2.0 * PETSC_PI) / (PetscReal)blocks_per_dim;
144 user->
Min_X = col * block_width;
145 user->
Max_X = (col + 1) * block_width;
146 user->
Min_Y = row * block_height;
147 user->
Max_Y = (row + 1) * block_height;
149 user->
Max_Z = 2.0 * PETSC_PI;
161 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_UNKNOWN_TYPE,
162 "Analytical type '%s' has no custom geometry implementation.",
168 user->
rx = 1.0; user->
ry = 1.0; user->
rz = 1.0;
171 simCtx->
rank, block_index, user->
IM, user->
JM, user->
KM);
172 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Rank %d: Block %d final bounds: X=[%.4f, %.4f], Y=[%.4f, %.4f], Z=[%.4f, %.4f]\n",
176 PetscFunctionReturn(0);
252 const PetscReal V0 = 1.0;
253 const PetscReal rho = 1.0;
254 const PetscReal p0 = 0.0;
257 const PetscReal nu = (simCtx->
ren > 0) ? (1.0 / simCtx->
ren) : 0.0;
259 const PetscReal k = 1.0;
260 const PetscReal t = simCtx->
ti;
262 LOG_ALLOW(
GLOBAL,
LOG_TRACE,
"TGV Setup: t = %.4f, V0* = %.4f, rho* = %.4f, k = %.4f, p0* = %4.f, nu = %.6f.\n",simCtx->
ti,V0,rho,k,p0,nu);
264 const PetscReal vel_decay = exp(-2.0 * nu * k * k * t);
265 const PetscReal prs_decay = exp(-4.0 * nu * k * k * t);
267 PetscFunctionBeginUser;
269 for (PetscInt bi = 0; bi < simCtx->
block_number; bi++) {
270 UserCtx* user = &user_finest[bi];
271 DMDALocalInfo info = user->
info;
272 PetscInt xs = info.xs, xe = info.xs + info.xm;
273 PetscInt ys = info.ys, ye = info.ys + info.ym;
274 PetscInt zs = info.zs, ze = info.zs + info.zm;
275 PetscInt mx = info.mx, my = info.my, mz = info.mz;
278 const Cmpnts ***cent, ***cent_x, ***cent_y, ***cent_z;
282 PetscInt lxs = (xs == 0) ? xs + 1 : xs, lxe = (xe == mx) ? xe - 1 : xe;
283 PetscInt lys = (ys == 0) ? ys + 1 : ys, lye = (ye == my) ? ye - 1 : ye;
284 PetscInt lzs = (zs == 0) ? zs + 1 : zs, lze = (ze == mz) ? ze - 1 : ze;
287 ierr = DMDAVecGetArray(user->
fda, user->
Ucat, &ucat); CHKERRQ(ierr);
288 ierr = DMDAVecGetArray(user->
da, user->
P, &p); CHKERRQ(ierr);
289 ierr = DMDAVecGetArray(user->
fda, user->
Bcs.
Ubcs, &ubcs); CHKERRQ(ierr);
290 ierr = DMDAVecGetArrayRead(user->
fda, user->
Cent, ¢); CHKERRQ(ierr);
291 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCentx, ¢_x); CHKERRQ(ierr);
292 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCenty, ¢_y); CHKERRQ(ierr);
293 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCentz, ¢_z); CHKERRQ(ierr);
296 for (PetscInt k_cell = lzs; k_cell < lze; k_cell++) {
297 for (PetscInt j_cell = lys; j_cell < lye; j_cell++) {
298 for (PetscInt i_cell = lxs; i_cell < lxe; i_cell++) {
299 const PetscReal cx = cent[k_cell][j_cell][i_cell].
x, cy = cent[k_cell][j_cell][i_cell].
y, cz = cent[k_cell][j_cell][i_cell].
z;
300 ucat[k_cell][j_cell][i_cell].
x = V0 * sin(k*cx) * cos(k*cy) * cos(k*cz) * vel_decay;
301 ucat[k_cell][j_cell][i_cell].
y = -V0 * cos(k*cx) * sin(k*cy) * cos(k*cz) * vel_decay;
302 ucat[k_cell][j_cell][i_cell].
z = 0.0;
309 for (PetscInt k_cell = lzs; k_cell < lze; k_cell++) {
310 for (PetscInt j_cell = lys; j_cell < lye; j_cell++) {
311 for (PetscInt i_cell = lxs; i_cell < lxe; i_cell++) {
312 const PetscReal cx = cent[k_cell][j_cell][i_cell].
x, cy = cent[k_cell][j_cell][i_cell].
y;
313 p[k_cell][j_cell][i_cell] = p0 + (rho * V0 * V0 / 4.0) * (cos(2*k*cx) + cos(2*k*cy)) * prs_decay;
320 if (xs == 0)
for (PetscInt k=zs; k<ze; k++)
for (PetscInt j=ys; j<ye; j++) {
321 const PetscReal fcx=cent_x[k][j][xs].
x, fcy=cent_x[k][j][xs].
y, fcz=cent_x[k][j][xs].
z;
322 ubcs[k][j][xs].
x = V0*sin(k*fcx)*cos(k*fcy)*cos(k*fcz)*vel_decay; ubcs[k][j][xs].
y = -V0*cos(k*fcx)*sin(k*fcy)*cos(k*fcz)*vel_decay; ubcs[k][j][xs].
z = 0.0;
324 if (xe == mx)
for (PetscInt k=zs; k<ze; k++)
for (PetscInt j=ys; j<ye; j++) {
325 const PetscReal fcx=cent_x[k][j][xe-1].
x, fcy=cent_x[k][j][xe-1].
y, fcz=cent_x[k][j][xe-1].
z;
326 ubcs[k][j][xe-1].
x = V0*sin(k*fcx)*cos(k*fcy)*cos(k*fcz)*vel_decay; ubcs[k][j][xe-1].
y = -V0*cos(k*fcx)*sin(k*fcy)*cos(k*fcz)*vel_decay; ubcs[k][j][xe-1].
z = 0.0;
328 if (ys == 0)
for (PetscInt k=zs; k<ze; k++)
for (PetscInt i=xs; i<xe; i++) {
329 const PetscReal fcx=cent_y[k][ys][i].
x, fcy=cent_y[k][ys][i].
y, fcz=cent_y[k][ys][i].
z;
330 ubcs[k][ys][i].
x = V0*sin(k*fcx)*cos(k*fcy)*cos(k*fcz)*vel_decay; ubcs[k][ys][i].
y = -V0*cos(k*fcx)*sin(k*fcy)*cos(k*fcz)*vel_decay; ubcs[k][ys][i].
z = 0.0;
332 if (ye == my)
for (PetscInt k=zs; k<ze; k++)
for (PetscInt i=xs; i<xe; i++) {
333 const PetscReal fcx=cent_y[k][ye-1][i].
x, fcy=cent_y[k][ye-1][i].
y, fcz=cent_y[k][ye-1][i].
z;
334 ubcs[k][ye-1][i].
x = V0*sin(k*fcx)*cos(k*fcy)*cos(k*fcz)*vel_decay; ubcs[k][ye-1][i].
y = -V0*cos(k*fcx)*sin(k*fcy)*cos(k*fcz)*vel_decay; ubcs[k][ye-1][i].
z = 0.0;
336 if (zs == 0)
for (PetscInt j=ys; j<ye; j++)
for (PetscInt i=xs; i<xe; i++) {
337 const PetscReal fcx=cent_z[zs][j][i].
x, fcy=cent_z[zs][j][i].
y, fcz=cent_z[zs][j][i].
z;
338 ubcs[zs][j][i].
x = V0*sin(k*fcx)*cos(k*fcy)*cos(k*fcz)*vel_decay; ubcs[zs][j][i].
y = -V0*cos(k*fcx)*sin(k*fcy)*cos(k*fcz)*vel_decay; ubcs[zs][j][i].
z = 0.0;
340 if (ze == mz)
for (PetscInt j=ys; j<ye; j++)
for (PetscInt i=xs; i<xe; i++) {
341 const PetscReal fcx=cent_z[ze-1][j][i].
x, fcy=cent_z[ze-1][j][i].
y, fcz=cent_z[ze-1][j][i].
z;
342 ubcs[ze-1][j][i].
x = V0*sin(k*fcx)*cos(k*fcy)*cos(k*fcz)*vel_decay; ubcs[ze-1][j][i].
y = -V0*cos(k*fcx)*sin(k*fcy)*cos(k*fcz)*vel_decay; ubcs[ze-1][j][i].
z = 0.0;
346 ierr = DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat); CHKERRQ(ierr);
347 ierr = DMDAVecRestoreArray(user->
da, user->
P, &p); CHKERRQ(ierr);
348 ierr = DMDAVecRestoreArray(user->
fda, user->
Bcs.
Ubcs, &ubcs); CHKERRQ(ierr);
349 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
Cent, ¢); CHKERRQ(ierr);
350 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCentx, ¢_x); CHKERRQ(ierr);
351 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCenty, ¢_y); CHKERRQ(ierr);
352 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCentz, ¢_z); CHKERRQ(ierr);
372 PetscFunctionReturn(0);
420 const PetscReal u = uniform_velocity.
x;
421 const PetscReal v = uniform_velocity.
y;
422 const PetscReal w = uniform_velocity.
z;
424 PetscFunctionBeginUser;
426 for (PetscInt bi = 0; bi < simCtx->
block_number; bi++) {
427 UserCtx *user = &user_finest[bi];
428 DMDALocalInfo info = user->
info;
429 PetscInt xs = info.xs, xe = info.xs + info.xm;
430 PetscInt ys = info.ys, ye = info.ys + info.ym;
431 PetscInt zs = info.zs, ze = info.zs + info.zm;
432 PetscInt mx = info.mx, my = info.my, mz = info.mz;
439 ierr = DMDAVecGetArray(user->
fda, user->
Bcs.
Ubcs, &ubcs); CHKERRQ(ierr);
440 if (xs == 0)
for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) ubcs[k][j][xs] = uniform_velocity;
441 if (xe == mx)
for (PetscInt k = zs; k < ze; k++)
for (PetscInt j = ys; j < ye; j++) ubcs[k][j][xe - 1] = uniform_velocity;
442 if (ys == 0)
for (PetscInt k = zs; k < ze; k++)
for (PetscInt i = xs; i < xe; i++) ubcs[k][ys][i] = uniform_velocity;
443 if (ye == my)
for (PetscInt k = zs; k < ze; k++)
for (PetscInt i = xs; i < xe; i++) ubcs[k][ye - 1][i] = uniform_velocity;
444 if (zs == 0)
for (PetscInt j = ys; j < ye; j++)
for (PetscInt i = xs; i < xe; i++) ubcs[zs][j][i] = uniform_velocity;
445 if (ze == mz)
for (PetscInt j = ys; j < ye; j++)
for (PetscInt i = xs; i < xe; i++) ubcs[ze - 1][j][i] = uniform_velocity;
446 ierr = DMDAVecRestoreArray(user->
fda, user->
Bcs.
Ubcs, &ubcs); CHKERRQ(ierr);
449 ierr = VecZeroEntries(user->
P); CHKERRQ(ierr);
467 PetscFunctionReturn(0);
639 PetscReal *positions = NULL;
640 PetscReal *scalar_values = NULL;
642 const char *swarm_field_name = NULL;
644 PetscFunctionBeginUser;
645 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx cannot be NULL.");
646 if (!user->
swarm) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"UserCtx->swarm is NULL.");
650 PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
651 "Analytical scalar assignment requires a one-component PETSC_REAL particle field; '%s' has %d components and type %s.",
655 ierr = DMSwarmGetLocalSize(user->
swarm, &nlocal); CHKERRQ(ierr);
656 if (nlocal == 0) PetscFunctionReturn(0);
659 ierr = DMSwarmGetField(user->
swarm, swarm_field_name, NULL, NULL, (
void **)&scalar_values); CHKERRQ(ierr);
661 for (PetscInt p = 0; p < nlocal; ++p) {
662 PetscReal value = 0.0;
664 positions[3 * p + 0],
665 positions[3 * p + 1],
666 positions[3 * p + 2],
668 &value); CHKERRQ(ierr);
669 scalar_values[p] = value;
672 ierr = DMSwarmRestoreField(user->
swarm, swarm_field_name, NULL, NULL, (
void **)&scalar_values); CHKERRQ(ierr);
674 PetscFunctionReturn(0);
688 PetscReal ***target = NULL;
689 const Cmpnts ***cent = NULL;
691 PetscInt xs, xe, ys, ye, zs, ze, mx, my, mz;
692 PetscInt lxs, lxe, lys, lye, lzs, lze;
694 PetscFunctionBeginUser;
695 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx cannot be NULL.");
696 if (!targetVec) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"targetVec cannot be NULL.");
699 xs = info.xs; xe = info.xs + info.xm;
700 ys = info.ys; ye = info.ys + info.ym;
701 zs = info.zs; ze = info.zs + info.zm;
702 mx = info.mx; my = info.my; mz = info.mz;
703 lxs = (xs == 0) ? xs + 1 : xs; lxe = (xe == mx) ? xe - 1 : xe;
704 lys = (ys == 0) ? ys + 1 : ys; lye = (ye == my) ? ye - 1 : ye;
705 lzs = (zs == 0) ? zs + 1 : zs; lze = (ze == mz) ? ze - 1 : ze;
707 ierr = VecSet(targetVec, 0.0); CHKERRQ(ierr);
708 ierr = DMDAVecGetArray(user->
da, targetVec, &target); CHKERRQ(ierr);
709 ierr = DMDAVecGetArrayRead(user->
fda, user->
Cent, ¢); CHKERRQ(ierr);
711 for (PetscInt k = lzs; k < lze; ++k) {
712 for (PetscInt j = lys; j < lye; ++j) {
713 for (PetscInt i = lxs; i < lxe; ++i) {
714 PetscReal value = 0.0;
720 &value); CHKERRQ(ierr);
721 target[k][j][i] = value;
726 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
Cent, ¢); CHKERRQ(ierr);
727 ierr = DMDAVecRestoreArray(user->
da, targetVec, &target); CHKERRQ(ierr);
728 PetscFunctionReturn(0);
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.
PetscErrorCode ParticleFieldGetDescriptor(ParticleFieldId field_id, const ParticleFieldDescriptor **descriptor)
Return immutable metadata for a valid particle field ID.