PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
AnalyticalSolutions.c
Go to the documentation of this file.
1/**
2 * @file AnalyticalSolutions.c
3 * @brief Implements the analytical solution engine for initializing or driving the simulation.
4 *
5 * @details This file provides a modular and extensible framework for applying analytical solutions
6 * to the Eulerian fields. The primary entry point is `AnalyticalSolutionEngine`, which acts
7 * as a dispatcher based on user configuration.
8 *
9 * --- DESIGN PHILOSOPHY ---
10 * 1. **Non-Dimensional Core:** All calculations within this engine are performed in
11 * **non-dimensional units** (e.g., reference velocity U_ref=1.0, reference length L_ref=1.0).
12 * This is critical for consistency with the core numerical solver, which also operates on
13 * non-dimensional equations. The `simCtx->scaling` parameters are intentionally NOT used here;
14 * they are reserved for dimensionalization during I/O and post-processing only.
15 *
16 * 2. **Separation of Concerns:** The role of this engine is to set the **physical state** of the
17 * fluid at a given time `t`. This involves:
18 * - For most types (TGV3D, ZERO_FLOW): setting `Ucat` and `P` directly.
19 * - For curvilinear-aware types (UNIFORM_FLOW): setting `Ucont` via metric
20 * dot products and deriving `Ucat` through `Contra2Cart`.
21 * - Declaring the physical values on the boundaries by populating the boundary condition
22 * vector (`user->Bcs.Ubcs`).
23 * It does NOT fill dummy cells itself. After setting the physical state, every setter
24 * runs the same sequence the solved flow is finalized with (see
25 * `FinalizePostProjectionCellFields`): `UpdateDummyCells` on non-periodic faces,
26 * `SynchronizePeriodicCellFields` on periodic ones, `UpdateCornerNodes` for edges and
27 * corners, and the periodic synchronization again because corner averaging can overwrite
28 * periodic endpoints. The boundary values are this module's own `Ubcs`, which is why the
29 * setters do not call that finalizer: it would refresh `Ubcs` from the boundary handlers.
30 *
31 * 3. **Extensibility:** The dispatcher design makes it straightforward to add new analytical
32 * solutions. A developer only needs to add a new `else if` condition and a corresponding
33 * `static` implementation function, without modifying any other part of the solver.
34 */
35
36#include "AnalyticalSolutions.h" // The header that declares this file's functions
37#include <petscmath.h> // Provides PETSc-compatible math functions like sin, cos, exp
38
39// Forward-declare the private function for the TGV3D case.
40// This function is not visible outside this file, enforcing modularity.
41/** @brief Cell-centred fields every analytical setter finalizes, in the order the
42 * post-projection finalization uses for the solved flow. */
44
45static PetscErrorCode SetAnalyticalSolution_TGV3D(SimCtx *simCtx);
46static PetscErrorCode SetAnalyticalSolution_ZeroFlow(SimCtx *simCtx);
47static PetscErrorCode SetAnalyticalSolution_UniformFlow(SimCtx *simCtx);
48static PetscErrorCode SetAnalyticalSolutionForParticles_TGV3D(Vec tempVec, SimCtx *simCtx);
49static PetscErrorCode SetAnalyticalSolutionForParticles_UniformFlow(Vec tempVec, SimCtx *simCtx);
50static PetscErrorCode EvaluateConfiguredScalarProfile(const VerificationScalarConfig *cfg,
51 PetscReal x,
52 PetscReal y,
53 PetscReal z,
54 PetscReal *value);
55
56/**
57 * @brief Implementation of \ref AnalyticalTypeRequiresCustomGeometry().
58 * @details Full API contract (arguments, ownership, side effects) is documented with
59 * the header declaration in `include/AnalyticalSolutions.h`.
60 * @see AnalyticalTypeRequiresCustomGeometry()
61 */
62
63PetscBool AnalyticalTypeRequiresCustomGeometry(const char *analytical_type)
64{
65 if (!analytical_type) return PETSC_FALSE;
66 return (strcmp(analytical_type, "TGV3D") == 0) ? PETSC_TRUE : PETSC_FALSE;
67}
68
69/**
70 * @brief Implementation of \ref AnalyticalTypeSupportsInterpolationError().
71 * @details Full API contract (arguments, ownership, side effects) is documented with
72 * the header declaration in `include/AnalyticalSolutions.h`.
73 * @see AnalyticalTypeSupportsInterpolationError()
74 */
75PetscBool AnalyticalTypeSupportsInterpolationError(const char *analytical_type)
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}
81
82#undef __FUNCT__
83#define __FUNCT__ "SetAnalyticalGridInfo"
84/**
85 * @brief Internal helper implementation: `SetAnalyticalGridInfo()`.
86 * @details Local to this translation unit.
87 */
88PetscErrorCode SetAnalyticalGridInfo(UserCtx *user)
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}
178
179
180/*================================================================================*
181 * PUBLIC ANALYTICAL SOLUTION ENGINE *
182 *================================================================================*/
183
184#undef __FUNCT__
185#define __FUNCT__ "AnalyticalSolutionEngine"
186/**
187 * @brief Implementation of \ref AnalyticalSolutionEngine().
188 * @details Full API contract (arguments, ownership, side effects) is documented with
189 * the header declaration in `include/AnalyticalSolutions.h`.
190 * @see AnalyticalSolutionEngine()
191 */
192PetscErrorCode AnalyticalSolutionEngine(SimCtx *simCtx)
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}
235
236
237/*================================================================================*
238 * PRIVATE IMPLEMENTATIONS *
239 *================================================================================*/
240
241#undef __FUNCT__
242#define __FUNCT__ "SetAnalyticalSolution_TGV3D"
243/**
244 * @brief Populate the Eulerian field vectors with the Taylor--Green vortex at the current time.
245 */
246static PetscErrorCode SetAnalyticalSolution_TGV3D(SimCtx *simCtx)
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}
374
375#undef __FUNCT__
376#define __FUNCT__ "SetAnalyticalSolution_ZeroFlow"
377/**
378 * @brief Set every analytical Eulerian field to the quiescent zero-flow reference state.
379 */
380static PetscErrorCode SetAnalyticalSolution_ZeroFlow(SimCtx *simCtx)
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}
409
410#undef __FUNCT__
411#define __FUNCT__ "SetAnalyticalSolution_UniformFlow"
412/**
413 * @brief Fill the analytical Eulerian fields with the configured spatially uniform flow state.
414 */
415static PetscErrorCode SetAnalyticalSolution_UniformFlow(SimCtx *simCtx)
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}
469
470#undef __FUNCT__
471#define __FUNCT__ "SetAnalyticalSolutionForParticles_TGV3D"
472/**
473 * @brief Evaluate Taylor--Green velocities at swarm particle positions and store them in `tempVec`.
474 */
475static PetscErrorCode SetAnalyticalSolutionForParticles_TGV3D(Vec tempVec, SimCtx *simCtx)
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}
511
512#undef __FUNCT__
513#define __FUNCT__ "SetAnalyticalSolutionForParticles_UniformFlow"
514/**
515 * @brief Fill the particle velocity vector with the configured uniform analytical flow.
516 */
517static PetscErrorCode SetAnalyticalSolutionForParticles_UniformFlow(Vec tempVec, SimCtx *simCtx)
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}
537
538#undef __FUNCT__
539#define __FUNCT__ "SetAnalyticalSolutionForParticles"
540/**
541 * @brief Implementation of \ref SetAnalyticalSolutionForParticles().
542 * @details Full API contract (arguments, ownership, side effects) is documented with
543 * the header declaration in `include/AnalyticalSolutions.h`.
544 * @see SetAnalyticalSolutionForParticles()
545 */
546PetscErrorCode SetAnalyticalSolutionForParticles(Vec tempVec, SimCtx *simCtx)
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}
569
570/**
571 * @brief Internal helper that evaluates the configured scalar verification profile.
572 * @details Local to this translation unit.
573 */
575 PetscReal x,
576 PetscReal y,
577 PetscReal z,
578 PetscReal *value)
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}
600
601#undef __FUNCT__
602#define __FUNCT__ "EvaluateAnalyticalScalarProfile"
603/**
604 * @brief Implementation of \ref EvaluateAnalyticalScalarProfile().
605 * @details Full API contract (arguments, ownership, side effects) is documented with
606 * the header declaration in `include/AnalyticalSolutions.h`.
607 * @see EvaluateAnalyticalScalarProfile()
608 */
609PetscErrorCode EvaluateAnalyticalScalarProfile(const SimCtx *simCtx,
610 PetscReal x,
611 PetscReal y,
612 PetscReal z,
613 PetscReal t,
614 PetscReal *value)
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}
626
627#undef __FUNCT__
628#define __FUNCT__ "SetAnalyticalScalarFieldOnParticles"
629/**
630 * @brief Implementation of \ref SetAnalyticalScalarFieldOnParticles().
631 * @details Full API contract (arguments, ownership, side effects) is documented with
632 * the header declaration in `include/AnalyticalSolutions.h`.
633 * @see SetAnalyticalScalarFieldOnParticles()
634 */
635PetscErrorCode SetAnalyticalScalarFieldOnParticles(UserCtx *user, ParticleFieldId particle_field_id)
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}
676
677#undef __FUNCT__
678#define __FUNCT__ "SetAnalyticalScalarFieldAtCellCenters"
679/**
680 * @brief Implementation of \ref SetAnalyticalScalarFieldAtCellCenters().
681 * @details Full API contract (arguments, ownership, side effects) is documented with
682 * the header declaration in `include/AnalyticalSolutions.h`.
683 * @see SetAnalyticalScalarFieldAtCellCenters()
684 */
685PetscErrorCode SetAnalyticalScalarFieldAtCellCenters(UserCtx *user, Vec targetVec)
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}
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.
PetscErrorCode EvaluateAnalyticalScalarProfile(const SimCtx *simCtx, PetscReal x, PetscReal y, PetscReal z, PetscReal t, PetscReal *value)
Implementation of EvaluateAnalyticalScalarProfile().
PetscErrorCode SetAnalyticalScalarFieldAtCellCenters(UserCtx *user, Vec targetVec)
Implementation of SetAnalyticalScalarFieldAtCellCenters().
PetscErrorCode SetAnalyticalScalarFieldOnParticles(UserCtx *user, ParticleFieldId particle_field_id)
Implementation of SetAnalyticalScalarFieldOnParticles().
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.
PetscErrorCode AnalyticalSolutionEngine(SimCtx *simCtx)
Implementation of AnalyticalSolutionEngine().
PetscBool AnalyticalTypeRequiresCustomGeometry(const char *analytical_type)
Implementation of AnalyticalTypeRequiresCustomGeometry().
PetscBool AnalyticalTypeSupportsInterpolationError(const char *analytical_type)
Implementation of AnalyticalTypeSupportsInterpolationError().
static const FieldId kAnalyticalCellFields[]
Cell-centred fields every analytical setter finalizes, in the order the post-projection finalization ...
PetscErrorCode SetAnalyticalSolutionForParticles(Vec tempVec, SimCtx *simCtx)
Implementation of SetAnalyticalSolutionForParticles().
static PetscErrorCode SetAnalyticalSolution_TGV3D(SimCtx *simCtx)
Populate the Eulerian field vectors with the Taylor–Green vortex at the current time.
PetscErrorCode SetAnalyticalGridInfo(UserCtx *user)
Internal helper implementation: SetAnalyticalGridInfo().
static PetscErrorCode SetAnalyticalSolutionForParticles_TGV3D(Vec tempVec, SimCtx *simCtx)
Evaluate Taylor–Green velocities at swarm particle positions and store them in tempVec.
PetscErrorCode UpdateDummyCells(UserCtx *user, FieldId field_id)
Fills the dummy cells on the non-periodic faces of one cell-centred field.
PetscErrorCode SynchronizePeriodicStaggeredFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes persistent component-staggered vector fields.
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.
FieldId
Compile-time identity for a catalogued Eulerian field.
@ FIELD_ID_UCAT
@ FIELD_ID_UCONT
@ FIELD_ID_P
#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_TRACE
Very fine-grained tracing information for in-depth debugging.
Definition logging.h:33
@ 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
const char * ParticleFieldName(ParticleFieldId field_id)
Return the canonical PETSc DMSwarm name for an ID.
ParticleFieldId
Compile-time identity for a persistent solver-particle field.
@ 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.
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
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
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
UserMG usermg
Definition variables.h:1015
PetscReal ren
Definition variables.h:906
PetscInt _this
Definition variables.h:1092
PetscReal ry
Definition variables.h:1093
PetscReal Max_Y
Definition variables.h:1089
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
VerificationScalarConfig verificationScalar
Definition variables.h:940
PetscReal rz
Definition variables.h:1093
Cmpnts AnalyticalUniformVelocity
Definition variables.h:922
PetscScalar z
Definition variables.h:122
PetscInt JM
Definition variables.h:1088
Vec lCenty
Definition variables.h:1150
PetscInt mglevels
Definition variables.h:736
PetscReal Min_Z
Definition variables.h:1089
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
Definition variables.h:893
PetscReal Max_X
Definition variables.h:1089
Vec lCentx
Definition variables.h:1150
PetscReal Min_Y
Definition variables.h:1089
DMDALocalInfo info
Definition variables.h:1086
PetscScalar y
Definition variables.h:122
PetscInt IM
Definition variables.h:1088
MGCtx * mgctx
Definition variables.h:739
PetscReal rx
Definition variables.h:1093
Vec lCentz
Definition variables.h:1150
PetscReal ti
Definition variables.h:868
PetscReal Max_Z
Definition variables.h:1089
A 3D point or vector with PetscScalar components.
Definition variables.h:121
The master context for the entire simulation.
Definition variables.h:859
User-defined context containing data specific to a single computational grid level.
Definition variables.h:1074
Verification-only analytical scalar override settings.
Definition variables.h:250