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);
354 char tmpdir[PETSC_MAX_PATH_LEN] =
"";
357 Vec X0 = NULL, X1 = NULL, Xfinal = NULL;
358 Vec F0 = NULL, F1 = NULL, Fafter = NULL, v = NULL, jv = NULL;
359 Vec F3 = NULL, F24 = NULL;
361 PetscReal norms[2] = {0.0, 0.0};
362 PetscReal imm_inf = 0.0, imm_2 = 0.0, mffd_inf = 0.0, mffd_2 = 0.0;
363 PetscReal f3_2 = 0.0, f24_2 = 0.0, f24_inf = 0.0, f24m3_inf = 0.0, f24m3_2 = 0.0;
364 PetscReal max_div = -1.0;
365 const char *fields[] = {
"Ucont"};
366 const char *stag[] = {
"Ucont"};
const char *cell[] = {
"Ucat"};
367 const PetscReal purity_inf_tol = 1e-13, purity_2_tol = 1e-12;
368 const PetscReal compat_tol = 1e-8, div_tol = 1e-6;
369 PetscMPIInt world, mffd_rank = 0;
370 PetscErrorCode prod_ierr;
372 PetscFunctionBeginUser;
373 PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &world));
374 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
375 "\n########## NEWTON-KRYLOV PRODUCTION REGRESSION (ranks=%d) ##########\n", (
int)world));
382 simCtx->
step = 1; simCtx->
ti = simCtx->
dt;
385 simCtx->
step = 2; simCtx->
ti = 2.0 * simCtx->
dt;
387 PetscCall(VecDuplicate(user->
Ucont, &user->
Rhs));
394 PetscCall(VecDuplicate(user->
Ucont, &X0)); PetscCall(VecCopy(user->
Ucont, X0));
397 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
"\n===== 4.1 production-callback residual purity =====\n"));
399 SNES snes = NULL; Mat J = NULL; KSP ksp = NULL;
400 PetscCall(VecDuplicate(X0, &X1)); PetscCall(VecCopy(X0, X1));
402 PetscCall(SNESSetConvergenceTest(snes,
StopAfterOne, norms, NULL));
403 PetscCall(SNESSolve(snes, NULL, X1));
404 PetscCall(MatDestroy(&J)); PetscCall(SNESDestroy(&snes));
406 PetscCall(VecDuplicate(X1, &F0)); PetscCall(VecDuplicate(X1, &F1));
407 PetscCall(VecDuplicate(X1, &Fafter)); PetscCall(VecDuplicate(X1, &v)); PetscCall(VecDuplicate(X1, &jv));
413 PetscCall(VecSet(user->
Ucat, 7.0)); PetscCall(VecSet(user->
lUcat, 7.0));
416 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
417 "PURITY immediate inf=% .3e l2=% .3e (tol inf=%.0e l2=%.0e)\n",
418 (
double)imm_inf, (
double)imm_2, (
double)purity_inf_tol, (
double)purity_2_tol));
422 SNES snes = NULL; Mat J = NULL; KSP ksp = NULL;
423 PetscInt lo, hi; PetscScalar *a = NULL; PetscReal vn;
424 PetscCall(VecGetOwnershipRange(v, &lo, &hi));
425 PetscCall(VecGetArray(v, &a));
426 for (PetscInt i = lo; i < hi; ++i) a[i - lo] = PetscSinReal(0.17 * (PetscReal)(i + 1));
427 PetscCall(VecRestoreArray(v, &a));
428 PetscCall(VecNorm(v, NORM_2, &vn)); PetscCall(VecScale(v, 1.0 / vn));
430 PetscCall(MatMFFDSetBase(J, X1, F0));
431 for (PetscInt i = 0; i < 40; ++i) PetscCall(MatMult(J, v, jv));
435 PetscCall(MatDestroy(&J)); PetscCall(SNESDestroy(&snes));
437 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
438 "PURITY post_mffd inf=% .3e l2=% .3e max_rank=%d\n",
439 (
double)mffd_inf, (
double)mffd_2, (
int)mffd_rank));
442 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
"\n===== 4.2 full production step-2 solve (default classical GS) =====\n"));
448 PetscCall(VecDestroy(&user->
Rhs));
449 prod_ierr = MomentumSolver_NewtonKrylov_BoundaryFixedpointPrivateCopy(user, NULL, NULL);
450 PetscCall(VecDuplicate(user->
Ucont, &user->
Rhs));
451 PetscCall(VecDuplicate(user->
Ucont, &Xfinal)); PetscCall(VecCopy(user->
Ucont, Xfinal));
452 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
453 "PROD_SOLVER ierr=%d mom_last_converged=%d\n",
456 PetscReal dinf, d2; PetscMPIInt r;
459 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
460 "PROD_SOLVER test_snes_vs_wrapper inf=% .3e l2=% .3e max_rank=%d\n",
461 (
double)dinf, (
double)d2, (
int)r));
465 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
"\n===== 4.3 boundary-map compatibility (3 vs 24 passes) =====\n"));
466 PetscCall(VecDuplicate(Xfinal, &F3)); PetscCall(VecDuplicate(Xfinal, &F24));
469 PetscCall(VecNorm(F3, NORM_2, &f3_2));
472 PetscCall(VecNorm(F24, NORM_2, &f24_2));
473 PetscCall(VecNorm(F24, NORM_INFINITY, &f24_inf));
475 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
476 "COMPAT F3_l2=% .6e F24_l2=% .6e F24_inf=% .6e F24_minus_F3_l2=% .6e (tol %.0e)\n",
477 (
double)f3_2, (
double)f24_2, (
double)f24_inf, (
double)f24m3_2, (
double)compat_tol));
480 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
"\n===== 4.4 projection compatibility =====\n"));
482 PetscCall(VecCopy(Xfinal, user->
Ucont));
494 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
495 "PROJECTION max_divergence=% .6e net_divergence_sum=% .6e (tol %.0e)\n",
496 (
double)max_div, (
double)simCtx->
summationRHS, (
double)div_tol));
499 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
"\nREGRESSION_VERDICTS (ranks=%d)\n", (
int)world));
500 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
" PRODUCTION_PURITY: %s\n",
501 (imm_inf <= purity_inf_tol && imm_2 <= purity_2_tol &&
502 mffd_inf <= purity_inf_tol && mffd_2 <= purity_2_tol) ?
"PASS" :
"FAIL"));
503 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
" FULL_STEP2_DEFAULT_GS: %s\n",
505 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
" PRODUCTION_SOLVER_WRAPPER: %s\n",
507 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
" THREE_PASS_24_PASS_COMPATIBLE: %s\n",
508 (f24_2 <= compat_tol) ?
"PASS" :
"FAIL"));
509 PetscCall(PetscPrintf(PETSC_COMM_WORLD,
" PROJECTION_DIVERGENCE_FREE: %s\n",
510 (max_div <= div_tol) ?
"PASS" :
"FAIL"));
513 PetscCheck(imm_inf <= purity_inf_tol && imm_2 <= purity_2_tol, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
514 "production residual not immediately repeatable (inf=%g l2=%g)", (
double)imm_inf, (
double)imm_2);
515 PetscCheck(mffd_inf <= purity_inf_tol && mffd_2 <= purity_2_tol, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
516 "production residual changed after MFFD products (inf=%g l2=%g)", (
double)mffd_inf, (
double)mffd_2);
517 PetscCheck(res_cgs.
converged, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
518 "full step-2 solve (default GS) did not converge (reason=%d)", (
int)res_cgs.
reason);
519 PetscCheck(res_cgs.
reason != SNES_DIVERGED_LINE_SEARCH && res_cgs.
reason != SNES_DIVERGED_LINEAR_SOLVE,
520 PETSC_COMM_WORLD, PETSC_ERR_PLIB,
"full step-2 solve diverged via line search or linear solve (reason=%d)",
522 PetscCheck(prod_ierr == 0 && simCtx->
mom_last_converged, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
523 "production Newton-Krylov solver wrapper did not converge (ierr=%d)", (
int)prod_ierr);
524 PetscCheck(f24_2 <= compat_tol, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
525 "converged three-pass solution does not satisfy the 24-pass residual (||F24||2=%g)", (
double)f24_2);
526 PetscCheck(max_div <= div_tol, PETSC_COMM_WORLD, PETSC_ERR_PLIB,
527 "projection of the converged momentum state is not divergence free (max_div=%g)", (
double)max_div);
529 PetscCall(VecDestroy(&F24)); PetscCall(VecDestroy(&F3));
530 PetscCall(VecDestroy(&Xfinal)); PetscCall(VecDestroy(&res_cgs.
Xfinal));
531 PetscCall(VecDestroy(&jv)); PetscCall(VecDestroy(&v));
532 PetscCall(VecDestroy(&Fafter)); PetscCall(VecDestroy(&F1)); PetscCall(VecDestroy(&F0));
533 PetscCall(VecDestroy(&X1)); PetscCall(VecDestroy(&X0));
535 PetscCall(VecDestroy(&user->
Rhs));
538 PetscFunctionReturn(PETSC_SUCCESS);