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__   "RepairPeriodicNormalFaceGhosts"
 
#define __FUNCT__   "UpdateLocalGhosts"
 
#define __FUNCT__   "SetupBoundaryConditions"
 
#define __FUNCT__   "GetOwnedCellRange"
 
#define __FUNCT__   "ComputeAndStoreNeighborRanks"
 
#define __FUNCT__   "SetDMDAProcLayout"
 
#define __FUNCT__   "SetupDomainRankInfo"
 
#define __FUNCT__   "Contra2Cart"
 
#define __FUNCT__   "Cart2Contra"
 
#define __FUNCT__   "UniformCart2Contra"
 
#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().
 
static PetscErrorCode RepairPeriodicNormalFaceGhosts (UserCtx *user, DM dm, Vec local_vec, PetscInt dof, char face_direction, PetscBool component_staggered)
 Repairs the adjacent normal ghost layer for periodic face-staggered data.
 
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 Cart2Contra (UserCtx *user)
 Convert a spatially varying Cartesian velocity field to contravariant fluxes.
 
PetscErrorCode UniformCart2Contra (UserCtx *user, PetscReal u, PetscReal v, PetscReal w)
 Convert a uniform Cartesian velocity (u,v,w) to contravariant fluxes in Ucont.
 
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/30]

#define __FUNCT__   "CreateSimulationContext"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [2/30]

#define __FUNCT__   "PetscMkdirRecursive"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [3/30]

#define __FUNCT__   "SetupSimulationEnvironment"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [4/30]

#define __FUNCT__   "AllocateContextHeirarchy"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [5/30]

#define __FUNCT__   "SetupSolverParameters"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [6/30]

#define __FUNCT__   "SetupGridAndSolvers"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [7/30]

#define __FUNCT__   "CreateAndInitializeAllVectors"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [8/30]

#define __FUNCT__   "RepairPeriodicNormalFaceGhosts"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [9/30]

#define __FUNCT__   "UpdateLocalGhosts"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [10/30]

#define __FUNCT__   "SetupBoundaryConditions"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [11/30]

#define __FUNCT__   "GetOwnedCellRange"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [12/30]

#define __FUNCT__   "ComputeAndStoreNeighborRanks"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [13/30]

#define __FUNCT__   "SetDMDAProcLayout"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [14/30]

#define __FUNCT__   "SetupDomainRankInfo"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [15/30]

#define __FUNCT__   "Contra2Cart"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [16/30]

#define __FUNCT__   "Cart2Contra"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [17/30]

#define __FUNCT__   "UniformCart2Contra"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [18/30]

#define __FUNCT__   "SetupDomainCellDecompositionMap"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [19/30]

#define __FUNCT__   "BinarySearchInt64"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [20/30]

#define __FUNCT__   "ComputeDivergence"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [21/30]

#define __FUNCT__   "InitializeRandomGenerators"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [22/30]

#define __FUNCT__   "InitializeLogicalSpaceRNGs"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [23/30]

#define __FUNCT__   "InitializeBrownianRNG"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [24/30]

#define __FUNCT__   "TransformScalarDerivativesToPhysical"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [25/30]

#define __FUNCT__   "TransformDerivativesToPhysical"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [26/30]

#define __FUNCT__   "ComputeScalarFieldDerivatives"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [27/30]

#define __FUNCT__   "ComputeVectorFieldDerivatives"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [28/30]

#define __FUNCT__   "DestroyUserVectors"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [29/30]

#define __FUNCT__   "DestroyUserContext"

Definition at line 143 of file setup.c.

◆ __FUNCT__ [30/30]

#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:569
PetscInt block_number
Definition variables.h:768
PetscReal * solutionConvergenceMeanSpeedHistory
Definition variables.h:753
UserMG usermg
Definition variables.h:821
PetscInt solutionConvergenceSamplesRecorded
Definition variables.h:752
PetscReal * solutionConvergenceMeanKEHistory
Definition variables.h:754
PetscInt solutionConvergencePeriodSteps
Definition variables.h:750
PetscInt mglevels
Definition variables.h:576
PetscInt solutionConvergenceWindowSteps
Definition variables.h:751
@ EXEC_MODE_SOLVER
Definition variables.h:657
MGCtx * mgctx
Definition variables.h:579
@ SOLUTION_CONVERGENCE_PERIODIC_DETERMINISTIC
Definition variables.h:543
@ SOLUTION_CONVERGENCE_STATISTICAL_STEADY
Definition variables.h:544
SolutionConvergenceMode solutionConvergenceMode
Definition variables.h:749
ExecutionMode exec_mode
Definition variables.h:703
User-defined context containing data specific to a single computational grid level.
Definition variables.h:876
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:914
Vec * solutionConvergencePeriodicUcatRef
Definition variables.h:913
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_jameson_residual_norm_noise_allowance_factor = 1.1; // raised from 1.05; less aggressive rejection
206 simCtx->mom_atol = 1e-7; simCtx->mom_rtol = 1e-4;
207 simCtx->mom_resid_atol = 0.0; simCtx->mom_resid_rtol = 0.0;
208 simCtx->imp_stol = 1.e-8;
209 simCtx->mglevels = 3; simCtx->mg_MAX_IT = 30; simCtx->mg_idx = 1;
210 simCtx->mg_preItr = 1; simCtx->mg_poItr = 1;
211 simCtx->poisson = 0; simCtx->poisson_tol = 5.e-9;
212 simCtx->STRONG_COUPLING = 0;simCtx->central=0;
213 /* pseudo_cfl and its bounds are now dimensionless Courant numbers: CFL = dtau * lambda_max,
214 where lambda_max is the global spectral radius computed at each physical timestep.
215 Stable range for 4-stage Jameson RK: ~0–2.83. Initial 0.5 gives a comfortable margin. */
216 simCtx->ren = 100.0; simCtx->pseudo_cfl = 0.5;
217 simCtx->max_pseudo_cfl = 2.0; simCtx->min_pseudo_cfl = 0.001;
218 simCtx->pseudo_cfl_reduction_factor = 0.75;
219 simCtx->pseudo_cfl_growth_factor = 1.1; // raised from 1.0; controller can now increase CFL
220 simCtx->no_pseudo_cfl_backtrack = PETSC_FALSE;
221 simCtx->mom_ratio_ema_alpha = 0.3; /* moderate smoothing; set to 1.0 to recover original raw-ratio behavior */
222 simCtx->mom_last_converged = PETSC_TRUE;
223 simCtx->mom_last_lambda_max = 0.0; /* populated after first momentum solve */
224 simCtx->mom_nk_monitor_history = PETSC_FALSE;
225 simCtx->ps_ksp_pic_monitor_true_residual = PETSC_FALSE;
226 simCtx->cdisx = 0.0; simCtx->cdisy = 0.0; simCtx->cdisz = 0.0;
229 strcpy(simCtx->initialConditionDirectory, "config/initial_condition");
230 simCtx->InitialConstantContra.x = 0.0;
231 simCtx->InitialConstantContra.y = 0.0;
232 simCtx->InitialConstantContra.z = 0.0;
234 simCtx->icVelocityPhysical = 0.0;
235 simCtx->AnalyticalUniformVelocity.x = 0.0;
236 simCtx->AnalyticalUniformVelocity.y = 0.0;
237 simCtx->AnalyticalUniformVelocity.z = 0.0;
244 simCtx->verificationDiffusivity.enabled = PETSC_FALSE;
245 strcpy(simCtx->verificationDiffusivity.mode, "");
246 strcpy(simCtx->verificationDiffusivity.profile, "");
247 simCtx->verificationDiffusivity.gamma0 = 0.0;
248 simCtx->verificationDiffusivity.slope_x = 0.0;
249
250 // --- Group 6: Physical & Geometric Parameters ---
251 simCtx->NumberOfBodies = 1; simCtx->Flux_in = 1.0; simCtx->angle = 0.0;
252 simCtx->max_angle = -54. * 3.1415926 / 180.;
253 simCtx->CMx_c=0.0; simCtx->CMy_c=0.0; simCtx->CMz_c=0.0;
254 simCtx->wall_roughness_height = 1e-16;
255 simCtx->schmidt_number = 1.0; simCtx->Turbulent_schmidt_number = 0.7;
256
257 // --- Group 7: Grid, Domain, and Boundary Condition Settings ---
258 simCtx->block_number = 1; simCtx->inletprofile = 1;
259 simCtx->grid1d = 0; simCtx->Ogrid = 0;
260 simCtx->i_periodic = 0; simCtx->j_periodic = 0; simCtx->k_periodic = 0;
261 simCtx->blkpbc = 10; simCtx->pseudo_periodic = 0;
262 strcpy(simCtx->grid_file, "config/grid.run");
263 simCtx->generate_grid = PETSC_FALSE;
264 simCtx->da_procs_x = PETSC_DECIDE;
265 simCtx->da_procs_y = PETSC_DECIDE;
266 simCtx->da_procs_z = PETSC_DECIDE;
267 simCtx->grid_rotation_angle = 0.0;
268 simCtx->Croty = 0.0; simCtx->Crotz = 0.0;
269 simCtx->num_bcs_files = 1;
270 ierr = PetscMalloc1(1, &simCtx->bcs_files); CHKERRQ(ierr);
271 ierr = PetscStrallocpy("config/bcs.run", &simCtx->bcs_files[0]); CHKERRQ(ierr);
272 simCtx->FluxInSum = 0.0; simCtx->FluxOutSum = 0.0; simCtx->Fluxsum = 0.0;
273 simCtx->drivingForceMagnitude = 0.0, simCtx->forceScalingFactor = 1.8;
274 simCtx->targetVolumetricFlux = 0.0;
275 simCtx->bulkVelocityCorrection = 0.0;
276 simCtx->boundaryVelocityCorrection = 0.0;
277 simCtx->AreaInSum = 0.0; simCtx->AreaOutSum = 0.0;
278 simCtx->U_bc = 0.0; simCtx->ccc = 0;
279 simCtx->ratio = 0.0;
280
281
282 // --- Group 8: Turbulence Modeling (LES/RANS) ---
283 simCtx->averaging = PETSC_FALSE; simCtx->les = NO_LES_MODEL; simCtx->rans = 0;
284 simCtx->wallfunction = 0; simCtx->mixed = 0; simCtx->clark = 0;
285 simCtx->dynamic_freq = 1; simCtx->max_cs = 0.5;
286 simCtx->Const_CS = 0.03;
287 simCtx->testfilter_ik = 0; simCtx->testfilter_1d = 0;
288 simCtx->i_homo_filter = 0; simCtx->j_homo_filter = 0; simCtx->k_homo_filter = 0;
289
290 // --- Group 9: Particle / DMSwarm Data & Settings ---
291 simCtx->np = 0; simCtx->readFields = PETSC_FALSE;
292 simCtx->dm_swarm = NULL; simCtx->bboxlist = NULL;
295 strcpy(simCtx->particleRestartMode,"load");
296 simCtx->particlesLostLastStep = 0;
297 simCtx->particlesLostCumulative = 0;
298 simCtx->particlesMigratedLastStep = 0;
299 simCtx->occupiedCellCount = 0;
300 simCtx->particleLoadImbalance = 0.0;
301 simCtx->migrationPassesLastStep = 0;
302 simCtx->searchMetrics.searchAttempts = 0;
305 simCtx->searchMetrics.searchLostCount = 0;
307 simCtx->searchMetrics.reSearchCount = 0;
310 simCtx->searchMetrics.tieBreakCount = 0;
316 simCtx->BrownianMotionRNG = NULL;
317 simCtx->C_IEM = 2.0;
318
319 // --- Group 10: Immersed Boundary & FSI Data Object Pointers ---
320 simCtx->ibm = NULL; simCtx->ibmv = NULL; simCtx->fsi = NULL;
321 simCtx->rstart_fsi = PETSC_FALSE; simCtx->duplicate = 0;
322
323 // --- Group 11: Logging and Custom Configuration ---
324 strcpy(simCtx->allowedFile, "config/whitelist.run");
325 simCtx->useCfg = PETSC_FALSE;
326 simCtx->allowedFuncs = NULL;
327 simCtx->nAllowed = 0;
328 simCtx->LoggingFrequency = 10;
329 simCtx->summationRHS = 0.0;
330 simCtx->MaxDiv = 0.0;
331 simCtx->MaxDivFlatArg = 0; simCtx->MaxDivx = 0; simCtx->MaxDivy = 0; simCtx->MaxDivz = 0;
332 strcpy(simCtx->profilingSelectedFuncsFile, "config/profile.run");
333 simCtx->useProfilingSelectedFuncsCfg = PETSC_FALSE;
334 simCtx->profilingSelectedFuncs = NULL;
335 simCtx->nProfilingSelectedFuncs = 0;
336 strcpy(simCtx->profilingTimestepMode, "selected");
337 strcpy(simCtx->profilingTimestepFile, "Profiling_Timestep_Summary.csv");
338 simCtx->profilingFinalSummary = PETSC_TRUE;
339 simCtx->walltimeGuardEnabled = PETSC_FALSE;
340 simCtx->walltimeGuardActive = PETSC_FALSE;
341 simCtx->walltimeGuardWarmupSteps = 10;
342 simCtx->walltimeGuardMultiplier = 2.0;
343 simCtx->walltimeGuardMinSeconds = 60.0;
344 simCtx->walltimeGuardEstimatorAlpha = 0.35;
346 simCtx->walltimeGuardLimitSeconds = 0.0;
347 simCtx->walltimeGuardCompletedSteps = 0;
350 simCtx->walltimeGuardHasEWMA = PETSC_FALSE;
351 simCtx->walltimeGuardEWMASeconds = 0.0;
352 simCtx->walltimeGuardLatestStepSeconds = 0.0;
353 simCtx->runtimeMemoryLogEnabled = PETSC_TRUE;
354 strcpy(simCtx->runtimeMemoryLogFile, "Runtime_Memory.log");
355 simCtx->runtimeMemoryLogStarted = PETSC_FALSE;
356 simCtx->runtimeMemoryLogHasPrevious = PETSC_FALSE;
358 // --- Group 11: Post-Processing Information ---
359 strcpy(simCtx->PostprocessingControlFile, "config/post.run");
360 ierr = PetscNew(&simCtx->pps); CHKERRQ(ierr);
361
362 // === 2. Get MPI Info and Handle Config File =============================
363 // -- Group 1: Parallelism & MPI Information
364 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &simCtx->rank); CHKERRQ(ierr);
365 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &simCtx->size); CHKERRQ(ierr);
366
367 // First, check if the -control_file argument was provided by the user/script.
368 ierr = PetscOptionsGetString(NULL, NULL, "-control_file", control_filename, sizeof(control_filename), &control_flg); CHKERRQ(ierr);
369
370 // If the flag is NOT present or the filename is empty, abort with a helpful error.
371 if (!control_flg || strlen(control_filename) == 0) {
372 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
373 "\n\n*** MANDATORY ARGUMENT MISSING ***\n"
374 "The -control_file argument was not provided.\n"
375 "This program must be launched with a configuration file.\n"
376 "Example: mpiexec -n 4 ./simulator -control_file /path/to/your/config.control\n"
377 "This is typically handled automatically by the 'picurv' script.\n");
378 }
379
380 // At this point, we have a valid filename. Attempt to load it.
381 LOG(GLOBAL, LOG_INFO, "Loading mandatory configuration from: %s\n", control_filename);
382 ierr = PetscOptionsInsertFile(PETSC_COMM_WORLD, NULL, control_filename, PETSC_FALSE);
383 if (ierr == PETSC_ERR_FILE_OPEN) {
384 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_FILE_OPEN, "The specified control file was not found or could not be opened: %s", control_filename);
385 }
386 CHKERRQ(ierr);
387
388 // === 3. A Configure Logging System ========================================
389 // This logic determines the logging configuration and STORES it in simCtx for
390 // later reference and cleanup.
391 ierr = PetscOptionsGetString(NULL, NULL, "-whitelist_config_file", simCtx->allowedFile, PETSC_MAX_PATH_LEN, &simCtx->useCfg); CHKERRQ(ierr);
392
393 if (simCtx->useCfg) {
394 ierr = LoadAllowedFunctionsFromFile(simCtx->allowedFile, &simCtx->allowedFuncs, &simCtx->nAllowed);
395 if (ierr) {
396 // Use direct PetscPrintf as logging system isn't fully active yet.
397 PetscPrintf(PETSC_COMM_SELF, "[%s] WARNING: Failed to load allowed functions from '%s'. Falling back to default list.\n", __func__, simCtx->allowedFile);
398 simCtx->useCfg = PETSC_FALSE; // Mark as failed.
399 ierr = 0; // Clear the error to allow fallback.
400 } else if (simCtx->nAllowed == 0) {
401 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
402 "Whitelist config file '%s' is empty. Omit -whitelist_config_file to use the default allow-list, or list at least one function.",
403 simCtx->allowedFile);
404 }
405 }
406 if (!simCtx->useCfg) {
407 // Fallback to default logging functions if no file was used or if loading failed.
408 simCtx->nAllowed = 2;
409 ierr = PetscMalloc1(simCtx->nAllowed, &simCtx->allowedFuncs); CHKERRQ(ierr);
410 ierr = PetscStrallocpy("main", &simCtx->allowedFuncs[0]); CHKERRQ(ierr);
411 ierr = PetscStrallocpy("CreateSimulationContext", &simCtx->allowedFuncs[1]); CHKERRQ(ierr);
412 }
413
414 // Activate the configuration by passing it to the logging module's setup function.
415 set_allowed_functions((const char**)simCtx->allowedFuncs, (size_t)simCtx->nAllowed);
416
417 // Now that the logger is configured, we can use it.
418 LOG_ALLOW_SYNC(LOCAL, LOG_INFO, "Context created. Initializing on rank %d of %d.\n", simCtx->rank, simCtx->size);
419 print_log_level(); // This will now correctly reflect the LOG_LEVEL environment variable.
420
421 // === 3.B Configure Profiling System ========================================
422 ierr = PetscOptionsGetString(NULL, NULL, "-profiling_timestep_mode", simCtx->profilingTimestepMode, sizeof(simCtx->profilingTimestepMode), NULL); CHKERRQ(ierr);
423 ierr = PetscOptionsGetString(NULL, NULL, "-profiling_timestep_file", simCtx->profilingTimestepFile, PETSC_MAX_PATH_LEN, NULL); CHKERRQ(ierr);
424 ierr = PetscOptionsGetBool(NULL, NULL, "-profiling_final_summary", &simCtx->profilingFinalSummary, NULL); CHKERRQ(ierr);
425 if (strcmp(simCtx->profilingTimestepMode, "off") != 0 &&
426 strcmp(simCtx->profilingTimestepMode, "selected") != 0 &&
427 strcmp(simCtx->profilingTimestepMode, "all") != 0) {
428 PetscPrintf(PETSC_COMM_SELF, "[%s] WARNING: Unknown profiling timestep mode '%s'. Falling back to 'selected'.\n", __func__, simCtx->profilingTimestepMode);
429 strcpy(simCtx->profilingTimestepMode, "selected");
430 }
431
432 if (strcmp(simCtx->profilingTimestepMode, "selected") == 0) {
433 ierr = PetscOptionsGetString(NULL, NULL, "-profile_config_file", simCtx->profilingSelectedFuncsFile, PETSC_MAX_PATH_LEN, &simCtx->useProfilingSelectedFuncsCfg); CHKERRQ(ierr);
434 if (simCtx->useProfilingSelectedFuncsCfg) {
436 if (ierr) {
437 PetscPrintf(PETSC_COMM_SELF, "[%s] WARNING: Failed to load selected profiling functions from '%s'. Falling back to default list.\n", __func__, simCtx->profilingSelectedFuncsFile);
438 simCtx->useProfilingSelectedFuncsCfg = PETSC_FALSE;
439 ierr = 0;
440 }
441 }
442 if (!simCtx->useProfilingSelectedFuncsCfg) {
443 // Fallback to a hardcoded default list if no file was provided or loading failed.
444 simCtx->nProfilingSelectedFuncs = 4;
445 ierr = PetscMalloc1(simCtx->nProfilingSelectedFuncs, &simCtx->profilingSelectedFuncs); CHKERRQ(ierr);
446 ierr = PetscStrallocpy("FlowSolver", &simCtx->profilingSelectedFuncs[0]); CHKERRQ(ierr);
447 ierr = PetscStrallocpy("AdvanceSimulation", &simCtx->profilingSelectedFuncs[1]); CHKERRQ(ierr);
448 ierr = PetscStrallocpy("LocateAllParticlesInGrid", &simCtx->profilingSelectedFuncs[2]); CHKERRQ(ierr);
449 ierr = PetscStrallocpy("InterpolateAllFieldsToSwarm", &simCtx->profilingSelectedFuncs[3]); CHKERRQ(ierr);
450 }
451 }
452
453 // Initialize the profiling system with the current updated simulation context.
454 ierr = ProfilingInitialize(simCtx); CHKERRQ(ierr);
455
456 // === 4. Parse All Command Line Options ==================================
457 LOG_ALLOW(GLOBAL, LOG_INFO, "Parsing command-line options...\n");
458
459 // --- Group 2
460 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 2: Simulation Control,Time and I/O.\n");
461 // Read the physical time to start from.
462 // The default is already 0.0, so this will only be non-zero if the user provides it.
463 ierr = PetscOptionsGetInt(NULL, NULL, "-start_step", &simCtx->StartStep, NULL); CHKERRQ(ierr);
464 ierr = PetscOptionsGetInt(NULL,NULL, "-totalsteps", &simCtx->StepsToRun, NULL); CHKERRQ(ierr);
465 ierr = PetscOptionsGetBool(NULL, NULL, "-only_setup", &simCtx->OnlySetup, NULL); CHKERRQ(ierr);
466 ierr = PetscOptionsGetBool(NULL, NULL, "-continue_mode", &simCtx->continueMode, NULL); CHKERRQ(ierr);
467 ierr = PetscOptionsGetReal(NULL, NULL, "-dt", &simCtx->dt, NULL); CHKERRQ(ierr);
468 ierr = PetscOptionsGetInt(NULL, NULL, "-tio", &simCtx->tiout, NULL); CHKERRQ(ierr);
469 ierr = PetscOptionsGetInt(NULL, NULL, "-particle_console_output_freq", &simCtx->particleConsoleOutputFreq, &particle_console_output_freq_flg); CHKERRQ(ierr);
470 if (!particle_console_output_freq_flg) {
471 simCtx->particleConsoleOutputFreq = simCtx->tiout;
472 }
473 ierr = PetscOptionsGetString(NULL,NULL,"-euler_field_source",simCtx->eulerianSource,sizeof(simCtx->eulerianSource),NULL);CHKERRQ(ierr);
474 ierr = PetscOptionsGetString(NULL,NULL,"-output_dir",simCtx->output_dir,sizeof(simCtx->output_dir),NULL);CHKERRQ(ierr);
475 ierr = PetscOptionsGetString(NULL,NULL,"-restart_dir",simCtx->restart_dir,sizeof(simCtx->restart_dir),NULL);CHKERRQ(ierr);
476 ierr = PetscOptionsGetString(NULL,NULL,"-log_dir",simCtx->log_dir,sizeof(simCtx->log_dir),NULL);CHKERRQ(ierr);
477 ierr = PetscOptionsGetString(NULL,NULL,"-euler_subdir",simCtx->euler_subdir,sizeof(simCtx->euler_subdir),NULL);CHKERRQ(ierr);
478 ierr = PetscOptionsGetString(NULL,NULL,"-particle_subdir",simCtx->particle_subdir,sizeof(simCtx->particle_subdir),NULL);CHKERRQ(ierr);
479 ierr = PetscOptionsGetBool(NULL, NULL, "-walltime_guard_enabled", &simCtx->walltimeGuardEnabled, NULL); CHKERRQ(ierr);
480 ierr = PetscOptionsGetInt(NULL, NULL, "-walltime_guard_warmup_steps", &simCtx->walltimeGuardWarmupSteps, NULL); CHKERRQ(ierr);
481 ierr = PetscOptionsGetReal(NULL, NULL, "-walltime_guard_multiplier", &simCtx->walltimeGuardMultiplier, NULL); CHKERRQ(ierr);
482 ierr = PetscOptionsGetBool(NULL, NULL, "-runtime_memory_log_enabled", &simCtx->runtimeMemoryLogEnabled, NULL); CHKERRQ(ierr);
483 ierr = PetscOptionsGetString(NULL, NULL, "-runtime_memory_log_file", simCtx->runtimeMemoryLogFile, PETSC_MAX_PATH_LEN, NULL); CHKERRQ(ierr);
484 ierr = PetscOptionsGetReal(NULL, NULL, "-walltime_guard_min_seconds", &simCtx->walltimeGuardMinSeconds, NULL); CHKERRQ(ierr);
485 ierr = PetscOptionsGetReal(NULL, NULL, "-walltime_guard_estimator_alpha", &simCtx->walltimeGuardEstimatorAlpha, NULL); CHKERRQ(ierr);
486
487 if (simCtx->walltimeGuardWarmupSteps <= 0) {
488 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Invalid value for -walltime_guard_warmup_steps: %d. Must be > 0.", simCtx->walltimeGuardWarmupSteps);
489 }
490 if (simCtx->walltimeGuardMultiplier <= 0.0 || simCtx->walltimeGuardMultiplier > 5.0) {
491 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Invalid value for -walltime_guard_multiplier: %.6f. Must be in (0, 5].", (double)simCtx->walltimeGuardMultiplier);
492 }
493 if (simCtx->walltimeGuardMinSeconds <= 0.0) {
494 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Invalid value for -walltime_guard_min_seconds: %.6f. Must be > 0.", (double)simCtx->walltimeGuardMinSeconds);
495 }
496 if (simCtx->walltimeGuardEstimatorAlpha <= 0.0 || simCtx->walltimeGuardEstimatorAlpha > 1.0) {
497 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Invalid value for -walltime_guard_estimator_alpha: %.6f. Must be in (0, 1].", (double)simCtx->walltimeGuardEstimatorAlpha);
498 }
499
500 if(strcmp(simCtx->eulerianSource,"solve")!= 0 && strcmp(simCtx->eulerianSource,"load") != 0 && strcmp(simCtx->eulerianSource,"analytical")!=0){
501 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);
502 }
503 if (simCtx->walltimeGuardEnabled) {
504 const char *job_start_env = getenv("PICURV_JOB_START_EPOCH");
505 const char *limit_env = getenv("PICURV_WALLTIME_LIMIT_SECONDS");
506 PetscBool job_start_ok = RuntimeWalltimeGuardParsePositiveSeconds(job_start_env, &simCtx->walltimeGuardJobStartEpochSeconds);
507 PetscBool limit_ok = RuntimeWalltimeGuardParsePositiveSeconds(limit_env, &simCtx->walltimeGuardLimitSeconds);
508
509 if (!job_start_ok || !limit_ok) {
510 simCtx->walltimeGuardActive = PETSC_FALSE;
512 simCtx->walltimeGuardLimitSeconds = 0.0;
513 LOG_ALLOW(
514 GLOBAL,
516 "Runtime walltime guard enabled but %s/%s are missing or invalid. Falling back to external shutdown signals only.\n",
517 "PICURV_JOB_START_EPOCH",
518 "PICURV_WALLTIME_LIMIT_SECONDS"
519 );
520 } else {
521 simCtx->walltimeGuardActive = PETSC_TRUE;
522 }
523 }
524
525 // --- Group 3
526 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 3: High-Level Physics & Model Selection Flags\n");
527 ierr = PetscOptionsGetInt(NULL, NULL, "-imm", &simCtx->immersed, NULL); CHKERRQ(ierr);
528 ierr = PetscOptionsGetInt(NULL, NULL, "-fsi", &simCtx->movefsi, NULL); CHKERRQ(ierr);
529 ierr = PetscOptionsGetInt(NULL, NULL, "-rfsi", &simCtx->rotatefsi, NULL); CHKERRQ(ierr);
530 ierr = PetscOptionsGetInt(NULL, NULL, "-sediment", &simCtx->sediment, NULL); CHKERRQ(ierr);
531 ierr = PetscOptionsGetInt(NULL, NULL, "-rheology", &simCtx->rheology, NULL); CHKERRQ(ierr);
532 ierr = PetscOptionsGetInt(NULL, NULL, "-inv", &simCtx->invicid, NULL); CHKERRQ(ierr);
533 ierr = PetscOptionsGetInt(NULL, NULL, "-TwoD", &simCtx->TwoD, NULL); CHKERRQ(ierr);
534 ierr = PetscOptionsGetInt(NULL, NULL, "-thin", &simCtx->thin, NULL); CHKERRQ(ierr);
535 ierr = PetscOptionsGetInt(NULL, NULL, "-mframe", &simCtx->moveframe, NULL); CHKERRQ(ierr);
536 ierr = PetscOptionsGetInt(NULL, NULL, "-rframe", &simCtx->rotateframe, NULL); CHKERRQ(ierr);
537 ierr = PetscOptionsGetInt(NULL, NULL, "-blk", &simCtx->blank, NULL); CHKERRQ(ierr);
538 ierr = PetscOptionsGetInt(NULL, NULL, "-dgf_z", &simCtx->dgf_z, NULL); CHKERRQ(ierr);
539 ierr = PetscOptionsGetInt(NULL, NULL, "-dgf_y", &simCtx->dgf_y, NULL); CHKERRQ(ierr);
540 ierr = PetscOptionsGetInt(NULL, NULL, "-dgf_x", &simCtx->dgf_x, NULL); CHKERRQ(ierr);
541 ierr = PetscOptionsGetInt(NULL, NULL, "-dgf_az", &simCtx->dgf_az, NULL); CHKERRQ(ierr);
542 ierr = PetscOptionsGetInt(NULL, NULL, "-dgf_ay", &simCtx->dgf_ay, NULL); CHKERRQ(ierr);
543 ierr = PetscOptionsGetInt(NULL, NULL, "-dgf_ax", &simCtx->dgf_ax, NULL); CHKERRQ(ierr);
544 ierr = PetscOptionsGetString(NULL,NULL,"-analytical_type",simCtx->AnalyticalSolutionType,sizeof(simCtx->AnalyticalSolutionType),NULL);CHKERRQ(ierr);
545
546 // --- Group 4
547 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 4: Specific Simulation Case Flags \n");
548 ierr = PetscOptionsGetInt(NULL, NULL, "-cop", &simCtx->cop, NULL); CHKERRQ(ierr);
549 ierr = PetscOptionsGetInt(NULL, NULL, "-fish", &simCtx->fish, NULL); CHKERRQ(ierr);
550 ierr = PetscOptionsGetInt(NULL, NULL, "-pizza", &simCtx->pizza, NULL); CHKERRQ(ierr);
551 ierr = PetscOptionsGetInt(NULL, NULL, "-turbine", &simCtx->turbine, NULL); CHKERRQ(ierr);
552 ierr = PetscOptionsGetInt(NULL, NULL, "-fishcyl", &simCtx->fishcyl, NULL); CHKERRQ(ierr);
553 ierr = PetscOptionsGetInt(NULL, NULL, "-eel", &simCtx->eel, NULL); CHKERRQ(ierr);
554 ierr = PetscOptionsGetInt(NULL, NULL, "-cstart", &simCtx->fish_c, NULL); CHKERRQ(ierr);
555 ierr = PetscOptionsGetInt(NULL, NULL, "-wing", &simCtx->wing, NULL); CHKERRQ(ierr);
556 ierr = PetscOptionsGetInt(NULL, NULL, "-mhv", &simCtx->MHV, NULL); CHKERRQ(ierr);
557 ierr = PetscOptionsGetInt(NULL, NULL, "-hydro", &simCtx->hydro, NULL); CHKERRQ(ierr);
558 ierr = PetscOptionsGetInt(NULL, NULL, "-lv", &simCtx->LV, NULL); CHKERRQ(ierr);
559 ierr = PetscOptionsGetInt(NULL, NULL, "-Pipe", &simCtx->Pipe, NULL); CHKERRQ(ierr);
560 ierr = PetscOptionsGetInt(NULL, NULL, "-Turbulent_Channel_z", &simCtx->channelz, NULL); CHKERRQ(ierr);
561 ierr = PetscOptionsGetReal(NULL,NULL,"-driven_flow_initial_force",&simCtx->drivingForceMagnitude,NULL);CHKERRQ(ierr);
562 ierr = PetscOptionsGetReal(NULL,NULL,"-driven_flow_scaling_factor",&simCtx->forceScalingFactor,NULL);CHKERRQ(ierr);
563 // --- Group 5
564 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 5: Solver & Numerics Parameters \n");
565 char mom_solver_type_char[PETSC_MAX_PATH_LEN];
566 char solution_convergence_mode_char[PETSC_MAX_PATH_LEN];
567 PetscBool mom_solver_type_flg = PETSC_FALSE;
568 PetscBool solution_convergence_mode_flg = PETSC_FALSE;
569 ierr = PetscOptionsGetString(NULL, NULL, "-mom_solver_type", mom_solver_type_char, sizeof(mom_solver_type_char), &mom_solver_type_flg); CHKERRQ(ierr);
570 ierr = PetscOptionsGetInt(NULL, NULL, "-mom_max_pseudo_steps", &simCtx->mom_max_pseudo_steps, NULL); CHKERRQ(ierr);
571 ierr = PetscOptionsGetReal(NULL, NULL, "-mom_atol", &simCtx->mom_atol, NULL); CHKERRQ(ierr);
572 ierr = PetscOptionsGetReal(NULL, NULL, "-mom_rtol", &simCtx->mom_rtol, NULL); CHKERRQ(ierr);
573 ierr = PetscOptionsGetReal(NULL, NULL, "-mom_resid_atol", &simCtx->mom_resid_atol, NULL); CHKERRQ(ierr);
574 ierr = PetscOptionsGetReal(NULL, NULL, "-mom_resid_rtol", &simCtx->mom_resid_rtol, NULL); CHKERRQ(ierr);
575 ierr = PetscOptionsGetReal(NULL, NULL, "-imp_stol", &simCtx->imp_stol, NULL); CHKERRQ(ierr);
576 ierr = PetscOptionsGetInt(NULL, NULL, "-central", &simCtx->central, NULL); CHKERRQ(ierr);
577 ierr = PetscOptionsGetString(NULL, NULL, "-solution_convergence_mode",
578 solution_convergence_mode_char, sizeof(solution_convergence_mode_char),
579 &solution_convergence_mode_flg); CHKERRQ(ierr);
580 ierr = PetscOptionsGetInt(NULL, NULL, "-solution_convergence_period_steps", &simCtx->solutionConvergencePeriodSteps, NULL); CHKERRQ(ierr);
581 ierr = PetscOptionsGetInt(NULL, NULL, "-solution_convergence_window_steps", &simCtx->solutionConvergenceWindowSteps, NULL); CHKERRQ(ierr);
582
583 // Keep parser acceptance aligned with the enum and FlowSolver dispatch.
584 if (mom_solver_type_flg) {
585 if(strcmp(mom_solver_type_char, "DUALTIME_PICARD_JAMESON_RK") == 0 ||
586 strcmp(mom_solver_type_char, "DUALTIME_PICARD_RK4") == 0) {
588 } else if (strcmp(mom_solver_type_char, "EXPLICIT_RK") == 0) {
590 } else if (strcmp(mom_solver_type_char, "newton_krylov") == 0) {
592 } else {
593 LOG(GLOBAL, LOG_ERROR, "Invalid value for -mom_solver_type: '%s'. Valid options are: 'DUALTIME_PICARD_JAMESON_RK', 'EXPLICIT_RK', 'newton_krylov'.\n", mom_solver_type_char);
594 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Invalid value for -mom_solver_type: '%s'.", mom_solver_type_char);
595 }
596 }
597
598 if (solution_convergence_mode_flg) {
599 if (strcmp(solution_convergence_mode_char, "STEADY_DETERMINISTIC") == 0) {
601 } else if (strcmp(solution_convergence_mode_char, "PERIODIC_DETERMINISTIC") == 0) {
603 } else if (strcmp(solution_convergence_mode_char, "STATISTICAL_STEADY") == 0) {
605 } else if (strcmp(solution_convergence_mode_char, "TRANSIENT") == 0) {
607 } else {
608 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
609 "Invalid value for -solution_convergence_mode: '%s'.", solution_convergence_mode_char);
610 }
611 }
612
614 simCtx->solutionConvergencePeriodSteps <= 0) {
615 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
616 "solution convergence mode PERIODIC_DETERMINISTIC requires -solution_convergence_period_steps > 0.");
617 }
619 simCtx->solutionConvergenceWindowSteps <= 0) {
620 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
621 "solution convergence mode STATISTICAL_STEADY requires -solution_convergence_window_steps > 0.");
622 }
623
624 // --- Multigrid Options ---
625 ierr = PetscOptionsGetInt(NULL, NULL, "-mg_level", &simCtx->mglevels, NULL); CHKERRQ(ierr);
626 ierr = PetscOptionsGetInt(NULL, NULL, "-mg_max_it", &simCtx->mg_MAX_IT, NULL); CHKERRQ(ierr);
627 ierr = PetscOptionsGetInt(NULL, NULL, "-mg_idx", &simCtx->mg_idx, NULL); CHKERRQ(ierr);
628 ierr = PetscOptionsGetInt(NULL, NULL, "-mg_pre_it", &simCtx->mg_preItr, NULL); CHKERRQ(ierr);
629 ierr = PetscOptionsGetInt(NULL, NULL, "-mg_post_it", &simCtx->mg_poItr, NULL); CHKERRQ(ierr);
630
631 // --- Other Solver Options ---
632 ierr = PetscOptionsGetInt(NULL, NULL, "-poisson", &simCtx->poisson, NULL); CHKERRQ(ierr);
633 ierr = PetscOptionsGetReal(NULL, NULL, "-poisson_tol", &simCtx->poisson_tol, NULL); CHKERRQ(ierr);
634 ierr = PetscOptionsGetInt(NULL, NULL, "-str", &simCtx->STRONG_COUPLING, NULL); CHKERRQ(ierr);
635 ierr = PetscOptionsGetReal(NULL, NULL, "-ren", &simCtx->ren, NULL); CHKERRQ(ierr);
636 ierr = PetscOptionsGetReal(NULL, NULL, "-pseudo_cfl", &simCtx->pseudo_cfl, NULL); CHKERRQ(ierr);
637 ierr = PetscOptionsGetReal(NULL, NULL, "-max_pseudo_cfl", &simCtx->max_pseudo_cfl, NULL); CHKERRQ(ierr);
638 ierr = PetscOptionsGetReal(NULL, NULL, "-min_pseudo_cfl", &simCtx->min_pseudo_cfl, NULL); CHKERRQ(ierr);
639 ierr = PetscOptionsGetReal(NULL, NULL, "-pseudo_cfl_reduction_factor", &simCtx->pseudo_cfl_reduction_factor, NULL); CHKERRQ(ierr);
640 ierr = PetscOptionsGetReal(NULL, NULL, "-pseudo_cfl_growth_factor", &simCtx->pseudo_cfl_growth_factor, NULL); CHKERRQ(ierr);
641 // Read the deprecated RK4 spelling first so the canonical Jameson option wins if both are present.
642 ierr = PetscOptionsGetReal(NULL,NULL, "-mom_dt_rk4_residual_norm_noise_allowance_factor",&simCtx->mom_dt_jameson_residual_norm_noise_allowance_factor,NULL);CHKERRQ(ierr);
643 ierr = PetscOptionsGetReal(NULL,NULL, "-mom_dt_jameson_residual_norm_noise_allowance_factor",&simCtx->mom_dt_jameson_residual_norm_noise_allowance_factor,NULL);CHKERRQ(ierr);
644 ierr = PetscOptionsGetBool(NULL, NULL, "-no_pseudo_cfl_backtrack", &simCtx->no_pseudo_cfl_backtrack, NULL); CHKERRQ(ierr);
645 ierr = PetscOptionsGetReal(NULL, NULL, "-mom_ratio_ema_alpha", &simCtx->mom_ratio_ema_alpha, NULL); CHKERRQ(ierr);
646 if (simCtx->min_pseudo_cfl <= 0.0 ||
647 simCtx->pseudo_cfl < simCtx->min_pseudo_cfl ||
648 simCtx->pseudo_cfl > simCtx->max_pseudo_cfl) {
649 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
650 "Pseudo-CFL controls require 0 < minimum <= initial <= maximum.");
651 }
652 if (simCtx->pseudo_cfl_growth_factor < 1.0 ||
653 simCtx->pseudo_cfl_reduction_factor <= 0.0 ||
654 simCtx->pseudo_cfl_reduction_factor >= 1.0 ||
656 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
657 "Pseudo-CFL controls require growth_factor >= 1, 0 < reduction_factor < 1, and noise allowance >= 1.");
658 }
659 if (simCtx->mom_ratio_ema_alpha < 0.0 || simCtx->mom_ratio_ema_alpha > 1.0) {
660 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
661 "-mom_ratio_ema_alpha must be in [0, 1].");
662 }
663 ierr = PetscOptionsHasName(NULL, NULL, "-ps_ksp_pic_monitor_true_residual", &simCtx->ps_ksp_pic_monitor_true_residual); CHKERRQ(ierr);
664 ierr = PetscOptionsGetBool(NULL, NULL, "-mom_nk_pic_monitor", &simCtx->mom_nk_monitor_history, NULL); CHKERRQ(ierr);
665 {
666 PetscInt ic_mode = (PetscInt)simCtx->initialConditionMode;
667 PetscInt ic_field = (PetscInt)simCtx->initialConditionField;
668 ierr = PetscOptionsGetInt(NULL, NULL, "-finit", &ic_mode, NULL); CHKERRQ(ierr);
669 ierr = PetscOptionsGetInt(NULL, NULL, "-ic_field", &ic_field, NULL); CHKERRQ(ierr);
672 }
673 ierr = PetscOptionsGetString(NULL, NULL, "-ic_dir", simCtx->initialConditionDirectory,
674 sizeof(simCtx->initialConditionDirectory), NULL); CHKERRQ(ierr);
676 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
677 "Invalid value for -finit. Expected an initial-condition mode in [0,4], got %d.",
678 simCtx->initialConditionMode);
679 }
681 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
682 "Invalid value for -ic_field. Expected 0 (Ucat) or 1 (Ucont), got %d.",
683 simCtx->initialConditionField);
684 }
685 ierr = PetscOptionsGetReal(NULL, NULL, "-ucont_x", &simCtx->InitialConstantContra.x, NULL); CHKERRQ(ierr);
686 ierr = PetscOptionsGetReal(NULL, NULL, "-ucont_y", &simCtx->InitialConstantContra.y, NULL); CHKERRQ(ierr);
687 ierr = PetscOptionsGetReal(NULL, NULL, "-ucont_z", &simCtx->InitialConstantContra.z, NULL); CHKERRQ(ierr);
688 {
689 PetscInt fd_int = (PetscInt)FLOW_DIR_UNSET;
690 PetscBool fd_set = PETSC_FALSE;
691 ierr = PetscOptionsGetInt(NULL, NULL, "-flow_direction", &fd_int, &fd_set); CHKERRQ(ierr);
692 if (fd_set) simCtx->flowDirection = (FlowDirection)fd_int;
693 }
694 ierr = PetscOptionsGetReal(NULL, NULL, "-ic_velocity_physical", &simCtx->icVelocityPhysical, NULL); CHKERRQ(ierr);
695 ierr = PetscOptionsGetReal(NULL, NULL, "-analytical_uniform_u", &simCtx->AnalyticalUniformVelocity.x, NULL); CHKERRQ(ierr);
696 ierr = PetscOptionsGetReal(NULL, NULL, "-analytical_uniform_v", &simCtx->AnalyticalUniformVelocity.y, NULL); CHKERRQ(ierr);
697 ierr = PetscOptionsGetReal(NULL, NULL, "-analytical_uniform_w", &simCtx->AnalyticalUniformVelocity.z, NULL); CHKERRQ(ierr);
698 PetscBool verification_scalar_value_set = PETSC_FALSE;
699 PetscBool verification_scalar_phi0_set = PETSC_FALSE;
700 PetscBool verification_scalar_slope_x_set = PETSC_FALSE;
701 PetscBool verification_scalar_amplitude_set = PETSC_FALSE;
702 PetscBool verification_scalar_kx_set = PETSC_FALSE;
703 PetscBool verification_scalar_ky_set = PETSC_FALSE;
704 PetscBool verification_scalar_kz_set = PETSC_FALSE;
705 ierr = PetscOptionsGetString(NULL, NULL, "-verification_diffusivity_mode",
707 sizeof(simCtx->verificationDiffusivity.mode), NULL); CHKERRQ(ierr);
708 ierr = PetscOptionsGetString(NULL, NULL, "-verification_diffusivity_profile",
710 sizeof(simCtx->verificationDiffusivity.profile), NULL); CHKERRQ(ierr);
711 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_diffusivity_gamma0",
712 &simCtx->verificationDiffusivity.gamma0, NULL); CHKERRQ(ierr);
713 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_diffusivity_slope_x",
714 &simCtx->verificationDiffusivity.slope_x, NULL); CHKERRQ(ierr);
715 ierr = PetscOptionsGetString(NULL, NULL, "-verification_scalar_mode",
716 simCtx->verificationScalar.mode,
717 sizeof(simCtx->verificationScalar.mode), NULL); CHKERRQ(ierr);
718 ierr = PetscOptionsGetString(NULL, NULL, "-verification_scalar_profile",
720 sizeof(simCtx->verificationScalar.profile), NULL); CHKERRQ(ierr);
721 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_value",
722 &simCtx->verificationScalar.value, &verification_scalar_value_set); CHKERRQ(ierr);
723 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_phi0",
724 &simCtx->verificationScalar.phi0, &verification_scalar_phi0_set); CHKERRQ(ierr);
725 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_slope_x",
726 &simCtx->verificationScalar.slope_x, &verification_scalar_slope_x_set); CHKERRQ(ierr);
727 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_amplitude",
728 &simCtx->verificationScalar.amplitude, &verification_scalar_amplitude_set); CHKERRQ(ierr);
729 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_kx",
730 &simCtx->verificationScalar.kx, &verification_scalar_kx_set); CHKERRQ(ierr);
731 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_ky",
732 &simCtx->verificationScalar.ky, &verification_scalar_ky_set); CHKERRQ(ierr);
733 ierr = PetscOptionsGetReal(NULL, NULL, "-verification_scalar_kz",
734 &simCtx->verificationScalar.kz, &verification_scalar_kz_set); CHKERRQ(ierr);
736 (PetscBool)(simCtx->verificationDiffusivity.mode[0] != '\0' ||
737 simCtx->verificationDiffusivity.profile[0] != '\0');
739 (PetscBool)(simCtx->verificationScalar.mode[0] != '\0' ||
740 simCtx->verificationScalar.profile[0] != '\0');
741 if (simCtx->verificationDiffusivity.enabled) {
742 if (strcmp(simCtx->eulerianSource, "analytical") != 0) {
743 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
744 "verification diffusivity overrides require -euler_field_source \"analytical\".");
745 }
746 if (strcmp(simCtx->verificationDiffusivity.mode, "analytical") != 0) {
747 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
748 "Unsupported -verification_diffusivity_mode '%s'. Only 'analytical' is supported.",
750 }
751 if (strcmp(simCtx->verificationDiffusivity.profile, "LINEAR_X") != 0) {
752 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
753 "Unsupported -verification_diffusivity_profile '%s'. Only 'LINEAR_X' is supported.",
755 }
756 }
757 if (simCtx->verificationScalar.enabled) {
758 if (strcmp(simCtx->eulerianSource, "analytical") != 0) {
759 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
760 "verification scalar overrides require -euler_field_source \"analytical\".");
761 }
762 if (strcmp(simCtx->verificationScalar.mode, "analytical") != 0) {
763 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
764 "Unsupported -verification_scalar_mode '%s'. Only 'analytical' is supported.",
765 simCtx->verificationScalar.mode);
766 }
767 if (strcmp(simCtx->verificationScalar.profile, "CONSTANT") == 0) {
768 if (!verification_scalar_value_set) {
769 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
770 "verification scalar profile CONSTANT requires -verification_scalar_value.");
771 }
772 } else if (strcmp(simCtx->verificationScalar.profile, "LINEAR_X") == 0) {
773 if (!verification_scalar_phi0_set || !verification_scalar_slope_x_set) {
774 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
775 "verification scalar profile LINEAR_X requires -verification_scalar_phi0 and -verification_scalar_slope_x.");
776 }
777 } else if (strcmp(simCtx->verificationScalar.profile, "SIN_PRODUCT") == 0) {
778 if (!verification_scalar_amplitude_set || !verification_scalar_kx_set ||
779 !verification_scalar_ky_set || !verification_scalar_kz_set) {
780 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
781 "verification scalar profile SIN_PRODUCT requires -verification_scalar_amplitude, -verification_scalar_kx, -verification_scalar_ky, and -verification_scalar_kz.");
782 }
783 } else {
784 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
785 "Unsupported -verification_scalar_profile '%s'. Supported profiles: CONSTANT, LINEAR_X, SIN_PRODUCT.",
787 }
788 }
789 // NOTE: cdisx,cdisy,cdisz haven't been parsed, add if necessary.
790
791 // --- Group 6
792 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 6: Physical & Geometric Parameters \n");
793 ierr = PetscOptionsGetReal(NULL,NULL,"-schmidt_number",&simCtx->schmidt_number,NULL);CHKERRQ(ierr);
794 ierr = PetscOptionsGetReal(NULL,NULL,"-turb_schmidt_number",&simCtx->Turbulent_schmidt_number,NULL);CHKERRQ(ierr);
795 ierr = PetscOptionsGetInt(NULL, NULL, "-no_of_bodies", &simCtx->NumberOfBodies, NULL); CHKERRQ(ierr);
796 ierr = PetscOptionsGetReal(NULL,NULL,"-wall_roughness",&simCtx->wall_roughness_height,NULL);CHKERRQ(ierr);
797 // NOTE: angle is not parsed in the original code, it set programmatically. We will follow that.
798 // NOTE: max_angle is calculated based on other flags (like MHV) in the legacy code.
799 // We will defer that logic to a later setup stage and not parse them directly.
800 // The Scaling Information is calculated here
801 ierr = ParseScalingInformation(simCtx); CHKERRQ(ierr);
802
803 // --- Group 7
804 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 7: Grid, Domain, and Boundary Condition Settings \n");
805 ierr = PetscOptionsGetInt(NULL, NULL, "-nblk", &simCtx->block_number, NULL); CHKERRQ(ierr); // This is also a modern option
806 ierr = PetscOptionsGetInt(NULL, NULL, "-inlet", &simCtx->inletprofile, NULL); CHKERRQ(ierr);
807 ierr = PetscOptionsGetInt(NULL, NULL, "-Ogrid", &simCtx->Ogrid, NULL); CHKERRQ(ierr);
808 // NOTE: channelz was not parsed, likely set programmatically. We will omit its parsing call.
809 ierr = PetscOptionsGetInt(NULL, NULL, "-grid1d", &simCtx->grid1d, NULL); CHKERRQ(ierr);
810 ierr = PetscOptionsGetBool(NULL, NULL, "-grid", &simCtx->generate_grid, NULL); CHKERRQ(ierr);
811 ierr = PetscOptionsGetString(NULL, NULL, "-grid_file", simCtx->grid_file, PETSC_MAX_PATH_LEN, NULL); CHKERRQ(ierr);
812 ierr = PetscOptionsGetInt(NULL, NULL, "-da_processors_x", &simCtx->da_procs_x, NULL); CHKERRQ(ierr);
813 ierr = PetscOptionsGetInt(NULL, NULL, "-da_processors_y", &simCtx->da_procs_y, NULL); CHKERRQ(ierr);
814 ierr = PetscOptionsGetInt(NULL, NULL, "-da_processors_z", &simCtx->da_procs_z, NULL); CHKERRQ(ierr);
815 ierr = PetscOptionsGetInt(NULL, NULL, "-pbc_domain", &simCtx->blkpbc, NULL); CHKERRQ(ierr);
816 // NOTE: pseudo_periodic was not parsed. We will omit its parsing call.
817 ierr = PetscOptionsGetReal(NULL, NULL, "-grid_rotation_angle", &simCtx->grid_rotation_angle, NULL); CHKERRQ(ierr);
818 ierr = PetscOptionsGetReal(NULL, NULL, "-Croty", &simCtx->Croty, NULL); CHKERRQ(ierr);
819 ierr = PetscOptionsGetReal(NULL, NULL, "-Crotz", &simCtx->Crotz, NULL); CHKERRQ(ierr);
820 PetscBool bcs_flg;
821 char file_list_str[PETSC_MAX_PATH_LEN * 10]; // Buffer for comma-separated list
822
823 ierr = PetscOptionsGetString(NULL, NULL, "-bcs_files", file_list_str, sizeof(file_list_str), &bcs_flg); CHKERRQ(ierr);
824 ierr = PetscOptionsGetReal(NULL, NULL, "-U_bc", &simCtx->U_bc, NULL); CHKERRQ(ierr);
825
826 if (bcs_flg) {
827 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Found -bcs_files option, overriding default.\n");
828
829 // A. Clean up the default memory we allocated in Phase 1.
830 ierr = PetscFree(simCtx->bcs_files[0]); CHKERRQ(ierr);
831 ierr = PetscFree(simCtx->bcs_files); CHKERRQ(ierr);
832 simCtx->num_bcs_files = 0;
833 simCtx->bcs_files = NULL;
834
835 // B. Parse the user-provided comma-separated list.
836 char *token;
837 char *str_copy;
838 ierr = PetscStrallocpy(file_list_str, &str_copy); CHKERRQ(ierr);
839
840 // First pass: count the number of files.
841 token = strtok(str_copy, ",");
842 while (token) {
843 simCtx->num_bcs_files++;
844 token = strtok(NULL, ",");
845 }
846 ierr = PetscFree(str_copy); CHKERRQ(ierr);
847
848 // Second pass: allocate memory and store the filenames.
849 ierr = PetscMalloc1(simCtx->num_bcs_files, &simCtx->bcs_files); CHKERRQ(ierr);
850 ierr = PetscStrallocpy(file_list_str, &str_copy); CHKERRQ(ierr);
851 token = strtok(str_copy, ",");
852 for (PetscInt i = 0; i < simCtx->num_bcs_files; i++) {
853 ierr = PetscStrallocpy(token, &simCtx->bcs_files[i]); CHKERRQ(ierr);
854 token = strtok(NULL, ",");
855 }
856 ierr = PetscFree(str_copy); CHKERRQ(ierr);
857 }
858
859
860 // --- Group 8
861 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 8: Turbulence Modeling (LES/RANS) \n");
862 PetscInt temp_les_model;
863 ierr = PetscOptionsGetInt(NULL, NULL, "-les", &temp_les_model, NULL); CHKERRQ(ierr);
864 simCtx->les = (LESModelType)temp_les_model;
865 ierr = PetscOptionsGetInt(NULL, NULL, "-rans", &simCtx->rans, NULL); CHKERRQ(ierr);
866 ierr = PetscOptionsGetInt(NULL, NULL, "-wallfunction", &simCtx->wallfunction, NULL); CHKERRQ(ierr);
867 ierr = PetscOptionsGetInt(NULL, NULL, "-mixed", &simCtx->mixed, NULL); CHKERRQ(ierr);
868 ierr = PetscOptionsGetInt(NULL, NULL, "-clark", &simCtx->clark, NULL); CHKERRQ(ierr);
869 ierr = PetscOptionsGetInt(NULL, NULL, "-dynamic_freq", &simCtx->dynamic_freq, NULL); CHKERRQ(ierr);
870 ierr = PetscOptionsGetReal(NULL, NULL, "-max_cs", &simCtx->max_cs, NULL); CHKERRQ(ierr);
871 ierr = PetscOptionsGetReal(NULL, NULL, "-const_cs", &simCtx->Const_CS, NULL); CHKERRQ(ierr);
872 ierr = PetscOptionsGetInt(NULL, NULL, "-testfilter_ik", &simCtx->testfilter_ik, NULL); CHKERRQ(ierr);
873 ierr = PetscOptionsGetInt(NULL, NULL, "-testfilter_1d", &simCtx->testfilter_1d, NULL); CHKERRQ(ierr);
874 ierr = PetscOptionsGetInt(NULL, NULL, "-i_homo_filter", &simCtx->i_homo_filter, NULL); CHKERRQ(ierr);
875 ierr = PetscOptionsGetInt(NULL, NULL, "-j_homo_filter", &simCtx->j_homo_filter, NULL); CHKERRQ(ierr);
876 ierr = PetscOptionsGetInt(NULL, NULL, "-k_homo_filter", &simCtx->k_homo_filter, NULL); CHKERRQ(ierr);
877 ierr = PetscOptionsGetBool(NULL, NULL, "-averaging", &simCtx->averaging, NULL); CHKERRQ(ierr);
878
879 // --- Group 9
880 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 9: Particle / DMSwarm Data & Settings \n");
881 ierr = PetscOptionsGetInt(NULL, NULL, "-numParticles", &simCtx->np, NULL); CHKERRQ(ierr);
882 ierr = PetscOptionsGetBool(NULL, NULL, "-read_fields", &simCtx->readFields, NULL); CHKERRQ(ierr);
883 PetscInt temp_pinit = (PetscInt)PARTICLE_INIT_SURFACE_RANDOM;
884 ierr = PetscOptionsGetInt(NULL, NULL, "-pinit", &temp_pinit, NULL); CHKERRQ(ierr);
886 PetscInt temp_interp = (PetscInt)INTERP_TRILINEAR;
887 ierr = PetscOptionsGetInt(NULL, NULL, "-interpolation_method", &temp_interp, NULL); CHKERRQ(ierr);
888 simCtx->interpolationMethod = (InterpolationMethod)temp_interp;
889 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Interpolation method: %s\n",
890 simCtx->interpolationMethod == INTERP_TRILINEAR ? "Trilinear (direct cell-center)" : "CornerAveraged (legacy)");
891 ierr = PetscOptionsGetReal(NULL, NULL, "-psrc_x", &simCtx->psrc_x, NULL); CHKERRQ(ierr);
892 ierr = PetscOptionsGetReal(NULL, NULL, "-psrc_y", &simCtx->psrc_y, NULL); CHKERRQ(ierr);
893 ierr = PetscOptionsGetReal(NULL, NULL, "-psrc_z", &simCtx->psrc_z, NULL); CHKERRQ(ierr);
894 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Particle initialization mode: %s. Point source: (%.6f, %.6f, %.6f)\n",
896 simCtx->psrc_x, simCtx->psrc_y, simCtx->psrc_z);
897 ierr = PetscOptionsGetString(NULL,NULL,"-particle_restart_mode",simCtx->particleRestartMode,sizeof(simCtx->particleRestartMode),NULL); CHKERRQ(ierr);
898 // Validation for Particle Restart Mode
899 if (strcmp(simCtx->particleRestartMode, "load") != 0 && strcmp(simCtx->particleRestartMode, "init") != 0) {
900 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Invalid value for -particle_restart_mode. Must be 'load' or 'init'. You provided '%s'.", simCtx->particleRestartMode);
901 }
902 ierr = InitializeBrownianRNG(simCtx); CHKERRQ(ierr);
903 // --- Group 10
904 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 10: Immersed Boundary & FSI Data Object Pointers \n");
905 ierr = PetscOptionsGetBool(NULL, NULL, "-rs_fsi", &simCtx->rstart_fsi, NULL); CHKERRQ(ierr);
906 ierr = PetscOptionsGetInt(NULL, NULL, "-duplicate", &simCtx->duplicate, NULL); CHKERRQ(ierr);
907
908 // --- Group 11
909 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 11: Top-Level Managers & Custom Configuration \n");
910 ierr = PetscOptionsGetInt(NULL, NULL, "-logfreq", &simCtx->LoggingFrequency, NULL); CHKERRQ(ierr);
911
912 if (simCtx->num_bcs_files != simCtx->block_number) {
913 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);
914 }
915
916 // --- Group 12
917 LOG_ALLOW(GLOBAL,LOG_DEBUG, "Parsing Group 12: Post-Processing Information.\n");
918 // This logic determines the Post Processing configuration and STORES it in simCtx for later reference and cleanup.
919 ierr = PetscOptionsGetString(NULL,NULL,"-postprocessing_config_file",simCtx->PostprocessingControlFile,PETSC_MAX_PATH_LEN,NULL); CHKERRQ(ierr);
920 /* Parse post settings for both solver and post-processor binaries using the single pre-allocated pps object. */
921 ierr = ParsePostProcessingSettings(simCtx);
922
923 // === 5. Dependent Parameter Calculations ================================
924 // Some parameters depend on others, so we calculate them here.
925 simCtx->StartTime = (PetscReal)simCtx->StartStep*simCtx->dt;
926 simCtx->ti = simCtx->StartTime;
927 simCtx->step = simCtx->StartStep;
928
929 // === 5. Log Summary and Finalize Setup ==================================
930 LOG_ALLOW(GLOBAL, LOG_DEBUG, "-- Console Output Functions [Total : %d] : --\n", simCtx->nAllowed);
931 for (PetscInt i = 0; i < simCtx->nAllowed; ++i) {
932 LOG_ALLOW(GLOBAL, LOG_DEBUG, " [%2d] «%s»\n", i, simCtx->allowedFuncs[i]);
933 }
934
935 LOG_ALLOW(GLOBAL, LOG_INFO, "Configuration complete. Key parameters:\n");
936 LOG_ALLOW(GLOBAL, LOG_INFO, " - Run mode: %s\n", simCtx->OnlySetup ? "SETUP ONLY" : "Full Simulation");
937 LOG_ALLOW(GLOBAL, LOG_INFO, " - Time steps: %d (from %d to %d)\n", simCtx->StepsToRun, simCtx->StartStep, simCtx->StartStep + simCtx->StepsToRun);
938 LOG_ALLOW(GLOBAL, LOG_INFO, " - Time step size (dt): %g\n", simCtx->dt);
939 if (simCtx->tiout > 0) {
940 LOG_ALLOW(GLOBAL, LOG_INFO, " - Field/restart output cadence: every %d step(s)\n", simCtx->tiout);
941 } else {
942 LOG_ALLOW(GLOBAL, LOG_INFO, " - Field/restart output cadence: DISABLED\n");
943 }
944 LOG_ALLOW(GLOBAL, LOG_INFO, " - Immersed Boundary: %s\n", simCtx->immersed ? "ENABLED" : "DISABLED");
945 LOG_ALLOW(GLOBAL, LOG_INFO, " - Particles: %d\n", simCtx->np);
946 if (simCtx->np > 0) {
947 if (simCtx->particleConsoleOutputFreq > 0) {
948 LOG_ALLOW(GLOBAL, LOG_INFO, " - Particle console cadence: every %d step(s)\n", simCtx->particleConsoleOutputFreq);
949 } else {
950 LOG_ALLOW(GLOBAL, LOG_INFO, " - Particle console cadence: DISABLED\n");
951 }
952 LOG_ALLOW(GLOBAL, LOG_INFO, " - Particle console row subsampling: every %d particle(s)\n", simCtx->LoggingFrequency);
953 }
954 if (simCtx->StartStep > 0 && simCtx->np > 0) {
955 LOG_ALLOW(GLOBAL, LOG_INFO, " - Particle Restart Mode: %s\n", simCtx->particleRestartMode);
956 }
957
958 // --- Initialize PETSc's internal performance logging stage ---
959 ierr = PetscLogDefaultBegin(); CHKERRQ(ierr); // REDUNDANT but safe.
960 ierr = PetscMemorySetGetMaximumUsage(); CHKERRQ(ierr);
961
962 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Finished CreateSimulationContext successfully on rank %d.\n", simCtx->rank);
963
965 PetscFunctionReturn(0);
966}
PetscErrorCode ParsePostProcessingSettings(SimCtx *simCtx)
Initializes post-processing settings from a config file and command-line overrides.
Definition io.c:2264
PetscErrorCode ParseScalingInformation(SimCtx *simCtx)
Parses physical scaling parameters from command-line options.
Definition io.c:2412
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:827
#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:1927
@ 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:818
const char * ParticleInitializationToString(ParticleInitializationType ParticleInitialization)
Helper function to convert ParticleInitialization to a string representation.
Definition logging.c:723
PetscErrorCode InitializeBrownianRNG(SimCtx *simCtx)
Internal helper implementation: InitializeBrownianRNG().
Definition setup.c:3386
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:518
@ NO_LES_MODEL
Definition variables.h:519
PetscReal icVelocityPhysical
Definition variables.h:747
PetscInt MHV
Definition variables.h:720
PetscInt turbine
Definition variables.h:720
PetscBool mom_nk_monitor_history
Definition variables.h:740
PetscInt fishcyl
Definition variables.h:720
PetscInt clark
Definition variables.h:790
PetscInt movefsi
Definition variables.h:714
PetscBool continueMode
Definition variables.h:701
PetscInt moveframe
Definition variables.h:715
PetscInt TwoD
Definition variables.h:715
PetscInt pseudo_periodic
Definition variables.h:769
PetscInt fish_c
Definition variables.h:720
PetscInt dgf_z
Definition variables.h:716
PetscReal poisson_tol
Definition variables.h:729
PetscBool profilingFinalSummary
Definition variables.h:837
PetscReal schmidt_number
Definition variables.h:765
PetscMPIInt rank
Definition variables.h:687
char profilingTimestepFile[PETSC_MAX_PATH_LEN]
Definition variables.h:836
PetscInt fish
Definition variables.h:720
PetscInt LV
Definition variables.h:720
PetscReal angle
Definition variables.h:760
PetscReal Turbulent_schmidt_number
Definition variables.h:765
PetscInt64 searchLocatedCount
Definition variables.h:239
PetscInt thin
Definition variables.h:715
PetscInt grid1d
Definition variables.h:768
PetscReal mom_rtol
Definition variables.h:726
PetscInt64 searchLostCount
Definition variables.h:240
PetscInt da_procs_z
Definition variables.h:774
PetscInt blkpbc
Definition variables.h:769
PetscInt sediment
Definition variables.h:714
PetscReal targetVolumetricFlux
Definition variables.h:780
PetscBool walltimeGuardActive
Definition variables.h:839
PetscReal mom_last_lambda_max
Definition variables.h:739
PetscInt channelz
Definition variables.h:721
char euler_subdir[PETSC_MAX_PATH_LEN]
Definition variables.h:707
PetscReal walltimeGuardWarmupTotalSeconds
Definition variables.h:847
PetscReal forceScalingFactor
Definition variables.h:779
PetscReal pseudo_cfl_reduction_factor
Definition variables.h:733
InitialConditionMode initialConditionMode
Definition variables.h:742
PetscInt rans
Definition variables.h:789
ParticleInitializationType
Enumerator to identify the particle initialization strategy.
Definition variables.h:549
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
Definition variables.h:550
PetscReal StartTime
Definition variables.h:698
PetscInt dgf_az
Definition variables.h:716
PetscReal FluxOutSum
Definition variables.h:777
PetscBool walltimeGuardHasEWMA
Definition variables.h:849
PetscReal CMy_c
Definition variables.h:761
FlowDirection flowDirection
Definition variables.h:746
PetscBool runtimeMemoryLogEnabled
Enable the rank-reduced runtime memory log.
Definition variables.h:852
char ** bcs_files
Definition variables.h:776
PetscReal boundaryVelocityCorrection
Definition variables.h:782
PetscReal max_angle
Definition variables.h:760
PetscReal min_pseudo_cfl
Definition variables.h:734
PetscInt64 boundaryClampCount
Definition variables.h:246
PetscInt particlesLostLastStep
Definition variables.h:803
PetscInt duplicate
Definition variables.h:818
PetscInt tiout
Definition variables.h:696
PetscReal walltimeGuardMinSeconds
Definition variables.h:842
char allowedFile[PETSC_MAX_PATH_LEN]
Definition variables.h:822
PetscInt da_procs_y
Definition variables.h:774
PetscInt64 traversalStepsSum
Definition variables.h:241
PetscBool mom_last_converged
Definition variables.h:738
PetscInt testfilter_1d
Definition variables.h:792
PetscReal psrc_x
Definition variables.h:762
PetscReal ren
Definition variables.h:732
PetscReal Crotz
Definition variables.h:772
PetscInt mixed
Definition variables.h:790
IBMVNodes * ibmv
Definition variables.h:815
PetscInt64 searchPopulation
Definition variables.h:238
char output_dir[PETSC_MAX_PATH_LEN]
Definition variables.h:706
PetscReal walltimeGuardLatestStepSeconds
Definition variables.h:851
PetscReal dt
Definition variables.h:699
char runtimeMemoryLogFile[PETSC_MAX_PATH_LEN]
File name written under log_dir.
Definition variables.h:853
PetscBool runtimeMemoryLogStarted
True after rank 0 writes the log header.
Definition variables.h:854
PetscInt occupiedCellCount
Definition variables.h:807
PetscInt StepsToRun
Definition variables.h:695
char profilingTimestepMode[32]
Definition variables.h:835
PetscInt k_periodic
Definition variables.h:769
PetscInt inletprofile
Definition variables.h:768
PetscReal bulkVelocityCorrection
Definition variables.h:781
PetscReal cdisy
Definition variables.h:732
PetscReal mom_atol
Definition variables.h:726
PetscBool rstart_fsi
Definition variables.h:817
PetscInt currentSettlementPass
Definition variables.h:250
PetscInt np
Definition variables.h:796
PetscBool averaging
Definition variables.h:793
PetscBool no_pseudo_cfl_backtrack
Definition variables.h:736
PetscReal C_IEM
Definition variables.h:811
PetscInt ccc
Definition variables.h:785
PetscReal ratio
Definition variables.h:786
PetscInt mg_idx
Definition variables.h:727
PetscInt StartStep
Definition variables.h:694
PetscInt mg_MAX_IT
Definition variables.h:727
PetscBool OnlySetup
Definition variables.h:700
PetscInt rotatefsi
Definition variables.h:714
@ MOMENTUM_SOLVER_DUALTIME_PICARD_JAMESON_RK
Definition variables.h:534
@ MOMENTUM_SOLVER_EXPLICIT_RK
Definition variables.h:533
@ MOMENTUM_SOLVER_NEWTON_KRYLOV
Definition variables.h:535
PetscReal cdisz
Definition variables.h:732
PetscScalar x
Definition variables.h:101
PetscInt64 reSearchCount
Definition variables.h:242
PetscInt dgf_x
Definition variables.h:716
char * current_io_directory
Definition variables.h:711
PetscInt pizza
Definition variables.h:720
PetscReal MaxDiv
Definition variables.h:828
char grid_file[PETSC_MAX_PATH_LEN]
Definition variables.h:773
PetscReal max_cs
Definition variables.h:791
PetscInt invicid
Definition variables.h:715
char ** allowedFuncs
Definition variables.h:824
PetscInt64 bboxGuessFallbackCount
Definition variables.h:248
InterpolationMethod interpolationMethod
Definition variables.h:801
PetscReal psrc_z
Point source location for PARTICLE_INIT_POINT_SOURCE.
Definition variables.h:762
PetscInt mg_poItr
Definition variables.h:727
PetscInt STRONG_COUPLING
Definition variables.h:730
VerificationScalarConfig verificationScalar
Definition variables.h:756
PetscReal max_pseudo_cfl
Definition variables.h:734
PetscInt MaxDivx
Definition variables.h:829
PetscInt poisson
Definition variables.h:728
PetscInt k_homo_filter
Definition variables.h:792
char profilingSelectedFuncsFile[PETSC_MAX_PATH_LEN]
Definition variables.h:831
PetscInt MaxDivy
Definition variables.h:829
PetscInt NumberOfBodies
Definition variables.h:759
char particleRestartMode[16]
Definition variables.h:802
PetscInt Ogrid
Definition variables.h:768
PetscInt64 bboxGuessSuccessCount
Definition variables.h:247
char particle_subdir[PETSC_MAX_PATH_LEN]
Definition variables.h:708
PetscInt MaxDivz
Definition variables.h:829
BoundingBox * bboxlist
Definition variables.h:799
PetscInt j_homo_filter
Definition variables.h:792
PetscInt eel
Definition variables.h:720
char log_dir[PETSC_MAX_PATH_LEN]
Definition variables.h:709
PetscInt MaxDivFlatArg
Definition variables.h:829
PetscReal FluxInSum
Definition variables.h:777
PetscInt walltimeGuardCompletedSteps
Definition variables.h:846
PetscInt64 maxParticlePassDepth
Definition variables.h:249
PetscReal CMz_c
Definition variables.h:761
PetscInt64 maxTraversalSteps
Definition variables.h:243
PetscBool generate_grid
Definition variables.h:770
Cmpnts AnalyticalUniformVelocity
Definition variables.h:748
char eulerianSource[PETSC_MAX_PATH_LEN]
Definition variables.h:704
PetscReal imp_stol
Definition variables.h:726
PetscInt nAllowed
Definition variables.h:825
PetscBool walltimeGuardEnabled
Definition variables.h:838
PetscReal wall_roughness_height
Definition variables.h:764
PetscBool useProfilingSelectedFuncsCfg
Definition variables.h:832
PetscInt walltimeGuardWarmupSteps
Definition variables.h:840
ParticleInitializationType ParticleInitialization
Definition variables.h:800
PetscReal mom_dt_jameson_residual_norm_noise_allowance_factor
Definition variables.h:735
PetscScalar z
Definition variables.h:101
InterpolationMethod
Selects the grid-to-particle interpolation method.
Definition variables.h:562
@ INTERP_TRILINEAR
Definition variables.h:563
PetscReal Const_CS
Definition variables.h:791
PetscInt i_homo_filter
Definition variables.h:792
PetscInt wallfunction
Definition variables.h:790
PetscInt rheology
Definition variables.h:714
PetscReal Flux_in
Definition variables.h:760
PetscBool runtimeMemoryLogHasPrevious
True after the first process-memory sample.
Definition variables.h:855
char ** profilingSelectedFuncs
Definition variables.h:833
PetscReal cdisx
Definition variables.h:732
PetscInt dgf_ax
Definition variables.h:716
PetscInt mglevels
Definition variables.h:727
PetscInt num_bcs_files
Definition variables.h:775
DM dm_swarm
Definition variables.h:798
PetscBool useCfg
Definition variables.h:823
PetscReal psrc_y
Definition variables.h:762
PetscBool readFields
Definition variables.h:797
PetscInt central
Definition variables.h:730
PetscReal Fluxsum
Definition variables.h:777
FlowDirection
Primary flow direction for streamwise IC and Poiseuille modes.
Definition variables.h:270
@ FLOW_DIR_UNSET
Definition variables.h:277
PetscReal pseudo_cfl_growth_factor
Definition variables.h:733
PetscReal Croty
Definition variables.h:772
PetscInt particlesLostCumulative
Definition variables.h:804
PetscInt nProfilingSelectedFuncs
Definition variables.h:834
PetscInt particlesMigratedLastStep
Definition variables.h:806
char initialConditionDirectory[PETSC_MAX_PATH_LEN]
Definition variables.h:744
PetscReal grid_rotation_angle
Definition variables.h:771
PetscInt dynamic_freq
Definition variables.h:790
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
Definition variables.h:717
PetscInt da_procs_x
Definition variables.h:774
PetscReal U_bc
Definition variables.h:784
PetscReal walltimeGuardWarmupAverageSeconds
Definition variables.h:848
InitialConditionMode
Selects the algorithm used to populate a fresh Eulerian velocity field.
Definition variables.h:149
@ IC_MODE_FILE
Definition variables.h:154
@ IC_MODE_ZERO
Definition variables.h:150
PetscInt particleConsoleOutputFreq
Definition variables.h:697
Cmpnts InitialConstantContra
Definition variables.h:745
SearchMetricsState searchMetrics
Definition variables.h:809
PetscInt i_periodic
Definition variables.h:769
PetscReal mom_resid_rtol
Definition variables.h:726
PetscReal runtimeMemoryLogPreviousProcessMB
Previous local process memory sample in MB.
Definition variables.h:856
PetscInt step
Definition variables.h:692
PetscReal walltimeGuardEWMASeconds
Definition variables.h:850
PetscReal AreaOutSum
Definition variables.h:783
PetscInt dgf_ay
Definition variables.h:716
PetscInt mom_max_pseudo_steps
Definition variables.h:725
PetscRandom BrownianMotionRNG
Definition variables.h:810
PetscInt testfilter_ik
Definition variables.h:792
PetscInt hydro
Definition variables.h:720
PostProcessParams * pps
Definition variables.h:860
PetscInt migrationPassesLastStep
Definition variables.h:805
PetscScalar y
Definition variables.h:101
InitialConditionField
Selects the authoritative velocity representation in a staged file IC.
Definition variables.h:158
@ IC_FIELD_UCONT
Definition variables.h:160
@ IC_FIELD_UCAT
Definition variables.h:159
PetscMPIInt size
Definition variables.h:688
char _io_context_buffer[PETSC_MAX_PATH_LEN]
Definition variables.h:710
PetscReal walltimeGuardLimitSeconds
Definition variables.h:845
PetscBool ps_ksp_pic_monitor_true_residual
Definition variables.h:741
PetscReal walltimeGuardEstimatorAlpha
Definition variables.h:843
PetscInt les
Definition variables.h:789
@ SOLUTION_CONVERGENCE_TRANSIENT
Definition variables.h:545
@ SOLUTION_CONVERGENCE_STEADY_DETERMINISTIC
Definition variables.h:542
PetscInt mg_preItr
Definition variables.h:727
PetscReal mom_ratio_ema_alpha
Definition variables.h:737
PetscViewer logviewer
Definition variables.h:702
PetscInt64 searchAttempts
Definition variables.h:237
InitialConditionField initialConditionField
Definition variables.h:743
PetscInt64 tieBreakCount
Definition variables.h:245
PetscReal mom_resid_atol
Definition variables.h:726
PetscInt cop
Definition variables.h:720
PetscReal ti
Definition variables.h:693
PetscReal walltimeGuardMultiplier
Definition variables.h:841
PetscInt Pipe
Definition variables.h:720
PetscInt rotateframe
Definition variables.h:715
IBMNodes * ibm
Definition variables.h:814
PetscReal AreaInSum
Definition variables.h:783
MomentumSolverType mom_solver_type
Definition variables.h:724
PetscReal summationRHS
Definition variables.h:827
PetscInt immersed
Definition variables.h:714
PetscInt64 maxTraversalFailCount
Definition variables.h:244
char PostprocessingControlFile[PETSC_MAX_PATH_LEN]
Definition variables.h:859
char restart_dir[PETSC_MAX_PATH_LEN]
Definition variables.h:705
VerificationDiffusivityConfig verificationDiffusivity
Definition variables.h:755
PetscInt blank
Definition variables.h:715
PetscInt dgf_y
Definition variables.h:716
PetscReal walltimeGuardJobStartEpochSeconds
Definition variables.h:844
PetscReal pseudo_cfl
Definition variables.h:732
PetscInt LoggingFrequency
Definition variables.h:826
PetscReal CMx_c
Definition variables.h:761
PetscReal drivingForceMagnitude
Definition variables.h:779
PetscReal particleLoadImbalance
Definition variables.h:808
PetscInt j_periodic
Definition variables.h:769
PetscInt wing
Definition variables.h:720
FSInfo * fsi
Definition variables.h:816
The master context for the entire simulation.
Definition variables.h:684
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 974 of file setup.c.

975{
976 PetscErrorCode ierr;
977 char tmp_path[PETSC_MAX_PATH_LEN];
978 char *p = NULL;
979 size_t len;
980 PetscBool exists;
981
982 PetscFunctionBeginUser;
983
984 // Create a mutable copy of the path
985 len = strlen(path);
986 if (len >= sizeof(tmp_path)) {
987 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Path is too long to process: %s", path);
988 }
989 strcpy(tmp_path, path);
990
991 // If the path ends with a separator, remove it
992 if (tmp_path[len - 1] == '/') {
993 tmp_path[len - 1] = 0;
994 }
995
996 // Iterate through the path, creating each directory level
997 for (p = tmp_path + 1; *p; p++) {
998 if (*p == '/') {
999 *p = 0; // Temporarily terminate the string
1000
1001 // Check if this directory level exists
1002 ierr = PetscTestDirectory(tmp_path, 'r', &exists); CHKERRQ(ierr);
1003 if (!exists) {
1004 ierr = PetscMkdir(tmp_path); CHKERRQ(ierr);
1005 }
1006
1007 *p = '/'; // Restore the separator
1008 }
1009 }
1010
1011 // Create the final, full directory path
1012 ierr = PetscTestDirectory(tmp_path, 'r', &exists); CHKERRQ(ierr);
1013 if (!exists) {
1014 ierr = PetscMkdir(tmp_path); CHKERRQ(ierr);
1015 }
1016
1017 PetscFunctionReturn(0);
1018}
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 1026 of file setup.c.

1027{
1028 PetscErrorCode ierr;
1029 PetscMPIInt rank;
1030 PetscBool exists;
1031
1032 PetscFunctionBeginUser;
1033 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1034
1035 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Setting up simulation environment ---\n");
1036
1037 /* =====================================================================
1038 * Phase 1: Check for all required and optional INPUT files.
1039 * ===================================================================== */
1040 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Phase 1: Verifying input files...\n");
1041
1042 // --- Mandatory Inputs ---
1043 if (!simCtx->generate_grid) {
1044 ierr = VerifyPathExistence(simCtx->grid_file, PETSC_FALSE, PETSC_FALSE, "Grid file", &exists); CHKERRQ(ierr);
1045 }
1046 for (PetscInt i = 0; i < simCtx->num_bcs_files; i++) {
1047 char desc[128];
1048 ierr = PetscSNPrintf(desc, sizeof(desc), "BCS file #%d", i + 1); CHKERRQ(ierr);
1049 ierr = VerifyPathExistence(simCtx->bcs_files[i], PETSC_FALSE, PETSC_FALSE, desc, &exists); CHKERRQ(ierr);
1050 }
1051
1052 // --- Optional Inputs (these produce warnings if missing) ---
1053 if (simCtx->useCfg) {
1054 ierr = VerifyPathExistence(simCtx->allowedFile, PETSC_FALSE, PETSC_TRUE, "Whitelist config file", &exists); CHKERRQ(ierr);
1055 }
1056 if (simCtx->useProfilingSelectedFuncsCfg) {
1057 ierr = VerifyPathExistence(simCtx->profilingSelectedFuncsFile, PETSC_FALSE, PETSC_TRUE, "Profiling config file", &exists); CHKERRQ(ierr);
1058 }
1059 if (simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR) {
1060 ierr = VerifyPathExistence(simCtx->PostprocessingControlFile, PETSC_FALSE, PETSC_TRUE, "Post-processing control file", &exists); CHKERRQ(ierr);
1061 }
1062
1063
1064 /* =====================================================================
1065 * Phase 2: Validate directories specific to the execution mode.
1066 * ===================================================================== */
1067 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Phase 2: Verifying execution mode directories...\n");
1068 // The data source directory must exist if we intend to load any data from it.
1069 // This is true if:
1070 // 1. We are restarting from a previous time step (StartStep > 0), which implies
1071 // loading Eulerian fields and/or particle fields.
1072 // 2. We are starting from t=0 but are explicitly told to load the initial
1073 // Eulerian fields from a file (eulerianSource == "load").
1074 if (simCtx->StartStep > 0 || strcmp(simCtx->eulerianSource,"load")== 0){ // If this is a restart run
1075 ierr = VerifyPathExistence(simCtx->restart_dir, PETSC_TRUE, PETSC_FALSE, "Restart source directory", &exists); CHKERRQ(ierr);
1076 }
1077 if (simCtx->StartStep == 0 && strcmp(simCtx->eulerianSource, "solve") == 0 &&
1079 ierr = VerifyPathExistence(simCtx->initialConditionDirectory, PETSC_TRUE, PETSC_FALSE,
1080 "Initial-condition source directory", &exists); CHKERRQ(ierr);
1081 }
1082 if (simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR) {
1083 ierr = VerifyPathExistence(simCtx->pps->source_dir, PETSC_TRUE, PETSC_FALSE, "Post-processing source directory", &exists); CHKERRQ(ierr);
1084 }
1085
1086 /* =====================================================================
1087 * Phase 3: Create and prepare all OUTPUT directories.
1088 * ===================================================================== */
1089 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Phase 3: Preparing output directories...\n");
1090
1091 if (rank == 0){
1092 if(simCtx->exec_mode == EXEC_MODE_SOLVER){
1093 // --- Prepare Log Directory ---
1094 if (!simCtx->continueMode) {
1095 // Only wipe logs on fresh runs; continue mode appends to existing logs.
1096 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Creating/cleaning log directory: %s\n", simCtx->log_dir);
1097 ierr = PetscRMTree(simCtx->log_dir); // Wipes the directory and its contents
1098 if (ierr) { /* Ignore file-not-found error, but fail on others */
1099 PetscError(PETSC_COMM_SELF, __LINE__, __FUNCT__, __FILE__, ierr, PETSC_ERROR_INITIAL, "Could not remove existing log directory '%s'. Check permissions.", simCtx->log_dir);
1100 }
1101 ierr = PetscMkdir(simCtx->log_dir); CHKERRQ(ierr);
1102 } else {
1103 // In continue mode, ensure log directory exists but don't wipe it.
1104 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Continue mode: preserving existing log directory: %s\n", simCtx->log_dir);
1105 ierr = PetscMkdir(simCtx->log_dir); CHKERRQ(ierr);
1106 }
1107
1108 // --- Prepare Output Directories ---
1109 char path_buffer[PETSC_MAX_PATH_LEN];
1110
1111 // 1. Check/Create the main output directory
1112 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Verifying main output directory: %s\n", simCtx->output_dir);
1113 ierr = PetscTestDirectory(simCtx->output_dir, 'r', &exists); CHKERRQ(ierr);
1114 if (!exists) {
1115 LOG_ALLOW(GLOBAL, LOG_INFO, "Output directory not found. Creating: %s\n", simCtx->output_dir);
1116 ierr = PetscMkdir(simCtx->output_dir); CHKERRQ(ierr);
1117 }
1118
1119 // 2. Check/Create the Eulerian subdirectory
1120 ierr = PetscSNPrintf(path_buffer, sizeof(path_buffer), "%s/%s", simCtx->output_dir, simCtx->euler_subdir); CHKERRQ(ierr);
1121 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Verifying Eulerian subdirectory: %s\n", path_buffer);
1122 ierr = PetscTestDirectory(path_buffer, 'r', &exists); CHKERRQ(ierr);
1123 if (!exists) {
1124 LOG_ALLOW(GLOBAL, LOG_INFO, "Eulerian subdirectory not found. Creating: %s\n", path_buffer);
1125 ierr = PetscMkdir(path_buffer); CHKERRQ(ierr);
1126 }
1127
1128 // 3. Check/Create the Particle subdirectory if needed
1129 if (simCtx->np > 0) {
1130 ierr = PetscSNPrintf(path_buffer, sizeof(path_buffer), "%s/%s", simCtx->output_dir, simCtx->particle_subdir); CHKERRQ(ierr);
1131 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Verifying Particle subdirectory: %s\n", path_buffer);
1132 ierr = PetscTestDirectory(path_buffer, 'r', &exists); CHKERRQ(ierr);
1133 if (!exists) {
1134 LOG_ALLOW(GLOBAL, LOG_INFO, "Particle subdirectory not found. Creating: %s\n", path_buffer);
1135 ierr = PetscMkdir(path_buffer); CHKERRQ(ierr);
1136 }
1137 }
1138 } else if(simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR){
1139 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Preparing post-processing output directories ...\n");
1140
1141 PostProcessParams *pps = simCtx->pps;
1142 char path_buffer[PETSC_MAX_PATH_LEN];
1143
1144 const char *last_slash_euler = strrchr(pps->output_prefix, '/');
1145 if(last_slash_euler){
1146 size_t dir_len = last_slash_euler - pps->output_prefix;
1147 if(dir_len > 0){
1148 if(dir_len >= sizeof(path_buffer)) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Post-processing output prefix path is too long.");
1149 strncpy(path_buffer, pps->output_prefix, dir_len);
1150 path_buffer[dir_len] = '\0';
1151
1152 ierr = PetscTestDirectory(path_buffer, 'r', &exists); CHKERRQ(ierr);
1153 if (!exists){
1154 LOG_ALLOW(GLOBAL, LOG_INFO, "Creating post-processing Eulerian output directory: %s\n", path_buffer);
1155 ierr = PetscMkdirRecursive(path_buffer); CHKERRQ(ierr);
1156 }
1157 }
1158 }
1159
1160 // Particle output directory
1161 if(pps->outputParticles){
1162 const char *last_slash_particle = strrchr(pps->particle_output_prefix, '/');
1163 if(last_slash_particle){
1164 size_t dir_len = last_slash_particle - pps->particle_output_prefix;
1165 if(dir_len > 0){
1166 if(dir_len > sizeof(path_buffer)) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Post-processing particle output prefix path is too long.");
1167 strncpy(path_buffer, pps->particle_output_prefix, dir_len);
1168 path_buffer[dir_len] = '\0';
1169
1170 ierr = PetscTestDirectory(path_buffer, 'r', &exists); CHKERRQ(ierr);
1171
1172 if (!exists){
1173 LOG_ALLOW(GLOBAL, LOG_INFO, "Creating post-processing Particle output directory: %s\n", path_buffer);
1174 ierr = PetscMkdirRecursive(path_buffer); CHKERRQ(ierr);
1175 }
1176 }
1177 }
1178 }
1179
1180 // Statistics output directory
1181 if(pps->statistics_pipeline[0] != '\0'){
1182 const char *last_slash_stats = strrchr(pps->statistics_output_prefix, '/');
1183 if(last_slash_stats){
1184 size_t dir_len = last_slash_stats - pps->statistics_output_prefix;
1185 if(dir_len > 0){
1186 if(dir_len >= sizeof(path_buffer)) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Post-processing statistics output prefix path is too long.");
1187 strncpy(path_buffer, pps->statistics_output_prefix, dir_len);
1188 path_buffer[dir_len] = '\0';
1189
1190 ierr = PetscTestDirectory(path_buffer, 'r', &exists); CHKERRQ(ierr);
1191 if (!exists){
1192 LOG_ALLOW(GLOBAL, LOG_INFO, "Creating post-processing Statistics output directory: %s\n", path_buffer);
1193 ierr = PetscMkdirRecursive(path_buffer); CHKERRQ(ierr);
1194 }
1195 }
1196 }
1197 }
1198 }
1199 }
1200
1201 // Synchronize all processes before proceeding
1202 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRMPI(ierr);
1203
1204 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Environment setup complete ---\n");
1205
1206 PetscFunctionReturn(0);
1207}
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:974
#define __FUNCT__
Definition setup.c:143
char statistics_output_prefix[256]
basename for CSV output, e.g.
Definition variables.h:616
char particle_output_prefix[256]
Definition variables.h:611
char output_prefix[256]
Definition variables.h:608
char statistics_pipeline[1024]
e.g.
Definition variables.h:615
char source_dir[PETSC_MAX_PATH_LEN]
Definition variables.h:596
PetscBool outputParticles
Definition variables.h:602
@ EXEC_MODE_POSTPROCESSOR
Definition variables.h:658
Holds all configuration parameters for a post-processing run.
Definition variables.h:594
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 1215 of file setup.c.

