PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Macros | Functions
AnalyticalSolutions.h File Reference
#include <petscpf.h>
#include <petscdmswarm.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <petsctime.h>
#include <petscdmcomposite.h>
#include "variables.h"
#include "ParticleSwarm.h"
#include "walkingsearch.h"
#include "grid.h"
#include "logging.h"
#include "io.h"
#include "setup.h"
#include "interpolation.h"
Include dependency graph for AnalyticalSolutions.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define __FUNCT__   "AnalyticalSolutionEngine"
 

Functions

PetscErrorCode SetAnalyticalGridInfo (UserCtx *user)
 Sets the grid domain and resolution for analytical solution cases.
 
PetscBool AnalyticalTypeRequiresCustomGeometry (const char *analytical_type)
 Reports whether an analytical type requires custom geometry/decomposition logic.
 
PetscBool AnalyticalTypeSupportsInterpolationError (const char *analytical_type)
 Reports whether an analytical type has a non-trivial velocity field for which interpolation error measurement is meaningful.
 
PetscErrorCode AnalyticalSolutionEngine (SimCtx *simCtx)
 Dispatches to the appropriate analytical solution function based on simulation settings.
 
PetscErrorCode SetAnalyticalSolutionForParticles (Vec tempVec, SimCtx *simCtx)
 Applies the analytical solution to particle velocity vector.
 
PetscErrorCode EvaluateAnalyticalScalarProfile (const SimCtx *simCtx, PetscReal x, PetscReal y, PetscReal z, PetscReal t, PetscReal *value)
 Evaluates the configured verification scalar profile at one physical point.
 
PetscErrorCode SetAnalyticalScalarFieldOnParticles (UserCtx *user, ParticleFieldId particle_field_id)
 Writes the configured verification scalar profile onto a particle swarm scalar field.
 
PetscErrorCode SetAnalyticalScalarFieldAtCellCenters (UserCtx *user, Vec targetVec)
 Writes the configured verification scalar profile at physical cell centers into a scalar Vec.
 

Macro Definition Documentation

◆ __FUNCT__

#define __FUNCT__   "AnalyticalSolutionEngine"

Definition at line 73 of file AnalyticalSolutions.h.

Function Documentation

◆ SetAnalyticalGridInfo()

PetscErrorCode SetAnalyticalGridInfo ( UserCtx *  user)

Sets the grid domain and resolution for analytical solution cases.

This function is called when eulerianSource is "analytical". It is responsible for automatically configuring the grid based on the chosen AnalyticalSolutionType.

TGV3D Multi-Block Decomposition
If the analytical solution is "TGV3D", this function automatically decomposes the required [0, 2*PI] physical domain among the available blocks.
  • **Single Block (nblk=1):** The single block is assigned the full [0, 2*PI] domain.
  • **Multiple Blocks (nblk>1):** It requires that the number of blocks be a perfect square (e.g., 4, 9, 16). It then arranges the blocks in a sqrt(nblk) by sqrt(nblk) grid in the X-Y plane, partitioning the [0, 2*PI] domain in X and Y accordingly. The Z domain for all blocks remains [0, 2*PI]. If nblk is not a perfect square, the simulation is aborted with an error.

Grid resolution (IM/JM/KM) is expected to be pre-populated in user before this function is called.

Parameters
userPointer to the UserCtx for a specific block. The function will populate the geometric fields (IM, JM, KM, Min_X, Max_X, etc.) within this struct.
Returns
PetscErrorCode 0 on success, or a PETSc error code on failure.

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 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
#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
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:32
#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
PetscInt block_number
Definition variables.h:952
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:

◆ AnalyticalTypeRequiresCustomGeometry()

PetscBool AnalyticalTypeRequiresCustomGeometry ( const char *  analytical_type)

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

Analytical types returning PETSC_TRUE are expected to route through SetAnalyticalGridInfo. Types returning PETSC_FALSE should use the standard programmatic grid parser fallback.

Parameters
analytical_typeAnalytical solution type string.
Returns
PETSC_TRUE if custom geometry is required, PETSC_FALSE otherwise.

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)

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

Types with identically zero velocity (e.g. ZERO_FLOW) return PETSC_FALSE because the interpolation error is trivially zero and uninformative.

Parameters
analytical_typeAnalytical solution type string.
Returns
PETSC_TRUE if interpolation error is meaningful, PETSC_FALSE otherwise.

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:

◆ AnalyticalSolutionEngine()

PetscErrorCode AnalyticalSolutionEngine ( SimCtx *  simCtx)

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

This function acts as a router. It reads the AnalyticalSolutionType from the simulation context and calls the corresponding private implementation function (e.g., for Taylor-Green Vortex, lid-driven cavity, etc.). This design keeps the main simulation code clean and makes it easy to add new analytical test cases.

Parameters
simCtxThe main simulation context, containing configuration and state.
Returns
PetscErrorCode 0 on success.

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 
)

Applies the analytical solution to particle velocity vector.

Dispatcher function that calls the appropriate analytical solution based on simCtx->AnalyticalSolutionType. Supports multiple solution types.

Parameters
tempVecThe PETSc Vec containing particle positions which will be used to store velocities.
simCtxThe simulation context.
Returns
PetscErrorCode Returns 0 on success.

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 
)

Evaluates the configured verification scalar profile at one physical point.

Parameters
[in]simCtxSimulation context providing the scalar verification profile.
[in]xPhysical x coordinate.
[in]yPhysical y coordinate.
[in]zPhysical z coordinate.
[in]tSimulation time.
[out]valueEvaluated scalar value.
Returns
PetscErrorCode 0 on success.

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 
)

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

Parameters
[in,out]userBlock-local context providing particle positions.
[in]particle_field_idTyped identity of the scalar swarm field to overwrite.
Returns
PetscErrorCode 0 on success.

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.
PetscReal ti
Definition variables.h:868
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetAnalyticalScalarFieldAtCellCenters()

PetscErrorCode SetAnalyticalScalarFieldAtCellCenters ( UserCtx *  user,
Vec  targetVec 
)

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

Parameters
[in]userBlock-local context providing the cell-center coordinates.
[in,out]targetVecScalar Vec on user->da storage to fill with analytical reference values.
Returns
PetscErrorCode 0 on success.

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}
DMDALocalInfo info
Definition variables.h:1086
A 3D point or vector with PetscScalar components.
Definition variables.h:121
Here is the call graph for this function:
Here is the caller graph for this function: