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

// Setup code for running any simulation More...

#include <ctype.h>
#include <errno.h>
#include "setup.h"
Include dependency graph for setup.c:

Go to the source code of this file.

Macros

#define __FUNCT__   "CreateSimulationContext"
 
#define __FUNCT__   "PetscMkdirRecursive"
 
#define __FUNCT__   "SetupSimulationEnvironment"
 
#define __FUNCT__   "AllocateContextHeirarchy"
 
#define __FUNCT__   "SetupSolverParameters"
 
#define __FUNCT__   "SetupGridAndSolvers"
 
#define __FUNCT__   "CreateAndInitializeAllVectors"
 
#define __FUNCT__   "UpdateLocalGhosts"
 
#define __FUNCT__   "SetupBoundaryConditions"
 
#define __FUNCT__   "GetOwnedCellRange"
 
#define __FUNCT__   "ComputeAndStoreNeighborRanks"
 
#define __FUNCT__   "SetDMDAProcLayout"
 
#define __FUNCT__   "SetupDomainRankInfo"
 
#define __FUNCT__   "Contra2Cart"
 
#define __FUNCT__   "SetupDomainCellDecompositionMap"
 
#define __FUNCT__   "BinarySearchInt64"
 
#define __FUNCT__   "ComputeDivergence"
 
#define __FUNCT__   "InitializeRandomGenerators"
 
#define __FUNCT__   "InitializeLogicalSpaceRNGs"
 
#define __FUNCT__   "InitializeBrownianRNG"
 
#define __FUNCT__   "TransformScalarDerivativesToPhysical"
 
#define __FUNCT__   "TransformDerivativesToPhysical"
 
#define __FUNCT__   "ComputeScalarFieldDerivatives"
 
#define __FUNCT__   "ComputeVectorFieldDerivatives"
 
#define __FUNCT__   "DestroyUserVectors"
 
#define __FUNCT__   "DestroyUserContext"
 
#define __FUNCT__   "FinalizeSimulation"
 

Functions

PetscBool RuntimeWalltimeGuardParsePositiveSeconds (const char *text, PetscReal *seconds_out)
 Implementation of RuntimeWalltimeGuardParsePositiveSeconds().
 
PetscErrorCode InitializeSolutionConvergenceState (SimCtx *simCtx)
 Implementation of InitializeSolutionConvergenceState().
 
PetscErrorCode DestroySolutionConvergenceState (SimCtx *simCtx)
 Implementation of DestroySolutionConvergenceState().
 
PetscErrorCode CreateSimulationContext (int argc, char **argv, SimCtx **p_simCtx)
 Implementation of CreateSimulationContext().
 
static PetscErrorCode PetscMkdirRecursive (const char *path)
 Internal helper implementation: PetscMkdirRecursive().
 
PetscErrorCode SetupSimulationEnvironment (SimCtx *simCtx)
 Internal helper implementation: SetupSimulationEnvironment().
 
static PetscErrorCode AllocateContextHierarchy (SimCtx *simCtx)
 Internal helper implementation: AllocateContextHierarchy().
 
static PetscErrorCode SetupSolverParameters (SimCtx *simCtx)
 Internal helper implementation: SetupSolverParameters().
 
PetscErrorCode SetupGridAndSolvers (SimCtx *simCtx)
 Implementation of SetupGridAndSolvers().
 
PetscErrorCode CreateAndInitializeAllVectors (SimCtx *simCtx)
 Internal helper implementation: CreateAndInitializeAllVectors().
 
PetscErrorCode UpdateLocalGhosts (UserCtx *user, const char *fieldName)
 Internal helper implementation: UpdateLocalGhosts().
 
PetscErrorCode SetupBoundaryConditions (SimCtx *simCtx)
 Internal helper implementation: SetupBoundaryConditions().
 
PetscErrorCode Allocate3DArrayScalar (PetscReal ****array, PetscInt nz, PetscInt ny, PetscInt nx)
 Internal helper implementation: Allocate3DArrayScalar().
 
PetscErrorCode Deallocate3DArrayScalar (PetscReal ***array, PetscInt nz, PetscInt ny)
 Internal helper implementation: Deallocate3DArrayScalar().
 
PetscErrorCode Allocate3DArrayVector (Cmpnts ****array, PetscInt nz, PetscInt ny, PetscInt nx)
 Implementation of Allocate3DArrayVector().
 
PetscErrorCode Deallocate3DArrayVector (Cmpnts ***array, PetscInt nz, PetscInt ny)
 Implementation of Deallocate3DArrayVector().
 
PetscErrorCode GetOwnedCellRange (const DMDALocalInfo *info_nodes, PetscInt dim, PetscInt *xs_cell_global_out, PetscInt *xm_cell_local_out)
 Internal helper implementation: GetOwnedCellRange().
 
PetscErrorCode ComputeAndStoreNeighborRanks (UserCtx *user)
 Internal helper implementation: ComputeAndStoreNeighborRanks().
 
PetscErrorCode SetDMDAProcLayout (DM dm, UserCtx *user)
 Internal helper implementation: SetDMDAProcLayout().
 
PetscErrorCode SetupDomainRankInfo (SimCtx *simCtx)
 Implementation of SetupDomainRankInfo().
 
PetscErrorCode Contra2Cart (UserCtx *user)
 Internal helper implementation: Contra2Cart().
 
PetscErrorCode SetupDomainCellDecompositionMap (UserCtx *user)
 Internal helper implementation: SetupDomainCellDecompositionMap().
 
PetscErrorCode BinarySearchInt64 (PetscInt n, const PetscInt64 arr[], PetscInt64 key, PetscBool *found)
 Implementation of BinarySearchInt64().
 
static PetscInt Gidx (PetscInt i, PetscInt j, PetscInt k, UserCtx *user)
 Internal helper implementation: Gidx().
 
PetscErrorCode ComputeDivergence (UserCtx *user)
 Implementation of ComputeDivergence().
 
PetscErrorCode InitializeRandomGenerators (UserCtx *user, PetscRandom *randx, PetscRandom *randy, PetscRandom *randz)
 Implementation of InitializeRandomGenerators().
 
PetscErrorCode InitializeLogicalSpaceRNGs (PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k)
 Internal helper implementation: InitializeLogicalSpaceRNGs().
 
PetscErrorCode InitializeBrownianRNG (SimCtx *simCtx)
 Internal helper implementation: InitializeBrownianRNG().
 
void TransformScalarDerivativesToPhysical (PetscReal jacobian, Cmpnts csi_metrics, Cmpnts eta_metrics, Cmpnts zet_metrics, PetscReal dPhi_dcsi, PetscReal dPhi_deta, PetscReal dPhi_dzet, Cmpnts *gradPhi)
 Implementation of TransformScalarDerivativesToPhysical().
 
static void TransformDerivativesToPhysical (PetscReal jacobian, Cmpnts csi_metrics, Cmpnts eta_metrics, Cmpnts zet_metrics, Cmpnts deriv_csi, Cmpnts deriv_eta, Cmpnts deriv_zet, Cmpnts *dudx, Cmpnts *dvdx, Cmpnts *dwdx)
 Internal helper implementation: TransformDerivativesToPhysical().
 
PetscErrorCode ComputeScalarFieldDerivatives (UserCtx *user, PetscInt i, PetscInt j, PetscInt k, PetscReal ***field_data, Cmpnts *grad)
 Internal helper implementation: ComputeScalarFieldDerivatives().
 
PetscErrorCode ComputeVectorFieldDerivatives (UserCtx *user, PetscInt i, PetscInt j, PetscInt k, Cmpnts ***field_data, Cmpnts *dudx, Cmpnts *dvdx, Cmpnts *dwdx)
 Internal helper implementation: ComputeVectorFieldDerivatives().
 
PetscErrorCode DestroyUserVectors (UserCtx *user)
 Internal helper implementation: DestroyUserVectors().
 
PetscErrorCode DestroyUserContext (UserCtx *user)
 Internal helper implementation: DestroyUserContext().
 
PetscErrorCode FinalizeSimulation (SimCtx *simCtx)
 Implementation of FinalizeSimulation().
 

Detailed Description

// Setup code for running any simulation

Test program for DMSwarm interpolation using the fdf-curvIB method. Provides the setup to start any simulation with DMSwarm and DMDAs.

Definition in file setup.c.

Macro Definition Documentation

◆ __FUNCT__ [1/27]

#define __FUNCT__   "CreateSimulationContext"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [2/27]

#define __FUNCT__   "PetscMkdirRecursive"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [3/27]

#define __FUNCT__   "SetupSimulationEnvironment"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [4/27]

#define __FUNCT__   "AllocateContextHeirarchy"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [5/27]

#define __FUNCT__   "SetupSolverParameters"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [6/27]

#define __FUNCT__   "SetupGridAndSolvers"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [7/27]

#define __FUNCT__   "CreateAndInitializeAllVectors"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [8/27]

#define __FUNCT__   "UpdateLocalGhosts"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [9/27]

#define __FUNCT__   "SetupBoundaryConditions"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [10/27]

#define __FUNCT__   "GetOwnedCellRange"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [11/27]

#define __FUNCT__   "ComputeAndStoreNeighborRanks"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [12/27]

#define __FUNCT__   "SetDMDAProcLayout"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [13/27]

#define __FUNCT__   "SetupDomainRankInfo"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [14/27]

#define __FUNCT__   "Contra2Cart"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [15/27]

#define __FUNCT__   "SetupDomainCellDecompositionMap"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [16/27]

#define __FUNCT__   "BinarySearchInt64"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [17/27]

#define __FUNCT__   "ComputeDivergence"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [18/27]

#define __FUNCT__   "InitializeRandomGenerators"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [19/27]

#define __FUNCT__   "InitializeLogicalSpaceRNGs"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [20/27]

#define __FUNCT__   "InitializeBrownianRNG"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [21/27]

#define __FUNCT__   "TransformScalarDerivativesToPhysical"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [22/27]

#define __FUNCT__   "TransformDerivativesToPhysical"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [23/27]

#define __FUNCT__   "ComputeScalarFieldDerivatives"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [24/27]

#define __FUNCT__   "ComputeVectorFieldDerivatives"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [25/27]

#define __FUNCT__   "DestroyUserVectors"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [26/27]

#define __FUNCT__   "DestroyUserContext"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [27/27]

#define __FUNCT__   "FinalizeSimulation"

Definition at line 143 of file setup.c.

Function Documentation

◆ RuntimeWalltimeGuardParsePositiveSeconds()

PetscBool RuntimeWalltimeGuardParsePositiveSeconds ( const char *  text,
PetscReal *  seconds_out 
)

Implementation of RuntimeWalltimeGuardParsePositiveSeconds().

Parse a positive floating-point seconds value from runtime metadata.

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

See also
RuntimeWalltimeGuardParsePositiveSeconds()

Definition at line 18 of file setup.c.

19{
20 char *endptr = NULL;
21 double parsed_value;
22
23 if (seconds_out) *seconds_out = 0.0;
24 if (!text || text[0] == '\0') return PETSC_FALSE;
25
26 errno = 0;
27 parsed_value = strtod(text, &endptr);
28 if (endptr == text || errno == ERANGE || !isfinite(parsed_value) || parsed_value <= 0.0) {
29 return PETSC_FALSE;
30 }
31
32 while (*endptr != '\0' && isspace((unsigned char)*endptr)) {
33 endptr++;
34 }
35 if (*endptr != '\0') return PETSC_FALSE;
36
37 if (seconds_out) *seconds_out = (PetscReal)parsed_value;
38 return PETSC_TRUE;
39}
Here is the caller graph for this function:

◆ InitializeSolutionConvergenceState()

PetscErrorCode InitializeSolutionConvergenceState ( SimCtx simCtx)

Implementation of InitializeSolutionConvergenceState().

Allocates any runtime storage required by solution-convergence logging.

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

See also
InitializeSolutionConvergenceState()

Definition at line 47 of file setup.c.

48{
49 UserCtx *user = NULL;
50 PetscInt history_capacity = 0;
51
52 PetscFunctionBeginUser;
53 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "SimCtx cannot be NULL.");
54 if (simCtx->exec_mode != EXEC_MODE_SOLVER) PetscFunctionReturn(0);
55 if (!simCtx->usermg.mgctx) {
56 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
57 "Multigrid hierarchy must exist before initializing solution convergence storage.");
58 }
59
60 user = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
61 if (!user) {
62 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
63 "Finest-level UserCtx must exist before initializing solution convergence storage.");
64 }
65
67
69 for (PetscInt bi = 0; bi < simCtx->block_number; ++bi) {
70 PetscCall(PetscCalloc1((size_t)simCtx->solutionConvergencePeriodSteps,
71 &user[bi].solutionConvergencePeriodicUcatRef));
72 PetscCall(PetscCalloc1((size_t)simCtx->solutionConvergencePeriodSteps,
73 &user[bi].solutionConvergencePeriodicPRef));
74 for (PetscInt phase = 0; phase < simCtx->solutionConvergencePeriodSteps; ++phase) {
75 PetscCall(VecDuplicate(user[bi].Ucat, &user[bi].solutionConvergencePeriodicUcatRef[phase]));
76 PetscCall(VecSet(user[bi].solutionConvergencePeriodicUcatRef[phase], 0.0));
77 PetscCall(VecDuplicate(user[bi].P, &user[bi].solutionConvergencePeriodicPRef[phase]));
78 PetscCall(VecSet(user[bi].solutionConvergencePeriodicPRef[phase], 0.0));
79 }
80 }
81 }
82
84 history_capacity = 2 * simCtx->solutionConvergenceWindowSteps;
85 PetscCall(PetscCalloc1((size_t)history_capacity, &simCtx->solutionConvergenceMeanSpeedHistory));
86 PetscCall(PetscCalloc1((size_t)history_capacity, &simCtx->solutionConvergenceMeanKEHistory));
87 }
88
89 PetscFunctionReturn(0);
90}
UserCtx * user
Definition variables.h:536
PetscInt block_number
Definition variables.h:726
PetscReal * solutionConvergenceMeanSpeedHistory
Definition variables.h:711
UserMG usermg
Definition variables.h:778
PetscInt solutionConvergenceSamplesRecorded
Definition variables.h:710
PetscReal * solutionConvergenceMeanKEHistory
Definition variables.h:712
PetscInt solutionConvergencePeriodSteps
Definition variables.h:708
PetscInt mglevels
Definition variables.h:543
PetscInt solutionConvergenceWindowSteps
Definition variables.h:709
@ EXEC_MODE_SOLVER
Definition variables.h:624
MGCtx * mgctx
Definition variables.h:546
@ SOLUTION_CONVERGENCE_PERIODIC_DETERMINISTIC
Definition variables.h:510
@ SOLUTION_CONVERGENCE_STATISTICAL_STEADY
Definition variables.h:511
SolutionConvergenceMode solutionConvergenceMode
Definition variables.h:707
ExecutionMode exec_mode
Definition variables.h:670
User-defined context containing data specific to a single computational grid level.
Definition variables.h:830
Here is the caller graph for this function:

◆ DestroySolutionConvergenceState()

PetscErrorCode DestroySolutionConvergenceState ( SimCtx simCtx)

Implementation of DestroySolutionConvergenceState().

Frees any runtime storage allocated for solution-convergence logging.

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

See also
DestroySolutionConvergenceState()

Definition at line 98 of file setup.c.

99{
100 UserCtx *user = NULL;
101
102 PetscFunctionBeginUser;
103 if (!simCtx || !simCtx->usermg.mgctx) PetscFunctionReturn(0);
104
105 user = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
106 if (user) {
107 for (PetscInt bi = 0; bi < simCtx->block_number; ++bi) {
108 if (user[bi].solutionConvergencePeriodicUcatRef) {
109 for (PetscInt phase = 0; phase < simCtx->solutionConvergencePeriodSteps; ++phase) {
110 if (user[bi].solutionConvergencePeriodicUcatRef[phase]) {
111 PetscCall(VecDestroy(&user[bi].solutionConvergencePeriodicUcatRef[phase]));
112 }
113 }
114 PetscCall(PetscFree(user[bi].solutionConvergencePeriodicUcatRef));
116 }
117 if (user[bi].solutionConvergencePeriodicPRef) {
118 for (PetscInt phase = 0; phase < simCtx->solutionConvergencePeriodSteps; ++phase) {
119 if (user[bi].solutionConvergencePeriodicPRef[phase]) {
120 PetscCall(VecDestroy(&user[bi].solutionConvergencePeriodicPRef[phase]));
121 }
122 }
123 PetscCall(PetscFree(user[bi].solutionConvergencePeriodicPRef));
124 user[bi].solutionConvergencePeriodicPRef = NULL;
125 }
126 }
127 }
128
130 PetscCall(PetscFree(simCtx->solutionConvergenceMeanSpeedHistory));
132 }
134 PetscCall(PetscFree(simCtx->solutionConvergenceMeanKEHistory));
136 }
138
139 PetscFunctionReturn(0);
140}
Vec * solutionConvergencePeriodicPRef
Definition variables.h:866
Vec * solutionConvergencePeriodicUcatRef
Definition variables.h:865
Here is the caller graph for this function:

◆ CreateSimulationContext()

PetscErrorCode CreateSimulationContext ( int  argc,
char **  argv,
SimCtx **  p_simCtx 
)

Implementation of CreateSimulationContext().

Allocates and populates the master SimulationContext object.

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

See also
CreateSimulationContext()

Definition at line 151 of file setup.c.

