Solves the Momentum Equations using Dual-Time Stepping with a Fixed-Point RK4 Smoother.
– Physics Variables (Legacy Names Kept) – ti : Physical Time Step Index. dt : Physical Time Step size (Delta t). st : Pseudo-Time Step size (Delta tau). alfa : Runge-Kutta stage coefficients {1/4, 1/3, 1/2, 1}.
– Convergence & Solver Control (Renamed) – pseudo_iter : Counter for the inner dual-time loop. pseudo_dt_scaling : Adaptive scalar for the pseudo-time step (formerly lambda). delta_sol_norm : The L_inf norm of the change in solution (dU).
225{
226
229
230
231 const PetscInt ti = simCtx->
step;
232 const PetscReal dt = simCtx->
dt;
234 const PetscReal alfa[] = {0.25, 1.0/3.0, 0.5, 1.0};
235 Vec *pRhs;
236
237
238 PetscBool force_restart = PETSC_FALSE;
239
240
242 const PetscReal tol_abs_delta = simCtx->
mom_atol;
243 const PetscReal tol_rtol_delta = simCtx->
mom_rtol;
244
245
246 PetscErrorCode ierr;
247 PetscMPIInt rank;
248 PetscInt istage, pseudo_iter, ibi;
249 PetscReal ts, te, cput;
250
251
252 PetscReal global_norm_delta = 10.0;
253 PetscReal global_rel_delta = 1.0;
254 PetscReal global_rel_resid = 1.0;
255
256
257 PetscReal *delta_sol_norm_init, *delta_sol_norm_prev, *delta_sol_norm_curr, *delta_sol_rel_curr;
258 PetscReal *resid_norm_init, *resid_norm_prev, *resid_norm_curr, *resid_rel_curr;
259 PetscReal *pseudo_dt_scaling;
260
261 PetscFunctionBeginUser;
263 ierr = MPI_Comm_rank(PETSC_COMM_WORLD, &rank); CHKERRQ(ierr);
265
266
267 ierr = PetscMalloc2(block_number, &delta_sol_norm_init, block_number, &delta_sol_norm_prev); CHKERRQ(ierr);
268 ierr = PetscMalloc2(block_number, &delta_sol_norm_curr, block_number, &delta_sol_rel_curr); CHKERRQ(ierr);
269 ierr = PetscMalloc2(block_number, &resid_norm_init, block_number, &resid_norm_prev); CHKERRQ(ierr);
270 ierr = PetscMalloc2(block_number, &resid_norm_curr, block_number, &pseudo_dt_scaling); CHKERRQ(ierr);
271 ierr = PetscMalloc1(block_number, &resid_rel_curr); CHKERRQ(ierr);
272 ierr = PetscMalloc1(block_number, &pRhs); CHKERRQ(ierr);
273
274 ierr = PetscTime(&ts); CHKERRQ(ierr);
275
276
277
278 if (block_number > 1) {
279
280 }
281
282 for (PetscInt bi = 0; bi < block_number; bi++) {
284
285
286
287
288 ierr = VecDuplicate(user[bi].Ucont, &user[bi].Rhs); CHKERRQ(ierr);
289 ierr = VecDuplicate(user[bi].Rhs, &pRhs[bi]); CHKERRQ(ierr);
290 ierr = VecDuplicate(user[bi].Ucont, &user[bi].dUcont); CHKERRQ(ierr);
291 ierr = VecDuplicate(user[bi].Ucont, &user[bi].pUcont); CHKERRQ(ierr);
292
293
294 ierr = VecCopy(user[bi].Ucont, user[bi].pUcont); CHKERRQ(ierr);
295
296
298
299
300 ierr = VecCopy(user[bi].Rhs, pRhs[bi]); CHKERRQ(ierr);
301
302
303 ierr = VecNorm(user[bi].Rhs, NORM_INFINITY, &resid_norm_init[bi]); CHKERRQ(ierr);
304
305
306 resid_norm_prev[bi] = resid_norm_init[bi];
307 delta_sol_norm_prev[bi] = 1000.0;
308 pseudo_dt_scaling[bi] = cfl;
309
311 }
312
313
314 pseudo_iter = 0;
315 while ((force_restart || (global_norm_delta > tol_abs_delta || global_rel_delta > tol_rtol_delta) || pseudo_iter < 1)
316 && pseudo_iter < max_pseudo_steps)
317 {
318 pseudo_iter++;
319 force_restart = PETSC_FALSE;
320
321 for (PetscInt bi = 0; bi < block_number; bi++) {
322
323
324 for (istage = 0; istage < 4; istage++) {
325
327
328
329 ierr = VecWAXPY(user[bi].Ucont,
330 pseudo_dt_scaling[bi] * alfa[istage] * dt,
331 user[bi].Rhs,
332 user[bi].pUcont); CHKERRQ(ierr);
333
334
336
337
338
339
341
342
344
345 }
346
347
348
349
350
351
352 ierr = VecWAXPY(user[bi].dUcont, -1.0, user[bi].pUcont, user[bi].Ucont); CHKERRQ(ierr);
353
354
355 ierr = VecNorm(user[bi].dUcont, NORM_INFINITY, &delta_sol_norm_curr[bi]); CHKERRQ(ierr);
356 ierr = VecNorm(user[bi].Rhs, NORM_INFINITY, &resid_norm_curr[bi]); CHKERRQ(ierr);
357
358
359 if (pseudo_iter == 1) {
360 delta_sol_norm_init[bi] = delta_sol_norm_curr[bi];
361 delta_sol_rel_curr[bi] = 1.0;
362 resid_rel_curr[bi] = 1.0;
363
364 } else {
365 if (delta_sol_norm_init[bi] > 1.0e-10)
366 delta_sol_rel_curr[bi] = delta_sol_norm_curr[bi] / delta_sol_norm_init[bi];
367 else
368 delta_sol_rel_curr[bi] = 0.0;
369
370 if(resid_norm_init[bi] > 1.0e-10)
371 resid_rel_curr[bi] = resid_norm_curr[bi] / resid_norm_init[bi];
372 else
373 resid_rel_curr[bi] = 0.0;
374 }
375
376
377 if (!rank) {
378 FILE *f;
379 char filen[128];
380 sprintf(filen,
"%s/Momentum_Solver_Convergence_History_Block_%1d.log", simCtx->
log_dir, bi);
381 if(simCtx->
step == simCtx->
StartStep + 1 && pseudo_iter == 1) f = fopen(filen,
"w");
382 else f = fopen(filen, "a");
383
384 PetscFPrintf(PETSC_COMM_WORLD, f, "Step: %d | PseudoIter(k): %d| | Pseudo-cfl: %.4f |dUk|: %le | |dUk|/|dUprev|: %le | |Rk|: %le | |Rk|/|Rprev|: %le \n",
385 (int)ti, (int)pseudo_iter, pseudo_dt_scaling[bi], delta_sol_norm_curr[bi], delta_sol_rel_curr[bi], resid_norm_curr[bi],resid_rel_curr[bi]);
386 fclose(f);
387 }
388 }
389
390
391 global_norm_delta = -1.0e20;
392 global_rel_delta = -1.0e20;
393 global_rel_resid = -1.0e20;
394
395 for (PetscInt bi = 0; bi < block_number; bi++) {
396 global_norm_delta = PetscMax(delta_sol_norm_curr[bi], global_norm_delta);
397 global_rel_delta = PetscMax(delta_sol_rel_curr[bi], global_rel_delta);
398 global_rel_resid = PetscMax(resid_rel_curr[bi], global_rel_resid);
399 }
400 ierr = PetscTime(&te); CHKERRQ(ierr);
401 cput = te - ts;
403 pseudo_iter, global_norm_delta, global_rel_delta, global_rel_resid, cput);
404
405
406 for (PetscInt bi = 0; bi < block_number; bi++) {
407
408 PetscReal resid_ratio = resid_norm_curr[bi] / resid_norm_prev[bi];
409
410 PetscBool is_sol_nan, is_resid_nan, is_diverging;
411
412 is_sol_nan = (PetscBool)PetscIsNanReal(delta_sol_norm_curr[bi]);
413 is_resid_nan = (PetscBool)PetscIsNanReal(resid_norm_curr[bi]);
414
415
416 is_diverging = (PetscBool)(pseudo_iter > 1 &&
418 delta_sol_norm_curr[bi] > delta_sol_norm_prev[bi]
419 );
420
421 if(is_diverging || is_sol_nan || is_resid_nan) {
422
423 if(is_sol_nan){
425 }
426 if(is_resid_nan){
428 }
429 if(is_diverging){
431 }
432
434 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_CONV_FAILED,
435 "Block %d: Solver diverged (NaN or explosion) and min time-step reached. Simulation aborted.", bi);
436 }
437
438
439 force_restart = PETSC_TRUE;
440
441
443
444
445 LOG_ALLOW(
LOCAL,
LOG_DEBUG,
" Block %d: Backtracking triggered. Reducing scaling to %f.\n", bi, pseudo_dt_scaling[bi]);
446
447
448 ierr = VecCopy(user[bi].pUcont, user[bi].Ucont); CHKERRQ(ierr);
449
450 ierr = VecCopy(pRhs[bi], user[bi].Rhs); CHKERRQ(ierr);
451
452
454
455
456
457
458 delta_sol_norm_curr[bi] = 1000.0;
459 resid_norm_curr[bi] = 1000.0;
460
461 }
462 else {
463
464 ierr = VecCopy(user[bi].Ucont, user[bi].pUcont); CHKERRQ(ierr);
465 ierr = VecCopy(user[bi].Rhs, pRhs[bi]); CHKERRQ(ierr);
466 resid_norm_prev[bi] = resid_norm_curr[bi];
467 delta_sol_norm_prev[bi] = delta_sol_norm_curr[bi];
468
469
470
471 PetscBool is_converging_fast;
472 is_converging_fast = (PetscBool)(resid_ratio < 0.9);
473 PetscBool is_stagnating;
474 is_stagnating = (PetscBool)(resid_ratio >= 0.98 && resid_ratio < 1.0);
475 PetscBool is_noisy;
476 is_noisy = (PetscBool)(resid_ratio >= 1.0 && resid_ratio < simCtx->mom_dt_rk4_residual_norm_noise_allowance_factor);
477
478 PetscReal current_cfl = pseudo_dt_scaling[bi];
481
482 if(is_converging_fast){
483
485 } else if(is_stagnating && current_cfl < cfl_floor){
486
488 } else if(is_stagnating && current_cfl >= cfl_floor && current_cfl < cfl_ceiling && !is_noisy){
489
491 } else if(is_stagnating && current_cfl >= cfl_ceiling && !is_noisy){
492
494 } else if(is_noisy){
495
496 if(current_cfl > cfl_ceiling){
497
499 } else if(current_cfl > cfl_floor && current_cfl <= cfl_ceiling){
500
502 } else if(current_cfl <= cfl_floor){
503
504
506 }
507 }
508
509 pseudo_dt_scaling[bi] = PetscMin(pseudo_dt_scaling[bi], simCtx->
max_pseudo_cfl);
510 pseudo_dt_scaling[bi] = PetscMax(pseudo_dt_scaling[bi], simCtx->
min_pseudo_cfl);
511 }
512 }
513
514
515 if (force_restart) pseudo_iter--;
516
517 if (block_number > 1) {
518
519 }
520 }
521
522
523
524
525 PetscReal local_min_cfl = 1.0e20;
526 PetscReal global_min_cfl;
527
529
530
531 for (PetscInt bi = 0; bi < block_number; bi++) {
532 if (pseudo_dt_scaling[bi] < local_min_cfl) {
533 local_min_cfl = pseudo_dt_scaling[bi];
534 }
535 }
536
537
538
539 ierr = MPI_Allreduce(&local_min_cfl, &global_min_cfl, 1, MPIU_REAL, MPI_MIN, PETSC_COMM_WORLD); CHKERRQ(ierr);
540
541
542
543
544
545 PetscReal cfl_carry_over_relaxation_factor = 1.0;
546
547 PetscReal next_start_cfl;
548
549 if(global_min_cfl < cfl_floor){
550
551 next_start_cfl = cfl_floor * 1.5;
552 } else{
553 next_start_cfl = global_min_cfl * cfl_carry_over_relaxation_factor;
554 }
555
556 next_start_cfl = PetscMin(next_start_cfl, simCtx->
max_pseudo_cfl);
557 next_start_cfl = PetscMax(next_start_cfl, simCtx->
min_pseudo_cfl);
558
559
560 if (!rank) {
561 LOG_ALLOW(
GLOBAL,
LOG_INFO,
" CFL Adaptation: Step %d finished at CFL %.3f. Next step will start at CFL %.3f.\n",
562 simCtx->
step, global_min_cfl, next_start_cfl);
563 }
564
565
567
568
569 for (PetscInt bi = 0; bi < block_number; bi++) {
570 ierr = VecDestroy(&user[bi].Rhs); CHKERRQ(ierr);
571 ierr = VecDestroy(&user[bi].dUcont); CHKERRQ(ierr);
572 ierr = VecDestroy(&user[bi].pUcont); CHKERRQ(ierr);
573 ierr = VecDestroy(&pRhs[bi]); CHKERRQ(ierr);
574 }
575 ierr = PetscFree(pRhs); CHKERRQ(ierr);
576
577 ierr = PetscFree2(delta_sol_norm_init, delta_sol_norm_prev);CHKERRQ(ierr);
578 ierr = PetscFree2(delta_sol_norm_curr, delta_sol_rel_curr);CHKERRQ(ierr);
579 ierr = PetscFree2(resid_norm_init, resid_norm_prev);CHKERRQ(ierr);
580 ierr = PetscFree2(resid_norm_curr, pseudo_dt_scaling); CHKERRQ(ierr);
581 ierr = PetscFree(resid_rel_curr); CHKERRQ(ierr);
582
585 PetscFunctionReturn(0);
586}
@ LOG_TRACE
Very fine-grained tracing information for in-depth debugging.
@ LOG_WARNING
Non-critical issues that warrant attention.
static PetscErrorCode ComputeTotalResidual(UserCtx *user)
Computes the Total Residual for the Dual-Time stepping method.
PetscErrorCode UpdateLocalGhosts(UserCtx *user, const char *fieldName)
Updates the local vector (including ghost points) from its corresponding global vector.
PetscReal pseudo_cfl_reduction_factor
char log_dir[PETSC_MAX_PATH_LEN]
PetscReal pseudo_cfl_growth_factor
PetscReal mom_dt_rk4_residual_norm_noise_allowance_factor
PetscInt mom_max_pseudo_steps