1216{
1217 PetscErrorCode ierr;
1218 UserMG *usermg = &simCtx->usermg;
1219 MGCtx *mgctx;
1220 PetscInt nblk = simCtx->block_number;
1221 PetscBool found;
1222 PetscFunctionBeginUser;
1224
1225 LOG_ALLOW(GLOBAL, LOG_INFO, "Allocating context hierarchy for %d levels and %d blocks...\n", simCtx->mglevels, nblk);
1226
1227 // Store the number of levels in the UserMG struct itself
1228 usermg->mglevels = simCtx->mglevels;
1229
1230 // --- 1. Allocate the array of MGCtx structs ---
1231 ierr = PetscMalloc(usermg->mglevels * sizeof(MGCtx), &usermg->mgctx); CHKERRQ(ierr);
1232 // Zero-initialize to ensure all pointers (especially packer) are NULL
1233 ierr = PetscMemzero(usermg->mgctx, usermg->mglevels * sizeof(MGCtx)); CHKERRQ(ierr);
1234 mgctx = usermg->mgctx;
1235 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Allocated MGCtx array of size %d.\n", simCtx->rank, usermg->mglevels);
1236
1237 // --- 2. Parse semi-coarsening options (logic from MG_Initial) ---
1238 // These flags determine if a dimension is coarsened in the multigrid hierarchy.
1239 PetscInt *isc, *jsc, *ksc;
1240 ierr = PetscMalloc3(nblk, &isc, nblk, &jsc, nblk, &ksc); CHKERRQ(ierr);
1241 // Set defaults to FALSE (full coarsening)
1242 for (PetscInt i = 0; i < nblk; ++i) {
1243 isc[i] = 0; jsc[i] = 0; ksc[i] = 0;
1244 }
1245
1246// Use a temporary variable for the 'count' argument to the parsing function.
1247 // This protects the original 'nblk' which is needed for the loop bounds.
1248 PetscInt n_opts_found = nblk;
1249 ierr = PetscOptionsGetIntArray(NULL, NULL, "-mg_i_semi", isc, &n_opts_found, &found); CHKERRQ(ierr);
1250
1251 n_opts_found = nblk; // Reset the temp variable before the next call
1252 ierr = PetscOptionsGetIntArray(NULL, NULL, "-mg_j_semi", jsc, &n_opts_found, &found); CHKERRQ(ierr);
1253
1254 n_opts_found = nblk; // Reset the temp variable before the next call
1255 ierr = PetscOptionsGetIntArray(NULL, NULL, "-mg_k_semi", ksc, &n_opts_found, &found); CHKERRQ(ierr);
1256
1257 // --- 3. Loop over levels and blocks to allocate UserCtx arrays ---
1258 for (PetscInt level = 0; level < simCtx->mglevels; level++) {
1259
1260 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Setting up MG Level %d...\n", simCtx->rank, level);
1261 // Allocate the array of UserCtx structs for this level
1262 ierr = PetscMalloc(nblk * sizeof(UserCtx), &mgctx[level].user); CHKERRQ(ierr);
1263 // It's good practice to zero out the memory to avoid uninitialized values
1264 ierr = PetscMemzero(mgctx[level].user, nblk * sizeof(UserCtx)); CHKERRQ(ierr);
1265 mgctx[level].thislevel = level;
1266
1267 for (PetscInt bi = 0; bi < nblk; bi++) {
1268 UserCtx *currentUser = &mgctx[level].user[bi];
1269 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Initializing UserCtx for Level %d, Block %d.\n", simCtx->rank, level, bi);
1270
1271 // --- CRITICAL STEP: Set the back-pointer to the master context ---
1272 currentUser->simCtx = simCtx;
1273
1274 // Initialize other per-context values
1275 currentUser->thislevel = level;
1276 currentUser->_this = bi; //
1277 currentUser->mglevels = usermg->mglevels;
1278
1279 // Assign semi-coarsening flags
1280 currentUser->isc = isc[bi];
1281 currentUser->jsc = jsc[bi];
1282 currentUser->ksc = ksc[bi];
1283
1284 // Link to finer/coarser contexts for multigrid operations
1285 if (level > 0) {
1286 currentUser->user_c = &mgctx[level-1].user[bi];
1287 LOG_ALLOW_SYNC(GLOBAL, LOG_DEBUG, "Rank %d: -> Linked to coarser context (user_c).\n", simCtx->rank);
1288 }
1289 if (level < usermg->mglevels - 1) {
1290 currentUser->user_f = &mgctx[level+1].user[bi];
1291 LOG_ALLOW_SYNC(GLOBAL, LOG_DEBUG, "Rank %d: -> Linked to finer context (user_f).\n", simCtx->rank);
1292 }
1293 }
1294 }
1295
1296 // Log a summary of the parsed flags on each rank.
1297 if (get_log_level() >= LOG_DEBUG && nblk > 0) {
1298 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Final semi-coarsening configuration view:\n", simCtx->rank);
1299 for (PetscInt bi = 0; bi < nblk; ++bi) {
1300 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]);
1301 }
1302 }
1303
1304 // Clean up temporary arrays
1305 ierr = PetscFree3(isc, jsc, ksc); CHKERRQ(ierr);
1306
1307 LOG_ALLOW(GLOBAL, LOG_INFO, "Context hierarchy allocation complete.\n");
1309 PetscFunctionReturn(0);
1310}
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
Definition logging.c:84
PetscInt isc
Definition variables.h:889
PetscInt mglevels
Definition variables.h:944
UserCtx * user_f
Definition variables.h:945
SimCtx * simCtx
Back-pointer to the master simulation context.
Definition variables.h:879
PetscInt ksc
Definition variables.h:889
PetscInt _this
Definition variables.h:889
PetscInt jsc
Definition variables.h:889
PetscInt thislevel
Definition variables.h:570
UserCtx * user_c
Definition variables.h:945
PetscInt thislevel
Definition variables.h:944
Context for Multigrid operations.
Definition variables.h:568
User-level context for managing the entire multigrid hierarchy.
Definition variables.h:575
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 1318 of file setup.c.

1318 {
1319
1320 PetscFunctionBeginUser;
1322
1323 LOG_ALLOW(GLOBAL,LOG_INFO, " -- Setting up solver parameters -- .\n");
1324
1325 UserMG *usermg = &simCtx->usermg;
1326 MGCtx *mgctx = usermg->mgctx;
1327 PetscInt nblk = simCtx->block_number;
1328
1329 for (PetscInt level = usermg->mglevels-1; level >=0; level--) {
1330 for (PetscInt bi = 0; bi < nblk; bi++) {
1331 UserCtx *user = &mgctx[level].user[bi];
1332 LOG_ALLOW_SYNC(LOCAL, LOG_DEBUG, "Rank %d: Setting up parameters for level %d, block %d\n", simCtx->rank, level, bi);
1333
1334 user->assignedA = PETSC_FALSE;
1335 user->multinullspace = PETSC_FALSE;
1336 }
1337 }
1339 PetscFunctionReturn(0);
1340}
PetscBool assignedA
Definition variables.h:923
PetscBool multinullspace
Definition variables.h:920
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 1350 of file setup.c.

1351{
1352 PetscErrorCode ierr;
1353 PetscFunctionBeginUser;
1354
1356
1357 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Starting Grid and Solvers Setup ---\n");
1358
1359 // Phase 1: Allocate the UserMG and UserCtx hierarchy
1360 ierr = AllocateContextHierarchy(simCtx); CHKERRQ(ierr);
1361
1362 ierr = DefineAllGridDimensions(simCtx); CHKERRQ(ierr);
1363 ierr = InitializeAllGridDMs(simCtx); CHKERRQ(ierr);
1364 ierr = AssignAllGridCoordinates(simCtx); CHKERRQ(ierr);
1365 ierr = CreateAndInitializeAllVectors(simCtx); CHKERRQ(ierr);
1366 ierr = SetupSolverParameters(simCtx); CHKERRQ(ierr);
1367 ierr = InitializeSolutionConvergenceState(simCtx); CHKERRQ(ierr);
1368
1369 // NOTE: CalculateAllGridMetrics is now called inside SetupBoundaryConditions (not here) to ensure:
1370 // 1. Boundary condition configuration data (boundary_faces) is available for periodic BC corrections
1371 // 2. Computed metrics are available for inlet/outlet area calculations
1372 // This resolves the circular dependency between BC setup and metric calculations.
1373
1374 LOG_ALLOW(GLOBAL, LOG_INFO, "--- Grid and Solvers Setup Complete ---\n");
1375
1377 PetscFunctionReturn(0);
1378}
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:1318
PetscErrorCode CreateAndInitializeAllVectors(SimCtx *simCtx)
Internal helper implementation: CreateAndInitializeAllVectors().
Definition setup.c:1387
PetscErrorCode InitializeSolutionConvergenceState(SimCtx *simCtx)
Implementation of InitializeSolutionConvergenceState().
Definition setup.c:47
static PetscErrorCode AllocateContextHierarchy(SimCtx *simCtx)
Internal helper implementation: AllocateContextHierarchy().
Definition setup.c:1215
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 1387 of file setup.c.

1388{
1389 PetscErrorCode ierr;
1390 UserMG *usermg = &simCtx->usermg;
1391 MGCtx *mgctx = usermg->mgctx;
1392 PetscInt nblk = simCtx->block_number;
1393
1394 PetscFunctionBeginUser;
1395
1397
1398 LOG_ALLOW(GLOBAL, LOG_INFO, "Creating and initializing all simulation vectors...\n");
1399
1400 for (PetscInt level = usermg->mglevels-1; level >=0; level--) {
1401 for (PetscInt bi = 0; bi < nblk; bi++) {
1402 UserCtx *user = &mgctx[level].user[bi];
1403
1404 if(!user->da || !user->fda) {
1405 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE, "DMs not properly initialized in UserCtx before vector creation.");
1406 }
1407
1408 LOG_ALLOW_SYNC(LOCAL, LOG_DEBUG, "Rank %d: Creating vectors for level %d, block %d\n", simCtx->rank, level, bi);
1409
1410 // --- Group A: Primary Flow Fields (Global and Local) ---
1411 // These are the core solution variables.
1412 ierr = DMCreateGlobalVector(user->fda, &user->Ucont); CHKERRQ(ierr); ierr = VecSet(user->Ucont, 0.0); CHKERRQ(ierr);
1413 ierr = DMCreateGlobalVector(user->fda, &user->Ucat); CHKERRQ(ierr); ierr = VecSet(user->Ucat, 0.0); CHKERRQ(ierr);
1414 ierr = DMCreateGlobalVector(user->da, &user->P); CHKERRQ(ierr); ierr = VecSet(user->P, 0.0); CHKERRQ(ierr);
1415 ierr = DMCreateGlobalVector(user->da, &user->Nvert); CHKERRQ(ierr); ierr = VecSet(user->Nvert, 0.0); CHKERRQ(ierr);
1416
1417 ierr = DMCreateLocalVector(user->fda, &user->lUcont); CHKERRQ(ierr); ierr = VecSet(user->lUcont, 0.0); CHKERRQ(ierr);
1418 ierr = DMCreateLocalVector(user->fda, &user->lUcat); CHKERRQ(ierr); ierr = VecSet(user->lUcat, 0.0); CHKERRQ(ierr);
1419 ierr = DMCreateLocalVector(user->da, &user->lP); CHKERRQ(ierr); ierr = VecSet(user->lP, 0.0); CHKERRQ(ierr);
1420 ierr = DMCreateLocalVector(user->da, &user->lNvert); CHKERRQ(ierr); ierr = VecSet(user->lNvert, 0.0); CHKERRQ(ierr);
1421
1422 // -- Group A2: Derived Flow Fields (Global and Local) ---
1423 ierr = VecDuplicate(user->P,&user->Diffusivity); CHKERRQ(ierr); ierr = VecSet(user->Diffusivity, 0.0); CHKERRQ(ierr);
1424 ierr = VecDuplicate(user->lP,&user->lDiffusivity); CHKERRQ(ierr); ierr = VecSet(user->lDiffusivity, 0.0); CHKERRQ(ierr);
1425 ierr = VecDuplicate(user->Ucat,&user->DiffusivityGradient); CHKERRQ(ierr); ierr = VecSet(user->DiffusivityGradient, 0.0); CHKERRQ(ierr);
1426 ierr = VecDuplicate(user->lUcat,&user->lDiffusivityGradient); CHKERRQ(ierr); ierr = VecSet(user->lDiffusivityGradient, 0.0); CHKERRQ(ierr);
1427
1428 // -- Group B: Solver Work Vectors (Global and Local) ---
1429 ierr = VecDuplicate(user->P, &user->Phi); CHKERRQ(ierr); ierr = VecSet(user->Phi, 0.0); CHKERRQ(ierr);
1430 ierr = VecDuplicate(user->lP, &user->lPhi); CHKERRQ(ierr); ierr = VecSet(user->lPhi, 0.0); CHKERRQ(ierr);
1431
1432 // --- Group C: Time-Stepping & Workspace Fields (Finest Level Only) ---
1433 if (level == usermg->mglevels - 1) {
1434 ierr = VecDuplicate(user->Ucont, &user->Ucont_o); CHKERRQ(ierr); ierr = VecSet(user->Ucont_o, 0.0); CHKERRQ(ierr);
1435 ierr = VecDuplicate(user->Ucont, &user->Ucont_rm1); CHKERRQ(ierr); ierr = VecSet(user->Ucont_rm1, 0.0); CHKERRQ(ierr);
1436 ierr = VecDuplicate(user->Ucat, &user->Ucat_o); CHKERRQ(ierr); ierr = VecSet(user->Ucat_o, 0.0); CHKERRQ(ierr);
1437 ierr = VecDuplicate(user->P, &user->P_o); CHKERRQ(ierr); ierr = VecSet(user->P_o, 0.0); CHKERRQ(ierr);
1438 ierr = VecDuplicate(user->lUcont, &user->lUcont_o); CHKERRQ(ierr); ierr = VecSet(user->lUcont_o, 0.0); CHKERRQ(ierr);
1439 ierr = VecDuplicate(user->lUcont, &user->lUcont_rm1); CHKERRQ(ierr); ierr = VecSet(user->lUcont_rm1, 0.0); CHKERRQ(ierr);
1440 ierr = DMCreateLocalVector(user->da, &user->lNvert_o); CHKERRQ(ierr); ierr = VecSet(user->lNvert_o, 0.0); CHKERRQ(ierr);
1441 ierr = VecDuplicate(user->Nvert, &user->Nvert_o); CHKERRQ(ierr); ierr = VecSet(user->Nvert_o, 0.0); CHKERRQ(ierr);
1442 }
1443
1444 // --- Group D: Grid Metrics (Face-Centered) ---
1445 ierr = DMCreateGlobalVector(user->fda, &user->Csi); CHKERRQ(ierr); ierr = VecSet(user->Csi, 0.0); CHKERRQ(ierr);
1446 ierr = VecDuplicate(user->Csi, &user->Eta); CHKERRQ(ierr); ierr = VecSet(user->Eta, 0.0); CHKERRQ(ierr);
1447 ierr = VecDuplicate(user->Csi, &user->Zet); CHKERRQ(ierr); ierr = VecSet(user->Zet, 0.0); CHKERRQ(ierr);
1448 ierr = DMCreateGlobalVector(user->da, &user->Aj); CHKERRQ(ierr); ierr = VecSet(user->Aj, 0.0); CHKERRQ(ierr);
1449
1450 ierr = DMCreateLocalVector(user->fda, &user->lCsi); CHKERRQ(ierr); ierr = VecSet(user->lCsi, 0.0); CHKERRQ(ierr);
1451 ierr = VecDuplicate(user->lCsi, &user->lEta); CHKERRQ(ierr); ierr = VecSet(user->lEta, 0.0); CHKERRQ(ierr);
1452 ierr = VecDuplicate(user->lCsi, &user->lZet); CHKERRQ(ierr); ierr = VecSet(user->lZet, 0.0); CHKERRQ(ierr);
1453 ierr = DMCreateLocalVector(user->da, &user->lAj); CHKERRQ(ierr); ierr = VecSet(user->lAj, 0.0); CHKERRQ(ierr);
1454
1455
1456 // --- Group E: Grid Metrics (Face-Centered) ---
1457 // Vector metrics are duplicated from Csi (DOF=3, fda-based)
1458 ierr = VecDuplicate(user->Csi, &user->ICsi); CHKERRQ(ierr); ierr = VecSet(user->ICsi, 0.0); CHKERRQ(ierr);
1459 ierr = VecDuplicate(user->Csi, &user->IEta); CHKERRQ(ierr); ierr = VecSet(user->IEta, 0.0); CHKERRQ(ierr);
1460 ierr = VecDuplicate(user->Csi, &user->IZet); CHKERRQ(ierr); ierr = VecSet(user->IZet, 0.0); CHKERRQ(ierr);
1461 ierr = VecDuplicate(user->Csi, &user->JCsi); CHKERRQ(ierr); ierr = VecSet(user->JCsi, 0.0); CHKERRQ(ierr);
1462 ierr = VecDuplicate(user->Csi, &user->JEta); CHKERRQ(ierr); ierr = VecSet(user->JEta, 0.0); CHKERRQ(ierr);
1463 ierr = VecDuplicate(user->Csi, &user->JZet); CHKERRQ(ierr); ierr = VecSet(user->JZet, 0.0); CHKERRQ(ierr);
1464 ierr = VecDuplicate(user->Csi, &user->KCsi); CHKERRQ(ierr); ierr = VecSet(user->KCsi, 0.0); CHKERRQ(ierr);
1465 ierr = VecDuplicate(user->Csi, &user->KEta); CHKERRQ(ierr); ierr = VecSet(user->KEta, 0.0); CHKERRQ(ierr);
1466 ierr = VecDuplicate(user->Csi, &user->KZet); CHKERRQ(ierr); ierr = VecSet(user->KZet, 0.0); CHKERRQ(ierr);
1467 // Scalar metrics are duplicated from Aj (DOF=1, da-based)
1468 ierr = VecDuplicate(user->Aj, &user->IAj); CHKERRQ(ierr); ierr = VecSet(user->IAj, 0.0); CHKERRQ(ierr);
1469 ierr = VecDuplicate(user->Aj, &user->JAj); CHKERRQ(ierr); ierr = VecSet(user->JAj, 0.0); CHKERRQ(ierr);
1470 ierr = VecDuplicate(user->Aj, &user->KAj); CHKERRQ(ierr); ierr = VecSet(user->KAj, 0.0); CHKERRQ(ierr);
1471
1472 ierr = VecDuplicate(user->lCsi, &user->lICsi); CHKERRQ(ierr); ierr = VecSet(user->lICsi, 0.0); CHKERRQ(ierr);
1473 ierr = VecDuplicate(user->lCsi, &user->lIEta); CHKERRQ(ierr); ierr = VecSet(user->lIEta, 0.0); CHKERRQ(ierr);
1474 ierr = VecDuplicate(user->lCsi, &user->lIZet); CHKERRQ(ierr); ierr = VecSet(user->lIZet, 0.0); CHKERRQ(ierr);
1475 ierr = VecDuplicate(user->lCsi, &user->lJCsi); CHKERRQ(ierr); ierr = VecSet(user->lJCsi, 0.0); CHKERRQ(ierr);
1476 ierr = VecDuplicate(user->lCsi, &user->lJEta); CHKERRQ(ierr); ierr = VecSet(user->lJEta, 0.0); CHKERRQ(ierr);
1477 ierr = VecDuplicate(user->lCsi, &user->lJZet); CHKERRQ(ierr); ierr = VecSet(user->lJZet, 0.0); CHKERRQ(ierr);
1478 ierr = VecDuplicate(user->lCsi, &user->lKCsi); CHKERRQ(ierr); ierr = VecSet(user->lKCsi, 0.0); CHKERRQ(ierr);
1479 ierr = VecDuplicate(user->lCsi, &user->lKEta); CHKERRQ(ierr); ierr = VecSet(user->lKEta, 0.0); CHKERRQ(ierr);
1480 ierr = VecDuplicate(user->lCsi, &user->lKZet); CHKERRQ(ierr); ierr = VecSet(user->lKZet, 0.0); CHKERRQ(ierr);
1481
1482 ierr = VecDuplicate(user->lAj, &user->lIAj); CHKERRQ(ierr); ierr = VecSet(user->lIAj, 0.0); CHKERRQ(ierr);
1483 ierr = VecDuplicate(user->lAj, &user->lJAj); CHKERRQ(ierr); ierr = VecSet(user->lJAj, 0.0); CHKERRQ(ierr);
1484 ierr = VecDuplicate(user->lAj, &user->lKAj); CHKERRQ(ierr); ierr = VecSet(user->lKAj, 0.0); CHKERRQ(ierr);
1485
1486 // --- Group F: Cell/Face Center Coordinates and Grid Spacing ---
1487 ierr = DMCreateGlobalVector(user->fda, &user->Cent); CHKERRQ(ierr); ierr = VecSet(user->Cent, 0.0); CHKERRQ(ierr);
1488 ierr = DMCreateLocalVector(user->fda, &user->lCent); CHKERRQ(ierr); ierr = VecSet(user->lCent, 0.0); CHKERRQ(ierr);
1489
1490 ierr = VecDuplicate(user->Cent, &user->GridSpace); CHKERRQ(ierr); ierr = VecSet(user->GridSpace, 0.0); CHKERRQ(ierr);
1491 ierr = VecDuplicate(user->lCent, &user->lGridSpace); CHKERRQ(ierr); ierr = VecSet(user->lGridSpace, 0.0); CHKERRQ(ierr);
1492
1493 ierr = VecDuplicate(user->Cent, &user->Centx); CHKERRQ(ierr); ierr = VecSet(user->Centx, 0.0); CHKERRQ(ierr);
1494 ierr = VecDuplicate(user->Cent, &user->Centy); CHKERRQ(ierr); ierr = VecSet(user->Centy, 0.0); CHKERRQ(ierr);
1495 ierr = VecDuplicate(user->Cent, &user->Centz); CHKERRQ(ierr); ierr = VecSet(user->Centz, 0.0); CHKERRQ(ierr);
1496 ierr = VecDuplicate(user->lCent, &user->lCentx); CHKERRQ(ierr); ierr = VecSet(user->lCentx, 0.0); CHKERRQ(ierr);
1497 ierr = VecDuplicate(user->lCent, &user->lCenty); CHKERRQ(ierr); ierr = VecSet(user->lCenty, 0.0); CHKERRQ(ierr);
1498 ierr = VecDuplicate(user->lCent, &user->lCentz); CHKERRQ(ierr); ierr = VecSet(user->lCentz, 0.0); CHKERRQ(ierr);
1499
1500 if(level == usermg->mglevels -1){
1501 // --- Group G: Turbulence Models (Finest Level Only) ---
1502 if (simCtx->les || simCtx->rans) {
1503 ierr = DMCreateGlobalVector(user->da, &user->Nu_t); CHKERRQ(ierr); ierr = VecSet(user->Nu_t, 0.0); CHKERRQ(ierr);
1504 ierr = DMCreateLocalVector(user->da, &user->lNu_t); CHKERRQ(ierr); ierr = VecSet(user->lNu_t, 0.0); CHKERRQ(ierr);
1505 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Turbulence viscosity (Nu_t) vectors created for LES/RANS model.\n");
1506 if(simCtx->les){
1507 ierr = DMCreateGlobalVector(user->da,&user->CS); CHKERRQ(ierr); ierr = VecSet(user->CS,0.0); CHKERRQ(ierr);
1508 ierr = DMCreateLocalVector(user->da,&user->lCs); CHKERRQ(ierr); ierr = VecSet(user->lCs,0.0); CHKERRQ(ierr);
1509 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Smagorinsky constant (CS) vectors created for LES model.\n");
1510 }
1511
1512 if(simCtx->wallfunction){
1513 ierr = DMCreateLocalVector(user->fda,&user->lFriction_Velocity); CHKERRQ(ierr); ierr = VecSet(user->lFriction_Velocity,0.0);
1514 }
1515 // Add K_Omega etc. here as needed
1516
1517 // Note: Add any other vectors from the legacy MG_Initial here as needed.
1518 // For example: Rhs, Forcing, turbulence Vecs (K_Omega, Nu_t)...
1519
1520 }
1521 // --- Group H: Particle Methods
1522 if(simCtx->np>0){
1523 ierr = DMCreateGlobalVector(user->da,&user->ParticleCount); CHKERRQ(ierr); ierr = VecSet(user->ParticleCount,0.0); CHKERRQ(ierr);
1524 ierr = DMCreateLocalVector(user->da,&user->lParticleCount); CHKERRQ(ierr); ierr = VecSet(user->lParticleCount,0.0); CHKERRQ(ierr);
1525 // Scalar field to hold particle scalar property (e.g., temperature, concentration)
1526 ierr = DMCreateGlobalVector(user->da,&user->Psi); CHKERRQ(ierr); ierr = VecSet(user->Psi,0.0); CHKERRQ(ierr);
1527 ierr = DMCreateLocalVector(user->da,&user->lPsi); CHKERRQ(ierr); ierr = VecSet(user->lPsi,0.0); CHKERRQ(ierr);
1528 LOG_ALLOW(GLOBAL,LOG_DEBUG,"ParticleCount & Scalar(Psi) created for %d particles.\n",simCtx->np);
1529 }
1530 }
1531 // --- Group I: Boundary Condition vectors ---
1532 ierr = DMCreateGlobalVector(user->fda, &user->Bcs.Ubcs); CHKERRQ(ierr);
1533 ierr = VecSet(user->Bcs.Ubcs, 0.0); CHKERRQ(ierr);
1534 ierr = DMCreateGlobalVector(user->fda, &user->Bcs.Uch); CHKERRQ(ierr);
1535 ierr = VecSet(user->Bcs.Uch, 0.0); CHKERRQ(ierr);
1536
1537 if(level == usermg->mglevels - 1){
1538 if(simCtx->exec_mode == EXEC_MODE_POSTPROCESSOR){
1539 LOG_ALLOW(LOCAL, LOG_DEBUG, "Post-processor mode detected. Allocating derived field vectors.\n");
1540
1541 ierr = VecDuplicate(user->P, &user->P_nodal); CHKERRQ(ierr);
1542 ierr = VecSet(user->P_nodal, 0.0); CHKERRQ(ierr);
1543
1544 ierr = VecDuplicate(user->Ucat, &user->Ucat_nodal); CHKERRQ(ierr);
1545 ierr = VecSet(user->Ucat_nodal, 0.0); CHKERRQ(ierr);
1546
1547 ierr = VecDuplicate(user->P, &user->Qcrit); CHKERRQ(ierr);
1548 ierr = VecSet(user->Qcrit, 0.0); CHKERRQ(ierr);
1549
1550 LOG_ALLOW(LOCAL, LOG_DEBUG, "Derived field vectors P_nodal, Ucat_nodal, and Qcrit created.\n");
1551
1552 if(simCtx->np>0){
1553 ierr = VecDuplicate(user->Psi, &user->Psi_nodal); CHKERRQ(ierr);
1554 ierr = VecSet(user->Psi_nodal, 0.0); CHKERRQ(ierr);
1555
1556 LOG_ALLOW(LOCAL, LOG_DEBUG, "Derived field vector Psi_nodal created for particle scalar property.\n");
1557
1558 }
1559 }else{
1560 user->P_nodal = NULL;
1561 user->Ucat_nodal = NULL;
1562 user->Qcrit = NULL;
1563 user->Psi_nodal = NULL;
1564 }
1565 }
1566
1567 }
1568}
1569
1570 LOG_ALLOW(GLOBAL, LOG_INFO, "All simulation vectors created and initialized.\n");
1571
1573 PetscFunctionReturn(0);
1574}
Vec lFriction_Velocity
Definition variables.h:900
Vec lDiffusivityGradient
Definition variables.h:908
Vec lCent
Definition variables.h:927
Vec GridSpace
Definition variables.h:927
Vec P_nodal
Definition variables.h:957
Vec JCsi
Definition variables.h:931
Vec KAj
Definition variables.h:932
Vec JEta
Definition variables.h:931
Vec Zet
Definition variables.h:927
Vec lIEta
Definition variables.h:930
Vec lIZet
Definition variables.h:930
Vec lNvert
Definition variables.h:904
Vec Phi
Definition variables.h:904
Vec IZet
Definition variables.h:930
Vec Centz
Definition variables.h:928
Vec IEta
Definition variables.h:930
Vec lZet
Definition variables.h:927
Vec Csi
Definition variables.h:927
Vec lUcont_rm1
Definition variables.h:912
Vec lIAj
Definition variables.h:930
Vec lKEta
Definition variables.h:932
Vec Ucat_nodal
Definition variables.h:958
Vec lPsi
Definition variables.h:953
Vec DiffusivityGradient
Definition variables.h:908
Vec lJCsi
Definition variables.h:931
Vec lCs
Definition variables.h:935
Vec Ucont
Definition variables.h:904
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:959
Vec JZet
Definition variables.h:931
Vec Centx
Definition variables.h:928
BCS Bcs
Definition variables.h:899
Vec lPhi
Definition variables.h:904
Vec lParticleCount
Definition variables.h:952
Vec lUcont_o
Definition variables.h:911
Vec Ucat_o
Definition variables.h:911
Vec lKZet
Definition variables.h:932
Vec Eta
Definition variables.h:927
Vec lNu_t
Definition variables.h:935
Vec Nu_t
Definition variables.h:935
Vec lJEta
Definition variables.h:931
Vec lCsi
Definition variables.h:927
Vec lGridSpace
Definition variables.h:927
Vec ICsi
Definition variables.h:930
Vec lKCsi
Definition variables.h:932
Vec Ucat
Definition variables.h:904
Vec ParticleCount
Definition variables.h:952
Vec Ucont_o
Definition variables.h:911
Vec lCenty
Definition variables.h:929
Vec lJZet
Definition variables.h:931
Vec Nvert_o
Definition variables.h:911
Vec IAj
Definition variables.h:930
Vec Psi_nodal
Definition variables.h:960
Vec JAj
Definition variables.h:931
Vec KEta
Definition variables.h:932
Vec lCentx
Definition variables.h:929
Vec Ucont_rm1
Definition variables.h:912
Vec lUcont
Definition variables.h:904
Vec Diffusivity
Definition variables.h:907
Vec lAj
Definition variables.h:927
Vec lICsi
Definition variables.h:930
Vec lUcat
Definition variables.h:904
Vec lEta
Definition variables.h:927
Vec KZet
Definition variables.h:932
Vec Cent
Definition variables.h:927
Vec Nvert
Definition variables.h:904
Vec KCsi
Definition variables.h:932
Vec lDiffusivity
Definition variables.h:907
Vec lNvert_o
Definition variables.h:911
Vec Centy
Definition variables.h:928
Vec lCentz
Definition variables.h:929
Vec lJAj
Definition variables.h:931
Vec lKAj
Definition variables.h:932
Vec Psi
Definition variables.h:953
Vec P_o
Definition variables.h:911
Vec Uch
Characteristic velocity for boundary conditions.
Definition variables.h:122
Here is the caller graph for this function:

◆ RepairPeriodicNormalFaceGhosts()

static PetscErrorCode RepairPeriodicNormalFaceGhosts ( UserCtx user,
DM  dm,
Vec  local_vec,
PetscInt  dof,
char  face_direction,
PetscBool  component_staggered 
)
static

Repairs the adjacent normal ghost layer for periodic face-staggered data.

PETSc wraps every component with cell-style indexing. A face family instead needs its adjacent normal ghost shifted by one additional physical face. With the width-three periodic DMDA, the required value is available in the deeper PETSc ghost at -3 or n+2. Tangential ghosts retain PETSc's native wraparound.

Definition at line 1586 of file setup.c.

1589{
1590 DMDALocalInfo info;
1591 PetscInt xs, xe, ys, ye, zs, ze;
1592 PetscInt gxs, gxe, gys, gye, gzs, gze;
1593 PetscInt mx, my, mz;
1594
1595 PetscFunctionBeginUser;
1596 if (!face_direction && !component_staggered) PetscFunctionReturn(0);
1597
1598 PetscCall(DMDAGetLocalInfo(dm, &info));
1599 xs = info.xs; xe = info.xs + info.xm;
1600 ys = info.ys; ye = info.ys + info.ym;
1601 zs = info.zs; ze = info.zs + info.zm;
1602 gxs = info.gxs; gxe = info.gxs + info.gxm;
1603 gys = info.gys; gye = info.gys + info.gym;
1604 gzs = info.gzs; gze = info.gzs + info.gzm;
1605 mx = info.mx; my = info.my; mz = info.mz;
1606
1607 if (component_staggered) {
1608 Cmpnts ***array;
1609 PetscCall(DMDAVecGetArray(dm, local_vec, &array));
1610
1611 if (user->boundary_faces[BC_FACE_NEG_X].mathematical_type == PERIODIC && xs == 0) {
1612 PetscCheck(gxs <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1613 "Periodic Ucont.x ghost repair requires DMDA stencil width at least 3.");
1614 for (PetscInt k = gzs; k < gze; k++) for (PetscInt j = gys; j < gye; j++)
1615 array[k][j][-1].x = array[k][j][-3].x;
1616 }
1617 if (user->boundary_faces[BC_FACE_POS_X].mathematical_type == PERIODIC && xe == mx) {
1618 PetscCheck(gxe > mx + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1619 "Periodic Ucont.x ghost repair requires DMDA stencil width at least 3.");
1620 for (PetscInt k = gzs; k < gze; k++) for (PetscInt j = gys; j < gye; j++)
1621 array[k][j][mx].x = array[k][j][mx + 2].x;
1622 }
1623 if (user->boundary_faces[BC_FACE_NEG_Y].mathematical_type == PERIODIC && ys == 0) {
1624 PetscCheck(gys <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1625 "Periodic Ucont.y ghost repair requires DMDA stencil width at least 3.");
1626 for (PetscInt k = gzs; k < gze; k++) for (PetscInt i = gxs; i < gxe; i++)
1627 array[k][-1][i].y = array[k][-3][i].y;
1628 }
1629 if (user->boundary_faces[BC_FACE_POS_Y].mathematical_type == PERIODIC && ye == my) {
1630 PetscCheck(gye > my + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1631 "Periodic Ucont.y ghost repair requires DMDA stencil width at least 3.");
1632 for (PetscInt k = gzs; k < gze; k++) for (PetscInt i = gxs; i < gxe; i++)
1633 array[k][my][i].y = array[k][my + 2][i].y;
1634 }
1635 if (user->boundary_faces[BC_FACE_NEG_Z].mathematical_type == PERIODIC && zs == 0) {
1636 PetscCheck(gzs <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1637 "Periodic Ucont.z ghost repair requires DMDA stencil width at least 3.");
1638 for (PetscInt j = gys; j < gye; j++) for (PetscInt i = gxs; i < gxe; i++)
1639 array[-1][j][i].z = array[-3][j][i].z;
1640 }
1641 if (user->boundary_faces[BC_FACE_POS_Z].mathematical_type == PERIODIC && ze == mz) {
1642 PetscCheck(gze > mz + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1643 "Periodic Ucont.z ghost repair requires DMDA stencil width at least 3.");
1644 for (PetscInt j = gys; j < gye; j++) for (PetscInt i = gxs; i < gxe; i++)
1645 array[mz][j][i].z = array[mz + 2][j][i].z;
1646 }
1647
1648 PetscCall(DMDAVecRestoreArray(dm, local_vec, &array));
1649 PetscFunctionReturn(0);
1650 }
1651
1652 if (dof == 1) {
1653 PetscReal ***array;
1654 PetscCall(DMDAVecGetArray(dm, local_vec, &array));
1655
1656 if (face_direction == 'i') {
1657 if (user->boundary_faces[BC_FACE_NEG_X].mathematical_type == PERIODIC && xs == 0) {
1658 PetscCheck(gxs <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1659 "Periodic I-face ghost repair requires DMDA stencil width at least 3.");
1660 for (PetscInt k = gzs; k < gze; k++) for (PetscInt j = gys; j < gye; j++)
1661 array[k][j][-1] = array[k][j][-3];
1662 }
1663 if (user->boundary_faces[BC_FACE_POS_X].mathematical_type == PERIODIC && xe == mx) {
1664 PetscCheck(gxe > mx + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1665 "Periodic I-face ghost repair requires DMDA stencil width at least 3.");
1666 for (PetscInt k = gzs; k < gze; k++) for (PetscInt j = gys; j < gye; j++)
1667 array[k][j][mx] = array[k][j][mx + 2];
1668 }
1669 } else if (face_direction == 'j') {
1670 if (user->boundary_faces[BC_FACE_NEG_Y].mathematical_type == PERIODIC && ys == 0) {
1671 PetscCheck(gys <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1672 "Periodic J-face ghost repair requires DMDA stencil width at least 3.");
1673 for (PetscInt k = gzs; k < gze; k++) for (PetscInt i = gxs; i < gxe; i++)
1674 array[k][-1][i] = array[k][-3][i];
1675 }
1676 if (user->boundary_faces[BC_FACE_POS_Y].mathematical_type == PERIODIC && ye == my) {
1677 PetscCheck(gye > my + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1678 "Periodic J-face ghost repair requires DMDA stencil width at least 3.");
1679 for (PetscInt k = gzs; k < gze; k++) for (PetscInt i = gxs; i < gxe; i++)
1680 array[k][my][i] = array[k][my + 2][i];
1681 }
1682 } else if (face_direction == 'k') {
1683 if (user->boundary_faces[BC_FACE_NEG_Z].mathematical_type == PERIODIC && zs == 0) {
1684 PetscCheck(gzs <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1685 "Periodic K-face ghost repair requires DMDA stencil width at least 3.");
1686 for (PetscInt j = gys; j < gye; j++) for (PetscInt i = gxs; i < gxe; i++)
1687 array[-1][j][i] = array[-3][j][i];
1688 }
1689 if (user->boundary_faces[BC_FACE_POS_Z].mathematical_type == PERIODIC && ze == mz) {
1690 PetscCheck(gze > mz + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1691 "Periodic K-face ghost repair requires DMDA stencil width at least 3.");
1692 for (PetscInt j = gys; j < gye; j++) for (PetscInt i = gxs; i < gxe; i++)
1693 array[mz][j][i] = array[mz + 2][j][i];
1694 }
1695 }
1696
1697 PetscCall(DMDAVecRestoreArray(dm, local_vec, &array));
1698 } else {
1699 Cmpnts ***array;
1700 PetscCall(DMDAVecGetArray(dm, local_vec, &array));
1701
1702 if (face_direction == 'i') {
1703 if (user->boundary_faces[BC_FACE_NEG_X].mathematical_type == PERIODIC && xs == 0) {
1704 PetscCheck(gxs <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1705 "Periodic I-face ghost repair requires DMDA stencil width at least 3.");
1706 for (PetscInt k = gzs; k < gze; k++) for (PetscInt j = gys; j < gye; j++)
1707 array[k][j][-1] = array[k][j][-3];
1708 }
1709 if (user->boundary_faces[BC_FACE_POS_X].mathematical_type == PERIODIC && xe == mx) {
1710 PetscCheck(gxe > mx + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1711 "Periodic I-face ghost repair requires DMDA stencil width at least 3.");
1712 for (PetscInt k = gzs; k < gze; k++) for (PetscInt j = gys; j < gye; j++)
1713 array[k][j][mx] = array[k][j][mx + 2];
1714 }
1715 } else if (face_direction == 'j') {
1716 if (user->boundary_faces[BC_FACE_NEG_Y].mathematical_type == PERIODIC && ys == 0) {
1717 PetscCheck(gys <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1718 "Periodic J-face ghost repair requires DMDA stencil width at least 3.");
1719 for (PetscInt k = gzs; k < gze; k++) for (PetscInt i = gxs; i < gxe; i++)
1720 array[k][-1][i] = array[k][-3][i];
1721 }
1722 if (user->boundary_faces[BC_FACE_POS_Y].mathematical_type == PERIODIC && ye == my) {
1723 PetscCheck(gye > my + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1724 "Periodic J-face ghost repair requires DMDA stencil width at least 3.");
1725 for (PetscInt k = gzs; k < gze; k++) for (PetscInt i = gxs; i < gxe; i++)
1726 array[k][my][i] = array[k][my + 2][i];
1727 }
1728 } else if (face_direction == 'k') {
1729 if (user->boundary_faces[BC_FACE_NEG_Z].mathematical_type == PERIODIC && zs == 0) {
1730 PetscCheck(gzs <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1731 "Periodic K-face ghost repair requires DMDA stencil width at least 3.");
1732 for (PetscInt j = gys; j < gye; j++) for (PetscInt i = gxs; i < gxe; i++)
1733 array[-1][j][i] = array[-3][j][i];
1734 }
1735 if (user->boundary_faces[BC_FACE_POS_Z].mathematical_type == PERIODIC && ze == mz) {
1736 PetscCheck(gze > mz + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
1737 "Periodic K-face ghost repair requires DMDA stencil width at least 3.");
1738 for (PetscInt j = gys; j < gye; j++) for (PetscInt i = gxs; i < gxe; i++)
1739 array[mz][j][i] = array[mz + 2][j][i];
1740 }
1741 }
1742
1743 PetscCall(DMDAVecRestoreArray(dm, local_vec, &array));
1744 }
1745
1746 PetscFunctionReturn(0);
1747}
@ PERIODIC
Definition variables.h:290
BoundaryFaceConfig boundary_faces[6]
Definition variables.h:896
BCType mathematical_type
Definition variables.h:366
@ BC_FACE_NEG_X
Definition variables.h:260
@ BC_FACE_POS_Z
Definition variables.h:262
@ BC_FACE_POS_Y
Definition variables.h:261
@ BC_FACE_NEG_Z
Definition variables.h:262
@ BC_FACE_POS_X
Definition variables.h:260
@ BC_FACE_NEG_Y
Definition variables.h:261
A 3D point or vector with PetscScalar components.
Definition variables.h:100
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 1755 of file setup.c.

1756{
1757 PetscErrorCode ierr;
1758 PetscMPIInt rank;
1759 Vec globalVec = NULL;
1760 Vec localVec = NULL;
1761 DM dm = NULL; // The DM associated with this field pair
1762 PetscInt dof = 0;
1763 char face_direction = '\0';
1764 PetscBool component_staggered = PETSC_FALSE;
1765
1766 PetscFunctionBeginUser; // Use User version for application code
1768 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1769 LOG_ALLOW(GLOBAL, LOG_INFO, "Rank %d: Starting ghost update for field '%s'.\n", rank, fieldName);
1770
1771 // --- 1. Identify the correct Vectors and DM ---
1772 if (strcmp(fieldName, "Coordinates") == 0) {
1773 ierr = DMGetCoordinates(user->da, &globalVec); CHKERRQ(ierr);
1774 ierr = DMGetCoordinatesLocal(user->da, &localVec); CHKERRQ(ierr);
1775 dm = user->fda;
1776 dof = 3;
1777 } else if (strcmp(fieldName, "Ucat") == 0) {
1778 globalVec = user->Ucat;
1779 localVec = user->lUcat;
1780 dm = user->fda;
1781 dof = 3;
1782 } else if (strcmp(fieldName, "Ucont") == 0) {
1783 globalVec = user->Ucont;
1784 localVec = user->lUcont;
1785 dm = user->fda;
1786 dof = 3;
1787 component_staggered = PETSC_TRUE;
1788 } else if (strcmp(fieldName, "Ucont_o") == 0) {
1789 globalVec = user->Ucont_o;
1790 localVec = user->lUcont_o;
1791 dm = user->fda;
1792 dof = 3;
1793 component_staggered = PETSC_TRUE;
1794 } else if (strcmp(fieldName, "Ucont_rm1") == 0) {
1795 globalVec = user->Ucont_rm1;
1796 localVec = user->lUcont_rm1;
1797 dm = user->fda;
1798 dof = 3;
1799 component_staggered = PETSC_TRUE;
1800 } else if (strcmp(fieldName, "P") == 0) {
1801 globalVec = user->P;
1802 localVec = user->lP;
1803 dm = user->da;
1804 } else if (strcmp(fieldName, "Nu_t") == 0 || strcmp(fieldName, "Eddy Viscosity") == 0) {
1805 globalVec = user->Nu_t;
1806 localVec = user->lNu_t;
1807 dm = user->da;
1808 } else if (strcmp(fieldName, "CS") == 0 || strcmp(fieldName, "Cs") == 0) {
1809 globalVec = user->CS;
1810 localVec = user->lCs;
1811 dm = user->da;
1812 } else if (strcmp(fieldName, "Diffusivity") == 0) {
1813 globalVec = user->Diffusivity;
1814 localVec = user->lDiffusivity;
1815 dm = user->da;
1816 } else if (strcmp(fieldName, "DiffusivityGradient") == 0) {
1817 globalVec = user->DiffusivityGradient;
1818 localVec = user->lDiffusivityGradient;
1819 dm = user->fda;
1820 } else if (strcmp(fieldName, "Csi") == 0) {
1821 globalVec = user->Csi;
1822 localVec = user->lCsi;
1823 dm = user->fda;
1824 dof = 3;
1825 face_direction = 'i';
1826 } else if (strcmp(fieldName, "Eta") == 0) {
1827 globalVec = user->Eta;
1828 localVec = user->lEta;
1829 dm = user->fda;
1830 dof = 3;
1831 face_direction = 'j';
1832 } else if (strcmp(fieldName, "Zet") == 0) {
1833 globalVec = user->Zet;
1834 localVec = user->lZet;
1835 dm = user->fda;
1836 dof = 3;
1837 face_direction = 'k';
1838 }else if (strcmp(fieldName, "Nvert") == 0) {
1839 globalVec = user->Nvert;
1840 localVec = user->lNvert;
1841 dm = user->da;
1842 // Add other fields as needed
1843 } else if (strcmp(fieldName, "Aj") == 0) {
1844 globalVec = user->Aj;
1845 localVec = user->lAj;
1846 dm = user->da;
1847 } else if (strcmp(fieldName, "Cent") == 0) {
1848 globalVec = user->Cent;
1849 localVec = user->lCent;
1850 dm = user->fda;
1851 }else if (strcmp(fieldName, "GridSpace") == 0) {
1852 globalVec = user->GridSpace;
1853 localVec = user->lGridSpace;
1854 dm = user->fda;
1855 }else if (strcmp(fieldName, "Centx") == 0) {
1856 globalVec = user->Centx;
1857 localVec = user->lCentx;
1858 dm = user->fda;
1859 dof = 3;
1860 face_direction = 'i';
1861 }else if (strcmp(fieldName, "Centy") == 0) {
1862 globalVec = user->Centy;
1863 localVec = user->lCenty;
1864 dm = user->fda;
1865 dof = 3;
1866 face_direction = 'j';
1867 }else if (strcmp(fieldName, "Centz") == 0) {
1868 globalVec = user->Centz;
1869 localVec = user->lCentz;
1870 dm = user->fda;
1871 dof = 3;
1872 face_direction = 'k';
1873 }else if (strcmp(fieldName,"ICsi") == 0){
1874 globalVec = user->ICsi;
1875 localVec = user->lICsi;
1876 dm = user->fda;
1877 dof = 3;
1878 face_direction = 'i';
1879 }else if (strcmp(fieldName,"IEta") == 0){
1880 globalVec = user->IEta;
1881 localVec = user->lIEta;
1882 dm = user->fda;
1883 dof = 3;
1884 face_direction = 'i';
1885 }else if (strcmp(fieldName,"IZet") == 0){
1886 globalVec = user->IZet;
1887 localVec = user->lIZet;
1888 dm = user->fda;
1889 dof = 3;
1890 face_direction = 'i';
1891 }else if (strcmp(fieldName,"JCsi") == 0){
1892 globalVec = user->JCsi;
1893 localVec = user->lJCsi;
1894 dm = user->fda;
1895 dof = 3;
1896 face_direction = 'j';
1897 }else if (strcmp(fieldName,"JEta") == 0){
1898 globalVec = user->JEta;
1899 localVec = user->lJEta;
1900 dm = user->fda;
1901 dof = 3;
1902 face_direction = 'j';
1903 }else if (strcmp(fieldName,"JZet") == 0){
1904 globalVec = user->JZet;
1905 localVec = user->lJZet;
1906 dm = user->fda;
1907 dof = 3;
1908 face_direction = 'j';
1909 }else if (strcmp(fieldName,"KCsi") == 0){
1910 globalVec = user->KCsi;
1911 localVec = user->lKCsi;
1912 dm = user->fda;
1913 dof = 3;
1914 face_direction = 'k';
1915 }else if (strcmp(fieldName,"KEta") == 0){
1916 globalVec = user->KEta;
1917 localVec = user->lKEta;
1918 dm = user->fda;
1919 dof = 3;
1920 face_direction = 'k';
1921 }else if (strcmp(fieldName,"KZet") == 0){
1922 globalVec = user->KZet;
1923 localVec = user->lKZet;
1924 dm = user->fda;
1925 dof = 3;
1926 face_direction = 'k';
1927 }else if (strcmp(fieldName,"IAj") == 0){
1928 globalVec = user->IAj;
1929 localVec = user->lIAj;
1930 dm = user->da;
1931 dof = 1;
1932 face_direction = 'i';
1933 }else if (strcmp(fieldName,"JAj") == 0){
1934 globalVec = user->JAj;
1935 localVec = user->lJAj;
1936 dm = user->da;
1937 dof = 1;
1938 face_direction = 'j';
1939 }else if (strcmp(fieldName,"KAj") == 0){
1940 globalVec = user->KAj;
1941 localVec = user->lKAj;
1942 dm = user->da;
1943 dof = 1;
1944 face_direction = 'k';
1945 }else if (strcmp(fieldName,"Phi") == 0){ // Pressure correction term.
1946 globalVec = user->Phi;
1947 localVec = user->lPhi;
1948 dm = user->da;
1949 }else if (strcmp(fieldName,"Psi") == 0){ // Particle scalar property.
1950 globalVec = user->Psi;
1951 localVec = user->lPsi;
1952 dm = user->da;
1953 }else if (strcmp(fieldName,"Nvert_o") == 0){
1954 globalVec = user->Nvert_o;
1955 localVec = user->lNvert_o;
1956 dm = user->da;
1957 }else if (strcmp(fieldName,"ParticleCount") == 0){
1958 globalVec = user->ParticleCount;
1959 localVec = user->lParticleCount;
1960 dm = user->da;
1961 }else if (strcmp(fieldName,"K_Omega") == 0){
1962 globalVec = user->K_Omega;
1963 localVec = user->lK_Omega;
1964 dm = user->fda2;
1965 }else if (strcmp(fieldName,"K_Omega_o") == 0){
1966 globalVec = user->K_Omega_o;
1967 localVec = user->lK_Omega_o;
1968 dm = user->fda2;
1969 }else {
1970 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Field '%s' not recognized for ghost update.", fieldName);
1971 }
1972
1973 // --- 2. Check if components were found ---
1974 if (!globalVec) {
1975 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Global vector for field '%s' is NULL.", fieldName);
1976 }
1977 if (!localVec) {
1978 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Local vector for field '%s' is NULL.", fieldName);
1979 }
1980 if (!dm) {
1981 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "DM for field '%s' is NULL.", fieldName);
1982 }
1983
1984 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Identified components for '%s': DM=%p, GlobalVec=%p, LocalVec=%p.\n",
1985 rank, fieldName, (void*)dm, (void*)globalVec, (void*)localVec);
1986
1987 // --- 3. Optional Debugging: Norm Before Update ---
1988 // Use your logging convention check
1989 // if (get_log_level() >= LOG_LEVEL_DEBUG && is_function_allowed("UpdateLocalGhosts")) { // Example check
1990 if(get_log_level() == LOG_DEBUG && is_function_allowed(__func__)){
1991 PetscReal norm_global_before;
1992 ierr = VecNorm(globalVec, NORM_INFINITY, &norm_global_before); CHKERRQ(ierr);
1993 LOG_ALLOW(GLOBAL, LOG_INFO,"Max norm '%s' (Global) BEFORE Ghost Update: %g\n", fieldName, norm_global_before);
1994 // Optional: Norm of local vector before update (might contain old ghost values)
1995 // PetscReal norm_local_before;
1996 // ierr = VecNorm(localVec, NORM_INFINITY, &norm_local_before); CHKERRQ(ierr);
1997 // LOG_ALLOW(GLOBAL, LOG_DEBUG,"Max norm '%s' (Local) BEFORE Ghost Update: %g\n", fieldName, norm_local_before);
1998 }
1999
2000 // --- 4. Perform the Global-to-Local Transfer (Ghost Update) ---
2001 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Calling DMGlobalToLocalBegin/End for '%s'.\n", rank, fieldName);
2002 ierr = DMGlobalToLocalBegin(dm, globalVec, INSERT_VALUES, localVec); CHKERRQ(ierr);
2003 ierr = DMGlobalToLocalEnd(dm, globalVec, INSERT_VALUES, localVec); CHKERRQ(ierr);
2004 ierr = RepairPeriodicNormalFaceGhosts(user, dm, localVec, dof, face_direction,
2005 component_staggered); CHKERRQ(ierr);
2006 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Completed DMGlobalToLocalBegin/End for '%s'.\n", rank, fieldName);
2007
2008 // --- 5. Optional Debugging: Norm After Update ---
2009 // Use your logging convention check
2010 // if (get_log_level() >= LOG_LEVEL_DEBUG && is_function_allowed("UpdateLocalGhosts")) { // Example check
2011 if(get_log_level() == LOG_DEBUG && is_function_allowed(__func__)){ // Using your specific check
2012 PetscReal norm_local_after;
2013 ierr = VecNorm(localVec, NORM_INFINITY, &norm_local_after); CHKERRQ(ierr);
2014 LOG_ALLOW(GLOBAL, LOG_INFO,"Max norm '%s' (Local) AFTER Ghost Update: %g\n", fieldName, norm_local_after);
2015
2016 // --- 6. Optional Debugging: Specific Point Checks (Example for Ucat on Rank 0/1) ---
2017 // (Keep this conditional if it's only for specific debug scenarios)
2018 if (strcmp(fieldName, "Ucat") == 0) { // Only do detailed checks for Ucat for now
2019 PetscMPIInt rank_test;
2020 MPI_Comm_rank(PETSC_COMM_WORLD, &rank_test);
2021
2022 // Get Local Info needed for indexing checks
2023 DMDALocalInfo info_check;
2024 ierr = DMDAGetLocalInfo(dm, &info_check); CHKERRQ(ierr); // Use the correct dm
2025
2026 // Buffer for array pointer
2027 Cmpnts ***lUcat_arr_test = NULL;
2028 PetscErrorCode ierr_test = 0;
2029
2030 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Testing '%s' access immediately after ghost update...\n", rank_test, fieldName);
2031 ierr_test = DMDAVecGetArrayDOFRead(dm, localVec, &lUcat_arr_test); // Use correct dm and localVec
2032
2033 if (ierr_test) {
2034 LOG_ALLOW(LOCAL, LOG_ERROR, "Rank %d: ERROR %d getting '%s' array after ghost update!\n", rank_test, ierr_test, fieldName);
2035 } else if (!lUcat_arr_test) {
2036 LOG_ALLOW(LOCAL, LOG_ERROR, "Rank %d: ERROR NULL pointer getting '%s' array after ghost update!\n", rank_test, fieldName);
2037 }
2038 else {
2039 // Check owned interior point (e.g., first interior point)
2040 PetscInt k_int = info_check.zs + (info_check.zm > 1 ? 1 : 0); // Global k index (at least zs+1 if possible)
2041 PetscInt j_int = info_check.ys + (info_check.ym > 1 ? 1 : 0); // Global j index
2042 PetscInt i_int = info_check.xs + (info_check.xm > 1 ? 1 : 0); // Global i index
2043 // Ensure indices are within global bounds if domain is very small
2044 //if (k_int >= info_check.mz-1) k_int = info_check.mz-2; if (k_int < 1) k_int = 1;
2045 //if (j_int >= info_check.my-1) j_int = info_check.my-2; if (j_int < 1) j_int = 1;
2046 // if (i_int >= info_check.mx-1) i_int = info_check.mx-2; if (i_int < 1) i_int = 1;
2047 // clamp k_int to [1 .. mz-2]
2048 if (k_int >= info_check.mz - 1) {
2049 k_int = info_check.mz - 2;
2050 }
2051 if (k_int < 1) {
2052 k_int = 1;
2053 }
2054
2055 // clamp j_int to [1 .. my-2]
2056 if (j_int >= info_check.my - 1) {
2057 j_int = info_check.my - 2;
2058 }
2059 if (j_int < 1) {
2060 j_int = 1;
2061 }
2062
2063 // clamp i_int to [1 .. mx-2]
2064 if (i_int >= info_check.mx - 1) {
2065 i_int = info_check.mx - 2;
2066 }
2067 if (i_int < 1) {
2068 i_int = 1;
2069 }
2070
2071 // Only attempt read if indices are actually owned (relevant for multi-rank)
2072 if (k_int >= info_check.zs && k_int < info_check.zs + info_check.zm &&
2073 j_int >= info_check.ys && j_int < info_check.ys + info_check.ym &&
2074 i_int >= info_check.xs && i_int < info_check.xs + info_check.xm)
2075 {
2076 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);
2077 Cmpnts test_val_owned_interior = lUcat_arr_test[k_int][j_int][i_int];
2078 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: SUCCESS reading owned interior: x=%g\n", rank_test, test_val_owned_interior.x);
2079 } else {
2080 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);
2081 }
2082
2083
2084 // Check owned boundary point (e.g., first owned point)
2085 PetscInt k_bnd = info_check.zs; // Global k index
2086 PetscInt j_bnd = info_check.ys; // Global j index
2087 PetscInt i_bnd = info_check.xs; // Global i index
2088 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);
2089 Cmpnts test_val_owned_boundary = lUcat_arr_test[k_bnd][j_bnd][i_bnd];
2090 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: SUCCESS reading owned boundary: x=%g\n", rank_test, test_val_owned_boundary.x);
2091
2092
2093 // Check ghost point (e.g., one layer below in k, if applicable)
2094 if (info_check.zs > 0) { // Only if there's a rank below
2095 PetscInt k_ghost = info_check.zs - 1;
2096 PetscInt j_ghost = info_check.ys; // Use start of owned y, simple example
2097 PetscInt i_ghost = info_check.xs; // Use start of owned x, simple example
2098 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Attempting test read GHOST [%d][%d][%d] (Global)\n", rank_test, k_ghost, j_ghost, i_ghost);
2099 Cmpnts test_val_ghost = lUcat_arr_test[k_ghost][j_ghost][i_ghost];
2100 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: SUCCESS reading ghost: x=%g\n", rank_test, test_val_ghost.x);
2101 } else {
2102 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Skipping ghost test read (zs=0).\n", rank_test);
2103 }
2104
2105 // Restore the array
2106 ierr_test = DMDAVecRestoreArrayDOFRead(dm, localVec, &lUcat_arr_test);
2107 if(ierr_test){ LOG_ALLOW(LOCAL, LOG_ERROR, "Rank %d: ERROR %d restoring '%s' array after test read!\n", rank_test, ierr_test, fieldName); }
2108 LOG_ALLOW(LOCAL, LOG_DEBUG, "Rank %d: Finished testing '%s' access.\n", rank_test, fieldName);
2109 }
2110 } // end if Ucat
2111 } // end debug logging check
2112
2113 LOG_ALLOW(GLOBAL, LOG_INFO, "Rank %d: Completed ghost update for field '%s'.\n", rank, fieldName);
2115 PetscFunctionReturn(0);
2116}
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
Definition logging.c:183
static PetscErrorCode RepairPeriodicNormalFaceGhosts(UserCtx *user, DM dm, Vec local_vec, PetscInt dof, char face_direction, PetscBool component_staggered)
Repairs the adjacent normal ghost layer for periodic face-staggered data.
Definition setup.c:1586
Vec K_Omega_o
Definition variables.h:935
Vec K_Omega
Definition variables.h:935
Vec lK_Omega_o
Definition variables.h:935
Vec lK_Omega
Definition variables.h:935
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 2124 of file setup.c.

2125{
2126 PetscErrorCode ierr;
2127 PetscFunctionBeginUser;
2128
2130
2131 LOG_ALLOW(GLOBAL,LOG_INFO, "--- Setting up Boundary Conditions ---\n");
2132 // --- Phase 1: Parse and initialize BC configuration for all blocks ---
2133 LOG_ALLOW(GLOBAL,LOG_INFO,"Parsing BC configuration files and initializing boundary condition data structures.\n");
2134 UserCtx *user_finest = simCtx->usermg.mgctx[simCtx->usermg.mglevels-1].user;
2135 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
2136 LOG_ALLOW(GLOBAL,LOG_DEBUG, " -> Processing Block %d:\n", bi);
2137
2138 // --- Generate the filename for the current block ---
2139 const char *current_bc_filename = simCtx->bcs_files[bi];
2140 LOG_ALLOW(GLOBAL,LOG_DEBUG," -> Processing Block %d using config file '%s'\n", bi, current_bc_filename);
2141 // This will populate user_finest[bi].boundary_faces
2142
2143 //ierr = ParseAllBoundaryConditions(&user_finest[bi],current_bc_filename); CHKERRQ(ierr);
2144
2145 ierr = BoundarySystem_Initialize(&user_finest[bi], current_bc_filename); CHKERRQ(ierr);
2146 }
2147
2148 // Propogate BC Configuration to coarser levels.
2149 ierr = PropagateBoundaryConfigToCoarserLevels(simCtx); CHKERRQ(ierr);
2150
2151 // Validate the geometric contract before any metric consumes periodic geometry.
2152 for (PetscInt level = simCtx->usermg.mglevels - 1; level >= 0; level--) {
2153 UserCtx *level_users = simCtx->usermg.mgctx[level].user;
2154 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
2155 ierr = ValidatePeriodicGeometry(&level_users[bi]); CHKERRQ(ierr);
2156 }
2157 }
2158
2159 // --- Calculate Grid Metrics (requires BC configuration) ---
2160 // NOTE: This MUST be called here (after BC initialization but before inlet/outlet calculations) because:
2161 // 1. Periodic BC corrections in metric calculations need boundary_faces data to be populated
2162 // 2. Inlet/Outlet area calculations (below) require computed metrics (Csi, Eta, Zet) to be available
2163 // Previously this was in SetupGridAndSolvers, but that caused metrics to be computed without BC info.
2164 LOG_ALLOW(GLOBAL,LOG_INFO,"Computing grid metrics with boundary condition information.\n");
2165 ierr = CalculateAllGridMetrics(simCtx); CHKERRQ(ierr);
2166
2167 // --- Phase 2: Calculate inlet/outlet properties (requires computed metrics) ---
2168 LOG_ALLOW(GLOBAL,LOG_INFO,"Calculating inlet and outlet face properties.\n");
2169 for (PetscInt bi = 0; bi < simCtx->block_number; bi++) {
2170 // Call the function to calculate the center of the inlet face & the inlet area, which may be used to calculate Boundary values.
2171 ierr = CalculateInletProperties(&user_finest[bi]); CHKERRQ(ierr);
2172
2173 // Call the function to calculate the center of the outlet face & the outlet area, which may be used to calculate Boundary values.
2174 ierr = CalculateOutletProperties(&user_finest[bi]); CHKERRQ(ierr);
2175 }
2176
2177 LOG_ALLOW(GLOBAL,LOG_INFO, "--- Boundary Conditions setup complete ---\n");
2178
2179
2181 PetscFunctionReturn(0);
2182}
PetscErrorCode BoundarySystem_Initialize(UserCtx *user, const char *bcs_filename)
Initializes the entire boundary system.
Definition Boundaries.c:891
PetscErrorCode PropagateBoundaryConfigToCoarserLevels(SimCtx *simCtx)
Propagates boundary condition configuration from finest to all coarser multigrid levels.
Definition Boundaries.c:988
PetscErrorCode CalculateAllGridMetrics(SimCtx *simCtx)
Orchestrates the calculation of all grid metrics.
Definition Metric.c:1942
PetscErrorCode CalculateOutletProperties(UserCtx *user)
Calculates the center and area of the primary OUTLET face.
Definition grid.c:1119
PetscErrorCode ValidatePeriodicGeometry(UserCtx *user)
Validates that configured geometric periodic seams match by translation.
Definition grid.c:380
PetscErrorCode CalculateInletProperties(UserCtx *user)
Calculates the center and area of the primary INLET face.
Definition grid.c:1066
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 2188 of file setup.c.

2189{
2190 PetscErrorCode ierr;
2191 PetscReal ***data;
2192 PetscReal *dataContiguous;
2193 PetscInt k, j;
2194
2195 PetscFunctionBegin;
2196 /* Step 1: Allocate memory for an array of nz layer pointers (zero-initialized) */
2197 ierr = PetscCalloc1(nz, &data); CHKERRQ(ierr);
2198
2199 /* Step 2: Allocate memory for all row pointers (nz * ny pointers) */
2200 ierr = PetscCalloc1(nz * ny, &data[0]); CHKERRQ(ierr);
2201 for (k = 1; k < nz; k++) {
2202 data[k] = data[0] + k * ny;
2203 }
2204
2205 /* Step 3: Allocate one contiguous block for all data elements (nz*ny*nx) */
2206 ierr = PetscCalloc1(nz * ny * nx, &dataContiguous); CHKERRQ(ierr);
2207
2208 /* Build the 3D pointer structure: each row pointer gets the correct segment of data */
2209 for (k = 0; k < nz; k++) {
2210 for (j = 0; j < ny; j++) {
2211 data[k][j] = dataContiguous + (k * ny + j) * nx;
2212 /* Memory is already zeroed by PetscCalloc1, so no manual initialization is needed */
2213 }
2214 }
2215 *array = data;
2216 PetscFunctionReturn(0);
2217}

◆ 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 2223 of file setup.c.

2224{
2225 PetscErrorCode ierr;
2226 (void)nz;
2227 (void)ny;
2228
2229 PetscFunctionBegin;
2230 if (!array || !array[0] || !array[0][0] ) { // Added more robust check
2231 LOG_ALLOW(GLOBAL, LOG_WARNING, "Deallocate3DArrayScalar called with potentially unallocated or NULL array.\n");
2232 if (array) {
2233 if (array[0]) { // Check if row pointers might exist
2234 // Cannot safely access array[0][0] if array[0] might be invalid/freed
2235 // Standard deallocation below assumes valid pointers.
2236 ierr = PetscFree(array[0]); CHKERRQ(ierr); // Free row pointers if they exist
2237 }
2238 ierr = PetscFree(array); CHKERRQ(ierr); // Free layer pointers if they exist
2239 }
2240 PetscFunctionReturn(0);
2241 }
2242
2243 // --- Standard Deallocation (assuming valid allocation) ---
2244
2245 /* 1. Free the contiguous block of PetscReal values.
2246 The starting address was stored in array[0][0]. */
2247 ierr = PetscFree(array[0][0]); CHKERRQ(ierr); // Free the ACTUAL DATA
2248
2249 /* 2. Free the contiguous block of row pointers.
2250 The starting address was stored in array[0]. */
2251 ierr = PetscFree(array[0]); CHKERRQ(ierr); // Free the ROW POINTERS
2252
2253 /* 3. Free the layer pointer array.
2254 The starting address is 'array' itself. */
2255 ierr = PetscFree(array); CHKERRQ(ierr); // Free the LAYER POINTERS
2256
2257 PetscFunctionReturn(0);
2258}

◆ 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 2266 of file setup.c.

2267{
2268 PetscErrorCode ierr;
2269 Cmpnts ***data;
2270 Cmpnts *dataContiguous;
2271 PetscInt k, j;
2272 PetscMPIInt rank;
2273
2274 PetscFunctionBegin;
2275
2276 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
2277
2278 /* Step 1: Allocate memory for nz layer pointers (zeroed) */
2279 ierr = PetscCalloc1(nz, &data); CHKERRQ(ierr);
2280
2281 LOG_ALLOW(LOCAL,LOG_DEBUG," [Rank %d] memory allocated for outermost layer (%d k-layer pointers).\n",rank,nz);
2282
2283 /* Step 2: Allocate memory for all row pointers (nz * ny pointers) */
2284 ierr = PetscCalloc1(nz * ny, &data[0]); CHKERRQ(ierr);
2285 for (k = 1; k < nz; k++) {
2286 data[k] = data[0] + k * ny;
2287 }
2288
2289 LOG_ALLOW(LOCAL,LOG_DEBUG,"[Rank %d] memory allocated for %dx%d row pointers.\n",rank,nz,ny);
2290
2291 /* Step 3: Allocate one contiguous block for nz*ny*nx Cmpnts structures (zeroed) */
2292 ierr = PetscCalloc1(nz * ny * nx, &dataContiguous); CHKERRQ(ierr);
2293
2294 LOG_ALLOW(GLOBAL,LOG_DEBUG,"[Rank %d] memory allocated for contigous block of %dx%dx%d Cmpnts structures).\n",rank,nz,ny,nx);
2295
2296 /* Build the 3D pointer structure for vector data */
2297 for (k = 0; k < nz; k++) {
2298 for (j = 0; j < ny; j++) {
2299 data[k][j] = dataContiguous + (k * ny + j) * nx;
2300 /* The PetscCalloc1 call has already initialized each Cmpnts to zero. */
2301 }
2302 }
2303
2304 LOG_ALLOW(GLOBAL,LOG_DEBUG,"[Rank %d] 3D pointer structure for vector data created. \n",rank);
2305
2306 *array = data;
2307 PetscFunctionReturn(0);
2308}

◆ 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 2316 of file setup.c.

2317{
2318 PetscErrorCode ierr;
2319 (void)nz;
2320 (void)ny;
2321
2322 PetscFunctionBegin;
2323 // If array is NULL or hasn't been allocated properly, just return.
2324 if (!array || !array[0] || !array[0][0] ) {
2325 LOG_ALLOW(GLOBAL, LOG_WARNING, "Deallocate3DArrayVector called with potentially unallocated or NULL array.\n");
2326 // Attempt to free what might exist, but be cautious
2327 if (array) {
2328 if (array[0]) { // Check if row pointers were allocated
2329 // We don't have a direct pointer to the contiguous data block
2330 // saved separately in this allocation scheme. The allocation relies
2331 // on array[0][0] pointing to it. If array[0] was freed first,
2332 // accessing array[0][0] is unsafe.
2333 // The allocation scheme where the contiguous data block is not
2334 // stored separately makes safe deallocation tricky if freeing
2335 // happens out of order or if parts are NULL.
2336
2337 // A SAFER ALLOCATION/DEALLOCATION would store the data pointer separately.
2338 // Given the current allocation scheme, the order MUST be:
2339 // 1. Free the data block (pointed to by array[0][0])
2340 // 2. Free the row pointer block (pointed to by array[0])
2341 // 3. Free the layer pointer block (pointed to by array)
2342
2343 // Let's assume the allocation was successful and pointers are valid.
2344 // Get pointer to the contiguous data block *before* freeing row pointers
2345 Cmpnts *dataContiguous = array[0][0];
2346 ierr = PetscFree(dataContiguous); CHKERRQ(ierr); // Free data block
2347
2348 // Now free the row pointers block
2349 ierr = PetscFree(array[0]); CHKERRQ(ierr); // Free row pointers
2350
2351 }
2352 // Finally, free the array of layer pointers
2353 ierr = PetscFree(array); CHKERRQ(ierr);
2354 }
2355 PetscFunctionReturn(0); // Return gracefully if input was NULL initially
2356 }
2357
2358
2359 // --- Standard Deallocation (assuming valid allocation) ---
2360
2361 /* 1. Free the contiguous block of Cmpnts structures.
2362 The starting address was stored in array[0][0] by Allocate3DArrayVector. */
2363 ierr = PetscFree(array[0][0]); CHKERRQ(ierr); // Free the ACTUAL DATA
2364
2365 /* 2. Free the contiguous block of row pointers.
2366 The starting address was stored in array[0]. */
2367 ierr = PetscFree(array[0]); CHKERRQ(ierr); // Free the ROW POINTERS
2368
2369 /* 3. Free the layer pointer array.
2370 The starting address is 'array' itself. */
2371 ierr = PetscFree(array); CHKERRQ(ierr); // Free the LAYER POINTERS
2372
2373 PetscFunctionReturn(0);
2374}

◆ 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 2382 of file setup.c.

2386{
2387 PetscErrorCode ierr = 0; // Standard PETSc error code, not explicitly set here but good practice.
2388 PetscInt xs_node_global_rank; // Global index of the first node owned by this rank in the specified dimension.
2389 PetscInt num_nodes_owned_rank; // Number of nodes owned by this rank in this dimension (local count, excluding ghosts).
2390 PetscInt GlobalNodesInDim_from_info; // Total number of DA points in this dimension, from DMDALocalInfo.
2391
2392 PetscFunctionBeginUser;
2393
2394 // --- 1. Input Validation ---
2395 if (!info_nodes || !xs_cell_global_out || !xm_cell_local_out) {
2396 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Null pointer passed to GetOwnedCellRange.");
2397 }
2398
2399 // --- 2. Extract Node Ownership and Global Dimension Information from DMDALocalInfo ---
2400 if (dim == 0) { // I-direction
2401 xs_node_global_rank = info_nodes->xs;
2402 num_nodes_owned_rank = info_nodes->xm;
2403 GlobalNodesInDim_from_info = info_nodes->mx;
2404 } else if (dim == 1) { // J-direction
2405 xs_node_global_rank = info_nodes->ys;
2406 num_nodes_owned_rank = info_nodes->ym;
2407 GlobalNodesInDim_from_info = info_nodes->my;
2408 } else if (dim == 2) { // K-direction
2409 xs_node_global_rank = info_nodes->zs;
2410 num_nodes_owned_rank = info_nodes->zm;
2411 GlobalNodesInDim_from_info = info_nodes->mz;
2412 } else {
2413 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid dimension %d in GetOwnedCellRange. Must be 0, 1, or 2.", dim);
2414 }
2415
2416 // --- 3. Correct for User-Defined Ghost Node ---
2417 // Per the function's contract (@warning), the DA size includes an extra, non-physical
2418 // node. We subtract 1 to get the true number of physical nodes for cell calculations.
2419 const PetscInt physical_nodes_in_dim = GlobalNodesInDim_from_info - 1;
2420
2421 // --- 4. Handle Edge Cases for Physical Domain Size ---
2422 // If the physical domain has 0 or 1 node, no cells can be formed.
2423 if (physical_nodes_in_dim <= 1) {
2424 *xs_cell_global_out = xs_node_global_rank; // Still report the rank's starting node
2425 *xm_cell_local_out = 0; // But 0 cells
2426 PetscFunctionReturn(0);
2427 }
2428
2429 // --- 5. Determine Cell Ownership Based on Corrected Node Ownership ---
2430 // The first cell this rank *could* define has its origin at the first node this rank owns.
2431 *xs_cell_global_out = xs_node_global_rank;
2432
2433 // If the rank owns no nodes in this dimension, it can't form any cell origins.
2434 if (num_nodes_owned_rank == 0) {
2435 *xm_cell_local_out = 0;
2436 } else {
2437 // --- BUG FIX APPLIED HERE ---
2438 // The previous logic incorrectly assumed a cell's end node (N_{k+1}) must be on the
2439 // same rank as its origin node (N_k). The correct logic is to find the intersection
2440 // between the nodes this rank owns and the nodes that are valid origins globally.
2441
2442 // The first node owned by the rank is its first potential origin.
2443 PetscInt first_owned_origin = xs_node_global_rank;
2444
2445 // The absolute last node owned by this rank. Any node up to and including this one
2446 // is a potential cell origin from this rank's perspective.
2447 PetscInt last_node_owned_by_rank = xs_node_global_rank + num_nodes_owned_rank - 1;
2448
2449 // The absolute last node in the entire PHYSICAL domain that can serve as a cell origin.
2450 // If there are `N` physical nodes (0 to N-1), this index is `N-2`.
2451 PetscInt last_possible_origin_global_idx = physical_nodes_in_dim - 2;
2452
2453 // The actual last origin this rank can provide is the *minimum* of what it owns
2454 // and what is globally possible. This correctly handles both ranks in the middle of
2455 // the domain and the very last rank.
2456 PetscInt actual_last_origin_this_rank_can_form = PetscMin(last_node_owned_by_rank, last_possible_origin_global_idx);
2457
2458 // If the first potential origin this rank owns is already beyond the actual last
2459 // origin it can form, then this rank forms no valid cell origins. This happens if
2460 // the rank only owns the very last physical node.
2461 if (first_owned_origin > actual_last_origin_this_rank_can_form) {
2462 *xm_cell_local_out = 0;
2463 } else {
2464 // The number of cells is the count of valid origins this rank owns.
2465 // (Count = Last Index - First Index + 1)
2466 *xm_cell_local_out = actual_last_origin_this_rank_can_form - first_owned_origin + 1;
2467 }
2468 }
2469
2470 PetscFunctionReturn(ierr);
2471}
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 2479 of file setup.c.

2480{
2481 PetscErrorCode ierr;
2482 PetscMPIInt rank;
2483 PetscMPIInt size; // MPI communicator size
2484 const PetscMPIInt *neighbor_ranks_ptr; // Pointer to raw neighbor data from PETSc
2485
2486 PetscFunctionBeginUser;
2488 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2489 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr); // Get MPI size for validation
2490
2491 LOG_ALLOW(GLOBAL, LOG_INFO, "Rank %d: Computing DMDA neighbor ranks.\n", rank);
2492
2493 if (!user || !user->da) {
2494 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx or user->da is NULL in ComputeAndStoreNeighborRanks.");
2495 }
2496
2497 // Get the neighbor information from the DMDA
2498 // neighbor_ranks_ptr will point to an internal PETSc array of 27 ranks.
2499 ierr = DMDAGetNeighbors(user->da, &neighbor_ranks_ptr); CHKERRQ(ierr);
2500
2501 // Log the raw values from DMDAGetNeighbors for boundary-relevant directions for debugging
2502 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",
2503 rank,
2504 neighbor_ranks_ptr[12], neighbor_ranks_ptr[14],
2505 neighbor_ranks_ptr[10], neighbor_ranks_ptr[16],
2506 neighbor_ranks_ptr[4], neighbor_ranks_ptr[22],
2507 (int)MPI_PROC_NULL);
2508
2509 // PETSc standard indices for 3D face neighbors from the 27-point stencil:
2510 // Index = k_offset*9 + j_offset*3 + i_offset (where offsets -1,0,1 map to 0,1,2)
2511 // Center: (i_off=1, j_off=1, k_off=1) => 1*9 + 1*3 + 1 = 13
2512 // X-min: (i_off=0, j_off=1, k_off=1) => 1*9 + 1*3 + 0 = 12
2513 // X-plus: (i_off=2, j_off=1, k_off=1) => 1*9 + 1*3 + 2 = 14
2514 // Y-min: (i_off=1, j_off=0, k_off=1) => 1*9 + 0*3 + 1 = 10
2515 // Y-plus: (i_off=1, j_off=2, k_off=1) => 1*9 + 2*3 + 1 = 16
2516 // Z-min: (i_off=1, j_off=1, k_off=0) => 0*9 + 1*3 + 1 = 4
2517 // Z-plus: (i_off=1, j_off=1, k_off=2) => 2*9 + 1*3 + 1 = 22
2518
2519 if (neighbor_ranks_ptr[13] != rank) {
2520 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",
2521 rank, neighbor_ranks_ptr[13], rank);
2522 // This warning is important. If the center isn't the current rank, the offsets are likely wrong.
2523 // However, PETSc should ensure this unless the DM is too small for a 3x3x3 stencil.
2524 }
2525
2526 // Assign and sanitize each neighbor rank
2527 PetscMPIInt temp_neighbor;
2528
2529 temp_neighbor = neighbor_ranks_ptr[12]; // xm
2530 if (temp_neighbor < 0 || temp_neighbor >= size) {
2531 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);
2532 user->neighbors.rank_xm = MPI_PROC_NULL;
2533 } else {
2534 user->neighbors.rank_xm = temp_neighbor;
2535 }
2536
2537 temp_neighbor = neighbor_ranks_ptr[14]; // xp
2538 if (temp_neighbor < 0 || temp_neighbor >= size) {
2539 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);
2540 user->neighbors.rank_xp = MPI_PROC_NULL;
2541 } else {
2542 user->neighbors.rank_xp = temp_neighbor;
2543 }
2544
2545 temp_neighbor = neighbor_ranks_ptr[10]; // ym
2546 if (temp_neighbor < 0 || temp_neighbor >= size) {
2547 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);
2548 user->neighbors.rank_ym = MPI_PROC_NULL;
2549 } else {
2550 user->neighbors.rank_ym = temp_neighbor;
2551 }
2552
2553 temp_neighbor = neighbor_ranks_ptr[16]; // yp
2554 if (temp_neighbor < 0 || temp_neighbor >= size) {
2555 // The log for index 16 was "zm" in your output, should be yp
2556 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);
2557 user->neighbors.rank_yp = MPI_PROC_NULL;
2558 } else {
2559 user->neighbors.rank_yp = temp_neighbor;
2560 }
2561
2562 temp_neighbor = neighbor_ranks_ptr[4]; // zm
2563 if (temp_neighbor < 0 || temp_neighbor >= size) {
2564 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);
2565 user->neighbors.rank_zm = MPI_PROC_NULL;
2566 } else {
2567 user->neighbors.rank_zm = temp_neighbor;
2568 }
2569
2570 temp_neighbor = neighbor_ranks_ptr[22]; // zp
2571 if (temp_neighbor < 0 || temp_neighbor >= size) {
2572 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);
2573 user->neighbors.rank_zp = MPI_PROC_NULL;
2574 } else {
2575 user->neighbors.rank_zp = temp_neighbor;
2576 }
2577
2578 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,
2579 user->neighbors.rank_xm, user->neighbors.rank_xp,
2580 user->neighbors.rank_ym, user->neighbors.rank_yp,
2581 user->neighbors.rank_zm, user->neighbors.rank_zp);
2582 PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT); // Ensure logs are flushed
2583
2584 // Note: neighbor_ranks_ptr memory is managed by PETSc, do not free it.
2586 PetscFunctionReturn(0);
2587}
PetscMPIInt rank_zm
Definition variables.h:197
PetscMPIInt rank_yp
Definition variables.h:196
PetscMPIInt rank_ym
Definition variables.h:196
PetscMPIInt rank_xp
Definition variables.h:195
RankNeighbors neighbors
Definition variables.h:888
PetscMPIInt rank_xm
Definition variables.h:195
PetscMPIInt rank_zp
Definition variables.h:197
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 2595 of file setup.c.

2596{
2597 PetscErrorCode ierr;
2598 PetscMPIInt size, rank;
2599 PetscInt px = PETSC_DECIDE, py = PETSC_DECIDE, pz = PETSC_DECIDE;
2600 PetscBool px_set = PETSC_FALSE, py_set = PETSC_FALSE, pz_set = PETSC_FALSE;
2601 SimCtx *simCtx = user->simCtx;
2602
2603 // Set no.of processors in direction 1
2604 if(simCtx->da_procs_x) {
2605 px_set = PETSC_TRUE;
2606 px = simCtx->da_procs_x;
2607 }
2608 // Set no.of processors in direction 2
2609 if(simCtx->da_procs_y) {
2610 py_set = PETSC_TRUE;
2611 py = simCtx->da_procs_y;
2612 }
2613 // Set no.of processors in direction 1
2614 if(simCtx->da_procs_z) {
2615 pz_set = PETSC_TRUE;
2616 pz = simCtx->da_procs_z;
2617 }
2618
2619 PetscFunctionBeginUser;
2621 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size); CHKERRQ(ierr);
2622 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank); CHKERRQ(ierr);
2623 LOG_ALLOW(GLOBAL, LOG_INFO, "Rank %d: Configuring DMDA processor layout for %d total processes.\n", rank, size);
2624
2625 // --- Validate User Input (Optional but Recommended) ---
2626 // Check if specified processor counts multiply to the total MPI size
2627 if (px_set && py_set && pz_set) {
2628 if (px * py * pz != size) {
2629 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP,
2630 "Specified processor layout %d x %d x %d = %d does not match MPI size %d",
2631 px, py, pz, px * py * pz, size);
2632 }
2633 LOG_ALLOW(GLOBAL, LOG_INFO, "Using specified processor layout: %d x %d x %d\n", px, py, pz);
2634 } else if (px_set || py_set || pz_set) {
2635 // If only some are set, PETSC_DECIDE will be used for others
2636 LOG_ALLOW(GLOBAL, LOG_INFO, "Using partially specified processor layout: %d x %d x %d (PETSC_DECIDE for unspecified)\n", px, py, pz);
2637 } else {
2638 LOG_ALLOW(GLOBAL, LOG_INFO, "Using fully automatic processor layout (PETSC_DECIDE x PETSC_DECIDE x PETSC_DECIDE)\n");
2639 }
2640 // Additional checks: Ensure px, py, pz are positive if set
2641 if ((px_set && px <= 0) || (py_set && py <= 0) || (pz_set && pz <= 0)) {
2642 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Specified processor counts must be positive.");
2643 }
2644
2645
2646 // --- Apply the layout to the DMDA ---
2647 ierr = DMDASetNumProcs(dm, px, py, pz); CHKERRQ(ierr);
2648 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Rank %d: DMDASetNumProcs called with px=%d, py=%d, pz=%d.\n", rank, px, py, pz);
2649
2650 // --- Store the values in UserCtx (Optional) ---
2651 // Note: If PETSC_DECIDE was used, PETSc calculates the actual values during DMSetUp.
2652 // We store the *requested* values here. To get the *actual* values used,
2653 // you would need to call DMDAGetInfo after DMSetUp.
2654 /*
2655 if (user) {
2656 user->procs_x = px;
2657 user->procs_y = py;
2658 user->procs_z = pz;
2659 }
2660 */
2662 PetscFunctionReturn(0);
2663}

◆ 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 2673 of file setup.c.

2674{
2675 PetscErrorCode ierr;
2676 PetscInt nblk = simCtx->block_number;
2677 PetscInt size = simCtx->size;
2678 BoundingBox *final_bboxlist = NULL;
2679
2680 PetscFunctionBeginUser;
2682
2683 LOG_ALLOW(GLOBAL, LOG_INFO, "Starting full rank communication setup for %d block(s).\n", nblk);
2684
2685 UserCtx *user_finest = simCtx->usermg.mgctx[simCtx->usermg.mglevels - 1].user;
2686
2687 // --- Step 1: Compute neighbor ranks (unchanged) ---
2688 for (int bi = 0; bi < nblk; bi++) {
2689 ierr = ComputeAndStoreNeighborRanks(&user_finest[bi]); CHKERRQ(ierr);
2690 }
2691 LOG_ALLOW(GLOBAL, LOG_INFO, "Neighbor ranks computed and stored for all blocks.\n");
2692
2693 // --- Step 2: Allocate the final, unified list on ALL ranks ---
2694 // Every rank will build this list in parallel.
2695 ierr = PetscMalloc1(size * nblk, &final_bboxlist); CHKERRQ(ierr);
2696
2697 // --- Step 3: Loop through each block, gather then broadcast its bbox list ---
2698 for (int bi = 0; bi < nblk; bi++) {
2699 // This is a temporary pointer for the current block's list.
2700 BoundingBox *block_bboxlist = NULL;
2701
2702 LOG_ALLOW(GLOBAL, LOG_INFO, "Processing bounding boxes for block %d...\n", bi);
2703
2704 // A) GATHER: On rank 0, block_bboxlist is allocated and filled. On others, it's NULL.
2705 ierr = GatherAllBoundingBoxes(&user_finest[bi], &block_bboxlist); CHKERRQ(ierr);
2706 LOG_ALLOW(GLOBAL, LOG_DEBUG, " -> Gather complete for block %d.\n", bi);
2707
2708 // B) BROADCAST: On non-root ranks, block_bboxlist is allocated. Then, the data
2709 // from rank 0 is broadcast to all ranks. After this call, ALL ranks have
2710 // an identical, complete copy of the bounding boxes for the current block.
2711 ierr = BroadcastAllBoundingBoxes(&user_finest[bi], &block_bboxlist); CHKERRQ(ierr);
2712 LOG_ALLOW(GLOBAL, LOG_DEBUG, " -> Broadcast complete for block %d.\n", bi);
2713
2714 // C) ASSEMBLE: Every rank now copies the data for this block into the
2715 // correct segment of its final, unified list.
2716 for (int r = 0; r < size; r++) {
2717 // The layout is [r0b0, r1b0, ..., r(size-1)b0, r0b1, r1b1, ...]
2718 final_bboxlist[bi * size + r] = block_bboxlist[r];
2719 }
2720 LOG_ALLOW(GLOBAL, LOG_DEBUG, " -> Assembly into final list complete for block %d.\n", bi);
2721
2722 // D) CLEANUP: Free the temporary list for this block on ALL ranks before the next iteration.
2723 // Your helper functions use malloc, so we must use free.
2724 free(block_bboxlist);
2725 }
2726
2727 // --- Step 4: Assign the final pointer and run the last setup step ---
2728 simCtx->bboxlist = final_bboxlist;
2729 LOG_ALLOW(GLOBAL, LOG_INFO, "Final unified bboxlist created on all ranks and stored in SimCtx.\n");
2730
2731 ierr = SetupDomainCellDecompositionMap(&user_finest[0]); CHKERRQ(ierr);
2732 LOG_ALLOW(GLOBAL, LOG_INFO, "Domain Cell Composition set and broadcasted.\n");
2733
2734 LOG_ALLOW(GLOBAL, LOG_INFO, "SetupDomainRankInfo: Completed successfully.\n");
2735
2737 PetscFunctionReturn(0);
2738}
PetscErrorCode BroadcastAllBoundingBoxes(UserCtx *user, BoundingBox **bboxlist)
Broadcasts the bounding box information collected on rank 0 to all other ranks.
Definition grid.c:1016
PetscErrorCode GatherAllBoundingBoxes(UserCtx *user, BoundingBox **allBBoxes)
Gathers local bounding boxes from all MPI processes to rank 0.
Definition grid.c:954
PetscErrorCode ComputeAndStoreNeighborRanks(UserCtx *user)
Internal helper implementation: ComputeAndStoreNeighborRanks().
Definition setup.c:2479
PetscErrorCode SetupDomainCellDecompositionMap(UserCtx *user)
Internal helper implementation: SetupDomainCellDecompositionMap().
Definition setup.c:3000
Defines a 3D axis-aligned bounding box.
Definition variables.h:169
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 2746 of file setup.c.

2747{
2748 PetscErrorCode ierr;
2749 DMDALocalInfo info;
2750 Cmpnts ***lcsi_arr, ***leta_arr, ***lzet_arr; // Local metric arrays
2751 Cmpnts ***lucont_arr; // Local contravariant velocity array
2752 Cmpnts ***gucat_arr; // Global Cartesian velocity array
2753 PetscReal ***lnvert_arr; // Local Nvert array
2754 PetscReal ***laj_arr; // Local Jacobian Determinant inverse array
2755
2756 PetscFunctionBeginUser;
2758 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Starting Contravariant-to-Cartesian velocity transformation.\n");
2759
2760 // --- 1. Get DMDA Info and Check for Valid Inputs ---
2761 // All inputs (lUcont, lCsi, etc.) and outputs (Ucat) are on DMs from the UserCtx.
2762 // We get local info from fda, which governs the layout of most arrays here.
2763 ierr = DMDAGetLocalInfo(user->fda, &info); CHKERRQ(ierr);
2764 if (!user->lUcont || !user->lCsi || !user->lEta || !user->lZet || !user->lNvert || !user->Ucat) {
2765 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Contra2Cart requires lUcont, lCsi/Eta/Zet, lNvert, and Ucat to be non-NULL.");
2766 }
2767
2768
2769 // --- 2. Get Read-Only Array Access to Local Input Vectors (with ghosts) ---
2770 ierr = DMDAVecGetArrayRead(user->fda, user->lUcont, &lucont_arr); CHKERRQ(ierr);
2771 ierr = DMDAVecGetArrayRead(user->fda, user->lCsi, &lcsi_arr); CHKERRQ(ierr);
2772 ierr = DMDAVecGetArrayRead(user->fda, user->lEta, &leta_arr); CHKERRQ(ierr);
2773 ierr = DMDAVecGetArrayRead(user->fda, user->lZet, &lzet_arr); CHKERRQ(ierr);
2774 ierr = DMDAVecGetArrayRead(user->da, user->lNvert, &lnvert_arr); CHKERRQ(ierr);
2775 ierr = DMDAVecGetArrayRead(user->da, user->lAj, &laj_arr); CHKERRQ(ierr);
2776
2777 // --- 3. Get Write-Only Array Access to the Global Output Vector ---
2778 // We compute for local owned cells and write into the global vector.
2779 // PETSc handles mapping the global indices to the correct local memory locations.
2780 ierr = DMDAVecGetArray(user->fda, user->Ucat, &gucat_arr); CHKERRQ(ierr);
2781
2782
2783 // --- 4. Define Loop Bounds for INTERIOR Cells ---
2784 // We use adjusted bounds to avoid calculating Ucat on the physical domain boundaries,
2785 // as these are typically set explicitly by boundary condition functions.
2786 // The stencils use indices like i-1, j-1, k-1, so we must start loops at least at index 1.
2787 PetscInt i_start = (info.xs == 0) ? info.xs + 1 : info.xs;
2788 PetscInt i_end = (info.xs + info.xm == info.mx) ? info.xs + info.xm - 1 : info.xs + info.xm;
2789
2790 PetscInt j_start = (info.ys == 0) ? info.ys + 1 : info.ys;
2791 PetscInt j_end = (info.ys + info.ym == info.my) ? info.ys + info.ym - 1 : info.ys + info.ym;
2792
2793 PetscInt k_start = (info.zs == 0) ? info.zs + 1 : info.zs;
2794 PetscInt k_end = (info.zs + info.zm == info.mz) ? info.zs + info.zm - 1 : info.zs + info.zm;
2795
2796 // --- 5. Main Computation Loop ---
2797 // Loops over the GLOBAL indices of interior cells owned by this rank.
2798 for (PetscInt k_cell = k_start; k_cell < k_end; ++k_cell) {
2799 for (PetscInt j_cell = j_start; j_cell < j_end; ++j_cell) {
2800 for (PetscInt i_cell = i_start; i_cell < i_end; ++i_cell) {
2801
2802 // Check if the cell is a fluid cell (not solid/blanked)
2803 // if (lnvert_arr[k_cell][j_cell][i_cell] > 0.1) continue; // Skip solid/blanked cells
2804
2805 // Transformation matrix [mat] is the metric tensor at the cell center,
2806 // estimated by averaging metrics from adjacent faces.
2807 PetscReal mat[3][3];
2808
2809 // PetscReal aj_center = laj_arr[k_cell+1][j_cell+1][i_cell+1];
2810
2811 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;
2812 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;
2813 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;
2814
2815 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;
2816 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;
2817 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;
2818
2819 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;
2820 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;
2821 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;
2822
2823 // Contravariant velocity vector `q` at the cell center,
2824 // estimated by averaging face-based contravariant velocities.
2825 PetscReal q[3];
2826 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
2827 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
2828 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
2829
2830 // Solve the 3x3 system `mat * ucat = q` using Cramer's rule.
2831 PetscReal det = mat[0][0] * (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) -
2832 mat[0][1] * (mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0]) +
2833 mat[0][2] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]);
2834
2835 if (PetscAbsReal(det) < 1.0e-18) {
2836 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);
2837 }
2838
2839 PetscReal det_inv = 1.0 / det;
2840
2841 PetscReal det0 = q[0] * (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) -
2842 q[1] * (mat[0][1] * mat[2][2] - mat[0][2] * mat[2][1]) +
2843 q[2] * (mat[0][1] * mat[1][2] - mat[0][2] * mat[1][1]);
2844
2845 PetscReal det1 = -q[0] * (mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0]) +
2846 q[1] * (mat[0][0] * mat[2][2] - mat[0][2] * mat[2][0]) -
2847 q[2] * (mat[0][0] * mat[1][2] - mat[0][2] * mat[1][0]);
2848
2849 PetscReal det2 = q[0] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]) -
2850 q[1] * (mat[0][0] * mat[2][1] - mat[0][1] * mat[2][0]) +
2851 q[2] * (mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]);
2852
2853 // Store computed Cartesian velocity in the GLOBAL Ucat array at the
2854 // array index corresponding to the cell's origin node.
2855 gucat_arr[k_cell][j_cell][i_cell].x = det0 * det_inv;
2856 gucat_arr[k_cell][j_cell][i_cell].y = det1 * det_inv;
2857 gucat_arr[k_cell][j_cell][i_cell].z = det2 * det_inv;
2858 }
2859 }
2860 }
2861
2862 // --- 6. Restore Array Access ---
2863 ierr = DMDAVecRestoreArrayRead(user->fda, user->lUcont, &lucont_arr); CHKERRQ(ierr);
2864 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCsi, &lcsi_arr); CHKERRQ(ierr);
2865 ierr = DMDAVecRestoreArrayRead(user->fda, user->lEta, &leta_arr); CHKERRQ(ierr);
2866 ierr = DMDAVecRestoreArrayRead(user->fda, user->lZet, &lzet_arr); CHKERRQ(ierr);
2867 ierr = DMDAVecRestoreArrayRead(user->da, user->lNvert, &lnvert_arr); CHKERRQ(ierr);
2868 ierr = DMDAVecRestoreArrayRead(user->da, user->lAj, &laj_arr); CHKERRQ(ierr);
2869 ierr = DMDAVecRestoreArray(user->fda, user->Ucat, &gucat_arr); CHKERRQ(ierr);
2870
2871 LOG_ALLOW(GLOBAL, LOG_INFO, "Completed Contravariant-to-Cartesian velocity transformation. \n");
2873 PetscFunctionReturn(0);
2874}
Here is the caller graph for this function:

◆ Cart2Contra()

PetscErrorCode Cart2Contra ( UserCtx user)

Convert a spatially varying Cartesian velocity field to contravariant fluxes.

Convert the ghosted Cartesian velocity field to contravariant face fluxes.

Definition at line 2881 of file setup.c.

2882{
2883 PetscErrorCode ierr;
2884 DMDALocalInfo info;
2885 const Cmpnts ***ucat_arr, ***csi_arr, ***eta_arr, ***zet_arr;
2886 Cmpnts ***ucont_arr;
2887
2888 PetscFunctionBeginUser;
2890
2891 ierr = DMDAGetLocalInfo(user->fda, &info); CHKERRQ(ierr);
2892 ierr = DMDAVecGetArrayRead(user->fda, user->lUcat, &ucat_arr); CHKERRQ(ierr);
2893 ierr = DMDAVecGetArrayRead(user->fda, user->lCsi, &csi_arr); CHKERRQ(ierr);
2894 ierr = DMDAVecGetArrayRead(user->fda, user->lEta, &eta_arr); CHKERRQ(ierr);
2895 ierr = DMDAVecGetArrayRead(user->fda, user->lZet, &zet_arr); CHKERRQ(ierr);
2896 ierr = DMDAVecGetArray(user->fda, user->Ucont, &ucont_arr); CHKERRQ(ierr);
2897
2898 const PetscInt i_start = PetscMax(info.xs, 1);
2899 const PetscInt j_start = PetscMax(info.ys, 1);
2900 const PetscInt k_start = PetscMax(info.zs, 1);
2901 const PetscInt i_end = PetscMin(info.xs + info.xm, info.mx - 1);
2902 const PetscInt j_end = PetscMin(info.ys + info.ym, info.my - 1);
2903 const PetscInt k_end = PetscMin(info.zs + info.zm, info.mz - 1);
2904
2905 for (PetscInt k = k_start; k < k_end; k++) {
2906 for (PetscInt j = j_start; j < j_end; j++) {
2907 for (PetscInt i = i_start; i < i_end; i++) {
2908 const Cmpnts u_xi = {
2909 0.5 * (ucat_arr[k][j][i].x + ucat_arr[k][j][i + 1].x),
2910 0.5 * (ucat_arr[k][j][i].y + ucat_arr[k][j][i + 1].y),
2911 0.5 * (ucat_arr[k][j][i].z + ucat_arr[k][j][i + 1].z)
2912 };
2913 const Cmpnts u_eta = {
2914 0.5 * (ucat_arr[k][j][i].x + ucat_arr[k][j + 1][i].x),
2915 0.5 * (ucat_arr[k][j][i].y + ucat_arr[k][j + 1][i].y),
2916 0.5 * (ucat_arr[k][j][i].z + ucat_arr[k][j + 1][i].z)
2917 };
2918 const Cmpnts u_zeta = {
2919 0.5 * (ucat_arr[k][j][i].x + ucat_arr[k + 1][j][i].x),
2920 0.5 * (ucat_arr[k][j][i].y + ucat_arr[k + 1][j][i].y),
2921 0.5 * (ucat_arr[k][j][i].z + ucat_arr[k + 1][j][i].z)
2922 };
2923 ucont_arr[k][j][i].x = csi_arr[k][j][i].x * u_xi.x + csi_arr[k][j][i].y * u_xi.y + csi_arr[k][j][i].z * u_xi.z;
2924 ucont_arr[k][j][i].y = eta_arr[k][j][i].x * u_eta.x + eta_arr[k][j][i].y * u_eta.y + eta_arr[k][j][i].z * u_eta.z;
2925 ucont_arr[k][j][i].z = zet_arr[k][j][i].x * u_zeta.x + zet_arr[k][j][i].y * u_zeta.y + zet_arr[k][j][i].z * u_zeta.z;
2926 }
2927 }
2928 }
2929
2930 ierr = DMDAVecRestoreArray(user->fda, user->Ucont, &ucont_arr); CHKERRQ(ierr);
2931 ierr = DMDAVecRestoreArrayRead(user->fda, user->lZet, &zet_arr); CHKERRQ(ierr);
2932 ierr = DMDAVecRestoreArrayRead(user->fda, user->lEta, &eta_arr); CHKERRQ(ierr);
2933 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCsi, &csi_arr); CHKERRQ(ierr);
2934 ierr = DMDAVecRestoreArrayRead(user->fda, user->lUcat, &ucat_arr); CHKERRQ(ierr);
2935
2937 PetscFunctionReturn(0);
2938}
Here is the caller graph for this function:

◆ UniformCart2Contra()

PetscErrorCode UniformCart2Contra ( UserCtx user,
PetscReal  u,
PetscReal  v,
PetscReal  w 
)

Convert a uniform Cartesian velocity (u,v,w) to contravariant fluxes in Ucont.

Populate contravariant fluxes from one uniform Cartesian velocity.

Computes the dot product of the physical velocity with each face-area vector: U^xi = csi · (u,v,w), U^eta = eta · (u,v,w), U^zeta = zet · (u,v,w). Writes to all owned nodes (xs..xe, ys..ye, zs..ze); boundary ghosts are overwritten later by ApplyBoundaryConditions.

Parameters
userUserCtx with fda, Ucont, lCsi, lEta, lZet populated.
uPhysical Cartesian x-velocity.
vPhysical Cartesian y-velocity.
wPhysical Cartesian z-velocity.

Definition at line 2953 of file setup.c.

2954{
2955 PetscErrorCode ierr;
2956 PetscFunctionBeginUser;
2958
2959 DMDALocalInfo info;
2960 Cmpnts ***ucont_arr;
2961 const Cmpnts ***csi_arr, ***eta_arr, ***zet_arr;
2962
2963 ierr = DMDAGetLocalInfo(user->fda, &info); CHKERRQ(ierr);
2964 ierr = DMDAVecGetArray(user->fda, user->Ucont, &ucont_arr); CHKERRQ(ierr);
2965 ierr = DMDAVecGetArrayRead(user->fda, user->lCsi, &csi_arr); CHKERRQ(ierr);
2966 ierr = DMDAVecGetArrayRead(user->fda, user->lEta, &eta_arr); CHKERRQ(ierr);
2967 ierr = DMDAVecGetArrayRead(user->fda, user->lZet, &zet_arr); CHKERRQ(ierr);
2968
2969 const PetscInt xs = info.xs, xe = info.xs + info.xm;
2970 const PetscInt ys = info.ys, ye = info.ys + info.ym;
2971 const PetscInt zs = info.zs, ze = info.zs + info.zm;
2972
2973 for (PetscInt k = zs; k < ze; k++) {
2974 for (PetscInt j = ys; j < ye; j++) {
2975 for (PetscInt i = xs; i < xe; i++) {
2976 ucont_arr[k][j][i].x = csi_arr[k][j][i].x * u + csi_arr[k][j][i].y * v + csi_arr[k][j][i].z * w;
2977 ucont_arr[k][j][i].y = eta_arr[k][j][i].x * u + eta_arr[k][j][i].y * v + eta_arr[k][j][i].z * w;
2978 ucont_arr[k][j][i].z = zet_arr[k][j][i].x * u + zet_arr[k][j][i].y * v + zet_arr[k][j][i].z * w;
2979 }
2980 }
2981 }
2982
2983 ierr = DMDAVecRestoreArrayRead(user->fda, user->lZet, &zet_arr); CHKERRQ(ierr);
2984 ierr = DMDAVecRestoreArrayRead(user->fda, user->lEta, &eta_arr); CHKERRQ(ierr);
2985 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCsi, &csi_arr); CHKERRQ(ierr);
2986 ierr = DMDAVecRestoreArray(user->fda, user->Ucont, &ucont_arr); CHKERRQ(ierr);
2987
2988 LOG_ALLOW(GLOBAL, LOG_DEBUG, "Cart2Contra: set Ucont from Cartesian (%.3f, %.3f, %.3f).\n",
2989 (double)u, (double)v, (double)w);
2991 PetscFunctionReturn(0);
2992}
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 3000 of file setup.c.

3001{
3002 PetscErrorCode ierr;
3003 DMDALocalInfo local_node_info;
3004 RankCellInfo my_cell_info;
3005 PetscMPIInt rank, size;
3006
3007 PetscFunctionBeginUser;
3009
3010 // --- 1. Input Validation and MPI Info ---
3011 if (!user) {
3012 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "UserCtx pointer is NULL in SetupDomainCellDecompositionMap.");
3013 }
3014 if (!user->da) {
3015 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "user->da is not initialized in SetupDomainCellDecompositionMap.");
3016 }
3017
3018 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
3019 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
3020
3021 LOG_ALLOW(GLOBAL, LOG_INFO, "Setting up domain cell decomposition map for %d ranks.\n", size);
3022
3023 // --- 2. Determine Local Cell Ownership ---
3024 // Get the local node ownership information from the primary DMDA.
3025 ierr = DMDAGetLocalInfo(user->da, &local_node_info); CHKERRQ(ierr);
3026
3027 // Use the robust helper function to convert node ownership to cell ownership.
3028 // A cell's index is defined by its origin node.
3029
3030 ierr = GetOwnedCellRange(&local_node_info, 0, &my_cell_info.xs_cell, &my_cell_info.xm_cell); CHKERRQ(ierr);
3031 ierr = GetOwnedCellRange(&local_node_info, 1, &my_cell_info.ys_cell, &my_cell_info.ym_cell); CHKERRQ(ierr);
3032 ierr = GetOwnedCellRange(&local_node_info, 2, &my_cell_info.zs_cell, &my_cell_info.zm_cell); CHKERRQ(ierr);
3033
3034 // Log the calculated local ownership for debugging purposes.
3035 LOG_ALLOW(LOCAL, LOG_DEBUG, "[Rank %d] Owns cells: i[%d, %d), j[%d, %d), k[%d, %d)\n",
3036 rank, my_cell_info.xs_cell, my_cell_info.xs_cell + my_cell_info.xm_cell,
3037 my_cell_info.ys_cell, my_cell_info.ys_cell + my_cell_info.ym_cell,
3038 my_cell_info.zs_cell, my_cell_info.zs_cell + my_cell_info.zm_cell);
3039
3040 // --- 3. Allocate and Distribute the Global Map ---
3041 // Allocate memory for the global map that will hold information from all ranks.
3042 ierr = PetscMalloc1(size, &user->RankCellInfoMap); CHKERRQ(ierr);
3043
3044 // Perform the collective communication to gather the `RankCellInfo` struct from every rank.
3045 // Each rank sends its `my_cell_info` and receives the complete array in `user->RankCellInfoMap`.
3046 // We use MPI_BYTE to ensure portability across different systems and struct padding.
3047 ierr = MPI_Allgather(&my_cell_info, sizeof(RankCellInfo), MPI_BYTE,
3048 user->RankCellInfoMap, sizeof(RankCellInfo), MPI_BYTE,
3049 PETSC_COMM_WORLD); CHKERRQ(ierr);
3050
3051 LOG_ALLOW(GLOBAL, LOG_INFO, "Domain cell decomposition map created and distributed successfully.\n");
3052
3054 PetscFunctionReturn(0);
3055}
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:2382
PetscInt ys_cell
Definition variables.h:202
PetscInt xs_cell
Definition variables.h:202
PetscInt zm_cell
Definition variables.h:203
PetscInt zs_cell
Definition variables.h:202
PetscInt xm_cell
Definition variables.h:203
RankCellInfo * RankCellInfoMap
Definition variables.h:951
PetscInt ym_cell
Definition variables.h:203
A lean struct to hold the global cell ownership range for a single MPI rank.
Definition variables.h:201
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 3065 of file setup.c.

3066{
3067 PetscInt low = 0, high = n - 1;
3068
3069 PetscFunctionBeginUser;
3071
3072 // --- 1. Input Validation ---
3073 if (!found) {
3074 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Output pointer 'found' is NULL in PetscBinarySearchInt64.");
3075 }
3076 if (n > 0 && !arr) {
3077 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Input array 'arr' is NULL for n > 0.");
3078 }
3079
3080 // Initialize output
3081 *found = PETSC_FALSE;
3082
3083 // --- 2. Binary Search Algorithm ---
3084 while (low <= high) {
3085 // Use this form to prevent potential integer overflow on very large arrays
3086 PetscInt mid = low + (high - low) / 2;
3087
3088 if (arr[mid] == key) {
3089 *found = PETSC_TRUE; // Key found!
3090 break; // Exit the loop
3091 }
3092
3093 if (arr[mid] < key) {
3094 low = mid + 1; // Search in the right half
3095 } else {
3096 high = mid - 1; // Search in the left half
3097 }
3098 }
3099
3101 PetscFunctionReturn(0);
3102}
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 3109 of file setup.c.

3110{
3111 PetscInt nidx;
3112 DMDALocalInfo info = user->info;
3113
3114 PetscInt mx = info.mx, my = info.my;
3115
3116 AO ao;
3117 DMDAGetAO(user->da, &ao);
3118 nidx=i+j*mx+k*mx*my;
3119
3120 AOApplicationToPetsc(ao,1,&nidx);
3121
3122 return (nidx);
3123}
DMDALocalInfo info
Definition variables.h:883
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 3135 of file setup.c.

3136{
3137 DM da = user->da, fda = user->fda;
3138 DMDALocalInfo info = user->info;
3139
3140 PetscInt ti = user->simCtx->step;
3141
3142 PetscInt xs = info.xs, xe = info.xs + info.xm;
3143 PetscInt ys = info.ys, ye = info.ys + info.ym;
3144 PetscInt zs = info.zs, ze = info.zs + info.zm;
3145 PetscInt mx = info.mx, my = info.my, mz = info.mz;
3146
3147 PetscInt lxs, lys, lzs, lxe, lye, lze;
3148 PetscInt i, j, k;
3149
3150 Vec Div;
3151 PetscReal ***div, ***aj, ***nvert,***p;
3152 Cmpnts ***ucont;
3153 PetscReal maxdiv;
3154
3155 lxs = xs; lxe = xe;
3156 lys = ys; lye = ye;
3157 lzs = zs; lze = ze;
3158
3159 if (xs==0) lxs = xs+1;
3160 if (ys==0) lys = ys+1;
3161 if (zs==0) lzs = zs+1;
3162
3163 if (xe==mx) lxe = xe-1;
3164 if (ye==my) lye = ye-1;
3165 if (ze==mz) lze = ze-1;
3166
3167 PetscFunctionBeginUser;
3169
3170 DMDAVecGetArray(fda,user->lUcont, &ucont);
3171 DMDAVecGetArray(da, user->lAj, &aj);
3172 VecDuplicate(user->P, &Div);
3173 DMDAVecGetArray(da, Div, &div);
3174 DMDAVecGetArray(da, user->lNvert, &nvert);
3175 DMDAVecGetArray(da, user->P, &p);
3176 for (k=lzs; k<lze; k++) {
3177 for (j=lys; j<lye; j++){
3178 for (i=lxs; i<lxe; i++) {
3179 if (k==10 && j==10 && i==1){
3180 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]);
3181 }
3182
3183 if (k==10 && j==10 && i==mx-3)
3184 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]);
3185 }
3186 }
3187 }
3188 DMDAVecRestoreArray(da, user->P, &p);
3189
3190
3191 for (k=lzs; k<lze; k++) {
3192 for (j=lys; j<lye; j++) {
3193 for (i=lxs; i<lxe; i++) {
3194 maxdiv = fabs((ucont[k][j][i].x - ucont[k][j][i-1].x +
3195 ucont[k][j][i].y - ucont[k][j-1][i].y +
3196 ucont[k][j][i].z - ucont[k-1][j][i].z)*aj[k][j][i]);
3197 if (nvert[k][j][i] + nvert[k+1][j][i] + nvert[k-1][j][i] +
3198 nvert[k][j+1][i] + nvert[k][j-1][i] +
3199 nvert[k][j][i+1] + nvert[k][j][i-1] > 0.1) maxdiv = 0.;
3200 div[k][j][i] = maxdiv;
3201
3202 }
3203 }
3204 }
3205
3206 if (zs==0) {
3207 k=0;
3208 for (j=ys; j<ye; j++) {
3209 for (i=xs; i<xe; i++) {
3210 div[k][j][i] = 0.;
3211 }
3212 }
3213 }
3214
3215 if (ze == mz) {
3216 k=mz-1;
3217 for (j=ys; j<ye; j++) {
3218 for (i=xs; i<xe; i++) {
3219 div[k][j][i] = 0.;
3220 }
3221 }
3222 }
3223
3224 if (xs==0) {
3225 i=0;
3226 for (k=zs; k<ze; k++) {
3227 for (j=ys; j<ye; j++) {
3228 div[k][j][i] = 0.;
3229 }
3230 }
3231 }
3232
3233 if (xe==mx) {
3234 i=mx-1;
3235 for (k=zs; k<ze; k++) {
3236 for (j=ys; j<ye; j++) {
3237 div[k][j][i] = 0;
3238 }
3239 }
3240 }
3241
3242 if (ys==0) {
3243 j=0;
3244 for (k=zs; k<ze; k++) {
3245 for (i=xs; i<xe; i++) {
3246 div[k][j][i] = 0.;
3247 }
3248 }
3249 }
3250
3251 if (ye==my) {
3252 j=my-1;
3253 for (k=zs; k<ze; k++) {
3254 for (i=xs; i<xe; i++) {
3255 div[k][j][i] = 0.;
3256 }
3257 }
3258 }
3259 DMDAVecRestoreArray(da, Div, &div);
3260 PetscInt MaxFlatIndex;
3261
3262 VecMax(Div, &MaxFlatIndex, &maxdiv);
3263
3264 LOG_ALLOW(GLOBAL,LOG_INFO,"[Step %d]] The Maximum Divergence is %e at flat index %d.\n",ti,maxdiv,MaxFlatIndex);
3265
3266 user->simCtx->MaxDivFlatArg = MaxFlatIndex;
3267 user->simCtx->MaxDiv = maxdiv;
3268
3269 for (k=zs; k<ze; k++) {
3270 for (j=ys; j<ye; j++) {
3271 for (i=xs; i<xe; i++) {
3272 if (Gidx(i,j,k,user) == MaxFlatIndex) {
3273 LOG_ALLOW(GLOBAL,LOG_INFO,"[Step %d] The Maximum Divergence(%e) is at location [%d][%d][%d]. \n", ti, maxdiv,k,j,i);
3274 user->simCtx->MaxDivz = k;
3275 user->simCtx->MaxDivy = j;
3276 user->simCtx->MaxDivx = i;
3277 }
3278 }
3279 }
3280 }
3281
3282
3283 DMDAVecRestoreArray(da, user->lNvert, &nvert);
3284 DMDAVecRestoreArray(fda, user->lUcont, &ucont);
3285 DMDAVecRestoreArray(da, user->lAj, &aj);
3286 VecDestroy(&Div);
3287
3289 PetscFunctionReturn(0);
3290}
static PetscInt Gidx(PetscInt i, PetscInt j, PetscInt k, UserCtx *user)
Internal helper implementation: Gidx().
Definition setup.c:3109
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 3301 of file setup.c.

3301 {
3302 PetscErrorCode ierr; // Error code for PETSc functions
3303 PetscMPIInt rank;
3304 PetscFunctionBeginUser;
3306 MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
3307
3308 // Initialize RNG for x-coordinate
3309 ierr = PetscRandomCreate(PETSC_COMM_SELF, randx); CHKERRQ(ierr);
3310 ierr = PetscRandomSetType((*randx), PETSCRAND48); CHKERRQ(ierr);
3311 ierr = PetscRandomSetInterval(*randx, user->bbox.min_coords.x, user->bbox.max_coords.x); CHKERRQ(ierr);
3312 ierr = PetscRandomSetSeed(*randx, rank + 12345); CHKERRQ(ierr); // Unique seed per rank
3313 ierr = PetscRandomSeed(*randx); CHKERRQ(ierr);
3314 LOG_ALLOW_SYNC(LOCAL,LOG_VERBOSE, "[Rank %d]Initialized RNG for X-axis.\n",rank);
3315
3316 // Initialize RNG for y-coordinate
3317 ierr = PetscRandomCreate(PETSC_COMM_SELF, randy); CHKERRQ(ierr);
3318 ierr = PetscRandomSetType((*randy), PETSCRAND48); CHKERRQ(ierr);
3319 ierr = PetscRandomSetInterval(*randy, user->bbox.min_coords.y, user->bbox.max_coords.y); CHKERRQ(ierr);
3320 ierr = PetscRandomSetSeed(*randy, rank + 67890); CHKERRQ(ierr); // Unique seed per rank
3321 ierr = PetscRandomSeed(*randy); CHKERRQ(ierr);
3322 LOG_ALLOW_SYNC(LOCAL,LOG_VERBOSE, "[Rank %d]Initialized RNG for Y-axis.\n",rank);
3323
3324 // Initialize RNG for z-coordinate
3325 ierr = PetscRandomCreate(PETSC_COMM_SELF, randz); CHKERRQ(ierr);
3326 ierr = PetscRandomSetType((*randz), PETSCRAND48); CHKERRQ(ierr);
3327 ierr = PetscRandomSetInterval(*randz, user->bbox.min_coords.z, user->bbox.max_coords.z); CHKERRQ(ierr);
3328 ierr = PetscRandomSetSeed(*randz, rank + 54321); CHKERRQ(ierr); // Unique seed per rank
3329 ierr = PetscRandomSeed(*randz); CHKERRQ(ierr);
3330 LOG_ALLOW_SYNC(LOCAL,LOG_VERBOSE, "[Rank %d]Initialized RNG for Z-axis.\n",rank);
3331
3333 PetscFunctionReturn(0);
3334}
@ 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:171
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
Definition variables.h:170
BoundingBox bbox
Definition variables.h:887
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 3342 of file setup.c.

3342 {
3343 PetscErrorCode ierr;
3344 PetscMPIInt rank;
3345 PetscFunctionBeginUser;
3346
3348
3349 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
3350
3351 // --- RNG for i-logical dimension ---
3352 ierr = PetscRandomCreate(PETSC_COMM_SELF, rand_logic_i); CHKERRQ(ierr);
3353 ierr = PetscRandomSetType((*rand_logic_i), PETSCRAND48); CHKERRQ(ierr);
3354 ierr = PetscRandomSetInterval(*rand_logic_i, 0.0, 1.0); CHKERRQ(ierr); // Key change: [0,1)
3355 ierr = PetscRandomSetSeed(*rand_logic_i, rank + 202401); CHKERRQ(ierr); // Unique seed
3356 ierr = PetscRandomSeed(*rand_logic_i); CHKERRQ(ierr);
3357 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d] Initialized RNG for i-logical dimension [0,1).\n",rank);
3358
3359 // --- RNG for j-logical dimension ---
3360 ierr = PetscRandomCreate(PETSC_COMM_SELF, rand_logic_j); CHKERRQ(ierr);
3361 ierr = PetscRandomSetType((*rand_logic_j), PETSCRAND48); CHKERRQ(ierr);
3362 ierr = PetscRandomSetInterval(*rand_logic_j, 0.0, 1.0); CHKERRQ(ierr); // Key change: [0,1)
3363 ierr = PetscRandomSetSeed(*rand_logic_j, rank + 202402); CHKERRQ(ierr);
3364 ierr = PetscRandomSeed(*rand_logic_j); CHKERRQ(ierr);
3365 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d] Initialized RNG for j-logical dimension [0,1).\n",rank);
3366
3367 // --- RNG for k-logical dimension ---
3368 ierr = PetscRandomCreate(PETSC_COMM_SELF, rand_logic_k); CHKERRQ(ierr);
3369 ierr = PetscRandomSetType((*rand_logic_k), PETSCRAND48); CHKERRQ(ierr);
3370 ierr = PetscRandomSetInterval(*rand_logic_k, 0.0, 1.0); CHKERRQ(ierr); // Key change: [0,1)
3371 ierr = PetscRandomSetSeed(*rand_logic_k, rank + 202403); CHKERRQ(ierr);
3372 ierr = PetscRandomSeed(*rand_logic_k); CHKERRQ(ierr);
3373 LOG_ALLOW(LOCAL,LOG_VERBOSE, "[Rank %d] Initialized RNG for k-logical dimension [0,1).\n",rank);
3374
3375
3377 PetscFunctionReturn(0);
3378}
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 3386 of file setup.c.

3386 {
3387 PetscErrorCode ierr;
3388 PetscMPIInt rank;
3389
3390 PetscFunctionBeginUser;
3392
3393 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
3394
3395 // 1. Create the generator (stored in SimCtx, not UserCtx, as it is global physics)
3396 ierr = PetscRandomCreate(PETSC_COMM_WORLD, &simCtx->BrownianMotionRNG); CHKERRQ(ierr);
3397 ierr = PetscRandomSetType(simCtx->BrownianMotionRNG, PETSCRAND48); CHKERRQ(ierr);
3398
3399 // 2. CRITICAL: Set interval to [0, 1).
3400 // This is required for the Gaussian math to work.
3401 ierr = PetscRandomSetInterval(simCtx->BrownianMotionRNG, 0.0, 1.0); CHKERRQ(ierr);
3402
3403 // 3. Seed based on Rank to ensure spatial randomness
3404 // Multiplying by a large prime helps separate the streams significantly
3405 unsigned long seed = (unsigned long)rank * 987654321 + (unsigned long)time(NULL);
3406 ierr = PetscRandomSetSeed(simCtx->BrownianMotionRNG, seed); CHKERRQ(ierr);
3407 ierr = PetscRandomSeed(simCtx->BrownianMotionRNG); CHKERRQ(ierr);
3408
3409 LOG_ALLOW(LOCAL, LOG_VERBOSE, "[Rank %d] Initialized Brownian Physics RNG.\n", rank);
3410
3412 PetscFunctionReturn(0);
3413}
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 3425 of file setup.c.

3433{
3434 // Gradient X component
3435 gradPhi->x = jacobian * (dPhi_dcsi * csi_metrics.x + dPhi_deta * eta_metrics.x + dPhi_dzet * zet_metrics.x);
3436
3437 // Gradient Y component
3438 gradPhi->y = jacobian * (dPhi_dcsi * csi_metrics.y + dPhi_deta * eta_metrics.y + dPhi_dzet * zet_metrics.y);
3439
3440 // Gradient Z component
3441 gradPhi->z = jacobian * (dPhi_dcsi * csi_metrics.z + dPhi_deta * eta_metrics.z + dPhi_dzet * zet_metrics.z);
3442}
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 3450 of file setup.c.

3453{
3454 // Derivatives of the first component (u)
3455 dudx->x = jacobian * (deriv_csi.x * csi_metrics.x + deriv_eta.x * eta_metrics.x + deriv_zet.x * zet_metrics.x);
3456 dudx->y = jacobian * (deriv_csi.x * csi_metrics.y + deriv_eta.x * eta_metrics.y + deriv_zet.x * zet_metrics.y);
3457 dudx->z = jacobian * (deriv_csi.x * csi_metrics.z + deriv_eta.x * eta_metrics.z + deriv_zet.x * zet_metrics.z);
3458 // Derivatives of the second component (v)
3459 dvdx->x = jacobian * (deriv_csi.y * csi_metrics.x + deriv_eta.y * eta_metrics.x + deriv_zet.y * zet_metrics.x);
3460 dvdx->y = jacobian * (deriv_csi.y * csi_metrics.y + deriv_eta.y * eta_metrics.y + deriv_zet.y * zet_metrics.y);
3461 dvdx->z = jacobian * (deriv_csi.y * csi_metrics.z + deriv_eta.y * eta_metrics.z + deriv_zet.y * zet_metrics.z);
3462 // Derivatives of the third component (w)
3463 dwdx->x = jacobian * (deriv_csi.z * csi_metrics.x + deriv_eta.z * eta_metrics.x + deriv_zet.z * zet_metrics.x);
3464 dwdx->y = jacobian * (deriv_csi.z * csi_metrics.y + deriv_eta.z * eta_metrics.y + deriv_zet.z * zet_metrics.y);
3465 dwdx->z = jacobian * (deriv_csi.z * csi_metrics.z + deriv_eta.z * eta_metrics.z + deriv_zet.z * zet_metrics.z);
3466}
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 3474 of file setup.c.

3476{
3477 PetscErrorCode ierr;
3478 Cmpnts ***csi, ***eta, ***zet;
3479 PetscReal ***jac;
3480 PetscReal d_csi, d_eta, d_zet;
3481
3482 PetscFunctionBeginUser;
3483
3484 // 1. Get read-only access to metrics
3485 ierr = DMDAVecGetArrayRead(user->fda, user->lCsi, &csi); CHKERRQ(ierr);
3486 ierr = DMDAVecGetArrayRead(user->fda, user->lEta, &eta); CHKERRQ(ierr);
3487 ierr = DMDAVecGetArrayRead(user->fda, user->lZet, &zet); CHKERRQ(ierr);
3488 ierr = DMDAVecGetArrayRead(user->da, user->lAj, &jac); CHKERRQ(ierr);
3489
3490 // 2. Compute derivatives in computational space (Central Difference)
3491 // Assumes ghosts are available at i+/-1
3492 d_csi = 0.5 * (field_data[k][j][i+1] - field_data[k][j][i-1]);
3493 d_eta = 0.5 * (field_data[k][j+1][i] - field_data[k][j-1][i]);
3494 d_zet = 0.5 * (field_data[k+1][j][i] - field_data[k-1][j][i]);
3495
3496 // 3. Transform to physical space
3498 csi[k][j][i], eta[k][j][i], zet[k][j][i],
3499 d_csi, d_eta, d_zet,
3500 grad);
3501
3502 // 4. Restore arrays
3503 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCsi, &csi); CHKERRQ(ierr);
3504 ierr = DMDAVecRestoreArrayRead(user->fda, user->lEta, &eta); CHKERRQ(ierr);
3505 ierr = DMDAVecRestoreArrayRead(user->fda, user->lZet, &zet); CHKERRQ(ierr);
3506 ierr = DMDAVecRestoreArrayRead(user->da, user->lAj, &jac); CHKERRQ(ierr);
3507
3508 PetscFunctionReturn(0);
3509}
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:3425
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 3517 of file setup.c.

3519{
3520 PetscErrorCode ierr;
3521 Cmpnts ***csi, ***eta, ***zet;
3522 PetscReal ***jac;
3523 PetscFunctionBeginUser;
3524
3525 // 1. Get read-only access to the necessary metric data arrays
3526 ierr = DMDAVecGetArrayRead(user->fda, user->lCsi, &csi); CHKERRQ(ierr);
3527 ierr = DMDAVecGetArrayRead(user->fda, user->lEta, &eta); CHKERRQ(ierr);
3528 ierr = DMDAVecGetArrayRead(user->fda, user->lZet, &zet); CHKERRQ(ierr);
3529 ierr = DMDAVecGetArrayRead(user->da, user->lAj, &jac); CHKERRQ(ierr);
3530
3531 // 2. Calculate derivatives in computational space using central differencing
3532 Cmpnts deriv_csi, deriv_eta, deriv_zet;
3533 deriv_csi.x = (field_data[k][j][i+1].x - field_data[k][j][i-1].x) * 0.5;
3534 deriv_csi.y = (field_data[k][j][i+1].y - field_data[k][j][i-1].y) * 0.5;
3535 deriv_csi.z = (field_data[k][j][i+1].z - field_data[k][j][i-1].z) * 0.5;
3536
3537 deriv_eta.x = (field_data[k][j+1][i].x - field_data[k][j-1][i].x) * 0.5;
3538 deriv_eta.y = (field_data[k][j+1][i].y - field_data[k][j-1][i].y) * 0.5;
3539 deriv_eta.z = (field_data[k][j+1][i].z - field_data[k][j-1][i].z) * 0.5;
3540
3541 deriv_zet.x = (field_data[k+1][j][i].x - field_data[k-1][j][i].x) * 0.5;
3542 deriv_zet.y = (field_data[k+1][j][i].y - field_data[k-1][j][i].y) * 0.5;
3543 deriv_zet.z = (field_data[k+1][j][i].z - field_data[k-1][j][i].z) * 0.5;
3544
3545 // 3. Transform derivatives to physical space
3546 TransformDerivativesToPhysical(jac[k][j][i], csi[k][j][i], eta[k][j][i], zet[k][j][i],
3547 deriv_csi, deriv_eta, deriv_zet,
3548 dudx, dvdx, dwdx);
3549
3550 // 4. Restore access to the PETSc data arrays
3551 ierr = DMDAVecRestoreArrayRead(user->fda, user->lCsi, &csi); CHKERRQ(ierr);
3552 ierr = DMDAVecRestoreArrayRead(user->fda, user->lEta, &eta); CHKERRQ(ierr);
3553 ierr = DMDAVecRestoreArrayRead(user->fda, user->lZet, &zet); CHKERRQ(ierr);
3554 ierr = DMDAVecRestoreArrayRead(user->da, user->lAj, &jac); CHKERRQ(ierr);
3555
3556 PetscFunctionReturn(0);
3557}
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:3450
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 3571 of file setup.c.

3572{
3573 PetscErrorCode ierr;
3574 PetscFunctionBeginUser;
3575
3576 // --- Group A: Primary Flow Fields (Always allocated at all levels) ---
3577 if (user->Ucont) { ierr = VecDestroy(&user->Ucont); CHKERRQ(ierr); }
3578 if (user->lUcont) { ierr = VecDestroy(&user->lUcont); CHKERRQ(ierr); }
3579 if (user->Ucat) { ierr = VecDestroy(&user->Ucat); CHKERRQ(ierr); }
3580 if (user->lUcat) { ierr = VecDestroy(&user->lUcat); CHKERRQ(ierr); }
3581 if (user->P) { ierr = VecDestroy(&user->P); CHKERRQ(ierr); }
3582 if (user->lP) { ierr = VecDestroy(&user->lP); CHKERRQ(ierr); }
3583 if (user->Nvert) { ierr = VecDestroy(&user->Nvert); CHKERRQ(ierr); }
3584 if (user->lNvert) { ierr = VecDestroy(&user->lNvert); CHKERRQ(ierr); }
3585
3586 // --- Group A2: Derived Flow Fields (Conditional) ---
3587 if(user->Diffusivity) {ierr = VecDestroy(&user->Diffusivity); CHKERRQ(ierr);}
3588 if(user->lDiffusivity){ierr = VecDestroy(&user->lDiffusivity); CHKERRQ(ierr);}
3589 if(user->DiffusivityGradient){ierr = VecDestroy(&user->DiffusivityGradient); CHKERRQ(ierr);}
3590 if(user->lDiffusivityGradient){ierr = VecDestroy(&user->lDiffusivityGradient); CHKERRQ(ierr);}
3591
3592 // --- Group B: Solver Work Vectors (All levels) ---
3593 if (user->Phi) { ierr = VecDestroy(&user->Phi); CHKERRQ(ierr); }
3594 if (user->lPhi) { ierr = VecDestroy(&user->lPhi); CHKERRQ(ierr); }
3595
3596 // --- Group C: Time-Stepping Vectors (Finest level only) ---
3597 if (user->Ucont_o) { ierr = VecDestroy(&user->Ucont_o); CHKERRQ(ierr); }
3598 if (user->Ucont_rm1) { ierr = VecDestroy(&user->Ucont_rm1); CHKERRQ(ierr); }
3599 if (user->Ucat_o) { ierr = VecDestroy(&user->Ucat_o); CHKERRQ(ierr); }
3600 if (user->P_o) { ierr = VecDestroy(&user->P_o); CHKERRQ(ierr); }
3601 if (user->Nvert_o) { ierr = VecDestroy(&user->Nvert_o); CHKERRQ(ierr); }
3602 if (user->lUcont_o) { ierr = VecDestroy(&user->lUcont_o); CHKERRQ(ierr); }
3603 if (user->lUcont_rm1) { ierr = VecDestroy(&user->lUcont_rm1); CHKERRQ(ierr); }
3604 if (user->lNvert_o) { ierr = VecDestroy(&user->lNvert_o); CHKERRQ(ierr); }
3605
3606 // --- Group D: Grid Metrics - Face Centered (All levels) ---
3607 if (user->Csi) { ierr = VecDestroy(&user->Csi); CHKERRQ(ierr); }
3608 if (user->Eta) { ierr = VecDestroy(&user->Eta); CHKERRQ(ierr); }
3609 if (user->Zet) { ierr = VecDestroy(&user->Zet); CHKERRQ(ierr); }
3610 if (user->Aj) { ierr = VecDestroy(&user->Aj); CHKERRQ(ierr); }
3611 if (user->lCsi) { ierr = VecDestroy(&user->lCsi); CHKERRQ(ierr); }
3612 if (user->lEta) { ierr = VecDestroy(&user->lEta); CHKERRQ(ierr); }
3613 if (user->lZet) { ierr = VecDestroy(&user->lZet); CHKERRQ(ierr); }
3614 if (user->lAj) { ierr = VecDestroy(&user->lAj); CHKERRQ(ierr); }
3615
3616 // --- Group E: Grid Metrics - Face Centered (All levels) ---
3617 if (user->ICsi) { ierr = VecDestroy(&user->ICsi); CHKERRQ(ierr); }
3618 if (user->IEta) { ierr = VecDestroy(&user->IEta); CHKERRQ(ierr); }
3619 if (user->IZet) { ierr = VecDestroy(&user->IZet); CHKERRQ(ierr); }
3620 if (user->JCsi) { ierr = VecDestroy(&user->JCsi); CHKERRQ(ierr); }
3621 if (user->JEta) { ierr = VecDestroy(&user->JEta); CHKERRQ(ierr); }
3622 if (user->JZet) { ierr = VecDestroy(&user->JZet); CHKERRQ(ierr); }
3623 if (user->KCsi) { ierr = VecDestroy(&user->KCsi); CHKERRQ(ierr); }
3624 if (user->KEta) { ierr = VecDestroy(&user->KEta); CHKERRQ(ierr); }
3625 if (user->KZet) { ierr = VecDestroy(&user->KZet); CHKERRQ(ierr); }
3626 if (user->IAj) { ierr = VecDestroy(&user->IAj); CHKERRQ(ierr); }
3627 if (user->JAj) { ierr = VecDestroy(&user->JAj); CHKERRQ(ierr); }
3628 if (user->KAj) { ierr = VecDestroy(&user->KAj); CHKERRQ(ierr); }
3629 if (user->lICsi) { ierr = VecDestroy(&user->lICsi); CHKERRQ(ierr); }
3630 if (user->lIEta) { ierr = VecDestroy(&user->lIEta); CHKERRQ(ierr); }
3631 if (user->lIZet) { ierr = VecDestroy(&user->lIZet); CHKERRQ(ierr); }
3632 if (user->lJCsi) { ierr = VecDestroy(&user->lJCsi); CHKERRQ(ierr); }
3633 if (user->lJEta) { ierr = VecDestroy(&user->lJEta); CHKERRQ(ierr); }
3634 if (user->lJZet) { ierr = VecDestroy(&user->lJZet); CHKERRQ(ierr); }
3635 if (user->lKCsi) { ierr = VecDestroy(&user->lKCsi); CHKERRQ(ierr); }
3636 if (user->lKEta) { ierr = VecDestroy(&user->lKEta); CHKERRQ(ierr); }
3637 if (user->lKZet) { ierr = VecDestroy(&user->lKZet); CHKERRQ(ierr); }
3638 if (user->lIAj) { ierr = VecDestroy(&user->lIAj); CHKERRQ(ierr); }
3639 if (user->lJAj) { ierr = VecDestroy(&user->lJAj); CHKERRQ(ierr); }
3640 if (user->lKAj) { ierr = VecDestroy(&user->lKAj); CHKERRQ(ierr); }
3641
3642 // --- Group F: Cell/Face Coordinates and Grid Spacing (All levels) ---
3643 if (user->Cent) { ierr = VecDestroy(&user->Cent); CHKERRQ(ierr); }
3644 if (user->lCent) { ierr = VecDestroy(&user->lCent); CHKERRQ(ierr); }
3645 if (user->GridSpace) { ierr = VecDestroy(&user->GridSpace); CHKERRQ(ierr); }
3646 if (user->lGridSpace) { ierr = VecDestroy(&user->lGridSpace); CHKERRQ(ierr); }
3647 if (user->Centx) { ierr = VecDestroy(&user->Centx); CHKERRQ(ierr); }
3648 if (user->Centy) { ierr = VecDestroy(&user->Centy); CHKERRQ(ierr); }
3649 if (user->Centz) { ierr = VecDestroy(&user->Centz); CHKERRQ(ierr); }
3650 if (user->lCentx) { ierr = VecDestroy(&user->lCentx); CHKERRQ(ierr); }
3651 if (user->lCenty) { ierr = VecDestroy(&user->lCenty); CHKERRQ(ierr); }
3652 if (user->lCentz) { ierr = VecDestroy(&user->lCentz); CHKERRQ(ierr); }
3653
3654 // --- Group G: Turbulence Model Vectors (Finest level, conditional on les/rans) ---
3655 if (user->Nu_t) { ierr = VecDestroy(&user->Nu_t); CHKERRQ(ierr); }
3656 if (user->lNu_t) { ierr = VecDestroy(&user->lNu_t); CHKERRQ(ierr); }
3657 if (user->CS) { ierr = VecDestroy(&user->CS); CHKERRQ(ierr); }
3658 if (user->lCs) { ierr = VecDestroy(&user->lCs); CHKERRQ(ierr); }
3659 if (user->lFriction_Velocity) { ierr = VecDestroy(&user->lFriction_Velocity); CHKERRQ(ierr); }
3660 if (user->K_Omega) { ierr = VecDestroy(&user->K_Omega); CHKERRQ(ierr); }
3661 if (user->lK_Omega) { ierr = VecDestroy(&user->lK_Omega); CHKERRQ(ierr); }
3662 if (user->K_Omega_o) { ierr = VecDestroy(&user->K_Omega_o); CHKERRQ(ierr); }
3663 if (user->lK_Omega_o) { ierr = VecDestroy(&user->lK_Omega_o); CHKERRQ(ierr); }
3664
3665 // --- Group H: Particle Vectors (Finest level, conditional on np > 0) ---
3666 if (user->ParticleCount) { ierr = VecDestroy(&user->ParticleCount); CHKERRQ(ierr); }
3667 if (user->lParticleCount) { ierr = VecDestroy(&user->lParticleCount); CHKERRQ(ierr); }
3668 if (user->Psi) { ierr = VecDestroy(&user->Psi); CHKERRQ(ierr); }
3669 if (user->lPsi) { ierr = VecDestroy(&user->lPsi); CHKERRQ(ierr); }
3670
3671 // --- Group I: Boundary Condition Vectors (All levels) ---
3672 if (user->Bcs.Ubcs) { ierr = VecDestroy(&user->Bcs.Ubcs); CHKERRQ(ierr); }
3673 if (user->Bcs.Uch) { ierr = VecDestroy(&user->Bcs.Uch); CHKERRQ(ierr); }
3674
3675 // --- Group J: Post-Processing Vectors (Finest level, postprocessor mode) ---
3676 if (user->P_nodal) { ierr = VecDestroy(&user->P_nodal); CHKERRQ(ierr); }
3677 if (user->Ucat_nodal) { ierr = VecDestroy(&user->Ucat_nodal); CHKERRQ(ierr); }
3678 if (user->Qcrit) { ierr = VecDestroy(&user->Qcrit); CHKERRQ(ierr); }
3679 if (user->Psi_nodal) { ierr = VecDestroy(&user->Psi_nodal); CHKERRQ(ierr); }
3680
3681 // --- Group K: Interpolation Vectors (Lazy allocation) ---
3682 if (user->CellFieldAtCorner) { ierr = VecDestroy(&user->CellFieldAtCorner); CHKERRQ(ierr); }
3683 if (user->lCellFieldAtCorner) { ierr = VecDestroy(&user->lCellFieldAtCorner); CHKERRQ(ierr); }
3684
3685 // --- Group L: Statistical Averaging Vectors (If allocated) ---
3686 if (user->Ucat_sum) { ierr = VecDestroy(&user->Ucat_sum); CHKERRQ(ierr); }
3687 if (user->Ucat_cross_sum) { ierr = VecDestroy(&user->Ucat_cross_sum); CHKERRQ(ierr); }
3688 if (user->Ucat_square_sum) { ierr = VecDestroy(&user->Ucat_square_sum); CHKERRQ(ierr); }
3689 if (user->P_sum) { ierr = VecDestroy(&user->P_sum); CHKERRQ(ierr); }
3690
3691 // --- Group M: Implicit Solver Temporary Vectors (Destroyed after use, but check anyway) ---
3692 if (user->Rhs) { ierr = VecDestroy(&user->Rhs); CHKERRQ(ierr); }
3693 if (user->dUcont) { ierr = VecDestroy(&user->dUcont); CHKERRQ(ierr); }
3694 if (user->pUcont) { ierr = VecDestroy(&user->pUcont); CHKERRQ(ierr); }
3695
3696 // --- Group N: Poisson Solver Vectors (Destroyed after solve, but check anyway) ---
3697 if (user->B) { ierr = VecDestroy(&user->B); CHKERRQ(ierr); }
3698 if (user->R) { ierr = VecDestroy(&user->R); CHKERRQ(ierr); }
3699
3700 LOG_ALLOW(LOCAL, LOG_DEBUG, "All vectors destroyed for UserCtx.\n");
3701 PetscFunctionReturn(0);
3702}
Vec Rhs
Definition variables.h:912
Vec lCellFieldAtCorner
Definition variables.h:915
Vec Ucat_square_sum
Definition variables.h:938
Vec P_sum
Definition variables.h:938
Vec pUcont
Definition variables.h:912
Vec CellFieldAtCorner
Definition variables.h:915
Vec Ucat_sum
Definition variables.h:938
Vec dUcont
Definition variables.h:912
Vec Ucat_cross_sum
Definition variables.h:938
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 3709 of file setup.c.

3710{
3711 PetscErrorCode ierr;
3712 PetscFunctionBeginUser;
3713
3714 if (!user) {
3715 LOG_ALLOW(LOCAL, LOG_WARNING, "DestroyUserContext called with NULL user pointer.\n");
3716 PetscFunctionReturn(0);
3717 }
3718
3719 LOG_ALLOW(LOCAL, LOG_INFO, "Destroying UserCtx at level %d...\n", user->thislevel);
3720
3721 // --- Step 1: Destroy Boundary Condition System ---
3722 // This handles all BC handlers and their private data.
3723 ierr = BoundarySystem_Destroy(user); CHKERRQ(ierr);
3724 LOG_ALLOW(LOCAL, LOG_DEBUG, " Boundary system destroyed.\n");
3725
3726 // --- Step 2: Destroy All Vectors ---
3727 // Handles ~74 Vec objects with proper NULL checking.
3728 ierr = DestroyUserVectors(user); CHKERRQ(ierr);
3729 LOG_ALLOW(LOCAL, LOG_DEBUG, " All vectors destroyed.\n");
3730
3731 // --- Step 3: Destroy Matrix and Solver Objects ---
3732 // Destroy pressure-Poisson matrices and solver.
3733 if (user->A) {
3734 ierr = MatDestroy(&user->A); CHKERRQ(ierr);
3735 LOG_ALLOW(LOCAL, LOG_DEBUG, " Matrix A destroyed.\n");
3736 }
3737 if (user->C) {
3738 ierr = MatDestroy(&user->C); CHKERRQ(ierr);
3739 LOG_ALLOW(LOCAL, LOG_DEBUG, " Matrix C destroyed.\n");
3740 }
3741 if (user->MR) {
3742 ierr = MatDestroy(&user->MR); CHKERRQ(ierr);
3743 LOG_ALLOW(LOCAL, LOG_DEBUG, " Matrix MR destroyed.\n");
3744 }
3745 if (user->MP) {
3746 ierr = MatDestroy(&user->MP); CHKERRQ(ierr);
3747 LOG_ALLOW(LOCAL, LOG_DEBUG, " Matrix MP destroyed.\n");
3748 }
3749 if (user->ksp) {
3750 ierr = KSPDestroy(&user->ksp); CHKERRQ(ierr);
3751 LOG_ALLOW(LOCAL, LOG_DEBUG, " KSP solver destroyed.\n");
3752 }
3753 if (user->nullsp) {
3754 ierr = MatNullSpaceDestroy(&user->nullsp); CHKERRQ(ierr);
3755 LOG_ALLOW(LOCAL, LOG_DEBUG, " MatNullSpace destroyed.\n");
3756 }
3757
3758 // --- Step 4: Destroy Application Ordering ---
3759 if (user->ao) {
3760 ierr = AODestroy(&user->ao); CHKERRQ(ierr);
3761 LOG_ALLOW(LOCAL, LOG_DEBUG, " AO destroyed.\n");
3762 }
3763
3764 // --- Step 5: Destroy DM Objects ---
3765 // Destroy in reverse order of dependency: post_swarm, swarm, fda2, fda, da
3766 if (user->post_swarm) {
3767 ierr = DMDestroy(&user->post_swarm); CHKERRQ(ierr);
3768 LOG_ALLOW(LOCAL, LOG_DEBUG, " post_swarm DM destroyed.\n");
3769 }
3770 if (user->swarm) {
3771 ierr = DMDestroy(&user->swarm); CHKERRQ(ierr);
3772 LOG_ALLOW(LOCAL, LOG_DEBUG, " swarm DM destroyed.\n");
3773 }
3774 if (user->fda2) {
3775 ierr = DMDestroy(&user->fda2); CHKERRQ(ierr);
3776 LOG_ALLOW(LOCAL, LOG_DEBUG, " fda2 DM destroyed.\n");
3777 }
3778 if (user->da) {
3779 ierr = DMDestroy(&user->da); CHKERRQ(ierr);
3780 LOG_ALLOW(LOCAL, LOG_DEBUG, " da DM destroyed.\n");
3781 }
3782
3783 // --- Step 6: Free PetscMalloc'd Arrays ---
3784 // Free arrays allocated with PetscMalloc1
3785 if (user->RankCellInfoMap) {
3786 ierr = PetscFree(user->RankCellInfoMap); CHKERRQ(ierr);
3787 user->RankCellInfoMap = NULL;
3788 LOG_ALLOW(LOCAL, LOG_DEBUG, " RankCellInfoMap freed.\n");
3789 }
3790 if (user->KSKE) {
3791 ierr = PetscFree(user->KSKE); CHKERRQ(ierr);
3792 user->KSKE = NULL;
3793 LOG_ALLOW(LOCAL, LOG_DEBUG, " KSKE array freed.\n");
3794 }
3795
3796 LOG_ALLOW(LOCAL, LOG_INFO, "UserCtx at level %d fully destroyed.\n", user->thislevel);
3797 PetscFunctionReturn(0);
3798}
PetscErrorCode BoundarySystem_Destroy(UserCtx *user)
Cleans up and destroys all boundary system resources.
PetscErrorCode DestroyUserVectors(UserCtx *user)
Internal helper implementation: DestroyUserVectors().
Definition setup.c:3571
MatNullSpace nullsp
Definition variables.h:918
PetscInt * KSKE
Definition variables.h:919
DM post_swarm
Definition variables.h:956
KSP ksp
Definition variables.h:918
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 3808 of file setup.c.

3809{
3810 PetscErrorCode ierr;
3811 PetscFunctionBeginUser;
3812
3813 if (!simCtx) {
3814 LOG_ALLOW(GLOBAL, LOG_WARNING, "FinalizeSimulation called with NULL SimCtx pointer.\n");
3815 PetscFunctionReturn(0);
3816 }
3817
3818 LOG_ALLOW(GLOBAL, LOG_INFO, "========================================\n");
3819 LOG_ALLOW(GLOBAL, LOG_INFO, "Beginning simulation memory cleanup...\n");
3820 LOG_ALLOW(GLOBAL, LOG_INFO, "========================================\n");
3821
3822 // ============================================================================
3823 // PHASE 1: DESTROY MULTIGRID HIERARCHY (All UserCtx structures)
3824 // ============================================================================
3825
3826 ierr = DestroySolutionConvergenceState(simCtx); CHKERRQ(ierr);
3827
3828 if (simCtx->usermg.mgctx) {
3829 LOG_ALLOW(GLOBAL, LOG_INFO, "Destroying multigrid hierarchy (%d levels)...\n",
3830 simCtx->usermg.mglevels);
3831
3832 // Destroy each UserCtx from finest to coarsest (reverse order is safer)
3833 for (PetscInt level = simCtx->usermg.mglevels - 1; level >= 0; level--) {
3834 UserCtx *user = simCtx->usermg.mgctx[level].user;
3835 if (user) {
3836 LOG_ALLOW(LOCAL, LOG_INFO, " Destroying level %d of %d...\n",
3837 level, simCtx->usermg.mglevels - 1);
3838 ierr = DestroyUserContext(user); CHKERRQ(ierr);
3839
3840 // Free the UserCtx structure itself
3841 ierr = PetscFree(user); CHKERRQ(ierr);
3842 simCtx->usermg.mgctx[level].user = NULL;
3843 }
3844
3845 // Destroy the MGCtx-level packer DM
3846 if (simCtx->usermg.mgctx[level].packer) {
3847 ierr = DMDestroy(&simCtx->usermg.mgctx[level].packer); CHKERRQ(ierr);
3848 LOG_ALLOW(LOCAL, LOG_DEBUG, " MGCtx[%d].packer destroyed.\n", level);
3849 }
3850 }
3851
3852 // Free the MGCtx array itself
3853 ierr = PetscFree(simCtx->usermg.mgctx); CHKERRQ(ierr);
3854 simCtx->usermg.mgctx = NULL;
3855 LOG_ALLOW(GLOBAL, LOG_INFO, "All multigrid levels destroyed.\n");
3856 }
3857
3858 // ============================================================================
3859 // PHASE 2: DESTROY USERMG-LEVEL OBJECTS
3860 // ============================================================================
3861
3862 if (simCtx->usermg.packer) {
3863 ierr = DMDestroy(&simCtx->usermg.packer); CHKERRQ(ierr);
3864 LOG_ALLOW(LOCAL, LOG_DEBUG, "UserMG.packer DM destroyed.\n");
3865 }
3866
3867 if (simCtx->usermg.snespacker) {
3868 ierr = SNESDestroy(&simCtx->usermg.snespacker); CHKERRQ(ierr);
3869 LOG_ALLOW(LOCAL, LOG_DEBUG, "UserMG.snespacker SNES destroyed.\n");
3870 }
3871
3872 // ============================================================================
3873 // PHASE 3: DESTROY SIMCTX-LEVEL OBJECTS
3874 // ============================================================================
3875
3876 LOG_ALLOW(GLOBAL, LOG_INFO, "Destroying SimCtx-level objects...\n");
3877
3878 // --- PetscViewer for logging ---
3879 if (simCtx->logviewer) {
3880 ierr = PetscViewerDestroy(&simCtx->logviewer); CHKERRQ(ierr);
3881 LOG_ALLOW(LOCAL, LOG_DEBUG, " logviewer destroyed.\n");
3882 }
3883
3884 // --- Particle System DM ---
3885 if (simCtx->dm_swarm) {
3886 ierr = DMDestroy(&simCtx->dm_swarm); CHKERRQ(ierr);
3887 LOG_ALLOW(LOCAL, LOG_DEBUG, " dm_swarm destroyed.\n");
3888 }
3889
3890 // --- BoundingBox List (Array of BoundingBox structs) ---
3891 if (simCtx->bboxlist) {
3892 ierr = PetscFree(simCtx->bboxlist); CHKERRQ(ierr);
3893 simCtx->bboxlist = NULL;
3894 LOG_ALLOW(LOCAL, LOG_DEBUG, " bboxlist freed.\n");
3895 }
3896
3897 // --- Boundary Condition Files (Array of strings) ---
3898 if (simCtx->bcs_files) {
3899 for (PetscInt i = 0; i < simCtx->num_bcs_files; i++) {
3900 if (simCtx->bcs_files[i]) {
3901 ierr = PetscFree(simCtx->bcs_files[i]); CHKERRQ(ierr);
3902 }
3903 }
3904 ierr = PetscFree(simCtx->bcs_files); CHKERRQ(ierr);
3905 simCtx->bcs_files = NULL;
3906 LOG_ALLOW(LOCAL, LOG_DEBUG, " bcs_files array freed (%d files).\n", simCtx->num_bcs_files);
3907 }
3908
3909 // --- Brownian Motion RNG ---
3910 if (simCtx->BrownianMotionRNG) {
3911 ierr = PetscRandomDestroy(&simCtx->BrownianMotionRNG); CHKERRQ(ierr);
3912 LOG_ALLOW(LOCAL, LOG_DEBUG, " BrownianMotionRNG destroyed.\n");
3913 }
3914 // --- Post-Processing Parameters ---
3915 // pps is allocated with PetscNew and contains only static char arrays and basic types.
3916 // No internal dynamic allocations need to be freed.
3917 if (simCtx->pps) {
3918 ierr = PetscFree(simCtx->pps); CHKERRQ(ierr);
3919 simCtx->pps = NULL;
3920 LOG_ALLOW(LOCAL, LOG_DEBUG, " PostProcessParams freed.\n");
3921 }
3922
3923 // --- IBM/FSI Objects ---
3924 // Note: These are initialized to NULL and currently have no dedicated destroy functions.
3925 // If these modules are extended with cleanup routines, call them here.
3926 if (simCtx->ibm != NULL) {
3927 LOG_ALLOW(GLOBAL, LOG_WARNING, " WARNING: simCtx->ibm is non-NULL but no destroy function exists. Potential memory leak.\n");
3928 }
3929 if (simCtx->ibmv != NULL) {
3930 LOG_ALLOW(GLOBAL, LOG_WARNING, " WARNING: simCtx->ibmv is non-NULL but no destroy function exists. Potential memory leak.\n");
3931 }
3932 if (simCtx->fsi != NULL) {
3933 LOG_ALLOW(GLOBAL, LOG_WARNING, " WARNING: simCtx->fsi is non-NULL but no destroy function exists. Potential memory leak.\n");
3934 }
3935
3936 // --- Logging Allowed Functions (Array of strings) ---
3937 // Note: The logging system maintains its own copy via set_allowed_functions(),
3938 // so freeing simCtx->allowedFuncs will NOT affect LOG_ALLOW functionality.
3939 if (simCtx->allowedFuncs) {
3940 for (PetscInt i = 0; i < simCtx->nAllowed; i++) {
3941 if (simCtx->allowedFuncs[i]) {
3942 ierr = PetscFree(simCtx->allowedFuncs[i]); CHKERRQ(ierr);
3943 }
3944 }
3945 ierr = PetscFree(simCtx->allowedFuncs); CHKERRQ(ierr);
3946 simCtx->allowedFuncs = NULL;
3947 LOG_ALLOW(LOCAL, LOG_DEBUG, " allowedFuncs array freed (%d functions).\n", simCtx->nAllowed);
3948 }
3949
3950 // --- Profiling Critical Functions (Array of strings) ---
3951 if (simCtx->profilingSelectedFuncs) {
3952 for (PetscInt i = 0; i < simCtx->nProfilingSelectedFuncs; i++) {
3953 if (simCtx->profilingSelectedFuncs[i]) {
3954 ierr = PetscFree(simCtx->profilingSelectedFuncs[i]); CHKERRQ(ierr);
3955 }
3956 }
3957 ierr = PetscFree(simCtx->profilingSelectedFuncs); CHKERRQ(ierr);
3958 simCtx->profilingSelectedFuncs = NULL;
3959 LOG_ALLOW(LOCAL, LOG_DEBUG, " profilingSelectedFuncs array freed (%d functions).\n", simCtx->nProfilingSelectedFuncs);
3960 }
3961
3962 // ============================================================================
3963 // PHASE 4: FINAL SUMMARY
3964 // ============================================================================
3965
3966 LOG_ALLOW(GLOBAL, LOG_INFO, "========================================\n");
3967 LOG_ALLOW(GLOBAL, LOG_INFO, "Simulation cleanup completed successfully.\n");
3968 LOG_ALLOW(GLOBAL, LOG_INFO, "All PETSc objects have been destroyed.\n");
3969 LOG_ALLOW(GLOBAL, LOG_INFO, "========================================\n");
3970
3971 ierr = PetscFree(simCtx); CHKERRQ(ierr);
3972 PetscFunctionReturn(0);
3973}
PetscErrorCode DestroyUserContext(UserCtx *user)
Internal helper implementation: DestroyUserContext().
Definition setup.c:3709
PetscErrorCode DestroySolutionConvergenceState(SimCtx *simCtx)
Implementation of DestroySolutionConvergenceState().
Definition setup.c:98
DM packer
Definition variables.h:580
SNES snespacker
Definition variables.h:581
DM packer
Definition variables.h:571
Here is the call graph for this function:
Here is the caller graph for this function: