1 static char help[] = "Bratu nonlinear PDE in 2d.\n\ 2 We solve the Bratu (SFI - solid fuel ignition) problem in a 2D rectangular\n\ 3 domain, using distributed arrays (DMDAs) to partition the parallel grid.\n\ 4 The command line options include:\n\ 5 -par <parameter>, where <parameter> indicates the problem's nonlinearity\n\ 6 problem SFI: <parameter> = Bratu parameter (0 <= par <= 6.81)\n\n\ 7 -m_par/n_par <parameter>, where <parameter> indicates an integer\n \ 8 that MMS3 will be evaluated with 2^m_par, 2^n_par"; 9 10 /* ------------------------------------------------------------------------ 11 12 Solid Fuel Ignition (SFI) problem. This problem is modeled by 13 the partial differential equation 14 15 -Laplacian u - lambda*exp(u) = 0, 0 < x,y < 1, 16 17 with boundary conditions 18 19 u = 0 for x = 0, x = 1, y = 0, y = 1. 20 21 A finite difference approximation with the usual 5-point stencil 22 is used to discretize the boundary value problem to obtain a nonlinear 23 system of equations. 24 25 This example shows how geometric multigrid can be run transparently with a nonlinear solver so long 26 as SNESSetDM() is provided. Example usage 27 28 ./ex5 -pc_type mg -ksp_monitor -snes_view -pc_mg_levels 3 -pc_mg_galerkin pmat -da_grid_x 17 -da_grid_y 17 29 -mg_levels_ksp_monitor -snes_monitor -mg_levels_pc_type sor -pc_mg_type full 30 31 or to run with grid sequencing on the nonlinear problem (note that you do not need to provide the number of 32 multigrid levels, it will be determined automatically based on the number of refinements done) 33 34 ./ex5 -pc_type mg -ksp_monitor -snes_view -pc_mg_galerkin pmat -snes_grid_sequence 3 35 -mg_levels_ksp_monitor -snes_monitor -mg_levels_pc_type sor -pc_mg_type full 36 37 ------------------------------------------------------------------------- */ 38 39 /* 40 Include "petscdmda.h" so that we can use distributed arrays (DMDAs). 41 Include "petscsnes.h" so that we can use SNES solvers. Note that this 42 */ 43 #include <petscdm.h> 44 #include <petscdmda.h> 45 #include <petscsnes.h> 46 #include <petscmatlab.h> 47 #include <petsc/private/snesimpl.h> /* For SNES_Solve event */ 48 49 /* 50 User-defined application context - contains data needed by the 51 application-provided call-back routines, FormJacobianLocal() and 52 FormFunctionLocal(). 53 */ 54 typedef struct AppCtx AppCtx; 55 struct AppCtx { 56 PetscReal param; /* test problem parameter */ 57 PetscInt m, n; /* MMS3 parameters */ 58 PetscErrorCode (*mms_solution)(AppCtx *, const DMDACoor2d *, PetscScalar *); 59 PetscErrorCode (*mms_forcing)(AppCtx *, const DMDACoor2d *, PetscScalar *); 60 }; 61 62 /* ------------------------------------------------------------------- */ 63 /* 64 FormInitialGuess - Forms initial approximation. 65 66 Input Parameters: 67 da - The DM 68 user - user-defined application context 69 70 Output Parameter: 71 X - vector 72 */ 73 static PetscErrorCode FormInitialGuess(DM da, AppCtx *user, Vec X) 74 { 75 PetscInt i, j, Mx, My, xs, ys, xm, ym; 76 PetscReal lambda, temp1, temp, hx, hy; 77 PetscScalar **x; 78 79 PetscFunctionBeginUser; 80 PetscCall(DMDAGetInfo(da, PETSC_IGNORE, &Mx, &My, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE)); 81 82 lambda = user->param; 83 hx = 1.0 / (PetscReal)(Mx - 1); 84 hy = 1.0 / (PetscReal)(My - 1); 85 temp1 = lambda / (lambda + 1.0); 86 87 /* 88 Get a pointer to vector data. 89 - For default PETSc vectors, VecGetArray() returns a pointer to 90 the data array. Otherwise, the routine is implementation dependent. 91 - You MUST call VecRestoreArray() when you no longer need access to 92 the array. 93 */ 94 PetscCall(DMDAVecGetArray(da, X, &x)); 95 96 /* 97 Get local grid boundaries (for 2-dimensional DMDA): 98 xs, ys - starting grid indices (no ghost points) 99 xm, ym - widths of local grid (no ghost points) 100 101 */ 102 PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &xm, &ym, NULL)); 103 104 /* 105 Compute initial guess over the locally owned part of the grid 106 */ 107 for (j = ys; j < ys + ym; j++) { 108 temp = (PetscReal)(PetscMin(j, My - j - 1)) * hy; 109 for (i = xs; i < xs + xm; i++) { 110 if (i == 0 || j == 0 || i == Mx - 1 || j == My - 1) { 111 /* boundary conditions are all zero Dirichlet */ 112 x[j][i] = 0.0; 113 } else { 114 x[j][i] = temp1 * PetscSqrtReal(PetscMin((PetscReal)(PetscMin(i, Mx - i - 1)) * hx, temp)); 115 } 116 } 117 } 118 119 /* 120 Restore vector 121 */ 122 PetscCall(DMDAVecRestoreArray(da, X, &x)); 123 PetscFunctionReturn(PETSC_SUCCESS); 124 } 125 126 /* 127 FormExactSolution - Forms MMS solution 128 129 Input Parameters: 130 da - The DM 131 user - user-defined application context 132 133 Output Parameter: 134 X - vector 135 */ 136 static PetscErrorCode FormExactSolution(DM da, AppCtx *user, Vec U) 137 { 138 DM coordDA; 139 Vec coordinates; 140 DMDACoor2d **coords; 141 PetscScalar **u; 142 PetscInt xs, ys, xm, ym, i, j; 143 144 PetscFunctionBeginUser; 145 PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &xm, &ym, NULL)); 146 PetscCall(DMGetCoordinateDM(da, &coordDA)); 147 PetscCall(DMGetCoordinates(da, &coordinates)); 148 PetscCall(DMDAVecGetArray(coordDA, coordinates, &coords)); 149 PetscCall(DMDAVecGetArray(da, U, &u)); 150 for (j = ys; j < ys + ym; ++j) { 151 for (i = xs; i < xs + xm; ++i) PetscCall(user->mms_solution(user, &coords[j][i], &u[j][i])); 152 } 153 PetscCall(DMDAVecRestoreArray(da, U, &u)); 154 PetscCall(DMDAVecRestoreArray(coordDA, coordinates, &coords)); 155 PetscFunctionReturn(PETSC_SUCCESS); 156 } 157 158 static PetscErrorCode ZeroBCSolution(AppCtx *user, const DMDACoor2d *c, PetscScalar *u) 159 { 160 u[0] = 0.; 161 return PETSC_SUCCESS; 162 } 163 164 /* The functions below evaluate the MMS solution u(x,y) and associated forcing 165 166 f(x,y) = -u_xx - u_yy - lambda exp(u) 167 168 such that u(x,y) is an exact solution with f(x,y) as the right-hand side forcing term. 169 */ 170 static PetscErrorCode MMSSolution1(AppCtx *user, const DMDACoor2d *c, PetscScalar *u) 171 { 172 PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 173 174 PetscFunctionBeginUser; 175 u[0] = x * (1 - x) * y * (1 - y); 176 PetscCall(PetscLogFlops(5)); 177 PetscFunctionReturn(PETSC_SUCCESS); 178 } 179 static PetscErrorCode MMSForcing1(AppCtx *user, const DMDACoor2d *c, PetscScalar *f) 180 { 181 PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 182 183 PetscFunctionBeginUser; 184 f[0] = 2 * x * (1 - x) + 2 * y * (1 - y) - user->param * PetscExpReal(x * (1 - x) * y * (1 - y)); 185 PetscFunctionReturn(PETSC_SUCCESS); 186 } 187 188 static PetscErrorCode MMSSolution2(AppCtx *user, const DMDACoor2d *c, PetscScalar *u) 189 { 190 PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 191 192 PetscFunctionBeginUser; 193 u[0] = PetscSinReal(PETSC_PI * x) * PetscSinReal(PETSC_PI * y); 194 PetscCall(PetscLogFlops(5)); 195 PetscFunctionReturn(PETSC_SUCCESS); 196 } 197 static PetscErrorCode MMSForcing2(AppCtx *user, const DMDACoor2d *c, PetscScalar *f) 198 { 199 PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 200 201 PetscFunctionBeginUser; 202 f[0] = 2 * PetscSqr(PETSC_PI) * PetscSinReal(PETSC_PI * x) * PetscSinReal(PETSC_PI * y) - user->param * PetscExpReal(PetscSinReal(PETSC_PI * x) * PetscSinReal(PETSC_PI * y)); 203 PetscFunctionReturn(PETSC_SUCCESS); 204 } 205 206 static PetscErrorCode MMSSolution3(AppCtx *user, const DMDACoor2d *c, PetscScalar *u) 207 { 208 PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 209 210 PetscFunctionBeginUser; 211 u[0] = PetscSinReal(user->m * PETSC_PI * x * (1 - y)) * PetscSinReal(user->n * PETSC_PI * y * (1 - x)); 212 PetscCall(PetscLogFlops(5)); 213 PetscFunctionReturn(PETSC_SUCCESS); 214 } 215 static PetscErrorCode MMSForcing3(AppCtx *user, const DMDACoor2d *c, PetscScalar *f) 216 { 217 PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 218 PetscReal m = user->m, n = user->n, lambda = user->param; 219 220 PetscFunctionBeginUser; 221 f[0] = (-(PetscExpReal(PetscSinReal(m * PETSC_PI * x * (1 - y)) * PetscSinReal(n * PETSC_PI * (1 - x) * y)) * lambda) + PetscSqr(PETSC_PI) * (-2 * m * n * ((-1 + x) * x + (-1 + y) * y) * PetscCosReal(m * PETSC_PI * x * (-1 + y)) * PetscCosReal(n * PETSC_PI * (-1 + x) * y) + (PetscSqr(m) * (PetscSqr(x) + PetscSqr(-1 + y)) + PetscSqr(n) * (PetscSqr(-1 + x) + PetscSqr(y))) * PetscSinReal(m * PETSC_PI * x * (-1 + y)) * PetscSinReal(n * PETSC_PI * (-1 + x) * y))); 222 PetscFunctionReturn(PETSC_SUCCESS); 223 } 224 225 static PetscErrorCode MMSSolution4(AppCtx *user, const DMDACoor2d *c, PetscScalar *u) 226 { 227 const PetscReal Lx = 1., Ly = 1.; 228 PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 229 230 PetscFunctionBeginUser; 231 u[0] = (PetscPowReal(x, 4) - PetscSqr(Lx) * PetscSqr(x)) * (PetscPowReal(y, 4) - PetscSqr(Ly) * PetscSqr(y)); 232 PetscCall(PetscLogFlops(9)); 233 PetscFunctionReturn(PETSC_SUCCESS); 234 } 235 static PetscErrorCode MMSForcing4(AppCtx *user, const DMDACoor2d *c, PetscScalar *f) 236 { 237 const PetscReal Lx = 1., Ly = 1.; 238 PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 239 240 PetscFunctionBeginUser; 241 f[0] = (2 * PetscSqr(x) * (PetscSqr(x) - PetscSqr(Lx)) * (PetscSqr(Ly) - 6 * PetscSqr(y)) + 2 * PetscSqr(y) * (PetscSqr(Lx) - 6 * PetscSqr(x)) * (PetscSqr(y) - PetscSqr(Ly)) - user->param * PetscExpReal((PetscPowReal(x, 4) - PetscSqr(Lx) * PetscSqr(x)) * (PetscPowReal(y, 4) - PetscSqr(Ly) * PetscSqr(y)))); 242 PetscFunctionReturn(PETSC_SUCCESS); 243 } 244 245 /* ------------------------------------------------------------------- */ 246 /* 247 FormFunctionLocal - Evaluates nonlinear function, F(x) on local process patch 248 249 */ 250 static PetscErrorCode FormFunctionLocal(DMDALocalInfo *info, PetscScalar **x, PetscScalar **f, AppCtx *user) 251 { 252 PetscInt i, j; 253 PetscReal lambda, hx, hy, hxdhy, hydhx; 254 PetscScalar u, ue, uw, un, us, uxx, uyy, mms_solution, mms_forcing; 255 DMDACoor2d c; 256 257 PetscFunctionBeginUser; 258 lambda = user->param; 259 hx = 1.0 / (PetscReal)(info->mx - 1); 260 hy = 1.0 / (PetscReal)(info->my - 1); 261 hxdhy = hx / hy; 262 hydhx = hy / hx; 263 /* 264 Compute function over the locally owned part of the grid 265 */ 266 for (j = info->ys; j < info->ys + info->ym; j++) { 267 for (i = info->xs; i < info->xs + info->xm; i++) { 268 if (i == 0 || j == 0 || i == info->mx - 1 || j == info->my - 1) { 269 c.x = i * hx; 270 c.y = j * hy; 271 PetscCall(user->mms_solution(user, &c, &mms_solution)); 272 f[j][i] = 2.0 * (hydhx + hxdhy) * (x[j][i] - mms_solution); 273 } else { 274 u = x[j][i]; 275 uw = x[j][i - 1]; 276 ue = x[j][i + 1]; 277 un = x[j - 1][i]; 278 us = x[j + 1][i]; 279 280 /* Enforce boundary conditions at neighboring points -- setting these values causes the Jacobian to be symmetric. */ 281 if (i - 1 == 0) { 282 c.x = (i - 1) * hx; 283 c.y = j * hy; 284 PetscCall(user->mms_solution(user, &c, &uw)); 285 } 286 if (i + 1 == info->mx - 1) { 287 c.x = (i + 1) * hx; 288 c.y = j * hy; 289 PetscCall(user->mms_solution(user, &c, &ue)); 290 } 291 if (j - 1 == 0) { 292 c.x = i * hx; 293 c.y = (j - 1) * hy; 294 PetscCall(user->mms_solution(user, &c, &un)); 295 } 296 if (j + 1 == info->my - 1) { 297 c.x = i * hx; 298 c.y = (j + 1) * hy; 299 PetscCall(user->mms_solution(user, &c, &us)); 300 } 301 302 uxx = (2.0 * u - uw - ue) * hydhx; 303 uyy = (2.0 * u - un - us) * hxdhy; 304 mms_forcing = 0; 305 c.x = i * hx; 306 c.y = j * hy; 307 if (user->mms_forcing) PetscCall(user->mms_forcing(user, &c, &mms_forcing)); 308 f[j][i] = uxx + uyy - hx * hy * (lambda * PetscExpScalar(u) + mms_forcing); 309 } 310 } 311 } 312 PetscCall(PetscLogFlops(11.0 * info->ym * info->xm)); 313 PetscFunctionReturn(PETSC_SUCCESS); 314 } 315 316 /* FormObjectiveLocal - Evaluates nonlinear function, F(x) on local process patch */ 317 static PetscErrorCode FormObjectiveLocal(DMDALocalInfo *info, PetscScalar **x, PetscReal *obj, AppCtx *user) 318 { 319 PetscInt i, j; 320 PetscReal lambda, hx, hy, hxdhy, hydhx, sc, lobj = 0; 321 PetscScalar u, ue, uw, un, us, uxux, uyuy; 322 MPI_Comm comm; 323 324 PetscFunctionBeginUser; 325 *obj = 0; 326 PetscCall(PetscObjectGetComm((PetscObject)info->da, &comm)); 327 lambda = user->param; 328 hx = 1.0 / (PetscReal)(info->mx - 1); 329 hy = 1.0 / (PetscReal)(info->my - 1); 330 sc = hx * hy * lambda; 331 hxdhy = hx / hy; 332 hydhx = hy / hx; 333 /* 334 Compute function over the locally owned part of the grid 335 */ 336 for (j = info->ys; j < info->ys + info->ym; j++) { 337 for (i = info->xs; i < info->xs + info->xm; i++) { 338 if (i == 0 || j == 0 || i == info->mx - 1 || j == info->my - 1) { 339 lobj += PetscRealPart((hydhx + hxdhy) * x[j][i] * x[j][i]); 340 } else { 341 u = x[j][i]; 342 uw = x[j][i - 1]; 343 ue = x[j][i + 1]; 344 un = x[j - 1][i]; 345 us = x[j + 1][i]; 346 347 if (i - 1 == 0) uw = 0.; 348 if (i + 1 == info->mx - 1) ue = 0.; 349 if (j - 1 == 0) un = 0.; 350 if (j + 1 == info->my - 1) us = 0.; 351 352 /* F[u] = 1/2\int_{\omega}\nabla^2u(x)*u(x)*dx */ 353 354 uxux = u * (2. * u - ue - uw) * hydhx; 355 uyuy = u * (2. * u - un - us) * hxdhy; 356 357 lobj += PetscRealPart(0.5 * (uxux + uyuy) - sc * PetscExpScalar(u)); 358 } 359 } 360 } 361 PetscCall(PetscLogFlops(12.0 * info->ym * info->xm)); 362 *obj = lobj; 363 PetscFunctionReturn(PETSC_SUCCESS); 364 } 365 366 /* 367 FormJacobianLocal - Evaluates Jacobian matrix on local process patch 368 */ 369 static PetscErrorCode FormJacobianLocal(DMDALocalInfo *info, PetscScalar **x, Mat jac, Mat jacpre, AppCtx *user) 370 { 371 PetscInt i, j, k; 372 MatStencil col[5], row; 373 PetscScalar lambda, v[5], hx, hy, hxdhy, hydhx, sc; 374 DM coordDA; 375 Vec coordinates; 376 DMDACoor2d **coords; 377 378 PetscFunctionBeginUser; 379 lambda = user->param; 380 /* Extract coordinates */ 381 PetscCall(DMGetCoordinateDM(info->da, &coordDA)); 382 PetscCall(DMGetCoordinates(info->da, &coordinates)); 383 PetscCall(DMDAVecGetArray(coordDA, coordinates, &coords)); 384 hx = info->xm > 1 ? PetscRealPart(coords[info->ys][info->xs + 1].x) - PetscRealPart(coords[info->ys][info->xs].x) : 1.0; 385 hy = info->ym > 1 ? PetscRealPart(coords[info->ys + 1][info->xs].y) - PetscRealPart(coords[info->ys][info->xs].y) : 1.0; 386 PetscCall(DMDAVecRestoreArray(coordDA, coordinates, &coords)); 387 hxdhy = hx / hy; 388 hydhx = hy / hx; 389 sc = hx * hy * lambda; 390 391 /* 392 Compute entries for the locally owned part of the Jacobian. 393 - Currently, all PETSc parallel matrix formats are partitioned by 394 contiguous chunks of rows across the processors. 395 - Each processor needs to insert only elements that it owns 396 locally (but any non-local elements will be sent to the 397 appropriate processor during matrix assembly). 398 - Here, we set all entries for a particular row at once. 399 - We can set matrix entries either using either 400 MatSetValuesLocal() or MatSetValues(), as discussed above. 401 */ 402 for (j = info->ys; j < info->ys + info->ym; j++) { 403 for (i = info->xs; i < info->xs + info->xm; i++) { 404 row.j = j; 405 row.i = i; 406 /* boundary points */ 407 if (i == 0 || j == 0 || i == info->mx - 1 || j == info->my - 1) { 408 v[0] = 2.0 * (hydhx + hxdhy); 409 PetscCall(MatSetValuesStencil(jacpre, 1, &row, 1, &row, v, INSERT_VALUES)); 410 } else { 411 k = 0; 412 /* interior grid points */ 413 if (j - 1 != 0) { 414 v[k] = -hxdhy; 415 col[k].j = j - 1; 416 col[k].i = i; 417 k++; 418 } 419 if (i - 1 != 0) { 420 v[k] = -hydhx; 421 col[k].j = j; 422 col[k].i = i - 1; 423 k++; 424 } 425 426 v[k] = 2.0 * (hydhx + hxdhy) - sc * PetscExpScalar(x[j][i]); 427 col[k].j = row.j; 428 col[k].i = row.i; 429 k++; 430 431 if (i + 1 != info->mx - 1) { 432 v[k] = -hydhx; 433 col[k].j = j; 434 col[k].i = i + 1; 435 k++; 436 } 437 if (j + 1 != info->mx - 1) { 438 v[k] = -hxdhy; 439 col[k].j = j + 1; 440 col[k].i = i; 441 k++; 442 } 443 PetscCall(MatSetValuesStencil(jacpre, 1, &row, k, col, v, INSERT_VALUES)); 444 } 445 } 446 } 447 448 /* 449 Assemble matrix, using the 2-step process: 450 MatAssemblyBegin(), MatAssemblyEnd(). 451 */ 452 PetscCall(MatAssemblyBegin(jacpre, MAT_FINAL_ASSEMBLY)); 453 PetscCall(MatAssemblyEnd(jacpre, MAT_FINAL_ASSEMBLY)); 454 /* 455 Tell the matrix we will never add a new nonzero location to the 456 matrix. If we do, it will generate an error. 457 */ 458 PetscCall(MatSetOption(jac, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 459 PetscFunctionReturn(PETSC_SUCCESS); 460 } 461 462 static PetscErrorCode FormFunctionMatlab(SNES snes, Vec X, Vec F, void *ptr) 463 { 464 #if PetscDefined(HAVE_MATLAB) 465 AppCtx *user = (AppCtx *)ptr; 466 PetscInt Mx, My; 467 PetscReal lambda, hx, hy; 468 Vec localX, localF; 469 MPI_Comm comm; 470 DM da; 471 472 PetscFunctionBeginUser; 473 PetscCall(SNESGetDM(snes, &da)); 474 PetscCall(DMGetLocalVector(da, &localX)); 475 PetscCall(DMGetLocalVector(da, &localF)); 476 PetscCall(PetscObjectSetName((PetscObject)localX, "localX")); 477 PetscCall(PetscObjectSetName((PetscObject)localF, "localF")); 478 PetscCall(DMDAGetInfo(da, PETSC_IGNORE, &Mx, &My, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE)); 479 480 lambda = user->param; 481 hx = 1.0 / (PetscReal)(Mx - 1); 482 hy = 1.0 / (PetscReal)(My - 1); 483 484 PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 485 /* 486 Scatter ghost points to local vector,using the 2-step process 487 DMGlobalToLocalBegin(),DMGlobalToLocalEnd(). 488 By placing code between these two statements, computations can be 489 done while messages are in transition. 490 */ 491 PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, localX)); 492 PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, localX)); 493 PetscCall(PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(comm), (PetscObject)localX)); 494 PetscCall(PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(comm), "localF=ex5m(localX,%18.16e,%18.16e,%18.16e)", (double)hx, (double)hy, (double)lambda)); 495 PetscCall(PetscMatlabEngineGet(PETSC_MATLAB_ENGINE_(comm), (PetscObject)localF)); 496 497 /* 498 Insert values into global vector 499 */ 500 PetscCall(DMLocalToGlobalBegin(da, localF, INSERT_VALUES, F)); 501 PetscCall(DMLocalToGlobalEnd(da, localF, INSERT_VALUES, F)); 502 PetscCall(DMRestoreLocalVector(da, &localX)); 503 PetscCall(DMRestoreLocalVector(da, &localF)); 504 PetscFunctionReturn(PETSC_SUCCESS); 505 #else 506 return PETSC_SUCCESS; /* Never called */ 507 #endif 508 } 509 510 /* ------------------------------------------------------------------- */ 511 /* 512 Applies some sweeps on nonlinear Gauss-Seidel on each process 513 514 */ 515 static PetscErrorCode NonlinearGS(SNES snes, Vec X, Vec B, void *ctx) 516 { 517 PetscInt i, j, k, Mx, My, xs, ys, xm, ym, its, tot_its, sweeps, l; 518 PetscReal lambda, hx, hy, hxdhy, hydhx, sc; 519 PetscScalar **x, **b, bij, F, F0 = 0, J, u, un, us, ue, eu, uw, uxx, uyy, y; 520 PetscReal atol, rtol, stol; 521 DM da; 522 AppCtx *user; 523 Vec localX, localB; 524 525 PetscFunctionBeginUser; 526 tot_its = 0; 527 PetscCall(SNESNGSGetSweeps(snes, &sweeps)); 528 PetscCall(SNESNGSGetTolerances(snes, &atol, &rtol, &stol, &its)); 529 PetscCall(SNESGetDM(snes, &da)); 530 PetscCall(DMGetApplicationContext(da, &user)); 531 532 PetscCall(DMDAGetInfo(da, PETSC_IGNORE, &Mx, &My, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE, PETSC_IGNORE)); 533 534 lambda = user->param; 535 hx = 1.0 / (PetscReal)(Mx - 1); 536 hy = 1.0 / (PetscReal)(My - 1); 537 sc = hx * hy * lambda; 538 hxdhy = hx / hy; 539 hydhx = hy / hx; 540 541 PetscCall(DMGetLocalVector(da, &localX)); 542 if (B) PetscCall(DMGetLocalVector(da, &localB)); 543 for (l = 0; l < sweeps; l++) { 544 PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, localX)); 545 PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, localX)); 546 if (B) { 547 PetscCall(DMGlobalToLocalBegin(da, B, INSERT_VALUES, localB)); 548 PetscCall(DMGlobalToLocalEnd(da, B, INSERT_VALUES, localB)); 549 } 550 /* 551 Get a pointer to vector data. 552 - For default PETSc vectors, VecGetArray() returns a pointer to 553 the data array. Otherwise, the routine is implementation dependent. 554 - You MUST call VecRestoreArray() when you no longer need access to 555 the array. 556 */ 557 PetscCall(DMDAVecGetArray(da, localX, &x)); 558 if (B) PetscCall(DMDAVecGetArray(da, localB, &b)); 559 /* 560 Get local grid boundaries (for 2-dimensional DMDA): 561 xs, ys - starting grid indices (no ghost points) 562 xm, ym - widths of local grid (no ghost points) 563 */ 564 PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &xm, &ym, NULL)); 565 566 for (j = ys; j < ys + ym; j++) { 567 for (i = xs; i < xs + xm; i++) { 568 if (i == 0 || j == 0 || i == Mx - 1 || j == My - 1) { 569 /* boundary conditions are all zero Dirichlet */ 570 x[j][i] = 0.0; 571 } else { 572 if (B) bij = b[j][i]; 573 else bij = 0.; 574 575 u = x[j][i]; 576 un = x[j - 1][i]; 577 us = x[j + 1][i]; 578 ue = x[j][i - 1]; 579 uw = x[j][i + 1]; 580 581 for (k = 0; k < its; k++) { 582 eu = PetscExpScalar(u); 583 uxx = (2.0 * u - ue - uw) * hydhx; 584 uyy = (2.0 * u - un - us) * hxdhy; 585 F = uxx + uyy - sc * eu - bij; 586 if (k == 0) F0 = F; 587 J = 2.0 * (hydhx + hxdhy) - sc * eu; 588 y = F / J; 589 u -= y; 590 tot_its++; 591 592 if (atol > PetscAbsReal(PetscRealPart(F)) || rtol * PetscAbsReal(PetscRealPart(F0)) > PetscAbsReal(PetscRealPart(F)) || stol * PetscAbsReal(PetscRealPart(u)) > PetscAbsReal(PetscRealPart(y))) break; 593 } 594 x[j][i] = u; 595 } 596 } 597 } 598 /* 599 Restore vector 600 */ 601 PetscCall(DMDAVecRestoreArray(da, localX, &x)); 602 PetscCall(DMLocalToGlobalBegin(da, localX, INSERT_VALUES, X)); 603 PetscCall(DMLocalToGlobalEnd(da, localX, INSERT_VALUES, X)); 604 } 605 PetscCall(PetscLogFlops(tot_its * (21.0))); 606 PetscCall(DMRestoreLocalVector(da, &localX)); 607 if (B) { 608 PetscCall(DMDAVecRestoreArray(da, localB, &b)); 609 PetscCall(DMRestoreLocalVector(da, &localB)); 610 } 611 PetscFunctionReturn(PETSC_SUCCESS); 612 } 613 614 int main(int argc, char **argv) 615 { 616 SNES snes; /* nonlinear solver */ 617 Vec x; /* solution vector */ 618 AppCtx user; /* user-defined work context */ 619 PetscInt its; /* iterations for convergence */ 620 PetscReal bratu_lambda_max = 6.81; 621 PetscReal bratu_lambda_min = 0.; 622 PetscInt MMS = 1; 623 PetscBool flg = PETSC_FALSE, setMMS; 624 DM da; 625 Vec r = NULL; 626 KSP ksp; 627 PetscInt lits, slits; 628 629 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 630 Initialize program 631 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 632 633 PetscFunctionBeginUser; 634 PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 635 636 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 637 Initialize problem parameters 638 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 639 user.param = 6.0; 640 PetscCall(PetscOptionsGetReal(NULL, NULL, "-par", &user.param, NULL)); 641 PetscCheck(user.param <= bratu_lambda_max && user.param >= bratu_lambda_min, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Lambda, %g, is out of range, [%g, %g]", (double)user.param, (double)bratu_lambda_min, (double)bratu_lambda_max); 642 PetscCall(PetscOptionsGetInt(NULL, NULL, "-mms", &MMS, &setMMS)); 643 if (MMS == 3) { 644 PetscInt mPar = 2, nPar = 1; 645 PetscCall(PetscOptionsGetInt(NULL, NULL, "-m_par", &mPar, NULL)); 646 PetscCall(PetscOptionsGetInt(NULL, NULL, "-n_par", &nPar, NULL)); 647 user.m = PetscPowInt(2, mPar); 648 user.n = PetscPowInt(2, nPar); 649 } 650 651 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 652 Create nonlinear solver context 653 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 654 PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes)); 655 PetscCall(SNESSetCountersReset(snes, PETSC_FALSE)); 656 PetscCall(SNESSetNGS(snes, NonlinearGS, NULL)); 657 658 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 659 Create distributed array (DMDA) to manage parallel grid and vectors 660 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 661 PetscCall(DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DMDA_STENCIL_STAR, 4, 4, PETSC_DECIDE, PETSC_DECIDE, 1, 1, NULL, NULL, &da)); 662 PetscCall(DMSetFromOptions(da)); 663 PetscCall(DMSetUp(da)); 664 PetscCall(DMDASetUniformCoordinates(da, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0)); 665 PetscCall(DMSetApplicationContext(da, &user)); 666 PetscCall(SNESSetDM(snes, da)); 667 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 668 Extract global vectors from DMDA; then duplicate for remaining 669 vectors that are the same types 670 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 671 PetscCall(DMCreateGlobalVector(da, &x)); 672 673 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 674 Set local function evaluation routine 675 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 676 switch (MMS) { 677 case 0: 678 user.mms_solution = ZeroBCSolution; 679 user.mms_forcing = NULL; 680 break; 681 case 1: 682 user.mms_solution = MMSSolution1; 683 user.mms_forcing = MMSForcing1; 684 break; 685 case 2: 686 user.mms_solution = MMSSolution2; 687 user.mms_forcing = MMSForcing2; 688 break; 689 case 3: 690 user.mms_solution = MMSSolution3; 691 user.mms_forcing = MMSForcing3; 692 break; 693 case 4: 694 user.mms_solution = MMSSolution4; 695 user.mms_forcing = MMSForcing4; 696 break; 697 default: 698 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_USER, "Unknown MMS type %" PetscInt_FMT, MMS); 699 } 700 PetscCall(DMDASNESSetFunctionLocal(da, INSERT_VALUES, (DMDASNESFunctionFn *)FormFunctionLocal, &user)); 701 PetscCall(PetscOptionsGetBool(NULL, NULL, "-fd", &flg, NULL)); 702 if (!flg) PetscCall(DMDASNESSetJacobianLocal(da, (DMDASNESJacobianFn *)FormJacobianLocal, &user)); 703 704 PetscCall(PetscOptionsGetBool(NULL, NULL, "-obj", &flg, NULL)); 705 if (flg) PetscCall(DMDASNESSetObjectiveLocal(da, (DMDASNESObjectiveFn *)FormObjectiveLocal, &user)); 706 707 if (PetscDefined(HAVE_MATLAB)) { 708 PetscBool matlab_function = PETSC_FALSE; 709 PetscCall(PetscOptionsGetBool(NULL, NULL, "-matlab_function", &matlab_function, 0)); 710 if (matlab_function) { 711 PetscCall(VecDuplicate(x, &r)); 712 PetscCall(SNESSetFunction(snes, r, FormFunctionMatlab, &user)); 713 } 714 } 715 716 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 717 Customize nonlinear solver; set runtime options 718 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 719 PetscCall(SNESSetFromOptions(snes)); 720 721 PetscCall(FormInitialGuess(da, &user, x)); 722 723 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 724 Solve nonlinear system 725 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 726 PetscCall(SNESSolve(snes, NULL, x)); 727 PetscCall(SNESGetIterationNumber(snes, &its)); 728 729 PetscCall(SNESGetLinearSolveIterations(snes, &slits)); 730 PetscCall(SNESGetKSP(snes, &ksp)); 731 PetscCall(KSPGetTotalIterations(ksp, &lits)); 732 PetscCheck(lits == slits, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Number of total linear iterations reported by SNES %" PetscInt_FMT " does not match reported by KSP %" PetscInt_FMT, slits, lits); 733 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 734 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 735 736 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 737 If using MMS, check the l_2 error 738 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 739 if (setMMS) { 740 Vec e; 741 PetscReal errorl2, errorinf; 742 PetscInt N; 743 744 PetscCall(VecDuplicate(x, &e)); 745 PetscCall(PetscObjectViewFromOptions((PetscObject)x, NULL, "-sol_view")); 746 PetscCall(FormExactSolution(da, &user, e)); 747 PetscCall(PetscObjectViewFromOptions((PetscObject)e, NULL, "-exact_view")); 748 PetscCall(VecAXPY(e, -1.0, x)); 749 PetscCall(PetscObjectViewFromOptions((PetscObject)e, NULL, "-error_view")); 750 PetscCall(VecNorm(e, NORM_2, &errorl2)); 751 PetscCall(VecNorm(e, NORM_INFINITY, &errorinf)); 752 PetscCall(VecGetSize(e, &N)); 753 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "N: %" PetscInt_FMT " error L2 %g inf %g\n", N, (double)(errorl2 / PetscSqrtReal((PetscReal)N)), (double)errorinf)); 754 PetscCall(VecDestroy(&e)); 755 PetscCall(PetscLogEventSetDof(SNES_Solve, 0, N)); 756 PetscCall(PetscLogEventSetError(SNES_Solve, 0, errorl2 / PetscSqrtReal(N))); 757 } 758 759 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 760 Free work space. All PETSc objects should be destroyed when they 761 are no longer needed. 762 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 763 PetscCall(VecDestroy(&r)); 764 PetscCall(VecDestroy(&x)); 765 PetscCall(SNESDestroy(&snes)); 766 PetscCall(DMDestroy(&da)); 767 PetscCall(PetscFinalize()); 768 return 0; 769 } 770 771 /*TEST 772 773 test: 774 suffix: asm_0 775 requires: !single 776 args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 2 -pc_asm_overlap 0 -pc_asm_local_type additive -sub_pc_type lu 777 778 test: 779 suffix: msm_0 780 requires: !single 781 args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 2 -pc_asm_overlap 0 -pc_asm_local_type multiplicative -sub_pc_type lu 782 783 test: 784 suffix: asm_1 785 requires: !single 786 args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 2 -pc_asm_overlap 0 -pc_asm_local_type additive -sub_pc_type lu -da_grid_x 8 787 788 test: 789 suffix: msm_1 790 requires: !single 791 args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 2 -pc_asm_overlap 0 -pc_asm_local_type multiplicative -sub_pc_type lu -da_grid_x 8 792 793 test: 794 suffix: asm_2 795 requires: !single 796 args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 3 -pc_asm_overlap 0 -pc_asm_local_type additive -sub_pc_type lu -da_grid_x 8 797 798 test: 799 suffix: msm_2 800 requires: !single 801 args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 3 -pc_asm_overlap 0 -pc_asm_local_type multiplicative -sub_pc_type lu -da_grid_x 8 802 803 test: 804 suffix: asm_3 805 requires: !single 806 args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 4 -pc_asm_overlap 0 -pc_asm_local_type additive -sub_pc_type lu -da_grid_x 8 807 808 test: 809 suffix: msm_3 810 requires: !single 811 args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 4 -pc_asm_overlap 0 -pc_asm_local_type multiplicative -sub_pc_type lu -da_grid_x 8 812 813 test: 814 suffix: asm_4 815 requires: !single 816 nsize: 2 817 args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 2 -pc_asm_overlap 0 -pc_asm_local_type additive -sub_pc_type lu -da_grid_x 8 818 819 test: 820 suffix: msm_4 821 requires: !single 822 nsize: 2 823 args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 2 -pc_asm_overlap 0 -pc_asm_local_type multiplicative -sub_pc_type lu -da_grid_x 8 824 825 test: 826 suffix: asm_5 827 requires: !single 828 nsize: 2 829 args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 4 -pc_asm_overlap 0 -pc_asm_local_type additive -sub_pc_type lu -da_grid_x 8 830 831 test: 832 suffix: msm_5 833 requires: !single 834 nsize: 2 835 args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -snes_view -ksp_rtol 1.0e-9 -ksp_monitor_short -ksp_type richardson -pc_type asm -pc_asm_blocks 4 -pc_asm_overlap 0 -pc_asm_local_type multiplicative -sub_pc_type lu -da_grid_x 8 836 837 test: 838 args: -snes_rtol 1.e-5 -pc_type mg -ksp_monitor_short -snes_view -pc_mg_levels 3 -pc_mg_galerkin pmat -da_grid_x 17 -da_grid_y 17 -mg_levels_ksp_monitor_short -mg_levels_ksp_norm_type unpreconditioned -snes_monitor_short -mg_levels_ksp_chebyshev_esteig 0.5,1.1 -mg_levels_pc_type sor -pc_mg_type full 839 requires: !single 840 841 test: 842 suffix: 2 843 args: -pc_type mg -ksp_converged_reason -snes_view -pc_mg_galerkin pmat -snes_grid_sequence 3 -mg_levels_ksp_norm_type unpreconditioned -snes_monitor_short -mg_levels_ksp_chebyshev_esteig 0.5,1.1 -mg_levels_pc_type sor -pc_mg_type full -ksp_atol 0 844 845 test: 846 suffix: 3 847 nsize: 2 848 args: -snes_grid_sequence 2 -snes_mf_operator -snes_converged_reason -snes_view -pc_type mg -snes_atol 0 -snes_rtol 1.e-2 849 filter: grep -v "otal number of function evaluations" 850 851 test: 852 suffix: 4 853 nsize: 2 854 args: -snes_grid_sequence 2 -snes_monitor_short -ksp_converged_reason -snes_converged_reason -snes_view -pc_type mg -snes_atol 0 -ksp_atol 0 855 856 test: 857 suffix: 5_anderson 858 args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type anderson 859 860 test: 861 suffix: 5_aspin 862 nsize: 4 863 args: -snes_monitor_short -ksp_monitor_short -snes_converged_reason -da_refine 4 -da_overlap 3 -snes_type aspin -snes_view -npc_sub_pc_type lu -npc_sub_ksp_type preonly 864 865 test: 866 suffix: 5_broyden 867 args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type qn -snes_qn_type broyden -snes_qn_m 10 868 869 test: 870 suffix: 5_fas 871 args: -fas_coarse_snes_max_it 1 -fas_coarse_pc_type lu -fas_coarse_ksp_type preonly -snes_monitor_short -snes_type fas -fas_coarse_ksp_type richardson -da_refine 6 872 requires: !single 873 874 test: 875 suffix: 5_fas_additive 876 args: -fas_coarse_snes_max_it 1 -fas_coarse_pc_type lu -fas_coarse_ksp_type preonly -snes_monitor_short -snes_type fas -fas_coarse_ksp_type richardson -da_refine 6 -snes_fas_type additive -snes_max_it 50 877 878 test: 879 suffix: 5_fas_monitor 880 args: -da_refine 1 -snes_type fas -snes_fas_monitor 881 requires: !single 882 883 test: 884 suffix: 5_ls 885 args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type newtonls 886 887 test: 888 suffix: 5_ls_sell_sor 889 args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type newtonls -dm_mat_type sell -pc_type sor 890 output_file: output/ex5_5_ls.out 891 892 test: 893 suffix: 5_nasm 894 nsize: 4 895 args: -snes_monitor_short -snes_converged_reason -da_refine 4 -da_overlap 3 -snes_type nasm -snes_nasm_type restrict -snes_max_it 10 896 897 test: 898 suffix: 5_ncg 899 args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type ncg -snes_ncg_type fr 900 901 test: 902 suffix: 5_newton_asm_dmda 903 nsize: 4 904 args: -snes_monitor_short -ksp_monitor_short -snes_converged_reason -da_refine 4 -da_overlap 3 -snes_type newtonls -pc_type asm -pc_asm_dm_subdomains -malloc_dump 905 requires: !single 906 907 test: 908 suffix: 5_newton_gasm_dmda 909 nsize: 4 910 args: -snes_monitor_short -ksp_monitor_short -snes_converged_reason -da_refine 4 -da_overlap 3 -snes_type newtonls -pc_type gasm -malloc_dump 911 requires: !single 912 913 test: 914 suffix: 5_ngmres 915 args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type ngmres -snes_ngmres_m 10 916 917 test: 918 suffix: 5_ngmres_fas 919 args: -snes_rtol 1.e-4 -snes_type ngmres -npc_fas_coarse_snes_max_it 1 -npc_fas_coarse_snes_type newtonls -npc_fas_coarse_pc_type lu -npc_fas_coarse_ksp_type preonly -snes_ngmres_m 10 -snes_monitor_short -npc_snes_max_it 1 -npc_snes_type fas -npc_fas_coarse_ksp_type richardson -da_refine 6 920 921 test: 922 suffix: 5_ngmres_ngs 923 args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type ngmres -npc_snes_type ngs -npc_snes_max_it 1 924 925 test: 926 suffix: 5_ngmres_nrichardson 927 args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type ngmres -snes_ngmres_m 10 -npc_snes_type nrichardson -npc_snes_max_it 3 928 output_file: output/ex5_5_ngmres_richardson.out 929 930 test: 931 suffix: 5_nrichardson 932 args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type nrichardson 933 934 test: 935 suffix: 5_qn 936 args: -da_grid_x 81 -da_grid_y 81 -snes_monitor_short -snes_max_it 50 -par 6.0 -snes_type qn -snes_linesearch_type cp -snes_qn_m 10 937 938 test: 939 suffix: 6 940 nsize: 4 941 args: -snes_converged_reason -ksp_converged_reason -da_grid_x 129 -da_grid_y 129 -pc_type mg -pc_mg_levels 8 -mg_levels_ksp_type chebyshev -mg_levels_ksp_chebyshev_esteig 0,0.5,0,1.1 -mg_levels_ksp_max_it 2 942 943 test: 944 requires: complex !single 945 suffix: complex 946 args: -snes_mf_operator -mat_mffd_complex -snes_monitor 947 948 test: 949 requires: !single 950 suffix: 7_ksp_view_pre 951 args: -pc_type gamg -ksp_view_pre 952 953 test: 954 requires: !single 955 suffix: hem_view_detailed 956 args: -pc_type gamg -ksp_view ::ascii_info_detail -pc_gamg_mat_coarsen_type hem 957 958 test: 959 requires: !single 960 suffix: mis_view_detailed 961 args: -pc_type gamg -ksp_view ::ascii_info_detail -pc_gamg_mat_coarsen_type mis 962 963 TEST*/ 964