152{
153 PetscErrorCode ierr;
154 (void)argc;
155 (void)argv;
156 SimCtx *simCtx;
157 char control_filename[PETSC_MAX_PATH_LEN] = ""; // Temporary placeholder for control file name.
158 PetscBool control_flg; // Temporary placeholder for control file tag existence check flag.
159 PetscBool particle_console_output_freq_flg = PETSC_FALSE;
160
161 PetscFunctionBeginUser;
162
164
165 // === 1. Allocate the Context Struct and Set ALL Defaults ==================
166 ierr = PetscNew(p_simCtx); CHKERRQ(ierr);
167 simCtx = *p_simCtx;
168
169 // --- Group 1: Parallelism & MPI ---
170 simCtx->rank = 0; simCtx->size = 1;
171
172 // --- Group 2: Simulation Control, Time, and I/O ---
173 simCtx->step = 0; simCtx->ti = 0.0; simCtx->StartStep = 0; simCtx->StepsToRun = 10;
174 simCtx->tiout = 10; simCtx->particleConsoleOutputFreq = simCtx->tiout;
175 simCtx->StartTime = 0.0; simCtx->dt = 0.001;
176 simCtx->OnlySetup = PETSC_FALSE;
177 simCtx->continueMode = PETSC_FALSE;
178 simCtx->logviewer = NULL;
179 strcpy(simCtx->eulerianSource,"solve");
180 strcpy(simCtx->restart_dir,"restart");
181 strcpy(simCtx->output_dir,"output");
182 strcpy(simCtx->log_dir,"logs");
183 strcpy(simCtx->euler_subdir,"eulerian");
184 strcpy(simCtx->particle_subdir,"particles");
185 simCtx->_io_context_buffer[0] = '\0';
186 simCtx->current_io_directory = NULL;
187
188 // --- Group 3: High-Level Physics & Model Selection Flags ---
189 simCtx->immersed = 0; simCtx->movefsi = 0; simCtx->rotatefsi = 0;
190 simCtx->sediment = 0; simCtx->rheology = 0; simCtx->invicid = 0;
191 simCtx->TwoD = 0; simCtx->thin = 0; simCtx->moveframe = 0;
192 simCtx->rotateframe = 0; simCtx->blank = 0;
193 simCtx->dgf_x = 0; simCtx->dgf_y = 1; simCtx->dgf_z = 0;
194 simCtx->dgf_ax = 1; simCtx->dgf_ay = 0; simCtx->dgf_az = 0;
195 strcpy(simCtx->AnalyticalSolutionType,"TGV3D");
196
197 // --- Group 4: Specific Simulation Case Flags --- (DEPRICATED)
198 simCtx->cop=0; simCtx->fish=0; simCtx->fish_c=0; simCtx->fishcyl=0;
199 simCtx->eel=0; simCtx->pizza=0; simCtx->turbine=0; simCtx->Pipe=0;
200 simCtx->wing=0; simCtx->hydro=0; simCtx->MHV=0; simCtx->LV=0;
201 simCtx->channelz = 0;
202
203 // --- Group 5: Solver & Numerics Parameters ---
205 simCtx->mom_dt_rk4_residual_norm_noise_allowance_factor = 1.05; // New addition for divergence detection
206 simCtx->mom_atol = 1e-7; simCtx->mom_rtol = 1e-4; simCtx->imp_stol = 1.e-8;
207 simCtx->mglevels = 3; simCtx->mg_MAX_IT = 30; simCtx->mg_idx = 1;
208 simCtx->mg_preItr = 1; simCtx->mg_poItr = 1;
209 simCtx->poisson = 0; simCtx->poisson_tol = 5.e-9;
210 simCtx->STRONG_COUPLING = 0;simCtx->central=0;
211 simCtx->ren = 100.0; simCtx->pseudo_cfl = 0.1;
212 simCtx->max_pseudo_cfl = 1.0; simCtx->min_pseudo_cfl = 0.001;
213 simCtx->pseudo_cfl_reduction_factor = 1.0;
214 simCtx->pseudo_cfl_growth_factor = 1.0; //simCtx->vnn = 0.1;
215 simCtx->ps_ksp_pic_monitor_true_residual = PETSC_FALSE;
216 simCtx->cdisx = 0.0; simCtx->cdisy = 0.0; simCtx->cdisz = 0.0;
217 simCtx->FieldInitialization = 0;
218 simCtx->InitialConstantContra.x = 0.0;
219 simCtx->InitialConstantContra.y = 0.0;
220 simCtx->InitialConstantContra.z = 0.0;
221 simCtx->AnalyticalUniformVelocity.x = 0.0;
222 simCtx->AnalyticalUniformVelocity.y = 0.0;
223 simCtx->AnalyticalUniformVelocity.z = 0.0;
230 simCtx->verificationDiffusivity.enabled = PETSC_FALSE;
231 strcpy(simCtx->verificationDiffusivity.mode, "");
232 strcpy(simCtx->verificationDiffusivity.profile, "");
233 simCtx->verificationDiffusivity.gamma0 = 0.0;
234 simCtx->verificationDiffusivity.slope_x = 0.0;
235
236 // --- Group 6: Physical & Geometric Parameters ---
237 simCtx->NumberOfBodies = 1; simCtx->Flux_in = 1.0; simCtx->angle = 0.0;
238 simCtx->max_angle = -54. * 3.1415926 / 180.;
239 simCtx->CMx_c=0.0; simCtx->CMy_c=0.0; simCtx->CMz_c=0.0;
240 simCtx->wall_roughness_height = 1e-16;
241 simCtx->schmidt_number = 1.0; simCtx->Turbulent_schmidt_number = 0.7;
242
243 // --- Group 7: Grid, Domain, and Boundary Condition Settings ---
244 simCtx->block_number = 1; simCtx->inletprofile = 1;
245 simCtx->grid1d = 0; simCtx->Ogrid = 0;
246 simCtx->i_periodic = 0; simCtx->j_periodic = 0; simCtx->k_periodic = 0;
247 simCtx->blkpbc = 10; simCtx->pseudo_periodic = 0;
248 strcpy(simCtx->grid_file, "config/grid.run");
249 simCtx->generate_grid = PETSC_FALSE;
250 simCtx->da_procs_x = PETSC_DECIDE;
251 simCtx->da_procs_y = PETSC_DECIDE;
252 simCtx->da_procs_z = PETSC_DECIDE;
253 simCtx->grid_rotation_angle = 0.0;
254 simCtx->Croty = 0.0; simCtx->Crotz = 0.0;
255 simCtx->num_bcs_files = 1;
256 ierr = PetscMalloc1(1, &simCtx->bcs_files); CHKERRQ(ierr);
257 ierr = PetscStrallocpy("config/bcs.run", &simCtx->bcs_files[0]); CHKERRQ(ierr);
258 simCtx->FluxInSum = 0.0; simCtx->FluxOutSum = 0.0; simCtx->Fluxsum = 0.0;
259 simCtx->drivingForceMagnitude = 0.0, simCtx->forceScalingFactor = 1.8;
260 simCtx->targetVolumetricFlux = 0.0;
261 simCtx->AreaInSum = 0.0; simCtx->AreaOutSum = 0.0;
262 simCtx->U_bc = 0.0; simCtx->ccc = 0;
263 simCtx->ratio = 0.0;
264
265
266 // --- Group 8: Turbulence Modeling (LES/RANS) ---
267 simCtx->averaging = PETSC_FALSE; simCtx->les = NO_LES_MODEL; simCtx->rans = 0;
268 simCtx->wallfunction = 0; simCtx->mixed = 0; simCtx->clark = 0;
269 simCtx->dynamic_freq = 1; simCtx->max_cs = 0.5;
270 simCtx->Const_CS = 0.03;
271 simCtx->testfilter_ik = 0; simCtx->testfilter_1d = 0;
272 simCtx->i_homo_filter = 0; simCtx->j_homo_filter = 0; simCtx->k_homo_filter = 0;
273
274 // --- Group 9: Particle / DMSwarm Data & Settings ---
275 simCtx->np = 0; simCtx->readFields = PETSC_FALSE;
276 simCtx->dm_swarm = NULL; simCtx->bboxlist = NULL;
279 strcpy(simCtx->particleRestartMode,"load");
280 simCtx->particlesLostLastStep = 0;
281 simCtx->particlesLostCumulative = 0;
282 simCtx->particlesMigratedLastStep = 0;
283 simCtx->occupiedCellCount = 0;
284 simCtx->particleLoadImbalance = 0.0;
285 simCtx->migrationPassesLastStep = 0;
286 simCtx->searchMetrics.searchAttempts = 0;
289 simCtx->searchMetrics.searchLostCount = 0;
291 simCtx->searchMetrics.reSearchCount = 0;
294 simCtx->searchMetrics.tieBreakCount = 0;
300 simCtx->BrownianMotionRNG = NULL;
301 simCtx->C_IEM = 2.0;
302
303 // --- Group 10: Immersed Boundary & FSI Data Object Pointers ---
304 simCtx->ibm = NULL; simCtx->ibmv = NULL; simCtx->fsi = NULL;
305 simCtx->rstart_fsi = PETSC_FALSE; simCtx->duplicate = 0;
306
307 // --- Group 11: Logging and Custom Configuration ---
308 strcpy(simCtx->allowedFile, "config/whitelist.run");
309 simCtx->useCfg = PETSC_FALSE;
310 simCtx->allowedFuncs = NULL;
311 simCtx->nAllowed = 0;
312 simCtx->LoggingFrequency = 10;
313 simCtx->summationRHS = 0.0;
314 simCtx->MaxDiv = 0.0;
315 simCtx->MaxDivFlatArg = 0; simCtx->MaxDivx = 0; simCtx->MaxDivy = 0; simCtx->MaxDivz = 0;
316 strcpy(simCtx->profilingSelectedFuncsFile, "config/profile.run");
317 simCtx->useProfilingSelectedFuncsCfg = PETSC_FALSE;
318 simCtx->profilingSelectedFuncs = NULL;
319 simCtx->nProfilingSelectedFuncs = 0;
320 strcpy(simCtx->profilingTimestepMode, "selected");
321 strcpy(simCtx->profilingTimestepFile, "Profiling_Timestep_Summary.csv");
322 simCtx->profilingFinalSummary = PETSC_TRUE;
323 simCtx->walltimeGuardEnabled = PETSC_FALSE;
324 simCtx->walltimeGuardActive = PETSC_FALSE;
325 simCtx->walltimeGuardWarmupSteps = 10;
326 simCtx->walltimeGuardMultiplier = 2.0;
327 simCtx->walltimeGuardMinSeconds = 60.0;
328 simCtx->walltimeGuardEstimatorAlpha = 0.35;
330 simCtx->walltimeGuardLimitSeconds = 0.0;
331 simCtx->walltimeGuardCompletedSteps = 0;
334 simCtx->walltimeGuardHasEWMA = PETSC_FALSE;
335 simCtx->walltimeGuardEWMASeconds = 0.0;
336 simCtx->walltimeGuardLatestStepSeconds = 0.0;
337 simCtx->runtimeMemoryLogEnabled = PETSC_TRUE;
338 strcpy(simCtx->runtimeMemoryLogFile, "Runtime_Memory.log");
339 simCtx->runtimeMemoryLogStarted = PETSC_FALSE;
340 simCtx->runtimeMemoryLogHasPrevious = PETSC_FALSE;
342 // --- Group 11: Post-Processing Information ---
343 strcpy(simCtx->PostprocessingControlFile, "config/post.run");
344 ierr = PetscNew(&simCtx->pps); CHKERRQ(ierr);
345
346 // === 2. Get MPI Info and Handle Config File =============================
347 // -- Group 1: Parallelism & MPI Information
348 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &simCtx->rank); CHKERRQ(ierr);
349 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &simCtx->size); CHKERRQ(ierr);
350
351 // First, check if the -control_file argument was provided by the user/script.
352 ierr = PetscOptionsGetString(NULL, NULL, "-control_file", control_filename, sizeof(control_filename), &control_flg); CHKERRQ(ierr);
353
354 // If the flag is NOT present or the filename is empty, abort with a helpful error.
355 if (!control_flg || strlen(control_filename) == 0) {
356 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
357 "\n\n*** MANDATORY ARGUMENT MISSING ***\n"
358 "The -control_file argument was not provided.\n"
359 "This program must be launched with a configuration file.\n"
360 "Example: mpiexec -n 4 ./simulator -control_file /path/to/your/config.control\n"
361 "This is typically handled automatically by the 'picurv' script.\n");
362 }
363
364 // At this point, we have a valid filename. Attempt to load it.
365 LOG(GLOBAL, LOG_INFO, "Loading mandatory configuration from: %s\n", control_filename);
366 ierr = PetscOptionsInsertFile(PETSC_COMM_WORLD, NULL, control_filename, PETSC_FALSE);
367 if (ierr == PETSC_ERR_FILE_OPEN) {
368 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_FILE_OPEN, "The specified control file was not found or could not be opened: %s", control_filename);
369 }
370 CHKERRQ(ierr);
371
372 // === 3. A Configure Logging System ========================================
373 // This logic determines the logging configuration and STORES it in simCtx for
374 // later reference and cleanup.
375 ierr = PetscOptionsGetString(NULL, NULL, "-whitelist_config_file", simCtx->allowedFile, PETSC_MAX_PATH_LEN, &simCtx->useCfg); CHKERRQ(ierr);
376
377 if (simCtx->useCfg) {
378 ierr = LoadAllowedFunctionsFromFile(simCtx->allowedFile, &simCtx->allowedFuncs, &simCtx->nAllowed);
379 if (ierr) {
380 // Use direct PetscPrintf as logging system isn't fully active yet.
381 PetscPrintf(PETSC_COMM_SELF, "[%s] WARNING: Failed to load allowed functions from '%s'. Falling back to default list.\n", __func__, simCtx->allowedFile);
382 simCtx->useCfg = PETSC_FALSE; // Mark as failed.
383 ierr = 0; // Clear the error to allow fallback.
384 } else if (simCtx->nAllowed == 0) {
385 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
386 "Whitelist config file '%s' is empty. Omit -whitelist_config_file to use the default allow-list, or list at least one function.",
387 simCtx->allowedFile);
388 }
389 }
390 if (!simCtx->useCfg) {
391 // Fallback to default logging functions if no file was used or if loading failed.
392 simCtx->nAllowed = 2;
393 ierr = PetscMalloc1(simCtx->nAllowed, &simCtx->allowedFuncs); CHKERRQ(ierr);
394 ierr = PetscStrallocpy("main", &simCtx->allowedFuncs[0]); CHKERRQ(ierr);
395 ierr = PetscStrallocpy("CreateSimulationContext", &simCtx->allowedFuncs[1]); CHKERRQ(ierr);
396 }
397
398 // Activate the configuration by passing it to the logging module's setup function.
399 set_allowed_functions((const char**)simCtx->allowedFuncs, (size_t)simCtx->nAllowed);
400
401 // Now that the logger is configured, we can use it.
402 LOG_ALLOW_SYNC(LOCAL, LOG_INFO, "Context created. Initializing on rank %d of %d.\n", simCtx->rank, simCtx->size);
403 print_log_level(); // This will now correctly reflect the LOG_LEVEL environment variable.
404
405 // === 3.B Configure Profiling System ========================================
406 ierr = PetscOptionsGetString(NULL, NULL, "-profiling_timestep_mode", simCtx->profilingTimestepMode, sizeof(simCtx->profilingTimestepMode), NULL); CHKERRQ(ierr);
407 ierr = PetscOptionsGetString(NULL, NULL, "-profiling_timestep_file", simCtx->profilingTimestepFile, PETSC_MAX_PATH_LEN, NULL); CHKERRQ(ierr);
408 ierr = PetscOptionsGetBool(NULL, NULL, "-profiling_final_summary", &simCtx->profilingFinalSummary, NULL); CHKERRQ(ierr);
409 if (strcmp(simCtx->profilingTimestepMode, "off") != 0 &&
410 strcmp(simCtx->profilingTimestepMode, "selected") != 0 &&
411 strcmp(simCtx->profilingTimestepMode, "all") != 0) {
412 PetscPrintf(PETSC_COMM_SELF, "[%s] WARNING: Unknown profiling timestep mode '%s'. Falling back to 'selected'.\n", __func__, simCtx->profilingTimestepMode);
413 strcpy(simCtx->profilingTimestepMode, "selected");
414 }
415
416 if (strcmp(simCtx->profilingTimestepMode, "selected") == 0) {
417 ierr = PetscOptionsGetString(NULL, NULL, "-profile_config_file", simCtx->profilingSelectedFuncsFile, PETSC_MAX_PATH_LEN, &simCtx->useProfilingSelectedFuncsCfg); CHKERRQ(ierr);
418 if (simCtx->useProfilingSelectedFuncsCfg) {
420 if (ierr) {
421 PetscPrintf(PETSC_COMM_SELF, "[%s] WARNING: Failed to load selected profiling functions from '%s'. Falling back to default list.\n", __func__, simCtx->profilingSelectedFuncsFile);
422 simCtx->useProfilingSelectedFuncsCfg = PETSC_FALSE;
423 ierr = 0;
424 }
425 }
426 if (!simCtx->useProfilingSelectedFuncsCfg) {
427 // Fallback to a hardcoded default list if no file was provided or loading failed.
428 simCtx->nProfilingSelectedFuncs = 4;
429 ierr = PetscMalloc1(simCtx->nProfilingSelectedFuncs, &simCtx->profilingSelectedFuncs); CHKERRQ(ierr);
430 ierr = PetscStrallocpy("FlowSolver", &simCtx->profilingSelectedFuncs[0]); CHKERRQ(ierr);
431 ierr = PetscStrallocpy("AdvanceSimulation", &simCtx->profilingSelectedFuncs[1]); CHKERRQ(ierr);
432 ierr = PetscStrallocpy("LocateAllParticlesInGrid", &simCtx->profilingSelectedFuncs[2]); CHKERRQ(ierr);
433 ierr = PetscStrallocpy("InterpolateAllFieldsToSwarm", &simCtx->profilingSelectedFuncs[3]); CHKERRQ(ierr);
434 }
435 }
436
437 // Initialize the profiling system with the current updated simulation context.
438 ierr = ProfilingInitialize(simCtx); CHKERRQ(ierr);
439
440 // === 4. Parse All Command Line Options ==================================
441 LOG_ALLOW(GLOBAL, LOG_INFO, "Parsing command-line options...\n");
442
443 // --- Group 2
444 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 2: Simulation Control,Time and I/O.\n");
445 // Read the physical time to start from.
446 // The default is already 0.0, so this will only be non-zero if the user provides it.
447 ierr = PetscOptionsGetInt(NULL, NULL, "-start_step", &simCtx->StartStep, NULL); CHKERRQ(ierr);
448 ierr = PetscOptionsGetInt(NULL,NULL, "-totalsteps", &simCtx->StepsToRun, NULL); CHKERRQ(ierr);
449 ierr = PetscOptionsGetBool(NULL, NULL, "-only_setup", &simCtx->OnlySetup, NULL); CHKERRQ(ierr);
450 ierr = PetscOptionsGetBool(NULL, NULL, "-continue_mode", &simCtx->continueMode, NULL); CHKERRQ(ierr);
451 ierr = PetscOptionsGetReal(NULL, NULL, "-dt", &simCtx->dt, NULL); CHKERRQ(ierr);
452 ierr = PetscOptionsGetInt(NULL, NULL, "-tio", &simCtx->tiout, NULL); CHKERRQ(ierr);
453 ierr = PetscOptionsGetInt(NULL, NULL, "-particle_console_output_freq", &simCtx->particleConsoleOutputFreq, &particle_console_output_freq_flg); CHKERRQ(ierr);
454 if (!particle_console_output_freq_flg) {
455 simCtx->particleConsoleOutputFreq = simCtx->tiout;
456 }
457 ierr = PetscOptionsGetString(NULL,NULL,"-euler_field_source",simCtx->eulerianSource,sizeof(simCtx->eulerianSource),NULL);CHKERRQ(ierr);
458 ierr = PetscOptionsGetString(NULL,NULL,"-output_dir",simCtx->output_dir,sizeof(simCtx->output_dir),NULL);CHKERRQ(ierr);
459 ierr = PetscOptionsGetString(NULL,NULL,"-restart_dir",simCtx->restart_dir,sizeof(simCtx->restart_dir),NULL);CHKERRQ(ierr);
460 ierr = PetscOptionsGetString(NULL,NULL,"-log_dir",simCtx->log_dir,sizeof(simCtx->log_dir),NULL);CHKERRQ(ierr);
461 ierr = PetscOptionsGetString(NULL,NULL,"-euler_subdir",simCtx->euler_subdir,sizeof(simCtx->euler_subdir),NULL);CHKERRQ(ierr);
462 ierr = PetscOptionsGetString(NULL,NULL,"-particle_subdir",simCtx->particle_subdir,sizeof(simCtx->particle_subdir),NULL);CHKERRQ(ierr);
463 ierr = PetscOptionsGetBool(NULL, NULL, "-walltime_guard_enabled", &simCtx->walltimeGuardEnabled, NULL); CHKERRQ(ierr);
464 ierr = PetscOptionsGetInt(NULL, NULL, "-walltime_guard_warmup_steps", &simCtx->walltimeGuardWarmupSteps, NULL); CHKERRQ(ierr);
465 ierr = PetscOptionsGetReal(NULL, NULL, "-walltime_guard_multiplier", &simCtx->walltimeGuardMultiplier, NULL); CHKERRQ(ierr);
466 ierr = PetscOptionsGetBool(NULL, NULL, "-runtime_memory_log_enabled", &simCtx->runtimeMemoryLogEnabled, NULL); CHKERRQ(ierr);
467 ierr = PetscOptionsGetString(NULL, NULL, "-runtime_memory_log_file", simCtx->runtimeMemoryLogFile, PETSC_MAX_PATH_LEN, NULL); CHKERRQ(ierr);
468 ierr = PetscOptionsGetReal(NULL, NULL, "-walltime_guard_min_seconds", &simCtx->walltimeGuardMinSeconds, NULL); CHKERRQ(ierr);
469 ierr = PetscOptionsGetReal(NULL, NULL, "-walltime_guard_estimator_alpha", &simCtx->walltimeGuardEstimatorAlpha, NULL); CHKERRQ(ierr);
470
471 if (simCtx->walltimeGuardWarmupSteps <= 0) {
472 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Invalid value for -walltime_guard_warmup_steps: %d. Must be > 0.", simCtx->walltimeGuardWarmupSteps);
473 }
474 if (simCtx->walltimeGuardMultiplier <= 0.0 || simCtx->walltimeGuardMultiplier > 5.0) {
475 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Invalid value for -walltime_guard_multiplier: %.6f. Must be in (0, 5].", (double)simCtx->walltimeGuardMultiplier);
476 }
477 if (simCtx->walltimeGuardMinSeconds <= 0.0) {
478 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Invalid value for -walltime_guard_min_seconds: %.6f. Must be > 0.", (double)simCtx->walltimeGuardMinSeconds);
479 }
480 if (simCtx->walltimeGuardEstimatorAlpha <= 0.0 || simCtx->walltimeGuardEstimatorAlpha > 1.0) {
481 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Invalid value for -walltime_guard_estimator_alpha: %.6f. Must be in (0, 1].", (double)simCtx->walltimeGuardEstimatorAlpha);
482 }
483
484 if(strcmp(simCtx->eulerianSource,"solve")!= 0 && strcmp(simCtx->eulerianSource,"load") != 0 && strcmp(simCtx->eulerianSource,"analytical")!=0){
485 SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Invalid value for -euler_field_source. Must be 'load','analytical' or 'solve'. You provided '%s'.",simCtx->eulerianSource);
486 }
487
488 if (simCtx->walltimeGuardEnabled) {
489 const char *job_start_env = getenv("PICURV_JOB_START_EPOCH");
490 const char *limit_env = getenv("PICURV_WALLTIME_LIMIT_SECONDS");
491 PetscBool job_start_ok = RuntimeWalltimeGuardParsePositiveSeconds(job_start_env, &simCtx->walltimeGuardJobStartEpochSeconds);
492 PetscBool limit_ok = RuntimeWalltimeGuardParsePositiveSeconds(limit_env, &simCtx->walltimeGuardLimitSeconds);
493
494 if (!job_start_ok || !limit_ok) {
495 simCtx->walltimeGuardActive = PETSC_FALSE;
497 simCtx->walltimeGuardLimitSeconds = 0.0;
498 LOG_ALLOW(
499 GLOBAL,
501 "Runtime walltime guard enabled but %s/%s are missing or invalid. Falling back to external shutdown signals only.\n",
502 "PICURV_JOB_START_EPOCH",
503 "PICURV_WALLTIME_LIMIT_SECONDS"
504 );
505 } else {
506 simCtx->walltimeGuardActive = PETSC_TRUE;
507 }
508 }
509
510 // --- Group 3
511 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 3: High-Level Physics & Model Selection Flags\n");
512 ierr = PetscOptionsGetInt(NULL, NULL, "-imm", &simCtx->immersed, NULL); CHKERRQ(ierr);
513 ierr = PetscOptionsGetInt(NULL, NULL, "-fsi", &simCtx->movefsi, NULL); CHKERRQ(ierr);
514 ierr = PetscOptionsGetInt(NULL, NULL, "-rfsi", &simCtx->rotatefsi, NULL); CHKERRQ(ierr);
515 ierr = PetscOptionsGetInt(NULL, NULL, "-sediment", &simCtx->sediment, NULL); CHKERRQ(ierr);
516 ierr = PetscOptionsGetInt(NULL, NULL, "-rheology", &simCtx->rheology, NULL); CHKERRQ(ierr);
517 ierr = PetscOptionsGetInt(NULL, NULL, "-inv", &simCtx->invicid, NULL); CHKERRQ(ierr);
518 ierr = PetscOptionsGetInt(NULL, NULL, "-TwoD", &simCtx->TwoD, NULL); CHKERRQ(ierr);
519 ierr = PetscOptionsGetInt(NULL, NULL, "-thin", &simCtx->thin, NULL); CHKERRQ(ierr);
520 ierr = PetscOptionsGetInt(NULL, NULL, "-mframe", &simCtx->moveframe, NULL); CHKERRQ(ierr);
521 ierr = PetscOptionsGetInt(NULL, NULL, "-rframe", &simCtx->rotateframe, NULL); CHKERRQ(ierr);
522 ierr = PetscOptionsGetInt(NULL, NULL, "-blk", &simCtx->blank, NULL); CHKERRQ(ierr);
523 ierr = PetscOptionsGetInt(NULL, NULL, "-dgf_z", &simCtx->dgf_z, NULL); CHKERRQ(ierr);
524 ierr = PetscOptionsGetInt(NULL, NULL, "-dgf_y", &simCtx->dgf_y, NULL); CHKERRQ(ierr);
525 ierr = PetscOptionsGetInt(NULL, NULL, "-dgf_x", &simCtx->dgf_x, NULL); CHKERRQ(ierr);
526 ierr = PetscOptionsGetInt(NULL, NULL, "-dgf_az", &simCtx->dgf_az, NULL); CHKERRQ(ierr);
527 ierr = PetscOptionsGetInt(NULL, NULL, "-dgf_ay", &simCtx->dgf_ay, NULL); CHKERRQ(ierr);
528 ierr = PetscOptionsGetInt(NULL, NULL, "-dgf_ax", &simCtx->dgf_ax, NULL); CHKERRQ(ierr);
529 ierr = PetscOptionsGetString(NULL,NULL,"-analytical_type",simCtx->AnalyticalSolutionType,sizeof(simCtx->AnalyticalSolutionType),NULL);CHKERRQ(ierr);
530
531 // --- Group 4
532 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 4: Specific Simulation Case Flags \n");
533 ierr = PetscOptionsGetInt(NULL, NULL, "-cop", &simCtx->cop, NULL); CHKERRQ(ierr);
534 ierr = PetscOptionsGetInt(NULL, NULL, "-fish", &simCtx->fish, NULL); CHKERRQ(ierr);
535 ierr = PetscOptionsGetInt(NULL, NULL, "-pizza", &simCtx->pizza, NULL); CHKERRQ(ierr);
536 ierr = PetscOptionsGetInt(NULL, NULL, "-turbine", &simCtx->turbine, NULL); CHKERRQ(ierr);
537 ierr = PetscOptionsGetInt(NULL, NULL, "-fishcyl", &simCtx->fishcyl, NULL); CHKERRQ(ierr);
538 ierr = PetscOptionsGetInt(NULL, NULL, "-eel", &simCtx->eel, NULL); CHKERRQ(ierr);
539 ierr = PetscOptionsGetInt(NULL, NULL, "-cstart", &simCtx->fish_c, NULL); CHKERRQ(ierr);
540 ierr = PetscOptionsGetInt(NULL, NULL, "-wing", &simCtx->wing, NULL); CHKERRQ(ierr);
541 ierr = PetscOptionsGetInt(NULL, NULL, "-mhv", &simCtx->MHV, NULL); CHKERRQ(ierr);
542 ierr = PetscOptionsGetInt(NULL, NULL, "-hydro", &simCtx->hydro, NULL); CHKERRQ(ierr);
543 ierr = PetscOptionsGetInt(NULL, NULL, "-lv", &simCtx->LV, NULL); CHKERRQ(ierr);
544 ierr = PetscOptionsGetInt(NULL, NULL, "-Pipe", &simCtx->Pipe, NULL); CHKERRQ(ierr);
545 ierr = PetscOptionsGetInt(NULL, NULL, "-Turbulent_Channel_z", &simCtx->channelz, NULL); CHKERRQ(ierr);
546 ierr = PetscOptionsGetReal(NULL,NULL,"-Turbulent_Channel_z_Driving_Force",&simCtx->drivingForceMagnitude,NULL);CHKERRQ(ierr);
547 ierr = PetscOptionsGetReal(NULL,NULL,"-Turbulent_Channel_z_Scaling_Factor",&simCtx->forceScalingFactor,NULL);CHKERRQ(ierr);
548 // --- Group 5
549 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 5: Solver & Numerics Parameters \n");
550 char mom_solver_type_char[PETSC_MAX_PATH_LEN];
551 char solution_convergence_mode_char[PETSC_MAX_PATH_LEN];
552 PetscBool mom_solver_type_flg = PETSC_FALSE;
553 PetscBool solution_convergence_mode_flg = PETSC_FALSE;
554 ierr = PetscOptionsGetString(NULL, NULL, "-mom_solver_type", mom_solver_type_char, sizeof(mom_solver_type_char), &mom_solver_type_flg); CHKERRQ(ierr);
555 ierr = PetscOptionsGetInt(NULL, NULL, "-mom_max_pseudo_steps", &simCtx->mom_max_pseudo_steps, NULL); CHKERRQ(ierr);
556 ierr = PetscOptionsGetReal(NULL, NULL, "-mom_atol", &simCtx->mom_atol, NULL); CHKERRQ(ierr);
557 ierr = PetscOptionsGetReal(NULL, NULL, "-mom_rtol", &simCtx->mom_rtol, NULL); CHKERRQ(ierr);
558 ierr = PetscOptionsGetReal(NULL, NULL, "-imp_stol", &simCtx->imp_stol, NULL); CHKERRQ(ierr);
559 ierr = PetscOptionsGetInt(NULL, NULL, "-central", &simCtx->central, NULL); CHKERRQ(ierr);
560 ierr = PetscOptionsGetString(NULL, NULL, "-solution_convergence_mode",
561 solution_convergence_mode_char, sizeof(solution_convergence_mode_char),
562 &solution_convergence_mode_flg); CHKERRQ(ierr);
563 ierr = PetscOptionsGetInt(NULL, NULL, "-solution_convergence_period_steps", &simCtx->solutionConvergencePeriodSteps, NULL); CHKERRQ(ierr);
564 ierr = PetscOptionsGetInt(NULL, NULL, "-solution_convergence_window_steps", &simCtx->solutionConvergenceWindowSteps, NULL); CHKERRQ(ierr);
565
566 // Keep parser acceptance aligned with the enum and FlowSolver dispatch.
567 if (mom_solver_type_flg) {
568 if(strcmp(mom_solver_type_char, "DUALTIME_PICARD_RK4") == 0) {
570 } else if (strcmp(mom_solver_type_char, "EXPLICIT_RK") == 0) {
572 } else {
573 LOG(GLOBAL, LOG_ERROR, "Invalid value for -mom_solver_type: '%s'. Valid options are: 'DUALTIME_PICARD_RK4', 'EXPLICIT_RK'.\n", mom_solver_type_char);
574 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Invalid value for -mom_solver_type: '%s'.", mom_solver_type_char);
575 }
576 }
577
578 if (solution_convergence_mode_flg) {
579 if (strcmp(solution_convergence_mode_char, "STEADY_DETERMINISTIC") == 0) {
581 } else if (strcmp(solution_convergence_mode_char, "PERIODIC_DETERMINISTIC") == 0) {
583 } else if (strcmp(solution_convergence_mode_char, "STATISTICAL_STEADY") == 0) {
585 } else if (strcmp(solution_convergence_mode_char, "TRANSIENT") == 0) {
587 } else {
588 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
589 "Invalid value for -solution_convergence_mode: '%s'.", solution_convergence_mode_char);
590 }
591 }
592
594 simCtx->solutionConvergencePeriodSteps <= 0) {
595 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
596 "solution convergence mode PERIODIC_DETERMINISTIC requires -solution_convergence_period_steps > 0.");
597 }
599 simCtx->solutionConvergenceWindowSteps <= 0) {
600 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
601 "solution convergence mode STATISTICAL_STEADY requires -solution_convergence_window_steps > 0.");
602 }
603
604 // --- Multigrid Options ---
605 ierr = PetscOptionsGetInt(NULL, NULL, "-mg_level", &simCtx->mglevels, NULL); CHKERRQ(ierr);
606 ierr = PetscOptionsGetInt(NULL, NULL, "-mg_max_it", &simCtx->mg_MAX_IT, NULL); CHKERRQ(ierr);
607 ierr = PetscOptionsGetInt(NULL, NULL, "-mg_idx", &simCtx->mg_idx, NULL); CHKERRQ(ierr);
608 ierr = PetscOptionsGetInt(NULL, NULL, "-mg_pre_it", &simCtx->mg_preItr, NULL); CHKERRQ(ierr);
609 ierr = PetscOptionsGetInt(NULL, NULL, "-mg_post_it", &simCtx->mg_poItr, NULL); CHKERRQ(ierr);
610
611 // --- Other Solver Options ---
612 ierr = PetscOptionsGetInt(NULL, NULL, "-poisson", &simCtx->poisson, NULL); CHKERRQ(ierr);
613 ierr = PetscOptionsGetReal(NULL, NULL, "-poisson_tol", &simCtx->poisson_tol, NULL); CHKERRQ(ierr);
614 ierr = PetscOptionsGetInt(NULL, NULL, "-str", &simCtx->STRONG_COUPLING, NULL); CHKERRQ(ierr);
615 ierr = PetscOptionsGetReal(NULL, NULL, "-ren", &simCtx->ren, NULL); CHKERRQ(ierr);
616 ierr = PetscOptionsGetReal(NULL, NULL, "-pseudo_cfl", &simCtx->pseudo_cfl, NULL); CHKERRQ(ierr);
617 ierr = PetscOptionsGetReal(NULL, NULL, "-max_pseudo_cfl", &simCtx->max_pseudo_cfl, NULL); CHKERRQ(ierr);
618 ierr = PetscOptionsGetReal(NULL, NULL, "-min_pseudo_cfl", &simCtx->min_pseudo_cfl, NULL); CHKERRQ(ierr);
619 ierr = PetscOptionsGetReal(NULL, NULL, "-pseudo_cfl_reduction_factor", &simCtx->pseudo_cfl_reduction_factor, NULL); CHKERRQ(ierr);
620 ierr = PetscOptionsGetReal(NULL, NULL, "-pseudo_cfl_growth_factor", &simCtx->pseudo_cfl_growth_factor, NULL); CHKERRQ(ierr);
621 ierr = PetscOptionsGetReal(NULL,NULL, "-mom_dt_rk4_residual_norm_noise_allowance_factor",&simCtx->mom_dt_rk4_residual_norm_noise_allowance_factor,NULL);CHKERRQ(ierr);
622 ierr = PetscOptionsHasName(NULL, NULL, "-ps_ksp_pic_monitor_true_residual", &simCtx->ps_ksp_pic_monitor_true_residual); CHKERRQ(ierr);
623 ierr = PetscOptionsGetInt(NULL, NULL, "-finit", &simCtx->FieldInitialization, NULL); CHKERRQ(ierr);
624 ierr = PetscOptionsGetReal(NULL, NULL, "-ucont_x", &simCtx->InitialConstantContra.x, NULL); CHKERRQ(ierr);
625 ierr = PetscOptionsGetReal(NULL, NULL, "-ucont_y", &simCtx->InitialConstantContra.y, NULL); CHKERRQ(ierr);
626 ierr = PetscOptionsGetReal(NULL, NULL, "-ucont_z", &simCtx->InitialConstantContra.z, NULL); CHKERRQ(ierr);
627 ierr = PetscOptionsGetReal(NULL, NULL, "-analytical_uniform_u", &simCtx->AnalyticalUniformVelocity.x, NULL); CHKERRQ(ierr);
628 ierr = PetscOptionsGetReal(NULL, NULL, "-analytical_uniform_v", &simCtx->AnalyticalUniformVelocity.y, NULL); CHKERRQ(ierr);
629 ierr = PetscOptionsGetReal(NULL, NULL, "-analytical_uniform_w", &simCtx->AnalyticalUniformVelocity.z, NULL); CHKERRQ(ierr);
630 PetscBool verification_scalar_value_set = PETSC_FALSE;
631 PetscBool verification_scalar_phi0_set = PETSC_FALSE;
632 PetscBool verification_scalar_slope_x_set = PETSC_FALSE;
633 PetscBool verification_scalar_amplitude_set = PETSC_FALSE;
634 PetscBool verification_scalar_kx_set = PETSC_FALSE;
635 PetscBool verification_scalar_ky_set = PETSC_FALSE;
636 PetscBool verification_scalar_kz_set = PETSC_FALSE;
637 ierr = PetscOptionsGetString(NULL, NULL, "-verification_diffusivity_mode",
639 sizeof(simCtx->verificationDiffusivity.mode), NULL); CHKERRQ(ierr);
640 ierr = PetscOptionsGetString(NULL, NULL, "-verification_diffusivity_profile",
642 sizeof(simCtx->verificationDiffusivity.profile), NULL); CHKERRQ(ierr);
643 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_diffusivity_gamma0",
644 &simCtx->verificationDiffusivity.gamma0, NULL); CHKERRQ(ierr);
645 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_diffusivity_slope_x",
646 &simCtx->verificationDiffusivity.slope_x, NULL); CHKERRQ(ierr);
647 ierr = PetscOptionsGetString(NULL, NULL, "-verification_scalar_mode",
648 simCtx->verificationScalar.mode,
649 sizeof(simCtx->verificationScalar.mode), NULL); CHKERRQ(ierr);
650 ierr = PetscOptionsGetString(NULL, NULL, "-verification_scalar_profile",
652 sizeof(simCtx->verificationScalar.profile), NULL); CHKERRQ(ierr);
653 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_value",
654 &simCtx->verificationScalar.value, &verification_scalar_value_set); CHKERRQ(ierr);
655 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_phi0",
656 &simCtx->verificationScalar.phi0, &verification_scalar_phi0_set); CHKERRQ(ierr);
657 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_slope_x",
658 &simCtx->verificationScalar.slope_x, &verification_scalar_slope_x_set); CHKERRQ(ierr);
659 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_amplitude",
660 &simCtx->verificationScalar.amplitude, &verification_scalar_amplitude_set); CHKERRQ(ierr);
661 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_kx",
662 &simCtx->verificationScalar.kx, &verification_scalar_kx_set); CHKERRQ(ierr);
663 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_ky",
664 &simCtx->verificationScalar.ky, &verification_scalar_ky_set); CHKERRQ(ierr);
665 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_kz",
666 &simCtx->verificationScalar.kz, &verification_scalar_kz_set); CHKERRQ(ierr);
668 (PetscBool)(simCtx->verificationDiffusivity.mode[0] != '\0' ||
669 simCtx->verificationDiffusivity.profile[0] != '\0');
671 (PetscBool)(simCtx->verificationScalar.mode[0] != '\0' ||
672 simCtx->verificationScalar.profile[0] != '\0');
673 if (simCtx->verificationDiffusivity.enabled) {
674 if (strcmp(simCtx->eulerianSource, "analytical") != 0) {
675 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
676 "verification diffusivity overrides require -euler_field_source \"analytical\".");
677 }
678 if (strcmp(simCtx->verificationDiffusivity.mode, "analytical") != 0) {
679 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
680 "Unsupported -verification_diffusivity_mode '%s'. Only 'analytical' is supported.",
682 }
683 if (strcmp(simCtx->verificationDiffusivity.profile, "LINEAR_X") != 0) {
684 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
685 "Unsupported -verification_diffusivity_profile '%s'. Only 'LINEAR_X' is supported.",
687 }
688 }
689 if (simCtx->verificationScalar.enabled) {
690 if (strcmp(simCtx->eulerianSource, "analytical") != 0) {
691 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
692 "verification scalar overrides require -euler_field_source \"analytical\".");
693 }
694 if (strcmp(simCtx->verificationScalar.mode, "analytical") != 0) {
695 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
696 "Unsupported -verification_scalar_mode '%s'. Only 'analytical' is supported.",
697 simCtx->verificationScalar.mode);
698 }
699 if (strcmp(simCtx->verificationScalar.profile, "CONSTANT") == 0) {
700 if (!verification_scalar_value_set) {
701 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
702 "verification scalar profile CONSTANT requires -verification_scalar_value.");
703 }
704 } else if (strcmp(simCtx->verificationScalar.profile, "LINEAR_X") == 0) {
705 if (!verification_scalar_phi0_set || !verification_scalar_slope_x_set) {
706 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
707 "verification scalar profile LINEAR_X requires -verification_scalar_phi0 and -verification_scalar_slope_x.");
708 }
709 } else if (strcmp(simCtx->verificationScalar.profile, "SIN_PRODUCT") == 0) {
710 if (!verification_scalar_amplitude_set || !verification_scalar_kx_set ||
711 !verification_scalar_ky_set || !verification_scalar_kz_set) {
712 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
713 "verification scalar profile SIN_PRODUCT requires -verification_scalar_amplitude, -verification_scalar_kx, -verification_scalar_ky, and -verification_scalar_kz.");
714 }
715 } else {
716 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
717 "Unsupported -verification_scalar_profile '%s'. Supported profiles: CONSTANT, LINEAR_X, SIN_PRODUCT.",
719 }
720 }
721 // NOTE: cdisx,cdisy,cdisz haven't been parsed, add if necessary.
722
723 // --- Group 6
724 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 6: Physical & Geometric Parameters \n");
725 ierr = PetscOptionsGetReal(NULL,NULL,"-schmidt_number",&simCtx->schmidt_number,NULL);CHKERRQ(ierr);
726 ierr = PetscOptionsGetReal(NULL,NULL,"-turb_schmidt_number",&simCtx->Turbulent_schmidt_number,NULL);CHKERRQ(ierr);
727 ierr = PetscOptionsGetInt(NULL, NULL, "-no_of_bodies", &simCtx->NumberOfBodies, NULL); CHKERRQ(ierr);
728 ierr = PetscOptionsGetReal(NULL,NULL,"-wall_roughness",&simCtx->wall_roughness_height,NULL);CHKERRQ(ierr);
729 // NOTE: angle is not parsed in the original code, it set programmatically. We will follow that.
730 // NOTE: max_angle is calculated based on other flags (like MHV) in the legacy code.
731 // We will defer that logic to a later setup stage and not parse them directly.
732 // The Scaling Information is calculated here
733 ierr = ParseScalingInformation(simCtx); CHKERRQ(ierr);
734
735 // --- Group 7
736 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 7: Grid, Domain, and Boundary Condition Settings \n");
737 ierr = PetscOptionsGetInt(NULL, NULL, "-nblk", &simCtx->block_number, NULL); CHKERRQ(ierr); // This is also a modern option
738 ierr = PetscOptionsGetInt(NULL, NULL, "-inlet", &simCtx->inletprofile, NULL); CHKERRQ(ierr);
739 ierr = PetscOptionsGetInt(NULL, NULL, "-Ogrid", &simCtx->Ogrid, NULL); CHKERRQ(ierr);
740 // NOTE: channelz was not parsed, likely set programmatically. We will omit its parsing call.
741 ierr = PetscOptionsGetInt(NULL, NULL, "-grid1d", &simCtx->grid1d, NULL); CHKERRQ(ierr);
742 ierr = PetscOptionsGetBool(NULL, NULL, "-grid", &simCtx->generate_grid, NULL); CHKERRQ(ierr);
743 ierr = PetscOptionsGetString(NULL, NULL, "-grid_file", simCtx->grid_file, PETSC_MAX_PATH_LEN, NULL); CHKERRQ(ierr);
744 ierr = PetscOptionsGetInt(NULL, NULL, "-da_processors_x", &simCtx->da_procs_x, NULL); CHKERRQ(ierr);
745 ierr = PetscOptionsGetInt(NULL, NULL, "-da_processors_y", &simCtx->da_procs_y, NULL); CHKERRQ(ierr);
746 ierr = PetscOptionsGetInt(NULL, NULL, "-da_processors_z", &simCtx->da_procs_z, NULL); CHKERRQ(ierr);
747 ierr = PetscOptionsGetInt(NULL, NULL, "-i_periodic", &simCtx->i_periodic, NULL); CHKERRQ(ierr);
748 ierr = PetscOptionsGetInt(NULL, NULL, "-j_periodic", &simCtx->j_periodic, NULL); CHKERRQ(ierr);
749 ierr = PetscOptionsGetInt(NULL, NULL, "-k_periodic", &simCtx->k_periodic, NULL); CHKERRQ(ierr);
750 ierr = PetscOptionsGetInt(NULL, NULL, "-pbc_domain", &simCtx->blkpbc, NULL); CHKERRQ(ierr);
751 // NOTE: pseudo_periodic was not parsed. We will omit its parsing call.
752 ierr = PetscOptionsGetReal(NULL, NULL, "-grid_rotation_angle", &simCtx->grid_rotation_angle, NULL); CHKERRQ(ierr);
753 ierr = PetscOptionsGetReal(NULL, NULL, "-Croty", &simCtx->Croty, NULL); CHKERRQ(ierr);
754 ierr = PetscOptionsGetReal(NULL, NULL, "-Crotz", &simCtx->Crotz, NULL); CHKERRQ(ierr);
755 PetscBool bcs_flg;
756 char file_list_str[PETSC_MAX_PATH_LEN * 10]; // Buffer for comma-separated list
757
758 ierr = PetscOptionsGetString(NULL, NULL, "-bcs_files", file_list_str, sizeof(file_list_str), &bcs_flg); CHKERRQ(ierr);
759 ierr = PetscOptionsGetReal(NULL, NULL, "-U_bc", &simCtx->U_bc, NULL); CHKERRQ(ierr);
760
761 if (bcs_flg) {
762 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Found -bcs_files option, overriding default.\n");
763
764 // A. Clean up the default memory we allocated in Phase 1.
765 ierr = PetscFree(simCtx->bcs_files[0]); CHKERRQ(ierr);
766 ierr = PetscFree(simCtx->bcs_files); CHKERRQ(ierr);
767 simCtx->num_bcs_files = 0;
768 simCtx->bcs_files = NULL;
769
770 // B. Parse the user-provided comma-separated list.
771 char *token;
772 char *str_copy;
773 ierr = PetscStrallocpy(file_list_str, &str_copy); CHKERRQ(ierr);
774
775 // First pass: count the number of files.
776 token = strtok(str_copy, ",");
777 while (token) {
778 simCtx->num_bcs_files++;
779 token = strtok(NULL, ",");
780 }
781 ierr = PetscFree(str_copy); CHKERRQ(ierr);
782
783 // Second pass: allocate memory and store the filenames.
784 ierr = PetscMalloc1(simCtx->num_bcs_files, &simCtx->bcs_files); CHKERRQ(ierr);
785 ierr = PetscStrallocpy(file_list_str, &str_copy); CHKERRQ(ierr);
786 token = strtok(str_copy, ",");
787 for (PetscInt i = 0; i < simCtx->num_bcs_files; i++) {
788 ierr = PetscStrallocpy(token, &simCtx->bcs_files[i]); CHKERRQ(ierr);
789 token = strtok(NULL, ",");
790 }
791 ierr = PetscFree(str_copy); CHKERRQ(ierr);
792 }
793
794
795 // --- Group 8
796 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 8: Turbulence Modeling (LES/RANS) \n");
797 PetscInt temp_les_model;
798 ierr = PetscOptionsGetInt(NULL, NULL, "-les", &temp_les_model, NULL); CHKERRQ(ierr);
799 simCtx->les = (LESModelType)temp_les_model;
800 ierr = PetscOptionsGetInt(NULL, NULL, "-rans", &simCtx->rans, NULL); CHKERRQ(ierr);
801 ierr = PetscOptionsGetInt(NULL, NULL, "-wallfunction", &simCtx->wallfunction, NULL); CHKERRQ(ierr);
802 ierr = PetscOptionsGetInt(NULL, NULL, "-mixed", &simCtx->mixed, NULL); CHKERRQ(ierr);
803 ierr = PetscOptionsGetInt(NULL, NULL, "-clark", &simCtx->clark, NULL); CHKERRQ(ierr);
804 ierr = PetscOptionsGetInt(NULL, NULL, "-dynamic_freq", &simCtx->dynamic_freq, NULL); CHKERRQ(ierr);
805 ierr = PetscOptionsGetReal(NULL, NULL, "-max_cs", &simCtx->max_cs, NULL); CHKERRQ(ierr);
806 ierr = PetscOptionsGetReal(NULL, NULL, "-const_cs", &simCtx->Const_CS, NULL); CHKERRQ(ierr);
807 ierr = PetscOptionsGetInt(NULL, NULL, "-testfilter_ik", &simCtx->testfilter_ik, NULL); CHKERRQ(ierr);
808 ierr = PetscOptionsGetInt(NULL, NULL, "-testfilter_1d", &simCtx->testfilter_1d, NULL); CHKERRQ(ierr);
809 ierr = PetscOptionsGetInt(NULL, NULL, "-i_homo_filter", &simCtx->i_homo_filter, NULL); CHKERRQ(ierr);
810 ierr = PetscOptionsGetInt(NULL, NULL, "-j_homo_filter", &simCtx->j_homo_filter, NULL); CHKERRQ(ierr);
811 ierr = PetscOptionsGetInt(NULL, NULL, "-k_homo_filter", &simCtx->k_homo_filter, NULL); CHKERRQ(ierr);
812 ierr = PetscOptionsGetBool(NULL, NULL, "-averaging", &simCtx->averaging, NULL); CHKERRQ(ierr);
813
814 // --- Group 9
815 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 9: Particle / DMSwarm Data & Settings \n");
816 ierr = PetscOptionsGetInt(NULL, NULL, "-numParticles", &simCtx->np, NULL); CHKERRQ(ierr);
817 ierr = PetscOptionsGetBool(NULL, NULL, "-read_fields", &simCtx->readFields, NULL); CHKERRQ(ierr);
818 PetscInt temp_pinit = (PetscInt)PARTICLE_INIT_SURFACE_RANDOM;
819 ierr = PetscOptionsGetInt(NULL, NULL, "-pinit", &temp_pinit, NULL); CHKERRQ(ierr);
821 PetscInt temp_interp = (PetscInt)INTERP_TRILINEAR;
822 ierr = PetscOptionsGetInt(NULL, NULL, "-interpolation_method", &temp_interp, NULL); CHKERRQ(ierr);
823 simCtx->interpolationMethod = (InterpolationMethod)temp_interp;
824 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Interpolation method: %s\n",
825 simCtx->interpolationMethod == INTERP_TRILINEAR ? "Trilinear (direct cell-center)" : "CornerAveraged (legacy)");
826 ierr = PetscOptionsGetReal(NULL, NULL, "-psrc_x", &simCtx->psrc_x, NULL); CHKERRQ(ierr);
827 ierr = PetscOptionsGetReal(NULL, NULL, "-psrc_y", &simCtx->psrc_y, NULL); CHKERRQ(ierr);
828 ierr = PetscOptionsGetReal(NULL, NULL, "-psrc_z", &simCtx->psrc_z, NULL); CHKERRQ(ierr);
829 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Particle initialization mode: %s. Point source: (%.6f, %.6f, %.6f)\n",
831 simCtx->psrc_x, simCtx->psrc_y, simCtx->psrc_z);
832 ierr = PetscOptionsGetString(NULL,NULL,"-particle_restart_mode",simCtx->particleRestartMode,sizeof(simCtx->particleRestartMode),NULL); CHKERRQ(ierr);
833 // Validation for Particle Restart Mode
834 if (strcmp(simCtx->particleRestartMode, "load") != 0 && strcmp(simCtx->particleRestartMode, "init") != 0) {
835 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Invalid value for -particle_restart_mode. Must be 'load' or 'init'. You provided '%s'.", simCtx->particleRestartMode);
836 }
837 ierr = InitializeBrownianRNG(simCtx); CHKERRQ(ierr);
838 // --- Group 10
839 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 10: Immersed Boundary & FSI Data Object Pointers \n");
840 ierr = PetscOptionsGetBool(NULL, NULL, "-rs_fsi", &simCtx->rstart_fsi, NULL); CHKERRQ(ierr);
841 ierr = PetscOptionsGetInt(NULL, NULL, "-duplicate", &simCtx->duplicate, NULL); CHKERRQ(ierr);
842
843 // --- Group 11
844 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 11: Top-Level Managers & Custom Configuration \n");
845 ierr = PetscOptionsGetInt(NULL, NULL, "-logfreq", &simCtx->LoggingFrequency, NULL); CHKERRQ(ierr);
846
847 if (simCtx->num_bcs_files != simCtx->block_number) {
848 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "Number of BC files (%d) does not match number of blocks (%d). Use -bcs_files \"file1.dat,file2.dat,...\".", simCtx->num_bcs_files, simCtx->block_number);
849 }
850
851 // --- Group 12
852 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 12: Post-Processing Information.\n");
853 // This logic determines the Post Processing configuration and STORES it in simCtx for later reference and cleanup.
854 ierr = PetscOptionsGetString(NULL,NULL,"-postprocessing_config_file",simCtx->PostprocessingControlFile,PETSC_MAX_PATH_LEN,NULL); CHKERRQ(ierr);
855 /* Parse post settings for both solver and post-processor binaries using the single pre-allocated pps object. */
856 ierr = ParsePostProcessingSettings(simCtx);
857
858 // === 5. Dependent Parameter Calculations ================================
859 // Some parameters depend on others, so we calculate them here.
860 simCtx->StartTime = (PetscReal)simCtx->StartStep*simCtx->dt;
861 simCtx->ti = simCtx->StartTime;
862 simCtx->step = simCtx->StartStep;
863
864 // === 5. Log Summary and Finalize Setup ==================================
865 LOG_ALLOW(GLOBAL, LOG_DEBUG, "-- Console Output Functions [Total : %d] : --\n", simCtx->nAllowed);
866 for (PetscInt i = 0; i < simCtx->nAllowed; ++i) {
867 LOG_ALLOW(GLOBAL, LOG_DEBUG, " [%2d] «%s»\n", i, simCtx->allowedFuncs[i]);
868 }
869
870 LOG_ALLOW(GLOBAL, LOG_INFO, "Configuration complete. Key parameters:\n");
871 LOG_ALLOW(GLOBAL, LOG_INFO, " - Run mode: %s\n", simCtx->OnlySetup ? "SETUP ONLY" : "Full Simulation");
872 LOG_ALLOW(GLOBAL, LOG_INFO, " - Time steps: %d (from %d to %d)\n", simCtx->StepsToRun, simCtx->StartStep, simCtx->StartStep + simCtx->StepsToRun);
873 LOG_ALLOW(GLOBAL, LOG_INFO, " - Time step size (dt): %g\n", simCtx->dt);
874 if (simCtx->tiout > 0) {
875 LOG_ALLOW(GLOBAL, LOG_INFO, " - Field/restart output cadence: every %d step(s)\n", simCtx->tiout);
876 } else {
877 LOG_ALLOW(GLOBAL, LOG_INFO, " - Field/restart output cadence: DISABLED\n");
878 }
879 LOG_ALLOW(GLOBAL, LOG_INFO, " - Immersed Boundary: %s\n", simCtx->immersed ? "ENABLED" : "DISABLED");
880 LOG_ALLOW(GLOBAL, LOG_INFO, " - Particles: %d\n", simCtx->np);
881 if (simCtx->np > 0) {
882 if (simCtx->particleConsoleOutputFreq > 0) {
883 LOG_ALLOW(GLOBAL, LOG_INFO, " - Particle console cadence: every %d step(s)\n", simCtx->particleConsoleOutputFreq);
884 } else {
885 LOG_ALLOW(GLOBAL, LOG_INFO, " - Particle console cadence: DISABLED\n");
886 }
887 LOG_ALLOW(GLOBAL, LOG_INFO, " - Particle console row subsampling: every %d particle(s)\n", simCtx->LoggingFrequency);
888 }
889 if (simCtx->StartStep > 0 && simCtx->np > 0) {
890 LOG_ALLOW(GLOBAL, LOG_INFO, " - Particle Restart Mode: %s\n", simCtx->particleRestartMode);
891 }
892
893 // --- Initialize PETSc's internal performance logging stage ---
894 ierr = PetscLogDefaultBegin(); CHKERRQ(ierr); // REDUNDANT but safe.
895 ierr = PetscMemorySetGetMaximumUsage(); CHKERRQ(ierr);
896
897 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Finished CreateSimulationContext successfully on rank %d.\n", simCtx->rank);
898
900 PetscFunctionReturn(0);
901}
PetscErrorCode ParsePostProcessingSettings(SimCtx *simCtx)
Initializes post-processing settings from a config file and command-line overrides.
Definition io.c:2222
PetscErrorCode ParseScalingInformation(SimCtx *simCtx)
Parses physical scaling parameters from command-line options.
Definition io.c:2370
void set_allowed_functions(const char **functionList, int count)
Sets the global list of function names that are allowed to log.
Definition logging.c:152
#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:252
#define LOCAL
Logging scope definitions for controlling message output.
Definition logging.h:44
#define GLOBAL
Scope for global logging across all processes.
Definition logging.h:45
#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:199
PetscErrorCode print_log_level(void)
Prints the current logging level to the console.
Definition logging.c:116
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
Definition logging.h:820
#define LOG(scope, level, fmt,...)
Logging macro for PETSc-based applications with scope control.
Definition logging.h:83
PetscErrorCode LoadAllowedFunctionsFromFile(const char filename[], char ***funcsOut, PetscInt *nOut)
Load function names from a text file.
Definition logging.c:596
PetscErrorCode ProfilingInitialize(SimCtx *simCtx)
Initializes the custom profiling system using configuration from SimCtx.
Definition logging.c:1882
@ LOG_ERROR
Critical errors that may halt the program.
Definition logging.h:28
@ LOG_INFO
Informational messages about program execution.
Definition logging.h:30
@ LOG_WARNING
Non-critical issues that warrant attention.
Definition logging.h:29
@ LOG_DEBUG
Detailed debugging information.
Definition logging.h:31
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
Definition logging.h:811
const char * ParticleInitializationToString(ParticleInitializationType ParticleInitialization)
Helper function to convert ParticleInitialization to a string representation.
Definition logging.c:703
PetscErrorCode InitializeBrownianRNG(SimCtx *simCtx)
Internal helper implementation: InitializeBrownianRNG().
Definition setup.c:2918
PetscBool RuntimeWalltimeGuardParsePositiveSeconds(const char *text, PetscReal *seconds_out)
Implementation of RuntimeWalltimeGuardParsePositiveSeconds().
Definition setup.c:18
LESModelType
Identifies the six logical faces of a structured computational block.
Definition variables.h:488
@ NO_LES_MODEL
Definition variables.h:489
PetscInt MHV
Definition variables.h:687
PetscInt turbine
Definition variables.h:687
PetscInt fishcyl
Definition variables.h:687
PetscInt clark
Definition variables.h:747
PetscInt movefsi
Definition variables.h:681
PetscBool continueMode
Definition variables.h:668
PetscInt moveframe
Definition variables.h:682
PetscInt TwoD
Definition variables.h:682
PetscInt pseudo_periodic
Definition variables.h:727
PetscInt fish_c
Definition variables.h:687
PetscInt dgf_z
Definition variables.h:683
PetscReal poisson_tol
Definition variables.h:696
PetscBool profilingFinalSummary
Definition variables.h:794
PetscReal schmidt_number
Definition variables.h:723
PetscMPIInt rank
Definition variables.h:654
char profilingTimestepFile[PETSC_MAX_PATH_LEN]
Definition variables.h:793
PetscInt fish
Definition variables.h:687
PetscInt LV
Definition variables.h:687
PetscReal angle
Definition variables.h:718
PetscReal Turbulent_schmidt_number
Definition variables.h:723
PetscInt64 searchLocatedCount
Definition variables.h:224
PetscInt thin
Definition variables.h:682
PetscInt grid1d
Definition variables.h:726
PetscReal mom_rtol
Definition variables.h:693
PetscInt64 searchLostCount
Definition variables.h:225
PetscInt da_procs_z
Definition variables.h:732
PetscInt blkpbc
Definition variables.h:727
PetscInt sediment
Definition variables.h:681
PetscReal targetVolumetricFlux
Definition variables.h:738
PetscBool walltimeGuardActive
Definition variables.h:796
PetscInt channelz
Definition variables.h:688
char euler_subdir[PETSC_MAX_PATH_LEN]
Definition variables.h:674
PetscReal walltimeGuardWarmupTotalSeconds
Definition variables.h:804
PetscReal forceScalingFactor
Definition variables.h:737
PetscReal pseudo_cfl_reduction_factor
Definition variables.h:700
PetscInt rans
Definition variables.h:746
ParticleInitializationType
Enumerator to identify the particle initialization strategy.
Definition variables.h:516
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
Definition variables.h:517
PetscReal StartTime
Definition variables.h:665
PetscInt dgf_az
Definition variables.h:683
PetscReal FluxOutSum
Definition variables.h:735
PetscBool walltimeGuardHasEWMA
Definition variables.h:806
PetscReal CMy_c
Definition variables.h:719
PetscBool runtimeMemoryLogEnabled
Enable the rank-reduced runtime memory log.
Definition variables.h:809
char ** bcs_files
Definition variables.h:734
PetscReal max_angle
Definition variables.h:718
PetscReal min_pseudo_cfl
Definition variables.h:701
PetscInt64 boundaryClampCount
Definition variables.h:231
PetscInt particlesLostLastStep
Definition variables.h:760
PetscInt duplicate
Definition variables.h:775
PetscInt tiout
Definition variables.h:663
PetscReal walltimeGuardMinSeconds
Definition variables.h:799
char allowedFile[PETSC_MAX_PATH_LEN]
Definition variables.h:779
PetscInt da_procs_y
Definition variables.h:732
PetscInt64 traversalStepsSum
Definition variables.h:226
PetscInt testfilter_1d
Definition variables.h:749
PetscReal psrc_x
Definition variables.h:720
PetscInt FieldInitialization
Definition variables.h:704
PetscReal ren
Definition variables.h:699
PetscReal Crotz
Definition variables.h:730
PetscInt mixed
Definition variables.h:747
IBMVNodes * ibmv
Definition variables.h:772
PetscInt64 searchPopulation
Definition variables.h:223
char output_dir[PETSC_MAX_PATH_LEN]
Definition variables.h:673
PetscReal walltimeGuardLatestStepSeconds
Definition variables.h:808
PetscReal dt
Definition variables.h:666
char runtimeMemoryLogFile[PETSC_MAX_PATH_LEN]
File name written under log_dir.
Definition variables.h:810
PetscBool runtimeMemoryLogStarted
True after rank 0 writes the log header.
Definition variables.h:811
PetscInt occupiedCellCount
Definition variables.h:764
PetscInt StepsToRun
Definition variables.h:662
char profilingTimestepMode[32]
Definition variables.h:792
PetscInt k_periodic
Definition variables.h:727
PetscInt inletprofile
Definition variables.h:726
PetscReal cdisy
Definition variables.h:699
PetscReal mom_atol
Definition variables.h:693
PetscBool rstart_fsi
Definition variables.h:774
PetscInt currentSettlementPass
Definition variables.h:235
PetscInt np
Definition variables.h:753
PetscBool averaging
Definition variables.h:750
PetscReal C_IEM
Definition variables.h:768
PetscInt ccc
Definition variables.h:742
PetscReal ratio
Definition variables.h:743
PetscInt mg_idx
Definition variables.h:694
PetscInt StartStep
Definition variables.h:661
PetscInt mg_MAX_IT
Definition variables.h:694
PetscBool OnlySetup
Definition variables.h:667
PetscInt rotatefsi
Definition variables.h:681
@ MOMENTUM_SOLVER_EXPLICIT_RK
Definition variables.h:503
@ MOMENTUM_SOLVER_DUALTIME_PICARD_RK4
Definition variables.h:504
PetscReal cdisz
Definition variables.h:699
PetscScalar x
Definition variables.h:101
PetscInt64 reSearchCount
Definition variables.h:227
PetscInt dgf_x
Definition variables.h:683
char * current_io_directory
Definition variables.h:678
PetscInt pizza
Definition variables.h:687
PetscReal MaxDiv
Definition variables.h:785
char grid_file[PETSC_MAX_PATH_LEN]
Definition variables.h:731
PetscReal max_cs
Definition variables.h:748
PetscInt invicid
Definition variables.h:682
char ** allowedFuncs
Definition variables.h:781
PetscInt64 bboxGuessFallbackCount
Definition variables.h:233
InterpolationMethod interpolationMethod
Definition variables.h:758
PetscReal psrc_z
Point source location for PARTICLE_INIT_POINT_SOURCE.
Definition variables.h:720
PetscInt mg_poItr
Definition variables.h:694
PetscInt STRONG_COUPLING
Definition variables.h:697
VerificationScalarConfig verificationScalar
Definition variables.h:714
PetscReal max_pseudo_cfl
Definition variables.h:701
PetscInt MaxDivx
Definition variables.h:786
PetscInt poisson
Definition variables.h:695
PetscInt k_homo_filter
Definition variables.h:749
char profilingSelectedFuncsFile[PETSC_MAX_PATH_LEN]
Definition variables.h:788
PetscInt MaxDivy
Definition variables.h:786
PetscInt NumberOfBodies
Definition variables.h:717
char particleRestartMode[16]
Definition variables.h:759
PetscInt Ogrid
Definition variables.h:726
PetscInt64 bboxGuessSuccessCount
Definition variables.h:232
char particle_subdir[PETSC_MAX_PATH_LEN]
Definition variables.h:675
PetscInt MaxDivz
Definition variables.h:786
BoundingBox * bboxlist
Definition variables.h:756
PetscInt j_homo_filter
Definition variables.h:749
PetscInt eel
Definition variables.h:687
char log_dir[PETSC_MAX_PATH_LEN]
Definition variables.h:676
PetscInt MaxDivFlatArg
Definition variables.h:786
PetscReal FluxInSum
Definition variables.h:735
PetscInt walltimeGuardCompletedSteps
Definition variables.h:803
PetscInt64 maxParticlePassDepth
Definition variables.h:234
PetscReal CMz_c
Definition variables.h:719
PetscInt64 maxTraversalSteps
Definition variables.h:228
PetscBool generate_grid
Definition variables.h:728
Cmpnts AnalyticalUniformVelocity
Definition variables.h:706
char eulerianSource[PETSC_MAX_PATH_LEN]
Definition variables.h:671
PetscReal imp_stol
Definition variables.h:693
PetscInt nAllowed
Definition variables.h:782
PetscBool walltimeGuardEnabled
Definition variables.h:795
PetscReal wall_roughness_height
Definition variables.h:722
PetscBool useProfilingSelectedFuncsCfg
Definition variables.h:789
PetscInt walltimeGuardWarmupSteps
Definition variables.h:797
ParticleInitializationType ParticleInitialization
Definition variables.h:757
PetscScalar z
Definition variables.h:101
InterpolationMethod
Selects the grid-to-particle interpolation method.
Definition variables.h:529
@ INTERP_TRILINEAR
Definition variables.h:530
PetscReal Const_CS
Definition variables.h:748
PetscInt i_homo_filter
Definition variables.h:749
PetscInt wallfunction
Definition variables.h:747
PetscInt rheology
Definition variables.h:681
PetscReal Flux_in
Definition variables.h:718
PetscBool runtimeMemoryLogHasPrevious
True after the first process-memory sample.
Definition variables.h:812
char ** profilingSelectedFuncs
Definition variables.h:790
PetscReal cdisx
Definition variables.h:699
PetscInt dgf_ax
Definition variables.h:683
PetscInt mglevels
Definition variables.h:694
PetscInt num_bcs_files
Definition variables.h:733
DM dm_swarm
Definition variables.h:755
PetscBool useCfg
Definition variables.h:780
PetscReal psrc_y
Definition variables.h:720
PetscBool readFields
Definition variables.h:754
PetscInt central
Definition variables.h:697
PetscReal Fluxsum
Definition variables.h:735
PetscReal pseudo_cfl_growth_factor
Definition variables.h:700
PetscReal Croty
Definition variables.h:730
PetscInt particlesLostCumulative
Definition variables.h:761
PetscInt nProfilingSelectedFuncs
Definition variables.h:791
PetscReal mom_dt_rk4_residual_norm_noise_allowance_factor
Definition variables.h:702
PetscInt particlesMigratedLastStep
Definition variables.h:763
PetscReal grid_rotation_angle
Definition variables.h:729
PetscInt dynamic_freq
Definition variables.h:747
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
Definition variables.h:684
PetscInt da_procs_x
Definition variables.h:732
PetscReal U_bc
Definition variables.h:741
PetscReal walltimeGuardWarmupAverageSeconds
Definition variables.h:805
PetscInt particleConsoleOutputFreq
Definition variables.h:664
Cmpnts InitialConstantContra
Definition variables.h:705
SearchMetricsState searchMetrics
Definition variables.h:766
PetscInt i_periodic
Definition variables.h:727
PetscReal runtimeMemoryLogPreviousProcessMB
Previous local process memory sample in MB.
Definition variables.h:813
PetscInt step
Definition variables.h:659
PetscReal walltimeGuardEWMASeconds
Definition variables.h:807
PetscReal AreaOutSum
Definition variables.h:740
PetscInt dgf_ay
Definition variables.h:683
PetscInt mom_max_pseudo_steps
Definition variables.h:692
PetscRandom BrownianMotionRNG
Definition variables.h:767
PetscInt testfilter_ik
Definition variables.h:749
PetscInt hydro
Definition variables.h:687
PostProcessParams * pps
Definition variables.h:817
PetscInt migrationPassesLastStep
Definition variables.h:762
PetscScalar y
Definition variables.h:101
PetscMPIInt size
Definition variables.h:655
char _io_context_buffer[PETSC_MAX_PATH_LEN]
Definition variables.h:677
PetscReal walltimeGuardLimitSeconds
Definition variables.h:802
PetscBool ps_ksp_pic_monitor_true_residual
Definition variables.h:703
PetscReal walltimeGuardEstimatorAlpha
Definition variables.h:800
PetscInt les
Definition variables.h:746
@ SOLUTION_CONVERGENCE_TRANSIENT
Definition variables.h:512
@ SOLUTION_CONVERGENCE_STEADY_DETERMINISTIC
Definition variables.h:509
PetscInt mg_preItr
Definition variables.h:694
PetscViewer logviewer
Definition variables.h:669
PetscInt64 searchAttempts
Definition variables.h:222
PetscInt64 tieBreakCount
Definition variables.h:230
PetscInt cop
Definition variables.h:687
PetscReal ti
Definition variables.h:660
PetscReal walltimeGuardMultiplier
Definition variables.h:798
PetscInt Pipe
Definition variables.h:687
PetscInt rotateframe
Definition variables.h:682
IBMNodes * ibm
Definition variables.h:771
PetscReal AreaInSum
Definition variables.h:740
MomentumSolverType mom_solver_type
Definition variables.h:691
PetscReal summationRHS
Definition variables.h:784
PetscInt immersed
Definition variables.h:681
PetscInt64 maxTraversalFailCount
Definition variables.h:229
char PostprocessingControlFile[PETSC_MAX_PATH_LEN]
Definition variables.h:816
char restart_dir[PETSC_MAX_PATH_LEN]
Definition variables.h:672
VerificationDiffusivityConfig verificationDiffusivity
Definition variables.h:713
PetscInt blank
Definition variables.h:682
PetscInt dgf_y
Definition variables.h:683
PetscReal walltimeGuardJobStartEpochSeconds
Definition variables.h:801
PetscReal pseudo_cfl
Definition variables.h:699
PetscInt LoggingFrequency
Definition variables.h:783
PetscReal CMx_c
Definition variables.h:719
PetscReal drivingForceMagnitude
Definition variables.h:737
PetscReal particleLoadImbalance
Definition variables.h:765
PetscInt j_periodic
Definition variables.h:727
PetscInt wing
Definition variables.h:687
FSInfo * fsi
Definition variables.h:773
The master context for the entire simulation.
Definition variables.h:651
Here is the call graph for this function:
Here is the caller graph for this function:

◆ PetscMkdirRecursive()

static PetscErrorCode PetscMkdirRecursive ( const char *  path)
static

Internal helper implementation: PetscMkdirRecursive().

Local to this translation unit.

Definition at line 909 of file setup.c.

910{
911 PetscErrorCode ierr;
912 char tmp_path[PETSC_MAX_PATH_LEN];
913 char *p = NULL;
914 size_t len;
915 PetscBool exists;
916
917 PetscFunctionBeginUser;
918
919 // Create a mutable copy of the path
920 len = strlen(path);
921 if (len >= sizeof(tmp_path)) {
922 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Path is too long to process: %s", path);
923 }
924 strcpy(tmp_path, path);
925
926 // If the path ends with a separator, remove it
927 if (tmp_path[len - 1] == '/') {
928 tmp_path[len - 1] = 0;
929 }
930
931 // Iterate through the path, creating each directory level
932 for (p = tmp_path + 1; *p; p++) {
933 if (*p == '/') {
934 *p = 0; // Temporarily terminate the string
935
936 // Check if this directory level exists
937 ierr = PetscTestDirectory(tmp_path, 'r', &exists); CHKERRQ(ierr);
938 if (!exists) {
939 ierr = PetscMkdir(tmp_path); CHKERRQ(ierr);
940 }
941
942 *p = '/'; // Restore the separator
943 }
944 }
945
946 // Create the final, full directory path
947 ierr = PetscTestDirectory(tmp_path, 'r', &exists); CHKERRQ(ierr);
948 if (!exists) {
949 ierr = PetscMkdir(tmp_path); CHKERRQ(ierr);
950 }
951
952 PetscFunctionReturn(0);
953}
Here is the caller graph for this function:

◆ SetupSimulationEnvironment()

PetscErrorCode SetupSimulationEnvironment ( SimCtx simCtx)

Internal helper implementation: SetupSimulationEnvironment().

Verifies and prepares the complete I/O environment for a simulation run.

Local to this translation unit.

Definition at line 961 of file setup.c.

962{
963 PetscErrorCode ierr;
964 PetscMPIInt rank;
965 PetscBool exists;
966
967 PetscFunctionBeginUser;
968 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
969
970 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Setting up simulation environment ---\n");
971
972 /* =====================================================================
973 * Phase 1: Check for all required and optional INPUT files.
974 * ===================================================================== */
975 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Phase 1: Verifying input files...\n");
976
977 // --- Mandatory Inputs ---
978 if (!simCtx->generate_grid) {
979 ierr = VerifyPathExistence(simCtx->grid_file, PETSC_FALSE, PETSC_FALSE, "Grid file", &exists); CHKERRQ(ierr);
980 }
981 for (PetscInt i = 0; i < simCtx->num_bcs_files; i++) {
982 char desc[128];
983 ierr = PetscSNPrintf(desc, sizeof(desc), "BCS file #%d", i + 1); CHKERRQ(ierr);
984 ierr = VerifyPathExistence(simCtx->bcs_files[i], PETSC_FALSE, PETSC_FALSE, desc, &exists); CHKERRQ(ierr);
985 }
986
987 // --- Optional Inputs (these produce warnings if missing) ---
988 if (simCtx->useCfg) {
989 ierr = VerifyPathExistence(simCtx->allowedFile, PETSC_FALSE, PETSC_TRUE, "Whitelist config file", &exists); CHKERRQ(ierr);
990 }
991 if (simCtx->useProfilingSelectedFuncsCfg) {
992 ierr = VerifyPathExistence(simCtx->profilingSelectedFuncsFile, PETSC_FALSE, PETSC_TRUE, "Profiling config file", &exists); CHKERRQ(ierr);
993 }
994 if (simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR) {
995 ierr = VerifyPathExistence(simCtx->PostprocessingControlFile, PETSC_FALSE, PETSC_TRUE, "Post-processing control file", &exists); CHKERRQ(ierr);
996 }
997
998
999 /* =====================================================================
1000 * Phase 2: Validate directories specific to the execution mode.
1001 * ===================================================================== */
1002 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Phase 2: Verifying execution mode directories...\n");
1003 // The data source directory must exist if we intend to load any data from it.
1004 // This is true if:
1005 // 1. We are restarting from a previous time step (StartStep > 0), which implies
1006 // loading Eulerian fields and/or particle fields.
1007 // 2. We are starting from t=0 but are explicitly told to load the initial
1008 // Eulerian fields from a file (eulerianSource == "load").
1009 if (simCtx->StartStep > 0 || strcmp(simCtx->eulerianSource,"load")== 0){ // If this is a restart run
1010 ierr = VerifyPathExistence(simCtx->restart_dir, PETSC_TRUE, PETSC_FALSE, "Restart source directory", &exists); CHKERRQ(ierr);
1011 }
1012 if (simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR) {
1013 ierr = VerifyPathExistence(simCtx->pps->source_dir, PETSC_TRUE, PETSC_FALSE, "Post-processing source directory", &exists); CHKERRQ(ierr);
1014 }
1015
1016 /* =====================================================================
1017 * Phase 3: Create and prepare all OUTPUT directories.
1018 * ===================================================================== */
1019 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Phase 3: Preparing output directories...\n");
1020
1021 if (rank == 0){
1022 if(simCtx->exec_mode == EXEC_MODE_SOLVER){
1023 // --- Prepare Log Directory ---
1024 if (!simCtx->continueMode) {
1025 // Only wipe logs on fresh runs; continue mode appends to existing logs.
1026 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Creating/cleaning log directory: %s\n", simCtx->log_dir);
1027 ierr = PetscRMTree(simCtx->log_dir); // Wipes the directory and its contents
1028 if (ierr) { /* Ignore file-not-found error, but fail on others */
1029 PetscError(PETSC_COMM_SELF, __LINE__, __FUNCT__, __FILE__, ierr, PETSC_ERROR_INITIAL, "Could not remove existing log directory '%s'. Check permissions.", simCtx->log_dir);
1030 }
1031 ierr = PetscMkdir(simCtx->log_dir); CHKERRQ(ierr);
1032 } else {
1033 // In continue mode, ensure log directory exists but don't wipe it.
1034 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Continue mode: preserving existing log directory: %s\n", simCtx->log_dir);
1035 ierr = PetscMkdir(simCtx->log_dir); CHKERRQ(ierr);
1036 }
1037
1038 // --- Prepare Output Directories ---
1039 char path_buffer[PETSC_MAX_PATH_LEN];
1040
1041 // 1. Check/Create the main output directory
1042 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Verifying main output directory: %s\n", simCtx->output_dir);
1043 ierr = PetscTestDirectory(simCtx->output_dir, 'r', &exists); CHKERRQ(ierr);
1044 if (!exists) {
1045 LOG_ALLOW(GLOBAL, LOG_INFO, "Output directory not found. Creating: %s\n", simCtx->output_dir);
1046 ierr = PetscMkdir(simCtx->output_dir); CHKERRQ(ierr);
1047 }
1048
1049 // 2. Check/Create the Eulerian subdirectory
1050 ierr = PetscSNPrintf(path_buffer, sizeof(path_buffer), "%s/%s", simCtx->output_dir, simCtx->euler_subdir); CHKERRQ(ierr);
1051 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Verifying Eulerian subdirectory: %s\n", path_buffer);
1052 ierr = PetscTestDirectory(path_buffer, 'r', &exists); CHKERRQ(ierr);
1053 if (!exists) {
1054 LOG_ALLOW(GLOBAL, LOG_INFO, "Eulerian subdirectory not found. Creating: %s\n", path_buffer);
1055 ierr = PetscMkdir(path_buffer); CHKERRQ(ierr);
1056 }
1057
1058 // 3. Check/Create the Particle subdirectory if needed
1059 if (simCtx->np > 0) {
1060 ierr = PetscSNPrintf(path_buffer, sizeof(path_buffer), "%s/%s", simCtx->output_dir, simCtx->particle_subdir); CHKERRQ(ierr);
1061 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Verifying Particle subdirectory: %s\n", path_buffer);
1062 ierr = PetscTestDirectory(path_buffer, 'r', &exists); CHKERRQ(ierr);
1063 if (!exists) {
1064 LOG_ALLOW(GLOBAL, LOG_INFO, "Particle subdirectory not found. Creating: %s\n", path_buffer);
1065 ierr = PetscMkdir(path_buffer); CHKERRQ(ierr);
1066 }
1067 }
1068 } else if(simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR){
1069 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Preparing post-processing output directories ...\n");
1070
1071 PostProcessParams *pps = simCtx->pps;
1072 char path_buffer[PETSC_MAX_PATH_LEN];
1073
1074 const char *last_slash_euler = strrchr(pps->output_prefix, '/');
1075 if(last_slash_euler){
1076 size_t dir_len = last_slash_euler - pps->output_prefix;
1077 if(dir_len > 0){
1078 if(dir_len >= sizeof(path_buffer)) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Post-processing output prefix path is too long.");
1079 strncpy(path_buffer, pps->output_prefix, dir_len);
1080 path_buffer[dir_len] = '\0';
1081
1082 ierr = PetscTestDirectory(path_buffer, 'r', &exists); CHKERRQ(ierr);
1083 if (!exists){
1084 LOG_ALLOW(GLOBAL, LOG_INFO, "Creating post-processing Eulerian output directory: %s\n", path_buffer);
1085 ierr = PetscMkdirRecursive(path_buffer); CHKERRQ(ierr);
1086 }
1087 }
1088 }
1089
1090 // Particle output directory
1091 if(pps->outputParticles){
1092 const char *last_slash_particle = strrchr(pps->particle_output_prefix, '/');
1093 if(last_slash_particle){
1094 size_t dir_len = last_slash_particle - pps->particle_output_prefix;
1095 if(dir_len > 0){
1096 if(dir_len > sizeof(path_buffer)) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Post-processing particle output prefix path is too long.");
1097 strncpy(path_buffer, pps->particle_output_prefix, dir_len);
1098 path_buffer[dir_len] = '\0';
1099
1100 ierr = PetscTestDirectory(path_buffer, 'r', &exists); CHKERRQ(ierr);
1101
1102 if (!exists){
1103 LOG_ALLOW(GLOBAL, LOG_INFO, "Creating post-processing Particle output directory: %s\n", path_buffer);
1104 ierr = PetscMkdirRecursive(path_buffer); CHKERRQ(ierr);
1105 }
1106 }
1107 }
1108 }
1109
1110 // Statistics output directory
1111 if(pps->statistics_pipeline[0] != '\0'){
1112 const char *last_slash_stats = strrchr(pps->statistics_output_prefix, '/');
1113 if(last_slash_stats){
1114 size_t dir_len = last_slash_stats - pps->statistics_output_prefix;
1115 if(dir_len > 0){
1116 if(dir_len >= sizeof(path_buffer)) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Post-processing statistics output prefix path is too long.");
1117 strncpy(path_buffer, pps->statistics_output_prefix, dir_len);
1118 path_buffer[dir_len] = '\0';
1119
1120 ierr = PetscTestDirectory(path_buffer, 'r', &exists); CHKERRQ(ierr);
1121 if (!exists){
1122 LOG_ALLOW(GLOBAL, LOG_INFO, "Creating post-processing Statistics output directory: %s\n", path_buffer);
1123 ierr = PetscMkdirRecursive(path_buffer); CHKERRQ(ierr);
1124 }
1125 }
1126 }
1127 }
1128 }
1129 }
1130
1131 // Synchronize all processes before proceeding
1132 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRMPI(ierr);
1133
1134 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Environment setup complete ---\n");
1135
1136 PetscFunctionReturn(0);
1137}
PetscErrorCode VerifyPathExistence(const char *path, PetscBool is_dir, PetscBool is_optional, const char *description, PetscBool *exists)
A parallel-safe helper to verify the existence of a generic file or directory path.
Definition io.c:741
static PetscErrorCode PetscMkdirRecursive(const char *path)
Internal helper implementation: PetscMkdirRecursive().
Definition setup.c:909
#define __FUNCT__
Definition setup.c:143
char statistics_output_prefix[256]
basename for CSV output, e.g.
Definition variables.h:583
char particle_output_prefix[256]
Definition variables.h:578
char output_prefix[256]
Definition variables.h:575
char statistics_pipeline[1024]
e.g.
Definition variables.h:582
char source_dir[PETSC_MAX_PATH_LEN]
Definition variables.h:563
PetscBool outputParticles
Definition variables.h:569
@ EXEC_MODE_POSTPROCESSOR
Definition variables.h:625
Holds all configuration parameters for a post-processing run.
Definition variables.h:561
Here is the call graph for this function:
Here is the caller graph for this function:

◆ AllocateContextHierarchy()

static PetscErrorCode AllocateContextHierarchy ( SimCtx simCtx)
static

Internal helper implementation: AllocateContextHierarchy().

Local to this translation unit.

Definition at line 1145 of file setup.c.

1146{
1147 PetscErrorCode ierr;
1148 UserMG *usermg = &simCtx->usermg;
1149 MGCtx *mgctx;
1150 PetscInt nblk = simCtx->block_number;
1151 PetscBool found;
1152 PetscFunctionBeginUser;
1154
1155 LOG_ALLOW(GLOBAL, LOG_INFO, "Allocating context hierarchy for %d levels and %d blocks...\n", simCtx->mglevels, nblk);
1156
1157 // Store the number of levels in the UserMG struct itself
1158 usermg->mglevels = simCtx->mglevels;
1159
1160 // --- 1. Allocate the array of MGCtx structs ---
1161 ierr = PetscMalloc(usermg->mglevels * sizeof(MGCtx), &usermg->mgctx); CHKERRQ(ierr);
1162 // Zero-initialize to ensure all pointers (especially packer) are NULL
1163 ierr = PetscMemzero(usermg->mgctx, usermg->mglevels * sizeof(MGCtx)); CHKERRQ(ierr);
1164 mgctx = usermg->mgctx;
1165 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Allocated MGCtx array of size %d.\n", simCtx->rank, usermg->mglevels);
1166
1167 // --- 2. Parse semi-coarsening options (logic from MG_Initial) ---
1168 // These flags determine if a dimension is coarsened in the multigrid hierarchy.
1169 PetscInt *isc, *jsc, *ksc;
1170 ierr = PetscMalloc3(nblk, &isc, nblk, &jsc, nblk, &ksc); CHKERRQ(ierr);
1171 // Set defaults to FALSE (full coarsening)
1172 for (PetscInt i = 0; i < nblk; ++i) {
1173 isc[i] = 0; jsc[i] = 0; ksc[i] = 0;
1174 }
1175
1176// Use a temporary variable for the 'count' argument to the parsing function.
1177 // This protects the original 'nblk' which is needed for the loop bounds.
1178 PetscInt n_opts_found = nblk;
1179 ierr = PetscOptionsGetIntArray(NULL, NULL, "-mg_i_semi", isc, &n_opts_found, &found); CHKERRQ(ierr);
1180
1181 n_opts_found = nblk; // Reset the temp variable before the next call
1182 ierr = PetscOptionsGetIntArray(NULL, NULL, "-mg_j_semi", jsc, &n_opts_found, &found); CHKERRQ(ierr);
1183
1184 n_opts_found = nblk; // Reset the temp variable before the next call
1185 ierr = PetscOptionsGetIntArray(NULL, NULL, "-mg_k_semi", ksc, &n_opts_found, &found); CHKERRQ(ierr);
1186
1187 // --- 3. Loop over levels and blocks to allocate UserCtx arrays ---
1188 for (PetscInt level = 0; level < simCtx->mglevels; level++) {
1189
1190 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Setting up MG Level %d...\n", simCtx->rank, level);
1191 // Allocate the array of UserCtx structs for this level
1192 ierr = PetscMalloc(nblk * sizeof(UserCtx), &mgctx[level].user); CHKERRQ(ierr);
1193 // It's good practice to zero out the memory to avoid uninitialized values
1194 ierr = PetscMemzero(mgctx[level].user, nblk * sizeof(UserCtx)); CHKERRQ(ierr);
1195 mgctx[level].thislevel = level;
1196
1197 for (PetscInt bi = 0; bi < nblk; bi++) {
1198 UserCtx *currentUser = &mgctx[level].user[bi];
1199 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Initializing UserCtx for Level %d, Block %d.\n", simCtx->rank, level, bi);
1200
1201 // --- CRITICAL STEP: Set the back-pointer to the master context ---
1202 currentUser->simCtx = simCtx;
1203
1204 // Initialize other per-context values
1205 currentUser->thislevel = level;
1206 currentUser->_this = bi; //
1207 currentUser->mglevels = usermg->mglevels;
1208
1209 // Assign semi-coarsening flags
1210 currentUser->isc = isc[bi];
1211 currentUser->jsc = jsc[bi];
1212 currentUser->ksc = ksc[bi];
1213
1214 // Link to finer/coarser contexts for multigrid operations
1215 if (level > 0) {
1216 currentUser->user_c = &mgctx[level-1].user[bi];
1217 LOG_ALLOW_SYNC(GLOBAL, LOG_DEBUG, "Rank %d: -> Linked to coarser context (user_c).\n", simCtx->rank);
1218 }
1219 if (level < usermg->mglevels - 1) {
1220 currentUser->user_f = &mgctx[level+1].user[bi];
1221 LOG_ALLOW_SYNC(GLOBAL, LOG_DEBUG, "Rank %d: -> Linked to finer context (user_f).\n", simCtx->rank);
1222 }
1223 }
1224 }
1225
1226 // Log a summary of the parsed flags on each rank.
1227 if (get_log_level() >= LOG_DEBUG && nblk > 0) {
1228 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Final semi-coarsening configuration view:\n", simCtx->rank);
1229 for (PetscInt bi = 0; bi < nblk; ++bi) {
1230 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Block %d: i-semi=%d, j-semi=%d, k-semi=%d\n", simCtx->rank, bi, isc[bi], jsc[bi], ksc[bi]);
1231 }
1232 }
1233
1234 // Clean up temporary arrays
1235 ierr = PetscFree3(isc, jsc, ksc); CHKERRQ(ierr);
1236
1237 LOG_ALLOW(GLOBAL, LOG_INFO, "Context hierarchy allocation complete.\n");
1239 PetscFunctionReturn(0);
1240}
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:84
PetscInt isc
Definition variables.h:843
PetscInt mglevels
Definition variables.h:895
UserCtx * user_f
Definition variables.h:896
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:833
PetscInt ksc
Definition variables.h:843
PetscInt _this
Definition variables.h:843
PetscInt jsc
Definition variables.h:843
PetscInt thislevel
Definition variables.h:537
UserCtx * user_c
Definition variables.h:896
PetscInt thislevel
Definition variables.h:895
Context for Multigrid operations.
Definition variables.h:535
User-level context for managing the entire multigrid hierarchy.
Definition variables.h:542
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetupSolverParameters()

static PetscErrorCode SetupSolverParameters ( SimCtx simCtx)
static

Internal helper implementation: SetupSolverParameters().

Local to this translation unit.

Definition at line 1248 of file setup.c.

1248 {
1249
1250 PetscFunctionBeginUser;
1252
1253 LOG_ALLOW(GLOBAL,LOG_INFO, " -- Setting up solver parameters -- .\n");
1254
1255 UserMG *usermg = &simCtx->usermg;
1256 MGCtx *mgctx = usermg->mgctx;
1257 PetscInt nblk = simCtx->block_number;
1258
1259 for (PetscInt level = usermg->mglevels-1; level >=0; level--) {
1260 for (PetscInt bi = 0; bi < nblk; bi++) {
1261 UserCtx *user = &mgctx[level].user[bi];
1262 LOG_ALLOW_SYNC(LOCAL, LOG_DEBUG, "Rank %d: Setting up parameters for level %d, block %d\n", simCtx->rank, level, bi);
1263
1264 user->assignedA = PETSC_FALSE;
1265 user->multinullspace = PETSC_FALSE;
1266 }
1267 }
1269 PetscFunctionReturn(0);
1270}
PetscBool assignedA
Definition variables.h:875
PetscBool multinullspace
Definition variables.h:872
Here is the caller graph for this function:

◆ SetupGridAndSolvers()

PetscErrorCode SetupGridAndSolvers ( SimCtx simCtx)

Implementation of SetupGridAndSolvers().

The main orchestrator for setting up all grid-related components.

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

See also
SetupGridAndSolvers()

Definition at line 1280 of file setup.c.

1281{
1282 PetscErrorCode ierr;
1283 PetscFunctionBeginUser;
1284
1286
1287 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Starting Grid and Solvers Setup ---\n");
1288
1289 // Phase 1: Allocate the UserMG and UserCtx hierarchy
1290 ierr = AllocateContextHierarchy(simCtx); CHKERRQ(ierr);
1291
1292 ierr = DefineAllGridDimensions(simCtx); CHKERRQ(ierr);
1293 ierr = InitializeAllGridDMs(simCtx); CHKERRQ(ierr);
1294 ierr = AssignAllGridCoordinates(simCtx);
1295 ierr = CreateAndInitializeAllVectors(simCtx); CHKERRQ(ierr);
1296 ierr = SetupSolverParameters(simCtx); CHKERRQ(ierr);
1297 ierr = InitializeSolutionConvergenceState(simCtx); CHKERRQ(ierr);
1298
1299 // NOTE: CalculateAllGridMetrics is now called inside SetupBoundaryConditions (not here) to ensure:
1300 // 1. Boundary condition configuration data (boundary_faces) is available for periodic BC corrections
1301 // 2. Computed metrics are available for inlet/outlet area calculations
1302 // This resolves the circular dependency between BC setup and metric calculations.
1303
1304 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Grid and Solvers Setup Complete ---\n");
1305
1307 PetscFunctionReturn(0);
1308}
PetscErrorCode DefineAllGridDimensions(SimCtx *simCtx)
Orchestrates the parsing and setting of grid dimensions for all blocks.
Definition grid.c:57
PetscErrorCode InitializeAllGridDMs(SimCtx *simCtx)
Orchestrates the creation of DMDA objects for every block and multigrid level.
Definition grid.c:235
PetscErrorCode AssignAllGridCoordinates(SimCtx *simCtx)
Orchestrates the assignment of physical coordinates to all DMDA objects.
Definition grid.c:317
static PetscErrorCode SetupSolverParameters(SimCtx *simCtx)
Internal helper implementation: SetupSolverParameters().
Definition setup.c:1248
PetscErrorCode CreateAndInitializeAllVectors(SimCtx *simCtx)
Internal helper implementation: CreateAndInitializeAllVectors().
Definition setup.c:1317
PetscErrorCode InitializeSolutionConvergenceState(SimCtx *simCtx)
Implementation of InitializeSolutionConvergenceState().
Definition setup.c:47
static PetscErrorCode AllocateContextHierarchy(SimCtx *simCtx)
Internal helper implementation: AllocateContextHierarchy().
Definition setup.c:1145
Here is the call graph for this function:
Here is the caller graph for this function:

◆ CreateAndInitializeAllVectors()

PetscErrorCode CreateAndInitializeAllVectors ( SimCtx simCtx)

Internal helper implementation: CreateAndInitializeAllVectors().

Creates and initializes all PETSc Vec objects for all fields.

Local to this translation unit.

Definition at line 1317 of file setup.c.

1318{
1319 PetscErrorCode ierr;
1320 UserMG *usermg = &simCtx->usermg;
1321 MGCtx *mgctx = usermg->mgctx;
1322 PetscInt nblk = simCtx->block_number;
1323
1324 PetscFunctionBeginUser;
1325
1327
1328 LOG_ALLOW(GLOBAL, LOG_INFO, "Creating and initializing all simulation vectors...\n");
1329
1330 for (PetscInt level = usermg->mglevels-1; level >=0; level--) {
1331 for (PetscInt bi = 0; bi < nblk; bi++) {
1332 UserCtx *user = &mgctx[level].user[bi];
1333
1334 if(!user->da || !user->fda) {
1335 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "DMs not properly initialized in UserCtx before vector creation.");
1336 }
1337
1338 LOG_ALLOW_SYNC(LOCAL, LOG_DEBUG, "Rank %d: Creating vectors for level %d, block %d\n", simCtx->rank, level, bi);
1339
1340 // --- Group A: Primary Flow Fields (Global and Local) ---
1341 // These are the core solution variables.
1342 ierr = DMCreateGlobalVector(user->fda, &user->Ucont); CHKERRQ(ierr); ierr = VecSet(user->Ucont, 0.0); CHKERRQ(ierr);
1343 ierr = DMCreateGlobalVector(user->fda, &user->Ucat); CHKERRQ(ierr); ierr = VecSet(user->Ucat, 0.0); CHKERRQ(ierr);
1344 ierr = DMCreateGlobalVector(user->da, &user->P); CHKERRQ(ierr); ierr = VecSet(user->P, 0.0); CHKERRQ(ierr);
1345 ierr = DMCreateGlobalVector(user->da, &user->Nvert); CHKERRQ(ierr); ierr = VecSet(user->Nvert, 0.0); CHKERRQ(ierr);
1346
1347 ierr = DMCreateLocalVector(user->fda, &user->lUcont); CHKERRQ(ierr); ierr = VecSet(user->lUcont, 0.0); CHKERRQ(ierr);
1348 ierr = DMCreateLocalVector(user->fda, &user->lUcat); CHKERRQ(ierr); ierr = VecSet(user->lUcat, 0.0); CHKERRQ(ierr);
1349 ierr = DMCreateLocalVector(user->da, &user->lP); CHKERRQ(ierr); ierr = VecSet(user->lP, 0.0); CHKERRQ(ierr);
1350 ierr = DMCreateLocalVector(user->da, &user->lNvert); CHKERRQ(ierr); ierr = VecSet(user->lNvert, 0.0); CHKERRQ(ierr);
1351
1352 // -- Group A2: Derived Flow Fields (Global and Local) ---
1353 ierr = VecDuplicate(user->P,&user->Diffusivity); CHKERRQ(ierr); ierr = VecSet(user->Diffusivity, 0.0); CHKERRQ(ierr);
1354 ierr = VecDuplicate(user->lP,&user->lDiffusivity); CHKERRQ(ierr); ierr = VecSet(user->lDiffusivity, 0.0); CHKERRQ(ierr);
1355 ierr = VecDuplicate(user->Ucat,&user->DiffusivityGradient); CHKERRQ(ierr); ierr = VecSet(user->DiffusivityGradient, 0.0); CHKERRQ(ierr);
1356 ierr = VecDuplicate(user->lUcat,&user->lDiffusivityGradient); CHKERRQ(ierr); ierr = VecSet(user->lDiffusivityGradient, 0.0); CHKERRQ(ierr);
1357
1358 // -- Group B: Solver Work Vectors (Global and Local) ---
1359 ierr = VecDuplicate(user->P, &user->Phi); CHKERRQ(ierr); ierr = VecSet(user->Phi, 0.0); CHKERRQ(ierr);
1360 ierr = VecDuplicate(user->lP, &user->lPhi); CHKERRQ(ierr); ierr = VecSet(user->lPhi, 0.0); CHKERRQ(ierr);
1361
1362 // --- Group C: Time-Stepping & Workspace Fields (Finest Level Only) ---
1363 if (level == usermg->mglevels - 1) {
1364 ierr = VecDuplicate(user->Ucont, &user->Ucont_o); CHKERRQ(ierr); ierr = VecSet(user->Ucont_o, 0.0); CHKERRQ(ierr);
1365 ierr = VecDuplicate(user->Ucont, &user->Ucont_rm1); CHKERRQ(ierr); ierr = VecSet(user->Ucont_rm1, 0.0); CHKERRQ(ierr);
1366 ierr = VecDuplicate(user->Ucat, &user->Ucat_o); CHKERRQ(ierr); ierr = VecSet(user->Ucat_o, 0.0); CHKERRQ(ierr);
1367 ierr = VecDuplicate(user->P, &user->P_o); CHKERRQ(ierr); ierr = VecSet(user->P_o, 0.0); CHKERRQ(ierr);
1368 ierr = VecDuplicate(user->lUcont, &user->lUcont_o); CHKERRQ(ierr); ierr = VecSet(user->lUcont_o, 0.0); CHKERRQ(ierr);
1369 ierr = VecDuplicate(user->lUcont, &user->lUcont_rm1); CHKERRQ(ierr); ierr = VecSet(user->lUcont_rm1, 0.0); CHKERRQ(ierr);
1370 ierr = DMCreateLocalVector(user->da, &user->lNvert_o); CHKERRQ(ierr); ierr = VecSet(user->lNvert_o, 0.0); CHKERRQ(ierr);
1371 ierr = VecDuplicate(user->Nvert, &user->Nvert_o); CHKERRQ(ierr); ierr = VecSet(user->Nvert_o, 0.0); CHKERRQ(ierr);
1372 }
1373
1374 // --- Group D: Grid Metrics (Face-Centered) ---
1375 ierr = DMCreateGlobalVector(user->fda, &user->Csi); CHKERRQ(ierr); ierr = VecSet(user->Csi, 0.0); CHKERRQ(ierr);
1376 ierr = VecDuplicate(user->Csi, &user->Eta); CHKERRQ(ierr); ierr = VecSet(user->Eta, 0.0); CHKERRQ(ierr);
1377 ierr = VecDuplicate(user->Csi, &user->Zet); CHKERRQ(ierr); ierr = VecSet(user->Zet, 0.0); CHKERRQ(ierr);
1378 ierr = DMCreateGlobalVector(user->da, &user->Aj); CHKERRQ(ierr); ierr = VecSet(user->Aj, 0.0); CHKERRQ(ierr);
1379
1380 ierr = DMCreateLocalVector(user->fda, &user->lCsi); CHKERRQ(ierr); ierr = VecSet(user->lCsi, 0.0); CHKERRQ(ierr);
1381 ierr = VecDuplicate(user->lCsi, &user->lEta); CHKERRQ(ierr); ierr = VecSet(user->lEta, 0.0); CHKERRQ(ierr);
1382 ierr = VecDuplicate(user->lCsi, &user->lZet); CHKERRQ(ierr); ierr = VecSet(user->lZet, 0.0); CHKERRQ(ierr);
1383 ierr = DMCreateLocalVector(user->da, &user->lAj); CHKERRQ(ierr); ierr = VecSet(user->lAj, 0.0); CHKERRQ(ierr);
1384
1385
1386 // --- Group E: Grid Metrics (Face-Centered) ---
1387 // Vector metrics are duplicated from Csi (DOF=3, fda-based)
1388 ierr = VecDuplicate(user->Csi, &user->ICsi); CHKERRQ(ierr); ierr = VecSet(user->ICsi, 0.0); CHKERRQ(ierr);
1389 ierr = VecDuplicate(user->Csi, &user->IEta); CHKERRQ(ierr); ierr = VecSet(user->IEta, 0.0); CHKERRQ(ierr);
1390 ierr = VecDuplicate(user->Csi, &user->IZet); CHKERRQ(ierr); ierr = VecSet(user->IZet, 0.0); CHKERRQ(ierr);
1391 ierr = VecDuplicate(user->Csi, &user->JCsi); CHKERRQ(ierr); ierr = VecSet(user->JCsi, 0.0); CHKERRQ(ierr);
1392 ierr = VecDuplicate(user->Csi, &user->JEta); CHKERRQ(ierr); ierr = VecSet(user->JEta, 0.0); CHKERRQ(ierr);
1393 ierr = VecDuplicate(user->Csi, &user->JZet); CHKERRQ(ierr); ierr = VecSet(user->JZet, 0.0); CHKERRQ(ierr);
1394 ierr = VecDuplicate(user->Csi, &user->KCsi); CHKERRQ(ierr); ierr = VecSet(user->KCsi, 0.0); CHKERRQ(ierr);
1395 ierr = VecDuplicate(user->Csi, &user->KEta); CHKERRQ(ierr); ierr = VecSet(user->KEta, 0.0); CHKERRQ(ierr);
1396 ierr = VecDuplicate(user->Csi, &user->KZet); CHKERRQ(ierr); ierr = VecSet(user->KZet, 0.0); CHKERRQ(ierr);
1397 // Scalar metrics are duplicated from Aj (DOF=1, da-based)
1398 ierr = VecDuplicate(user->Aj, &user->IAj); CHKERRQ(ierr); ierr = VecSet(user->IAj, 0.0); CHKERRQ(ierr);
1399 ierr = VecDuplicate(user->Aj, &user->JAj); CHKERRQ(ierr); ierr = VecSet(user->JAj, 0.0); CHKERRQ(ierr);
1400 ierr = VecDuplicate(user->Aj, &user->KAj); CHKERRQ(ierr); ierr = VecSet(user->KAj, 0.0); CHKERRQ(ierr);
1401
1402 ierr = VecDuplicate(user->lCsi, &user->lICsi); CHKERRQ(ierr); ierr = VecSet(user->lICsi, 0.0); CHKERRQ(ierr);
1403 ierr = VecDuplicate(user->lCsi, &user->lIEta); CHKERRQ(ierr); ierr = VecSet(user->lIEta, 0.0); CHKERRQ(ierr);
1404 ierr = VecDuplicate(user->lCsi, &user->lIZet); CHKERRQ(ierr); ierr = VecSet(user->lIZet, 0.0); CHKERRQ(ierr);
1405 ierr = VecDuplicate(user->lCsi, &user->lJCsi); CHKERRQ(ierr); ierr = VecSet(user->lJCsi, 0.0); CHKERRQ(ierr);
1406 ierr = VecDuplicate(user->lCsi, &user->lJEta); CHKERRQ(ierr); ierr = VecSet(user->lJEta, 0.0); CHKERRQ(ierr);
1407 ierr = VecDuplicate(user->lCsi, &user->lJZet); CHKERRQ(ierr); ierr = VecSet(user->lJZet, 0.0); CHKERRQ(ierr);
1408 ierr = VecDuplicate(user->lCsi, &user->lKCsi); CHKERRQ(ierr); ierr = VecSet(user->lKCsi, 0.0); CHKERRQ(ierr);
1409 ierr = VecDuplicate(user->lCsi, &user->lKEta); CHKERRQ(ierr); ierr = VecSet(user->lKEta, 0.0); CHKERRQ(ierr);
1410 ierr = VecDuplicate(user->lCsi, &user->lKZet); CHKERRQ(ierr); ierr = VecSet(user->lKZet, 0.0); CHKERRQ(ierr);
1411
1412 ierr = VecDuplicate(user->lAj, &user->lIAj); CHKERRQ(ierr); ierr = VecSet(user->lIAj, 0.0); CHKERRQ(ierr);
1413 ierr = VecDuplicate(user->lAj, &user->lJAj); CHKERRQ(ierr); ierr = VecSet(user->lJAj, 0.0); CHKERRQ(ierr);
1414 ierr = VecDuplicate(user->lAj, &user->lKAj); CHKERRQ(ierr); ierr = VecSet(user->lKAj, 0.0); CHKERRQ(ierr);
1415
1416 // --- Group F: Cell/Face Center Coordinates and Grid Spacing ---
1417 ierr = DMCreateGlobalVector(user->fda, &user->Cent); CHKERRQ(ierr); ierr = VecSet(user->Cent, 0.0); CHKERRQ(ierr);
1418 ierr = DMCreateLocalVector(user->fda, &user->lCent); CHKERRQ(ierr); ierr = VecSet(user->lCent, 0.0); CHKERRQ(ierr);
1419
1420 ierr = VecDuplicate(user->Cent, &user->GridSpace); CHKERRQ(ierr); ierr = VecSet(user->GridSpace, 0.0); CHKERRQ(ierr);
1421 ierr = VecDuplicate(user->lCent, &user->lGridSpace); CHKERRQ(ierr); ierr = VecSet(user->lGridSpace, 0.0); CHKERRQ(ierr);
1422
1423 // Face-center coordinate vectors are LOCAL to hold calculated values before scattering
1424 ierr = VecDuplicate(user->lCent, &user->Centx); CHKERRQ(ierr); ierr = VecSet(user->Centx, 0.0); CHKERRQ(ierr);
1425 ierr = VecDuplicate(user->lCent, &user->Centy); CHKERRQ(ierr); ierr = VecSet(user->Centy, 0.0); CHKERRQ(ierr);
1426 ierr = VecDuplicate(user->lCent, &user->Centz); CHKERRQ(ierr); ierr = VecSet(user->Centz, 0.0); CHKERRQ(ierr);
1427
1428 if(level == usermg->mglevels -1){
1429 // --- Group G: Turbulence Models (Finest Level Only) ---
1430 if (simCtx->les || simCtx->rans) {
1431 ierr = DMCreateGlobalVector(user->da, &user->Nu_t); CHKERRQ(ierr); ierr = VecSet(user->Nu_t, 0.0); CHKERRQ(ierr);
1432 ierr = DMCreateLocalVector(user->da, &user->lNu_t); CHKERRQ(ierr); ierr = VecSet(user->lNu_t, 0.0); CHKERRQ(ierr);
1433 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Turbulence viscosity (Nu_t) vectors created for LES/RANS model.\n");
1434 if(simCtx->les){
1435 ierr = DMCreateGlobalVector(user->da,&user->CS); CHKERRQ(ierr); ierr = VecSet(user->CS,0.0); CHKERRQ(ierr);
1436 ierr = DMCreateLocalVector(user->da,&user->lCs); CHKERRQ(ierr); ierr = VecSet(user->lCs,0.0); CHKERRQ(ierr);
1437 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Smagorinsky constant (CS) vectors created for LES model.\n");
1438 }
1439
1440 if(simCtx->wallfunction){
1441 ierr = DMCreateLocalVector(user->fda,&user->lFriction_Velocity); CHKERRQ(ierr); ierr = VecSet(user->lFriction_Velocity,0.0);
1442 }
1443 // Add K_Omega etc. here as needed
1444
1445 // Note: Add any other vectors from the legacy MG_Initial here as needed.
1446 // For example: Rhs, Forcing, turbulence Vecs (K_Omega, Nu_t)...
1447
1448 }
1449 // --- Group H: Particle Methods
1450 if(simCtx->np>0){
1451 ierr = DMCreateGlobalVector(user->da,&user->ParticleCount); CHKERRQ(ierr); ierr = VecSet(user->ParticleCount,0.0); CHKERRQ(ierr);
1452 ierr = DMCreateLocalVector(user->da,&user->lParticleCount); CHKERRQ(ierr); ierr = VecSet(user->lParticleCount,0.0); CHKERRQ(ierr);
1453 // Scalar field to hold particle scalar property (e.g., temperature, concentration)
1454 ierr = DMCreateGlobalVector(user->da,&user->Psi); CHKERRQ(ierr); ierr = VecSet(user->Psi,0.0); CHKERRQ(ierr);
1455 ierr = DMCreateLocalVector(user->da,&user->lPsi); CHKERRQ(ierr); ierr = VecSet(user->lPsi,0.0); CHKERRQ(ierr);
1456 LOG_ALLOW(GLOBAL,LOG_DEBUG,"ParticleCount & Scalar(Psi) created for %d particles.\n",simCtx->np);
1457 }
1458 }
1459 // --- Group I: Boundary Condition vectors ---
1460 ierr = DMCreateGlobalVector(user->fda, &user->Bcs.Ubcs); CHKERRQ(ierr);
1461 ierr = VecSet(user->Bcs.Ubcs, 0.0); CHKERRQ(ierr);
1462 ierr = DMCreateGlobalVector(user->fda, &user->Bcs.Uch); CHKERRQ(ierr);
1463 ierr = VecSet(user->Bcs.Uch, 0.0); CHKERRQ(ierr);
1464
1465 if(level == usermg->mglevels - 1){
1466 if(simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR){
1467 LOG_ALLOW(LOCAL, LOG_DEBUG, "Post-processor mode detected. Allocating derived field vectors.\n");
1468
1469 ierr = VecDuplicate(user->P, &user->P_nodal); CHKERRQ(ierr);
1470 ierr = VecSet(user->P_nodal, 0.0); CHKERRQ(ierr);
1471
1472 ierr = VecDuplicate(user->Ucat, &user->Ucat_nodal); CHKERRQ(ierr);
1473 ierr = VecSet(user->Ucat_nodal, 0.0); CHKERRQ(ierr);
1474
1475 ierr = VecDuplicate(user->P, &user->Qcrit); CHKERRQ(ierr);
1476 ierr = VecSet(user->Qcrit, 0.0); CHKERRQ(ierr);
1477
1478 LOG_ALLOW(LOCAL, LOG_DEBUG, "Derived field vectors P_nodal, Ucat_nodal, and Qcrit created.\n");
1479
1480 if(simCtx->np>0){
1481 ierr = VecDuplicate(user->Psi, &user->Psi_nodal); CHKERRQ(ierr);
1482 ierr = VecSet(user->Psi_nodal, 0.0); CHKERRQ(ierr);
1483
1484 LOG_ALLOW(LOCAL, LOG_DEBUG, "Derived field vector Psi_nodal created for particle scalar property.\n");
1485
1486 }
1487 }else{
1488 user->P_nodal = NULL;
1489 user->Ucat_nodal = NULL;
1490 user->Qcrit = NULL;
1491 user->Psi_nodal = NULL;
1492 }
1493 }
1494
1495 }
1496}
1497
1498 LOG_ALLOW(GLOBAL, LOG_INFO, "All simulation vectors created and initialized.\n");
1499
1501 PetscFunctionReturn(0);
1502}
Vec lFriction_Velocity
Definition variables.h:852
Vec lDiffusivityGradient
Definition variables.h:860
Vec lCent
Definition variables.h:879
Vec GridSpace
Definition variables.h:879
Vec P_nodal
Definition variables.h:908
Vec JCsi
Definition variables.h:882
Vec KAj
Definition variables.h:883
Vec JEta
Definition variables.h:882
Vec Zet
Definition variables.h:879
Vec lIEta
Definition variables.h:881
Vec lIZet
Definition variables.h:881
Vec lNvert
Definition variables.h:856
Vec Phi
Definition variables.h:856
Vec IZet
Definition variables.h:881
Vec Centz
Definition variables.h:880
Vec IEta
Definition variables.h:881
Vec lZet
Definition variables.h:879
Vec Csi
Definition variables.h:879
Vec lUcont_rm1
Definition variables.h:864
Vec lIAj
Definition variables.h:881
Vec lKEta
Definition variables.h:883
Vec Ucat_nodal
Definition variables.h:909
Vec lPsi
Definition variables.h:904
Vec DiffusivityGradient
Definition variables.h:860
Vec lJCsi
Definition variables.h:882
Vec lCs
Definition variables.h:886
Vec Ucont
Definition variables.h:856
Vec Ubcs
Physical Cartesian velocity at boundary faces. Full 3D array but only boundary-face entries are meani...
Definition variables.h:121
Vec Qcrit
Definition variables.h:910
Vec JZet
Definition variables.h:882
Vec Centx
Definition variables.h:880
BCS Bcs
Definition variables.h:851
Vec lPhi
Definition variables.h:856
Vec lParticleCount
Definition variables.h:903
Vec lUcont_o
Definition variables.h:863
Vec Ucat_o
Definition variables.h:863
Vec lKZet
Definition variables.h:883
Vec Eta
Definition variables.h:879
Vec lNu_t
Definition variables.h:886
Vec Nu_t
Definition variables.h:886
Vec lJEta
Definition variables.h:882
Vec lCsi
Definition variables.h:879
Vec lGridSpace
Definition variables.h:879
Vec ICsi
Definition variables.h:881
Vec lKCsi
Definition variables.h:883
Vec Ucat
Definition variables.h:856
Vec ParticleCount
Definition variables.h:903
Vec Ucont_o
Definition variables.h:863
Vec lJZet
Definition variables.h:882
Vec Nvert_o
Definition variables.h:863
Vec IAj
Definition variables.h:881
Vec Psi_nodal
Definition variables.h:911
Vec JAj
Definition variables.h:882
Vec KEta
Definition variables.h:883
Vec Ucont_rm1
Definition variables.h:864
Vec lUcont
Definition variables.h:856
Vec Diffusivity
Definition variables.h:859
Vec lAj
Definition variables.h:879
Vec lICsi
Definition variables.h:881
Vec lUcat
Definition variables.h:856
Vec lEta
Definition variables.h:879
Vec KZet
Definition variables.h:883
Vec Cent
Definition variables.h:879
Vec Nvert
Definition variables.h:856
Vec KCsi
Definition variables.h:883
Vec lDiffusivity
Definition variables.h:859
Vec lNvert_o
Definition variables.h:863
Vec Centy
Definition variables.h:880
Vec lJAj
Definition variables.h:882
Vec lKAj
Definition variables.h:883
Vec Psi
Definition variables.h:904
Vec P_o
Definition variables.h:863
Vec Uch
Characteristic velocity for boundary conditions.
Definition variables.h:122
Here is the caller graph for this function:

◆ UpdateLocalGhosts()

PetscErrorCode UpdateLocalGhosts ( UserCtx user,
const char *  fieldName 
)

Internal helper implementation: UpdateLocalGhosts().

Updates the local vector (including ghost points) from its corresponding global vector.

Local to this translation unit.

Definition at line 1510 of file setup.c.

1511{
1512 PetscErrorCode ierr;
1513 PetscMPIInt rank;
1514 Vec globalVec = NULL;
1515 Vec localVec = NULL;
1516 DM dm = NULL; // The DM associated with this field pair
1517
1518 PetscFunctionBeginUser; // Use User version for application code
1520 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1521 LOG_ALLOW(GLOBAL, LOG_INFO, "Rank %d: Starting ghost update for field '%s'.\n", rank, fieldName);
1522
1523 // --- 1. Identify the correct Vectors and DM ---
1524 if (strcmp(fieldName, "Ucat") == 0) {
1525 globalVec = user->Ucat;
1526 localVec = user->lUcat;
1527 dm = user->fda;
1528 } else if (strcmp(fieldName, "Ucont") == 0) {
1529 globalVec = user->Ucont;
1530 localVec = user->lUcont;
1531 dm = user->fda;
1532 } else if (strcmp(fieldName, "P") == 0) {
1533 globalVec = user->P;
1534 localVec = user->lP;
1535 dm = user->da;
1536 } else if (strcmp(fieldName, "Diffusivity") == 0) {
1537 globalVec = user->Diffusivity;
1538 localVec = user->lDiffusivity;
1539 dm = user->da;
1540 } else if (strcmp(fieldName, "DiffusivityGradient") == 0) {
1541 globalVec = user->DiffusivityGradient;
1542 localVec = user->lDiffusivityGradient;
1543 dm = user->fda;
1544 } else if (strcmp(fieldName, "Csi") == 0) {
1545 globalVec = user->Csi;
1546 localVec = user->lCsi;
1547 dm = user->fda;
1548 } else if (strcmp(fieldName, "Eta") == 0) {
1549 globalVec = user->Eta;
1550 localVec = user->lEta;
1551 dm = user->fda;
1552 } else if (strcmp(fieldName, "Zet") == 0) {
1553 globalVec = user->Zet;
1554 localVec = user->lZet;
1555 dm = user->fda;
1556 }else if (strcmp(fieldName, "Nvert") == 0) {
1557 globalVec = user->Nvert;
1558 localVec = user->lNvert;
1559 dm = user->da;
1560 // Add other fields as needed
1561 } else if (strcmp(fieldName, "Aj") == 0) {
1562 globalVec = user->Aj;
1563 localVec = user->lAj;
1564 dm = user->da;
1565 } else if (strcmp(fieldName, "Cent") == 0) {
1566 globalVec = user->Cent;
1567 localVec = user->lCent;
1568 dm = user->fda;
1569 }else if (strcmp(fieldName, "GridSpace") == 0) {
1570 globalVec = user->GridSpace;
1571 localVec = user->lGridSpace;
1572 dm = user->fda;
1573 }else if (strcmp(fieldName,"ICsi") == 0){
1574 globalVec = user->ICsi;
1575 localVec = user->lICsi;
1576 dm = user->fda;
1577 }else if (strcmp(fieldName,"IEta") == 0){
1578 globalVec = user->IEta;
1579 localVec = user->lIEta;
1580 dm = user->fda;
1581 }else if (strcmp(fieldName,"IZet") == 0){
1582 globalVec = user->IZet;
1583 localVec = user->lIZet;
1584 dm = user->fda;
1585 }else if (strcmp(fieldName,"JCsi") == 0){
1586 globalVec = user->JCsi;
1587 localVec = user->lJCsi;
1588 dm = user->fda;
1589 }else if (strcmp(fieldName,"JEta") == 0){
1590 globalVec = user->JEta;
1591 localVec = user->lJEta;
1592 dm = user->fda;
1593 }else if (strcmp(fieldName,"JZet") == 0){
1594 globalVec = user->JZet;
1595 localVec = user->lJZet;
1596 dm = user->fda;
1597 }else if (strcmp(fieldName,"KCsi") == 0){
1598 globalVec = user->KCsi;
1599 localVec = user->lKCsi;
1600 dm = user->fda;
1601 }else if (strcmp(fieldName,"KEta") == 0){
1602 globalVec = user->KEta;
1603 localVec = user->lKEta;
1604 dm = user->fda;
1605 }else if (strcmp(fieldName,"KZet") == 0){
1606 globalVec = user->KZet;
1607 localVec = user->lKZet;
1608 dm = user->fda;
1609 }else if (strcmp(fieldName,"IAj") == 0){
1610 globalVec = user->IAj;
1611 localVec = user->lIAj;
1612 dm = user->da;
1613 }else if (strcmp(fieldName,"JAj") == 0){
1614 globalVec = user->JAj;
1615 localVec = user->lJAj;
1616 dm = user->da;
1617 }else if (strcmp(fieldName,"KAj") == 0){
1618 globalVec = user->KAj;
1619 localVec = user->lKAj;
1620 dm = user->da;
1621 }else if (strcmp(fieldName,"Phi") == 0){ // Pressure correction term.
1622 globalVec = user->Phi;
1623 localVec = user->lPhi;
1624 dm = user->da;
1625 }else if (strcmp(fieldName,"Psi") == 0){ // Particle scalar property.
1626 globalVec = user->Psi;
1627 localVec = user->lPsi;
1628 dm = user->da;
1629 }else {
1630 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Field '%s' not recognized for ghost update.", fieldName);
1631 }
1632
1633 // --- 2. Check if components were found ---
1634 if (!globalVec) {
1635 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Global vector for field '%s' is NULL.", fieldName);
1636 }
1637 if (!localVec) {
1638 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Local vector for field '%s' is NULL.", fieldName);
1639 }
1640 if (!dm) {
1641 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM for field '%s' is NULL.", fieldName);
1642 }
1643
1644 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Identified components for '%s': DM=%p, GlobalVec=%p, LocalVec=%p.\n",
1645 rank, fieldName, (void*)dm, (void*)globalVec, (void*)localVec);
1646
1647 // --- 3. Optional Debugging: Norm Before Update ---
1648 // Use your logging convention check
1649 // if (get_log_level() >= LOG_LEVEL_DEBUG && is_function_allowed("UpdateLocalGhosts")) { // Example check
1650 if(get_log_level() == LOG_DEBUG && is_function_allowed(__func__)){
1651 PetscReal norm_global_before;
1652 ierr = VecNorm(globalVec, NORM_INFINITY, &norm_global_before); CHKERRQ(ierr);
1653 LOG_ALLOW(GLOBAL, LOG_INFO,"Max norm '%s' (Global) BEFORE Ghost Update: %g\n", fieldName, norm_global_before);
1654 // Optional: Norm of local vector before update (might contain old ghost values)
1655 // PetscReal norm_local_before;
1656 // ierr = VecNorm(localVec, NORM_INFINITY, &norm_local_before); CHKERRQ(ierr);
1657 // LOG_ALLOW(GLOBAL, LOG_DEBUG,"Max norm '%s' (Local) BEFORE Ghost Update: %g\n", fieldName, norm_local_before);
1658 }
1659
1660 // --- 4. Perform the Global-to-Local Transfer (Ghost Update) ---
1661 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Calling DMGlobalToLocalBegin/End for '%s'.\n", rank, fieldName);
1662 ierr = DMGlobalToLocalBegin(dm, globalVec, INSERT_VALUES, localVec); CHKERRQ(ierr);
1663 ierr = DMGlobalToLocalEnd(dm, globalVec, INSERT_VALUES, localVec); CHKERRQ(ierr);
1664 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Completed DMGlobalToLocalBegin/End for '%s'.\n", rank, fieldName);
1665
1666 // --- 5. Optional Debugging: Norm After Update ---
1667 // Use your logging convention check
1668 // if (get_log_level() >= LOG_LEVEL_DEBUG && is_function_allowed("UpdateLocalGhosts")) { // Example check
1669 if(get_log_level() == LOG_DEBUG && is_function_allowed(__func__)){ // Using your specific check
1670 PetscReal norm_local_after;
1671 ierr = VecNorm(localVec, NORM_INFINITY, &norm_local_after); CHKERRQ(ierr);
1672 LOG_ALLOW(GLOBAL, LOG_INFO,"Max norm '%s' (Local) AFTER Ghost Update: %g\n", fieldName, norm_local_after);
1673
1674 // --- 6. Optional Debugging: Specific Point Checks (Example for Ucat on Rank 0/1) ---
1675 // (Keep this conditional if it's only for specific debug scenarios)
1676 if (strcmp(fieldName, "Ucat") == 0) { // Only do detailed checks for Ucat for now
1677 PetscMPIInt rank_test;
1678 MPI_Comm_rank(PETSC_COMM_WORLD, &rank_test);
1679
1680 // Get Local Info needed for indexing checks
1681 DMDALocalInfo info_check;
1682 ierr = DMDAGetLocalInfo(dm, &info_check); CHKERRQ(ierr); // Use the correct dm
1683
1684 // Buffer for array pointer
1685 Cmpnts ***lUcat_arr_test = NULL;
1686 PetscErrorCode ierr_test = 0;
1687
1688 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Testing '%s' access immediately after ghost update...\n", rank_test, fieldName);
1689 ierr_test = DMDAVecGetArrayDOFRead(dm, localVec, &lUcat_arr_test); // Use correct dm and localVec
1690
1691 if (ierr_test) {
1692 LOG_ALLOW(LOCAL, LOG_ERROR, "Rank %d: ERROR %d getting '%s' array after ghost update!\n", rank_test, ierr_test, fieldName);
1693 } else if (!lUcat_arr_test) {
1694 LOG_ALLOW(LOCAL, LOG_ERROR, "Rank %d: ERROR NULL pointer getting '%s' array after ghost update!\n", rank_test, fieldName);
1695 }
1696 else {
1697 // Check owned interior point (e.g., first interior point)
1698 PetscInt k_int = info_check.zs + (info_check.zm > 1 ? 1 : 0); // Global k index (at least zs+1 if possible)
1699 PetscInt j_int = info_check.ys + (info_check.ym > 1 ? 1 : 0); // Global j index
1700 PetscInt i_int = info_check.xs + (info_check.xm > 1 ? 1 : 0); // Global i index
1701 // Ensure indices are within global bounds if domain is very small
1702 //if (k_int >= info_check.mz-1) k_int = info_check.mz-2; if (k_int < 1) k_int = 1;
1703 //if (j_int >= info_check.my-1) j_int = info_check.my-2; if (j_int < 1) j_int = 1;
1704 // if (i_int >= info_check.mx-1) i_int = info_check.mx-2; if (i_int < 1) i_int = 1;
1705 // clamp k_int to [1 .. mz-2]
1706 if (k_int >= info_check.mz - 1) {
1707 k_int = info_check.mz - 2;
1708 }
1709 if (k_int < 1) {
1710 k_int = 1;
1711 }
1712
1713 // clamp j_int to [1 .. my-2]
1714 if (j_int >= info_check.my - 1) {
1715 j_int = info_check.my - 2;
1716 }
1717 if (j_int < 1) {
1718 j_int = 1;
1719 }
1720
1721 // clamp i_int to [1 .. mx-2]
1722 if (i_int >= info_check.mx - 1) {
1723 i_int = info_check.mx - 2;
1724 }
1725 if (i_int < 1) {
1726 i_int = 1;
1727 }
1728
1729 // Only attempt read if indices are actually owned (relevant for multi-rank)
1730 if (k_int >= info_check.zs && k_int < info_check.zs + info_check.zm &&
1731 j_int >= info_check.ys && j_int < info_check.ys + info_check.ym &&
1732 i_int >= info_check.xs && i_int < info_check.xs + info_check.xm)
1733 {
1734 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Attempting test read OWNED INTERIOR [%d][%d][%d] (Global)\n", rank_test, k_int, j_int, i_int);
1735 Cmpnts test_val_owned_interior = lUcat_arr_test[k_int][j_int][i_int];
1736 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: SUCCESS reading owned interior: x=%g\n", rank_test, test_val_owned_interior.x);
1737 } else {
1738 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Skipping interior test read for non-owned index [%d][%d][%d].\n", rank_test, k_int, j_int, i_int);
1739 }
1740
1741
1742 // Check owned boundary point (e.g., first owned point)
1743 PetscInt k_bnd = info_check.zs; // Global k index
1744 PetscInt j_bnd = info_check.ys; // Global j index
1745 PetscInt i_bnd = info_check.xs; // Global i index
1746 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Attempting test read OWNED BOUNDARY [%d][%d][%d] (Global)\n", rank_test, k_bnd, j_bnd, i_bnd);
1747 Cmpnts test_val_owned_boundary = lUcat_arr_test[k_bnd][j_bnd][i_bnd];
1748 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: SUCCESS reading owned boundary: x=%g\n", rank_test, test_val_owned_boundary.x);
1749
1750
1751 // Check ghost point (e.g., one layer below in k, if applicable)
1752 if (info_check.zs > 0) { // Only if there's a rank below
1753 PetscInt k_ghost = info_check.zs - 1;
1754 PetscInt j_ghost = info_check.ys; // Use start of owned y, simple example
1755 PetscInt i_ghost = info_check.xs; // Use start of owned x, simple example
1756 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Attempting test read GHOST [%d][%d][%d] (Global)\n", rank_test, k_ghost, j_ghost, i_ghost);
1757 Cmpnts test_val_ghost = lUcat_arr_test[k_ghost][j_ghost][i_ghost];
1758 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: SUCCESS reading ghost: x=%g\n", rank_test, test_val_ghost.x);
1759 } else {
1760 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Skipping ghost test read (zs=0).\n", rank_test);
1761 }
1762
1763 // Restore the array
1764 ierr_test = DMDAVecRestoreArrayDOFRead(dm, localVec, &lUcat_arr_test);
1765 if(ierr_test){ LOG_ALLOW(LOCAL, LOG_ERROR, "Rank %d: ERROR %d restoring '%s' array after test read!\n", rank_test, ierr_test, fieldName); }
1766 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Finished testing '%s' access.\n", rank_test, fieldName);
1767 }
1768 } // end if Ucat
1769 } // end debug logging check
1770
1771 LOG_ALLOW(GLOBAL, LOG_INFO, "Rank %d: Completed ghost update for field '%s'.\n", rank, fieldName);
1773 PetscFunctionReturn(0);
1774}
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:183
A 3D point or vector with PetscScalar components.
Definition variables.h:100
Here is the call graph for this function:
Here is the caller graph for this function:

◆ SetupBoundaryConditions()

PetscErrorCode SetupBoundaryConditions ( SimCtx simCtx)

Internal helper implementation: SetupBoundaryConditions().

(Orchestrator) Sets up all boundary conditions for the simulation.

Local to this translation unit.

Definition at line 1782 of file setup.c.

1783{
1784 PetscErrorCode ierr;
1785 PetscFunctionBeginUser;
1786
1788
1789 LOG_ALLOW(GLOBAL,LOG_INFO, "--- Setting up Boundary Conditions ---\n");
1790 // --- Phase 1: Parse and initialize BC configuration for all blocks ---
1791 LOG_ALLOW(GLOBAL,LOG_INFO,"Parsing BC configuration files and initializing boundary condition data structures.\n");
1792 UserCtx *user_finest = simCtx->usermg.mgctx[simCtx->usermg.mglevels-1].user;
1793 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
1794 LOG_ALLOW(GLOBAL,LOG_DEBUG, " -> Processing Block %d:\n", bi);
1795
1796 // --- Generate the filename for the current block ---
1797 const char *current_bc_filename = simCtx->bcs_files[bi];
1798 LOG_ALLOW(GLOBAL,LOG_DEBUG," -> Processing Block %d using config file '%s'\n", bi, current_bc_filename);
1799 // This will populate user_finest[bi].boundary_faces
1800
1801 //ierr = ParseAllBoundaryConditions(&user_finest[bi],current_bc_filename); CHKERRQ(ierr);
1802
1803 ierr = BoundarySystem_Initialize(&user_finest[bi], current_bc_filename); CHKERRQ(ierr);
1804 }
1805
1806 // Propogate BC Configuration to coarser levels.
1807 ierr = PropagateBoundaryConfigToCoarserLevels(simCtx); CHKERRQ(ierr);
1808
1809 // --- Calculate Grid Metrics (requires BC configuration) ---
1810 // NOTE: This MUST be called here (after BC initialization but before inlet/outlet calculations) because:
1811 // 1. Periodic BC corrections in metric calculations need boundary_faces data to be populated
1812 // 2. Inlet/Outlet area calculations (below) require computed metrics (Csi, Eta, Zet) to be available
1813 // Previously this was in SetupGridAndSolvers, but that caused metrics to be computed without BC info.
1814 LOG_ALLOW(GLOBAL,LOG_INFO,"Computing grid metrics with boundary condition information.\n");
1815 ierr = CalculateAllGridMetrics(simCtx); CHKERRQ(ierr);
1816
1817 // --- Phase 2: Calculate inlet/outlet properties (requires computed metrics) ---
1818 LOG_ALLOW(GLOBAL,LOG_INFO,"Calculating inlet and outlet face properties.\n");
1819 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
1820 // Call the function to calculate the center of the inlet face & the inlet area, which may be used to calculate Boundary values.
1821 ierr = CalculateInletProperties(&user_finest[bi]); CHKERRQ(ierr);
1822
1823 // Call the function to calculate the center of the outlet face & the outlet area, which may be used to calculate Boundary values.
1824 ierr = CalculateOutletProperties(&user_finest[bi]); CHKERRQ(ierr);
1825 }
1826
1827 LOG_ALLOW(GLOBAL,LOG_INFO, "--- Boundary Conditions setup complete ---\n");
1828
1829
1831 PetscFunctionReturn(0);
1832}
PetscErrorCode BoundarySystem_Initialize(UserCtx *user, const char *bcs_filename)
Initializes the entire boundary system.
Definition Boundaries.c:862
PetscErrorCode PropagateBoundaryConfigToCoarserLevels(SimCtx *simCtx)
Propagates boundary condition configuration from finest to all coarser multigrid levels.
Definition Boundaries.c:987
PetscErrorCode CalculateAllGridMetrics(SimCtx *simCtx)
Orchestrates the calculation of all grid metrics.
Definition Metric.c:2168
PetscErrorCode CalculateOutletProperties(UserCtx *user)
Calculates the center and area of the primary OUTLET face.
Definition grid.c:986
PetscErrorCode CalculateInletProperties(UserCtx *user)
Calculates the center and area of the primary INLET face.
Definition grid.c:933
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Allocate3DArrayScalar()

PetscErrorCode Allocate3DArrayScalar ( PetscReal ****  array,
PetscInt  nz,
PetscInt  ny,
PetscInt  nx 
)

Internal helper implementation: Allocate3DArrayScalar().

Allocates a 3D array of PetscReal values using PetscCalloc.

Local to this translation unit.

Definition at line 1838 of file setup.c.

1839{
1840 PetscErrorCode ierr;
1841 PetscReal ***data;
1842 PetscReal *dataContiguous;
1843 PetscInt k, j;
1844
1845 PetscFunctionBegin;
1846 /* Step 1: Allocate memory for an array of nz layer pointers (zero-initialized) */
1847 ierr = PetscCalloc1(nz, &data); CHKERRQ(ierr);
1848
1849 /* Step 2: Allocate memory for all row pointers (nz * ny pointers) */
1850 ierr = PetscCalloc1(nz * ny, &data[0]); CHKERRQ(ierr);
1851 for (k = 1; k < nz; k++) {
1852 data[k] = data[0] + k * ny;
1853 }
1854
1855 /* Step 3: Allocate one contiguous block for all data elements (nz*ny*nx) */
1856 ierr = PetscCalloc1(nz * ny * nx, &dataContiguous); CHKERRQ(ierr);
1857
1858 /* Build the 3D pointer structure: each row pointer gets the correct segment of data */
1859 for (k = 0; k < nz; k++) {
1860 for (j = 0; j < ny; j++) {
1861 data[k][j] = dataContiguous + (k * ny + j) * nx;
1862 /* Memory is already zeroed by PetscCalloc1, so no manual initialization is needed */
1863 }
1864 }
1865 *array = data;
1866 PetscFunctionReturn(0);
1867}

◆ Deallocate3DArrayScalar()

PetscErrorCode Deallocate3DArrayScalar ( PetscReal ***  array,
PetscInt  nz,
PetscInt  ny 
)

Internal helper implementation: Deallocate3DArrayScalar().

Deallocates a 3D array of PetscReal values allocated by Allocate3DArrayScalar.

Local to this translation unit.

Definition at line 1873 of file setup.c.

1874{
1875 PetscErrorCode ierr;
1876 (void)nz;
1877 (void)ny;
1878
1879 PetscFunctionBegin;
1880 if (!array || !array[0] || !array[0][0] ) { // Added more robust check
1881 LOG_ALLOW(GLOBAL, LOG_WARNING, "Deallocate3DArrayScalar called with potentially unallocated or NULL array.\n");
1882 if (array) {
1883 if (array[0]) { // Check if row pointers might exist
1884 // Cannot safely access array[0][0] if array[0] might be invalid/freed
1885 // Standard deallocation below assumes valid pointers.
1886 ierr = PetscFree(array[0]); CHKERRQ(ierr); // Free row pointers if they exist
1887 }
1888 ierr = PetscFree(array); CHKERRQ(ierr); // Free layer pointers if they exist
1889 }
1890 PetscFunctionReturn(0);
1891 }
1892
1893 // --- Standard Deallocation (assuming valid allocation) ---
1894
1895 /* 1. Free the contiguous block of PetscReal values.
1896 The starting address was stored in array[0][0]. */
1897 ierr = PetscFree(array[0][0]); CHKERRQ(ierr); // Free the ACTUAL DATA
1898
1899 /* 2. Free the contiguous block of row pointers.
1900 The starting address was stored in array[0]. */
1901 ierr = PetscFree(array[0]); CHKERRQ(ierr); // Free the ROW POINTERS
1902
1903 /* 3. Free the layer pointer array.
1904 The starting address is 'array' itself. */
1905 ierr = PetscFree(array); CHKERRQ(ierr); // Free the LAYER POINTERS
1906
1907 PetscFunctionReturn(0);
1908}

◆ Allocate3DArrayVector()

PetscErrorCode Allocate3DArrayVector ( Cmpnts ****  array,
PetscInt  nz,
PetscInt  ny,
PetscInt  nx 
)

Implementation of Allocate3DArrayVector().

Allocates a contiguous 3D array of Cmpnts values.

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

See also
Allocate3DArrayVector()

Definition at line 1916 of file setup.c.

1917{
1918 PetscErrorCode ierr;
1919 Cmpnts ***data;
1920 Cmpnts *dataContiguous;
1921 PetscInt k, j;
1922 PetscMPIInt rank;
1923
1924 PetscFunctionBegin;
1925
1926 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
1927
1928 /* Step 1: Allocate memory for nz layer pointers (zeroed) */
1929 ierr = PetscCalloc1(nz, &data); CHKERRQ(ierr);
1930
1931 LOG_ALLOW(LOCAL,LOG_DEBUG," [Rank %d] memory allocated for outermost layer (%d k-layer pointers).\n",rank,nz);
1932
1933 /* Step 2: Allocate memory for all row pointers (nz * ny pointers) */
1934 ierr = PetscCalloc1(nz * ny, &data[0]); CHKERRQ(ierr);
1935 for (k = 1; k < nz; k++) {
1936 data[k] = data[0] + k * ny;
1937 }
1938
1939 LOG_ALLOW(LOCAL,LOG_DEBUG,"[Rank %d] memory allocated for %dx%d row pointers.\n",rank,nz,ny);
1940
1941 /* Step 3: Allocate one contiguous block for nz*ny*nx Cmpnts structures (zeroed) */
1942 ierr = PetscCalloc1(nz * ny * nx, &dataContiguous); CHKERRQ(ierr);
1943
1944 LOG_ALLOW(GLOBAL,LOG_DEBUG,"[Rank %d] memory allocated for contigous block of %dx%dx%d Cmpnts structures).\n",rank,nz,ny,nx);
1945
1946 /* Build the 3D pointer structure for vector data */
1947 for (k = 0; k < nz; k++) {
1948 for (j = 0; j < ny; j++) {
1949 data[k][j] = dataContiguous + (k * ny + j) * nx;
1950 /* The PetscCalloc1 call has already initialized each Cmpnts to zero. */
1951 }
1952 }
1953
1954 LOG_ALLOW(GLOBAL,LOG_DEBUG,"[Rank %d] 3D pointer structure for vector data created. \n",rank);
1955
1956 *array = data;
1957 PetscFunctionReturn(0);
1958}

◆ Deallocate3DArrayVector()

PetscErrorCode Deallocate3DArrayVector ( Cmpnts ***  array,
PetscInt  nz,
PetscInt  ny 
)

Implementation of Deallocate3DArrayVector().

Deallocates a 3D array of Cmpnts structures allocated by Allocate3DArrayVector.

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

See also
Deallocate3DArrayVector()

Definition at line 1966 of file setup.c.

1967{
1968 PetscErrorCode ierr;
1969 (void)nz;
1970 (void)ny;
1971
1972 PetscFunctionBegin;
1973 // If array is NULL or hasn't been allocated properly, just return.
1974 if (!array || !array[0] || !array[0][0] ) {
1975 LOG_ALLOW(GLOBAL, LOG_WARNING, "Deallocate3DArrayVector called with potentially unallocated or NULL array.\n");
1976 // Attempt to free what might exist, but be cautious
1977 if (array) {
1978 if (array[0]) { // Check if row pointers were allocated
1979 // We don't have a direct pointer to the contiguous data block
1980 // saved separately in this allocation scheme. The allocation relies
1981 // on array[0][0] pointing to it. If array[0] was freed first,
1982 // accessing array[0][0] is unsafe.
1983 // The allocation scheme where the contiguous data block is not
1984 // stored separately makes safe deallocation tricky if freeing
1985 // happens out of order or if parts are NULL.
1986
1987 // A SAFER ALLOCATION/DEALLOCATION would store the data pointer separately.
1988 // Given the current allocation scheme, the order MUST be:
1989 // 1. Free the data block (pointed to by array[0][0])
1990 // 2. Free the row pointer block (pointed to by array[0])
1991 // 3. Free the layer pointer block (pointed to by array)
1992
1993 // Let's assume the allocation was successful and pointers are valid.
1994 // Get pointer to the contiguous data block *before* freeing row pointers
1995 Cmpnts *dataContiguous = array[0][0];
1996 ierr = PetscFree(dataContiguous); CHKERRQ(ierr); // Free data block
1997
1998 // Now free the row pointers block
1999 ierr = PetscFree(array[0]); CHKERRQ(ierr); // Free row pointers
2000
2001 }
2002 // Finally, free the array of layer pointers
2003 ierr = PetscFree(array); CHKERRQ(ierr);
2004 }
2005 PetscFunctionReturn(0); // Return gracefully if input was NULL initially
2006 }
2007
2008
2009 // --- Standard Deallocation (assuming valid allocation) ---
2010
2011 /* 1. Free the contiguous block of Cmpnts structures.
2012 The starting address was stored in array[0][0] by Allocate3DArrayVector. */
2013 ierr = PetscFree(array[0][0]); CHKERRQ(ierr); // Free the ACTUAL DATA
2014
2015 /* 2. Free the contiguous block of row pointers.
2016 The starting address was stored in array[0]. */
2017 ierr = PetscFree(array[0]); CHKERRQ(ierr); // Free the ROW POINTERS
2018
2019 /* 3. Free the layer pointer array.
2020 The starting address is 'array' itself. */
2021 ierr = PetscFree(array); CHKERRQ(ierr); // Free the LAYER POINTERS
2022
2023 PetscFunctionReturn(0);
2024}

◆ GetOwnedCellRange()

PetscErrorCode GetOwnedCellRange ( const DMDALocalInfo *  info_nodes,
PetscInt  dim,
PetscInt *  xs_cell_global_out,
PetscInt *  xm_cell_local_out 
)

Internal helper implementation: GetOwnedCellRange().

Determines the global starting index and number of CELLS owned by the current processor in a specified dimension.

Local to this translation unit.

Definition at line 2032 of file setup.c.

2036{
2037 PetscErrorCode ierr = 0; // Standard PETSc error code, not explicitly set here but good practice.
2038 PetscInt xs_node_global_rank; // Global index of the first node owned by this rank in the specified dimension.
2039 PetscInt num_nodes_owned_rank; // Number of nodes owned by this rank in this dimension (local count, excluding ghosts).
2040 PetscInt GlobalNodesInDim_from_info; // Total number of DA points in this dimension, from DMDALocalInfo.
2041
2042 PetscFunctionBeginUser;
2043
2044 // --- 1. Input Validation ---
2045 if (!info_nodes || !xs_cell_global_out || !xm_cell_local_out) {
2046 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null pointer passed to GetOwnedCellRange.");
2047 }
2048
2049 // --- 2. Extract Node Ownership and Global Dimension Information from DMDALocalInfo ---
2050 if (dim == 0) { // I-direction
2051 xs_node_global_rank = info_nodes->xs;
2052 num_nodes_owned_rank = info_nodes->xm;
2053 GlobalNodesInDim_from_info = info_nodes->mx;
2054 } else if (dim == 1) { // J-direction
2055 xs_node_global_rank = info_nodes->ys;
2056 num_nodes_owned_rank = info_nodes->ym;
2057 GlobalNodesInDim_from_info = info_nodes->my;
2058 } else if (dim == 2) { // K-direction
2059 xs_node_global_rank = info_nodes->zs;
2060 num_nodes_owned_rank = info_nodes->zm;
2061 GlobalNodesInDim_from_info = info_nodes->mz;
2062 } else {
2063 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d in GetOwnedCellRange. Must be 0, 1, or 2.", dim);
2064 }
2065
2066 // --- 3. Correct for User-Defined Ghost Node ---
2067 // Per the function's contract (@warning), the DA size includes an extra, non-physical
2068 // node. We subtract 1 to get the true number of physical nodes for cell calculations.
2069 const PetscInt physical_nodes_in_dim = GlobalNodesInDim_from_info - 1;
2070
2071 // --- 4. Handle Edge Cases for Physical Domain Size ---
2072 // If the physical domain has 0 or 1 node, no cells can be formed.
2073 if (physical_nodes_in_dim <= 1) {
2074 *xs_cell_global_out = xs_node_global_rank; // Still report the rank's starting node
2075 *xm_cell_local_out = 0; // But 0 cells
2076 PetscFunctionReturn(0);
2077 }
2078
2079 // --- 5. Determine Cell Ownership Based on Corrected Node Ownership ---
2080 // The first cell this rank *could* define has its origin at the first node this rank owns.
2081 *xs_cell_global_out = xs_node_global_rank;
2082
2083 // If the rank owns no nodes in this dimension, it can't form any cell origins.
2084 if (num_nodes_owned_rank == 0) {
2085 *xm_cell_local_out = 0;
2086 } else {
2087 // --- BUG FIX APPLIED HERE ---
2088 // The previous logic incorrectly assumed a cell's end node (N_{k+1}) must be on the
2089 // same rank as its origin node (N_k). The correct logic is to find the intersection
2090 // between the nodes this rank owns and the nodes that are valid origins globally.
2091
2092 // The first node owned by the rank is its first potential origin.
2093 PetscInt first_owned_origin = xs_node_global_rank;
2094
2095 // The absolute last node owned by this rank. Any node up to and including this one
2096 // is a potential cell origin from this rank's perspective.
2097 PetscInt last_node_owned_by_rank = xs_node_global_rank + num_nodes_owned_rank - 1;
2098
2099 // The absolute last node in the entire PHYSICAL domain that can serve as a cell origin.
2100 // If there are `N` physical nodes (0 to N-1), this index is `N-2`.
2101 PetscInt last_possible_origin_global_idx = physical_nodes_in_dim - 2;
2102
2103 // The actual last origin this rank can provide is the *minimum* of what it owns
2104 // and what is globally possible. This correctly handles both ranks in the middle of
2105 // the domain and the very last rank.
2106 PetscInt actual_last_origin_this_rank_can_form = PetscMin(last_node_owned_by_rank, last_possible_origin_global_idx);
2107
2108 // If the first potential origin this rank owns is already beyond the actual last
2109 // origin it can form, then this rank forms no valid cell origins. This happens if
2110 // the rank only owns the very last physical node.
2111 if (first_owned_origin > actual_last_origin_this_rank_can_form) {
2112 *xm_cell_local_out = 0;
2113 } else {
2114 // The number of cells is the count of valid origins this rank owns.
2115 // (Count = Last Index - First Index + 1)
2116 *xm_cell_local_out = actual_last_origin_this_rank_can_form - first_owned_origin + 1;
2117 }
2118 }
2119
2120 PetscFunctionReturn(ierr);
2121}
Here is the caller graph for this function:

◆ ComputeAndStoreNeighborRanks()

PetscErrorCode ComputeAndStoreNeighborRanks ( UserCtx user)

Internal helper implementation: ComputeAndStoreNeighborRanks().

Computes and stores the Cartesian neighbor ranks for the DMDA decomposition.

Local to this translation unit.

Definition at line 2129 of file setup.c.

2130{
2131 PetscErrorCode ierr;
2132 PetscMPIInt rank;
2133 PetscMPIInt size; // MPI communicator size
2134 const PetscMPIInt *neighbor_ranks_ptr; // Pointer to raw neighbor data from PETSc
2135
2136 PetscFunctionBeginUser;
2138 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2139 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr); // Get MPI size for validation
2140
2141 LOG_ALLOW(GLOBAL, LOG_INFO, "Rank %d: Computing DMDA neighbor ranks.\n", rank);
2142
2143 if (!user || !user->da) {
2144 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx or user->da is NULL in ComputeAndStoreNeighborRanks.");
2145 }
2146
2147 // Get the neighbor information from the DMDA
2148 // neighbor_ranks_ptr will point to an internal PETSc array of 27 ranks.
2149 ierr = DMDAGetNeighbors(user->da, &neighbor_ranks_ptr); CHKERRQ(ierr);
2150
2151 // Log the raw values from DMDAGetNeighbors for boundary-relevant directions for debugging
2152 LOG_ALLOW_SYNC(GLOBAL, LOG_DEBUG, "[Rank %d]Raw DMDAGetNeighbors: xm_raw=%d, xp_raw=%d, ym_raw=%d, yp_raw=%d, zm_raw=%d, zp_raw=%d. MPI_PROC_NULL is %d.\n",
2153 rank,
2154 neighbor_ranks_ptr[12], neighbor_ranks_ptr[14],
2155 neighbor_ranks_ptr[10], neighbor_ranks_ptr[16],
2156 neighbor_ranks_ptr[4], neighbor_ranks_ptr[22],
2157 (int)MPI_PROC_NULL);
2158
2159 // PETSc standard indices for 3D face neighbors from the 27-point stencil:
2160 // Index = k_offset*9 + j_offset*3 + i_offset (where offsets -1,0,1 map to 0,1,2)
2161 // Center: (i_off=1, j_off=1, k_off=1) => 1*9 + 1*3 + 1 = 13
2162 // X-min: (i_off=0, j_off=1, k_off=1) => 1*9 + 1*3 + 0 = 12
2163 // X-plus: (i_off=2, j_off=1, k_off=1) => 1*9 + 1*3 + 2 = 14
2164 // Y-min: (i_off=1, j_off=0, k_off=1) => 1*9 + 0*3 + 1 = 10
2165 // Y-plus: (i_off=1, j_off=2, k_off=1) => 1*9 + 2*3 + 1 = 16
2166 // Z-min: (i_off=1, j_off=1, k_off=0) => 0*9 + 1*3 + 1 = 4
2167 // Z-plus: (i_off=1, j_off=1, k_off=2) => 2*9 + 1*3 + 1 = 22
2168
2169 if (neighbor_ranks_ptr[13] != rank) {
2170 LOG_ALLOW(GLOBAL, LOG_WARNING, "Rank %d: DMDAGetNeighbors center index (13) is %d, expected current rank %d. Neighbor indexing might be non-standard or DMDA small.\n",
2171 rank, neighbor_ranks_ptr[13], rank);
2172 // This warning is important. If the center isn't the current rank, the offsets are likely wrong.
2173 // However, PETSc should ensure this unless the DM is too small for a 3x3x3 stencil.
2174 }
2175
2176 // Assign and sanitize each neighbor rank
2177 PetscMPIInt temp_neighbor;
2178
2179 temp_neighbor = neighbor_ranks_ptr[12]; // xm
2180 if (temp_neighbor < 0 || temp_neighbor >= size) {
2181 LOG_ALLOW(GLOBAL, LOG_WARNING, "[Rank %d] Correcting invalid xm neighbor %d to MPI_PROC_NULL (%d).\n", rank, temp_neighbor, (int)MPI_PROC_NULL);
2182 user->neighbors.rank_xm = MPI_PROC_NULL;
2183 } else {
2184 user->neighbors.rank_xm = temp_neighbor;
2185 }
2186
2187 temp_neighbor = neighbor_ranks_ptr[14]; // xp
2188 if (temp_neighbor < 0 || temp_neighbor >= size) {
2189 LOG_ALLOW(GLOBAL, LOG_WARNING, "[Rank %d] Correcting invalid xp neighbor %d to MPI_PROC_NULL (%d).\n", rank, temp_neighbor, (int)MPI_PROC_NULL);
2190 user->neighbors.rank_xp = MPI_PROC_NULL;
2191 } else {
2192 user->neighbors.rank_xp = temp_neighbor;
2193 }
2194
2195 temp_neighbor = neighbor_ranks_ptr[10]; // ym
2196 if (temp_neighbor < 0 || temp_neighbor >= size) {
2197 LOG_ALLOW(GLOBAL, LOG_WARNING, "[Rank %d] Correcting invalid ym neighbor %d to MPI_PROC_NULL (%d).\n", rank, temp_neighbor, (int)MPI_PROC_NULL);
2198 user->neighbors.rank_ym = MPI_PROC_NULL;
2199 } else {
2200 user->neighbors.rank_ym = temp_neighbor;
2201 }
2202
2203 temp_neighbor = neighbor_ranks_ptr[16]; // yp
2204 if (temp_neighbor < 0 || temp_neighbor >= size) {
2205 // The log for index 16 was "zm" in your output, should be yp
2206 LOG_ALLOW(GLOBAL, LOG_WARNING, "[Rank %d] Correcting invalid yp neighbor (raw index 16) %d to MPI_PROC_NULL (%d).\n", rank, temp_neighbor, (int)MPI_PROC_NULL);
2207 user->neighbors.rank_yp = MPI_PROC_NULL;
2208 } else {
2209 user->neighbors.rank_yp = temp_neighbor;
2210 }
2211
2212 temp_neighbor = neighbor_ranks_ptr[4]; // zm
2213 if (temp_neighbor < 0 || temp_neighbor >= size) {
2214 LOG_ALLOW(GLOBAL, LOG_WARNING, "[Rank %d] Correcting invalid zm neighbor %d to MPI_PROC_NULL (%d).\n", rank, temp_neighbor, (int)MPI_PROC_NULL);
2215 user->neighbors.rank_zm = MPI_PROC_NULL;
2216 } else {
2217 user->neighbors.rank_zm = temp_neighbor;
2218 }
2219
2220 temp_neighbor = neighbor_ranks_ptr[22]; // zp
2221 if (temp_neighbor < 0 || temp_neighbor >= size) {
2222 LOG_ALLOW(GLOBAL, LOG_WARNING, "[Rank %d] Correcting invalid zp neighbor %d to MPI_PROC_NULL (%d).\n", rank, temp_neighbor, (int)MPI_PROC_NULL);
2223 user->neighbors.rank_zp = MPI_PROC_NULL;
2224 } else {
2225 user->neighbors.rank_zp = temp_neighbor;
2226 }
2227
2228 LOG_ALLOW_SYNC(GLOBAL, LOG_DEBUG, "[Rank %d] Stored user->neighbors: xm=%d, xp=%d, ym=%d, yp=%d, zm=%d, zp=%d\n", rank,
2229 user->neighbors.rank_xm, user->neighbors.rank_xp,
2230 user->neighbors.rank_ym, user->neighbors.rank_yp,
2231 user->neighbors.rank_zm, user->neighbors.rank_zp);
2232 PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT); // Ensure logs are flushed
2233
2234 // Note: neighbor_ranks_ptr memory is managed by PETSc, do not free it.
2236 PetscFunctionReturn(0);
2237}
PetscMPIInt rank_zm
Definition variables.h:182
PetscMPIInt rank_yp
Definition variables.h:181
PetscMPIInt rank_ym
Definition variables.h:181
PetscMPIInt rank_xp
Definition variables.h:180
RankNeighbors neighbors
Definition variables.h:842
PetscMPIInt rank_xm
Definition variables.h:180
PetscMPIInt rank_zp
Definition variables.h:182
Here is the caller graph for this function:

◆ SetDMDAProcLayout()

PetscErrorCode SetDMDAProcLayout ( DM  dm,
UserCtx user 
)

Internal helper implementation: SetDMDAProcLayout().

Sets the processor layout for a given DMDA based on PETSc options.

Local to this translation unit.

Definition at line 2245 of file setup.c.

2246{
2247 PetscErrorCode ierr;
2248 PetscMPIInt size, rank;
2249 PetscInt px = PETSC_DECIDE, py = PETSC_DECIDE, pz = PETSC_DECIDE;
2250 PetscBool px_set = PETSC_FALSE, py_set = PETSC_FALSE, pz_set = PETSC_FALSE;
2251 SimCtx *simCtx = user->simCtx;
2252
2253 // Set no.of processors in direction 1
2254 if(simCtx->da_procs_x) {
2255 px_set = PETSC_TRUE;
2256 px = simCtx->da_procs_x;
2257 }
2258 // Set no.of processors in direction 2
2259 if(simCtx->da_procs_y) {
2260 py_set = PETSC_TRUE;
2261 py = simCtx->da_procs_y;
2262 }
2263 // Set no.of processors in direction 1
2264 if(simCtx->da_procs_z) {
2265 pz_set = PETSC_TRUE;
2266 pz = simCtx->da_procs_z;
2267 }
2268
2269 PetscFunctionBeginUser;
2271 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size); CHKERRQ(ierr);
2272 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank); CHKERRQ(ierr);
2273 LOG_ALLOW(GLOBAL, LOG_INFO, "Rank %d: Configuring DMDA processor layout for %d total processes.\n", rank, size);
2274
2275 // --- Validate User Input (Optional but Recommended) ---
2276 // Check if specified processor counts multiply to the total MPI size
2277 if (px_set && py_set && pz_set) {
2278 if (px * py * pz != size) {
2279 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP,
2280 "Specified processor layout %d x %d x %d = %d does not match MPI size %d",
2281 px, py, pz, px * py * pz, size);
2282 }
2283 LOG_ALLOW(GLOBAL, LOG_INFO, "Using specified processor layout: %d x %d x %d\n", px, py, pz);
2284 } else if (px_set || py_set || pz_set) {
2285 // If only some are set, PETSC_DECIDE will be used for others
2286 LOG_ALLOW(GLOBAL, LOG_INFO, "Using partially specified processor layout: %d x %d x %d (PETSC_DECIDE for unspecified)\n", px, py, pz);
2287 } else {
2288 LOG_ALLOW(GLOBAL, LOG_INFO, "Using fully automatic processor layout (PETSC_DECIDE x PETSC_DECIDE x PETSC_DECIDE)\n");
2289 }
2290 // Additional checks: Ensure px, py, pz are positive if set
2291 if ((px_set && px <= 0) || (py_set && py <= 0) || (pz_set && pz <= 0)) {
2292 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Specified processor counts must be positive.");
2293 }
2294
2295
2296 // --- Apply the layout to the DMDA ---
2297 ierr = DMDASetNumProcs(dm, px, py, pz); CHKERRQ(ierr);
2298 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Rank %d: DMDASetNumProcs called with px=%d, py=%d, pz=%d.\n", rank, px, py, pz);
2299
2300 // --- Store the values in UserCtx (Optional) ---
2301 // Note: If PETSC_DECIDE was used, PETSc calculates the actual values during DMSetUp.
2302 // We store the *requested* values here. To get the *actual* values used,
2303 // you would need to call DMDAGetInfo after DMSetUp.
2304 /*
2305 if (user) {
2306 user->procs_x = px;
2307 user->procs_y = py;
2308 user->procs_z = pz;
2309 }
2310 */
2312 PetscFunctionReturn(0);
2313}

◆ SetupDomainRankInfo()

PetscErrorCode SetupDomainRankInfo ( SimCtx simCtx)

Implementation of SetupDomainRankInfo().

Sets up the full rank communication infrastructure, including neighbor ranks and bounding box exchange.

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

See also
SetupDomainRankInfo()

Definition at line 2323 of file setup.c.

2324{
2325 PetscErrorCode ierr;
2326 PetscInt nblk = simCtx->block_number;
2327 PetscInt size = simCtx->size;
2328 BoundingBox *final_bboxlist = NULL;
2329
2330 PetscFunctionBeginUser;
2332
2333 LOG_ALLOW(GLOBAL, LOG_INFO, "Starting full rank communication setup for %d block(s).\n", nblk);
2334
2335 UserCtx *user_finest = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
2336
2337 // --- Step 1: Compute neighbor ranks (unchanged) ---
2338 for (int bi = 0; bi < nblk; bi++) {
2339 ierr = ComputeAndStoreNeighborRanks(&user_finest[bi]); CHKERRQ(ierr);
2340 }
2341 LOG_ALLOW(GLOBAL, LOG_INFO, "Neighbor ranks computed and stored for all blocks.\n");
2342
2343 // --- Step 2: Allocate the final, unified list on ALL ranks ---
2344 // Every rank will build this list in parallel.
2345 ierr = PetscMalloc1(size * nblk, &final_bboxlist); CHKERRQ(ierr);
2346
2347 // --- Step 3: Loop through each block, gather then broadcast its bbox list ---
2348 for (int bi = 0; bi < nblk; bi++) {
2349 // This is a temporary pointer for the current block's list.
2350 BoundingBox *block_bboxlist = NULL;
2351
2352 LOG_ALLOW(GLOBAL, LOG_INFO, "Processing bounding boxes for block %d...\n", bi);
2353
2354 // A) GATHER: On rank 0, block_bboxlist is allocated and filled. On others, it's NULL.
2355 ierr = GatherAllBoundingBoxes(&user_finest[bi], &block_bboxlist); CHKERRQ(ierr);
2356 LOG_ALLOW(GLOBAL, LOG_DEBUG, " -> Gather complete for block %d.\n", bi);
2357
2358 // B) BROADCAST: On non-root ranks, block_bboxlist is allocated. Then, the data
2359 // from rank 0 is broadcast to all ranks. After this call, ALL ranks have
2360 // an identical, complete copy of the bounding boxes for the current block.
2361 ierr = BroadcastAllBoundingBoxes(&user_finest[bi], &block_bboxlist); CHKERRQ(ierr);
2362 LOG_ALLOW(GLOBAL, LOG_DEBUG, " -> Broadcast complete for block %d.\n", bi);
2363
2364 // C) ASSEMBLE: Every rank now copies the data for this block into the
2365 // correct segment of its final, unified list.
2366 for (int r = 0; r < size; r++) {
2367 // The layout is [r0b0, r1b0, ..., r(size-1)b0, r0b1, r1b1, ...]
2368 final_bboxlist[bi * size + r] = block_bboxlist[r];
2369 }
2370 LOG_ALLOW(GLOBAL, LOG_DEBUG, " -> Assembly into final list complete for block %d.\n", bi);
2371
2372 // D) CLEANUP: Free the temporary list for this block on ALL ranks before the next iteration.
2373 // Your helper functions use malloc, so we must use free.
2374 free(block_bboxlist);
2375 }
2376
2377 // --- Step 4: Assign the final pointer and run the last setup step ---
2378 simCtx->bboxlist = final_bboxlist;
2379 LOG_ALLOW(GLOBAL, LOG_INFO, "Final unified bboxlist created on all ranks and stored in SimCtx.\n");
2380
2381 ierr = SetupDomainCellDecompositionMap(&user_finest[0]); CHKERRQ(ierr);
2382 LOG_ALLOW(GLOBAL, LOG_INFO, "Domain Cell Composition set and broadcasted.\n");
2383
2384 LOG_ALLOW(GLOBAL, LOG_INFO, "SetupDomainRankInfo: Completed successfully.\n");
2385
2387 PetscFunctionReturn(0);
2388}
PetscErrorCode BroadcastAllBoundingBoxes(UserCtx *user, BoundingBox **bboxlist)
Broadcasts the bounding box information collected on rank 0 to all other ranks.
Definition grid.c:883
PetscErrorCode GatherAllBoundingBoxes(UserCtx *user, BoundingBox **allBBoxes)
Gathers local bounding boxes from all MPI processes to rank 0.
Definition grid.c:821
PetscErrorCode ComputeAndStoreNeighborRanks(UserCtx *user)
Internal helper implementation: ComputeAndStoreNeighborRanks().
Definition setup.c:2129
PetscErrorCode SetupDomainCellDecompositionMap(UserCtx *user)
Internal helper implementation: SetupDomainCellDecompositionMap().
Definition setup.c:2532
Defines a 3D axis-aligned bounding box.
Definition variables.h:154
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Contra2Cart()

PetscErrorCode Contra2Cart ( UserCtx user)

Internal helper implementation: Contra2Cart().

Reconstructs Cartesian velocity (Ucat) at cell centers from contravariant velocity (Ucont) defined on cell faces.

Local to this translation unit.

Definition at line 2396 of file setup.c.

2397{
2398 PetscErrorCode ierr;
2399 DMDALocalInfo info;
2400 Cmpnts ***lcsi_arr, ***leta_arr, ***lzet_arr; // Local metric arrays
2401 Cmpnts ***lucont_arr; // Local contravariant velocity array
2402 Cmpnts ***gucat_arr; // Global Cartesian velocity array
2403 PetscReal ***lnvert_arr; // Local Nvert array
2404 PetscReal ***laj_arr; // Local Jacobian Determinant inverse array
2405
2406 PetscFunctionBeginUser;
2408 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Starting Contravariant-to-Cartesian velocity transformation.\n");
2409
2410 // --- 1. Get DMDA Info and Check for Valid Inputs ---
2411 // All inputs (lUcont, lCsi, etc.) and outputs (Ucat) are on DMs from the UserCtx.
2412 // We get local info from fda, which governs the layout of most arrays here.
2413 ierr = DMDAGetLocalInfo(user->fda, &info); CHKERRQ(ierr);
2414 if (!user->lUcont || !user->lCsi || !user->lEta || !user->lZet || !user->lNvert || !user->Ucat) {
2415 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Contra2Cart requires lUcont, lCsi/Eta/Zet, lNvert, and Ucat to be non-NULL.");
2416 }
2417
2418
2419 // --- 2. Get Read-Only Array Access to Local Input Vectors (with ghosts) ---
2420 ierr = DMDAVecGetArrayRead(user->fda, user->lUcont, &lucont_arr); CHKERRQ(ierr);
2421 ierr = DMDAVecGetArrayRead(user->fda, user->lCsi, &lcsi_arr); CHKERRQ(ierr);
2422 ierr = DMDAVecGetArrayRead(user->fda, user->lEta, &leta_arr); CHKERRQ(ierr);
2423 ierr = DMDAVecGetArrayRead(user->fda, user->lZet, &lzet_arr); CHKERRQ(ierr);
2424 ierr = DMDAVecGetArrayRead(user->da, user->lNvert, &lnvert_arr); CHKERRQ(ierr);
2425 ierr = DMDAVecGetArrayRead(user->da, user->lAj, &laj_arr); CHKERRQ(ierr);
2426
2427 // --- 3. Get Write-Only Array Access to the Global Output Vector ---
2428 // We compute for local owned cells and write into the global vector.
2429 // PETSc handles mapping the global indices to the correct local memory locations.
2430 ierr = DMDAVecGetArray(user->fda, user->Ucat, &gucat_arr); CHKERRQ(ierr);
2431
2432
2433 // --- 4. Define Loop Bounds for INTERIOR Cells ---
2434 // We use adjusted bounds to avoid calculating Ucat on the physical domain boundaries,
2435 // as these are typically set explicitly by boundary condition functions.
2436 // The stencils use indices like i-1, j-1, k-1, so we must start loops at least at index 1.
2437 PetscInt i_start = (info.xs == 0) ? info.xs + 1 : info.xs;
2438 PetscInt i_end = (info.xs + info.xm == info.mx) ? info.xs + info.xm - 1 : info.xs + info.xm;
2439
2440 PetscInt j_start = (info.ys == 0) ? info.ys + 1 : info.ys;
2441 PetscInt j_end = (info.ys + info.ym == info.my) ? info.ys + info.ym - 1 : info.ys + info.ym;
2442
2443 PetscInt k_start = (info.zs == 0) ? info.zs + 1 : info.zs;
2444 PetscInt k_end = (info.zs + info.zm == info.mz) ? info.zs + info.zm - 1 : info.zs + info.zm;
2445
2446 // --- 5. Main Computation Loop ---
2447 // Loops over the GLOBAL indices of interior cells owned by this rank.
2448 for (PetscInt k_cell = k_start; k_cell < k_end; ++k_cell) {
2449 for (PetscInt j_cell = j_start; j_cell < j_end; ++j_cell) {
2450 for (PetscInt i_cell = i_start; i_cell < i_end; ++i_cell) {
2451
2452 // Check if the cell is a fluid cell (not solid/blanked)
2453 // if (lnvert_arr[k_cell][j_cell][i_cell] > 0.1) continue; // Skip solid/blanked cells
2454
2455 // Transformation matrix [mat] is the metric tensor at the cell center,
2456 // estimated by averaging metrics from adjacent faces.
2457 PetscReal mat[3][3];
2458
2459 // PetscReal aj_center = laj_arr[k_cell+1][j_cell+1][i_cell+1];
2460
2461 mat[0][0] = 0.5 * (lcsi_arr[k_cell][j_cell][i_cell-1].x + lcsi_arr[k_cell][j_cell][i_cell].x); //* aj_center;
2462 mat[0][1] = 0.5 * (lcsi_arr[k_cell][j_cell][i_cell-1].y + lcsi_arr[k_cell][j_cell][i_cell].y); //* aj_center;
2463 mat[0][2] = 0.5 * (lcsi_arr[k_cell][j_cell][i_cell-1].z + lcsi_arr[k_cell][j_cell][i_cell].z); //* aj_center;
2464
2465 mat[1][0] = 0.5 * (leta_arr[k_cell][j_cell-1][i_cell].x + leta_arr[k_cell][j_cell][i_cell].x); //* aj_center;
2466 mat[1][1] = 0.5 * (leta_arr[k_cell][j_cell-1][i_cell].y + leta_arr[k_cell][j_cell][i_cell].y); //* aj_center;
2467 mat[1][2] = 0.5 * (leta_arr[k_cell][j_cell-1][i_cell].z + leta_arr[k_cell][j_cell][i_cell].z); //* aj_center;
2468
2469 mat[2][0] = 0.5 * (lzet_arr[k_cell-1][j_cell][i_cell].x + lzet_arr[k_cell][j_cell][i_cell].x); //* aj_center;
2470 mat[2][1] = 0.5 * (lzet_arr[k_cell-1][j_cell][i_cell].y + lzet_arr[k_cell][j_cell][i_cell].y); //* aj_center;
2471 mat[2][2] = 0.5 * (lzet_arr[k_cell-1][j_cell][i_cell].z + lzet_arr[k_cell][j_cell][i_cell].z); //* aj_center;
2472
2473 // Contravariant velocity vector `q` at the cell center,
2474 // estimated by averaging face-based contravariant velocities.
2475 PetscReal q[3];
2476 q[0] = 0.5 * (lucont_arr[k_cell][j_cell][i_cell-1].x + lucont_arr[k_cell][j_cell][i_cell].x); // U¹ at cell center
2477 q[1] = 0.5 * (lucont_arr[k_cell][j_cell-1][i_cell].y + lucont_arr[k_cell][j_cell][i_cell].y); // U² at cell center
2478 q[2] = 0.5 * (lucont_arr[k_cell-1][j_cell][i_cell].z + lucont_arr[k_cell][j_cell][i_cell].z); // U³ at cell center
2479
2480 // Solve the 3x3 system `mat * ucat = q` using Cramer's rule.
2481 PetscReal det = mat[0][0] * (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) -
2482 mat[0][1] * (mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0]) +
2483 mat[0][2] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]);
2484
2485 if (PetscAbsReal(det) < 1.0e-18) {
2486 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FLOP_COUNT, "Transformation matrix determinant is near zero at cell (%d,%d,%d) \n", i_cell, j_cell, k_cell);
2487 }
2488
2489 PetscReal det_inv = 1.0 / det;
2490
2491 PetscReal det0 = q[0] * (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) -
2492 q[1] * (mat[0][1] * mat[2][2] - mat[0][2] * mat[2][1]) +
2493 q[2] * (mat[0][1] * mat[1][2] - mat[0][2] * mat[1][1]);
2494
2495 PetscReal det1 = -q[0] * (mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0]) +
2496 q[1] * (mat[0][0] * mat[2][2] - mat[0][2] * mat[2][0]) -
2497 q[2] * (mat[0][0] * mat[1][2] - mat[0][2] * mat[1][0]);
2498
2499 PetscReal det2 = q[0] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]) -
2500 q[1] * (mat[0][0] * mat[2][1] - mat[0][1] * mat[2][0]) +
2501 q[2] * (mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]);
2502
2503 // Store computed Cartesian velocity in the GLOBAL Ucat array at the
2504 // array index corresponding to the cell's origin node.
2505 gucat_arr[k_cell][j_cell][i_cell].x = det0 * det_inv;
2506 gucat_arr[k_cell][j_cell][i_cell].y = det1 * det_inv;
2507 gucat_arr[k_cell][j_cell][i_cell].z = det2 * det_inv;
2508 }
2509 }
2510 }
2511
2512 // --- 6. Restore Array Access ---
2513 ierr = DMDAVecRestoreArrayRead(user->fda, user->lUcont, &lucont_arr); CHKERRQ(ierr);
2514 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCsi, &lcsi_arr); CHKERRQ(ierr);
2515 ierr = DMDAVecRestoreArrayRead(user->fda, user->lEta, &leta_arr); CHKERRQ(ierr);
2516 ierr = DMDAVecRestoreArrayRead(user->fda, user->lZet, &lzet_arr); CHKERRQ(ierr);
2517 ierr = DMDAVecRestoreArrayRead(user->da, user->lNvert, &lnvert_arr); CHKERRQ(ierr);
2518 ierr = DMDAVecRestoreArrayRead(user->da, user->lAj, &laj_arr); CHKERRQ(ierr);
2519 ierr = DMDAVecRestoreArray(user->fda, user->Ucat, &gucat_arr); CHKERRQ(ierr);
2520
2521 LOG_ALLOW(GLOBAL, LOG_INFO, "Completed Contravariant-to-Cartesian velocity transformation. \n");
2523 PetscFunctionReturn(0);
2524}
Here is the caller graph for this function:

◆ SetupDomainCellDecompositionMap()

PetscErrorCode SetupDomainCellDecompositionMap ( UserCtx user)

Internal helper implementation: SetupDomainCellDecompositionMap().

Creates and distributes a map of the domain's cell decomposition to all ranks.

Local to this translation unit.

Definition at line 2532 of file setup.c.

2533{
2534 PetscErrorCode ierr;
2535 DMDALocalInfo local_node_info;
2536 RankCellInfo my_cell_info;
2537 PetscMPIInt rank, size;
2538
2539 PetscFunctionBeginUser;
2541
2542 // --- 1. Input Validation and MPI Info ---
2543 if (!user) {
2544 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx pointer is NULL in SetupDomainCellDecompositionMap.");
2545 }
2546 if (!user->da) {
2547 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "user->da is not initialized in SetupDomainCellDecompositionMap.");
2548 }
2549
2550 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2551 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
2552
2553 LOG_ALLOW(GLOBAL, LOG_INFO, "Setting up domain cell decomposition map for %d ranks.\n", size);
2554
2555 // --- 2. Determine Local Cell Ownership ---
2556 // Get the local node ownership information from the primary DMDA.
2557 ierr = DMDAGetLocalInfo(user->da, &local_node_info); CHKERRQ(ierr);
2558
2559 // Use the robust helper function to convert node ownership to cell ownership.
2560 // A cell's index is defined by its origin node.
2561
2562 ierr = GetOwnedCellRange(&local_node_info, 0, &my_cell_info.xs_cell, &my_cell_info.xm_cell); CHKERRQ(ierr);
2563 ierr = GetOwnedCellRange(&local_node_info, 1, &my_cell_info.ys_cell, &my_cell_info.ym_cell); CHKERRQ(ierr);
2564 ierr = GetOwnedCellRange(&local_node_info, 2, &my_cell_info.zs_cell, &my_cell_info.zm_cell); CHKERRQ(ierr);
2565
2566 // Log the calculated local ownership for debugging purposes.
2567 LOG_ALLOW(LOCAL, LOG_DEBUG, "[Rank %d] Owns cells: i[%d, %d), j[%d, %d), k[%d, %d)\n",
2568 rank, my_cell_info.xs_cell, my_cell_info.xs_cell + my_cell_info.xm_cell,
2569 my_cell_info.ys_cell, my_cell_info.ys_cell + my_cell_info.ym_cell,
2570 my_cell_info.zs_cell, my_cell_info.zs_cell + my_cell_info.zm_cell);
2571
2572 // --- 3. Allocate and Distribute the Global Map ---
2573 // Allocate memory for the global map that will hold information from all ranks.
2574 ierr = PetscMalloc1(size, &user->RankCellInfoMap); CHKERRQ(ierr);
2575
2576 // Perform the collective communication to gather the `RankCellInfo` struct from every rank.
2577 // Each rank sends its `my_cell_info` and receives the complete array in `user->RankCellInfoMap`.
2578 // We use MPI_BYTE to ensure portability across different systems and struct padding.
2579 ierr = MPI_Allgather(&my_cell_info, sizeof(RankCellInfo), MPI_BYTE,
2580 user->RankCellInfoMap, sizeof(RankCellInfo), MPI_BYTE,
2581 PETSC_COMM_WORLD); CHKERRQ(ierr);
2582
2583 LOG_ALLOW(GLOBAL, LOG_INFO, "Domain cell decomposition map created and distributed successfully.\n");
2584
2586 PetscFunctionReturn(0);
2587}
PetscErrorCode GetOwnedCellRange(const DMDALocalInfo *info_nodes, PetscInt dim, PetscInt *xs_cell_global_out, PetscInt *xm_cell_local_out)
Internal helper implementation: GetOwnedCellRange().
Definition setup.c:2032
PetscInt ys_cell
Definition variables.h:187
PetscInt xs_cell
Definition variables.h:187
PetscInt zm_cell
Definition variables.h:188
PetscInt zs_cell
Definition variables.h:187
PetscInt xm_cell
Definition variables.h:188
RankCellInfo * RankCellInfoMap
Definition variables.h:902
PetscInt ym_cell
Definition variables.h:188
A lean struct to hold the global cell ownership range for a single MPI rank.
Definition variables.h:186
Here is the call graph for this function:
Here is the caller graph for this function:

◆ BinarySearchInt64()

PetscErrorCode BinarySearchInt64 ( PetscInt  n,
const PetscInt64  arr[],
PetscInt64  key,
PetscBool *  found 
)

Implementation of BinarySearchInt64().

Performs a binary search for a key in a sorted array of PetscInt64.

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

See also
BinarySearchInt64()

Definition at line 2597 of file setup.c.

2598{
2599 PetscInt low = 0, high = n - 1;
2600
2601 PetscFunctionBeginUser;
2603
2604 // --- 1. Input Validation ---
2605 if (!found) {
2606 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output pointer 'found' is NULL in PetscBinarySearchInt64.");
2607 }
2608 if (n > 0 && !arr) {
2609 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input array 'arr' is NULL for n > 0.");
2610 }
2611
2612 // Initialize output
2613 *found = PETSC_FALSE;
2614
2615 // --- 2. Binary Search Algorithm ---
2616 while (low <= high) {
2617 // Use this form to prevent potential integer overflow on very large arrays
2618 PetscInt mid = low + (high - low) / 2;
2619
2620 if (arr[mid] == key) {
2621 *found = PETSC_TRUE; // Key found!
2622 break; // Exit the loop
2623 }
2624
2625 if (arr[mid] < key) {
2626 low = mid + 1; // Search in the right half
2627 } else {
2628 high = mid - 1; // Search in the left half
2629 }
2630 }
2631
2633 PetscFunctionReturn(0);
2634}
Here is the caller graph for this function:

◆ Gidx()

static PetscInt Gidx ( PetscInt  i,
PetscInt  j,
PetscInt  k,
UserCtx user 
)
static

Internal helper implementation: Gidx().

Local to this translation unit.

Definition at line 2641 of file setup.c.

2642{
2643 PetscInt nidx;
2644 DMDALocalInfo info = user->info;
2645
2646 PetscInt mx = info.mx, my = info.my;
2647
2648 AO ao;
2649 DMDAGetAO(user->da, &ao);
2650 nidx=i+j*mx+k*mx*my;
2651
2652 AOApplicationToPetsc(ao,1,&nidx);
2653
2654 return (nidx);
2655}
DMDALocalInfo info
Definition variables.h:837
Here is the caller graph for this function:

◆ ComputeDivergence()

PetscErrorCode ComputeDivergence ( UserCtx user)

Implementation of ComputeDivergence().

Computes the discrete divergence of the contravariant velocity field.

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

See also
ComputeDivergence()

Definition at line 2667 of file setup.c.

2668{
2669 DM da = user->da, fda = user->fda;
2670 DMDALocalInfo info = user->info;
2671
2672 PetscInt ti = user->simCtx->step;
2673
2674 PetscInt xs = info.xs, xe = info.xs + info.xm;
2675 PetscInt ys = info.ys, ye = info.ys + info.ym;
2676 PetscInt zs = info.zs, ze = info.zs + info.zm;
2677 PetscInt mx = info.mx, my = info.my, mz = info.mz;
2678
2679 PetscInt lxs, lys, lzs, lxe, lye, lze;
2680 PetscInt i, j, k;
2681
2682 Vec Div;
2683 PetscReal ***div, ***aj, ***nvert,***p;
2684 Cmpnts ***ucont;
2685 PetscReal maxdiv;
2686
2687 lxs = xs; lxe = xe;
2688 lys = ys; lye = ye;
2689 lzs = zs; lze = ze;
2690
2691 if (xs==0) lxs = xs+1;
2692 if (ys==0) lys = ys+1;
2693 if (zs==0) lzs = zs+1;
2694
2695 if (xe==mx) lxe = xe-1;
2696 if (ye==my) lye = ye-1;
2697 if (ze==mz) lze = ze-1;
2698
2699 PetscFunctionBeginUser;
2701
2702 DMDAVecGetArray(fda,user->lUcont, &ucont);
2703 DMDAVecGetArray(da, user->lAj, &aj);
2704 VecDuplicate(user->P, &Div);
2705 DMDAVecGetArray(da, Div, &div);
2706 DMDAVecGetArray(da, user->lNvert, &nvert);
2707 DMDAVecGetArray(da, user->P, &p);
2708 for (k=lzs; k<lze; k++) {
2709 for (j=lys; j<lye; j++){
2710 for (i=lxs; i<lxe; i++) {
2711 if (k==10 && j==10 && i==1){
2712 LOG_ALLOW(LOCAL,LOG_INFO,"Pressure[10][10][1] = %f | Pressure[10][10][0] = %f \n ",p[k][j][i],p[k][j][i-1]);
2713 }
2714
2715 if (k==10 && j==10 && i==mx-3)
2716 LOG_ALLOW(LOCAL,LOG_INFO,"Pressure[10][10][%d] = %f | Pressure[10][10][%d] = %f \n ",mx-2,p[k][j][mx-2],mx-1,p[k][j][mx-1]);
2717 }
2718 }
2719 }
2720 DMDAVecRestoreArray(da, user->P, &p);
2721
2722
2723 for (k=lzs; k<lze; k++) {
2724 for (j=lys; j<lye; j++) {
2725 for (i=lxs; i<lxe; i++) {
2726 maxdiv = fabs((ucont[k][j][i].x - ucont[k][j][i-1].x +
2727 ucont[k][j][i].y - ucont[k][j-1][i].y +
2728 ucont[k][j][i].z - ucont[k-1][j][i].z)*aj[k][j][i]);
2729 if (nvert[k][j][i] + nvert[k+1][j][i] + nvert[k-1][j][i] +
2730 nvert[k][j+1][i] + nvert[k][j-1][i] +
2731 nvert[k][j][i+1] + nvert[k][j][i-1] > 0.1) maxdiv = 0.;
2732 div[k][j][i] = maxdiv;
2733
2734 }
2735 }
2736 }
2737
2738 if (zs==0) {
2739 k=0;
2740 for (j=ys; j<ye; j++) {
2741 for (i=xs; i<xe; i++) {
2742 div[k][j][i] = 0.;
2743 }
2744 }
2745 }
2746
2747 if (ze == mz) {
2748 k=mz-1;
2749 for (j=ys; j<ye; j++) {
2750 for (i=xs; i<xe; i++) {
2751 div[k][j][i] = 0.;
2752 }
2753 }
2754 }
2755
2756 if (xs==0) {
2757 i=0;
2758 for (k=zs; k<ze; k++) {
2759 for (j=ys; j<ye; j++) {
2760 div[k][j][i] = 0.;
2761 }
2762 }
2763 }
2764
2765 if (xe==mx) {
2766 i=mx-1;
2767 for (k=zs; k<ze; k++) {
2768 for (j=ys; j<ye; j++) {
2769 div[k][j][i] = 0;
2770 }
2771 }
2772 }
2773
2774 if (ys==0) {
2775 j=0;
2776 for (k=zs; k<ze; k++) {
2777 for (i=xs; i<xe; i++) {
2778 div[k][j][i] = 0.;
2779 }
2780 }
2781 }
2782
2783 if (ye==my) {
2784 j=my-1;
2785 for (k=zs; k<ze; k++) {
2786 for (i=xs; i<xe; i++) {
2787 div[k][j][i] = 0.;
2788 }
2789 }
2790 }
2791 DMDAVecRestoreArray(da, Div, &div);
2792 PetscInt MaxFlatIndex;
2793
2794 VecMax(Div, &MaxFlatIndex, &maxdiv);
2795
2796 LOG_ALLOW(GLOBAL,LOG_INFO,"[Step %d]] The Maximum Divergence is %e at flat index %d.\n",ti,maxdiv,MaxFlatIndex);
2797
2798 user->simCtx->MaxDivFlatArg = MaxFlatIndex;
2799 user->simCtx->MaxDiv = maxdiv;
2800
2801 for (k=zs; k<ze; k++) {
2802 for (j=ys; j<ye; j++) {
2803 for (i=xs; i<xe; i++) {
2804 if (Gidx(i,j,k,user) == MaxFlatIndex) {
2805 LOG_ALLOW(GLOBAL,LOG_INFO,"[Step %d] The Maximum Divergence(%e) is at location [%d][%d][%d]. \n", ti, maxdiv,k,j,i);
2806 user->simCtx->MaxDivz = k;
2807 user->simCtx->MaxDivy = j;
2808 user->simCtx->MaxDivx = i;
2809 }
2810 }
2811 }
2812 }
2813
2814
2815 DMDAVecRestoreArray(da, user->lNvert, &nvert);
2816 DMDAVecRestoreArray(fda, user->lUcont, &ucont);
2817 DMDAVecRestoreArray(da, user->lAj, &aj);
2818 VecDestroy(&Div);
2819
2821 PetscFunctionReturn(0);
2822}
static PetscInt Gidx(PetscInt i, PetscInt j, PetscInt k, UserCtx *user)
Internal helper implementation: Gidx().
Definition setup.c:2641
Here is the call graph for this function:
Here is the caller graph for this function:

◆ InitializeRandomGenerators()

PetscErrorCode InitializeRandomGenerators ( UserCtx user,
PetscRandom *  randx,
PetscRandom *  randy,
PetscRandom *  randz 
)

Implementation of InitializeRandomGenerators().

Initializes random number generators for assigning particle properties.

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

See also
InitializeRandomGenerators()

Definition at line 2833 of file setup.c.

2833 {
2834 PetscErrorCode ierr; // Error code for PETSc functions
2835 PetscMPIInt rank;
2836 PetscFunctionBeginUser;
2838 MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
2839
2840 // Initialize RNG for x-coordinate
2841 ierr = PetscRandomCreate(PETSC_COMM_SELF, randx); CHKERRQ(ierr);
2842 ierr = PetscRandomSetType((*randx), PETSCRAND48); CHKERRQ(ierr);
2843 ierr = PetscRandomSetInterval(*randx, user->bbox.min_coords.x, user->bbox.max_coords.x); CHKERRQ(ierr);
2844 ierr = PetscRandomSetSeed(*randx, rank + 12345); CHKERRQ(ierr); // Unique seed per rank
2845 ierr = PetscRandomSeed(*randx); CHKERRQ(ierr);
2846 LOG_ALLOW_SYNC(LOCAL,LOG_VERBOSE, "[Rank %d]Initialized RNG for X-axis.\n",rank);
2847
2848 // Initialize RNG for y-coordinate
2849 ierr = PetscRandomCreate(PETSC_COMM_SELF, randy); CHKERRQ(ierr);
2850 ierr = PetscRandomSetType((*randy), PETSCRAND48); CHKERRQ(ierr);
2851 ierr = PetscRandomSetInterval(*randy, user->bbox.min_coords.y, user->bbox.max_coords.y); CHKERRQ(ierr);
2852 ierr = PetscRandomSetSeed(*randy, rank + 67890); CHKERRQ(ierr); // Unique seed per rank
2853 ierr = PetscRandomSeed(*randy); CHKERRQ(ierr);
2854 LOG_ALLOW_SYNC(LOCAL,LOG_VERBOSE, "[Rank %d]Initialized RNG for Y-axis.\n",rank);
2855
2856 // Initialize RNG for z-coordinate
2857 ierr = PetscRandomCreate(PETSC_COMM_SELF, randz); CHKERRQ(ierr);
2858 ierr = PetscRandomSetType((*randz), PETSCRAND48); CHKERRQ(ierr);
2859 ierr = PetscRandomSetInterval(*randz, user->bbox.min_coords.z, user->bbox.max_coords.z); CHKERRQ(ierr);
2860 ierr = PetscRandomSetSeed(*randz, rank + 54321); CHKERRQ(ierr); // Unique seed per rank
2861 ierr = PetscRandomSeed(*randz); CHKERRQ(ierr);
2862 LOG_ALLOW_SYNC(LOCAL,LOG_VERBOSE, "[Rank %d]Initialized RNG for Z-axis.\n",rank);
2863
2865 PetscFunctionReturn(0);
2866}
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
Definition logging.h:33
Cmpnts max_coords
Maximum x, y, z coordinates of the bounding box.
Definition variables.h:156
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
Definition variables.h:155
BoundingBox bbox
Definition variables.h:841
Here is the caller graph for this function:

◆ InitializeLogicalSpaceRNGs()

PetscErrorCode InitializeLogicalSpaceRNGs ( PetscRandom *  rand_logic_i,
PetscRandom *  rand_logic_j,
PetscRandom *  rand_logic_k 
)

Internal helper implementation: InitializeLogicalSpaceRNGs().

Initializes random number generators for logical space operations [0.0, 1.0).

Local to this translation unit.

Definition at line 2874 of file setup.c.

2874 {
2875 PetscErrorCode ierr;
2876 PetscMPIInt rank;
2877 PetscFunctionBeginUser;
2878
2880
2881 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2882
2883 // --- RNG for i-logical dimension ---
2884 ierr = PetscRandomCreate(PETSC_COMM_SELF, rand_logic_i); CHKERRQ(ierr);
2885 ierr = PetscRandomSetType((*rand_logic_i), PETSCRAND48); CHKERRQ(ierr);
2886 ierr = PetscRandomSetInterval(*rand_logic_i, 0.0, 1.0); CHKERRQ(ierr); // Key change: [0,1)
2887 ierr = PetscRandomSetSeed(*rand_logic_i, rank + 202401); CHKERRQ(ierr); // Unique seed
2888 ierr = PetscRandomSeed(*rand_logic_i); CHKERRQ(ierr);
2889 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d] Initialized RNG for i-logical dimension [0,1).\n",rank);
2890
2891 // --- RNG for j-logical dimension ---
2892 ierr = PetscRandomCreate(PETSC_COMM_SELF, rand_logic_j); CHKERRQ(ierr);
2893 ierr = PetscRandomSetType((*rand_logic_j), PETSCRAND48); CHKERRQ(ierr);
2894 ierr = PetscRandomSetInterval(*rand_logic_j, 0.0, 1.0); CHKERRQ(ierr); // Key change: [0,1)
2895 ierr = PetscRandomSetSeed(*rand_logic_j, rank + 202402); CHKERRQ(ierr);
2896 ierr = PetscRandomSeed(*rand_logic_j); CHKERRQ(ierr);
2897 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d] Initialized RNG for j-logical dimension [0,1).\n",rank);
2898
2899 // --- RNG for k-logical dimension ---
2900 ierr = PetscRandomCreate(PETSC_COMM_SELF, rand_logic_k); CHKERRQ(ierr);
2901 ierr = PetscRandomSetType((*rand_logic_k), PETSCRAND48); CHKERRQ(ierr);
2902 ierr = PetscRandomSetInterval(*rand_logic_k, 0.0, 1.0); CHKERRQ(ierr); // Key change: [0,1)
2903 ierr = PetscRandomSetSeed(*rand_logic_k, rank + 202403); CHKERRQ(ierr);
2904 ierr = PetscRandomSeed(*rand_logic_k); CHKERRQ(ierr);
2905 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d] Initialized RNG for k-logical dimension [0,1).\n",rank);
2906
2907
2909 PetscFunctionReturn(0);
2910}
Here is the caller graph for this function:

◆ InitializeBrownianRNG()

PetscErrorCode InitializeBrownianRNG ( SimCtx simCtx)

Internal helper implementation: InitializeBrownianRNG().

Initializes a single master RNG for time-stepping physics (Brownian motion).

Local to this translation unit.

Definition at line 2918 of file setup.c.

2918 {
2919 PetscErrorCode ierr;
2920 PetscMPIInt rank;
2921
2922 PetscFunctionBeginUser;
2924
2925 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2926
2927 // 1. Create the generator (stored in SimCtx, not UserCtx, as it is global physics)
2928 ierr = PetscRandomCreate(PETSC_COMM_WORLD, &simCtx->BrownianMotionRNG); CHKERRQ(ierr);
2929 ierr = PetscRandomSetType(simCtx->BrownianMotionRNG, PETSCRAND48); CHKERRQ(ierr);
2930
2931 // 2. CRITICAL: Set interval to [0, 1).
2932 // This is required for the Gaussian math to work.
2933 ierr = PetscRandomSetInterval(simCtx->BrownianMotionRNG, 0.0, 1.0); CHKERRQ(ierr);
2934
2935 // 3. Seed based on Rank to ensure spatial randomness
2936 // Multiplying by a large prime helps separate the streams significantly
2937 unsigned long seed = (unsigned long)rank * 987654321 + (unsigned long)time(NULL);
2938 ierr = PetscRandomSetSeed(simCtx->BrownianMotionRNG, seed); CHKERRQ(ierr);
2939 ierr = PetscRandomSeed(simCtx->BrownianMotionRNG); CHKERRQ(ierr);
2940
2941 LOG_ALLOW(LOCAL, LOG_VERBOSE, "[Rank %d] Initialized Brownian Physics RNG.\n", rank);
2942
2944 PetscFunctionReturn(0);
2945}
Here is the caller graph for this function:

◆ TransformScalarDerivativesToPhysical()

void TransformScalarDerivativesToPhysical ( PetscReal  jacobian,
Cmpnts  csi_metrics,
Cmpnts  eta_metrics,
Cmpnts  zet_metrics,
PetscReal  dPhi_dcsi,
PetscReal  dPhi_deta,
PetscReal  dPhi_dzet,
Cmpnts gradPhi 
)

Implementation of TransformScalarDerivativesToPhysical().

Transforms scalar derivatives from computational space to physical space.

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

See also
TransformScalarDerivativesToPhysical()

Definition at line 2957 of file setup.c.

2965{
2966 // Gradient X component
2967 gradPhi->x = jacobian * (dPhi_dcsi * csi_metrics.x + dPhi_deta * eta_metrics.x + dPhi_dzet * zet_metrics.x);
2968
2969 // Gradient Y component
2970 gradPhi->y = jacobian * (dPhi_dcsi * csi_metrics.y + dPhi_deta * eta_metrics.y + dPhi_dzet * zet_metrics.y);
2971
2972 // Gradient Z component
2973 gradPhi->z = jacobian * (dPhi_dcsi * csi_metrics.z + dPhi_deta * eta_metrics.z + dPhi_dzet * zet_metrics.z);
2974}
Here is the caller graph for this function:

◆ TransformDerivativesToPhysical()

static void TransformDerivativesToPhysical ( PetscReal  jacobian,
Cmpnts  csi_metrics,
Cmpnts  eta_metrics,
Cmpnts  zet_metrics,
Cmpnts  deriv_csi,
Cmpnts  deriv_eta,
Cmpnts  deriv_zet,
Cmpnts dudx,
Cmpnts dvdx,
Cmpnts dwdx 
)
static

Internal helper implementation: TransformDerivativesToPhysical().

Local to this translation unit.

Definition at line 2982 of file setup.c.

2985{
2986 // Derivatives of the first component (u)
2987 dudx->x = jacobian * (deriv_csi.x * csi_metrics.x + deriv_eta.x * eta_metrics.x + deriv_zet.x * zet_metrics.x);
2988 dudx->y = jacobian * (deriv_csi.x * csi_metrics.y + deriv_eta.x * eta_metrics.y + deriv_zet.x * zet_metrics.y);
2989 dudx->z = jacobian * (deriv_csi.x * csi_metrics.z + deriv_eta.x * eta_metrics.z + deriv_zet.x * zet_metrics.z);
2990 // Derivatives of the second component (v)
2991 dvdx->x = jacobian * (deriv_csi.y * csi_metrics.x + deriv_eta.y * eta_metrics.x + deriv_zet.y * zet_metrics.x);
2992 dvdx->y = jacobian * (deriv_csi.y * csi_metrics.y + deriv_eta.y * eta_metrics.y + deriv_zet.y * zet_metrics.y);
2993 dvdx->z = jacobian * (deriv_csi.y * csi_metrics.z + deriv_eta.y * eta_metrics.z + deriv_zet.y * zet_metrics.z);
2994 // Derivatives of the third component (w)
2995 dwdx->x = jacobian * (deriv_csi.z * csi_metrics.x + deriv_eta.z * eta_metrics.x + deriv_zet.z * zet_metrics.x);
2996 dwdx->y = jacobian * (deriv_csi.z * csi_metrics.y + deriv_eta.z * eta_metrics.y + deriv_zet.z * zet_metrics.y);
2997 dwdx->z = jacobian * (deriv_csi.z * csi_metrics.z + deriv_eta.z * eta_metrics.z + deriv_zet.z * zet_metrics.z);
2998}
Here is the caller graph for this function:

◆ ComputeScalarFieldDerivatives()

PetscErrorCode ComputeScalarFieldDerivatives ( UserCtx user,
PetscInt  i,
PetscInt  j,
PetscInt  k,
PetscReal ***  field_data,
Cmpnts grad 
)

Internal helper implementation: ComputeScalarFieldDerivatives().

Computes the gradient of a cell-centered SCALAR field at a specific grid point.

Local to this translation unit.

Definition at line 3006 of file setup.c.

3008{
3009 PetscErrorCode ierr;
3010 Cmpnts ***csi, ***eta, ***zet;
3011 PetscReal ***jac;
3012 PetscReal d_csi, d_eta, d_zet;
3013
3014 PetscFunctionBeginUser;
3015
3016 // 1. Get read-only access to metrics
3017 ierr = DMDAVecGetArrayRead(user->fda, user->lCsi, &csi); CHKERRQ(ierr);
3018 ierr = DMDAVecGetArrayRead(user->fda, user->lEta, &eta); CHKERRQ(ierr);
3019 ierr = DMDAVecGetArrayRead(user->fda, user->lZet, &zet); CHKERRQ(ierr);
3020 ierr = DMDAVecGetArrayRead(user->da, user->lAj, &jac); CHKERRQ(ierr);
3021
3022 // 2. Compute derivatives in computational space (Central Difference)
3023 // Assumes ghosts are available at i+/-1
3024 d_csi = 0.5 * (field_data[k][j][i+1] - field_data[k][j][i-1]);
3025 d_eta = 0.5 * (field_data[k][j+1][i] - field_data[k][j-1][i]);
3026 d_zet = 0.5 * (field_data[k+1][j][i] - field_data[k-1][j][i]);
3027
3028 // 3. Transform to physical space
3030 csi[k][j][i], eta[k][j][i], zet[k][j][i],
3031 d_csi, d_eta, d_zet,
3032 grad);
3033
3034 // 4. Restore arrays
3035 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCsi, &csi); CHKERRQ(ierr);
3036 ierr = DMDAVecRestoreArrayRead(user->fda, user->lEta, &eta); CHKERRQ(ierr);
3037 ierr = DMDAVecRestoreArrayRead(user->fda, user->lZet, &zet); CHKERRQ(ierr);
3038 ierr = DMDAVecRestoreArrayRead(user->da, user->lAj, &jac); CHKERRQ(ierr);
3039
3040 PetscFunctionReturn(0);
3041}
void TransformScalarDerivativesToPhysical(PetscReal jacobian, Cmpnts csi_metrics, Cmpnts eta_metrics, Cmpnts zet_metrics, PetscReal dPhi_dcsi, PetscReal dPhi_deta, PetscReal dPhi_dzet, Cmpnts *gradPhi)
Implementation of TransformScalarDerivativesToPhysical().
Definition setup.c:2957
Here is the call graph for this function:

◆ ComputeVectorFieldDerivatives()

PetscErrorCode ComputeVectorFieldDerivatives ( UserCtx user,
PetscInt  i,
PetscInt  j,
PetscInt  k,
Cmpnts ***  field_data,
Cmpnts dudx,
Cmpnts dvdx,
Cmpnts dwdx 
)

Internal helper implementation: ComputeVectorFieldDerivatives().

Computes the derivatives of a cell-centered vector field at a specific grid point.

Local to this translation unit.

Definition at line 3049 of file setup.c.

3051{
3052 PetscErrorCode ierr;
3053 Cmpnts ***csi, ***eta, ***zet;
3054 PetscReal ***jac;
3055 PetscFunctionBeginUser;
3056
3057 // 1. Get read-only access to the necessary metric data arrays
3058 ierr = DMDAVecGetArrayRead(user->fda, user->lCsi, &csi); CHKERRQ(ierr);
3059 ierr = DMDAVecGetArrayRead(user->fda, user->lEta, &eta); CHKERRQ(ierr);
3060 ierr = DMDAVecGetArrayRead(user->fda, user->lZet, &zet); CHKERRQ(ierr);
3061 ierr = DMDAVecGetArrayRead(user->da, user->lAj, &jac); CHKERRQ(ierr);
3062
3063 // 2. Calculate derivatives in computational space using central differencing
3064 Cmpnts deriv_csi, deriv_eta, deriv_zet;
3065 deriv_csi.x = (field_data[k][j][i+1].x - field_data[k][j][i-1].x) * 0.5;
3066 deriv_csi.y = (field_data[k][j][i+1].y - field_data[k][j][i-1].y) * 0.5;
3067 deriv_csi.z = (field_data[k][j][i+1].z - field_data[k][j][i-1].z) * 0.5;
3068
3069 deriv_eta.x = (field_data[k][j+1][i].x - field_data[k][j-1][i].x) * 0.5;
3070 deriv_eta.y = (field_data[k][j+1][i].y - field_data[k][j-1][i].y) * 0.5;
3071 deriv_eta.z = (field_data[k][j+1][i].z - field_data[k][j-1][i].z) * 0.5;
3072
3073 deriv_zet.x = (field_data[k+1][j][i].x - field_data[k-1][j][i].x) * 0.5;
3074 deriv_zet.y = (field_data[k+1][j][i].y - field_data[k-1][j][i].y) * 0.5;
3075 deriv_zet.z = (field_data[k+1][j][i].z - field_data[k-1][j][i].z) * 0.5;
3076
3077 // 3. Transform derivatives to physical space
3078 TransformDerivativesToPhysical(jac[k][j][i], csi[k][j][i], eta[k][j][i], zet[k][j][i],
3079 deriv_csi, deriv_eta, deriv_zet,
3080 dudx, dvdx, dwdx);
3081
3082 // 4. Restore access to the PETSc data arrays
3083 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCsi, &csi); CHKERRQ(ierr);
3084 ierr = DMDAVecRestoreArrayRead(user->fda, user->lEta, &eta); CHKERRQ(ierr);
3085 ierr = DMDAVecRestoreArrayRead(user->fda, user->lZet, &zet); CHKERRQ(ierr);
3086 ierr = DMDAVecRestoreArrayRead(user->da, user->lAj, &jac); CHKERRQ(ierr);
3087
3088 PetscFunctionReturn(0);
3089}
static void TransformDerivativesToPhysical(PetscReal jacobian, Cmpnts csi_metrics, Cmpnts eta_metrics, Cmpnts zet_metrics, Cmpnts deriv_csi, Cmpnts deriv_eta, Cmpnts deriv_zet, Cmpnts *dudx, Cmpnts *dvdx, Cmpnts *dwdx)
Internal helper implementation: TransformDerivativesToPhysical().
Definition setup.c:2982
Here is the call graph for this function:
Here is the caller graph for this function:

◆ DestroyUserVectors()

PetscErrorCode DestroyUserVectors ( UserCtx user)

Internal helper implementation: DestroyUserVectors().

Destroys all PETSc Vec objects within a single UserCtx structure.

Local to this translation unit.

Definition at line 3103 of file setup.c.

3104{
3105 PetscErrorCode ierr;
3106 PetscFunctionBeginUser;
3107
3108 // --- Group A: Primary Flow Fields (Always allocated at all levels) ---
3109 if (user->Ucont) { ierr = VecDestroy(&user->Ucont); CHKERRQ(ierr); }
3110 if (user->lUcont) { ierr = VecDestroy(&user->lUcont); CHKERRQ(ierr); }
3111 if (user->Ucat) { ierr = VecDestroy(&user->Ucat); CHKERRQ(ierr); }
3112 if (user->lUcat) { ierr = VecDestroy(&user->lUcat); CHKERRQ(ierr); }
3113 if (user->P) { ierr = VecDestroy(&user->P); CHKERRQ(ierr); }
3114 if (user->lP) { ierr = VecDestroy(&user->lP); CHKERRQ(ierr); }
3115 if (user->Nvert) { ierr = VecDestroy(&user->Nvert); CHKERRQ(ierr); }
3116 if (user->lNvert) { ierr = VecDestroy(&user->lNvert); CHKERRQ(ierr); }
3117
3118 // --- Group A2: Derived Flow Fields (Conditional) ---
3119 if(user->Diffusivity) {ierr = VecDestroy(&user->Diffusivity); CHKERRQ(ierr);}
3120 if(user->lDiffusivity){ierr = VecDestroy(&user->lDiffusivity); CHKERRQ(ierr);}
3121 if(user->DiffusivityGradient){ierr = VecDestroy(&user->DiffusivityGradient); CHKERRQ(ierr);}
3122 if(user->lDiffusivityGradient){ierr = VecDestroy(&user->lDiffusivityGradient); CHKERRQ(ierr);}
3123
3124 // --- Group B: Solver Work Vectors (All levels) ---
3125 if (user->Phi) { ierr = VecDestroy(&user->Phi); CHKERRQ(ierr); }
3126 if (user->lPhi) { ierr = VecDestroy(&user->lPhi); CHKERRQ(ierr); }
3127
3128 // --- Group C: Time-Stepping Vectors (Finest level only) ---
3129 if (user->Ucont_o) { ierr = VecDestroy(&user->Ucont_o); CHKERRQ(ierr); }
3130 if (user->Ucont_rm1) { ierr = VecDestroy(&user->Ucont_rm1); CHKERRQ(ierr); }
3131 if (user->Ucat_o) { ierr = VecDestroy(&user->Ucat_o); CHKERRQ(ierr); }
3132 if (user->P_o) { ierr = VecDestroy(&user->P_o); CHKERRQ(ierr); }
3133 if (user->Nvert_o) { ierr = VecDestroy(&user->Nvert_o); CHKERRQ(ierr); }
3134 if (user->lUcont_o) { ierr = VecDestroy(&user->lUcont_o); CHKERRQ(ierr); }
3135 if (user->lUcont_rm1) { ierr = VecDestroy(&user->lUcont_rm1); CHKERRQ(ierr); }
3136 if (user->lNvert_o) { ierr = VecDestroy(&user->lNvert_o); CHKERRQ(ierr); }
3137
3138 // --- Group D: Grid Metrics - Face Centered (All levels) ---
3139 if (user->Csi) { ierr = VecDestroy(&user->Csi); CHKERRQ(ierr); }
3140 if (user->Eta) { ierr = VecDestroy(&user->Eta); CHKERRQ(ierr); }
3141 if (user->Zet) { ierr = VecDestroy(&user->Zet); CHKERRQ(ierr); }
3142 if (user->Aj) { ierr = VecDestroy(&user->Aj); CHKERRQ(ierr); }
3143 if (user->lCsi) { ierr = VecDestroy(&user->lCsi); CHKERRQ(ierr); }
3144 if (user->lEta) { ierr = VecDestroy(&user->lEta); CHKERRQ(ierr); }
3145 if (user->lZet) { ierr = VecDestroy(&user->lZet); CHKERRQ(ierr); }
3146 if (user->lAj) { ierr = VecDestroy(&user->lAj); CHKERRQ(ierr); }
3147
3148 // --- Group E: Grid Metrics - Face Centered (All levels) ---
3149 if (user->ICsi) { ierr = VecDestroy(&user->ICsi); CHKERRQ(ierr); }
3150 if (user->IEta) { ierr = VecDestroy(&user->IEta); CHKERRQ(ierr); }
3151 if (user->IZet) { ierr = VecDestroy(&user->IZet); CHKERRQ(ierr); }
3152 if (user->JCsi) { ierr = VecDestroy(&user->JCsi); CHKERRQ(ierr); }
3153 if (user->JEta) { ierr = VecDestroy(&user->JEta); CHKERRQ(ierr); }
3154 if (user->JZet) { ierr = VecDestroy(&user->JZet); CHKERRQ(ierr); }
3155 if (user->KCsi) { ierr = VecDestroy(&user->KCsi); CHKERRQ(ierr); }
3156 if (user->KEta) { ierr = VecDestroy(&user->KEta); CHKERRQ(ierr); }
3157 if (user->KZet) { ierr = VecDestroy(&user->KZet); CHKERRQ(ierr); }
3158 if (user->IAj) { ierr = VecDestroy(&user->IAj); CHKERRQ(ierr); }
3159 if (user->JAj) { ierr = VecDestroy(&user->JAj); CHKERRQ(ierr); }
3160 if (user->KAj) { ierr = VecDestroy(&user->KAj); CHKERRQ(ierr); }
3161 if (user->lICsi) { ierr = VecDestroy(&user->lICsi); CHKERRQ(ierr); }
3162 if (user->lIEta) { ierr = VecDestroy(&user->lIEta); CHKERRQ(ierr); }
3163 if (user->lIZet) { ierr = VecDestroy(&user->lIZet); CHKERRQ(ierr); }
3164 if (user->lJCsi) { ierr = VecDestroy(&user->lJCsi); CHKERRQ(ierr); }
3165 if (user->lJEta) { ierr = VecDestroy(&user->lJEta); CHKERRQ(ierr); }
3166 if (user->lJZet) { ierr = VecDestroy(&user->lJZet); CHKERRQ(ierr); }
3167 if (user->lKCsi) { ierr = VecDestroy(&user->lKCsi); CHKERRQ(ierr); }
3168 if (user->lKEta) { ierr = VecDestroy(&user->lKEta); CHKERRQ(ierr); }
3169 if (user->lKZet) { ierr = VecDestroy(&user->lKZet); CHKERRQ(ierr); }
3170 if (user->lIAj) { ierr = VecDestroy(&user->lIAj); CHKERRQ(ierr); }
3171 if (user->lJAj) { ierr = VecDestroy(&user->lJAj); CHKERRQ(ierr); }
3172 if (user->lKAj) { ierr = VecDestroy(&user->lKAj); CHKERRQ(ierr); }
3173
3174 // --- Group F: Cell/Face Coordinates and Grid Spacing (All levels) ---
3175 if (user->Cent) { ierr = VecDestroy(&user->Cent); CHKERRQ(ierr); }
3176 if (user->lCent) { ierr = VecDestroy(&user->lCent); CHKERRQ(ierr); }
3177 if (user->GridSpace) { ierr = VecDestroy(&user->GridSpace); CHKERRQ(ierr); }
3178 if (user->lGridSpace) { ierr = VecDestroy(&user->lGridSpace); CHKERRQ(ierr); }
3179 if (user->Centx) { ierr = VecDestroy(&user->Centx); CHKERRQ(ierr); }
3180 if (user->Centy) { ierr = VecDestroy(&user->Centy); CHKERRQ(ierr); }
3181 if (user->Centz) { ierr = VecDestroy(&user->Centz); CHKERRQ(ierr); }
3182
3183 // --- Group G: Turbulence Model Vectors (Finest level, conditional on les/rans) ---
3184 if (user->Nu_t) { ierr = VecDestroy(&user->Nu_t); CHKERRQ(ierr); }
3185 if (user->lNu_t) { ierr = VecDestroy(&user->lNu_t); CHKERRQ(ierr); }
3186 if (user->CS) { ierr = VecDestroy(&user->CS); CHKERRQ(ierr); }
3187 if (user->lCs) { ierr = VecDestroy(&user->lCs); CHKERRQ(ierr); }
3188 if (user->lFriction_Velocity) { ierr = VecDestroy(&user->lFriction_Velocity); CHKERRQ(ierr); }
3189 if (user->K_Omega) { ierr = VecDestroy(&user->K_Omega); CHKERRQ(ierr); }
3190 if (user->lK_Omega) { ierr = VecDestroy(&user->lK_Omega); CHKERRQ(ierr); }
3191 if (user->K_Omega_o) { ierr = VecDestroy(&user->K_Omega_o); CHKERRQ(ierr); }
3192 if (user->lK_Omega_o) { ierr = VecDestroy(&user->lK_Omega_o); CHKERRQ(ierr); }
3193
3194 // --- Group H: Particle Vectors (Finest level, conditional on np > 0) ---
3195 if (user->ParticleCount) { ierr = VecDestroy(&user->ParticleCount); CHKERRQ(ierr); }
3196 if (user->lParticleCount) { ierr = VecDestroy(&user->lParticleCount); CHKERRQ(ierr); }
3197 if (user->Psi) { ierr = VecDestroy(&user->Psi); CHKERRQ(ierr); }
3198 if (user->lPsi) { ierr = VecDestroy(&user->lPsi); CHKERRQ(ierr); }
3199
3200 // --- Group I: Boundary Condition Vectors (All levels) ---
3201 if (user->Bcs.Ubcs) { ierr = VecDestroy(&user->Bcs.Ubcs); CHKERRQ(ierr); }
3202 if (user->Bcs.Uch) { ierr = VecDestroy(&user->Bcs.Uch); CHKERRQ(ierr); }
3203
3204 // --- Group J: Post-Processing Vectors (Finest level, postprocessor mode) ---
3205 if (user->P_nodal) { ierr = VecDestroy(&user->P_nodal); CHKERRQ(ierr); }
3206 if (user->Ucat_nodal) { ierr = VecDestroy(&user->Ucat_nodal); CHKERRQ(ierr); }
3207 if (user->Qcrit) { ierr = VecDestroy(&user->Qcrit); CHKERRQ(ierr); }
3208 if (user->Psi_nodal) { ierr = VecDestroy(&user->Psi_nodal); CHKERRQ(ierr); }
3209
3210 // --- Group K: Interpolation Vectors (Lazy allocation) ---
3211 if (user->CellFieldAtCorner) { ierr = VecDestroy(&user->CellFieldAtCorner); CHKERRQ(ierr); }
3212 if (user->lCellFieldAtCorner) { ierr = VecDestroy(&user->lCellFieldAtCorner); CHKERRQ(ierr); }
3213
3214 // --- Group L: Statistical Averaging Vectors (If allocated) ---
3215 if (user->Ucat_sum) { ierr = VecDestroy(&user->Ucat_sum); CHKERRQ(ierr); }
3216 if (user->Ucat_cross_sum) { ierr = VecDestroy(&user->Ucat_cross_sum); CHKERRQ(ierr); }
3217 if (user->Ucat_square_sum) { ierr = VecDestroy(&user->Ucat_square_sum); CHKERRQ(ierr); }
3218 if (user->P_sum) { ierr = VecDestroy(&user->P_sum); CHKERRQ(ierr); }
3219
3220 // --- Group M: Implicit Solver Temporary Vectors (Destroyed after use, but check anyway) ---
3221 if (user->Rhs) { ierr = VecDestroy(&user->Rhs); CHKERRQ(ierr); }
3222 if (user->dUcont) { ierr = VecDestroy(&user->dUcont); CHKERRQ(ierr); }
3223 if (user->pUcont) { ierr = VecDestroy(&user->pUcont); CHKERRQ(ierr); }
3224
3225 // --- Group N: Poisson Solver Vectors (Destroyed after solve, but check anyway) ---
3226 if (user->B) { ierr = VecDestroy(&user->B); CHKERRQ(ierr); }
3227 if (user->R) { ierr = VecDestroy(&user->R); CHKERRQ(ierr); }
3228
3229 LOG_ALLOW(LOCAL, LOG_DEBUG, "All vectors destroyed for UserCtx.\n");
3230 PetscFunctionReturn(0);
3231}
Vec Rhs
Definition variables.h:864
Vec K_Omega_o
Definition variables.h:886
Vec K_Omega
Definition variables.h:886
Vec lCellFieldAtCorner
Definition variables.h:867
Vec Ucat_square_sum
Definition variables.h:889
Vec P_sum
Definition variables.h:889
Vec pUcont
Definition variables.h:864
Vec lK_Omega_o
Definition variables.h:886
Vec lK_Omega
Definition variables.h:886
Vec CellFieldAtCorner
Definition variables.h:867
Vec Ucat_sum
Definition variables.h:889
Vec dUcont
Definition variables.h:864
Vec Ucat_cross_sum
Definition variables.h:889
Here is the caller graph for this function:

◆ DestroyUserContext()

PetscErrorCode DestroyUserContext ( UserCtx user)

Internal helper implementation: DestroyUserContext().

Destroys all resources allocated within a single UserCtx structure.

Local to this translation unit.

Definition at line 3238 of file setup.c.

3239{
3240 PetscErrorCode ierr;
3241 PetscFunctionBeginUser;
3242
3243 if (!user) {
3244 LOG_ALLOW(LOCAL, LOG_WARNING, "DestroyUserContext called with NULL user pointer.\n");
3245 PetscFunctionReturn(0);
3246 }
3247
3248 LOG_ALLOW(LOCAL, LOG_INFO, "Destroying UserCtx at level %d...\n", user->thislevel);
3249
3250 // --- Step 1: Destroy Boundary Condition System ---
3251 // This handles all BC handlers and their private data.
3252 ierr = BoundarySystem_Destroy(user); CHKERRQ(ierr);
3253 LOG_ALLOW(LOCAL, LOG_DEBUG, " Boundary system destroyed.\n");
3254
3255 // --- Step 2: Destroy All Vectors ---
3256 // Handles ~74 Vec objects with proper NULL checking.
3257 ierr = DestroyUserVectors(user); CHKERRQ(ierr);
3258 LOG_ALLOW(LOCAL, LOG_DEBUG, " All vectors destroyed.\n");
3259
3260 // --- Step 3: Destroy Matrix and Solver Objects ---
3261 // Destroy pressure-Poisson matrices and solver.
3262 if (user->A) {
3263 ierr = MatDestroy(&user->A); CHKERRQ(ierr);
3264 LOG_ALLOW(LOCAL, LOG_DEBUG, " Matrix A destroyed.\n");
3265 }
3266 if (user->C) {
3267 ierr = MatDestroy(&user->C); CHKERRQ(ierr);
3268 LOG_ALLOW(LOCAL, LOG_DEBUG, " Matrix C destroyed.\n");
3269 }
3270 if (user->MR) {
3271 ierr = MatDestroy(&user->MR); CHKERRQ(ierr);
3272 LOG_ALLOW(LOCAL, LOG_DEBUG, " Matrix MR destroyed.\n");
3273 }
3274 if (user->MP) {
3275 ierr = MatDestroy(&user->MP); CHKERRQ(ierr);
3276 LOG_ALLOW(LOCAL, LOG_DEBUG, " Matrix MP destroyed.\n");
3277 }
3278 if (user->ksp) {
3279 ierr = KSPDestroy(&user->ksp); CHKERRQ(ierr);
3280 LOG_ALLOW(LOCAL, LOG_DEBUG, " KSP solver destroyed.\n");
3281 }
3282 if (user->nullsp) {
3283 ierr = MatNullSpaceDestroy(&user->nullsp); CHKERRQ(ierr);
3284 LOG_ALLOW(LOCAL, LOG_DEBUG, " MatNullSpace destroyed.\n");
3285 }
3286
3287 // --- Step 4: Destroy Application Ordering ---
3288 if (user->ao) {
3289 ierr = AODestroy(&user->ao); CHKERRQ(ierr);
3290 LOG_ALLOW(LOCAL, LOG_DEBUG, " AO destroyed.\n");
3291 }
3292
3293 // --- Step 5: Destroy DM Objects ---
3294 // Destroy in reverse order of dependency: post_swarm, swarm, fda2, fda, da
3295 if (user->post_swarm) {
3296 ierr = DMDestroy(&user->post_swarm); CHKERRQ(ierr);
3297 LOG_ALLOW(LOCAL, LOG_DEBUG, " post_swarm DM destroyed.\n");
3298 }
3299 if (user->swarm) {
3300 ierr = DMDestroy(&user->swarm); CHKERRQ(ierr);
3301 LOG_ALLOW(LOCAL, LOG_DEBUG, " swarm DM destroyed.\n");
3302 }
3303 if (user->fda2) {
3304 ierr = DMDestroy(&user->fda2); CHKERRQ(ierr);
3305 LOG_ALLOW(LOCAL, LOG_DEBUG, " fda2 DM destroyed.\n");
3306 }
3307 if (user->da) {
3308 ierr = DMDestroy(&user->da); CHKERRQ(ierr);
3309 LOG_ALLOW(LOCAL, LOG_DEBUG, " da DM destroyed.\n");
3310 }
3311
3312 // --- Step 6: Free PetscMalloc'd Arrays ---
3313 // Free arrays allocated with PetscMalloc1
3314 if (user->RankCellInfoMap) {
3315 ierr = PetscFree(user->RankCellInfoMap); CHKERRQ(ierr);
3316 user->RankCellInfoMap = NULL;
3317 LOG_ALLOW(LOCAL, LOG_DEBUG, " RankCellInfoMap freed.\n");
3318 }
3319 if (user->KSKE) {
3320 ierr = PetscFree(user->KSKE); CHKERRQ(ierr);
3321 user->KSKE = NULL;
3322 LOG_ALLOW(LOCAL, LOG_DEBUG, " KSKE array freed.\n");
3323 }
3324
3325 LOG_ALLOW(LOCAL, LOG_INFO, "UserCtx at level %d fully destroyed.\n", user->thislevel);
3326 PetscFunctionReturn(0);
3327}
PetscErrorCode BoundarySystem_Destroy(UserCtx *user)
Cleans up and destroys all boundary system resources.
PetscErrorCode DestroyUserVectors(UserCtx *user)
Internal helper implementation: DestroyUserVectors().
Definition setup.c:3103
MatNullSpace nullsp
Definition variables.h:870
PetscInt * KSKE
Definition variables.h:871
DM post_swarm
Definition variables.h:907
KSP ksp
Definition variables.h:870
Here is the call graph for this function:
Here is the caller graph for this function:

◆ FinalizeSimulation()

PetscErrorCode FinalizeSimulation ( SimCtx simCtx)

Implementation of FinalizeSimulation().

Main cleanup function for the entire simulation context.

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

See also
FinalizeSimulation()

Definition at line 3337 of file setup.c.

3338{
3339 PetscErrorCode ierr;
3340 PetscFunctionBeginUser;
3341
3342 if (!simCtx) {
3343 LOG_ALLOW(GLOBAL, LOG_WARNING, "FinalizeSimulation called with NULL SimCtx pointer.\n");
3344 PetscFunctionReturn(0);
3345 }
3346
3347 LOG_ALLOW(GLOBAL, LOG_INFO, "========================================\n");
3348 LOG_ALLOW(GLOBAL, LOG_INFO, "Beginning simulation memory cleanup...\n");
3349 LOG_ALLOW(GLOBAL, LOG_INFO, "========================================\n");
3350
3351 // ============================================================================
3352 // PHASE 1: DESTROY MULTIGRID HIERARCHY (All UserCtx structures)
3353 // ============================================================================
3354
3355 ierr = DestroySolutionConvergenceState(simCtx); CHKERRQ(ierr);
3356
3357 if (simCtx->usermg.mgctx) {
3358 LOG_ALLOW(GLOBAL, LOG_INFO, "Destroying multigrid hierarchy (%d levels)...\n",
3359 simCtx->usermg.mglevels);
3360
3361 // Destroy each UserCtx from finest to coarsest (reverse order is safer)
3362 for (PetscInt level = simCtx->usermg.mglevels - 1; level >= 0; level--) {
3363 UserCtx *user = simCtx->usermg.mgctx[level].user;
3364 if (user) {
3365 LOG_ALLOW(LOCAL, LOG_INFO, " Destroying level %d of %d...\n",
3366 level, simCtx->usermg.mglevels - 1);
3367 ierr = DestroyUserContext(user); CHKERRQ(ierr);
3368
3369 // Free the UserCtx structure itself
3370 ierr = PetscFree(user); CHKERRQ(ierr);
3371 simCtx->usermg.mgctx[level].user = NULL;
3372 }
3373
3374 // Destroy the MGCtx-level packer DM
3375 if (simCtx->usermg.mgctx[level].packer) {
3376 ierr = DMDestroy(&simCtx->usermg.mgctx[level].packer); CHKERRQ(ierr);
3377 LOG_ALLOW(LOCAL, LOG_DEBUG, " MGCtx[%d].packer destroyed.\n", level);
3378 }
3379 }
3380
3381 // Free the MGCtx array itself
3382 ierr = PetscFree(simCtx->usermg.mgctx); CHKERRQ(ierr);
3383 simCtx->usermg.mgctx = NULL;
3384 LOG_ALLOW(GLOBAL, LOG_INFO, "All multigrid levels destroyed.\n");
3385 }
3386
3387 // ============================================================================
3388 // PHASE 2: DESTROY USERMG-LEVEL OBJECTS
3389 // ============================================================================
3390
3391 if (simCtx->usermg.packer) {
3392 ierr = DMDestroy(&simCtx->usermg.packer); CHKERRQ(ierr);
3393 LOG_ALLOW(LOCAL, LOG_DEBUG, "UserMG.packer DM destroyed.\n");
3394 }
3395
3396 if (simCtx->usermg.snespacker) {
3397 ierr = SNESDestroy(&simCtx->usermg.snespacker); CHKERRQ(ierr);
3398 LOG_ALLOW(LOCAL, LOG_DEBUG, "UserMG.snespacker SNES destroyed.\n");
3399 }
3400
3401 // ============================================================================
3402 // PHASE 3: DESTROY SIMCTX-LEVEL OBJECTS
3403 // ============================================================================
3404
3405 LOG_ALLOW(GLOBAL, LOG_INFO, "Destroying SimCtx-level objects...\n");
3406
3407 // --- PetscViewer for logging ---
3408 if (simCtx->logviewer) {
3409 ierr = PetscViewerDestroy(&simCtx->logviewer); CHKERRQ(ierr);
3410 LOG_ALLOW(LOCAL, LOG_DEBUG, " logviewer destroyed.\n");
3411 }
3412
3413 // --- Particle System DM ---
3414 if (simCtx->dm_swarm) {
3415 ierr = DMDestroy(&simCtx->dm_swarm); CHKERRQ(ierr);
3416 LOG_ALLOW(LOCAL, LOG_DEBUG, " dm_swarm destroyed.\n");
3417 }
3418
3419 // --- BoundingBox List (Array of BoundingBox structs) ---
3420 if (simCtx->bboxlist) {
3421 ierr = PetscFree(simCtx->bboxlist); CHKERRQ(ierr);
3422 simCtx->bboxlist = NULL;
3423 LOG_ALLOW(LOCAL, LOG_DEBUG, " bboxlist freed.\n");
3424 }
3425
3426 // --- Boundary Condition Files (Array of strings) ---
3427 if (simCtx->bcs_files) {
3428 for (PetscInt i = 0; i < simCtx->num_bcs_files; i++) {
3429 if (simCtx->bcs_files[i]) {
3430 ierr = PetscFree(simCtx->bcs_files[i]); CHKERRQ(ierr);
3431 }
3432 }
3433 ierr = PetscFree(simCtx->bcs_files); CHKERRQ(ierr);
3434 simCtx->bcs_files = NULL;
3435 LOG_ALLOW(LOCAL, LOG_DEBUG, " bcs_files array freed (%d files).\n", simCtx->num_bcs_files);
3436 }
3437
3438 // --- Brownian Motion RNG ---
3439 if (simCtx->BrownianMotionRNG) {
3440 ierr = PetscRandomDestroy(&simCtx->BrownianMotionRNG); CHKERRQ(ierr);
3441 LOG_ALLOW(LOCAL, LOG_DEBUG, " BrownianMotionRNG destroyed.\n");
3442 }
3443 // --- Post-Processing Parameters ---
3444 // pps is allocated with PetscNew and contains only static char arrays and basic types.
3445 // No internal dynamic allocations need to be freed.
3446 if (simCtx->pps) {
3447 ierr = PetscFree(simCtx->pps); CHKERRQ(ierr);
3448 simCtx->pps = NULL;
3449 LOG_ALLOW(LOCAL, LOG_DEBUG, " PostProcessParams freed.\n");
3450 }
3451
3452 // --- IBM/FSI Objects ---
3453 // Note: These are initialized to NULL and currently have no dedicated destroy functions.
3454 // If these modules are extended with cleanup routines, call them here.
3455 if (simCtx->ibm != NULL) {
3456 LOG_ALLOW(GLOBAL, LOG_WARNING, " WARNING: simCtx->ibm is non-NULL but no destroy function exists. Potential memory leak.\n");
3457 }
3458 if (simCtx->ibmv != NULL) {
3459 LOG_ALLOW(GLOBAL, LOG_WARNING, " WARNING: simCtx->ibmv is non-NULL but no destroy function exists. Potential memory leak.\n");
3460 }
3461 if (simCtx->fsi != NULL) {
3462 LOG_ALLOW(GLOBAL, LOG_WARNING, " WARNING: simCtx->fsi is non-NULL but no destroy function exists. Potential memory leak.\n");
3463 }
3464
3465 // --- Logging Allowed Functions (Array of strings) ---
3466 // Note: The logging system maintains its own copy via set_allowed_functions(),
3467 // so freeing simCtx->allowedFuncs will NOT affect LOG_ALLOW functionality.
3468 if (simCtx->allowedFuncs) {
3469 for (PetscInt i = 0; i < simCtx->nAllowed; i++) {
3470 if (simCtx->allowedFuncs[i]) {
3471 ierr = PetscFree(simCtx->allowedFuncs[i]); CHKERRQ(ierr);
3472 }
3473 }
3474 ierr = PetscFree(simCtx->allowedFuncs); CHKERRQ(ierr);
3475 simCtx->allowedFuncs = NULL;
3476 LOG_ALLOW(LOCAL, LOG_DEBUG, " allowedFuncs array freed (%d functions).\n", simCtx->nAllowed);
3477 }
3478
3479 // --- Profiling Critical Functions (Array of strings) ---
3480 if (simCtx->profilingSelectedFuncs) {
3481 for (PetscInt i = 0; i < simCtx->nProfilingSelectedFuncs; i++) {
3482 if (simCtx->profilingSelectedFuncs[i]) {
3483 ierr = PetscFree(simCtx->profilingSelectedFuncs[i]); CHKERRQ(ierr);
3484 }
3485 }
3486 ierr = PetscFree(simCtx->profilingSelectedFuncs); CHKERRQ(ierr);
3487 simCtx->profilingSelectedFuncs = NULL;
3488 LOG_ALLOW(LOCAL, LOG_DEBUG, " profilingSelectedFuncs array freed (%d functions).\n", simCtx->nProfilingSelectedFuncs);
3489 }
3490
3491 // ============================================================================
3492 // PHASE 4: FINAL SUMMARY
3493 // ============================================================================
3494
3495 LOG_ALLOW(GLOBAL, LOG_INFO, "========================================\n");
3496 LOG_ALLOW(GLOBAL, LOG_INFO, "Simulation cleanup completed successfully.\n");
3497 LOG_ALLOW(GLOBAL, LOG_INFO, "All PETSc objects have been destroyed.\n");
3498 LOG_ALLOW(GLOBAL, LOG_INFO, "========================================\n");
3499
3500 ierr = PetscFree(simCtx); CHKERRQ(ierr);
3501 PetscFunctionReturn(0);
3502}
PetscErrorCode DestroyUserContext(UserCtx *user)
Internal helper implementation: DestroyUserContext().
Definition setup.c:3238
PetscErrorCode DestroySolutionConvergenceState(SimCtx *simCtx)
Implementation of DestroySolutionConvergenceState().
Definition setup.c:98
DM packer
Definition variables.h:547
SNES snespacker
Definition variables.h:548
DM packer
Definition variables.h:538
Here is the call graph for this function:
Here is the caller graph for this function: