PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
Macros | Functions
AnalyticalSolutions.c File Reference

Implements the analytical solution engine for initializing or driving the simulation. More...

#include "AnalyticalSolutions.h"
#include <petscmath.h>
Include dependency graph for AnalyticalSolutions.c:

Go to the source code of this file.

Macros

#define __FUNCT__   "SetAnalyticalGridInfo"
 
#define __FUNCT__   "AnalyticalSolutionEngine"
 
#define __FUNCT__   "SetAnalyticalSolution_TGV3D"
 
#define __FUNCT__   "SetAnalyticalSolution_ZeroFlow"
 
#define __FUNCT__   "SetAnalyticalSolution_UniformFlow"
 
#define __FUNCT__   "SetAnalyticalSolutionForParticles_TGV3D"
 
#define __FUNCT__   "SetAnalyticalSolutionForParticles_UniformFlow"
 
#define __FUNCT__   "SetAnalyticalSolutionForParticles"
 
#define __FUNCT__   "EvaluateAnalyticalScalarProfile"
 
#define __FUNCT__   "SetAnalyticalScalarFieldOnParticles"
 
#define __FUNCT__   "SetAnalyticalScalarFieldAtCellCenters"
 

Functions

static PetscErrorCode SetAnalyticalSolution_TGV3D (SimCtx *simCtx)
 Populate the Eulerian field vectors with the Taylor–Green vortex at the current time.
 
static PetscErrorCode SetAnalyticalSolution_ZeroFlow (SimCtx *simCtx)
 Set every analytical Eulerian field to the quiescent zero-flow reference state.
 
static PetscErrorCode SetAnalyticalSolution_UniformFlow (SimCtx *simCtx)
 Fill the analytical Eulerian fields with the configured spatially uniform flow state.
 
static PetscErrorCode SetAnalyticalSolutionForParticles_TGV3D (Vec tempVec, SimCtx *simCtx)
 Evaluate Taylor–Green velocities at swarm particle positions and store them in tempVec.
 
static PetscErrorCode SetAnalyticalSolutionForParticles_UniformFlow (Vec tempVec, SimCtx *simCtx)
 Fill the particle velocity vector with the configured uniform analytical flow.
 
static PetscErrorCode EvaluateConfiguredScalarProfile (const VerificationScalarConfig *cfg, PetscReal x, PetscReal y, PetscReal z, PetscReal *value)
 Internal helper that evaluates the configured scalar verification profile.
 
PetscBool AnalyticalTypeRequiresCustomGeometry (const char *analytical_type)
 Implementation of AnalyticalTypeRequiresCustomGeometry().
 
PetscBool AnalyticalTypeSupportsInterpolationError (const char *analytical_type)
 Implementation of AnalyticalTypeSupportsInterpolationError().
 
PetscErrorCode SetAnalyticalGridInfo (UserCtx *user)
 Internal helper implementation: SetAnalyticalGridInfo().
 
PetscErrorCode AnalyticalSolutionEngine (SimCtx *simCtx)
 Implementation of AnalyticalSolutionEngine().
 
PetscErrorCode SetAnalyticalSolutionForParticles (Vec tempVec, SimCtx *simCtx)
 Implementation of SetAnalyticalSolutionForParticles().
 
PetscErrorCode EvaluateAnalyticalScalarProfile (const SimCtx *simCtx, PetscReal x, PetscReal y, PetscReal z, PetscReal t, PetscReal *value)
 Implementation of EvaluateAnalyticalScalarProfile().
 
PetscErrorCode SetAnalyticalScalarFieldOnParticles (UserCtx *user, ParticleFieldId particle_field_id)
 Implementation of SetAnalyticalScalarFieldOnParticles().
 
PetscErrorCode SetAnalyticalScalarFieldAtCellCenters (UserCtx *user, Vec targetVec)
 Implementation of SetAnalyticalScalarFieldAtCellCenters().
 

Detailed Description

Implements the analytical solution engine for initializing or driving the simulation.

This file provides a modular and extensible framework for applying analytical solutions to the Eulerian fields. The primary entry point is AnalyticalSolutionEngine, which acts as a dispatcher based on user configuration.

— DESIGN PHILOSOPHY —

  1. Non-Dimensional Core: All calculations within this engine are performed in non-dimensional units (e.g., reference velocity U_ref=1.0, reference length L_ref=1.0). This is critical for consistency with the core numerical solver, which also operates on non-dimensional equations. The simCtx->scaling parameters are intentionally NOT used here; they are reserved for dimensionalization during I/O and post-processing only.
  2. Separation of Concerns: The role of this engine is to set the physical state of the fluid at a given time t. This involves:
    • For most types (TGV3D, ZERO_FLOW): setting Ucat and P directly.
    • For curvilinear-aware types (UNIFORM_FLOW): setting Ucont via metric dot products and deriving Ucat through Contra2Cart.
    • Declaring the physical values on the boundaries by populating the boundary condition vector (user->Bcs.Ubcs). It does NOT implement the numerical scheme for ghost cells. Instead, after setting the physical state, it relies on the solver's standard utility functions (UpdateDummyCells, UpdateCornerNodes) to correctly populate all ghost cell layers.
  3. Extensibility: The dispatcher design makes it straightforward to add new analytical solutions. A developer only needs to add a new else if condition and a corresponding static implementation function, without modifying any other part of the solver.

Definition in file AnalyticalSolutions.c.

Macro Definition Documentation

◆ __FUNCT__ [1/11]

#define __FUNCT__   "SetAnalyticalGridInfo"

Definition at line 75 of file AnalyticalSolutions.c.

◆ __FUNCT__ [2/11]

#define __FUNCT__   "AnalyticalSolutionEngine"

Definition at line 75 of file AnalyticalSolutions.c.

◆ __FUNCT__ [3/11]

#define __FUNCT__   "SetAnalyticalSolution_TGV3D"

Definition at line 75 of file AnalyticalSolutions.c.

◆ __FUNCT__ [4/11]

#define __FUNCT__   "SetAnalyticalSolution_ZeroFlow"

Definition at line 75 of file AnalyticalSolutions.c.

◆ __FUNCT__ [5/11]

#define __FUNCT__   "SetAnalyticalSolution_UniformFlow"

Definition at line 75 of file AnalyticalSolutions.c.

◆ __FUNCT__ [6/11]

#define __FUNCT__   "SetAnalyticalSolutionForParticles_TGV3D"

Definition at line 75 of file AnalyticalSolutions.c.

◆ __FUNCT__ [7/11]

#define __FUNCT__   "SetAnalyticalSolutionForParticles_UniformFlow"

Definition at line 75 of file AnalyticalSolutions.c.

◆ __FUNCT__ [8/11]

#define __FUNCT__   "SetAnalyticalSolutionForParticles"

Definition at line 75 of file AnalyticalSolutions.c.

◆ __FUNCT__ [9/11]

#define __FUNCT__   "EvaluateAnalyticalScalarProfile"

Definition at line 75 of file AnalyticalSolutions.c.

◆ __FUNCT__ [10/11]

#define __FUNCT__   "SetAnalyticalScalarFieldOnParticles"

Definition at line 75 of file AnalyticalSolutions.c.

◆ __FUNCT__ [11/11]

#define __FUNCT__   "SetAnalyticalScalarFieldAtCellCenters"

Definition at line 75 of file AnalyticalSolutions.c.

Function Documentation

◆ SetAnalyticalSolution_TGV3D()

static PetscErrorCode SetAnalyticalSolution_TGV3D ( SimCtx simCtx)
static

Populate the Eulerian field vectors with the Taylor–Green vortex at the current time.

Definition at line 238 of file AnalyticalSolutions.c.

