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

Go to the source code of this file.

Functions

PetscErrorCode SetInitialInteriorField (UserCtx *user, FieldId field_id)
 Sets the initial values for the INTERIOR of a specified Eulerian field.
 
PetscErrorCode PopulateInitialUcont (UserCtx *user)
 Populate Ucont for one fresh-start block from the configured IC mode.
 
PetscErrorCode InitializeEulerianState (SimCtx *simCtx)
 High-level orchestrator to set the complete initial state of the Eulerian solver.
 

Function Documentation

◆ SetInitialInteriorField()

PetscErrorCode SetInitialInteriorField ( UserCtx *  user,
FieldId  field_id 
)

Sets the initial values for the INTERIOR of a specified Eulerian field.

This function initializes the interior nodes of Ucont based on the mode selected by simCtx->initialConditionMode.

Supported profiles for "Ucont":

  • IC_MODE_ZERO: All interior contravariant components are set to zero.
  • IC_MODE_CONSTANT_CARTESIAN: UniformCart2Contra dots the Cartesian vector (InitialConstantContra.x/y/z) with the local metric vectors to fill all three contravariant components correctly across the entire interior.
  • IC_MODE_CONSTANT_STREAMWISE: Sets only the contravariant component along the streamwise axis (from flowDirection or the identified INLET face) proportional to icVelocityPhysical * |A_n|.
  • IC_MODE_POISEUILLE: Separable parabolic profile in the two cross-stream index directions; centerline speed is icVelocityPhysical; streamwise axis from flowDirection or the identified INLET face.
Parameters
userThe main UserCtx struct, containing all simulation data and configuration.
field_idTyped identity of the field to initialize.
Returns
PetscErrorCode 0 on success.

Sets the initial values for the INTERIOR of a specified Eulerian field.

Local to this translation unit.

Definition at line 14 of file initialcondition.c.

15{
16 PetscErrorCode ierr;
17 const char *fieldName = FieldCanonicalName(field_id);
18 PetscFunctionBeginUser;
19
21
22 SimCtx *simCtx = user->simCtx;
23
24 LOG_ALLOW(GLOBAL, LOG_INFO, "Setting initial INTERIOR field for '%s' with mode %d.\n", fieldName, simCtx->initialConditionMode);
25
26 // This function currently only implements logic for Ucont.
27 if (field_id != FIELD_ID_UCONT) {
28 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Skipping SetInitialInteriorField for non-Ucont field '%s'.\n", fieldName);
29
31
32 PetscFunctionReturn(0);
33 }
34
35 // --- 1. Get DMDA info and grid dimensions ---
36 DMDALocalInfo info;
37 ierr = DMDAGetLocalInfo(user->fda, &info); CHKERRQ(ierr);
38
39 const PetscInt im_phys = info.mx - 1;
40 const PetscInt jm_phys = info.my - 1;
41 const PetscInt km_phys = info.mz - 1;
42
43 const PetscReal u_cart = simCtx->InitialConstantContra.x;
44 const PetscReal v_cart = simCtx->InitialConstantContra.y;
45 const PetscReal w_cart = simCtx->InitialConstantContra.z;
46
47 LOG_ALLOW(GLOBAL, LOG_DEBUG, "IC cartesian=(%.3f,%.3f,%.3f) ic_velocity_physical=%.3f mode=%d\n",
48 (double)u_cart, (double)v_cart, (double)w_cart,
49 (double)simCtx->icVelocityPhysical, (int)simCtx->initialConditionMode);
50
51 // --- 2. Early dispatch: cartesian Constant delegates to the uniform converter ---
53 ierr = UniformCart2Contra(user, u_cart, v_cart, w_cart); CHKERRQ(ierr);
55 PetscFunctionReturn(0);
56 }
57
58 // --- 3. Resolve flow direction for streamwise Constant and Poiseuille ---
59 const PetscBool needs_flow_dir = (PetscBool)(
63 PetscInt flow_axis = 0;
64 PetscReal flow_dir_sign = 1.0;
65
66 if (needs_flow_dir) {
67 if (user->inletFaceDefined)
69 else if (simCtx->flowDirection != FLOW_DIR_UNSET)
70 fd = simCtx->flowDirection;
71 else
72 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER,
73 "Streamwise Constant and Poiseuille IC modes require either an INLET face or -flow_direction.");
74 flow_axis = (PetscInt)fd / 2;
75 flow_dir_sign = ((PetscInt)fd % 2 == 0) ? 1.0 : -1.0;
76 LOG_ALLOW(GLOBAL, LOG_DEBUG, "IC flow_direction=%d (axis=%d sign=%.1f)\n",
77 (int)fd, (int)flow_axis, (double)flow_dir_sign);
78 }
79
80 // --- 4. Open arrays for non-cartesian modes ---
81 Cmpnts ***csi_arr, ***eta_arr, ***zet_arr;
82 ierr = DMDAVecGetArrayRead(user->fda, user->lCsi, &csi_arr); CHKERRQ(ierr);
83 ierr = DMDAVecGetArrayRead(user->fda, user->lEta, &eta_arr); CHKERRQ(ierr);
84 ierr = DMDAVecGetArrayRead(user->fda, user->lZet, &zet_arr); CHKERRQ(ierr);
85
86 Cmpnts ***ucont_arr;
87 ierr = DMDAVecGetArray(user->fda, user->Ucont, &ucont_arr); CHKERRQ(ierr);
88
89 PetscInt i, j, k;
90 const PetscInt xs = info.xs, xe = info.xs + info.xm;
91 const PetscInt ys = info.ys, ye = info.ys + info.ym;
92 const PetscInt zs = info.zs, ze = info.zs + info.zm;
93
94 for (k = zs; k < ze; k++) {
95 for (j = ys; j < ye; j++) {
96 for (i = xs; i < xe; i++) {
97
98 // Check to ensure we only set initial conditions for PHYSICAL cells, not ghost cells.
99 // Ghost cells (at indices 0 and n) will be set later by ApplyBoundaryConditions.
100 //
101 // Grid structure: For n physical grid points, DMDA has size n+1
102 // - im_phys = mx - 1 = n (number of coordinate points, also equals number of cells + 1)
103 // - Physical cell indices: [1, im_phys-1] = [1, n-1] (gives n-1 physical cells)
104 // - Ghost cells at boundaries: index 0 and index im_phys (= n)
105 //
106 // Example: n=25 physical points → im_phys=25
107 // - Physical cells: indices 1..24 (24 cells)
108 // - Ghost cells: indices 0 and 25
109 const PetscBool is_interior = (i > 0 && i < im_phys &&
110 j > 0 && j < jm_phys &&
111 k > 0 && k < km_phys);
112
113 if (is_interior) {
114 Cmpnts ucont_val = {0.0, 0.0, 0.0}; // Default to zero velocity
115 PetscReal normal_velocity_mag = 0.0;
116
117 switch (simCtx->initialConditionMode) {
118 case IC_MODE_ZERO:
119 break;
121 normal_velocity_mag = simCtx->icVelocityPhysical;
122 break;
124 {
125 PetscInt cs1, cs2, n1, n2;
126 PetscBool per1, per2;
127 if (flow_axis == 0) { cs1 = j; cs2 = k; n1 = jm_phys; n2 = km_phys;
128 per1 = (PetscBool)(simCtx->j_periodic != 0); per2 = (PetscBool)(simCtx->k_periodic != 0); }
129 else if (flow_axis == 1) { cs1 = i; cs2 = k; n1 = im_phys; n2 = km_phys;
130 per1 = (PetscBool)(simCtx->i_periodic != 0); per2 = (PetscBool)(simCtx->k_periodic != 0); }
131 else { cs1 = i; cs2 = j; n1 = im_phys; n2 = jm_phys;
132 per1 = (PetscBool)(simCtx->i_periodic != 0); per2 = (PetscBool)(simCtx->j_periodic != 0); }
133 /* An axis of n nodes has n-1 cells, and cell c is centred at logical
134 position c - 1/2, so the walls sit at 1/2 and n - 1/2 in that measure.
135 The parabola vanishes there, on the walls, not at the first cell
136 centres. A periodic cross-stream axis has no walls to vanish on, so
137 the profile is uniform along it: a streamwise-periodic, spanwise-
138 periodic channel then starts from its exact parabola. */
139 const PetscReal half1 = 0.5 * (PetscReal)(n1 - 1);
140 const PetscReal half2 = 0.5 * (PetscReal)(n2 - 1);
141 const PetscReal n1_norm = ((PetscReal)cs1 - 0.5 - half1) / half1;
142 const PetscReal n2_norm = ((PetscReal)cs2 - 0.5 - half2) / half2;
143 const PetscReal f1 = per1 ? 1.0 : (1.0 - n1_norm * n1_norm);
144 const PetscReal f2 = per2 ? 1.0 : (1.0 - n2_norm * n2_norm);
145 normal_velocity_mag = simCtx->icVelocityPhysical * f1 * f2;
146 if (normal_velocity_mag < 0.0) normal_velocity_mag = 0.0;
147 }
148 break;
149 default:
150 LOG_ALLOW(LOCAL, LOG_WARNING, "Unrecognized initial-condition mode %d. Defaulting to zero.\n", simCtx->initialConditionMode);
151 break;
152 }
153
154 // Step B: apply flow direction and set the single contravariant flux component.
155 if (normal_velocity_mag != 0.0) {
156 const PetscReal signed_vel = normal_velocity_mag * flow_dir_sign * user->GridOrientation;
157 if (flow_axis == 0) {
158 const PetscReal area = sqrt(csi_arr[k][j][i].x * csi_arr[k][j][i].x +
159 csi_arr[k][j][i].y * csi_arr[k][j][i].y +
160 csi_arr[k][j][i].z * csi_arr[k][j][i].z);
161 ucont_val.x = signed_vel * area;
162 } else if (flow_axis == 1) {
163 const PetscReal area = sqrt(eta_arr[k][j][i].x * eta_arr[k][j][i].x +
164 eta_arr[k][j][i].y * eta_arr[k][j][i].y +
165 eta_arr[k][j][i].z * eta_arr[k][j][i].z);
166 ucont_val.y = signed_vel * area;
167 } else {
168 const PetscReal area = sqrt(zet_arr[k][j][i].x * zet_arr[k][j][i].x +
169 zet_arr[k][j][i].y * zet_arr[k][j][i].y +
170 zet_arr[k][j][i].z * zet_arr[k][j][i].z);
171 ucont_val.z = signed_vel * area;
172 }
173 }
174 ucont_arr[k][j][i] = ucont_val;
175 } // end if(is_interior)
176 }
177 }
178 }
179 ierr = DMDAVecRestoreArray(user->fda, user->Ucont, &ucont_arr); CHKERRQ(ierr);
180
181 // --- 5. Restore arrays ---
182 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCsi, &csi_arr); CHKERRQ(ierr);
183 ierr = DMDAVecRestoreArrayRead(user->fda, user->lEta, &eta_arr); CHKERRQ(ierr);
184 ierr = DMDAVecRestoreArrayRead(user->fda, user->lZet, &zet_arr); CHKERRQ(ierr);
185
187
188 PetscFunctionReturn(0);
189}
const char * FieldCanonicalName(FieldId field_id)
Return the canonical printable name for an ID.
@ FIELD_ID_UCONT
#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_WARNING
Non-critical issues that warrant attention.
Definition logging.h:30
@ 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
PetscErrorCode UniformCart2Contra(UserCtx *user, PetscReal u, PetscReal v, PetscReal w)
Populate contravariant fluxes from one uniform Cartesian velocity.
Definition setup.c:3504
PetscReal icVelocityPhysical
Definition variables.h:921
PetscBool inletFaceDefined
Definition variables.h:1100
BCFace identifiedInletBCFace
Definition variables.h:1101
InitialConditionMode initialConditionMode
Definition variables.h:916
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:1077
FlowDirection flowDirection
Definition variables.h:920
PetscInt k_periodic
Definition variables.h:953
Vec Ucont
Definition variables.h:1113
PetscScalar x
Definition variables.h:122
PetscScalar z
Definition variables.h:122
FlowDirection
Primary flow direction for streamwise IC and Poiseuille modes.
Definition variables.h:298
@ FLOW_DIR_UNSET
Definition variables.h:305
@ IC_MODE_CONSTANT_CARTESIAN
Definition variables.h:179
@ IC_MODE_POISEUILLE
Definition variables.h:180
@ IC_MODE_CONSTANT_STREAMWISE
Definition variables.h:181
@ IC_MODE_ZERO
Definition variables.h:178
Cmpnts InitialConstantContra
Definition variables.h:919
PetscInt i_periodic
Definition variables.h:953
PetscInt GridOrientation
Definition variables.h:1092
PetscScalar y
Definition variables.h:122
PetscInt j_periodic
Definition variables.h:953
A 3D point or vector with PetscScalar components.
Definition variables.h:121
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:

◆ PopulateInitialUcont()

PetscErrorCode PopulateInitialUcont ( UserCtx *  user)

Populate Ucont for one fresh-start block from the configured IC mode.

Built-in modes generate Ucont directly. File mode loads either Ucat or Ucont from the staged IC directory and converts Ucat when necessary.

Parameters
[in,out]userBlock context whose velocity field is populated.
Returns
PETSc error code.

Populate Ucont for one fresh-start block from the configured IC mode.

Definition at line 231 of file initialcondition.c.

232{
233 PetscErrorCode ierr;
234 SimCtx *simCtx = user->simCtx;
235
236 PetscFunctionBeginUser;
237 if (simCtx->initialConditionMode == IC_MODE_FILE) {
238 ierr = LoadInitialUcont(user); CHKERRQ(ierr);
239 } else {
240 ierr = SetInitialInteriorField(user, FIELD_ID_UCONT); CHKERRQ(ierr);
241 }
242 PetscFunctionReturn(0);
243}
PetscErrorCode SetInitialInteriorField(UserCtx *user, FieldId field_id)
Internal helper implementation: SetInitialInteriorField().
static PetscErrorCode LoadInitialUcont(UserCtx *user)
Load a staged file IC and return with Ucont populated.
@ IC_MODE_FILE
Definition variables.h:182
Here is the call graph for this function:
Here is the caller graph for this function:

◆ InitializeEulerianState()

PetscErrorCode InitializeEulerianState ( SimCtx *  simCtx)

High-level orchestrator to set the complete initial state of the Eulerian solver.

This function is called once from main() before the time loop begins. It inspects the simulation context to determine whether to perform a fresh start (t=0) or restart from saved files. It then delegates to the appropriate helper function. Finally, it initializes the solver's history vectors (Ucont_o, P_o, etc.) to ensure the first time step has the necessary data.

Parameters
simCtxSimulation context controlling the operation.
Returns
PetscErrorCode 0 on success.

High-level orchestrator to set the complete initial state of the Eulerian solver.

Local to this translation unit.

Definition at line 369 of file initialcondition.c.

370{
371 PetscErrorCode ierr;
372 UserCtx *user_finest = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
373
374 PetscFunctionBeginUser;
375
377
378 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Initializing Eulerian State ---\n");
379
380 if (simCtx->StartStep > 0) {
381 if(strcmp(simCtx->eulerianSource,"analytical")==0){
382 LOG_ALLOW(GLOBAL,LOG_INFO,"Initializing Analytical Solution type: %s (t=%.4f, step=%d).\n",simCtx->AnalyticalSolutionType,simCtx->StartTime,simCtx->StartStep);
383 ierr = AnalyticalSolutionEngine(simCtx);
384 }
385 else{
386 LOG_ALLOW(GLOBAL, LOG_INFO, "Starting from RESTART files (t=%.4f, step=%d).\n",
387 simCtx->StartTime, simCtx->StartStep);
388 ierr = SetInitialFluidState_Load(simCtx); CHKERRQ(ierr);
389 }
390 /* Statistics resume from the same bundle the flow state came from, and are
391 * restored regardless of the Eulerian source: an analytical restart still
392 * continues a window that was accumulating before it. */
393 ierr = RestoreFieldStatisticsState(simCtx, simCtx->StartStep); CHKERRQ(ierr);
394 } else { // StartStep = 0
395 LOG_ALLOW(GLOBAL, LOG_INFO, "Performing a FRESH START (t=0, step=0).\n");
396 if(strcmp(simCtx->eulerianSource,"solve")==0){
397 ierr = SetInitialFluidState_FreshStart(simCtx); CHKERRQ(ierr);
398 }else if(strcmp(simCtx->eulerianSource,"load")==0){
399 LOG_ALLOW(GLOBAL,LOG_INFO,"FRESH START in LOAD mode. Reading files (t=%.4f,step=%d).\n",
400 simCtx->StartTime,simCtx->StartStep);
401 ierr=SetInitialFluidState_Load(simCtx);CHKERRQ(ierr);
402 }else if(strcmp(simCtx->eulerianSource,"analytical")==0){
403 LOG_ALLOW(GLOBAL,LOG_INFO,"FRESH START in ANALYTICAL mode. Initializing Analytical Solution type: %s (t=%.4f,step=%d).\n",
404 simCtx->AnalyticalSolutionType,simCtx->StartTime,simCtx->StartStep);
405 ierr=AnalyticalSolutionEngine(simCtx);CHKERRQ(ierr);
406 }
407 }
408
409 // This crucial step, taken from the end of the legacy setup, ensures
410 // that the history vectors (Ucont_o, Ucont_rm1, etc.) are correctly
411 // populated before the first call to the time-stepping loop.
412 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
413 ierr = UpdateSolverHistoryVectors(&user_finest[bi],
414 (PetscBool)(simCtx->StartStep > 0 && simCtx->restartHistoryAvailable)); CHKERRQ(ierr);
415 }
416
417 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Eulerian State Initialized and History Vectors Populated ---\n");
418
420 PetscFunctionReturn(0);
421}
PetscErrorCode AnalyticalSolutionEngine(SimCtx *simCtx)
Dispatches to the appropriate analytical solution function based on simulation settings.
static PetscErrorCode SetInitialFluidState_Load(SimCtx *simCtx)
Restore Eulerian fields from checkpoint files for a restart simulation.
static PetscErrorCode SetInitialFluidState_FreshStart(SimCtx *simCtx)
Initialize Eulerian fields for a new simulation without restart data.
PetscErrorCode RestoreFieldStatisticsState(SimCtx *simCtx, PetscInt ti)
Restores field-statistics window state and accumulators from a checkpoint.
Definition io.c:1686
PetscErrorCode UpdateSolverHistoryVectors(UserCtx *user, PetscBool preserve_previous_state)
Copies the current time step's solution fields into history vectors (e.g., U(t_n) -> U_o,...
Definition runloop.c:314
UserCtx * user
Definition variables.h:729
PetscInt block_number
Definition variables.h:952
PetscReal StartTime
Definition variables.h:873
UserMG usermg
Definition variables.h:1015
PetscInt StartStep
Definition variables.h:869
char eulerianSource[PETSC_MAX_PATH_LEN]
Definition variables.h:879
PetscInt mglevels
Definition variables.h:736
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
Definition variables.h:893
MGCtx * mgctx
Definition variables.h:739
PetscBool restartHistoryAvailable
Definition variables.h:888
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: