PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Macros | Functions | Variables
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().
 

Variables

static const FieldId kAnalyticalCellFields [] = {FIELD_ID_UCAT, FIELD_ID_P}
 Cell-centred fields every analytical setter finalizes, in the order the post-projection finalization uses for the solved flow.
 

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 fill dummy cells itself. After setting the physical state, every setter runs the same sequence the solved flow is finalized with (see FinalizePostProjectionCellFields): UpdateDummyCells on non-periodic faces, SynchronizePeriodicCellFields on periodic ones, UpdateCornerNodes for edges and corners, and the periodic synchronization again because corner averaging can overwrite periodic endpoints. The boundary values are this module's own Ubcs, which is why the setters do not call that finalizer: it would refresh Ubcs from the boundary handlers.
  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 83 of file AnalyticalSolutions.c.

◆ __FUNCT__ [2/11]

#define __FUNCT__   "AnalyticalSolutionEngine"

Definition at line 83 of file AnalyticalSolutions.c.

◆ __FUNCT__ [3/11]

#define __FUNCT__   "SetAnalyticalSolution_TGV3D"

Definition at line 83 of file AnalyticalSolutions.c.

◆ __FUNCT__ [4/11]

#define __FUNCT__   "SetAnalyticalSolution_ZeroFlow"

Definition at line 83 of file AnalyticalSolutions.c.

◆ __FUNCT__ [5/11]

#define __FUNCT__   "SetAnalyticalSolution_UniformFlow"

Definition at line 83 of file AnalyticalSolutions.c.

◆ __FUNCT__ [6/11]

#define __FUNCT__   "SetAnalyticalSolutionForParticles_TGV3D"

Definition at line 83 of file AnalyticalSolutions.c.

◆ __FUNCT__ [7/11]

#define __FUNCT__   "SetAnalyticalSolutionForParticles_UniformFlow"

Definition at line 83 of file AnalyticalSolutions.c.

◆ __FUNCT__ [8/11]

#define __FUNCT__   "SetAnalyticalSolutionForParticles"

Definition at line 83 of file AnalyticalSolutions.c.

◆ __FUNCT__ [9/11]

#define __FUNCT__   "EvaluateAnalyticalScalarProfile"

Definition at line 83 of file AnalyticalSolutions.c.

◆ __FUNCT__ [10/11]

#define __FUNCT__   "SetAnalyticalScalarFieldOnParticles"

Definition at line 83 of file AnalyticalSolutions.c.

◆ __FUNCT__ [11/11]

#define __FUNCT__   "SetAnalyticalScalarFieldAtCellCenters"

Definition at line 83 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 246 of file AnalyticalSolutions.c.

247{
248 PetscErrorCode ierr;
249 UserCtx *user_finest = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
250
251 // --- NON-DIMENSIONAL TGV Parameters ---
252 const PetscReal V0 = 1.0; // Non-dimensional reference velocity.
253 const PetscReal rho = 1.0; // Non-dimensional reference density.
254 const PetscReal p0 = 0.0; // Non-dimensional reference pressure.
255
256 // Kinematic viscosity is derived from the non-dimensional Reynolds number.
257 const PetscReal nu = (simCtx->ren > 0) ? (1.0 / simCtx->ren) : 0.0;
258
259 const PetscReal k = 1.0; // Wavenumber, assumes a non-dimensional [0, 2*pi] domain.
260 const PetscReal t = simCtx->ti;
261
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);
263
264 const PetscReal vel_decay = exp(-2.0 * nu * k * k * t);
265 const PetscReal prs_decay = exp(-4.0 * nu * k * k * t);
266
267 PetscFunctionBeginUser;
268
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;
276
277 Cmpnts ***ucat, ***ubcs;
278 const Cmpnts ***cent, ***cent_x, ***cent_y, ***cent_z;
279 PetscReal ***p;
280
281 // Define loop bounds for physical interior cells owned by this rank.
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;
285
286 // --- Get Arrays ---
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, &cent); CHKERRQ(ierr);
291 ierr = DMDAVecGetArrayRead(user->fda, user->lCentx, &cent_x); CHKERRQ(ierr);
292 ierr = DMDAVecGetArrayRead(user->fda, user->lCenty, &cent_y); CHKERRQ(ierr);
293 ierr = DMDAVecGetArrayRead(user->fda, user->lCentz, &cent_z); CHKERRQ(ierr);
294
295 // --- Set INTERIOR cell-centered velocity (Ucat) ---
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;
303 }
304 }
305 }
306
307
308 // --- Set INTERIOR cell-centered pressure (P) ---
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;
314 }
315 }
316 }
317
318
319 // --- Set BOUNDARY condition vector for velocity (Ubcs) ---
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;
323 }
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;
327 }
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;
331 }
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;
335 }
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;
339 }
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;
343 }
344
345 // --- Restore all arrays ---
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, &cent); CHKERRQ(ierr);
350 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCentx, &cent_x); CHKERRQ(ierr);
351 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCenty, &cent_y); CHKERRQ(ierr);
352 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCentz, &cent_z); CHKERRQ(ierr);
353
354 // Pre-Dummy cell update synchronization.
355 ierr = UpdateLocalGhosts(user, FIELD_ID_UCAT);
356 ierr = UpdateLocalGhosts(user, FIELD_ID_P);
357
358 // --- Finalize all ghost cell values ---
359 ierr = UpdateDummyCells(user, FIELD_ID_UCAT); CHKERRQ(ierr);
360 ierr = UpdateDummyCells(user, FIELD_ID_P); CHKERRQ(ierr);
361 ierr = SynchronizePeriodicCellFields(user, 2, kAnalyticalCellFields); CHKERRQ(ierr);
362 ierr = UpdateCornerNodes(user, FIELD_ID_UCAT); CHKERRQ(ierr);
363 ierr = UpdateCornerNodes(user, FIELD_ID_P); CHKERRQ(ierr);
364 ierr = SynchronizePeriodicCellFields(user, 2, kAnalyticalCellFields); CHKERRQ(ierr);
365
366 // Final Synchronization.
367 ierr = UpdateLocalGhosts(user, FIELD_ID_UCAT);
368 ierr = UpdateLocalGhosts(user, FIELD_ID_P);
369
370 }
371
372 PetscFunctionReturn(0);
373}
static const FieldId kAnalyticalCellFields[]
Cell-centred fields every analytical setter finalizes, in the order the post-projection finalization ...
PetscErrorCode UpdateDummyCells(UserCtx *user, FieldId field_id)
Fills the dummy cells on the non-periodic faces of one cell-centred field.
PetscErrorCode UpdateCornerNodes(UserCtx *user, FieldId field_id)
Fills the edge and corner dummy cells of one cell-centred field by averaging.
PetscErrorCode SynchronizePeriodicCellFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes periodic endpoint cells for a list of cell-centered fields.
@ 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:2489
UserCtx * user
Definition variables.h:729
PetscInt block_number
Definition variables.h:952
UserMG usermg
Definition variables.h:1015
PetscReal ren
Definition variables.h:906
Vec Ubcs
Physical Cartesian velocity at boundary faces. Full 3D array but only boundary-face entries are meani...
Definition variables.h:149
PetscScalar x
Definition variables.h:122
PetscScalar z
Definition variables.h:122
Vec lCenty
Definition variables.h:1150
PetscInt mglevels
Definition variables.h:736
Vec lCentx
Definition variables.h:1150
DMDALocalInfo info
Definition variables.h:1086
PetscScalar y
Definition variables.h:122
MGCtx * mgctx
Definition variables.h:739
Vec lCentz
Definition variables.h:1150
PetscReal ti
Definition variables.h:868
A 3D point or vector with PetscScalar components.
Definition variables.h:121
User-defined context containing data specific to a single computational grid level.
Definition variables.h:1074
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 380 of file AnalyticalSolutions.c.

381{
382 PetscErrorCode ierr;
383 UserCtx *user_finest = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
384
385 PetscFunctionBeginUser;
386
387 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
388 UserCtx *user = &user_finest[bi];
389
390 ierr = VecZeroEntries(user->Ucat); CHKERRQ(ierr);
391 ierr = VecZeroEntries(user->P); CHKERRQ(ierr);
392 ierr = VecZeroEntries(user->Bcs.Ubcs); CHKERRQ(ierr);
393
394 // Ghost-cell finalization — identical sequence to TGV3D
395 ierr = UpdateLocalGhosts(user, FIELD_ID_UCAT); CHKERRQ(ierr);
396 ierr = UpdateLocalGhosts(user, FIELD_ID_P); CHKERRQ(ierr);
397 ierr = UpdateDummyCells(user, FIELD_ID_UCAT); CHKERRQ(ierr);
398 ierr = UpdateDummyCells(user, FIELD_ID_P); CHKERRQ(ierr);
399 ierr = SynchronizePeriodicCellFields(user, 2, kAnalyticalCellFields); CHKERRQ(ierr);
400 ierr = UpdateCornerNodes(user, FIELD_ID_UCAT); CHKERRQ(ierr);
401 ierr = UpdateCornerNodes(user, FIELD_ID_P); CHKERRQ(ierr);
402 ierr = SynchronizePeriodicCellFields(user, 2, kAnalyticalCellFields); CHKERRQ(ierr);
403 ierr = UpdateLocalGhosts(user, FIELD_ID_UCAT); CHKERRQ(ierr);
404 ierr = UpdateLocalGhosts(user, FIELD_ID_P); CHKERRQ(ierr);
405 }
406
407 PetscFunctionReturn(0);
408}
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 415 of file AnalyticalSolutions.c.

416{
417 PetscErrorCode ierr;
418 UserCtx *user_finest = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
419 const Cmpnts uniform_velocity = simCtx->AnalyticalUniformVelocity;
420 const PetscReal u = uniform_velocity.x;
421 const PetscReal v = uniform_velocity.y;
422 const PetscReal w = uniform_velocity.z;
423
424 PetscFunctionBeginUser;
425
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;
433
434 // --- Step 1: Set Ucont (contravariant flux) via Cart2Contra ---
435 ierr = UniformCart2Contra(user, u, v, w); CHKERRQ(ierr);
436
437 // --- Step 2: Set Ubcs at boundaries (physical Cartesian velocity) ---
438 Cmpnts ***ubcs;
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);
447
448 // --- Step 3: Zero pressure ---
449 ierr = VecZeroEntries(user->P); CHKERRQ(ierr);
450
451 // --- Step 4: Finalize state — derive Ucat from Ucont via metric inversion ---
452 const FieldId staggered_fields[] = {FIELD_ID_UCONT};
453 ierr = SynchronizePeriodicStaggeredFields(user, 1, staggered_fields); CHKERRQ(ierr);
454 ierr = Contra2Cart(user); CHKERRQ(ierr);
455 ierr = UpdateLocalGhosts(user, FIELD_ID_UCAT); CHKERRQ(ierr);
456 ierr = UpdateLocalGhosts(user, FIELD_ID_P); CHKERRQ(ierr);
457 ierr = UpdateDummyCells(user, FIELD_ID_UCAT); CHKERRQ(ierr);
458 ierr = UpdateDummyCells(user, FIELD_ID_P); CHKERRQ(ierr);
459 ierr = SynchronizePeriodicCellFields(user, 2, kAnalyticalCellFields); CHKERRQ(ierr);
460 ierr = UpdateCornerNodes(user, FIELD_ID_UCAT); CHKERRQ(ierr);
461 ierr = UpdateCornerNodes(user, FIELD_ID_P); CHKERRQ(ierr);
462 ierr = SynchronizePeriodicCellFields(user, 2, kAnalyticalCellFields); CHKERRQ(ierr);
463 ierr = UpdateLocalGhosts(user, FIELD_ID_UCAT); CHKERRQ(ierr);
464 ierr = UpdateLocalGhosts(user, FIELD_ID_P); CHKERRQ(ierr);
465 }
466
467 PetscFunctionReturn(0);
468}
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:3504
PetscErrorCode Contra2Cart(UserCtx *user)
Reconstructs Cartesian velocity (Ucat) at cell centers from contravariant velocity (Ucont) defined on...
Definition setup.c:3300
Cmpnts AnalyticalUniformVelocity
Definition variables.h:922
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 475 of file AnalyticalSolutions.c.

476{
477 PetscErrorCode ierr;
478 PetscInt nLocal;
479 PetscReal *data;
480
481 PetscFunctionBeginUser;
482
483 // TGV3D parameters (matching your Eulerian implementation)
484 const PetscReal V0 = 1.0;
485 const PetscReal k = 1.0;
486 const PetscReal nu = (simCtx->ren > 0) ? (1.0 / simCtx->ren) : 0.0;
487 const PetscReal t = simCtx->ti;
488 const PetscReal vel_decay = exp(-2.0 * nu * k * k * t);
489
490 LOG_ALLOW(GLOBAL, LOG_DEBUG, "TGV3D Particles: t=%.4f, V0=%.4f, k=%.4f, nu=%.6f\n", t, V0, k, nu);
491
492 ierr = VecGetLocalSize(tempVec, &nLocal); CHKERRQ(ierr);
493 ierr = VecGetArray(tempVec, &data); CHKERRQ(ierr);
494
495 // Process particles: data is interleaved [x0,y0,z0, x1,y1,z1, ...]
496 for (PetscInt i = 0; i < nLocal; i += 3) {
497 const PetscReal x = data[i];
498 const PetscReal y = data[i+1];
499 const PetscReal z = data[i+2];
500
501 // TGV3D velocity field
502 data[i] = V0 * sin(k*x) * cos(k*y) * cos(k*z) * vel_decay; // u
503 data[i+1] = -V0 * cos(k*x) * sin(k*y) * cos(k*z) * vel_decay; // v
504 data[i+2] = 0.0; // w
505 }
506
507 ierr = VecRestoreArray(tempVec, &data); CHKERRQ(ierr);
508
509 PetscFunctionReturn(0);
510}
@ 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 517 of file AnalyticalSolutions.c.

518{
519 PetscErrorCode ierr;
520 PetscInt nLocal;
521 PetscReal *data;
522 const Cmpnts uniform_velocity = simCtx->AnalyticalUniformVelocity;
523
524 PetscFunctionBeginUser;
525
526 ierr = VecGetLocalSize(tempVec, &nLocal); CHKERRQ(ierr);
527 ierr = VecGetArray(tempVec, &data); CHKERRQ(ierr);
528 for (PetscInt i = 0; i < nLocal; i += 3) {
529 data[i] = uniform_velocity.x;
530 data[i + 1] = uniform_velocity.y;
531 data[i + 2] = uniform_velocity.z;
532 }
533 ierr = VecRestoreArray(tempVec, &data); CHKERRQ(ierr);
534
535 PetscFunctionReturn(0);
536}
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 574 of file AnalyticalSolutions.c.

579{
580 PetscFunctionBeginUser;
581 if (!cfg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "VerificationScalarConfig cannot be NULL.");
582 if (!value) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Scalar output pointer cannot be NULL.");
583
584 if (strcmp(cfg->profile, "CONSTANT") == 0) {
585 *value = cfg->value;
586 } else if (strcmp(cfg->profile, "LINEAR_X") == 0) {
587 *value = cfg->phi0 + cfg->slope_x * x;
588 } else if (strcmp(cfg->profile, "SIN_PRODUCT") == 0) {
589 *value = cfg->amplitude *
590 PetscSinReal(cfg->kx * x) *
591 PetscSinReal(cfg->ky * y) *
592 PetscSinReal(cfg->kz * z);
593 } else {
594 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
595 "Unsupported verification scalar profile '%s'.", cfg->profile);
596 }
597
598 PetscFunctionReturn(0);
599}
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 63 of file AnalyticalSolutions.c.

64{
65 if (!analytical_type) return PETSC_FALSE;
66 return (strcmp(analytical_type, "TGV3D") == 0) ? PETSC_TRUE : PETSC_FALSE;
67}
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 75 of file AnalyticalSolutions.c.

76{
77 if (!analytical_type) return PETSC_FALSE;
78 if (strcmp(analytical_type, "ZERO_FLOW") == 0 || strcmp(analytical_type, "UNIFORM_FLOW") == 0) return PETSC_FALSE;
79 return PETSC_TRUE;
80}
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 88 of file AnalyticalSolutions.c.

89{
90 SimCtx *simCtx = user->simCtx;
91 PetscInt nblk = simCtx->block_number;
92 PetscInt block_index = user->_this;
93
94 PetscFunctionBeginUser;
96
98 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
99 "SetAnalyticalGridInfo called for analytical type '%s' that does not require custom geometry.",
100 simCtx->AnalyticalSolutionType);
101 }
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.");
105 }
106
107 if (strcmp(simCtx->AnalyticalSolutionType, "TGV3D") == 0) {
108 LOG_ALLOW_SYNC(GLOBAL, LOG_DEBUG, "Rank %d: Configuring grid for TGV3D analytical solution, block %d.\n", simCtx->rank, block_index);
109
110 if (nblk == 1) {
111 // --- Single Block Case ---
112 if (block_index == 0) {
113 LOG_ALLOW(GLOBAL, LOG_INFO, "Single block detected. Setting domain to [0, 2*PI].\n");
114 }
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; //2.0 * PETSC_PI;
118
119 } else { // --- Multi-Block Case ---
120 PetscReal s = sqrt((PetscReal)nblk);
121
122 // Validate that nblk is a perfect square.
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);
128 }
129 PetscInt blocks_per_dim = (PetscInt)s;
130
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);
133 }
134
135 // Determine the (row, col) position of this block in the 2D decomposition
136 PetscInt row = block_index / blocks_per_dim;
137 PetscInt col = block_index % blocks_per_dim;
138
139 // Calculate the width/height of each sub-domain
140 PetscReal block_width = (2.0 * PETSC_PI) / (PetscReal)blocks_per_dim;
141 PetscReal block_height = (2.0 * PETSC_PI) / (PetscReal)blocks_per_dim;
142
143 // Assign this block its specific sub-domain
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;
148 user->Min_Z = 0.0;
149 user->Max_Z = 2.0 * PETSC_PI; // Z-domain is not decomposed
150 }
151 }
152 /*
153 * --- EXTENSIBILITY HOOK ---
154 * To add another analytical case with special grid requirements:
155 *
156 * else if (strcmp(simCtx->AnalyticalSolutionType, "ChannelFlow") == 0) {
157 * // ... implement logic to set domain for ChannelFlow case ...
158 * }
159 */
160 else {
161 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_UNKNOWN_TYPE,
162 "Analytical type '%s' has no custom geometry implementation.",
163 simCtx->AnalyticalSolutionType);
164 }
165
166 // We can also read stretching ratios, as they are independent of the domain size
167 // For simplicity, we assume uniform grid unless specified.
168 user->rx = 1.0; user->ry = 1.0; user->rz = 1.0;
169
170 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Block %d grid resolution set: IM=%d, JM=%d, KM=%d\n",
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",
173 simCtx->rank, block_index, user->Min_X, user->Max_X, user->Min_Y, user->Max_Y, user->Min_Z, user->Max_Z);
174
176 PetscFunctionReturn(0);
177}
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:894
@ 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:885
PetscMPIInt rank
Definition variables.h:862
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:1077
PetscReal Min_X
Definition variables.h:1089
PetscInt KM
Definition variables.h:1088
PetscInt _this
Definition variables.h:1092
PetscReal ry
Definition variables.h:1093
PetscReal Max_Y
Definition variables.h:1089
PetscReal rz
Definition variables.h:1093
PetscInt JM
Definition variables.h:1088
PetscReal Min_Z
Definition variables.h:1089
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
Definition variables.h:893
PetscReal Max_X
Definition variables.h:1089
PetscReal Min_Y
Definition variables.h:1089
PetscInt IM
Definition variables.h:1088
PetscReal rx
Definition variables.h:1093
PetscReal Max_Z
Definition variables.h:1089
The master context for the entire simulation.
Definition variables.h:859
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 192 of file AnalyticalSolutions.c.

193{
194 PetscErrorCode ierr;
195 PetscFunctionBeginUser;
197
198 // -- Before any operation, here is defensive test to ensure that the Corner->Center Interpolation method works
199 //ierr = TestCornerToCenterInterpolation(&(simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1]->user[0]));
200
201 // --- Dispatch based on the string provided by the user ---
202 if (strcmp(simCtx->AnalyticalSolutionType, "TGV3D") == 0) {
203 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Applying Analytical Solution: 3D Taylor-Green Vortex (TGV3D).\n");
204 ierr = SetAnalyticalSolution_TGV3D(simCtx); CHKERRQ(ierr);
205 }
206 else if (strcmp(simCtx->AnalyticalSolutionType, "ZERO_FLOW") == 0) {
207 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Applying Analytical Solution: Zero Background Flow (ZERO_FLOW).\n");
208 ierr = SetAnalyticalSolution_ZeroFlow(simCtx); CHKERRQ(ierr);
209 }
210 else if (strcmp(simCtx->AnalyticalSolutionType, "UNIFORM_FLOW") == 0) {
211 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Applying Analytical Solution: Uniform Background Flow (UNIFORM_FLOW).\n");
212 ierr = SetAnalyticalSolution_UniformFlow(simCtx); CHKERRQ(ierr);
213 }
214 /*
215 * --- EXTENSIBILITY HOOK ---
216 * To add a new analytical solution (e.g., "ChannelFlow"):
217 * 1. Add an `else if` block here:
218 *
219 * else if (strcmp(simCtx->AnalyticalSolutionType, "ChannelFlow") == 0) {
220 * LOG_ALLOW(GLOBAL, LOG_DEBUG, "Applying Analytical Solution: Channel Flow.\n");
221 * ierr = SetAnalyticalSolution_ChannelFlow(simCtx); CHKERRQ(ierr);
222 * }
223 *
224 * 2. Implement the static function `SetAnalyticalSolution_ChannelFlow(SimCtx *simCtx)`
225 * below, following the TGV3D pattern.
226 */
227 else {
228 // If the type is unknown, raise a fatal error to prevent silent failures.
229 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown AnalyticalSolutionType specified: '%s'", simCtx->AnalyticalSolutionType);
230 }
231
233 PetscFunctionReturn(0);
234}
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 546 of file AnalyticalSolutions.c.

547{
548 PetscErrorCode ierr;
549 const char *analytical_type = simCtx->AnalyticalSolutionType[0] ? simCtx->AnalyticalSolutionType : "default";
550
551 PetscFunctionBeginUser;
552
553 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Type: %s\n", analytical_type);
554
555 // Check for specific analytical solution types
556 if (strcmp(simCtx->AnalyticalSolutionType, "TGV3D") == 0) {
557 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Using TGV3D solution.\n");
558 ierr = SetAnalyticalSolutionForParticles_TGV3D(tempVec, simCtx); CHKERRQ(ierr);
559 return 0;
560 }
561 if (strcmp(simCtx->AnalyticalSolutionType, "UNIFORM_FLOW") == 0) {
562 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Using UNIFORM_FLOW solution.\n");
563 ierr = SetAnalyticalSolutionForParticles_UniformFlow(tempVec, simCtx); CHKERRQ(ierr);
564 return 0;
565 }
566
567 PetscFunctionReturn(0);
568}
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 609 of file AnalyticalSolutions.c.

615{
616 PetscFunctionBeginUser;
617 (void)t;
618 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "SimCtx cannot be NULL.");
619 if (!simCtx->verificationScalar.enabled) {
620 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
621 "EvaluateAnalyticalScalarProfile requires verification scalar mode to be enabled.");
622 }
623 PetscCall(EvaluateConfiguredScalarProfile(&simCtx->verificationScalar, x, y, z, value));
624 PetscFunctionReturn(0);
625}
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:940
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 635 of file AnalyticalSolutions.c.

636{
637 PetscErrorCode ierr;
638 PetscInt nlocal = 0;
639 PetscReal *positions = NULL;
640 PetscReal *scalar_values = NULL;
641 const ParticleFieldDescriptor *descriptor = NULL;
642 const char *swarm_field_name = NULL;
643
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.");
647
648 ierr = ParticleFieldGetDescriptor(particle_field_id, &descriptor); CHKERRQ(ierr);
649 PetscCheck(descriptor->components == 1 && descriptor->data_type == PETSC_REAL,
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.",
652 descriptor->canonical_name, descriptor->components, PetscDataTypes[descriptor->data_type]);
653 swarm_field_name = descriptor->canonical_name;
654
655 ierr = DMSwarmGetLocalSize(user->swarm, &nlocal); CHKERRQ(ierr);
656 if (nlocal == 0) PetscFunctionReturn(0);
657
658 ierr = DMSwarmGetField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_POSITION), NULL, NULL, (void **)&positions); CHKERRQ(ierr);
659 ierr = DMSwarmGetField(user->swarm, swarm_field_name, NULL, NULL, (void **)&scalar_values); CHKERRQ(ierr);
660
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],
667 user->simCtx->ti,
668 &value); CHKERRQ(ierr);
669 scalar_values[p] = value;
670 }
671
672 ierr = DMSwarmRestoreField(user->swarm, swarm_field_name, NULL, NULL, (void **)&scalar_values); CHKERRQ(ierr);
673 ierr = DMSwarmRestoreField(user->swarm, ParticleFieldName(PARTICLE_FIELD_ID_POSITION), NULL, NULL, (void **)&positions); CHKERRQ(ierr);
674 PetscFunctionReturn(0);
675}
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 685 of file AnalyticalSolutions.c.

686{
687 PetscErrorCode ierr;
688 PetscReal ***target = NULL;
689 const Cmpnts ***cent = NULL;
690 DMDALocalInfo info;
691 PetscInt xs, xe, ys, ye, zs, ze, mx, my, mz;
692 PetscInt lxs, lxe, lys, lye, lzs, lze;
693
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.");
697
698 info = user->info;
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;
706
707 ierr = VecSet(targetVec, 0.0); CHKERRQ(ierr);
708 ierr = DMDAVecGetArray(user->da, targetVec, &target); CHKERRQ(ierr);
709 ierr = DMDAVecGetArrayRead(user->fda, user->Cent, &cent); CHKERRQ(ierr);
710
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;
716 cent[k][j][i].x,
717 cent[k][j][i].y,
718 cent[k][j][i].z,
719 user->simCtx->ti,
720 &value); CHKERRQ(ierr);
721 target[k][j][i] = value;
722 }
723 }
724 }
725
726 ierr = DMDAVecRestoreArrayRead(user->fda, user->Cent, &cent); CHKERRQ(ierr);
727 ierr = DMDAVecRestoreArray(user->da, targetVec, &target); CHKERRQ(ierr);
728 PetscFunctionReturn(0);
729}
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ kAnalyticalCellFields

const FieldId kAnalyticalCellFields[] = {FIELD_ID_UCAT, FIELD_ID_P}
static

Cell-centred fields every analytical setter finalizes, in the order the post-projection finalization uses for the solved flow.

Definition at line 43 of file AnalyticalSolutions.c.