239{
240 PetscErrorCode ierr;
241 UserCtx *user_finest = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
242
243 // --- NON-DIMENSIONAL TGV Parameters ---
244 const PetscReal V0 = 1.0; // Non-dimensional reference velocity.
245 const PetscReal rho = 1.0; // Non-dimensional reference density.
246 const PetscReal p0 = 0.0; // Non-dimensional reference pressure.
247
248 // Kinematic viscosity is derived from the non-dimensional Reynolds number.
249 const PetscReal nu = (simCtx->ren > 0) ? (1.0 / simCtx->ren) : 0.0;
250
251 const PetscReal k = 1.0; // Wavenumber, assumes a non-dimensional [0, 2*pi] domain.
252 const PetscReal t = simCtx->ti;
253
254 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);
255
256 const PetscReal vel_decay = exp(-2.0 * nu * k * k * t);
257 const PetscReal prs_decay = exp(-4.0 * nu * k * k * t);
258
259 PetscFunctionBeginUser;
260
261 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
262 UserCtx* user = &user_finest[bi];
263 DMDALocalInfo info = user->info;
264 PetscInt xs = info.xs, xe = info.xs + info.xm;
265 PetscInt ys = info.ys, ye = info.ys + info.ym;
266 PetscInt zs = info.zs, ze = info.zs + info.zm;
267 PetscInt mx = info.mx, my = info.my, mz = info.mz;
268
269 Cmpnts ***ucat, ***ubcs;
270 const Cmpnts ***cent, ***cent_x, ***cent_y, ***cent_z;
271 PetscReal ***p;
272
273 // Define loop bounds for physical interior cells owned by this rank.
274 PetscInt lxs = (xs == 0) ? xs + 1 : xs, lxe = (xe == mx) ? xe - 1 : xe;
275 PetscInt lys = (ys == 0) ? ys + 1 : ys, lye = (ye == my) ? ye - 1 : ye;
276 PetscInt lzs = (zs == 0) ? zs + 1 : zs, lze = (ze == mz) ? ze - 1 : ze;
277
278 // --- Get Arrays ---
279 ierr = DMDAVecGetArray(user->fda, user->Ucat, &ucat); CHKERRQ(ierr);
280 ierr = DMDAVecGetArray(user->da, user->P, &p); CHKERRQ(ierr);
281 ierr = DMDAVecGetArray(user->fda, user->Bcs.Ubcs, &ubcs); CHKERRQ(ierr);
282 ierr = DMDAVecGetArrayRead(user->fda, user->Cent, &cent); CHKERRQ(ierr);
283 ierr = DMDAVecGetArrayRead(user->fda, user->lCentx, &cent_x); CHKERRQ(ierr);
284 ierr = DMDAVecGetArrayRead(user->fda, user->lCenty, &cent_y); CHKERRQ(ierr);
285 ierr = DMDAVecGetArrayRead(user->fda, user->lCentz, &cent_z); CHKERRQ(ierr);
286
287 // --- Set INTERIOR cell-centered velocity (Ucat) ---
288 for (PetscInt k_cell = lzs; k_cell < lze; k_cell++) {
289 for (PetscInt j_cell = lys; j_cell < lye; j_cell++) {
290 for (PetscInt i_cell = lxs; i_cell < lxe; i_cell++) {
291 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;
292 ucat[k_cell][j_cell][i_cell].x = V0 * sin(k*cx) * cos(k*cy) * cos(k*cz) * vel_decay;
293 ucat[k_cell][j_cell][i_cell].y = -V0 * cos(k*cx) * sin(k*cy) * cos(k*cz) * vel_decay;
294 ucat[k_cell][j_cell][i_cell].z = 0.0;
295 }
296 }
297 }
298
299
300 // --- Set INTERIOR cell-centered pressure (P) ---
301 for (PetscInt k_cell = lzs; k_cell < lze; k_cell++) {
302 for (PetscInt j_cell = lys; j_cell < lye; j_cell++) {
303 for (PetscInt i_cell = lxs; i_cell < lxe; i_cell++) {
304 const PetscReal cx = cent[k_cell][j_cell][i_cell].x, cy = cent[k_cell][j_cell][i_cell].y;
305 p[k_cell][j_cell][i_cell] = p0 + (rho * V0 * V0 / 4.0) * (cos(2*k*cx) + cos(2*k*cy)) * prs_decay;
306 }
307 }
308 }
309
310
311 // --- Set BOUNDARY condition vector for velocity (Ubcs) ---
312 if (xs == 0) for (PetscInt k=zs; k<ze; k++) for (PetscInt j=ys; j<ye; j++) {
313 const PetscReal fcx=cent_x[k][j][xs].x, fcy=cent_x[k][j][xs].y, fcz=cent_x[k][j][xs].z;
314 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;
315 }
316 if (xe == mx) for (PetscInt k=zs; k<ze; k++) for (PetscInt j=ys; j<ye; j++) {
317 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;
318 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;
319 }
320 if (ys == 0) for (PetscInt k=zs; k<ze; k++) for (PetscInt i=xs; i<xe; i++) {
321 const PetscReal fcx=cent_y[k][ys][i].x, fcy=cent_y[k][ys][i].y, fcz=cent_y[k][ys][i].z;
322 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;
323 }
324 if (ye == my) for (PetscInt k=zs; k<ze; k++) for (PetscInt i=xs; i<xe; i++) {
325 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;
326 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;
327 }
328 if (zs == 0) for (PetscInt j=ys; j<ye; j++) for (PetscInt i=xs; i<xe; i++) {
329 const PetscReal fcx=cent_z[zs][j][i].x, fcy=cent_z[zs][j][i].y, fcz=cent_z[zs][j][i].z;
330 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;
331 }
332 if (ze == mz) for (PetscInt j=ys; j<ye; j++) for (PetscInt i=xs; i<xe; i++) {
333 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;
334 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;
335 }
336
337 // --- Set PRESSURE GHOST CELLS (Neumann BC: P_ghost = P_interior) ---
338 if (xs == 0) for (PetscInt k=lzs; k<lze; k++) for (PetscInt j=lys; j<lye; j++) p[k][j][xs] = p[k][j][xs+1];
339 if (xe == mx) for (PetscInt k=lzs; k<lze; k++) for (PetscInt j=lys; j<lye; j++) p[k][j][xe-1] = p[k][j][xe-2];
340
341 if (ys == 0) for (PetscInt k=lzs; k<lze; k++) for (PetscInt i=lxs; i<lxe; i++) p[k][ys][i] = p[k][ys+1][i];
342 if (ye == my) for (PetscInt k=lzs; k<lze; k++) for (PetscInt i=lxs; i<lxe; i++) p[k][ye-1][i] = p[k][ye-2][i];
343
344 if (zs == 0) for (PetscInt j=lys; j<lye; j++) for (PetscInt i=lxs; i<lxe; i++) p[zs][j][i] = p[zs+1][j][i];
345 if (ze == mz) for (PetscInt j=lys; j<lye; j++) for (PetscInt i=lxs; i<lxe; i++) p[ze-1][j][i] = p[ze-2][j][i];
346
347 // --- Restore all arrays ---
348 ierr = DMDAVecRestoreArray(user->fda, user->Ucat, &ucat); CHKERRQ(ierr);
349 ierr = DMDAVecRestoreArray(user->da, user->P, &p); CHKERRQ(ierr);
350 ierr = DMDAVecRestoreArray(user->fda, user->Bcs.Ubcs, &ubcs); CHKERRQ(ierr);
351 ierr = DMDAVecRestoreArrayRead(user->fda, user->Cent, &cent); CHKERRQ(ierr);
352 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCentx, &cent_x); CHKERRQ(ierr);
353 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCenty, &cent_y); CHKERRQ(ierr);
354 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCentz, &cent_z); CHKERRQ(ierr);
355
356 // Pre-Dummy cell update synchronization.
357 ierr = UpdateLocalGhosts(user, FIELD_ID_UCAT);
358 ierr = UpdateLocalGhosts(user, FIELD_ID_P);
359
360 // --- Finalize all ghost cell values ---
361 ierr = UpdateDummyCells(user); CHKERRQ(ierr);
362 ierr = UpdateCornerNodes(user); CHKERRQ(ierr);
363
364 // Final Synchronization.
365 ierr = UpdateLocalGhosts(user, FIELD_ID_UCAT);
366 ierr = UpdateLocalGhosts(user, FIELD_ID_P);
367
368 }
369
370 PetscFunctionReturn(0);
371}
PetscErrorCode UpdateDummyCells(UserCtx *user)
Updates the dummy cells (ghost nodes) on the faces of the local domain for NON-PERIODIC boundaries.
PetscErrorCode UpdateCornerNodes(UserCtx *user)
Updates the corner and edge ghost nodes of the local domain by averaging.
@ FIELD_ID_UCAT
@ FIELD_ID_P
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:46
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
Definition logging.h:200
@ LOG_TRACE
Very fine-grained tracing information for in-depth debugging.
Definition logging.h:33
PetscErrorCode UpdateLocalGhosts(UserCtx *user, FieldId field_id)
Updates the local vector (including ghost points) from its corresponding global vector.
Definition setup.c:1838
UserCtx * user
Definition variables.h:571
PetscInt block_number
Definition variables.h:790
UserMG usermg
Definition variables.h:852
PetscReal ren
Definition variables.h:744
Vec Ubcs
Physical Cartesian velocity at boundary faces. Full 3D array but only boundary-face entries are meani...
Definition variables.h:123
PetscScalar x
Definition variables.h:103
BCS Bcs
Definition variables.h:934
PetscScalar z
Definition variables.h:103
Vec Ucat
Definition variables.h:939
Vec lCenty
Definition variables.h:976
PetscInt mglevels
Definition variables.h:578
Vec lCentx
Definition variables.h:976
DMDALocalInfo info
Definition variables.h:918
PetscScalar y
Definition variables.h:103
Vec Cent
Definition variables.h:974
MGCtx * mgctx
Definition variables.h:581
Vec lCentz
Definition variables.h:976
PetscReal ti
Definition variables.h:704
A 3D point or vector with PetscScalar components.
Definition variables.h:102
User-defined context containing data specific to a single computational grid level.
Definition variables.h:906
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetAnalyticalSolution_ZeroFlow()

static PetscErrorCode SetAnalyticalSolution_ZeroFlow ( SimCtx simCtx)
static

Set every analytical Eulerian field to the quiescent zero-flow reference state.

Definition at line 378 of file AnalyticalSolutions.c.

379{
380 PetscErrorCode ierr;
381 UserCtx *user_finest = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
382
383 PetscFunctionBeginUser;
384
385 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
386 UserCtx *user = &user_finest[bi];
387
388 ierr = VecZeroEntries(user->Ucat); CHKERRQ(ierr);
389 ierr = VecZeroEntries(user->P); CHKERRQ(ierr);
390 ierr = VecZeroEntries(user->Bcs.Ubcs); CHKERRQ(ierr);
391
392 // Ghost-cell finalization — identical sequence to TGV3D
393 ierr = UpdateLocalGhosts(user, FIELD_ID_UCAT); CHKERRQ(ierr);
394 ierr = UpdateLocalGhosts(user, FIELD_ID_P); CHKERRQ(ierr);
395 ierr = UpdateDummyCells(user); CHKERRQ(ierr);
396 ierr = UpdateCornerNodes(user); CHKERRQ(ierr);
397 ierr = UpdateLocalGhosts(user, FIELD_ID_UCAT); CHKERRQ(ierr);
398 ierr = UpdateLocalGhosts(user, FIELD_ID_P); CHKERRQ(ierr);
399 }
400
401 PetscFunctionReturn(0);
402}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetAnalyticalSolution_UniformFlow()

static PetscErrorCode SetAnalyticalSolution_UniformFlow ( SimCtx simCtx)
static

Fill the analytical Eulerian fields with the configured spatially uniform flow state.

Definition at line 409 of file AnalyticalSolutions.c.

410{
411 PetscErrorCode ierr;
412 UserCtx *user_finest = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
413 const Cmpnts uniform_velocity = simCtx->AnalyticalUniformVelocity;
414 const PetscReal u = uniform_velocity.x;
415 const PetscReal v = uniform_velocity.y;
416 const PetscReal w = uniform_velocity.z;
417
418 PetscFunctionBeginUser;
419
420 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
421 UserCtx *user = &user_finest[bi];
422 DMDALocalInfo info = user->info;
423 PetscInt xs = info.xs, xe = info.xs + info.xm;
424 PetscInt ys = info.ys, ye = info.ys + info.ym;
425 PetscInt zs = info.zs, ze = info.zs + info.zm;
426 PetscInt mx = info.mx, my = info.my, mz = info.mz;
427
428 // --- Step 1: Set Ucont (contravariant flux) via Cart2Contra ---
429 ierr = UniformCart2Contra(user, u, v, w); CHKERRQ(ierr);
430
431 // --- Step 2: Set Ubcs at boundaries (physical Cartesian velocity) ---
432 Cmpnts ***ubcs;
433 ierr = DMDAVecGetArray(user->fda, user->Bcs.Ubcs, &ubcs); CHKERRQ(ierr);
434 if (xs == 0) for (PetscInt k = zs; k < ze; k++) for (PetscInt j = ys; j < ye; j++) ubcs[k][j][xs] = uniform_velocity;
435 if (xe == mx) for (PetscInt k = zs; k < ze; k++) for (PetscInt j = ys; j < ye; j++) ubcs[k][j][xe - 1] = uniform_velocity;
436 if (ys == 0) for (PetscInt k = zs; k < ze; k++) for (PetscInt i = xs; i < xe; i++) ubcs[k][ys][i] = uniform_velocity;
437 if (ye == my) for (PetscInt k = zs; k < ze; k++) for (PetscInt i = xs; i < xe; i++) ubcs[k][ye - 1][i] = uniform_velocity;
438 if (zs == 0) for (PetscInt j = ys; j < ye; j++) for (PetscInt i = xs; i < xe; i++) ubcs[zs][j][i] = uniform_velocity;
439 if (ze == mz) for (PetscInt j = ys; j < ye; j++) for (PetscInt i = xs; i < xe; i++) ubcs[ze - 1][j][i] = uniform_velocity;
440 ierr = DMDAVecRestoreArray(user->fda, user->Bcs.Ubcs, &ubcs); CHKERRQ(ierr);
441
442 // --- Step 3: Zero pressure ---
443 ierr = VecZeroEntries(user->P); CHKERRQ(ierr);
444
445 // --- Step 4: Finalize state — derive Ucat from Ucont via metric inversion ---
446 const FieldId staggered_fields[] = {FIELD_ID_UCONT};
447 ierr = SynchronizePeriodicStaggeredFields(user, 1, staggered_fields); CHKERRQ(ierr);
448 ierr = Contra2Cart(user); CHKERRQ(ierr);
449 ierr = UpdateLocalGhosts(user, FIELD_ID_UCAT); CHKERRQ(ierr);
450 ierr = UpdateLocalGhosts(user, FIELD_ID_P); CHKERRQ(ierr);
451 ierr = UpdateDummyCells(user); CHKERRQ(ierr);
452 ierr = UpdateCornerNodes(user); CHKERRQ(ierr);
453 ierr = UpdateLocalGhosts(user, FIELD_ID_UCAT); CHKERRQ(ierr);
454 ierr = UpdateLocalGhosts(user, FIELD_ID_P); CHKERRQ(ierr);
455 }
456
457 PetscFunctionReturn(0);
458}
PetscErrorCode SynchronizePeriodicStaggeredFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes persistent component-staggered vector fields.
FieldId
Compile-time identity for a catalogued Eulerian field.
@ FIELD_ID_UCONT
PetscErrorCode UniformCart2Contra(UserCtx *user, PetscReal u, PetscReal v, PetscReal w)
Populate contravariant fluxes from one uniform Cartesian velocity.
Definition setup.c:2853
PetscErrorCode Contra2Cart(UserCtx *user)
Reconstructs Cartesian velocity (Ucat) at cell centers from contravariant velocity (Ucont) defined on...
Definition setup.c:2649
Cmpnts AnalyticalUniformVelocity
Definition variables.h:760
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetAnalyticalSolutionForParticles_TGV3D()

static PetscErrorCode SetAnalyticalSolutionForParticles_TGV3D ( Vec  tempVec,
SimCtx simCtx 
)
static

Evaluate Taylor–Green velocities at swarm particle positions and store them in tempVec.

Definition at line 465 of file AnalyticalSolutions.c.

466{
467 PetscErrorCode ierr;
468 PetscInt nLocal;
469 PetscReal *data;
470
471 PetscFunctionBeginUser;
472
473 // TGV3D parameters (matching your Eulerian implementation)
474 const PetscReal V0 = 1.0;
475 const PetscReal k = 1.0;
476 const PetscReal nu = (simCtx->ren > 0) ? (1.0 / simCtx->ren) : 0.0;
477 const PetscReal t = simCtx->ti;
478 const PetscReal vel_decay = exp(-2.0 * nu * k * k * t);
479
480 LOG_ALLOW(GLOBAL, LOG_DEBUG, "TGV3D Particles: t=%.4f, V0=%.4f, k=%.4f, nu=%.6f\n", t, V0, k, nu);
481
482 ierr = VecGetLocalSize(tempVec, &nLocal); CHKERRQ(ierr);
483 ierr = VecGetArray(tempVec, &data); CHKERRQ(ierr);
484
485 // Process particles: data is interleaved [x0,y0,z0, x1,y1,z1, ...]
486 for (PetscInt i = 0; i < nLocal; i += 3) {
487 const PetscReal x = data[i];
488 const PetscReal y = data[i+1];
489 const PetscReal z = data[i+2];
490
491 // TGV3D velocity field
492 data[i] = V0 * sin(k*x) * cos(k*y) * cos(k*z) * vel_decay; // u
493 data[i+1] = -V0 * cos(k*x) * sin(k*y) * cos(k*z) * vel_decay; // v
494 data[i+2] = 0.0; // w
495 }
496
497 ierr = VecRestoreArray(tempVec, &data); CHKERRQ(ierr);
498
499 PetscFunctionReturn(0);
500}
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:32
Here is the caller graph for this function:

◆ SetAnalyticalSolutionForParticles_UniformFlow()

static PetscErrorCode SetAnalyticalSolutionForParticles_UniformFlow ( Vec  tempVec,
SimCtx simCtx 
)
static

Fill the particle velocity vector with the configured uniform analytical flow.

Definition at line 507 of file AnalyticalSolutions.c.

508{
509 PetscErrorCode ierr;
510 PetscInt nLocal;
511 PetscReal *data;
512 const Cmpnts uniform_velocity = simCtx->AnalyticalUniformVelocity;
513
514 PetscFunctionBeginUser;
515
516 ierr = VecGetLocalSize(tempVec, &nLocal); CHKERRQ(ierr);
517 ierr = VecGetArray(tempVec, &data); CHKERRQ(ierr);
518 for (PetscInt i = 0; i < nLocal; i += 3) {
519 data[i] = uniform_velocity.x;
520 data[i + 1] = uniform_velocity.y;
521 data[i + 2] = uniform_velocity.z;
522 }
523 ierr = VecRestoreArray(tempVec, &data); CHKERRQ(ierr);
524
525 PetscFunctionReturn(0);
526}
Here is the caller graph for this function:

◆ EvaluateConfiguredScalarProfile()

static PetscErrorCode EvaluateConfiguredScalarProfile ( const VerificationScalarConfig cfg,
PetscReal  x,
PetscReal  y,
PetscReal  z,
PetscReal *  value 
)
static

Internal helper that evaluates the configured scalar verification profile.

Local to this translation unit.

Definition at line 564 of file AnalyticalSolutions.c.

569{
570 PetscFunctionBeginUser;
571 if (!cfg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "VerificationScalarConfig cannot be NULL.");
572 if (!value) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Scalar output pointer cannot be NULL.");
573
574 if (strcmp(cfg->profile, "CONSTANT") == 0) {
575 *value = cfg->value;
576 } else if (strcmp(cfg->profile, "LINEAR_X") == 0) {
577 *value = cfg->phi0 + cfg->slope_x * x;
578 } else if (strcmp(cfg->profile, "SIN_PRODUCT") == 0) {
579 *value = cfg->amplitude *
580 PetscSinReal(cfg->kx * x) *
581 PetscSinReal(cfg->ky * y) *
582 PetscSinReal(cfg->kz * z);
583 } else {
584 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
585 "Unsupported verification scalar profile '%s'.", cfg->profile);
586 }
587
588 PetscFunctionReturn(0);
589}
Here is the caller graph for this function:

◆ AnalyticalTypeRequiresCustomGeometry()

PetscBool AnalyticalTypeRequiresCustomGeometry ( const char *  analytical_type)

Implementation of AnalyticalTypeRequiresCustomGeometry().

Reports whether an analytical type requires custom geometry/decomposition logic.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/AnalyticalSolutions.h.

See also
AnalyticalTypeRequiresCustomGeometry()

Definition at line 55 of file AnalyticalSolutions.c.

56{
57 if (!analytical_type) return PETSC_FALSE;
58 return (strcmp(analytical_type, "TGV3D") == 0) ? PETSC_TRUE : PETSC_FALSE;
59}
Here is the caller graph for this function:

◆ AnalyticalTypeSupportsInterpolationError()

PetscBool AnalyticalTypeSupportsInterpolationError ( const char *  analytical_type)

Implementation of AnalyticalTypeSupportsInterpolationError().

Reports whether an analytical type has a non-trivial velocity field for which interpolation error measurement is meaningful.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/AnalyticalSolutions.h.

See also
AnalyticalTypeSupportsInterpolationError()

Definition at line 67 of file AnalyticalSolutions.c.

68{
69 if (!analytical_type) return PETSC_FALSE;
70 if (strcmp(analytical_type, "ZERO_FLOW") == 0 || strcmp(analytical_type, "UNIFORM_FLOW") == 0) return PETSC_FALSE;
71 return PETSC_TRUE;
72}
Here is the caller graph for this function:

◆ SetAnalyticalGridInfo()

PetscErrorCode SetAnalyticalGridInfo ( UserCtx user)

Internal helper implementation: SetAnalyticalGridInfo().

Sets the grid domain and resolution for analytical solution cases.

Local to this translation unit.

Definition at line 80 of file AnalyticalSolutions.c.

81{
82 SimCtx *simCtx = user->simCtx;
83 PetscInt nblk = simCtx->block_number;
84 PetscInt block_index = user->_this;
85
86 PetscFunctionBeginUser;
88
90 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
91 "SetAnalyticalGridInfo called for analytical type '%s' that does not require custom geometry.",
93 }
94 if (user->IM <= 0 || user->JM <= 0 || user->KM <= 0) {
95 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
96 "Analytical grid resolution is not initialized. Ensure IM/JM/KM are preloaded before SetAnalyticalGridInfo.");
97 }
98
99 if (strcmp(simCtx->AnalyticalSolutionType, "TGV3D") == 0) {
100 LOG_ALLOW_SYNC(GLOBAL, LOG_DEBUG, "Rank %d: Configuring grid for TGV3D analytical solution, block %d.\n", simCtx->rank, block_index);
101
102 if (nblk == 1) {
103 // --- Single Block Case ---
104 if (block_index == 0) {
105 LOG_ALLOW(GLOBAL, LOG_INFO, "Single block detected. Setting domain to [0, 2*PI].\n");
106 }
107 user->Min_X = 0.0; user->Max_X = 2.0 * PETSC_PI;
108 user->Min_Y = 0.0; user->Max_Y = 2.0 * PETSC_PI;
109 user->Min_Z = 0.0; user->Max_Z = 0.2 * PETSC_PI; //2.0 * PETSC_PI;
110
111 } else { // --- Multi-Block Case ---
112 PetscReal s = sqrt((PetscReal)nblk);
113
114 // Validate that nblk is a perfect square.
115 if (fabs(s - floor(s)) > 1e-9) {
116 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP,
117 "\n\n*** CONFIGURATION ERROR FOR TGV3D ***\n"
118 "For multi-block TGV3D cases, the number of blocks must be a perfect square (e.g., 4, 9, 16).\n"
119 "You have specified %d blocks. Please adjust `-block_number`.\n", nblk);
120 }
121 PetscInt blocks_per_dim = (PetscInt)s;
122
123 if (block_index == 0) {
124 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);
125 }
126
127 // Determine the (row, col) position of this block in the 2D decomposition
128 PetscInt row = block_index / blocks_per_dim;
129 PetscInt col = block_index % blocks_per_dim;
130
131 // Calculate the width/height of each sub-domain
132 PetscReal block_width = (2.0 * PETSC_PI) / (PetscReal)blocks_per_dim;
133 PetscReal block_height = (2.0 * PETSC_PI) / (PetscReal)blocks_per_dim;
134
135 // Assign this block its specific sub-domain
136 user->Min_X = col * block_width;
137 user->Max_X = (col + 1) * block_width;
138 user->Min_Y = row * block_height;
139 user->Max_Y = (row + 1) * block_height;
140 user->Min_Z = 0.0;
141 user->Max_Z = 2.0 * PETSC_PI; // Z-domain is not decomposed
142 }
143 }
144 /*
145 * --- EXTENSIBILITY HOOK ---
146 * To add another analytical case with special grid requirements:
147 *
148 * else if (strcmp(simCtx->AnalyticalSolutionType, "ChannelFlow") == 0) {
149 * // ... implement logic to set domain for ChannelFlow case ...
150 * }
151 */
152 else {
153 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_UNKNOWN_TYPE,
154 "Analytical type '%s' has no custom geometry implementation.",
155 simCtx->AnalyticalSolutionType);
156 }
157
158 // We can also read stretching ratios, as they are independent of the domain size
159 // For simplicity, we assume uniform grid unless specified.
160 user->rx = 1.0; user->ry = 1.0; user->rz = 1.0;
161
162 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Block %d grid resolution set: IM=%d, JM=%d, KM=%d\n",
163 simCtx->rank, block_index, user->IM, user->JM, user->KM);
164 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Block %d final bounds: X=[%.4f, %.4f], Y=[%.4f, %.4f], Z=[%.4f, %.4f]\n",
165 simCtx->rank, block_index, user->Min_X, user->Max_X, user->Min_Y, user->Max_Y, user->Min_Z, user->Max_Z);
166
168 PetscFunctionReturn(0);
169}
PetscBool AnalyticalTypeRequiresCustomGeometry(const char *analytical_type)
Implementation of AnalyticalTypeRequiresCustomGeometry().
#define LOG_ALLOW_SYNC(scope, level, fmt,...)
Synchronized logging macro that checks both the log level and whether the calling function is in the ...
Definition logging.h:253
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:45
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:859
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:31
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:850
PetscMPIInt rank
Definition variables.h:698
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:909
PetscReal Min_X
Definition variables.h:921
PetscInt KM
Definition variables.h:920
PetscInt _this
Definition variables.h:924
PetscReal ry
Definition variables.h:925
PetscReal Max_Y
Definition variables.h:921
PetscReal rz
Definition variables.h:925
PetscInt JM
Definition variables.h:920
PetscReal Min_Z
Definition variables.h:921
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
Definition variables.h:729
PetscReal Max_X
Definition variables.h:921
PetscReal Min_Y
Definition variables.h:921
PetscInt IM
Definition variables.h:920
PetscReal rx
Definition variables.h:925
PetscReal Max_Z
Definition variables.h:921
The master context for the entire simulation.
Definition variables.h:695
Here is the call graph for this function:
Here is the caller graph for this function:

◆ AnalyticalSolutionEngine()

PetscErrorCode AnalyticalSolutionEngine ( SimCtx simCtx)

Implementation of AnalyticalSolutionEngine().

Dispatches to the appropriate analytical solution function based on simulation settings.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/AnalyticalSolutions.h.

See also
AnalyticalSolutionEngine()

Definition at line 184 of file AnalyticalSolutions.c.

185{
186 PetscErrorCode ierr;
187 PetscFunctionBeginUser;
189
190 // -- Before any operation, here is defensive test to ensure that the Corner->Center Interpolation method works
191 //ierr = TestCornerToCenterInterpolation(&(simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1]->user[0]));
192
193 // --- Dispatch based on the string provided by the user ---
194 if (strcmp(simCtx->AnalyticalSolutionType, "TGV3D") == 0) {
195 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Applying Analytical Solution: 3D Taylor-Green Vortex (TGV3D).\n");
196 ierr = SetAnalyticalSolution_TGV3D(simCtx); CHKERRQ(ierr);
197 }
198 else if (strcmp(simCtx->AnalyticalSolutionType, "ZERO_FLOW") == 0) {
199 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Applying Analytical Solution: Zero Background Flow (ZERO_FLOW).\n");
200 ierr = SetAnalyticalSolution_ZeroFlow(simCtx); CHKERRQ(ierr);
201 }
202 else if (strcmp(simCtx->AnalyticalSolutionType, "UNIFORM_FLOW") == 0) {
203 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Applying Analytical Solution: Uniform Background Flow (UNIFORM_FLOW).\n");
204 ierr = SetAnalyticalSolution_UniformFlow(simCtx); CHKERRQ(ierr);
205 }
206 /*
207 * --- EXTENSIBILITY HOOK ---
208 * To add a new analytical solution (e.g., "ChannelFlow"):
209 * 1. Add an `else if` block here:
210 *
211 * else if (strcmp(simCtx->AnalyticalSolutionType, "ChannelFlow") == 0) {
212 * LOG_ALLOW(GLOBAL, LOG_DEBUG, "Applying Analytical Solution: Channel Flow.\n");
213 * ierr = SetAnalyticalSolution_ChannelFlow(simCtx); CHKERRQ(ierr);
214 * }
215 *
216 * 2. Implement the static function `SetAnalyticalSolution_ChannelFlow(SimCtx *simCtx)`
217 * below, following the TGV3D pattern.
218 */
219 else {
220 // If the type is unknown, raise a fatal error to prevent silent failures.
221 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown AnalyticalSolutionType specified: '%s'", simCtx->AnalyticalSolutionType);
222 }
223
225 PetscFunctionReturn(0);
226}
static PetscErrorCode SetAnalyticalSolution_ZeroFlow(SimCtx *simCtx)
Set every analytical Eulerian field to the quiescent zero-flow reference state.
static PetscErrorCode SetAnalyticalSolution_UniformFlow(SimCtx *simCtx)
Fill the analytical Eulerian fields with the configured spatially uniform flow state.
static PetscErrorCode SetAnalyticalSolution_TGV3D(SimCtx *simCtx)
Populate the Eulerian field vectors with the Taylor–Green vortex at the current time.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetAnalyticalSolutionForParticles()

PetscErrorCode SetAnalyticalSolutionForParticles ( Vec  tempVec,
SimCtx simCtx 
)

Implementation of SetAnalyticalSolutionForParticles().

Applies the analytical solution to particle velocity vector.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/AnalyticalSolutions.h.

See also
SetAnalyticalSolutionForParticles()

Definition at line 536 of file AnalyticalSolutions.c.

537{
538 PetscErrorCode ierr;
539 const char *analytical_type = simCtx->AnalyticalSolutionType[0] ? simCtx->AnalyticalSolutionType : "default";
540
541 PetscFunctionBeginUser;
542
543 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Type: %s\n", analytical_type);
544
545 // Check for specific analytical solution types
546 if (strcmp(simCtx->AnalyticalSolutionType, "TGV3D") == 0) {
547 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Using TGV3D solution.\n");
548 ierr = SetAnalyticalSolutionForParticles_TGV3D(tempVec, simCtx); CHKERRQ(ierr);
549 return 0;
550 }
551 if (strcmp(simCtx->AnalyticalSolutionType, "UNIFORM_FLOW") == 0) {
552 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Using UNIFORM_FLOW solution.\n");
553 ierr = SetAnalyticalSolutionForParticles_UniformFlow(tempVec, simCtx); CHKERRQ(ierr);
554 return 0;
555 }
556
557 PetscFunctionReturn(0);
558}
static PetscErrorCode SetAnalyticalSolutionForParticles_UniformFlow(Vec tempVec, SimCtx *simCtx)
Fill the particle velocity vector with the configured uniform analytical flow.
static PetscErrorCode SetAnalyticalSolutionForParticles_TGV3D(Vec tempVec, SimCtx *simCtx)
Evaluate Taylor–Green velocities at swarm particle positions and store them in tempVec.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ EvaluateAnalyticalScalarProfile()

PetscErrorCode EvaluateAnalyticalScalarProfile ( const SimCtx simCtx,
PetscReal  x,
PetscReal  y,
PetscReal  z,
PetscReal  t,
PetscReal *  value 
)

Implementation of EvaluateAnalyticalScalarProfile().

Evaluates the configured verification scalar profile at one physical point.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/AnalyticalSolutions.h.

See also
EvaluateAnalyticalScalarProfile()

Definition at line 599 of file AnalyticalSolutions.c.

605{
606 PetscFunctionBeginUser;
607 (void)t;
608 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "SimCtx cannot be NULL.");
609 if (!simCtx->verificationScalar.enabled) {
610 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
611 "EvaluateAnalyticalScalarProfile requires verification scalar mode to be enabled.");
612 }
613 PetscCall(EvaluateConfiguredScalarProfile(&simCtx->verificationScalar, x, y, z, value));
614 PetscFunctionReturn(0);
615}
static PetscErrorCode EvaluateConfiguredScalarProfile(const VerificationScalarConfig *cfg, PetscReal x, PetscReal y, PetscReal z, PetscReal *value)
Internal helper that evaluates the configured scalar verification profile.
VerificationScalarConfig verificationScalar
Definition variables.h:778
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetAnalyticalScalarFieldOnParticles()

PetscErrorCode SetAnalyticalScalarFieldOnParticles ( UserCtx user,
ParticleFieldId  particle_field_id 
)

Implementation of SetAnalyticalScalarFieldOnParticles().

Writes the configured verification scalar profile onto a particle swarm scalar field.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/AnalyticalSolutions.h.

See also
SetAnalyticalScalarFieldOnParticles()

Definition at line 625 of file AnalyticalSolutions.c.

626{
627 PetscErrorCode ierr;
628 PetscInt nlocal = 0;
629 PetscReal *positions = NULL;
630 PetscReal *scalar_values = NULL;
631 const ParticleFieldDescriptor *descriptor = NULL;
632 const char *swarm_field_name = NULL;
633
634 PetscFunctionBeginUser;
635 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx cannot be NULL.");
636 if (!user->swarm) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "UserCtx->swarm is NULL.");
637
638 ierr = ParticleFieldGetDescriptor(particle_field_id, &descriptor); CHKERRQ(ierr);
639 PetscCheck(descriptor->components == 1 && descriptor->data_type == PETSC_REAL,
640 PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP,
641 "Analytical scalar assignment requires a one-component PETSC_REAL particle field; '%s' has %d components and type %s.",
642 descriptor->canonical_name, descriptor->components, PetscDataTypes[descriptor->data_type]);
643 swarm_field_name = descriptor->canonical_name;
644
645 ierr = DMSwarmGetLocalSize(user->swarm, &nlocal); CHKERRQ(ierr);
646 if (nlocal == 0) PetscFunctionReturn(0);
647
648 ierr = DMSwarmGetField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_POSITION), NULL, NULL, (void **)&positions); CHKERRQ(ierr);
649 ierr = DMSwarmGetField(user->swarm, swarm_field_name, NULL, NULL, (void **)&scalar_values); CHKERRQ(ierr);
650
651 for (PetscInt p = 0; p < nlocal; ++p) {
652 PetscReal value = 0.0;
654 positions[3 * p + 0],
655 positions[3 * p + 1],
656 positions[3 * p + 2],
657 user->simCtx->ti,
658 &value); CHKERRQ(ierr);
659 scalar_values[p] = value;
660 }
661
662 ierr = DMSwarmRestoreField(user->swarm, swarm_field_name, NULL, NULL, (void **)&scalar_values); CHKERRQ(ierr);
663 ierr = DMSwarmRestoreField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_POSITION), NULL, NULL, (void **)&positions); CHKERRQ(ierr);
664 PetscFunctionReturn(0);
665}
PetscErrorCode EvaluateAnalyticalScalarProfile(const SimCtx *simCtx, PetscReal x, PetscReal y, PetscReal z, PetscReal t, PetscReal *value)
Implementation of EvaluateAnalyticalScalarProfile().
const char * ParticleFieldName(ParticleFieldId field_id)
Return the canonical PETSc DMSwarm name for an ID.
@ PARTICLE_FIELD_ID_POSITION
PetscErrorCode ParticleFieldGetDescriptor(ParticleFieldId field_id, const ParticleFieldDescriptor **descriptor)
Return immutable metadata for a valid particle field ID.
Immutable metadata for one persistent particle field.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetAnalyticalScalarFieldAtCellCenters()

PetscErrorCode SetAnalyticalScalarFieldAtCellCenters ( UserCtx user,
Vec  targetVec 
)

Implementation of SetAnalyticalScalarFieldAtCellCenters().

Writes the configured verification scalar profile at physical cell centers into a scalar Vec.

Full API contract (arguments, ownership, side effects) is documented with the header declaration in include/AnalyticalSolutions.h.

See also
SetAnalyticalScalarFieldAtCellCenters()

Definition at line 675 of file AnalyticalSolutions.c.

676{
677 PetscErrorCode ierr;
678 PetscReal ***target = NULL;
679 const Cmpnts ***cent = NULL;
680 DMDALocalInfo info;
681 PetscInt xs, xe, ys, ye, zs, ze, mx, my, mz;
682 PetscInt lxs, lxe, lys, lye, lzs, lze;
683
684 PetscFunctionBeginUser;
685 if (!user) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx cannot be NULL.");
686 if (!targetVec) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "targetVec cannot be NULL.");
687
688 info = user->info;
689 xs = info.xs; xe = info.xs + info.xm;
690 ys = info.ys; ye = info.ys + info.ym;
691 zs = info.zs; ze = info.zs + info.zm;
692 mx = info.mx; my = info.my; mz = info.mz;
693 lxs = (xs == 0) ? xs + 1 : xs; lxe = (xe == mx) ? xe - 1 : xe;
694 lys = (ys == 0) ? ys + 1 : ys; lye = (ye == my) ? ye - 1 : ye;
695 lzs = (zs == 0) ? zs + 1 : zs; lze = (ze == mz) ? ze - 1 : ze;
696
697 ierr = VecSet(targetVec, 0.0); CHKERRQ(ierr);
698 ierr = DMDAVecGetArray(user->da, targetVec, &target); CHKERRQ(ierr);
699 ierr = DMDAVecGetArrayRead(user->fda, user->Cent, &cent); CHKERRQ(ierr);
700
701 for (PetscInt k = lzs; k < lze; ++k) {
702 for (PetscInt j = lys; j < lye; ++j) {
703 for (PetscInt i = lxs; i < lxe; ++i) {
704 PetscReal value = 0.0;
706 cent[k][j][i].x,
707 cent[k][j][i].y,
708 cent[k][j][i].z,
709 user->simCtx->ti,
710 &value); CHKERRQ(ierr);
711 target[k][j][i] = value;
712 }
713 }
714 }
715
716 ierr = DMDAVecRestoreArrayRead(user->fda, user->Cent, &cent); CHKERRQ(ierr);
717 ierr = DMDAVecRestoreArray(user->da, targetVec, &target); CHKERRQ(ierr);
718 PetscFunctionReturn(0);
719}
Here is the call graph for this function:
Here is the caller graph for this function: