124 PetscMPIInt comm_size, world_size;
125 PetscReal local_inf, local_2;
126 PetscFunctionBeginUser;
127 PetscCall(VecDuplicate(a, &delta));
128 PetscCall(VecWAXPY(delta, -1.0, a, b));
129 PetscCall(VecNorm(delta, NORM_INFINITY, &local_inf));
130 PetscCall(VecNorm(delta, NORM_2, &local_2));
131 comm = PetscObjectComm((PetscObject)a);
132 PetscCallMPI(MPI_Comm_size(comm, &comm_size));
133 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &world_size));
134 if (comm_size == 1 && world_size > 1) {
135 PetscReal square = local_2 * local_2;
136 PetscCallMPI(MPI_Allreduce(&local_inf, norm_inf, 1, MPIU_REAL, MPI_MAX, PETSC_COMM_WORLD));
137 PetscCallMPI(MPI_Allreduce(&square, norm_2, 1, MPIU_REAL, MPI_SUM, PETSC_COMM_WORLD));
138 *norm_2 = PetscSqrtReal(*norm_2);
140 *norm_inf = local_inf;
143 PetscCall(VecDestroy(&delta));
144 PetscFunctionReturn(PETSC_SUCCESS);
360 char tmpdir[PETSC_MAX_PATH_LEN] =
"";
363 Vec X0 = NULL, X1 = NULL, Xfinal = NULL;
364 Vec F0 = NULL, F1 = NULL, Fafter = NULL, v = NULL, jv = NULL;
365 Vec F3 = NULL, F24 = NULL;
367 PetscReal norms[2] = {0.0, 0.0};
368 PetscReal imm_inf = 0.0, imm_2 = 0.0, mffd_inf = 0.0, mffd_2 = 0.0;
369 PetscReal f3_2 = 0.0, f24_2 = 0.0, f24_inf = 0.0, f24m3_inf = 0.0, f24m3_2 = 0.0;
370 PetscReal max_div = -1.0;
373 const PetscReal purity_inf_tol = 1e-13, purity_2_tol = 1e-12;
374 const PetscReal compat_tol = 1e-8, div_tol = 1e-6;
375 PetscMPIInt world, mffd_rank = 0;
376 PetscErrorCode prod_ierr;
378 PetscFunctionBeginUser;
379 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &world));
380 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
381 "\n########## NEWTON-KRYLOV PRODUCTION REGRESSION (ranks=%d) ##########\n", (
int)world));
388 simCtx->
step = 1; simCtx->
ti = simCtx->
dt;
391 simCtx->
step = 2; simCtx->
ti = 2.0 * simCtx->
dt;
393 PetscCall(VecDuplicate(user->
Ucont, &user->
Rhs));
400 PetscCall(VecDuplicate(user->
Ucont, &X0)); PetscCall(VecCopy(user->
Ucont, X0));
403 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
"\n===== 4.1 production-callback residual purity =====\n"));
405 SNES snes = NULL; Mat J = NULL; KSP ksp = NULL;
406 PetscCall(VecDuplicate(X0, &X1)); PetscCall(VecCopy(X0, X1));
408 PetscCall(SNESSetConvergenceTest(snes,
StopAfterOne, norms, NULL));
409 PetscCall(SNESSolve(snes, NULL, X1));
410 PetscCall(MatDestroy(&J)); PetscCall(SNESDestroy(&snes));
412 PetscCall(VecDuplicate(X1, &F0)); PetscCall(VecDuplicate(X1, &F1));
413 PetscCall(VecDuplicate(X1, &Fafter)); PetscCall(VecDuplicate(X1, &v)); PetscCall(VecDuplicate(X1, &jv));
419 PetscCall(VecSet(user->
Ucat, 7.0)); PetscCall(VecSet(user->
lUcat, 7.0));
422 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
423 "PURITY immediate inf=% .3e l2=% .3e (tol inf=%.0e l2=%.0e)\n",
424 (
double)imm_inf, (
double)imm_2, (
double)purity_inf_tol, (
double)purity_2_tol));
428 SNES snes = NULL; Mat J = NULL; KSP ksp = NULL;
429 PetscInt lo, hi; PetscScalar *a = NULL; PetscReal vn;
430 PetscCall(VecGetOwnershipRange(v, &lo, &hi));
431 PetscCall(VecGetArray(v, &a));
432 for (PetscInt i = lo; i < hi; ++i) a[i - lo] = PetscSinReal(0.17 * (PetscReal)(i + 1));
433 PetscCall(VecRestoreArray(v, &a));
434 PetscCall(VecNorm(v, NORM_2, &vn)); PetscCall(VecScale(v, 1.0 / vn));
436 PetscCall(MatMFFDSetBase(J, X1, F0));
437 for (PetscInt i = 0; i < 40; ++i) PetscCall(MatMult(J, v, jv));
441 PetscCall(MatDestroy(&J)); PetscCall(SNESDestroy(&snes));
443 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
444 "PURITY post_mffd inf=% .3e l2=% .3e max_rank=%d\n",
445 (
double)mffd_inf, (
double)mffd_2, (
int)mffd_rank));
448 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
"\n===== 4.2 full production step-2 solve (default classical GS) =====\n"));
454 PetscCall(VecDestroy(&user->
Rhs));
455 prod_ierr = MomentumSolver_NewtonKrylov_BoundaryFixedpointPrivateCopy(user, NULL, NULL);
456 PetscCall(VecDuplicate(user->
Ucont, &user->
Rhs));
457 PetscCall(VecDuplicate(user->
Ucont, &Xfinal)); PetscCall(VecCopy(user->
Ucont, Xfinal));
458 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
459 "PROD_SOLVER ierr=%d mom_last_converged=%d\n",
462 PetscReal dinf, d2; PetscMPIInt r;
465 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
466 "PROD_SOLVER test_snes_vs_wrapper inf=% .3e l2=% .3e max_rank=%d\n",
467 (
double)dinf, (
double)d2, (
int)r));
471 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
"\n===== 4.3 boundary-map compatibility (3 vs 24 passes) =====\n"));
472 PetscCall(VecDuplicate(Xfinal, &F3)); PetscCall(VecDuplicate(Xfinal, &F24));
475 PetscCall(VecNorm(F3, NORM_2, &f3_2));
478 PetscCall(VecNorm(F24, NORM_2, &f24_2));
479 PetscCall(VecNorm(F24, NORM_INFINITY, &f24_inf));
481 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
482 "COMPAT F3_l2=% .6e F24_l2=% .6e F24_inf=% .6e F24_minus_F3_l2=% .6e (tol %.0e)\n",
483 (
double)f3_2, (
double)f24_2, (
double)f24_inf, (
double)f24m3_2, (
double)compat_tol));
486 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
"\n===== 4.4 projection compatibility =====\n"));
488 PetscCall(VecCopy(Xfinal, user->
Ucont));
500 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
501 "PROJECTION max_divergence=% .6e net_divergence_sum=% .6e (tol %.0e)\n",
502 (
double)max_div, (
double)simCtx->
summationRHS, (
double)div_tol));
505 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
"\nREGRESSION_VERDICTS (ranks=%d)\n", (
int)world));
506 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
" PRODUCTION_PURITY: %s\n",
507 (imm_inf <= purity_inf_tol && imm_2 <= purity_2_tol &&
508 mffd_inf <= purity_inf_tol && mffd_2 <= purity_2_tol) ?
"PASS" :
"FAIL"));
509 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
" FULL_STEP2_DEFAULT_GS: %s\n",
511 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
" PRODUCTION_SOLVER_WRAPPER: %s\n",
513 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
" THREE_PASS_24_PASS_COMPATIBLE: %s\n",
514 (f24_2 <= compat_tol) ?
"PASS" :
"FAIL"));
515 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
" PROJECTION_DIVERGENCE_FREE: %s\n",
516 (max_div <= div_tol) ?
"PASS" :
"FAIL"));
519 PetscCheck(imm_inf <= purity_inf_tol && imm_2 <= purity_2_tol, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
520 "production residual not immediately repeatable (inf=%g l2=%g)", (
double)imm_inf, (
double)imm_2);
521 PetscCheck(mffd_inf <= purity_inf_tol && mffd_2 <= purity_2_tol, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
522 "production residual changed after MFFD products (inf=%g l2=%g)", (
double)mffd_inf, (
double)mffd_2);
523 PetscCheck(res_cgs.
converged, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
524 "full step-2 solve (default GS) did not converge (reason=%d)", (
int)res_cgs.
reason);
525 PetscCheck(res_cgs.
reason != SNES_DIVERGED_LINE_SEARCH && res_cgs.
reason != SNES_DIVERGED_LINEAR_SOLVE,
526 PETSC_COMM_WORLD, PETSC_ERR_PLIB,
"full step-2 solve diverged via line search or linear solve (reason=%d)",
528 PetscCheck(prod_ierr == 0 && simCtx->
mom_last_converged, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
529 "production Newton-Krylov solver wrapper did not converge (ierr=%d)", (
int)prod_ierr);
530 PetscCheck(f24_2 <= compat_tol, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
531 "converged three-pass solution does not satisfy the 24-pass residual (||F24||2=%g)", (
double)f24_2);
532 PetscCheck(max_div <= div_tol, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
533 "projection of the converged momentum state is not divergence free (max_div=%g)", (
double)max_div);
535 PetscCall(VecDestroy(&F24)); PetscCall(VecDestroy(&F3));
536 PetscCall(VecDestroy(&Xfinal)); PetscCall(VecDestroy(&res_cgs.
Xfinal));
537 PetscCall(VecDestroy(&jv)); PetscCall(VecDestroy(&v));
538 PetscCall(VecDestroy(&Fafter)); PetscCall(VecDestroy(&F1)); PetscCall(VecDestroy(&F0));
539 PetscCall(VecDestroy(&X1)); PetscCall(VecDestroy(&X0));
541 PetscCall(VecDestroy(&user->
Rhs));
544 PetscFunctionReturn(PETSC_SUCCESS);