19#define PICURV_STRINGIZE_(x) #x
20#define PICURV_STRINGIZE(x) PICURV_STRINGIZE_(x)
21#if defined(PETSC_USE_DEBUG)
22#define PICURV_PETSC_MODE "debug"
24#define PICURV_PETSC_MODE "optimized"
32#define PICURV_PETSC_STAMP_MARKER "PICURV_PETSC_BUILD:"
49 for (
int index = 1; index < argc; ++index) {
50 if (!strcmp(argv[index],
"--version") || !strcmp(argv[index],
"-version")) {
72 if (seconds_out) *seconds_out = 0.0;
73 if (!text || text[0] ==
'\0')
return PETSC_FALSE;
76 parsed_value = strtod(text, &endptr);
77 if (endptr == text || errno == ERANGE || !isfinite(parsed_value) || parsed_value <= 0.0) {
81 while (*endptr !=
'\0' && isspace((
unsigned char)*endptr)) {
84 if (*endptr !=
'\0')
return PETSC_FALSE;
86 if (seconds_out) *seconds_out = (PetscReal)parsed_value;
99 PetscInt history_capacity = 0;
101 PetscFunctionBeginUser;
102 if (!simCtx) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"SimCtx cannot be NULL.");
106 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
107 "Multigrid hierarchy must exist before initializing solution convergence storage.");
112 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
113 "Finest-level UserCtx must exist before initializing solution convergence storage.");
119 for (PetscInt bi = 0; bi < simCtx->
block_number; ++bi) {
125 PetscCall(VecDuplicate(user[bi].Ucat, &user[bi].solutionConvergencePeriodicUcatRef[phase]));
126 PetscCall(VecSet(user[bi].solutionConvergencePeriodicUcatRef[phase], 0.0));
127 PetscCall(VecDuplicate(user[bi].P, &user[bi].solutionConvergencePeriodicPRef[phase]));
128 PetscCall(VecSet(user[bi].solutionConvergencePeriodicPRef[phase], 0.0));
139 PetscFunctionReturn(0);
152 PetscFunctionBeginUser;
153 if (!simCtx) PetscFunctionReturn(0);
163 for (PetscInt bi = 0; bi < simCtx->
block_number; ++bi) {
164 if (user[bi].solutionConvergencePeriodicUcatRef) {
166 if (user[bi].solutionConvergencePeriodicUcatRef[phase]) {
167 PetscCall(VecDestroy(&user[bi].solutionConvergencePeriodicUcatRef[phase]));
170 PetscCall(PetscFree(user[bi].solutionConvergencePeriodicUcatRef));
173 if (user[bi].solutionConvergencePeriodicPRef) {
175 if (user[bi].solutionConvergencePeriodicPRef[phase]) {
176 PetscCall(VecDestroy(&user[bi].solutionConvergencePeriodicPRef[phase]));
179 PetscCall(PetscFree(user[bi].solutionConvergencePeriodicPRef));
195 PetscFunctionReturn(0);
199#define __FUNCT__ "LESConfigSetDefaults"
208 PetscFunctionBeginUser;
209 PetscCheck(config != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
210 "LES configuration destination cannot be NULL.");
237 PetscFunctionReturn(0);
241#define __FUNCT__ "ParseLESConfiguration"
263 char directions[8] =
"";
264 PetscBool found = PETSC_FALSE;
266 PetscFunctionBeginUser;
268 PetscCall(PetscOptionsGetReal(NULL, NULL,
"-les_constant_cs", &config->
constant_cs, NULL));
269 PetscCall(PetscOptionsGetReal(NULL, NULL,
"-les_vreman_coefficient", &config->
vreman_coefficient, NULL));
270 PetscCall(PetscOptionsGetReal(NULL, NULL,
"-les_wale_coefficient", &config->
wale_coefficient, NULL));
271 PetscCall(PetscOptionsGetInt(NULL, NULL,
"-les_dynamic_frequency", &config->
dynamic_frequency, NULL));
274 PetscCall(PetscOptionsGetInt(NULL, NULL,
"-les_filter_width", &selector, NULL));
276 PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
277 "-les_filter_width must be 0 (cube_root_volume), 1 (geometric_mean), 2 (max_edge), or 3 (scotti); received %" PetscInt_FMT
".",
282 PetscCall(PetscOptionsGetInt(NULL, NULL,
"-les_test_filter_kernel", &selector, NULL));
284 PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
285 "-les_test_filter_kernel must be 0 (volume_weighted_box) or 1 (simpson_ik); received %" PetscInt_FMT
".",
289 PetscCall(PetscOptionsGetReal(NULL, NULL,
"-les_test_filter_width_ratio",
292 "-les_test_filter_width_ratio must exceed 1; a test filter no wider than the grid "
293 "filter leaves the dynamic procedure nothing to measure. Received %g.",
297 PetscCall(PetscOptionsGetInt(NULL, NULL,
"-les_averaging_mode", &selector, NULL));
299 PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
300 "-les_averaging_mode must be 0 (local), 1 (homogeneous), or 2 (global); received %" PetscInt_FMT
".",
306 PetscCall(PetscOptionsGetString(NULL, NULL,
"-les_averaging_directions",
307 directions,
sizeof(directions), &found));
309 for (
size_t index = 0; directions[index] !=
'\0'; index++) {
310 switch (directions[index]) {
315 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
316 "-les_averaging_directions accepts only the characters i, j, and k; "
317 "received '%s'.", directions);
323 PetscCall(PetscOptionsGetInt(NULL, NULL,
"-les_clip_mode", &selector, NULL));
325 PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
326 "-les_clip_mode must be 0 (clamp), 1 (clip_negative), or 2 (none); received %" PetscInt_FMT
".",
330 PetscCall(PetscOptionsGetReal(NULL, NULL,
"-les_clip_max_cs", &config->
max_cs, NULL));
331 PetscCall(PetscOptionsGetReal(NULL, NULL,
"-les_min_viscosity_ratio",
333 PetscCall(PetscOptionsGetReal(NULL, NULL,
"-les_yoshizawa_ci", &config->
yoshizawa_ci, NULL));
334 PetscCall(PetscOptionsGetBool(NULL, NULL,
"-les_diagnostics",
336 PetscCall(PetscOptionsGetInt(NULL, NULL,
"-les_diagnostics_cadence",
339 PetscCheck(config->
dynamic_frequency > 0, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
340 "-les_dynamic_frequency must be positive; received %" PetscInt_FMT
".",
342 PetscCheck(config->
constant_cs >= 0.0, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
343 "-les_constant_cs must be nonnegative; received %g.", (
double)config->
constant_cs);
344 PetscCheck(config->
vreman_coefficient >= 0.0, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
345 "-les_vreman_coefficient must be nonnegative; received %g.",
347 PetscCheck(config->
wale_coefficient >= 0.0, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
348 "-les_wale_coefficient must be nonnegative; received %g.",
350 PetscCheck(config->
max_cs >= 0.0, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
351 "-les_clip_max_cs must be nonnegative; received %g.", (
double)config->
max_cs);
353 "-les_min_viscosity_ratio must be nonnegative; received %g.",
356 "-les_diagnostics_cadence must be positive; received %" PetscInt_FMT
".",
359 PetscFunctionReturn(0);
363#define __FUNCT__ "CreateSimulationContext"
377 char control_filename[PETSC_MAX_PATH_LEN] =
"";
378 PetscBool control_flg;
379 PetscBool particle_console_output_freq_flg = PETSC_FALSE;
381 PetscFunctionBeginUser;
386 ierr = PetscNew(p_simCtx); CHKERRQ(ierr);
402 strcpy(simCtx->
log_dir,
"logs");
417 simCtx->
MHV=0; simCtx->
LV=0;
479 simCtx->
max_angle = -54. * 3.1415926 / 180.;
489 strcpy(simCtx->
grid_file,
"config/grid.run");
495 ierr = PetscMalloc1(1, &simCtx->
bcs_files); CHKERRQ(ierr);
496 ierr = PetscStrallocpy(
"config/bcs.run", &simCtx->
bcs_files[0]); CHKERRQ(ierr);
547 simCtx->
ibm = NULL; simCtx->
ibmv = NULL; simCtx->
fsi = NULL;
550 strcpy(simCtx->
allowedFile,
"config/whitelist.run");
551 simCtx->
useCfg = PETSC_FALSE;
586 ierr = PetscNew(&simCtx->
pps); CHKERRQ(ierr);
590 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &simCtx->
rank); CHKERRQ(ierr);
591 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &simCtx->
size); CHKERRQ(ierr);
594 ierr = PetscOptionsGetString(NULL, NULL,
"-control_file", control_filename,
sizeof(control_filename), &control_flg); CHKERRQ(ierr);
597 if (!control_flg || strlen(control_filename) == 0) {
598 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
599 "\n\n*** MANDATORY ARGUMENT MISSING ***\n"
600 "The -control_file argument was not provided.\n"
601 "This program must be launched with a configuration file.\n"
602 "Example: mpiexec -n 4 ./simulator -control_file /path/to/your/config.control\n"
603 "This is typically handled automatically by the 'picurv' script.\n");
607 LOG(
GLOBAL,
LOG_INFO,
"Loading mandatory configuration from: %s\n", control_filename);
608 ierr = PetscOptionsInsertFile(PETSC_COMM_WORLD, NULL, control_filename, PETSC_FALSE);
609 if (ierr == PETSC_ERR_FILE_OPEN) {
610 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_FILE_OPEN,
"The specified control file was not found or could not be opened: %s", control_filename);
615 PetscBool legacy_averaging = PETSC_FALSE;
616 ierr = PetscOptionsHasName(NULL, NULL,
"-averaging", &legacy_averaging); CHKERRQ(ierr);
617 PetscCheck(!legacy_averaging, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
618 "Legacy -averaging was removed. Use instantaneous output and offline "
619 "postprocessing until the replacement field-statistics pipeline is available.");
625 ierr = PetscOptionsGetString(NULL, NULL,
"-whitelist_config_file", simCtx->
allowedFile, PETSC_MAX_PATH_LEN, &simCtx->
useCfg); CHKERRQ(ierr);
631 PetscPrintf(PETSC_COMM_SELF,
"[%s] WARNING: Failed to load allowed functions from '%s'. Falling back to default list.\n", __func__, simCtx->
allowedFile);
632 simCtx->
useCfg = PETSC_FALSE;
635 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
636 "Whitelist config file '%s' is empty. Omit -whitelist_config_file to use the default allow-list, or list at least one function.",
644 ierr = PetscStrallocpy(
"main", &simCtx->
allowedFuncs[0]); CHKERRQ(ierr);
645 ierr = PetscStrallocpy(
"CreateSimulationContext", &simCtx->
allowedFuncs[1]); CHKERRQ(ierr);
657 ierr = PetscOptionsGetString(NULL, NULL,
"-profiling_timestep_file", simCtx->
profilingTimestepFile, PETSC_MAX_PATH_LEN, NULL); CHKERRQ(ierr);
658 ierr = PetscOptionsGetBool(NULL, NULL,
"-profiling_final_summary", &simCtx->
profilingFinalSummary, NULL); CHKERRQ(ierr);
662 PetscPrintf(PETSC_COMM_SELF,
"[%s] WARNING: Unknown profiling timestep mode '%s'. Falling back to 'selected'.\n", __func__, simCtx->
profilingTimestepMode);
671 PetscPrintf(PETSC_COMM_SELF,
"[%s] WARNING: Failed to load selected profiling functions from '%s'. Falling back to default list.\n", __func__, simCtx->
profilingSelectedFuncsFile);
697 ierr = PetscOptionsGetInt(NULL, NULL,
"-start_step", &simCtx->
StartStep, NULL); CHKERRQ(ierr);
698 ierr = PetscOptionsGetInt(NULL,NULL,
"-totalsteps", &simCtx->
StepsToRun, NULL); CHKERRQ(ierr);
699 ierr = PetscOptionsGetBool(NULL, NULL,
"-only_setup", &simCtx->
OnlySetup, NULL); CHKERRQ(ierr);
700 ierr = PetscOptionsGetBool(NULL, NULL,
"-continue_mode", &simCtx->
continueMode, NULL); CHKERRQ(ierr);
705 ierr = PetscOptionsGetBool(NULL, NULL,
"-field_statistics_continue",
707 ierr = PetscOptionsGetReal(NULL, NULL,
"-dt", &simCtx->
dt, NULL); CHKERRQ(ierr);
708 ierr = PetscOptionsGetInt(NULL, NULL,
"-tio", &simCtx->
tiout, NULL); CHKERRQ(ierr);
709 ierr = PetscOptionsGetInt(NULL, NULL,
"-particle_console_output_freq", &simCtx->
particleConsoleOutputFreq, &particle_console_output_freq_flg); CHKERRQ(ierr);
710 if (!particle_console_output_freq_flg) {
714 ierr = PetscOptionsGetString(NULL,NULL,
"-output_dir",simCtx->
output_dir,
sizeof(simCtx->
output_dir),NULL);CHKERRQ(ierr);
715 ierr = PetscOptionsGetString(NULL,NULL,
"-restart_dir",simCtx->
restart_dir,
sizeof(simCtx->
restart_dir),NULL);CHKERRQ(ierr);
716 ierr = PetscOptionsGetString(NULL,NULL,
"-log_dir",simCtx->
log_dir,
sizeof(simCtx->
log_dir),NULL);CHKERRQ(ierr);
717 ierr = PetscOptionsGetString(NULL,NULL,
"-analysis_dir",simCtx->
analysis_dir,
sizeof(simCtx->
analysis_dir),NULL);CHKERRQ(ierr);
718 ierr = PetscOptionsGetBool(NULL, NULL,
"-walltime_guard_enabled", &simCtx->
walltimeGuardEnabled, NULL); CHKERRQ(ierr);
719 ierr = PetscOptionsGetInt(NULL, NULL,
"-walltime_guard_warmup_steps", &simCtx->
walltimeGuardWarmupSteps, NULL); CHKERRQ(ierr);
720 ierr = PetscOptionsGetReal(NULL, NULL,
"-walltime_guard_multiplier", &simCtx->
walltimeGuardMultiplier, NULL); CHKERRQ(ierr);
721 ierr = PetscOptionsGetBool(NULL, NULL,
"-runtime_memory_log_enabled", &simCtx->
runtimeMemoryLogEnabled, NULL); CHKERRQ(ierr);
722 ierr = PetscOptionsGetString(NULL, NULL,
"-runtime_memory_log_file", simCtx->
runtimeMemoryLogFile, PETSC_MAX_PATH_LEN, NULL); CHKERRQ(ierr);
723 ierr = PetscOptionsGetReal(NULL, NULL,
"-walltime_guard_min_seconds", &simCtx->
walltimeGuardMinSeconds, NULL); CHKERRQ(ierr);
724 ierr = PetscOptionsGetReal(NULL, NULL,
"-walltime_guard_estimator_alpha", &simCtx->
walltimeGuardEstimatorAlpha, NULL); CHKERRQ(ierr);
727 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
"Invalid value for -walltime_guard_warmup_steps: %d. Must be > 0.", simCtx->
walltimeGuardWarmupSteps);
730 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
"Invalid value for -walltime_guard_multiplier: %.6f. Must be in (0, 5].", (
double)simCtx->
walltimeGuardMultiplier);
733 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
"Invalid value for -walltime_guard_min_seconds: %.6f. Must be > 0.", (
double)simCtx->
walltimeGuardMinSeconds);
736 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
"Invalid value for -walltime_guard_estimator_alpha: %.6f. Must be in (0, 1].", (
double)simCtx->
walltimeGuardEstimatorAlpha);
740 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);
743 const char *job_start_env = getenv(
"PICURV_JOB_START_EPOCH");
744 const char *limit_env = getenv(
"PICURV_WALLTIME_LIMIT_SECONDS");
748 if (!job_start_ok || !limit_ok) {
755 "Runtime walltime guard enabled but %s/%s are missing or invalid. Falling back to external shutdown signals only.\n",
756 "PICURV_JOB_START_EPOCH",
757 "PICURV_WALLTIME_LIMIT_SECONDS"
766 ierr = PetscOptionsGetInt(NULL, NULL,
"-imm", &simCtx->
immersed, NULL); CHKERRQ(ierr);
767 ierr = PetscOptionsGetInt(NULL, NULL,
"-fsi", &simCtx->
movefsi, NULL); CHKERRQ(ierr);
768 ierr = PetscOptionsGetInt(NULL, NULL,
"-rfsi", &simCtx->
rotatefsi, NULL); CHKERRQ(ierr);
769 ierr = PetscOptionsGetInt(NULL, NULL,
"-inv", &simCtx->
invicid, NULL); CHKERRQ(ierr);
770 ierr = PetscOptionsGetInt(NULL, NULL,
"-TwoD", &simCtx->
TwoD, NULL); CHKERRQ(ierr);
771 ierr = PetscOptionsGetInt(NULL, NULL,
"-mframe", &simCtx->
moveframe, NULL); CHKERRQ(ierr);
772 ierr = PetscOptionsGetInt(NULL, NULL,
"-rframe", &simCtx->
rotateframe, NULL); CHKERRQ(ierr);
784 "Immersed boundaries and moving bodies (-imm, -fsi, -rfsi) are planned, not implemented.");
786 "Moving and rotating reference frames (-mframe, -rframe) are planned, not implemented: "
787 "their convection branch is absent, so the convective term would be dropped.");
791 ierr = PetscOptionsGetInt(NULL, NULL,
"-mhv", &simCtx->
MHV, NULL); CHKERRQ(ierr);
792 ierr = PetscOptionsGetInt(NULL, NULL,
"-lv", &simCtx->
LV, NULL); CHKERRQ(ierr);
795 PetscCheck(!simCtx->
MHV && !simCtx->
LV, PETSC_COMM_WORLD, PETSC_ERR_SUP,
796 "The -mhv/-lv immersed-body flux corrections need immersed boundaries, which are planned, not implemented.");
797 ierr = PetscOptionsGetReal(NULL,NULL,
"-driven_flow_initial_force",&simCtx->
drivingForceMagnitude,NULL);CHKERRQ(ierr);
798 ierr = PetscOptionsGetReal(NULL,NULL,
"-driven_flow_scaling_factor",&simCtx->
forceScalingFactor,NULL);CHKERRQ(ierr);
801 char mom_solver_type_char[PETSC_MAX_PATH_LEN];
802 char solution_convergence_mode_char[PETSC_MAX_PATH_LEN];
803 PetscBool mom_solver_type_flg = PETSC_FALSE;
804 PetscBool solution_convergence_mode_flg = PETSC_FALSE;
805 ierr = PetscOptionsGetString(NULL, NULL,
"-mom_solver_type", mom_solver_type_char,
sizeof(mom_solver_type_char), &mom_solver_type_flg); CHKERRQ(ierr);
806 ierr = PetscOptionsGetInt(NULL, NULL,
"-mom_max_pseudo_steps", &simCtx->
mom_max_pseudo_steps, NULL); CHKERRQ(ierr);
807 ierr = PetscOptionsGetReal(NULL, NULL,
"-mom_atol", &simCtx->
mom_atol, NULL); CHKERRQ(ierr);
808 ierr = PetscOptionsGetReal(NULL, NULL,
"-mom_rtol", &simCtx->
mom_rtol, NULL); CHKERRQ(ierr);
809 ierr = PetscOptionsGetReal(NULL, NULL,
"-mom_resid_atol", &simCtx->
mom_resid_atol, NULL); CHKERRQ(ierr);
810 ierr = PetscOptionsGetReal(NULL, NULL,
"-mom_resid_rtol", &simCtx->
mom_resid_rtol, NULL); CHKERRQ(ierr);
811 ierr = PetscOptionsGetReal(NULL, NULL,
"-imp_stol", &simCtx->
imp_stol, NULL); CHKERRQ(ierr);
812 ierr = PetscOptionsGetInt(NULL, NULL,
"-central", &simCtx->
central, NULL); CHKERRQ(ierr);
813 ierr = PetscOptionsGetString(NULL, NULL,
"-solution_convergence_mode",
814 solution_convergence_mode_char,
sizeof(solution_convergence_mode_char),
815 &solution_convergence_mode_flg); CHKERRQ(ierr);
816 ierr = PetscOptionsGetBool(NULL, NULL,
"-solution_convergence_enabled", &simCtx->
solutionConvergenceEnabled, NULL); CHKERRQ(ierr);
826 if (mom_solver_type_flg) {
827 if(strcmp(mom_solver_type_char,
"DUALTIME_PICARD_JAMESON_RK") == 0 ||
828 strcmp(mom_solver_type_char,
"DUALTIME_PICARD_RK4") == 0) {
830 }
else if (strcmp(mom_solver_type_char,
"EXPLICIT_RK") == 0) {
832 }
else if (strcmp(mom_solver_type_char,
"newton_krylov") == 0) {
835 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);
836 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
"Invalid value for -mom_solver_type: '%s'.", mom_solver_type_char);
840 if (solution_convergence_mode_flg) {
841 if (strcmp(solution_convergence_mode_char,
"STEADY_DETERMINISTIC") == 0) {
843 }
else if (strcmp(solution_convergence_mode_char,
"PERIODIC_DETERMINISTIC") == 0) {
845 }
else if (strcmp(solution_convergence_mode_char,
"STATISTICAL_STEADY") == 0) {
847 }
else if (strcmp(solution_convergence_mode_char,
"TRANSIENT") == 0) {
850 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
851 "Invalid value for -solution_convergence_mode: '%s'.", solution_convergence_mode_char);
857 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
858 "solution convergence mode PERIODIC_DETERMINISTIC requires -solution_convergence_period_steps > 0.");
862 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
863 "solution convergence mode STATISTICAL_STEADY requires -solution_convergence_window_steps > 0.");
867 ierr = PetscOptionsGetInt(NULL, NULL,
"-mg_level", &simCtx->
mglevels, NULL); CHKERRQ(ierr);
868 ierr = PetscOptionsGetInt(NULL, NULL,
"-mg_pre_it", &simCtx->
mg_preItr, NULL); CHKERRQ(ierr);
869 ierr = PetscOptionsGetInt(NULL, NULL,
"-mg_post_it", &simCtx->
mg_poItr, NULL); CHKERRQ(ierr);
872 ierr = PetscOptionsGetInt(NULL, NULL,
"-poisson", &simCtx->
poisson, NULL); CHKERRQ(ierr);
873 ierr = PetscOptionsGetReal(NULL, NULL,
"-ren", &simCtx->
ren, NULL); CHKERRQ(ierr);
874 ierr = PetscOptionsGetReal(NULL, NULL,
"-pseudo_cfl", &simCtx->
pseudo_cfl, NULL); CHKERRQ(ierr);
875 ierr = PetscOptionsGetReal(NULL, NULL,
"-max_pseudo_cfl", &simCtx->
max_pseudo_cfl, NULL); CHKERRQ(ierr);
876 ierr = PetscOptionsGetReal(NULL, NULL,
"-min_pseudo_cfl", &simCtx->
min_pseudo_cfl, NULL); CHKERRQ(ierr);
878 ierr = PetscOptionsGetReal(NULL, NULL,
"-pseudo_cfl_growth_factor", &simCtx->
pseudo_cfl_growth_factor, NULL); CHKERRQ(ierr);
882 ierr = PetscOptionsGetBool(NULL, NULL,
"-no_pseudo_cfl_backtrack", &simCtx->
no_pseudo_cfl_backtrack, NULL); CHKERRQ(ierr);
883 ierr = PetscOptionsGetReal(NULL, NULL,
"-mom_ratio_ema_alpha", &simCtx->
mom_ratio_ema_alpha, NULL); CHKERRQ(ierr);
887 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
888 "Pseudo-CFL controls require 0 < minimum <= initial <= maximum.");
894 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
895 "Pseudo-CFL controls require growth_factor >= 1, 0 < reduction_factor < 1, and noise allowance >= 1.");
898 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
899 "-mom_ratio_ema_alpha must be in [0, 1].");
902 ierr = PetscOptionsGetBool(NULL, NULL,
"-mom_nk_pic_monitor", &simCtx->
mom_nk_monitor_history, NULL); CHKERRQ(ierr);
906 ierr = PetscOptionsGetInt(NULL, NULL,
"-finit", &ic_mode, NULL); CHKERRQ(ierr);
907 ierr = PetscOptionsGetInt(NULL, NULL,
"-ic_field", &ic_field, NULL); CHKERRQ(ierr);
914 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
915 "Invalid value for -finit. Expected an initial-condition mode in [0,4], got %d.",
919 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
920 "Invalid value for -ic_field. Expected 0 (Ucat) or 1 (Ucont), got %d.",
923 ierr = PetscOptionsGetReal(NULL, NULL,
"-ucont_x", &simCtx->
InitialConstantContra.
x, NULL); CHKERRQ(ierr);
924 ierr = PetscOptionsGetReal(NULL, NULL,
"-ucont_y", &simCtx->
InitialConstantContra.
y, NULL); CHKERRQ(ierr);
925 ierr = PetscOptionsGetReal(NULL, NULL,
"-ucont_z", &simCtx->
InitialConstantContra.
z, NULL); CHKERRQ(ierr);
928 PetscBool fd_set = PETSC_FALSE;
929 ierr = PetscOptionsGetInt(NULL, NULL,
"-flow_direction", &fd_int, &fd_set); CHKERRQ(ierr);
932 ierr = PetscOptionsGetReal(NULL, NULL,
"-ic_velocity_physical", &simCtx->
icVelocityPhysical, NULL); CHKERRQ(ierr);
936 PetscBool verification_scalar_value_set = PETSC_FALSE;
937 PetscBool verification_scalar_phi0_set = PETSC_FALSE;
938 PetscBool verification_scalar_slope_x_set = PETSC_FALSE;
939 PetscBool verification_scalar_amplitude_set = PETSC_FALSE;
940 PetscBool verification_scalar_kx_set = PETSC_FALSE;
941 PetscBool verification_scalar_ky_set = PETSC_FALSE;
942 PetscBool verification_scalar_kz_set = PETSC_FALSE;
943 ierr = PetscOptionsGetString(NULL, NULL,
"-verification_diffusivity_mode",
946 ierr = PetscOptionsGetString(NULL, NULL,
"-verification_diffusivity_profile",
949 ierr = PetscOptionsGetReal(NULL, NULL,
"-verification_diffusivity_gamma0",
951 ierr = PetscOptionsGetReal(NULL, NULL,
"-verification_diffusivity_slope_x",
953 ierr = PetscOptionsGetString(NULL, NULL,
"-verification_scalar_mode",
956 ierr = PetscOptionsGetString(NULL, NULL,
"-verification_scalar_profile",
959 ierr = PetscOptionsGetReal(NULL, NULL,
"-verification_scalar_value",
961 ierr = PetscOptionsGetReal(NULL, NULL,
"-verification_scalar_phi0",
963 ierr = PetscOptionsGetReal(NULL, NULL,
"-verification_scalar_slope_x",
965 ierr = PetscOptionsGetReal(NULL, NULL,
"-verification_scalar_amplitude",
967 ierr = PetscOptionsGetReal(NULL, NULL,
"-verification_scalar_kx",
969 ierr = PetscOptionsGetReal(NULL, NULL,
"-verification_scalar_ky",
971 ierr = PetscOptionsGetReal(NULL, NULL,
"-verification_scalar_kz",
981 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
982 "verification diffusivity overrides require -euler_field_source \"analytical\".");
985 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
986 "Unsupported -verification_diffusivity_mode '%s'. Only 'analytical' is supported.",
990 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
991 "Unsupported -verification_diffusivity_profile '%s'. Only 'LINEAR_X' is supported.",
997 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
998 "verification scalar overrides require -euler_field_source \"analytical\".");
1001 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
1002 "Unsupported -verification_scalar_mode '%s'. Only 'analytical' is supported.",
1006 if (!verification_scalar_value_set) {
1007 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
1008 "verification scalar profile CONSTANT requires -verification_scalar_value.");
1011 if (!verification_scalar_phi0_set || !verification_scalar_slope_x_set) {
1012 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
1013 "verification scalar profile LINEAR_X requires -verification_scalar_phi0 and -verification_scalar_slope_x.");
1016 if (!verification_scalar_amplitude_set || !verification_scalar_kx_set ||
1017 !verification_scalar_ky_set || !verification_scalar_kz_set) {
1018 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
1019 "verification scalar profile SIN_PRODUCT requires -verification_scalar_amplitude, -verification_scalar_kx, -verification_scalar_ky, and -verification_scalar_kz.");
1022 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
1023 "Unsupported -verification_scalar_profile '%s'. Supported profiles: CONSTANT, LINEAR_X, SIN_PRODUCT.",
1031 ierr = PetscOptionsGetReal(NULL,NULL,
"-schmidt_number",&simCtx->
schmidt_number,NULL);CHKERRQ(ierr);
1033 ierr = PetscOptionsGetReal(NULL,NULL,
"-iem_constant",&simCtx->
iem_constant,NULL);CHKERRQ(ierr);
1036 PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
1037 "-iem_constant must be a non-negative finite number (got %g).", (
double)simCtx->
iem_constant);
1038 ierr = PetscOptionsGetReal(NULL,NULL,
"-wall_roughness",&simCtx->
wall_roughness_height,NULL);CHKERRQ(ierr);
1047 ierr = PetscOptionsGetInt(NULL, NULL,
"-nblk", &simCtx->
block_number, NULL); CHKERRQ(ierr);
1051 PetscCheck(simCtx->
block_number == 1, PETSC_COMM_WORLD, PETSC_ERR_SUP,
1052 "Multi-block domains are planned, not implemented: blocks are never coupled (got -nblk %" PetscInt_FMT
").",
1054 ierr = PetscOptionsGetInt(NULL, NULL,
"-inlet", &simCtx->
inletprofile, NULL); CHKERRQ(ierr);
1056 ierr = PetscOptionsGetBool(NULL, NULL,
"-grid", &simCtx->
generate_grid, NULL); CHKERRQ(ierr);
1057 ierr = PetscOptionsGetString(NULL, NULL,
"-grid_file", simCtx->
grid_file, PETSC_MAX_PATH_LEN, NULL); CHKERRQ(ierr);
1058 ierr = PetscOptionsGetInt(NULL, NULL,
"-da_processors_x", &simCtx->
da_procs_x, NULL); CHKERRQ(ierr);
1059 ierr = PetscOptionsGetInt(NULL, NULL,
"-da_processors_y", &simCtx->
da_procs_y, NULL); CHKERRQ(ierr);
1060 ierr = PetscOptionsGetInt(NULL, NULL,
"-da_processors_z", &simCtx->
da_procs_z, NULL); CHKERRQ(ierr);
1063 char file_list_str[PETSC_MAX_PATH_LEN * 10];
1065 ierr = PetscOptionsGetString(NULL, NULL,
"-bcs_files", file_list_str,
sizeof(file_list_str), &bcs_flg); CHKERRQ(ierr);
1071 ierr = PetscFree(simCtx->
bcs_files[0]); CHKERRQ(ierr);
1072 ierr = PetscFree(simCtx->
bcs_files); CHKERRQ(ierr);
1079 ierr = PetscStrallocpy(file_list_str, &str_copy); CHKERRQ(ierr);
1082 token = strtok(str_copy,
",");
1085 token = strtok(NULL,
",");
1087 ierr = PetscFree(str_copy); CHKERRQ(ierr);
1091 ierr = PetscStrallocpy(file_list_str, &str_copy); CHKERRQ(ierr);
1092 token = strtok(str_copy,
",");
1094 ierr = PetscStrallocpy(token, &simCtx->
bcs_files[i]); CHKERRQ(ierr);
1095 token = strtok(NULL,
",");
1097 ierr = PetscFree(str_copy); CHKERRQ(ierr);
1105 PetscInt temp_les_model = (PetscInt)simCtx->
les;
1106 ierr = PetscOptionsGetInt(NULL, NULL,
"-les", &temp_les_model, NULL); CHKERRQ(ierr);
1107 PetscCheck(temp_les_model >=
NO_LES_MODEL && temp_les_model <=
WALE, PETSC_COMM_WORLD,
1108 PETSC_ERR_ARG_OUTOFRANGE,
1109 "-les must be 0 (none), 1 (constant_smagorinsky), 2 (dynamic_smagorinsky), "
1110 "3 (vreman), or 4 (wale); received %" PetscInt_FMT
".", temp_les_model);
1117 PetscInt requested_rans = 0;
1118 ierr = PetscOptionsGetInt(NULL, NULL,
"-rans", &requested_rans, NULL); CHKERRQ(ierr);
1119 PetscCheck(requested_rans == 0, PETSC_COMM_WORLD, PETSC_ERR_SUP,
1120 "RANS closures (-rans) are planned, not implemented: no transport equation is "
1121 "solved for them. Use an LES closure, or run laminar.");
1123 ierr = PetscOptionsGetInt(NULL, NULL,
"-wallfunction", &simCtx->
wallfunction, NULL); CHKERRQ(ierr);
1125 PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
1126 "-wallfunction must be 0 (none), 1 (log_law), 2 (werner), or 3 (cabot); received %" PetscInt_FMT
".",
1128 ierr = PetscOptionsGetInt(NULL, NULL,
"-les_gradient_model", &simCtx->
les_gradient_model, NULL); CHKERRQ(ierr);
1133 ierr = PetscOptionsGetInt(NULL, NULL,
"-numParticles", &simCtx->
np, NULL); CHKERRQ(ierr);
1135 ierr = PetscOptionsGetInt(NULL, NULL,
"-pinit", &temp_pinit, NULL); CHKERRQ(ierr);
1138 ierr = PetscOptionsGetInt(NULL, NULL,
"-interpolation_method", &temp_interp, NULL); CHKERRQ(ierr);
1142 ierr = PetscOptionsGetReal(NULL, NULL,
"-psrc_x", &simCtx->
psrc_x, NULL); CHKERRQ(ierr);
1143 ierr = PetscOptionsGetReal(NULL, NULL,
"-psrc_y", &simCtx->
psrc_y, NULL); CHKERRQ(ierr);
1144 ierr = PetscOptionsGetReal(NULL, NULL,
"-psrc_z", &simCtx->
psrc_z, NULL); CHKERRQ(ierr);
1151 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
"Invalid value for -particle_restart_mode. Must be 'load' or 'init'. You provided '%s'.", simCtx->
particleRestartMode);
1153 ierr = PetscOptionsGetInt(NULL, NULL,
"-particle_random_seed", &simCtx->
particleRandomSeed, NULL); CHKERRQ(ierr);
1154 PetscCheck(simCtx->
particleRandomSeed >= 0, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE,
1155 "-particle_random_seed must be non-negative (got %" PetscInt_FMT
").", simCtx->
particleRandomSeed);
1158 PetscCheck(!simCtx->
particleFieldPlan || simCtx->
np > 0, PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
1159 "Particle field initial values are configured but the run has no particles.");
1161 PETSC_ERR_ARG_WRONG,
1162 "Particle field initial values cannot be combined with the verification scalar source, "
1163 "which prescribes Psi at every step.");
1169 ierr = PetscOptionsGetInt(NULL, NULL,
"-logfreq", &simCtx->
LoggingFrequency, NULL); CHKERRQ(ierr);
1172 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);
1178 ierr = PetscOptionsGetString(NULL,NULL,
"-postprocessing_config_file",simCtx->
PostprocessingControlFile,PETSC_MAX_PATH_LEN,NULL); CHKERRQ(ierr);
1190 for (PetscInt i = 0; i < simCtx->
nAllowed; ++i) {
1198 if (simCtx->
tiout > 0) {
1205 if (simCtx->
np > 0) {
1218 ierr = PetscLogDefaultBegin(); CHKERRQ(ierr);
1219 ierr = PetscMemorySetGetMaximumUsage(); CHKERRQ(ierr);
1224 PetscFunctionReturn(0);
1228#define __FUNCT__ "PetscMkdirRecursive"
1234 PetscErrorCode ierr;
1235 char tmp_path[PETSC_MAX_PATH_LEN];
1240 PetscFunctionBeginUser;
1244 if (len >=
sizeof(tmp_path)) {
1245 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
"Path is too long to process: %s", path);
1247 strcpy(tmp_path, path);
1250 if (tmp_path[len - 1] ==
'/') {
1251 tmp_path[len - 1] = 0;
1255 for (p = tmp_path + 1; *p; p++) {
1260 ierr = PetscTestDirectory(tmp_path,
'r', &exists); CHKERRQ(ierr);
1262 ierr = PetscMkdir(tmp_path); CHKERRQ(ierr);
1270 ierr = PetscTestDirectory(tmp_path,
'r', &exists); CHKERRQ(ierr);
1272 ierr = PetscMkdir(tmp_path); CHKERRQ(ierr);
1275 PetscFunctionReturn(0);
1291 char a[PETSC_MAX_PATH_LEN], b[PETSC_MAX_PATH_LEN];
1292 const char *source[2];
1296 if (!first || !second || !*first || !*second)
return PETSC_FALSE;
1297 source[0] = first; source[1] = second;
1298 target[0] = a; target[1] = b;
1300 for (which = 0; which < 2; ++which) {
1301 const char *cursor = source[which];
1302 char *out = target[which];
1305 while (*cursor && used + 1 < PETSC_MAX_PATH_LEN) {
1307 while (*cursor ==
'/') ++cursor;
1308 segment = strcspn(cursor,
"/");
1309 if (segment == 0)
break;
1310 if (segment == 1 && cursor[0] ==
'.') { cursor += segment;
continue; }
1311 if (used) out[used++] =
'/';
1312 if (used + segment + 1 >= PETSC_MAX_PATH_LEN)
break;
1313 memcpy(out + used, cursor, segment);
1320 if (!*a || !*b)
return PETSC_FALSE;
1321 if (strcmp(a, b) == 0)
return PETSC_TRUE;
1322 if (strncmp(a, b, strlen(b)) == 0 && a[strlen(b)] ==
'/')
return PETSC_TRUE;
1323 if (strncmp(b, a, strlen(a)) == 0 && b[strlen(a)] ==
'/')
return PETSC_TRUE;
1344 if (!value || value[0] ==
'\0')
return PETSC_FALSE;
1345 for (cursor = value; *cursor; ++cursor) {
1346 if (isspace((
unsigned char)*cursor))
return PETSC_FALSE;
1347 if (*cursor ==
'"' || *cursor ==
'\'' || *cursor ==
'#')
return PETSC_FALSE;
1360 const char *cursor = value;
1362 if (!value)
return PETSC_FALSE;
1371 while (*cursor ==
'/') ++cursor;
1372 if (!*cursor)
break;
1373 segment = strcspn(cursor,
"/");
1374 if (!(segment == 1 && cursor[0] ==
'.')) {
1417 const char *cursor = value;
1419 PetscBool absolute = (PetscBool)(value[0] ==
'/');
1426 while (*cursor ==
'/') cursor++;
1427 if (!*cursor)
break;
1428 slash = strchr(cursor,
'/');
1429 len = slash ? (size_t)(slash - cursor) : strlen(cursor);
1431 if (len == 1 && cursor[0] ==
'.') {
1433 }
else if (len == 2 && cursor[0] ==
'.' && cursor[1] ==
'.') {
1434 char *last = strrchr(stack,
'/');
1435 if (last) { *last =
'\0'; used = strlen(stack); }
1436 else if (used) { stack[0] =
'\0'; used = 0; }
1438 if (used + len + 2 >= PETSC_MAX_PATH_LEN)
return PETSC_FALSE;
1439 stack[used++] =
'/';
1440 memcpy(stack + used, cursor, len);
1449 if (strlen(stack) + 1 >= size)
return PETSC_FALSE;
1450 strcpy(out, used ? stack :
"/");
1452 const char *relative = used ? stack + 1 :
".";
1453 if (strlen(relative) + 1 >= size)
return PETSC_FALSE;
1454 strcpy(out, relative);
1475 char *out,
size_t size,
char *scratch)
1481 char *absolute = scratch;
1482 char *normalized = scratch + PETSC_MAX_PATH_LEN;
1483 char *probe = scratch + 2 * PETSC_MAX_PATH_LEN;
1484 char *resolved = scratch + 3 * PETSC_MAX_PATH_LEN;
1485 char *lexical = scratch + 4 * PETSC_MAX_PATH_LEN;
1487 if (value[0] ==
'/') {
1488 if ((
size_t)snprintf(absolute, PETSC_MAX_PATH_LEN,
"%s", value) >= PETSC_MAX_PATH_LEN)
1491 if ((
size_t)snprintf(absolute, PETSC_MAX_PATH_LEN,
"%s/%s", cwd, value)
1492 >= PETSC_MAX_PATH_LEN)
1498 if ((
size_t)snprintf(probe, PETSC_MAX_PATH_LEN,
"%s", normalized) >= PETSC_MAX_PATH_LEN)
1504 if (realpath(probe, resolved)) {
1505 size_t consumed = strlen(probe);
1506 const char *tail = normalized + consumed;
1507 if ((
size_t)snprintf(out, size,
"%s%s", resolved, tail) >= size)
return PETSC_FALSE;
1511 last = strrchr(probe,
'/');
1512 if (!last)
return PETSC_FALSE;
1513 if (last == probe) { probe[1] =
'\0'; }
1514 else { *last =
'\0'; }
1515 if (strcmp(probe,
"/") == 0 && !realpath(probe, resolved))
return PETSC_FALSE;
1527 size_t len = strlen(ancestor);
1529 if (strcmp(ancestor, path) == 0)
return PETSC_TRUE;
1530 if (strcmp(ancestor,
"/") == 0)
return PETSC_TRUE;
1531 return (PetscBool)(strncmp(path, ancestor, len) == 0 && path[len] ==
'/');
1550 const char **reason)
1554 char *scratch = NULL;
1555 char *cwd, *resolved, *cwd_real;
1558 *reason =
"unknown";
1561 if (!log_dir || log_dir[0] ==
'\0') {
1562 *reason =
"is empty";
1566 *reason =
"contains whitespace, a quote, or a comment marker";
1570 *reason =
"collides with a reserved run directory";
1574 *reason =
"overlaps the solver output directory";
1584 if (log_dir[0] ==
'~') {
1585 *reason =
"starts with '~', which nothing expands - the options file is read by "
1586 "PETSc, not by a shell, so this would name a literal '~' directory "
1587 "inside the run. Give a real absolute path. This cannot be overridden";
1592 if (log_dir[0] !=
'/' &&
1593 (strcmp(log_dir,
"..") == 0 || strncmp(log_dir,
"../", 3) == 0 ||
1594 strstr(log_dir,
"/../") != NULL ||
1595 (strlen(log_dir) >= 3 && strcmp(log_dir + strlen(log_dir) - 3,
"/..") == 0))) {
1596 *reason =
"walks above the working directory by relative traversal, which cannot "
1601 if (PetscMalloc1(8 * PETSC_MAX_PATH_LEN, &scratch)) {
1602 *reason =
"cannot be checked because scratch space could not be allocated";
1606 resolved = scratch + PETSC_MAX_PATH_LEN;
1607 cwd_real = scratch + 2 * PETSC_MAX_PATH_LEN;
1610 if (!getcwd(cwd, PETSC_MAX_PATH_LEN)) {
1611 *reason =
"cannot be checked because the working directory could not be determined";
1612 }
else if (!realpath(cwd, cwd_real)) {
1613 *reason =
"cannot be checked because the working directory could not be resolved";
1615 scratch + 3 * PETSC_MAX_PATH_LEN)) {
1616 *reason =
"could not be resolved to a physical path";
1617 }
else if (strcmp(resolved, cwd_real) == 0) {
1619 *reason =
"resolves to the working directory itself; deleting it would destroy "
1620 "the run. This cannot be overridden";
1623 *reason =
"contains the working directory, so deleting it recursively would "
1624 "destroy the run and everything beside it. This cannot be overridden";
1628 }
else if (log_dir[0] ==
'/') {
1632 *reason =
"is an absolute path outside the working directory and no "
1633 "-allow_unsafe_log_dir authorization was given";
1636 *reason =
"is a relative name that resolves outside the working directory "
1637 "through a symlink, which cannot be authorized";
1670 PetscBool authorized,
const char **reason)
1680#define __FUNCT__ "SetupSimulationEnvironment"
1687 PetscErrorCode ierr;
1691 PetscFunctionBeginUser;
1692 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
1707 ierr = PetscSNPrintf(desc,
sizeof(desc),
"BCS file #%d", i + 1); CHKERRQ(ierr);
1739 "Initial-condition source directory", &exists); CHKERRQ(ierr);
1758 PetscBool unsafe_authorized = PETSC_FALSE;
1759 const char *refusal = NULL;
1760 ierr = PetscOptionsGetBool(NULL, NULL,
"-allow_unsafe_log_dir",
1761 &unsafe_authorized, NULL); CHKERRQ(ierr);
1763 unsafe_authorized, &refusal)) {
1764 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
1765 "Refusing to delete log directory '%s': it %s. Configure run "
1766 "directories through monitor.io.directories.",
1769 if (unsafe_authorized) {
1771 "Deleting log directory '%s' outside the working directory, "
1772 "authorized by -allow_unsafe_log_dir.\n", simCtx->
log_dir);
1776 ierr = PetscRMTree(simCtx->
log_dir);
1778 PetscError(PETSC_COMM_SELF, __LINE__,
__FUNCT__, __FILE__, ierr, PETSC_ERROR_INITIAL,
"Could not remove existing log directory '%s'. Check permissions.", simCtx->
log_dir);
1780 ierr = PetscMkdir(simCtx->
log_dir); CHKERRQ(ierr);
1784 ierr = PetscMkdir(simCtx->
log_dir); CHKERRQ(ierr);
1791 ierr = PetscTestDirectory(simCtx->
output_dir,
'r', &exists); CHKERRQ(ierr);
1794 ierr = PetscMkdir(simCtx->
output_dir); CHKERRQ(ierr);
1804 char path_buffer[PETSC_MAX_PATH_LEN];
1806 const char *last_slash_euler = strrchr(pps->
output_prefix,
'/');
1807 if(last_slash_euler){
1810 if(dir_len >=
sizeof(path_buffer)) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,
"Post-processing output prefix path is too long.");
1812 path_buffer[dir_len] =
'\0';
1814 ierr = PetscTestDirectory(path_buffer,
'r', &exists); CHKERRQ(ierr);
1825 if(last_slash_particle){
1828 if(dir_len >
sizeof(path_buffer)) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,
"Post-processing particle output prefix path is too long.");
1830 path_buffer[dir_len] =
'\0';
1832 ierr = PetscTestDirectory(path_buffer,
'r', &exists); CHKERRQ(ierr);
1845 if(last_slash_stats){
1848 if(dir_len >=
sizeof(path_buffer)) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,
"Post-processing statistics output prefix path is too long.");
1850 path_buffer[dir_len] =
'\0';
1852 ierr = PetscTestDirectory(path_buffer,
'r', &exists); CHKERRQ(ierr);
1864 ierr = MPI_Barrier(PETSC_COMM_WORLD); CHKERRMPI(ierr);
1872 char *info_name = NULL;
1873 FILE *info_file = NULL;
1874 ierr = PetscInfoGetFile(&info_name, &info_file); CHKERRQ(ierr);
1875 if (info_name && info_name[0] !=
'\0') {
1876 char reopen_name[PETSC_MAX_PATH_LEN];
1877 ierr = PetscStrncpy(reopen_name, info_name,
sizeof(reopen_name)); CHKERRQ(ierr);
1878 if (info_file && info_file != PETSC_STDOUT) {
1879 ierr = PetscFClose(PETSC_COMM_SELF, info_file); CHKERRQ(ierr);
1881 ierr = PetscInfoSetFile(reopen_name,
"w"); CHKERRQ(ierr);
1884 ierr = PetscFree(info_name); CHKERRQ(ierr);
1889 PetscFunctionReturn(0);
1893#define __FUNCT__ "AllocateContextHeirarchy"
1899 PetscErrorCode ierr;
1904 PetscFunctionBeginUser;
1916 mgctx = usermg->
mgctx;
1921 PetscInt *isc, *jsc, *ksc;
1922 ierr = PetscMalloc3(nblk, &isc, nblk, &jsc, nblk, &ksc); CHKERRQ(ierr);
1924 for (PetscInt i = 0; i < nblk; ++i) {
1925 isc[i] = 0; jsc[i] = 0; ksc[i] = 0;
1930 PetscInt n_opts_found = nblk;
1931 ierr = PetscOptionsGetIntArray(NULL, NULL,
"-mg_i_semi", isc, &n_opts_found, &found); CHKERRQ(ierr);
1933 n_opts_found = nblk;
1934 ierr = PetscOptionsGetIntArray(NULL, NULL,
"-mg_j_semi", jsc, &n_opts_found, &found); CHKERRQ(ierr);
1936 n_opts_found = nblk;
1937 ierr = PetscOptionsGetIntArray(NULL, NULL,
"-mg_k_semi", ksc, &n_opts_found, &found); CHKERRQ(ierr);
1940 for (PetscInt level = 0; level < simCtx->
mglevels; level++) {
1944 ierr = PetscMalloc(nblk *
sizeof(
UserCtx), &mgctx[level].user); CHKERRQ(ierr);
1946 ierr = PetscMemzero(mgctx[level].user, nblk *
sizeof(
UserCtx)); CHKERRQ(ierr);
1949 for (PetscInt bi = 0; bi < nblk; bi++) {
1954 currentUser->
simCtx = simCtx;
1958 currentUser->
_this = bi;
1962 currentUser->
isc = isc[bi];
1963 currentUser->
jsc = jsc[bi];
1964 currentUser->
ksc = ksc[bi];
1970 currentUser->
user_c = &mgctx[level-1].
user[bi];
1971 mgctx[level-1].
user[bi].
user_f = currentUser;
1980 for (PetscInt bi = 0; bi < nblk; ++bi) {
1986 ierr = PetscFree3(isc, jsc, ksc); CHKERRQ(ierr);
1990 PetscFunctionReturn(0);
1994#define __FUNCT__ "SetupGridAndSolvers"
2003 PetscErrorCode ierr;
2004 PetscFunctionBeginUser;
2026 PetscFunctionReturn(0);
2031#define __FUNCT__ "CreateAndInitializeAllVectors"
2038 PetscErrorCode ierr;
2043 PetscFunctionBeginUser;
2049 for (PetscInt level = usermg->
mglevels-1; level >=0; level--) {
2050 for (PetscInt bi = 0; bi < nblk; bi++) {
2053 if(!user->
da || !user->
fda) {
2054 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONGSTATE,
"DMs not properly initialized in UserCtx before vector creation.");
2061 ierr = DMCreateGlobalVector(user->
fda, &user->
Ucont); CHKERRQ(ierr); ierr = VecSet(user->
Ucont, 0.0); CHKERRQ(ierr);
2062 ierr = DMCreateGlobalVector(user->
fda, &user->
Ucat); CHKERRQ(ierr); ierr = VecSet(user->
Ucat, 0.0); CHKERRQ(ierr);
2063 ierr = DMCreateGlobalVector(user->
da, &user->
P); CHKERRQ(ierr); ierr = VecSet(user->
P, 0.0); CHKERRQ(ierr);
2064 ierr = DMCreateGlobalVector(user->
da, &user->
Nvert); CHKERRQ(ierr); ierr = VecSet(user->
Nvert, 0.0); CHKERRQ(ierr);
2066 ierr = DMCreateLocalVector(user->
fda, &user->
lUcont); CHKERRQ(ierr); ierr = VecSet(user->
lUcont, 0.0); CHKERRQ(ierr);
2067 ierr = DMCreateLocalVector(user->
fda, &user->
lUcat); CHKERRQ(ierr); ierr = VecSet(user->
lUcat, 0.0); CHKERRQ(ierr);
2068 ierr = DMCreateLocalVector(user->
da, &user->
lP); CHKERRQ(ierr); ierr = VecSet(user->
lP, 0.0); CHKERRQ(ierr);
2069 ierr = DMCreateLocalVector(user->
da, &user->
lNvert); CHKERRQ(ierr); ierr = VecSet(user->
lNvert, 0.0); CHKERRQ(ierr);
2072 ierr = VecDuplicate(user->
P,&user->
Diffusivity); CHKERRQ(ierr); ierr = VecSet(user->
Diffusivity, 0.0); CHKERRQ(ierr);
2078 ierr = VecDuplicate(user->
P, &user->
Phi); CHKERRQ(ierr); ierr = VecSet(user->
Phi, 0.0); CHKERRQ(ierr);
2079 ierr = VecDuplicate(user->
lP, &user->
lPhi); CHKERRQ(ierr); ierr = VecSet(user->
lPhi, 0.0); CHKERRQ(ierr);
2082 if (level == usermg->
mglevels - 1) {
2083 ierr = VecDuplicate(user->
Ucont, &user->
Ucont_o); CHKERRQ(ierr); ierr = VecSet(user->
Ucont_o, 0.0); CHKERRQ(ierr);
2084 ierr = VecDuplicate(user->
Ucont, &user->
Ucont_rm1); CHKERRQ(ierr); ierr = VecSet(user->
Ucont_rm1, 0.0); CHKERRQ(ierr);
2085 ierr = VecDuplicate(user->
Ucat, &user->
Ucat_o); CHKERRQ(ierr); ierr = VecSet(user->
Ucat_o, 0.0); CHKERRQ(ierr);
2086 ierr = VecDuplicate(user->
P, &user->
P_o); CHKERRQ(ierr); ierr = VecSet(user->
P_o, 0.0); CHKERRQ(ierr);
2087 ierr = VecDuplicate(user->
lUcont, &user->
lUcont_o); CHKERRQ(ierr); ierr = VecSet(user->
lUcont_o, 0.0); CHKERRQ(ierr);
2089 ierr = DMCreateLocalVector(user->
da, &user->
lNvert_o); CHKERRQ(ierr); ierr = VecSet(user->
lNvert_o, 0.0); CHKERRQ(ierr);
2090 ierr = VecDuplicate(user->
Nvert, &user->
Nvert_o); CHKERRQ(ierr); ierr = VecSet(user->
Nvert_o, 0.0); CHKERRQ(ierr);
2094 ierr = DMCreateGlobalVector(user->
fda, &user->
Csi); CHKERRQ(ierr); ierr = VecSet(user->
Csi, 0.0); CHKERRQ(ierr);
2095 ierr = VecDuplicate(user->
Csi, &user->
Eta); CHKERRQ(ierr); ierr = VecSet(user->
Eta, 0.0); CHKERRQ(ierr);
2096 ierr = VecDuplicate(user->
Csi, &user->
Zet); CHKERRQ(ierr); ierr = VecSet(user->
Zet, 0.0); CHKERRQ(ierr);
2097 ierr = DMCreateGlobalVector(user->
da, &user->
Aj); CHKERRQ(ierr); ierr = VecSet(user->
Aj, 0.0); CHKERRQ(ierr);
2099 ierr = DMCreateLocalVector(user->
fda, &user->
lCsi); CHKERRQ(ierr); ierr = VecSet(user->
lCsi, 0.0); CHKERRQ(ierr);
2100 ierr = VecDuplicate(user->
lCsi, &user->
lEta); CHKERRQ(ierr); ierr = VecSet(user->
lEta, 0.0); CHKERRQ(ierr);
2101 ierr = VecDuplicate(user->
lCsi, &user->
lZet); CHKERRQ(ierr); ierr = VecSet(user->
lZet, 0.0); CHKERRQ(ierr);
2102 ierr = DMCreateLocalVector(user->
da, &user->
lAj); CHKERRQ(ierr); ierr = VecSet(user->
lAj, 0.0); CHKERRQ(ierr);
2107 ierr = VecDuplicate(user->
Csi, &user->
ICsi); CHKERRQ(ierr); ierr = VecSet(user->
ICsi, 0.0); CHKERRQ(ierr);
2108 ierr = VecDuplicate(user->
Csi, &user->
IEta); CHKERRQ(ierr); ierr = VecSet(user->
IEta, 0.0); CHKERRQ(ierr);
2109 ierr = VecDuplicate(user->
Csi, &user->
IZet); CHKERRQ(ierr); ierr = VecSet(user->
IZet, 0.0); CHKERRQ(ierr);
2110 ierr = VecDuplicate(user->
Csi, &user->
JCsi); CHKERRQ(ierr); ierr = VecSet(user->
JCsi, 0.0); CHKERRQ(ierr);
2111 ierr = VecDuplicate(user->
Csi, &user->
JEta); CHKERRQ(ierr); ierr = VecSet(user->
JEta, 0.0); CHKERRQ(ierr);
2112 ierr = VecDuplicate(user->
Csi, &user->
JZet); CHKERRQ(ierr); ierr = VecSet(user->
JZet, 0.0); CHKERRQ(ierr);
2113 ierr = VecDuplicate(user->
Csi, &user->
KCsi); CHKERRQ(ierr); ierr = VecSet(user->
KCsi, 0.0); CHKERRQ(ierr);
2114 ierr = VecDuplicate(user->
Csi, &user->
KEta); CHKERRQ(ierr); ierr = VecSet(user->
KEta, 0.0); CHKERRQ(ierr);
2115 ierr = VecDuplicate(user->
Csi, &user->
KZet); CHKERRQ(ierr); ierr = VecSet(user->
KZet, 0.0); CHKERRQ(ierr);
2117 ierr = VecDuplicate(user->
Aj, &user->
IAj); CHKERRQ(ierr); ierr = VecSet(user->
IAj, 0.0); CHKERRQ(ierr);
2118 ierr = VecDuplicate(user->
Aj, &user->
JAj); CHKERRQ(ierr); ierr = VecSet(user->
JAj, 0.0); CHKERRQ(ierr);
2119 ierr = VecDuplicate(user->
Aj, &user->
KAj); CHKERRQ(ierr); ierr = VecSet(user->
KAj, 0.0); CHKERRQ(ierr);
2121 ierr = VecDuplicate(user->
lCsi, &user->
lICsi); CHKERRQ(ierr); ierr = VecSet(user->
lICsi, 0.0); CHKERRQ(ierr);
2122 ierr = VecDuplicate(user->
lCsi, &user->
lIEta); CHKERRQ(ierr); ierr = VecSet(user->
lIEta, 0.0); CHKERRQ(ierr);
2123 ierr = VecDuplicate(user->
lCsi, &user->
lIZet); CHKERRQ(ierr); ierr = VecSet(user->
lIZet, 0.0); CHKERRQ(ierr);
2124 ierr = VecDuplicate(user->
lCsi, &user->
lJCsi); CHKERRQ(ierr); ierr = VecSet(user->
lJCsi, 0.0); CHKERRQ(ierr);
2125 ierr = VecDuplicate(user->
lCsi, &user->
lJEta); CHKERRQ(ierr); ierr = VecSet(user->
lJEta, 0.0); CHKERRQ(ierr);
2126 ierr = VecDuplicate(user->
lCsi, &user->
lJZet); CHKERRQ(ierr); ierr = VecSet(user->
lJZet, 0.0); CHKERRQ(ierr);
2127 ierr = VecDuplicate(user->
lCsi, &user->
lKCsi); CHKERRQ(ierr); ierr = VecSet(user->
lKCsi, 0.0); CHKERRQ(ierr);
2128 ierr = VecDuplicate(user->
lCsi, &user->
lKEta); CHKERRQ(ierr); ierr = VecSet(user->
lKEta, 0.0); CHKERRQ(ierr);
2129 ierr = VecDuplicate(user->
lCsi, &user->
lKZet); CHKERRQ(ierr); ierr = VecSet(user->
lKZet, 0.0); CHKERRQ(ierr);
2131 ierr = VecDuplicate(user->
lAj, &user->
lIAj); CHKERRQ(ierr); ierr = VecSet(user->
lIAj, 0.0); CHKERRQ(ierr);
2132 ierr = VecDuplicate(user->
lAj, &user->
lJAj); CHKERRQ(ierr); ierr = VecSet(user->
lJAj, 0.0); CHKERRQ(ierr);
2133 ierr = VecDuplicate(user->
lAj, &user->
lKAj); CHKERRQ(ierr); ierr = VecSet(user->
lKAj, 0.0); CHKERRQ(ierr);
2136 ierr = DMCreateGlobalVector(user->
fda, &user->
Cent); CHKERRQ(ierr); ierr = VecSet(user->
Cent, 0.0); CHKERRQ(ierr);
2137 ierr = DMCreateLocalVector(user->
fda, &user->
lCent); CHKERRQ(ierr); ierr = VecSet(user->
lCent, 0.0); CHKERRQ(ierr);
2139 ierr = VecDuplicate(user->
Cent, &user->
GridSpace); CHKERRQ(ierr); ierr = VecSet(user->
GridSpace, 0.0); CHKERRQ(ierr);
2140 ierr = VecDuplicate(user->
lCent, &user->
lGridSpace); CHKERRQ(ierr); ierr = VecSet(user->
lGridSpace, 0.0); CHKERRQ(ierr);
2142 ierr = VecDuplicate(user->
Cent, &user->
Centx); CHKERRQ(ierr); ierr = VecSet(user->
Centx, 0.0); CHKERRQ(ierr);
2143 ierr = VecDuplicate(user->
Cent, &user->
Centy); CHKERRQ(ierr); ierr = VecSet(user->
Centy, 0.0); CHKERRQ(ierr);
2144 ierr = VecDuplicate(user->
Cent, &user->
Centz); CHKERRQ(ierr); ierr = VecSet(user->
Centz, 0.0); CHKERRQ(ierr);
2145 ierr = VecDuplicate(user->
lCent, &user->
lCentx); CHKERRQ(ierr); ierr = VecSet(user->
lCentx, 0.0); CHKERRQ(ierr);
2146 ierr = VecDuplicate(user->
lCent, &user->
lCenty); CHKERRQ(ierr); ierr = VecSet(user->
lCenty, 0.0); CHKERRQ(ierr);
2147 ierr = VecDuplicate(user->
lCent, &user->
lCentz); CHKERRQ(ierr); ierr = VecSet(user->
lCentz, 0.0); CHKERRQ(ierr);
2152 ierr = DMCreateGlobalVector(user->
da, &user->
Nu_t); CHKERRQ(ierr); ierr = VecSet(user->
Nu_t, 0.0); CHKERRQ(ierr);
2153 ierr = DMCreateLocalVector(user->
da, &user->
lNu_t); CHKERRQ(ierr); ierr = VecSet(user->
lNu_t, 0.0); CHKERRQ(ierr);
2160 ierr = DMCreateGlobalVector(user->
da,&user->
CS); CHKERRQ(ierr); ierr = VecSet(user->
CS,0.0); CHKERRQ(ierr);
2161 ierr = DMCreateLocalVector(user->
da,&user->
lCs); CHKERRQ(ierr); ierr = VecSet(user->
lCs,0.0); CHKERRQ(ierr);
2184 ierr = DMCreateGlobalVector(user->
da, &user->
Nu_Wall); CHKERRQ(ierr);
2185 ierr = VecSet(user->
Nu_Wall, 0.0); CHKERRQ(ierr);
2186 ierr = DMCreateLocalVector(user->
da, &user->
lNu_Wall); CHKERRQ(ierr);
2187 ierr = VecSet(user->
lNu_Wall, 0.0); CHKERRQ(ierr);
2194 ierr = DMCreateGlobalVector(user->
da,&user->
Psi); CHKERRQ(ierr); ierr = VecSet(user->
Psi,0.0); CHKERRQ(ierr);
2195 ierr = DMCreateLocalVector(user->
da,&user->
lPsi); CHKERRQ(ierr); ierr = VecSet(user->
lPsi,0.0); CHKERRQ(ierr);
2200 ierr = DMCreateGlobalVector(user->
fda, &user->
Bcs.
Ubcs); CHKERRQ(ierr);
2201 ierr = VecSet(user->
Bcs.
Ubcs, 0.0); CHKERRQ(ierr);
2202 ierr = DMCreateGlobalVector(user->
fda, &user->
Bcs.
Uch); CHKERRQ(ierr);
2203 ierr = VecSet(user->
Bcs.
Uch, 0.0); CHKERRQ(ierr);
2218 "Allocated accumulators for %d statistics window(s).\n",
2226 if (level == usermg->
mglevels - 1) {
2243 ierr = DMCreateGlobalVector(user->
da, &user->
PostScalar); CHKERRQ(ierr);
2244 ierr = VecSet(user->
PostScalar, 0.0); CHKERRQ(ierr);
2245 ierr = DMCreateLocalVector(user->
da, &user->
lPostScalar); CHKERRQ(ierr);
2246 ierr = VecSet(user->
lPostScalar, 0.0); CHKERRQ(ierr);
2249 ierr = DMCreateGlobalVector(user->
fda, &user->
PostVector); CHKERRQ(ierr);
2250 ierr = VecSet(user->
PostVector, 0.0); CHKERRQ(ierr);
2251 ierr = DMCreateLocalVector(user->
fda, &user->
lPostVector); CHKERRQ(ierr);
2252 ierr = VecSet(user->
lPostVector, 0.0); CHKERRQ(ierr);
2261 ierr = VecDuplicate(user->
P, &user->
P_nodal); CHKERRQ(ierr);
2262 ierr = VecSet(user->
P_nodal, 0.0); CHKERRQ(ierr);
2264 ierr = VecDuplicate(user->
Ucat, &user->
Ucat_nodal); CHKERRQ(ierr);
2265 ierr = VecSet(user->
Ucat_nodal, 0.0); CHKERRQ(ierr);
2267 ierr = VecDuplicate(user->
P, &user->
Qcrit); CHKERRQ(ierr);
2268 ierr = VecSet(user->
Qcrit, 0.0); CHKERRQ(ierr);
2269 ierr = DMCreateLocalVector(user->
da, &user->
lQcrit); CHKERRQ(ierr);
2270 ierr = VecSet(user->
lQcrit, 0.0); CHKERRQ(ierr);
2271 ierr = VecDuplicate(user->
P, &user->
Qcrit_nodal); CHKERRQ(ierr);
2272 ierr = VecSet(user->
Qcrit_nodal, 0.0); CHKERRQ(ierr);
2277 ierr = VecDuplicate(user->
Psi, &user->
Psi_nodal); CHKERRQ(ierr);
2278 ierr = VecSet(user->
Psi_nodal, 0.0); CHKERRQ(ierr);
2306 PetscFunctionReturn(0);
2310#define __FUNCT__ "RepairPeriodicNormalFaceGhosts"
2320 PetscInt dof,
char face_direction,
2321 PetscBool component_staggered)
2324 PetscInt xs, xe, ys, ye, zs, ze;
2325 PetscInt gxs, gxe, gys, gye, gzs, gze;
2326 PetscInt mx, my, mz;
2328 PetscFunctionBeginUser;
2329 if (!face_direction && !component_staggered) PetscFunctionReturn(0);
2331 PetscCall(DMDAGetLocalInfo(dm, &info));
2332 xs = info.xs; xe = info.xs + info.xm;
2333 ys = info.ys; ye = info.ys + info.ym;
2334 zs = info.zs; ze = info.zs + info.zm;
2335 gxs = info.gxs; gxe = info.gxs + info.gxm;
2336 gys = info.gys; gye = info.gys + info.gym;
2337 gzs = info.gzs; gze = info.gzs + info.gzm;
2338 mx = info.mx; my = info.my; mz = info.mz;
2340 if (component_staggered) {
2342 PetscCall(DMDAVecGetArray(dm, local_vec, &array));
2345 PetscCheck(gxs <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2346 "Periodic Ucont.x ghost repair requires DMDA stencil width at least 3.");
2347 for (PetscInt k = gzs; k < gze; k++)
for (PetscInt j = gys; j < gye; j++)
2348 array[k][j][-1].x = array[k][j][-3].x;
2351 PetscCheck(gxe > mx + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2352 "Periodic Ucont.x ghost repair requires DMDA stencil width at least 3.");
2353 for (PetscInt k = gzs; k < gze; k++)
for (PetscInt j = gys; j < gye; j++)
2354 array[k][j][mx].x = array[k][j][mx + 2].x;
2357 PetscCheck(gys <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2358 "Periodic Ucont.y ghost repair requires DMDA stencil width at least 3.");
2359 for (PetscInt k = gzs; k < gze; k++)
for (PetscInt i = gxs; i < gxe; i++)
2360 array[k][-1][i].y = array[k][-3][i].y;
2363 PetscCheck(gye > my + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2364 "Periodic Ucont.y ghost repair requires DMDA stencil width at least 3.");
2365 for (PetscInt k = gzs; k < gze; k++)
for (PetscInt i = gxs; i < gxe; i++)
2366 array[k][my][i].y = array[k][my + 2][i].y;
2369 PetscCheck(gzs <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2370 "Periodic Ucont.z ghost repair requires DMDA stencil width at least 3.");
2371 for (PetscInt j = gys; j < gye; j++)
for (PetscInt i = gxs; i < gxe; i++)
2372 array[-1][j][i].z = array[-3][j][i].z;
2375 PetscCheck(gze > mz + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2376 "Periodic Ucont.z ghost repair requires DMDA stencil width at least 3.");
2377 for (PetscInt j = gys; j < gye; j++)
for (PetscInt i = gxs; i < gxe; i++)
2378 array[mz][j][i].z = array[mz + 2][j][i].z;
2381 PetscCall(DMDAVecRestoreArray(dm, local_vec, &array));
2382 PetscFunctionReturn(0);
2387 PetscCall(DMDAVecGetArray(dm, local_vec, &array));
2389 if (face_direction ==
'i') {
2391 PetscCheck(gxs <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2392 "Periodic I-face ghost repair requires DMDA stencil width at least 3.");
2393 for (PetscInt k = gzs; k < gze; k++)
for (PetscInt j = gys; j < gye; j++)
2394 array[k][j][-1] = array[k][j][-3];
2397 PetscCheck(gxe > mx + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2398 "Periodic I-face ghost repair requires DMDA stencil width at least 3.");
2399 for (PetscInt k = gzs; k < gze; k++)
for (PetscInt j = gys; j < gye; j++)
2400 array[k][j][mx] = array[k][j][mx + 2];
2402 }
else if (face_direction ==
'j') {
2404 PetscCheck(gys <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2405 "Periodic J-face ghost repair requires DMDA stencil width at least 3.");
2406 for (PetscInt k = gzs; k < gze; k++)
for (PetscInt i = gxs; i < gxe; i++)
2407 array[k][-1][i] = array[k][-3][i];
2410 PetscCheck(gye > my + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2411 "Periodic J-face ghost repair requires DMDA stencil width at least 3.");
2412 for (PetscInt k = gzs; k < gze; k++)
for (PetscInt i = gxs; i < gxe; i++)
2413 array[k][my][i] = array[k][my + 2][i];
2415 }
else if (face_direction ==
'k') {
2417 PetscCheck(gzs <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2418 "Periodic K-face ghost repair requires DMDA stencil width at least 3.");
2419 for (PetscInt j = gys; j < gye; j++)
for (PetscInt i = gxs; i < gxe; i++)
2420 array[-1][j][i] = array[-3][j][i];
2423 PetscCheck(gze > mz + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2424 "Periodic K-face ghost repair requires DMDA stencil width at least 3.");
2425 for (PetscInt j = gys; j < gye; j++)
for (PetscInt i = gxs; i < gxe; i++)
2426 array[mz][j][i] = array[mz + 2][j][i];
2430 PetscCall(DMDAVecRestoreArray(dm, local_vec, &array));
2433 PetscCall(DMDAVecGetArray(dm, local_vec, &array));
2435 if (face_direction ==
'i') {
2437 PetscCheck(gxs <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2438 "Periodic I-face ghost repair requires DMDA stencil width at least 3.");
2439 for (PetscInt k = gzs; k < gze; k++)
for (PetscInt j = gys; j < gye; j++)
2440 array[k][j][-1] = array[k][j][-3];
2443 PetscCheck(gxe > mx + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2444 "Periodic I-face ghost repair requires DMDA stencil width at least 3.");
2445 for (PetscInt k = gzs; k < gze; k++)
for (PetscInt j = gys; j < gye; j++)
2446 array[k][j][mx] = array[k][j][mx + 2];
2448 }
else if (face_direction ==
'j') {
2450 PetscCheck(gys <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2451 "Periodic J-face ghost repair requires DMDA stencil width at least 3.");
2452 for (PetscInt k = gzs; k < gze; k++)
for (PetscInt i = gxs; i < gxe; i++)
2453 array[k][-1][i] = array[k][-3][i];
2456 PetscCheck(gye > my + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2457 "Periodic J-face ghost repair requires DMDA stencil width at least 3.");
2458 for (PetscInt k = gzs; k < gze; k++)
for (PetscInt i = gxs; i < gxe; i++)
2459 array[k][my][i] = array[k][my + 2][i];
2461 }
else if (face_direction ==
'k') {
2463 PetscCheck(gzs <= -3, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2464 "Periodic K-face ghost repair requires DMDA stencil width at least 3.");
2465 for (PetscInt j = gys; j < gye; j++)
for (PetscInt i = gxs; i < gxe; i++)
2466 array[-1][j][i] = array[-3][j][i];
2469 PetscCheck(gze > mz + 2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ,
2470 "Periodic K-face ghost repair requires DMDA stencil width at least 3.");
2471 for (PetscInt j = gys; j < gye; j++)
for (PetscInt i = gxs; i < gxe; i++)
2472 array[mz][j][i] = array[mz + 2][j][i];
2476 PetscCall(DMDAVecRestoreArray(dm, local_vec, &array));
2479 PetscFunctionReturn(0);
2483#define __FUNCT__ "UpdateLocalGhosts"
2491 PetscErrorCode ierr;
2494 const char *field_name;
2499 char face_direction =
'\0';
2500 PetscBool component_staggered = PETSC_FALSE;
2502 PetscFunctionBeginUser;
2504 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
2505 ierr =
FieldGetView(user, field_id, &field_view); CHKERRQ(ierr);
2507 PETSC_COMM_SELF, PETSC_ERR_SUP,
2508 "Field '%s' does not support ghost updates.",
2518 face_direction =
'i';
2521 face_direction =
'j';
2524 face_direction =
'k';
2527 component_staggered = PETSC_TRUE;
2532 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB,
2533 "Field '%s' has an invalid ghost synchronization class.", field_name);
2539 rank, field_name, (
void*)dm, (
void*)globalVec, (
void*)localVec);
2545 PetscReal norm_global_before;
2546 ierr = VecNorm(globalVec, NORM_INFINITY, &norm_global_before); CHKERRQ(ierr);
2547 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Max norm '%s' (Global) BEFORE Ghost Update: %g\n", field_name, norm_global_before);
2556 ierr = DMGlobalToLocalBegin(dm, globalVec, INSERT_VALUES, localVec); CHKERRQ(ierr);
2557 ierr = DMGlobalToLocalEnd(dm, globalVec, INSERT_VALUES, localVec); CHKERRQ(ierr);
2559 component_staggered); CHKERRQ(ierr);
2566 PetscReal norm_local_after;
2567 ierr = VecNorm(localVec, NORM_INFINITY, &norm_local_after); CHKERRQ(ierr);
2573 PetscMPIInt rank_test;
2574 MPI_Comm_rank(PETSC_COMM_WORLD, &rank_test);
2577 DMDALocalInfo info_check;
2578 ierr = DMDAGetLocalInfo(dm, &info_check); CHKERRQ(ierr);
2581 Cmpnts ***lUcat_arr_test = NULL;
2582 PetscErrorCode ierr_test = 0;
2584 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Rank %d: Testing '%s' access immediately after ghost update...\n", rank_test, field_name);
2585 ierr_test = DMDAVecGetArrayDOFRead(dm, localVec, &lUcat_arr_test);
2588 LOG_ALLOW(
LOCAL,
LOG_ERROR,
"Rank %d: ERROR %d getting '%s' array after ghost update!\n", rank_test, ierr_test, field_name);
2589 }
else if (!lUcat_arr_test) {
2590 LOG_ALLOW(
LOCAL,
LOG_ERROR,
"Rank %d: ERROR NULL pointer getting '%s' array after ghost update!\n", rank_test, field_name);
2594 PetscInt k_int = info_check.zs + (info_check.zm > 1 ? 1 : 0);
2595 PetscInt j_int = info_check.ys + (info_check.ym > 1 ? 1 : 0);
2596 PetscInt i_int = info_check.xs + (info_check.xm > 1 ? 1 : 0);
2602 if (k_int >= info_check.mz - 1) {
2603 k_int = info_check.mz - 2;
2610 if (j_int >= info_check.my - 1) {
2611 j_int = info_check.my - 2;
2618 if (i_int >= info_check.mx - 1) {
2619 i_int = info_check.mx - 2;
2626 if (k_int >= info_check.zs && k_int < info_check.zs + info_check.zm &&
2627 j_int >= info_check.ys && j_int < info_check.ys + info_check.ym &&
2628 i_int >= info_check.xs && i_int < info_check.xs + info_check.xm)
2630 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);
2631 Cmpnts test_val_owned_interior = lUcat_arr_test[k_int][j_int][i_int];
2632 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Rank %d: SUCCESS reading owned interior: x=%g\n", rank_test, test_val_owned_interior.
x);
2634 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);
2639 PetscInt k_bnd = info_check.zs;
2640 PetscInt j_bnd = info_check.ys;
2641 PetscInt i_bnd = info_check.xs;
2642 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);
2643 Cmpnts test_val_owned_boundary = lUcat_arr_test[k_bnd][j_bnd][i_bnd];
2644 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Rank %d: SUCCESS reading owned boundary: x=%g\n", rank_test, test_val_owned_boundary.
x);
2648 if (info_check.zs > 0) {
2649 PetscInt k_ghost = info_check.zs - 1;
2650 PetscInt j_ghost = info_check.ys;
2651 PetscInt i_ghost = info_check.xs;
2652 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
"Rank %d: Attempting test read GHOST [%d][%d][%d] (Global)\n", rank_test, k_ghost, j_ghost, i_ghost);
2653 Cmpnts test_val_ghost = lUcat_arr_test[k_ghost][j_ghost][i_ghost];
2660 ierr_test = DMDAVecRestoreArrayDOFRead(dm, localVec, &lUcat_arr_test);
2661 if(ierr_test){
LOG_ALLOW(
LOCAL,
LOG_ERROR,
"Rank %d: ERROR %d restoring '%s' array after test read!\n", rank_test, ierr_test, field_name); }
2669 PetscFunctionReturn(0);
2673#define __FUNCT__ "SetupBoundaryConditions"
2680 PetscErrorCode ierr;
2681 PetscFunctionBeginUser;
2687 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Parsing BC configuration files and initializing boundary condition data structures.\n");
2689 for (PetscInt bi = 0; bi < simCtx->
block_number; bi++) {
2693 const char *current_bc_filename = simCtx->
bcs_files[bi];
2706 for (PetscInt level = simCtx->
usermg.
mglevels - 1; level >= 0; level--) {
2708 for (PetscInt bi = 0; bi < simCtx->
block_number; bi++) {
2723 for (PetscInt bi = 0; bi < simCtx->
block_number; bi++) {
2735 PetscFunctionReturn(0);
2744 PetscErrorCode ierr;
2746 PetscReal *dataContiguous;
2751 ierr = PetscCalloc1(nz, &data); CHKERRQ(ierr);
2754 ierr = PetscCalloc1(nz * ny, &data[0]); CHKERRQ(ierr);
2755 for (k = 1; k < nz; k++) {
2756 data[k] = data[0] + k * ny;
2760 ierr = PetscCalloc1(nz * ny * nx, &dataContiguous); CHKERRQ(ierr);
2763 for (k = 0; k < nz; k++) {
2764 for (j = 0; j < ny; j++) {
2765 data[k][j] = dataContiguous + (k * ny + j) * nx;
2770 PetscFunctionReturn(0);
2779 PetscErrorCode ierr;
2784 if (!array || !array[0] || !array[0][0] ) {
2790 ierr = PetscFree(array[0]); CHKERRQ(ierr);
2792 ierr = PetscFree(array); CHKERRQ(ierr);
2794 PetscFunctionReturn(0);
2801 ierr = PetscFree(array[0][0]); CHKERRQ(ierr);
2805 ierr = PetscFree(array[0]); CHKERRQ(ierr);
2809 ierr = PetscFree(array); CHKERRQ(ierr);
2811 PetscFunctionReturn(0);
2822 PetscErrorCode ierr;
2830 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
2833 ierr = PetscCalloc1(nz, &data); CHKERRQ(ierr);
2835 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
" [Rank %d] memory allocated for outermost layer (%d k-layer pointers).\n",rank,nz);
2838 ierr = PetscCalloc1(nz * ny, &data[0]); CHKERRQ(ierr);
2839 for (k = 1; k < nz; k++) {
2840 data[k] = data[0] + k * ny;
2846 ierr = PetscCalloc1(nz * ny * nx, &dataContiguous); CHKERRQ(ierr);
2848 LOG_ALLOW(
GLOBAL,
LOG_DEBUG,
"[Rank %d] memory allocated for contigous block of %dx%dx%d Cmpnts structures).\n",rank,nz,ny,nx);
2851 for (k = 0; k < nz; k++) {
2852 for (j = 0; j < ny; j++) {
2853 data[k][j] = dataContiguous + (k * ny + j) * nx;
2861 PetscFunctionReturn(0);
2872 PetscErrorCode ierr;
2878 if (!array || !array[0] || !array[0][0] ) {
2899 Cmpnts *dataContiguous = array[0][0];
2900 ierr = PetscFree(dataContiguous); CHKERRQ(ierr);
2903 ierr = PetscFree(array[0]); CHKERRQ(ierr);
2907 ierr = PetscFree(array); CHKERRQ(ierr);
2909 PetscFunctionReturn(0);
2917 ierr = PetscFree(array[0][0]); CHKERRQ(ierr);
2921 ierr = PetscFree(array[0]); CHKERRQ(ierr);
2925 ierr = PetscFree(array); CHKERRQ(ierr);
2927 PetscFunctionReturn(0);
2931#define __FUNCT__ "GetOwnedCellRange"
2938 PetscInt *xs_cell_global_out,
2939 PetscInt *xm_cell_local_out)
2941 PetscErrorCode ierr = 0;
2942 PetscInt xs_node_global_rank;
2943 PetscInt num_nodes_owned_rank;
2944 PetscInt GlobalNodesInDim_from_info;
2946 PetscFunctionBeginUser;
2949 if (!info_nodes || !xs_cell_global_out || !xm_cell_local_out) {
2950 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Null pointer passed to GetOwnedCellRange.");
2955 xs_node_global_rank = info_nodes->xs;
2956 num_nodes_owned_rank = info_nodes->xm;
2957 GlobalNodesInDim_from_info = info_nodes->mx;
2958 }
else if (dim == 1) {
2959 xs_node_global_rank = info_nodes->ys;
2960 num_nodes_owned_rank = info_nodes->ym;
2961 GlobalNodesInDim_from_info = info_nodes->my;
2962 }
else if (dim == 2) {
2963 xs_node_global_rank = info_nodes->zs;
2964 num_nodes_owned_rank = info_nodes->zm;
2965 GlobalNodesInDim_from_info = info_nodes->mz;
2967 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE,
"Invalid dimension %d in GetOwnedCellRange. Must be 0, 1, or 2.", dim);
2973 const PetscInt physical_nodes_in_dim = GlobalNodesInDim_from_info - 1;
2977 if (physical_nodes_in_dim <= 1) {
2978 *xs_cell_global_out = xs_node_global_rank;
2979 *xm_cell_local_out = 0;
2980 PetscFunctionReturn(0);
2985 *xs_cell_global_out = xs_node_global_rank;
2988 if (num_nodes_owned_rank == 0) {
2989 *xm_cell_local_out = 0;
2997 PetscInt first_owned_origin = xs_node_global_rank;
3001 PetscInt last_node_owned_by_rank = xs_node_global_rank + num_nodes_owned_rank - 1;
3005 PetscInt last_possible_origin_global_idx = physical_nodes_in_dim - 2;
3010 PetscInt actual_last_origin_this_rank_can_form = PetscMin(last_node_owned_by_rank, last_possible_origin_global_idx);
3015 if (first_owned_origin > actual_last_origin_this_rank_can_form) {
3016 *xm_cell_local_out = 0;
3020 *xm_cell_local_out = actual_last_origin_this_rank_can_form - first_owned_origin + 1;
3024 PetscFunctionReturn(ierr);
3028#define __FUNCT__ "ComputeAndStoreNeighborRanks"
3035 PetscErrorCode ierr;
3038 const PetscMPIInt *neighbor_ranks_ptr;
3040 PetscFunctionBeginUser;
3042 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
3043 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
3047 if (!user || !user->
da) {
3048 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx or user->da is NULL in ComputeAndStoreNeighborRanks.");
3053 ierr = DMDAGetNeighbors(user->
da, &neighbor_ranks_ptr); CHKERRQ(ierr);
3056 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",
3058 neighbor_ranks_ptr[12], neighbor_ranks_ptr[14],
3059 neighbor_ranks_ptr[10], neighbor_ranks_ptr[16],
3060 neighbor_ranks_ptr[4], neighbor_ranks_ptr[22],
3061 (
int)MPI_PROC_NULL);
3073 if (neighbor_ranks_ptr[13] != rank) {
3074 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",
3075 rank, neighbor_ranks_ptr[13], rank);
3081 PetscMPIInt temp_neighbor;
3083 temp_neighbor = neighbor_ranks_ptr[12];
3084 if (temp_neighbor < 0 || temp_neighbor >= size) {
3085 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);
3091 temp_neighbor = neighbor_ranks_ptr[14];
3092 if (temp_neighbor < 0 || temp_neighbor >= size) {
3093 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);
3099 temp_neighbor = neighbor_ranks_ptr[10];
3100 if (temp_neighbor < 0 || temp_neighbor >= size) {
3101 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);
3107 temp_neighbor = neighbor_ranks_ptr[16];
3108 if (temp_neighbor < 0 || temp_neighbor >= size) {
3110 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);
3116 temp_neighbor = neighbor_ranks_ptr[4];
3117 if (temp_neighbor < 0 || temp_neighbor >= size) {
3118 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);
3124 temp_neighbor = neighbor_ranks_ptr[22];
3125 if (temp_neighbor < 0 || temp_neighbor >= size) {
3126 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);
3136 PetscSynchronizedFlush(PETSC_COMM_WORLD, PETSC_STDOUT);
3140 PetscFunctionReturn(0);
3144#define __FUNCT__ "SetDMDAProcLayout"
3151 PetscErrorCode ierr;
3152 PetscMPIInt size, rank;
3153 PetscInt px = PETSC_DECIDE, py = PETSC_DECIDE, pz = PETSC_DECIDE;
3154 PetscBool px_set = PETSC_FALSE, py_set = PETSC_FALSE, pz_set = PETSC_FALSE;
3159 px_set = PETSC_TRUE;
3164 py_set = PETSC_TRUE;
3169 pz_set = PETSC_TRUE;
3173 PetscFunctionBeginUser;
3175 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size); CHKERRQ(ierr);
3176 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank); CHKERRQ(ierr);
3177 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Rank %d: Configuring DMDA processor layout for %d total processes.\n", rank, size);
3181 if (px_set && py_set && pz_set) {
3182 if (px * py * pz != size) {
3183 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP,
3184 "Specified processor layout %d x %d x %d = %d does not match MPI size %d",
3185 px, py, pz, px * py * pz, size);
3188 }
else if (px_set || py_set || pz_set) {
3190 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Using partially specified processor layout: %d x %d x %d (PETSC_DECIDE for unspecified)\n", px, py, pz);
3192 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Using fully automatic processor layout (PETSC_DECIDE x PETSC_DECIDE x PETSC_DECIDE)\n");
3195 if ((px_set && px <= 0) || (py_set && py <= 0) || (pz_set && pz <= 0)) {
3196 SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE,
"Specified processor counts must be positive.");
3201 ierr = DMDASetNumProcs(dm, px, py, pz); CHKERRQ(ierr);
3216 PetscFunctionReturn(0);
3220#define __FUNCT__ "SetupDomainRankInfo"
3229 PetscErrorCode ierr;
3231 PetscInt size = simCtx->
size;
3234 PetscFunctionBeginUser;
3242 for (
int bi = 0; bi < nblk; bi++) {
3249 ierr = PetscMalloc1(size * nblk, &final_bboxlist); CHKERRQ(ierr);
3252 for (
int bi = 0; bi < nblk; bi++) {
3270 for (
int r = 0; r < size; r++) {
3272 final_bboxlist[bi * size + r] = block_bboxlist[r];
3278 free(block_bboxlist);
3291 PetscFunctionReturn(0);
3295#define __FUNCT__ "Contra2Cart"
3302 PetscErrorCode ierr;
3304 Cmpnts ***lcsi_arr, ***leta_arr, ***lzet_arr;
3307 PetscReal ***lnvert_arr;
3308 PetscReal ***laj_arr;
3310 PetscFunctionBeginUser;
3317 ierr = DMDAGetLocalInfo(user->
fda, &info); CHKERRQ(ierr);
3319 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"Contra2Cart requires lUcont, lCsi/Eta/Zet, lNvert, and Ucat to be non-NULL.");
3324 ierr = DMDAVecGetArrayRead(user->
fda, user->
lUcont, &lucont_arr); CHKERRQ(ierr);
3325 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCsi, &lcsi_arr); CHKERRQ(ierr);
3326 ierr = DMDAVecGetArrayRead(user->
fda, user->
lEta, &leta_arr); CHKERRQ(ierr);
3327 ierr = DMDAVecGetArrayRead(user->
fda, user->
lZet, &lzet_arr); CHKERRQ(ierr);
3328 ierr = DMDAVecGetArrayRead(user->
da, user->
lNvert, &lnvert_arr); CHKERRQ(ierr);
3329 ierr = DMDAVecGetArrayRead(user->
da, user->
lAj, &laj_arr); CHKERRQ(ierr);
3334 ierr = DMDAVecGetArray(user->
fda, user->
Ucat, &gucat_arr); CHKERRQ(ierr);
3341 PetscInt i_start = (info.xs == 0) ? info.xs + 1 : info.xs;
3342 PetscInt i_end = (info.xs + info.xm == info.mx) ? info.xs + info.xm - 1 : info.xs + info.xm;
3344 PetscInt j_start = (info.ys == 0) ? info.ys + 1 : info.ys;
3345 PetscInt j_end = (info.ys + info.ym == info.my) ? info.ys + info.ym - 1 : info.ys + info.ym;
3347 PetscInt k_start = (info.zs == 0) ? info.zs + 1 : info.zs;
3348 PetscInt k_end = (info.zs + info.zm == info.mz) ? info.zs + info.zm - 1 : info.zs + info.zm;
3352 for (PetscInt k_cell = k_start; k_cell < k_end; ++k_cell) {
3353 for (PetscInt j_cell = j_start; j_cell < j_end; ++j_cell) {
3354 for (PetscInt i_cell = i_start; i_cell < i_end; ++i_cell) {
3361 PetscReal mat[3][3];
3365 mat[0][0] = 0.5 * (lcsi_arr[k_cell][j_cell][i_cell-1].
x + lcsi_arr[k_cell][j_cell][i_cell].
x);
3366 mat[0][1] = 0.5 * (lcsi_arr[k_cell][j_cell][i_cell-1].
y + lcsi_arr[k_cell][j_cell][i_cell].
y);
3367 mat[0][2] = 0.5 * (lcsi_arr[k_cell][j_cell][i_cell-1].
z + lcsi_arr[k_cell][j_cell][i_cell].
z);
3369 mat[1][0] = 0.5 * (leta_arr[k_cell][j_cell-1][i_cell].
x + leta_arr[k_cell][j_cell][i_cell].
x);
3370 mat[1][1] = 0.5 * (leta_arr[k_cell][j_cell-1][i_cell].
y + leta_arr[k_cell][j_cell][i_cell].
y);
3371 mat[1][2] = 0.5 * (leta_arr[k_cell][j_cell-1][i_cell].
z + leta_arr[k_cell][j_cell][i_cell].
z);
3373 mat[2][0] = 0.5 * (lzet_arr[k_cell-1][j_cell][i_cell].
x + lzet_arr[k_cell][j_cell][i_cell].
x);
3374 mat[2][1] = 0.5 * (lzet_arr[k_cell-1][j_cell][i_cell].
y + lzet_arr[k_cell][j_cell][i_cell].
y);
3375 mat[2][2] = 0.5 * (lzet_arr[k_cell-1][j_cell][i_cell].
z + lzet_arr[k_cell][j_cell][i_cell].
z);
3380 q[0] = 0.5 * (lucont_arr[k_cell][j_cell][i_cell-1].
x + lucont_arr[k_cell][j_cell][i_cell].
x);
3381 q[1] = 0.5 * (lucont_arr[k_cell][j_cell-1][i_cell].
y + lucont_arr[k_cell][j_cell][i_cell].
y);
3382 q[2] = 0.5 * (lucont_arr[k_cell-1][j_cell][i_cell].
z + lucont_arr[k_cell][j_cell][i_cell].
z);
3385 PetscReal det = mat[0][0] * (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) -
3386 mat[0][1] * (mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0]) +
3387 mat[0][2] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]);
3389 if (PetscAbsReal(det) < 1.0e-18) {
3390 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);
3393 PetscReal det_inv = 1.0 / det;
3395 PetscReal det0 = q[0] * (mat[1][1] * mat[2][2] - mat[1][2] * mat[2][1]) -
3396 q[1] * (mat[0][1] * mat[2][2] - mat[0][2] * mat[2][1]) +
3397 q[2] * (mat[0][1] * mat[1][2] - mat[0][2] * mat[1][1]);
3399 PetscReal det1 = -q[0] * (mat[1][0] * mat[2][2] - mat[1][2] * mat[2][0]) +
3400 q[1] * (mat[0][0] * mat[2][2] - mat[0][2] * mat[2][0]) -
3401 q[2] * (mat[0][0] * mat[1][2] - mat[0][2] * mat[1][0]);
3403 PetscReal det2 = q[0] * (mat[1][0] * mat[2][1] - mat[1][1] * mat[2][0]) -
3404 q[1] * (mat[0][0] * mat[2][1] - mat[0][1] * mat[2][0]) +
3405 q[2] * (mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]);
3409 gucat_arr[k_cell][j_cell][i_cell].
x = det0 * det_inv;
3410 gucat_arr[k_cell][j_cell][i_cell].
y = det1 * det_inv;
3411 gucat_arr[k_cell][j_cell][i_cell].
z = det2 * det_inv;
3417 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lUcont, &lucont_arr); CHKERRQ(ierr);
3418 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCsi, &lcsi_arr); CHKERRQ(ierr);
3419 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lEta, &leta_arr); CHKERRQ(ierr);
3420 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lZet, &lzet_arr); CHKERRQ(ierr);
3421 ierr = DMDAVecRestoreArrayRead(user->
da, user->
lNvert, &lnvert_arr); CHKERRQ(ierr);
3422 ierr = DMDAVecRestoreArrayRead(user->
da, user->
lAj, &laj_arr); CHKERRQ(ierr);
3423 ierr = DMDAVecRestoreArray(user->
fda, user->
Ucat, &gucat_arr); CHKERRQ(ierr);
3427 PetscFunctionReturn(0);
3431#define __FUNCT__ "Cart2Contra"
3437 PetscErrorCode ierr;
3439 const Cmpnts ***ucat_arr, ***csi_arr, ***eta_arr, ***zet_arr;
3442 PetscFunctionBeginUser;
3445 ierr = DMDAGetLocalInfo(user->
fda, &info); CHKERRQ(ierr);
3446 ierr = DMDAVecGetArrayRead(user->
fda, user->
lUcat, &ucat_arr); CHKERRQ(ierr);
3447 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCsi, &csi_arr); CHKERRQ(ierr);
3448 ierr = DMDAVecGetArrayRead(user->
fda, user->
lEta, &eta_arr); CHKERRQ(ierr);
3449 ierr = DMDAVecGetArrayRead(user->
fda, user->
lZet, &zet_arr); CHKERRQ(ierr);
3450 ierr = DMDAVecGetArray(user->
fda, user->
Ucont, &ucont_arr); CHKERRQ(ierr);
3452 const PetscInt i_start = PetscMax(info.xs, 1);
3453 const PetscInt j_start = PetscMax(info.ys, 1);
3454 const PetscInt k_start = PetscMax(info.zs, 1);
3455 const PetscInt i_end = PetscMin(info.xs + info.xm, info.mx - 1);
3456 const PetscInt j_end = PetscMin(info.ys + info.ym, info.my - 1);
3457 const PetscInt k_end = PetscMin(info.zs + info.zm, info.mz - 1);
3459 for (PetscInt k = k_start; k < k_end; k++) {
3460 for (PetscInt j = j_start; j < j_end; j++) {
3461 for (PetscInt i = i_start; i < i_end; i++) {
3463 0.5 * (ucat_arr[k][j][i].
x + ucat_arr[k][j][i + 1].
x),
3464 0.5 * (ucat_arr[k][j][i].y + ucat_arr[k][j][i + 1].y),
3465 0.5 * (ucat_arr[k][j][i].
z + ucat_arr[k][j][i + 1].
z)
3468 0.5 * (ucat_arr[k][j][i].
x + ucat_arr[k][j + 1][i].
x),
3469 0.5 * (ucat_arr[k][j][i].y + ucat_arr[k][j + 1][i].y),
3470 0.5 * (ucat_arr[k][j][i].
z + ucat_arr[k][j + 1][i].
z)
3473 0.5 * (ucat_arr[k][j][i].
x + ucat_arr[k + 1][j][i].
x),
3474 0.5 * (ucat_arr[k][j][i].y + ucat_arr[k + 1][j][i].y),
3475 0.5 * (ucat_arr[k][j][i].
z + ucat_arr[k + 1][j][i].
z)
3477 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;
3478 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;
3479 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;
3484 ierr = DMDAVecRestoreArray(user->
fda, user->
Ucont, &ucont_arr); CHKERRQ(ierr);
3485 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lZet, &zet_arr); CHKERRQ(ierr);
3486 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lEta, &eta_arr); CHKERRQ(ierr);
3487 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCsi, &csi_arr); CHKERRQ(ierr);
3488 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lUcat, &ucat_arr); CHKERRQ(ierr);
3491 PetscFunctionReturn(0);
3495#define __FUNCT__ "UniformCart2Contra"
3506 PetscErrorCode ierr;
3507 PetscFunctionBeginUser;
3512 const Cmpnts ***csi_arr, ***eta_arr, ***zet_arr;
3514 ierr = DMDAGetLocalInfo(user->
fda, &info); CHKERRQ(ierr);
3515 ierr = DMDAVecGetArray(user->
fda, user->
Ucont, &ucont_arr); CHKERRQ(ierr);
3516 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCsi, &csi_arr); CHKERRQ(ierr);
3517 ierr = DMDAVecGetArrayRead(user->
fda, user->
lEta, &eta_arr); CHKERRQ(ierr);
3518 ierr = DMDAVecGetArrayRead(user->
fda, user->
lZet, &zet_arr); CHKERRQ(ierr);
3520 const PetscInt xs = info.xs, xe = info.xs + info.xm;
3521 const PetscInt ys = info.ys, ye = info.ys + info.ym;
3522 const PetscInt zs = info.zs, ze = info.zs + info.zm;
3524 for (PetscInt k = zs; k < ze; k++) {
3525 for (PetscInt j = ys; j < ye; j++) {
3526 for (PetscInt i = xs; i < xe; i++) {
3527 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;
3528 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;
3529 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;
3534 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lZet, &zet_arr); CHKERRQ(ierr);
3535 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lEta, &eta_arr); CHKERRQ(ierr);
3536 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCsi, &csi_arr); CHKERRQ(ierr);
3537 ierr = DMDAVecRestoreArray(user->
fda, user->
Ucont, &ucont_arr); CHKERRQ(ierr);
3540 (
double)u, (
double)v, (
double)w);
3542 PetscFunctionReturn(0);
3546#define __FUNCT__ "SetupDomainCellDecompositionMap"
3553 PetscErrorCode ierr;
3554 DMDALocalInfo local_node_info;
3556 PetscMPIInt rank, size;
3558 PetscFunctionBeginUser;
3563 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"UserCtx pointer is NULL in SetupDomainCellDecompositionMap.");
3566 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
"user->da is not initialized in SetupDomainCellDecompositionMap.");
3569 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
3570 ierr = MPI_Comm_size(PETSC_COMM_WORLD, &size); CHKERRQ(ierr);
3576 ierr = DMDAGetLocalInfo(user->
da, &local_node_info); CHKERRQ(ierr);
3598 ierr = MPI_Allgather(&my_cell_info,
sizeof(
RankCellInfo), MPI_BYTE,
3600 PETSC_COMM_WORLD); CHKERRQ(ierr);
3605 PetscFunctionReturn(0);
3609#define __FUNCT__ "BinarySearchInt64"
3616PetscErrorCode
BinarySearchInt64(PetscInt n,
const PetscInt64 arr[], PetscInt64 key, PetscBool *found)
3618 PetscInt low = 0, high = n - 1;
3620 PetscFunctionBeginUser;
3625 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Output pointer 'found' is NULL in PetscBinarySearchInt64.");
3627 if (n > 0 && !arr) {
3628 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"Input array 'arr' is NULL for n > 0.");
3632 *found = PETSC_FALSE;
3635 while (low <= high) {
3637 PetscInt mid = low + (high - low) / 2;
3639 if (arr[mid] == key) {
3640 *found = PETSC_TRUE;
3644 if (arr[mid] < key) {
3652 PetscFunctionReturn(0);
3659static PetscInt
Gidx(PetscInt i, PetscInt j, PetscInt k,
UserCtx *user)
3662 DMDALocalInfo info = user->
info;
3664 PetscInt mx = info.mx, my = info.my;
3667 DMDAGetAO(user->
da, &ao);
3668 nidx=i+j*mx+k*mx*my;
3670 AOApplicationToPetsc(ao,1,&nidx);
3677#define __FUNCT__ "ComputeDivergence"
3687 DM da = user->
da, fda = user->
fda;
3688 DMDALocalInfo info = user->
info;
3692 PetscInt xs = info.xs, xe = info.xs + info.xm;
3693 PetscInt ys = info.ys, ye = info.ys + info.ym;
3694 PetscInt zs = info.zs, ze = info.zs + info.zm;
3695 PetscInt mx = info.mx, my = info.my, mz = info.mz;
3697 PetscInt lxs, lys, lzs, lxe, lye, lze;
3701 PetscReal ***div, ***aj, ***nvert,***p;
3709 if (xs==0) lxs = xs+1;
3710 if (ys==0) lys = ys+1;
3711 if (zs==0) lzs = zs+1;
3713 if (xe==mx) lxe = xe-1;
3714 if (ye==my) lye = ye-1;
3715 if (ze==mz) lze = ze-1;
3717 PetscFunctionBeginUser;
3720 DMDAVecGetArray(fda,user->
lUcont, &ucont);
3721 DMDAVecGetArray(da, user->
lAj, &aj);
3722 VecDuplicate(user->
P, &Div);
3723 DMDAVecGetArray(da, Div, &div);
3724 DMDAVecGetArray(da, user->
lNvert, &nvert);
3725 DMDAVecGetArray(da, user->
P, &p);
3726 for (k=lzs; k<lze; k++) {
3727 for (j=lys; j<lye; j++){
3728 for (i=lxs; i<lxe; i++) {
3729 if (k==10 && j==10 && i==1){
3730 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]);
3733 if (k==10 && j==10 && i==mx-3)
3734 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]);
3738 DMDAVecRestoreArray(da, user->
P, &p);
3741 for (k=lzs; k<lze; k++) {
3742 for (j=lys; j<lye; j++) {
3743 for (i=lxs; i<lxe; i++) {
3744 maxdiv = fabs((ucont[k][j][i].x - ucont[k][j][i-1].x +
3745 ucont[k][j][i].y - ucont[k][j-1][i].y +
3746 ucont[k][j][i].z - ucont[k-1][j][i].z)*aj[k][j][i]);
3747 if (nvert[k][j][i] + nvert[k+1][j][i] + nvert[k-1][j][i] +
3748 nvert[k][j+1][i] + nvert[k][j-1][i] +
3749 nvert[k][j][i+1] + nvert[k][j][i-1] > 0.1) maxdiv = 0.;
3750 div[k][j][i] = maxdiv;
3758 for (j=ys; j<ye; j++) {
3759 for (i=xs; i<xe; i++) {
3767 for (j=ys; j<ye; j++) {
3768 for (i=xs; i<xe; i++) {
3776 for (k=zs; k<ze; k++) {
3777 for (j=ys; j<ye; j++) {
3785 for (k=zs; k<ze; k++) {
3786 for (j=ys; j<ye; j++) {
3794 for (k=zs; k<ze; k++) {
3795 for (i=xs; i<xe; i++) {
3803 for (k=zs; k<ze; k++) {
3804 for (i=xs; i<xe; i++) {
3809 DMDAVecRestoreArray(da, Div, &div);
3810 PetscInt MaxFlatIndex;
3812 VecMax(Div, &MaxFlatIndex, &maxdiv);
3814 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"[Step %d]] The Maximum Divergence is %e at flat index %d.\n",ti,maxdiv,MaxFlatIndex);
3819 for (k=zs; k<ze; k++) {
3820 for (j=ys; j<ye; j++) {
3821 for (i=xs; i<xe; i++) {
3822 if (
Gidx(i,j,k,user) == MaxFlatIndex) {
3823 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"[Step %d] The Maximum Divergence(%e) is at location [%d][%d][%d]. \n", ti, maxdiv,k,j,i);
3833 DMDAVecRestoreArray(da, user->
lNvert, &nvert);
3834 DMDAVecRestoreArray(fda, user->
lUcont, &ucont);
3835 DMDAVecRestoreArray(da, user->
lAj, &aj);
3839 PetscFunctionReturn(0);
3843#define __FUNCT__ "InitializeRandomGenerators"
3852 PetscErrorCode ierr;
3854 PetscFunctionBeginUser;
3856 MPI_Comm_rank(PETSC_COMM_WORLD, &rank);
3859 ierr = PetscRandomCreate(PETSC_COMM_SELF, randx); CHKERRQ(ierr);
3860 ierr = PetscRandomSetType((*randx), PETSCRAND48); CHKERRQ(ierr);
3865 ierr = PetscRandomSetSeed(*randx, base_seed + (
unsigned long)rank); CHKERRQ(ierr);
3866 ierr = PetscRandomSeed(*randx); CHKERRQ(ierr);
3870 ierr = PetscRandomCreate(PETSC_COMM_SELF, randy); CHKERRQ(ierr);
3871 ierr = PetscRandomSetType((*randy), PETSCRAND48); CHKERRQ(ierr);
3873 ierr = PetscRandomSetSeed(*randy, base_seed + 55545UL + (
unsigned long)rank); CHKERRQ(ierr);
3874 ierr = PetscRandomSeed(*randy); CHKERRQ(ierr);
3878 ierr = PetscRandomCreate(PETSC_COMM_SELF, randz); CHKERRQ(ierr);
3879 ierr = PetscRandomSetType((*randz), PETSCRAND48); CHKERRQ(ierr);
3881 ierr = PetscRandomSetSeed(*randz, base_seed + 41976UL + (
unsigned long)rank); CHKERRQ(ierr);
3882 ierr = PetscRandomSeed(*randz); CHKERRQ(ierr);
3886 PetscFunctionReturn(0);
3890#define __FUNCT__ "InitializeLogicalSpaceRNGs"
3896 PetscErrorCode ierr;
3898 PetscFunctionBeginUser;
3902 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
3905 ierr = PetscRandomCreate(PETSC_COMM_SELF, rand_logic_i); CHKERRQ(ierr);
3906 ierr = PetscRandomSetType((*rand_logic_i), PETSCRAND48); CHKERRQ(ierr);
3907 ierr = PetscRandomSetInterval(*rand_logic_i, 0.0, 1.0); CHKERRQ(ierr);
3909 ierr = PetscRandomSetSeed(*rand_logic_i, (
unsigned long)base_seed + 190056UL + (
unsigned long)rank); CHKERRQ(ierr);
3910 ierr = PetscRandomSeed(*rand_logic_i); CHKERRQ(ierr);
3914 ierr = PetscRandomCreate(PETSC_COMM_SELF, rand_logic_j); CHKERRQ(ierr);
3915 ierr = PetscRandomSetType((*rand_logic_j), PETSCRAND48); CHKERRQ(ierr);
3916 ierr = PetscRandomSetInterval(*rand_logic_j, 0.0, 1.0); CHKERRQ(ierr);
3917 ierr = PetscRandomSetSeed(*rand_logic_j, (
unsigned long)base_seed + 190057UL + (
unsigned long)rank); CHKERRQ(ierr);
3918 ierr = PetscRandomSeed(*rand_logic_j); CHKERRQ(ierr);
3922 ierr = PetscRandomCreate(PETSC_COMM_SELF, rand_logic_k); CHKERRQ(ierr);
3923 ierr = PetscRandomSetType((*rand_logic_k), PETSCRAND48); CHKERRQ(ierr);
3924 ierr = PetscRandomSetInterval(*rand_logic_k, 0.0, 1.0); CHKERRQ(ierr);
3925 ierr = PetscRandomSetSeed(*rand_logic_k, (
unsigned long)base_seed + 190058UL + (
unsigned long)rank); CHKERRQ(ierr);
3926 ierr = PetscRandomSeed(*rand_logic_k); CHKERRQ(ierr);
3931 PetscFunctionReturn(0);
3935#define __FUNCT__ "InitializeBrownianRNG"
3941 PetscErrorCode ierr;
3944 PetscFunctionBeginUser;
3947 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
3950 ierr = PetscRandomCreate(PETSC_COMM_WORLD, &simCtx->
BrownianMotionRNG); CHKERRQ(ierr);
3951 ierr = PetscRandomSetType(simCtx->
BrownianMotionRNG, PETSCRAND48); CHKERRQ(ierr);
3955 ierr = PetscRandomSetInterval(simCtx->
BrownianMotionRNG, 0.0, 1.0); CHKERRQ(ierr);
3962 + (
unsigned long)rank * 987654321UL
3963 + (
unsigned long)simCtx->
StartStep * 1000003UL;
3970 PetscFunctionReturn(0);
3976#define __FUNCT__ "TransformScalarDerivativesToPhysical"
3987 PetscReal dPhi_dcsi,
3988 PetscReal dPhi_deta,
3989 PetscReal dPhi_dzet,
3993 gradPhi->
x = jacobian * (dPhi_dcsi * csi_metrics.
x + dPhi_deta * eta_metrics.
x + dPhi_dzet * zet_metrics.
x);
3996 gradPhi->
y = jacobian * (dPhi_dcsi * csi_metrics.
y + dPhi_deta * eta_metrics.
y + dPhi_dzet * zet_metrics.
y);
3999 gradPhi->
z = jacobian * (dPhi_dcsi * csi_metrics.
z + dPhi_deta * eta_metrics.
z + dPhi_dzet * zet_metrics.
z);
4003#define __FUNCT__ "TransformDerivativesToPhysical"
4012 dudx->
x = jacobian * (deriv_csi.
x * csi_metrics.
x + deriv_eta.
x * eta_metrics.
x + deriv_zet.
x * zet_metrics.
x);
4013 dudx->
y = jacobian * (deriv_csi.
x * csi_metrics.
y + deriv_eta.
x * eta_metrics.
y + deriv_zet.
x * zet_metrics.
y);
4014 dudx->
z = jacobian * (deriv_csi.
x * csi_metrics.
z + deriv_eta.
x * eta_metrics.
z + deriv_zet.
x * zet_metrics.
z);
4016 dvdx->
x = jacobian * (deriv_csi.
y * csi_metrics.
x + deriv_eta.
y * eta_metrics.
x + deriv_zet.
y * zet_metrics.
x);
4017 dvdx->
y = jacobian * (deriv_csi.
y * csi_metrics.
y + deriv_eta.
y * eta_metrics.
y + deriv_zet.
y * zet_metrics.
y);
4018 dvdx->
z = jacobian * (deriv_csi.
y * csi_metrics.
z + deriv_eta.
y * eta_metrics.
z + deriv_zet.
y * zet_metrics.
z);
4020 dwdx->
x = jacobian * (deriv_csi.
z * csi_metrics.
x + deriv_eta.
z * eta_metrics.
x + deriv_zet.
z * zet_metrics.
x);
4021 dwdx->
y = jacobian * (deriv_csi.
z * csi_metrics.
y + deriv_eta.
z * eta_metrics.
y + deriv_zet.
z * zet_metrics.
y);
4022 dwdx->
z = jacobian * (deriv_csi.
z * csi_metrics.
z + deriv_eta.
z * eta_metrics.
z + deriv_zet.
z * zet_metrics.
z);
4026#define __FUNCT__ "ComputeScalarFieldDerivatives"
4032 PetscReal ***field_data,
Cmpnts *grad)
4034 PetscErrorCode ierr;
4035 Cmpnts ***csi, ***eta, ***zet;
4037 PetscReal d_csi, d_eta, d_zet;
4039 PetscFunctionBeginUser;
4042 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCsi, &csi); CHKERRQ(ierr);
4043 ierr = DMDAVecGetArrayRead(user->
fda, user->
lEta, &eta); CHKERRQ(ierr);
4044 ierr = DMDAVecGetArrayRead(user->
fda, user->
lZet, &zet); CHKERRQ(ierr);
4045 ierr = DMDAVecGetArrayRead(user->
da, user->
lAj, &jac); CHKERRQ(ierr);
4049 d_csi = 0.5 * (field_data[k][j][i+1] - field_data[k][j][i-1]);
4050 d_eta = 0.5 * (field_data[k][j+1][i] - field_data[k][j-1][i]);
4051 d_zet = 0.5 * (field_data[k+1][j][i] - field_data[k-1][j][i]);
4055 csi[k][j][i], eta[k][j][i], zet[k][j][i],
4056 d_csi, d_eta, d_zet,
4060 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCsi, &csi); CHKERRQ(ierr);
4061 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lEta, &eta); CHKERRQ(ierr);
4062 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lZet, &zet); CHKERRQ(ierr);
4063 ierr = DMDAVecRestoreArrayRead(user->
da, user->
lAj, &jac); CHKERRQ(ierr);
4065 PetscFunctionReturn(0);
4069#define __FUNCT__ "ComputeVectorFieldDerivatives"
4077 PetscErrorCode ierr;
4078 Cmpnts ***csi, ***eta, ***zet;
4080 PetscFunctionBeginUser;
4083 ierr = DMDAVecGetArrayRead(user->
fda, user->
lCsi, &csi); CHKERRQ(ierr);
4084 ierr = DMDAVecGetArrayRead(user->
fda, user->
lEta, &eta); CHKERRQ(ierr);
4085 ierr = DMDAVecGetArrayRead(user->
fda, user->
lZet, &zet); CHKERRQ(ierr);
4086 ierr = DMDAVecGetArrayRead(user->
da, user->
lAj, &jac); CHKERRQ(ierr);
4089 Cmpnts deriv_csi, deriv_eta, deriv_zet;
4090 deriv_csi.
x = (field_data[k][j][i+1].
x - field_data[k][j][i-1].
x) * 0.5;
4091 deriv_csi.
y = (field_data[k][j][i+1].
y - field_data[k][j][i-1].
y) * 0.5;
4092 deriv_csi.
z = (field_data[k][j][i+1].
z - field_data[k][j][i-1].
z) * 0.5;
4094 deriv_eta.
x = (field_data[k][j+1][i].
x - field_data[k][j-1][i].
x) * 0.5;
4095 deriv_eta.
y = (field_data[k][j+1][i].
y - field_data[k][j-1][i].
y) * 0.5;
4096 deriv_eta.
z = (field_data[k][j+1][i].
z - field_data[k][j-1][i].
z) * 0.5;
4098 deriv_zet.
x = (field_data[k+1][j][i].
x - field_data[k-1][j][i].
x) * 0.5;
4099 deriv_zet.
y = (field_data[k+1][j][i].
y - field_data[k-1][j][i].
y) * 0.5;
4100 deriv_zet.
z = (field_data[k+1][j][i].
z - field_data[k-1][j][i].
z) * 0.5;
4104 deriv_csi, deriv_eta, deriv_zet,
4108 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lCsi, &csi); CHKERRQ(ierr);
4109 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lEta, &eta); CHKERRQ(ierr);
4110 ierr = DMDAVecRestoreArrayRead(user->
fda, user->
lZet, &zet); CHKERRQ(ierr);
4111 ierr = DMDAVecRestoreArrayRead(user->
da, user->
lAj, &jac); CHKERRQ(ierr);
4113 PetscFunctionReturn(0);
4123#define __FUNCT__ "DestroyUserVectors"
4130 PetscErrorCode ierr;
4131 PetscFunctionBeginUser;
4134 if (user->
Ucont) { ierr = VecDestroy(&user->
Ucont); CHKERRQ(ierr); }
4135 if (user->
lUcont) { ierr = VecDestroy(&user->
lUcont); CHKERRQ(ierr); }
4136 if (user->
Ucat) { ierr = VecDestroy(&user->
Ucat); CHKERRQ(ierr); }
4137 if (user->
lUcat) { ierr = VecDestroy(&user->
lUcat); CHKERRQ(ierr); }
4138 if (user->
P) { ierr = VecDestroy(&user->
P); CHKERRQ(ierr); }
4139 if (user->
lP) { ierr = VecDestroy(&user->
lP); CHKERRQ(ierr); }
4140 if (user->
Nvert) { ierr = VecDestroy(&user->
Nvert); CHKERRQ(ierr); }
4141 if (user->
lNvert) { ierr = VecDestroy(&user->
lNvert); CHKERRQ(ierr); }
4150 if (user->
Phi) { ierr = VecDestroy(&user->
Phi); CHKERRQ(ierr); }
4151 if (user->
lPhi) { ierr = VecDestroy(&user->
lPhi); CHKERRQ(ierr); }
4154 if (user->
Ucont_o) { ierr = VecDestroy(&user->
Ucont_o); CHKERRQ(ierr); }
4156 if (user->
Ucat_o) { ierr = VecDestroy(&user->
Ucat_o); CHKERRQ(ierr); }
4157 if (user->
P_o) { ierr = VecDestroy(&user->
P_o); CHKERRQ(ierr); }
4158 if (user->
Nvert_o) { ierr = VecDestroy(&user->
Nvert_o); CHKERRQ(ierr); }
4164 if (user->
Csi) { ierr = VecDestroy(&user->
Csi); CHKERRQ(ierr); }
4165 if (user->
Eta) { ierr = VecDestroy(&user->
Eta); CHKERRQ(ierr); }
4166 if (user->
Zet) { ierr = VecDestroy(&user->
Zet); CHKERRQ(ierr); }
4167 if (user->
Aj) { ierr = VecDestroy(&user->
Aj); CHKERRQ(ierr); }
4168 if (user->
lCsi) { ierr = VecDestroy(&user->
lCsi); CHKERRQ(ierr); }
4169 if (user->
lEta) { ierr = VecDestroy(&user->
lEta); CHKERRQ(ierr); }
4170 if (user->
lZet) { ierr = VecDestroy(&user->
lZet); CHKERRQ(ierr); }
4171 if (user->
lAj) { ierr = VecDestroy(&user->
lAj); CHKERRQ(ierr); }
4174 if (user->
ICsi) { ierr = VecDestroy(&user->
ICsi); CHKERRQ(ierr); }
4175 if (user->
IEta) { ierr = VecDestroy(&user->
IEta); CHKERRQ(ierr); }
4176 if (user->
IZet) { ierr = VecDestroy(&user->
IZet); CHKERRQ(ierr); }
4177 if (user->
JCsi) { ierr = VecDestroy(&user->
JCsi); CHKERRQ(ierr); }
4178 if (user->
JEta) { ierr = VecDestroy(&user->
JEta); CHKERRQ(ierr); }
4179 if (user->
JZet) { ierr = VecDestroy(&user->
JZet); CHKERRQ(ierr); }
4180 if (user->
KCsi) { ierr = VecDestroy(&user->
KCsi); CHKERRQ(ierr); }
4181 if (user->
KEta) { ierr = VecDestroy(&user->
KEta); CHKERRQ(ierr); }
4182 if (user->
KZet) { ierr = VecDestroy(&user->
KZet); CHKERRQ(ierr); }
4183 if (user->
IAj) { ierr = VecDestroy(&user->
IAj); CHKERRQ(ierr); }
4184 if (user->
JAj) { ierr = VecDestroy(&user->
JAj); CHKERRQ(ierr); }
4185 if (user->
KAj) { ierr = VecDestroy(&user->
KAj); CHKERRQ(ierr); }
4186 if (user->
lICsi) { ierr = VecDestroy(&user->
lICsi); CHKERRQ(ierr); }
4187 if (user->
lIEta) { ierr = VecDestroy(&user->
lIEta); CHKERRQ(ierr); }
4188 if (user->
lIZet) { ierr = VecDestroy(&user->
lIZet); CHKERRQ(ierr); }
4189 if (user->
lJCsi) { ierr = VecDestroy(&user->
lJCsi); CHKERRQ(ierr); }
4190 if (user->
lJEta) { ierr = VecDestroy(&user->
lJEta); CHKERRQ(ierr); }
4191 if (user->
lJZet) { ierr = VecDestroy(&user->
lJZet); CHKERRQ(ierr); }
4192 if (user->
lKCsi) { ierr = VecDestroy(&user->
lKCsi); CHKERRQ(ierr); }
4193 if (user->
lKEta) { ierr = VecDestroy(&user->
lKEta); CHKERRQ(ierr); }
4194 if (user->
lKZet) { ierr = VecDestroy(&user->
lKZet); CHKERRQ(ierr); }
4195 if (user->
lIAj) { ierr = VecDestroy(&user->
lIAj); CHKERRQ(ierr); }
4196 if (user->
lJAj) { ierr = VecDestroy(&user->
lJAj); CHKERRQ(ierr); }
4197 if (user->
lKAj) { ierr = VecDestroy(&user->
lKAj); CHKERRQ(ierr); }
4200 if (user->
Cent) { ierr = VecDestroy(&user->
Cent); CHKERRQ(ierr); }
4201 if (user->
lCent) { ierr = VecDestroy(&user->
lCent); CHKERRQ(ierr); }
4204 if (user->
Centx) { ierr = VecDestroy(&user->
Centx); CHKERRQ(ierr); }
4205 if (user->
Centy) { ierr = VecDestroy(&user->
Centy); CHKERRQ(ierr); }
4206 if (user->
Centz) { ierr = VecDestroy(&user->
Centz); CHKERRQ(ierr); }
4207 if (user->
lCentx) { ierr = VecDestroy(&user->
lCentx); CHKERRQ(ierr); }
4208 if (user->
lCenty) { ierr = VecDestroy(&user->
lCenty); CHKERRQ(ierr); }
4209 if (user->
lCentz) { ierr = VecDestroy(&user->
lCentz); CHKERRQ(ierr); }
4212 if (user->
Nu_t) { ierr = VecDestroy(&user->
Nu_t); CHKERRQ(ierr); }
4213 if (user->
lNu_t) { ierr = VecDestroy(&user->
lNu_t); CHKERRQ(ierr); }
4214 if (user->
CS) { ierr = VecDestroy(&user->
CS); CHKERRQ(ierr); }
4215 if (user->
lCs) { ierr = VecDestroy(&user->
lCs); CHKERRQ(ierr); }
4216 if (user->
Nu_Wall) { ierr = VecDestroy(&user->
Nu_Wall); CHKERRQ(ierr); }
4224 if (user->
Psi) { ierr = VecDestroy(&user->
Psi); CHKERRQ(ierr); }
4225 if (user->
lPsi) { ierr = VecDestroy(&user->
lPsi); CHKERRQ(ierr); }
4228 if (user->
Bcs.
Ubcs) { ierr = VecDestroy(&user->
Bcs.
Ubcs); CHKERRQ(ierr); }
4229 if (user->
Bcs.
Uch) { ierr = VecDestroy(&user->
Bcs.
Uch); CHKERRQ(ierr); }
4232 if (user->
P_nodal) { ierr = VecDestroy(&user->
P_nodal); CHKERRQ(ierr); }
4234 if (user->
Qcrit) { ierr = VecDestroy(&user->
Qcrit); CHKERRQ(ierr); }
4235 if (user->
lQcrit) { ierr = VecDestroy(&user->
lQcrit); CHKERRQ(ierr); }
4243 for (PetscInt w = 0; w < window_count; ++w) {
4261 if (user->
Rhs) { ierr = VecDestroy(&user->
Rhs); CHKERRQ(ierr); }
4262 if (user->
dUcont) { ierr = VecDestroy(&user->
dUcont); CHKERRQ(ierr); }
4263 if (user->
pUcont) { ierr = VecDestroy(&user->
pUcont); CHKERRQ(ierr); }
4266 if (user->
B) { ierr = VecDestroy(&user->
B); CHKERRQ(ierr); }
4267 if (user->
R) { ierr = VecDestroy(&user->
R); CHKERRQ(ierr); }
4270 PetscFunctionReturn(0);
4273#define __FUNCT__ "DestroyUserContext"
4280 PetscErrorCode ierr;
4281 PetscFunctionBeginUser;
4285 PetscFunctionReturn(0);
4303 ierr = MatDestroy(&user->
A); CHKERRQ(ierr);
4307 ierr = MatDestroy(&user->
MR); CHKERRQ(ierr);
4311 ierr = MatDestroy(&user->
MP); CHKERRQ(ierr);
4315 ierr = KSPDestroy(&user->
ksp); CHKERRQ(ierr);
4319 ierr = MatNullSpaceDestroy(&user->
nullsp); CHKERRQ(ierr);
4325 ierr = AODestroy(&user->
ao); CHKERRQ(ierr);
4332 ierr = DMDestroy(&user->
post_swarm); CHKERRQ(ierr);
4336 ierr = DMDestroy(&user->
swarm); CHKERRQ(ierr);
4340 ierr = DMDestroy(&user->
fda6); CHKERRQ(ierr);
4344 ierr = DMDestroy(&user->
da); CHKERRQ(ierr);
4357 PetscFunctionReturn(0);
4361#define __FUNCT__ "FinalizeSimulation"
4370 PetscErrorCode ierr;
4371 PetscFunctionBeginUser;
4375 PetscFunctionReturn(0);
4395 for (PetscInt level = simCtx->
usermg.
mglevels - 1; level >= 0; level--) {
4403 ierr = PetscFree(user); CHKERRQ(ierr);
4415 ierr = PetscFree(simCtx->
usermg.
mgctx); CHKERRQ(ierr);
4425 ierr = DMDestroy(&simCtx->
usermg.
packer); CHKERRQ(ierr);
4442 ierr = PetscViewerDestroy(&simCtx->
logviewer); CHKERRQ(ierr);
4448 ierr = DMDestroy(&simCtx->
dm_swarm); CHKERRQ(ierr);
4454 ierr = PetscFree(simCtx->
bboxlist); CHKERRQ(ierr);
4463 ierr = PetscFree(simCtx->
bcs_files[i]); CHKERRQ(ierr);
4466 ierr = PetscFree(simCtx->
bcs_files); CHKERRQ(ierr);
4480 ierr = PetscFree(simCtx->
pps); CHKERRQ(ierr);
4488 if (simCtx->
ibm != NULL) {
4489 LOG_ALLOW(
GLOBAL,
LOG_WARNING,
" WARNING: simCtx->ibm is non-NULL but no destroy function exists. Potential memory leak.\n");
4491 if (simCtx->
ibmv != NULL) {
4492 LOG_ALLOW(
GLOBAL,
LOG_WARNING,
" WARNING: simCtx->ibmv is non-NULL but no destroy function exists. Potential memory leak.\n");
4494 if (simCtx->
fsi != NULL) {
4495 LOG_ALLOW(
GLOBAL,
LOG_WARNING,
" WARNING: simCtx->fsi is non-NULL but no destroy function exists. Potential memory leak.\n");
4502 for (PetscInt i = 0; i < simCtx->
nAllowed; i++) {
4504 ierr = PetscFree(simCtx->
allowedFuncs[i]); CHKERRQ(ierr);
4533 ierr = PetscFree(simCtx); CHKERRQ(ierr);
4534 PetscFunctionReturn(0);
PetscErrorCode BoundarySystem_Initialize(UserCtx *user, const char *bcs_filename)
Initializes the entire boundary system.
PetscErrorCode PropagateBoundaryConfigToCoarserLevels(SimCtx *simCtx)
Propagates boundary condition configuration from finest to all coarser multigrid levels.
PetscErrorCode BoundarySystem_Destroy(UserCtx *user)
Cleans up and destroys all boundary system resources.
PetscErrorCode CalculateAllGridMetrics(SimCtx *simCtx)
Orchestrates the calculation of all grid metrics.
Configured initial values of particle-carried fields, and the expression language that defines them.
PetscErrorCode ParticleFieldPlanCreate(ParticleFieldPlan **plan)
Read a plan from the options database.
PetscErrorCode ParticleFieldPlanDestroy(ParticleFieldPlan **plan)
Free a plan and its compiled expressions.
@ FIELD_CAPABILITY_GHOST_UPDATE
@ FIELD_SYNC_COMPONENT_STAGGERED
unsigned int capabilities
const FieldDescriptor * descriptor
PetscErrorCode FieldGetView(UserCtx *user, FieldId field_id, FieldView *view)
Resolve the existing DM and global/local vectors for one field.
const char * canonical_name
FieldSyncClass sync_class
FieldId
Compile-time identity for a catalogued Eulerian field.
Non-owning runtime objects resolved for one field and UserCtx.
PetscErrorCode DefineAllGridDimensions(SimCtx *simCtx)
Orchestrates the parsing and setting of grid dimensions for all blocks.
PetscErrorCode CalculateOutletProperties(UserCtx *user)
Calculates the center and area of the primary OUTLET face.
PetscErrorCode BroadcastAllBoundingBoxes(UserCtx *user, BoundingBox **bboxlist)
Broadcasts the bounding box information collected on rank 0 to all other ranks.
PetscErrorCode ValidatePeriodicGeometry(UserCtx *user)
Validates that configured geometric periodic seams match by translation.
PetscErrorCode InitializeAllGridDMs(SimCtx *simCtx)
Orchestrates the creation of DMDA objects for every block and multigrid level.
PetscErrorCode AssignAllGridCoordinates(SimCtx *simCtx)
Orchestrates the assignment of physical coordinates to all DMDA objects.
PetscErrorCode CalculateInletProperties(UserCtx *user)
Calculates the center and area of the primary INLET face.
PetscErrorCode GatherAllBoundingBoxes(UserCtx *user, BoundingBox **allBBoxes)
Gathers local bounding boxes from all MPI processes to rank 0.
PetscErrorCode ParsePostProcessingSettings(SimCtx *simCtx)
Initializes post-processing settings from a config file and command-line overrides.
PetscErrorCode ParseScalingInformation(SimCtx *simCtx)
Parses physical scaling parameters from command-line options.
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.
void set_allowed_functions(const char **functionList, int count)
Sets the global list of function names that are allowed to log.
PetscBool is_function_allowed(const char *functionName)
Checks if a given function is in the allow-list.
#define LOG_ALLOW_SYNC(scope, level, fmt,...)
Synchronized logging macro that checks both the log level and whether the calling function is in the ...
#define LOCAL
Logging scope definitions for controlling message output.
#define GLOBAL
Scope for global logging across all processes.
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
PetscErrorCode print_log_level(void)
Prints the current logging level to the console.
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
#define LOG(scope, level, fmt,...)
Logging macro for PETSc-based applications with scope control.
PetscErrorCode LoadAllowedFunctionsFromFile(const char filename[], char ***funcsOut, PetscInt *nOut)
Load function names from a text file.
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
PetscErrorCode ProfilingInitialize(SimCtx *simCtx)
Initializes the custom profiling system using configuration from SimCtx.
@ LOG_ERROR
Critical errors that may halt the program.
@ LOG_INFO
Informational messages about program execution.
@ LOG_WARNING
Non-critical issues that warrant attention.
@ LOG_DEBUG
Detailed debugging information.
@ LOG_VERBOSE
Extremely detailed logs, typically for development use only.
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
const char * ParticleInitializationToString(ParticleInitializationType ParticleInitialization)
Returns the canonical log token for a particle-initialization mode.
PetscErrorCode ComputeVectorFieldDerivatives(UserCtx *user, PetscInt i, PetscInt j, PetscInt k, Cmpnts ***field_data, Cmpnts *dudx, Cmpnts *dvdx, Cmpnts *dwdx)
Internal helper implementation: ComputeVectorFieldDerivatives().
static const char * kReservedRunDirectories[]
Directory names the run tree owns; a log directory must never target one.
@ DIR_VERDICT_RELATIVE_ESCAPE
@ DIR_VERDICT_UNRESOLVABLE
@ DIR_VERDICT_UNEXPANDED_TILDE
@ DIR_VERDICT_EXTERNAL_ABSOLUTE
PetscErrorCode DestroyUserContext(UserCtx *user)
Internal helper implementation: DestroyUserContext().
static PetscBool LogDirectoryIsSafeToWipe(const char *log_dir, const char *output_dir, PetscBool authorized, const char **reason)
Final safety guard before the runtime deletes its log directory.
PetscErrorCode GetOwnedCellRange(const DMDALocalInfo *info_nodes, PetscInt dim, PetscInt *xs_cell_global_out, PetscInt *xm_cell_local_out)
Internal helper implementation: GetOwnedCellRange().
static PetscErrorCode ParseLESConfiguration(SimCtx *simCtx)
Reads every LES closure parameter from the generated control file.
#define PICURV_PETSC_MODE
PetscErrorCode SetupDomainRankInfo(SimCtx *simCtx)
Implementation of SetupDomainRankInfo().
PetscErrorCode UniformCart2Contra(UserCtx *user, PetscReal u, PetscReal v, PetscReal w)
Populate contravariant fluxes from one uniform Cartesian velocity.
PetscErrorCode InitializeRandomGenerators(UserCtx *user, PetscRandom *randx, PetscRandom *randy, PetscRandom *randz)
Implementation of InitializeRandomGenerators().
PetscErrorCode Deallocate3DArrayVector(Cmpnts ***array, PetscInt nz, PetscInt ny)
Implementation of Deallocate3DArrayVector().
PetscErrorCode SetupGridAndSolvers(SimCtx *simCtx)
Implementation of SetupGridAndSolvers().
#define PICURV_PETSC_STAMP_MARKER
PetscErrorCode InitializeBrownianRNG(SimCtx *simCtx)
Internal helper implementation: InitializeBrownianRNG().
static PetscInt Gidx(PetscInt i, PetscInt j, PetscInt k, UserCtx *user)
Convert logical indices into the flattened global index used by setup helpers.
PetscErrorCode SetupSimulationEnvironment(SimCtx *simCtx)
Internal helper implementation: SetupSimulationEnvironment().
static PetscBool NormalizePathLexically(const char *value, char *out, size_t size, char *stack)
Lexically normalize a path, resolving "." and ".." textually.
static PetscBool PathContainsOrEquals(const char *ancestor, const char *path)
Whether ancestor is the same directory as path, or contains it.
PetscErrorCode CreateAndInitializeAllVectors(SimCtx *simCtx)
Internal helper implementation: CreateAndInitializeAllVectors().
PetscErrorCode ComputeAndStoreNeighborRanks(UserCtx *user)
Internal helper implementation: ComputeAndStoreNeighborRanks().
PetscErrorCode Contra2Cart(UserCtx *user)
Internal helper implementation: Contra2Cart().
static const char picurv_petsc_build_stamp[]
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 PetscErrorCode PetscMkdirRecursive(const char *path)
Create a directory path recursively using PETSc-compatible error handling.
#define PICURV_STRINGIZE(x)
static DirectoryVerdict ClassifyLogDirectory(const char *log_dir, const char *output_dir, const char **reason)
Classify a configured log directory against the working directory.
int PicurvHandleVersionArgument(int argc, char **argv, const char *executable_name)
Implementation of PicurvHandleVersionArgument().
PetscErrorCode InitializeLogicalSpaceRNGs(PetscInt base_seed, PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k)
Internal helper implementation: InitializeLogicalSpaceRNGs().
PetscErrorCode DestroySolutionConvergenceState(SimCtx *simCtx)
Implementation of DestroySolutionConvergenceState().
static PetscBool DirectoryValueIsWellFormed(const char *value)
Whether a configured directory name is safe to write to a PETSc options line.
PetscErrorCode Allocate3DArrayScalar(PetscReal ****array, PetscInt nz, PetscInt ny, PetscInt nx)
Internal helper implementation: Allocate3DArrayScalar().
PetscErrorCode CreateSimulationContext(int argc, char **argv, SimCtx **p_simCtx)
Implementation of CreateSimulationContext().
PetscErrorCode InitializeSolutionConvergenceState(SimCtx *simCtx)
Implementation of InitializeSolutionConvergenceState().
PetscErrorCode SetDMDAProcLayout(DM dm, UserCtx *user)
Internal helper implementation: SetDMDAProcLayout().
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 ComputeScalarFieldDerivatives(UserCtx *user, PetscInt i, PetscInt j, PetscInt k, PetscReal ***field_data, Cmpnts *grad)
Internal helper implementation: ComputeScalarFieldDerivatives().
PetscErrorCode ComputeDivergence(UserCtx *user)
Implementation of ComputeDivergence().
static PetscBool ResolveDirectoryPhysically(const char *value, const char *cwd, char *out, size_t size, char *scratch)
Resolve a directory that may not exist yet to an absolute physical path.
PetscErrorCode UpdateLocalGhosts(UserCtx *user, FieldId field_id)
Updates a catalogued field's local ghost representation.
static PetscBool DirectoriesOverlap(const char *first, const char *second)
Whether two configured directories denote the same location or nest.
PetscErrorCode BinarySearchInt64(PetscInt n, const PetscInt64 arr[], PetscInt64 key, PetscBool *found)
Implementation of BinarySearchInt64().
static PetscErrorCode AllocateContextHierarchy(SimCtx *simCtx)
Allocate the user-context objects required by every multigrid level.
PetscErrorCode Cart2Contra(UserCtx *user)
Convert a spatially varying Cartesian velocity field to contravariant fluxes.
PetscErrorCode DestroyUserVectors(UserCtx *user)
Internal helper implementation: DestroyUserVectors().
PetscErrorCode Allocate3DArrayVector(Cmpnts ****array, PetscInt nz, PetscInt ny, PetscInt nx)
Implementation of Allocate3DArrayVector().
PetscErrorCode SetupBoundaryConditions(SimCtx *simCtx)
Internal helper implementation: SetupBoundaryConditions().
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)
Transform contravariant vector derivatives into physical Cartesian derivatives.
PetscErrorCode LESConfigSetDefaults(LESConfig *config)
Implementation of LESConfigSetDefaults().
PetscErrorCode SetupDomainCellDecompositionMap(UserCtx *user)
Internal helper implementation: SetupDomainCellDecompositionMap().
PetscErrorCode FinalizeSimulation(SimCtx *simCtx)
Implementation of FinalizeSimulation().
static PetscBool DirectoryHitsReservedName(const char *value)
Whether a directory's first path segment collides with a reserved run directory.
PetscErrorCode Deallocate3DArrayScalar(PetscReal ***array, PetscInt nz, PetscInt ny)
Internal helper implementation: Deallocate3DArrayScalar().
PetscBool RuntimeWalltimeGuardParsePositiveSeconds(const char *text, PetscReal *seconds_out)
Implementation of RuntimeWalltimeGuardParsePositiveSeconds().
Per-window PETSc accumulator storage and pointwise application.
PetscErrorCode PicurvWindowStorageCreate(UserCtx *user, const PicurvWindowDefinition *definition, PicurvWindowStorage *storage)
Allocates the accumulator state one window owns on one block.
PetscErrorCode PicurvWindowStorageDestroy(PicurvWindowStorage *storage)
Releases accumulator state previously created for one window.
Control ingress for the field-statistics pipeline.
PetscErrorCode DestroyFieldStatisticsConfig(SimCtx *simCtx)
Releases the window definitions resolved by ParseFieldStatisticsConfig().
PetscErrorCode ParseFieldStatisticsConfig(SimCtx *simCtx)
Resolves field-statistics configuration from the control file.
PicurvWindowDefinition definition
PetscBool FieldStatisticsIsActive(const struct SimCtx *simCtx)
Reports whether this run has live field-statistics state.
LESModelType
Identifies the subgrid-scale closure evaluated during a timestep.
PetscReal icVelocityPhysical
PetscBool mom_nk_monitor_history
Vec Qcrit_nodal
Q-criterion averaged to grid nodes; the field a .vts can place correctly.
PetscInt fieldStatisticsWindowCount
char statistics_output_prefix[256]
basename for CSV output, e.g.
PetscReal yoshizawa_ci
Yoshizawa constant for the reported SGS kinetic energy.
PetscBool profilingFinalSummary
char particle_output_prefix[256]
PetscInt dynamic_frequency
Recompute the dynamic coefficient every N steps.
char profilingTimestepFile[PETSC_MAX_PATH_LEN]
PetscInt LV
Heart-valve flux corrections for immersed bodies; refused at setup.
PetscReal Turbulent_schmidt_number
BoundaryFaceConfig boundary_faces[6]
PetscInt64 searchLocatedCount
LESFilterWidthModel filter_width_model
How the grid filter width Delta is derived per cell.
PetscInt statisticsConsoleOutputFreq
#define PICURV_BUILD_DIRTY
PetscInt64 searchLostCount
PetscReal targetVolumetricFlux
Vec * solutionConvergencePeriodicPRef
PetscBool walltimeGuardActive
LESTestFilterKernel test_filter_kernel
Discrete test-filter stencil.
PetscReal mom_last_lambda_max
PetscReal walltimeGuardWarmupTotalSeconds
LESConfig les_config
Parameters of the LES closure selected by les.
PetscReal forceScalingFactor
PetscReal pseudo_cfl_reduction_factor
InitialConditionMode initialConditionMode
SimCtx * simCtx
Back-pointer to the master simulation context.
ParticleInitializationType
Enumerator to identify the particle initialization strategy.
@ PARTICLE_INIT_SURFACE_RANDOM
Random placement on the inlet face.
PetscReal * solutionConvergenceMeanSpeedHistory
PetscBool walltimeGuardHasEWMA
FlowDirection flowDirection
PetscBool runtimeMemoryLogEnabled
Enable the rank-reduced runtime memory log.
PetscReal boundaryVelocityCorrection
PetscInt64 boundaryClampCount
PetscInt particlesLostLastStep
PetscReal walltimeGuardMinSeconds
char allowedFile[PETSC_MAX_PATH_LEN]
Vec * solutionConvergencePeriodicUcatRef
PetscInt64 traversalStepsSum
PetscBool mom_last_converged
PetscReal iem_constant
IEM mixing constant C_IEM in Omega = C_IEM Gamma / Delta^2 (default 2.0).
PetscInt solutionConvergenceSamplesRecorded
Cmpnts max_coords
Maximum x, y, z coordinates of the bounding box.
PetscReal poissonSourceImbalance
PetscBool drivenFluxTargetLatched
PetscInt64 searchPopulation
char output_dir[PETSC_MAX_PATH_LEN]
PetscBool solutionConvergenceEnabled
PetscReal * solutionConvergenceMeanKEHistory
PetscReal walltimeGuardLatestStepSeconds
char runtimeMemoryLogFile[PETSC_MAX_PATH_LEN]
File name written under log_dir.
PetscBool runtimeMemoryLogStarted
True after rank 0 writes the log header.
PetscInt occupiedCellCount
LESClipMode
Selects the admissible range imposed on the dynamic model coefficient.
char profilingTimestepMode[32]
PetscReal bulkVelocityCorrection
LESTestFilterKernel
Selects the discrete test-filter kernel used by the dynamic procedure.
@ LES_TEST_FILTER_SIMPSON_IK
@ LES_TEST_FILTER_VOLUME_WEIGHTED_BOX
PetscInt currentSettlementPass
PetscBool fieldStatisticsEnabled
PetscReal max_cs
Ceiling on Cs under LES_CLIP_CLAMP.
LESClipMode clip_mode
Admissible range for the coefficient.
PetscBool no_pseudo_cfl_backtrack
#define PICURV_GIT_COMMIT
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
PetscInt rotatefsi
Refused at setup: immersed boundaries and moving bodies are not implemented.
Vec Ubcs
Physical Cartesian velocity at boundary faces. Full 3D array but only boundary-face entries are meani...
@ MOMENTUM_SOLVER_DUALTIME_PICARD_JAMESON_RK
@ MOMENTUM_SOLVER_EXPLICIT_RK
@ MOMENTUM_SOLVER_NEWTON_KRYLOV
PetscInt solutionConvergencePeriodSteps
PetscBool averaging_direction[3]
Averaged-over logical directions (xi, eta, zeta).
PetscReal wale_coefficient
Model constant C_w for WALE (Nicoud & Ducros 1999).
char * current_io_directory
char grid_file[PETSC_MAX_PATH_LEN]
char statistics_pipeline[1024]
e.g.
PetscInt64 bboxGuessFallbackCount
InterpolationMethod interpolationMethod
RankCellInfo * RankCellInfoMap
PetscReal psrc_z
Point source location for PARTICLE_INIT_POINT_SOURCE.
VerificationScalarConfig verificationScalar
char profilingSelectedFuncsFile[PETSC_MAX_PATH_LEN]
char analysis_dir[PETSC_MAX_PATH_LEN]
char particleRestartMode[16]
PetscInt64 bboxGuessSuccessCount
struct PicurvWindow * fieldStatisticsWindows
char log_dir[PETSC_MAX_PATH_LEN]
PetscInt walltimeGuardCompletedSteps
PetscInt64 maxParticlePassDepth
char source_dir[PETSC_MAX_PATH_LEN]
PetscInt les_gradient_model
Add the Clark gradient (tensor-diffusivity) term to the viscous flux.
PetscInt64 maxTraversalSteps
Cmpnts AnalyticalUniformVelocity
char eulerianSource[PETSC_MAX_PATH_LEN]
PetscBool walltimeGuardEnabled
PetscBool checkpointGeometryHashReady
PetscReal wall_roughness_height
PetscBool useProfilingSelectedFuncsCfg
PetscInt walltimeGuardWarmupSteps
ParticleInitializationType ParticleInitialization
PetscReal mom_dt_jameson_residual_norm_noise_allowance_factor
InterpolationMethod
Selects the grid-to-particle interpolation method.
PetscInt diagnostics_cadence
Steps between diagnostic rows.
PetscReal min_viscosity_ratio
Enforce nu + nu_t >= ratio * nu.
PetscInt wallfunction
Enable wall functions on WALL faces.
PetscInt drivingForceStep
LESAveragingMode
Selects the set over which the Germano contractions are averaged.
PetscReal drivenFluxMeasured
PetscBool runtimeMemoryLogHasPrevious
True after the first process-memory sample.
char ** profilingSelectedFuncs
PetscBool diagnostics_enabled
Append per-step coefficient statistics to the run log directory.
PetscReal constant_cs
Fixed Cs for CONSTANT_SMAGORINSKY; unused by the dynamic model.
PetscInt solutionConvergenceWindowSteps
PetscReal test_filter_width_ratio
Test-to-grid ratio per filtered direction; alpha is its square for the box, ratio^(4/3) for Simpson.
FlowDirection
Primary flow direction for streamwise IC and Poiseuille modes.
PetscReal pseudo_cfl_growth_factor
PetscBool outputParticles
PetscInt particlesLostCumulative
PetscInt nProfilingSelectedFuncs
PetscInt particlesMigratedLastStep
PetscInt particleRandomSeed
Base seed for every particle RNG stream (-particle_random_seed).
char initialConditionDirectory[PETSC_MAX_PATH_LEN]
LESAveragingMode averaging_mode
Averaging set for the Germano contractions.
struct PicurvWindowStorage * fieldStatisticsStorage
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
PetscReal walltimeGuardWarmupAverageSeconds
InitialConditionMode
Selects the algorithm used to populate a fresh Eulerian velocity field.
PetscInt particleConsoleOutputFreq
Cmpnts InitialConstantContra
SearchMetricsState searchMetrics
char checkpointGeometrySHA256[65]
PetscReal runtimeMemoryLogPreviousProcessMB
Previous local process memory sample in MB.
PetscReal walltimeGuardEWMASeconds
PetscReal vreman_coefficient
Model constant c for VREMAN (Vreman 2004: 2.5 Cs^2).
PetscInt mom_max_pseudo_steps
PetscRandom BrownianMotionRNG
PetscInt migrationPassesLastStep
InitialConditionField
Selects the authoritative velocity representation in a staged file IC.
@ EXEC_MODE_POSTPROCESSOR
char _io_context_buffer[PETSC_MAX_PATH_LEN]
PetscReal walltimeGuardLimitSeconds
PetscBool ps_ksp_pic_monitor_true_residual
PetscReal walltimeGuardEstimatorAlpha
PetscInt les
Active LES closure; an LESModelType value.
Vec lQcrit
Cell-centred Q-criterion and its ghosted copy for nodal averaging.
@ SOLUTION_CONVERGENCE_TRANSIENT
@ SOLUTION_CONVERGENCE_PERIODIC_DETERMINISTIC
@ SOLUTION_CONVERGENCE_STATISTICAL_STEADY
@ SOLUTION_CONVERGENCE_STEADY_DETERMINISTIC
PetscReal mom_ratio_ema_alpha
SolutionConvergenceMode solutionConvergenceMode
PetscReal particlesLostScalarLastStep
Sum of Psi over the particles removed this step.
PetscInt64 searchAttempts
InitialConditionField initialConditionField
PetscBool restartHistoryAvailable
PetscReal walltimeGuardMultiplier
PetscInt rotateframe
moveframe/rotateframe are refused at setup.
MomentumSolverType mom_solver_type
PetscInt64 maxTraversalFailCount
char PostprocessingControlFile[PETSC_MAX_PATH_LEN]
char restart_dir[PETSC_MAX_PATH_LEN]
VerificationDiffusivityConfig verificationDiffusivity
PetscReal walltimeGuardJobStartEpochSeconds
LESFilterWidthModel
Selects how a cell's grid filter width is derived from its metrics.
@ LES_FILTER_WIDTH_SCOTTI
@ LES_FILTER_WIDTH_CUBE_ROOT_VOLUME
PetscInt LoggingFrequency
#define PICURV_RELEASE_VERSION
PetscReal drivingForceMagnitude
PetscReal particleLoadImbalance
struct ParticleFieldPlan * particleFieldPlan
Configured initial particle-field values, or NULL.
PetscBool fieldStatisticsContinue
Vec Uch
Characteristic velocity for boundary conditions.
Defines a 3D axis-aligned bounding box.
A 3D point or vector with PetscScalar components.
Every user-selectable parameter of the LES closure.
Context for Multigrid operations.
Holds all configuration parameters for a post-processing run.
A lean struct to hold the global cell ownership range for a single MPI rank.
The master context for the entire simulation.
User-defined context containing data specific to a single computational grid level.
User-level context for managing the entire multigrid hierarchy.
PetscBool VerificationScalarOverrideActive(const SimCtx *simCtx)
Reports whether a verification-only scalar override is active.