32 PetscReal mask_max = 0.0;
34 PetscFunctionBeginUser;
35 PetscCheck(user != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
36 "Newton Krylov requires a non-NULL UserCtx.");
38 PetscCheck(simCtx != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
39 "Newton Krylov requires UserCtx::simCtx.");
40 PetscCheck(simCtx->
block_number == 1, PETSC_COMM_WORLD, PETSC_ERR_SUP,
41 "Newton Krylov version one supports exactly one block (got %d).",
43 PetscCheck(!simCtx->
immersed, PETSC_COMM_WORLD, PETSC_ERR_SUP,
44 "Newton Krylov version one does not support immersed boundaries.");
45 PetscCheck(!simCtx->
movefsi && !simCtx->
rotatefsi, PETSC_COMM_WORLD, PETSC_ERR_SUP,
46 "Newton Krylov version one does not support moving or rotating bodies/FSI.");
48 "Newton Krylov version one does not support moving or rotating reference frames.");
49 PetscCheck(!simCtx->
rans, PETSC_COMM_WORLD, PETSC_ERR_SUP,
50 "Newton Krylov version one does not support RANS.");
51 PetscCheck(!simCtx->
clark, PETSC_COMM_WORLD, PETSC_ERR_SUP,
52 "Newton Krylov version one does not support the Clark model.");
53 PetscCheck(!simCtx->
TwoD, PETSC_COMM_WORLD, PETSC_ERR_SUP,
54 "Newton Krylov version one does not support TwoD component masking.");
55 PetscCheck(!simCtx->
wallfunction, PETSC_COMM_WORLD, PETSC_ERR_SUP,
56 "Newton Krylov version one does not support wall functions.");
57 PetscCheck(simCtx->
StartStep == 0, PETSC_COMM_WORLD, PETSC_ERR_SUP,
58 "Newton Krylov version one supports fresh starts only (StartStep must be zero)." );
60 for (PetscInt face = 0; face < 6; ++face) {
62 PetscBool supported = PETSC_FALSE;
80 supported = PETSC_FALSE;
83 PetscCheck(supported, PETSC_COMM_WORLD, PETSC_ERR_SUP,
84 "Newton Krylov version one does not support boundary face %d with mathematical type %d and handler %d.",
90 PETSC_COMM_WORLD, PETSC_ERR_SUP,
"Newton Krylov requires paired x-periodic faces.");
93 PETSC_COMM_WORLD, PETSC_ERR_SUP,
"Newton Krylov requires paired y-periodic faces.");
96 PETSC_COMM_WORLD, PETSC_ERR_SUP,
"Newton Krylov requires paired z-periodic faces.");
98 PetscCheck(user->
Nvert != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
99 "Newton Krylov requires the cell-mask vector Nvert.");
100 PetscCall(VecMax(user->
Nvert, NULL, &mask_max));
101 PetscCheck(mask_max <= 0.1, PETSC_COMM_WORLD, PETSC_ERR_SUP,
102 "Newton Krylov version one does not define equations for masked solid cells (max Nvert=%g).",
104 PetscFunctionReturn(PETSC_SUCCESS);
130 UserCtx *user, PetscInt i, PetscInt j, PetscInt k, PetscInt component,
131 PetscInt *ri, PetscInt *rj, PetscInt *rk)
133 const PetscInt mx = user->
info.mx, my = user->
info.my, mz = user->
info.mz;
134 const PetscInt coord[3] = {i, j, k};
135 const PetscInt size[3] = {mx, my, mz};
137 PetscBool periodic[3], periodic_duplicate = PETSC_FALSE;
138 PetscBool residual_zeroed = PETSC_FALSE, conditioned = PETSC_FALSE;
140 *ri = i; *rj = j; *rk = k;
141 for (PetscInt axis = 0; axis < 3; ++axis) {
142 periodic[axis] = (PetscBool)(
144 if (periodic[axis] && coord[axis] == 0) {
145 periodic_duplicate = PETSC_TRUE;
146 if (axis == 0) *ri = -2;
147 else if (axis == 1) *rj = -2;
150 if (periodic[axis] && coord[axis] == size[axis] - 1) {
151 periodic_duplicate = PETSC_TRUE;
152 if (axis == 0) *ri = mx + 1;
153 else if (axis == 1) *rj = my + 1;
157 if (!periodic[axis] && coord[axis] == 0) residual_zeroed = PETSC_TRUE;
158 if (coord[axis] == size[axis] - 1) residual_zeroed = PETSC_TRUE;
159 if (!periodic[axis] && coord[axis] == size[axis] - 2 && component == axis)
160 residual_zeroed = PETSC_TRUE;
163 if (!periodic[component] &&
164 (coord[component] == 0 || coord[component] == size[component] - 2)) {
165 PetscBool tangential_interior = PETSC_TRUE;
166 for (PetscInt axis = 0; axis < 3; ++axis) {
167 if (axis == component)
continue;
168 if (coord[axis] < 1 || coord[axis] > size[axis] - 2)
169 tangential_interior = PETSC_FALSE;
171 conditioned = tangential_interior;
199 DMDALocalInfo info = user->
info;
201 Cmpnts ***x = NULL, ***conditioned = NULL, ***f = NULL, ***lx = NULL;
202 const PetscInt xs = info.xs, xe = info.xs + info.xm;
203 const PetscInt ys = info.ys, ye = info.ys + info.ym;
204 const PetscInt zs = info.zs, ze = info.zs + info.zm;
206 PetscFunctionBeginUser;
207 PetscCall(DMGetLocalVector(user->
fda, &local_x));
208 PetscCall(DMGlobalToLocalBegin(user->
fda, X, INSERT_VALUES, local_x));
209 PetscCall(DMGlobalToLocalEnd(user->
fda, X, INSERT_VALUES, local_x));
210 PetscCall(DMDAVecGetArrayRead(user->
fda, X, &x));
211 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucont, &conditioned));
212 PetscCall(DMDAVecGetArray(user->
fda, F, &f));
213 PetscCall(DMDAVecGetArrayRead(user->
fda, local_x, &lx));
215 for (PetscInt k = zs; k < ze; ++k) {
216 for (PetscInt j = ys; j < ye; ++j) {
217 for (PetscInt i = xs; i < xe; ++i) {
218 PetscScalar *fv = &f[k][j][i].x;
219 const PetscScalar *xv = &x[k][j][i].
x;
220 const PetscScalar *cv = &conditioned[k][j][i].x;
222 for (PetscInt component = 0; component < 3; ++component) {
225 user, i, j, k, component, &ri, &rj, &rk);
226 const PetscScalar *rv = &lx[rk][rj][ri].x;
236 PetscCall(DMDAVecRestoreArrayRead(user->
fda, local_x, &lx));
237 PetscCall(DMDAVecRestoreArray(user->
fda, F, &f));
238 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucont, &conditioned));
239 PetscCall(DMDAVecRestoreArrayRead(user->
fda, X, &x));
240 PetscCall(DMRestoreLocalVector(user->
fda, &local_x));
241 PetscFunctionReturn(PETSC_SUCCESS);
288 PetscErrorCode ierr = PETSC_SUCCESS, cleanup_ierr;
292 Vec solution = NULL, entry_backup = NULL;
295 const char *pc_type = NULL;
296 PetscBool pc_is_none = PETSC_FALSE;
297 PetscBool restore_entry = PETSC_FALSE;
298 PetscBool rhs_created = PETSC_FALSE;
299 SNESConvergedReason reason = SNES_CONVERGED_ITERATING;
300 PetscInt nonlinear_its = 0, function_evals = 0, linear_its = 0;
301 PetscReal final_norm = PETSC_MAX_REAL;
303 const char *staggered_fields[] = {
"Ucont"};
305 PetscFunctionBeginUser;
307 PetscCheck(ibm == NULL && fsi == NULL, PETSC_COMM_WORLD, PETSC_ERR_SUP,
308 "Newton Krylov version one does not accept IBM or FSI objects.");
309 PetscCheck(user->
Rhs == NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE,
310 "Newton Krylov requires UserCtx::Rhs to be unallocated on entry.");
313 ierr = VecDuplicate(user->
Ucont, &solution);
if (ierr)
goto cleanup;
314 ierr = VecDuplicate(user->
Ucont, &entry_backup);
if (ierr)
goto cleanup;
315 ierr = VecDuplicate(user->
Ucont, &user->
Rhs);
if (ierr)
goto cleanup;
316 rhs_created = PETSC_TRUE;
317 ierr = SNESCreate(PetscObjectComm((PetscObject)user->
Ucont), &snes);
if (ierr)
goto cleanup;
321 ierr = VecCopy(user->
Ucont, entry_backup);
if (ierr)
goto cleanup;
322 restore_entry = PETSC_TRUE;
323 ierr = VecCopy(user->
Ucont, solution);
if (ierr)
goto cleanup;
326 ierr = SNESSetOptionsPrefix(snes,
"mom_nk_");
if (ierr)
goto cleanup;
327 ierr = SNESSetType(snes, SNESNEWTONLS);
if (ierr)
goto cleanup;
328 ierr = SNESSetDM(snes, user->
fda);
if (ierr)
goto cleanup;
330 ierr = MatCreateSNESMF(snes, &J);
if (ierr)
goto cleanup;
331 ierr = SNESSetJacobian(snes, J, J, MatMFFDComputeJacobian, NULL);
if (ierr)
goto cleanup;
332 ierr = SNESGetKSP(snes, &ksp);
if (ierr)
goto cleanup;
333 ierr = KSPSetType(ksp, KSPGMRES);
if (ierr)
goto cleanup;
334 ierr = KSPGetPC(ksp, &pc);
if (ierr)
goto cleanup;
335 ierr = PCSetType(pc, PCNONE);
if (ierr)
goto cleanup;
336 ierr = SNESSetFromOptions(snes);
if (ierr)
goto cleanup;
337 ierr = PCGetType(pc, &pc_type);
if (ierr)
goto cleanup;
338 ierr = PetscStrcmp(pc_type, PCNONE, &pc_is_none);
if (ierr)
goto cleanup;
341 "Newton Krylov version one requires PCNONE; option processing selected PC type '%s'.\n",
342 pc_type ? pc_type :
"(unset)");
343 ierr = PETSC_ERR_SUP;
347 ierr = SNESSolve(snes, NULL, solution);
348 if (ierr)
goto cleanup;
349 ierr = SNESGetConvergedReason(snes, &reason);
if (ierr)
goto cleanup;
350 ierr = SNESGetIterationNumber(snes, &nonlinear_its);
if (ierr)
goto cleanup;
351 ierr = SNESGetNumberFunctionEvals(snes, &function_evals);
if (ierr)
goto cleanup;
352 ierr = SNESGetLinearSolveIterations(snes, &linear_its);
if (ierr)
goto cleanup;
353 ierr = SNESGetFunctionNorm(snes, &final_norm);
if (ierr)
goto cleanup;
356 ierr = VecCopy(solution, user->
Ucont);
if (ierr)
goto cleanup;
359 ierr = VecCopy(entry_backup, user->
Ucont);
if (ierr)
goto cleanup;
364 restore_entry = PETSC_FALSE;
367 "Newton Krylov momentum solve: reason=%s (%d), Newton iterations=%d, residual evaluations=%d, Krylov iterations=%d, final norm=%.6e, state=%s.\n",
368 SNESConvergedReasons[reason], (PetscInt)reason, nonlinear_its, function_evals,
369 linear_its, (
double)final_norm, reason > 0 ?
"committed" :
"rolled back");
370 if (reason <= 0) ierr = PETSC_ERR_CONV_FAILED;
373 if (restore_entry && entry_backup) {
374 cleanup_ierr = VecCopy(entry_backup, user->
Ucont);
375 if (!ierr) ierr = cleanup_ierr;
377 if (!ierr) ierr = cleanup_ierr;
379 if (!ierr) ierr = cleanup_ierr;
383 cleanup_ierr = VecDestroy(&user->
Rhs);
384 if (!ierr) ierr = cleanup_ierr;
386 cleanup_ierr = VecDestroy(&entry_backup);
if (!ierr) ierr = cleanup_ierr;
387 cleanup_ierr = VecDestroy(&solution);
if (!ierr) ierr = cleanup_ierr;
388 cleanup_ierr = MatDestroy(&J);
if (!ierr) ierr = cleanup_ierr;
389 cleanup_ierr = SNESDestroy(&snes);
if (!ierr) ierr = cleanup_ierr;
390 PetscFunctionReturn(ierr);