1c5566c22SJunchao Zhang static char help[] = "Copy of ex5.c\n"; 2c5566c22SJunchao Zhang 3c5566c22SJunchao Zhang /* ------------------------------------------------------------------------ 4c5566c22SJunchao Zhang 5c5566c22SJunchao Zhang Copy of ex5.c. 6c5566c22SJunchao Zhang Once petsc test harness supports conditional linking, we can remove this duplicate. 7c5566c22SJunchao Zhang See https://gitlab.com/petsc/petsc/-/issues/1173 8c5566c22SJunchao Zhang ------------------------------------------------------------------------- */ 9c5566c22SJunchao Zhang 10c5566c22SJunchao Zhang /* 11c5566c22SJunchao Zhang Include "petscdmda.h" so that we can use distributed arrays (DMDAs). 12c5566c22SJunchao Zhang Include "petscsnes.h" so that we can use SNES solvers. Note that this 13c5566c22SJunchao Zhang */ 14c5566c22SJunchao Zhang #include <petscdm.h> 15c5566c22SJunchao Zhang #include <petscdmda.h> 16c5566c22SJunchao Zhang #include <petscsnes.h> 17c5566c22SJunchao Zhang #include <petscmatlab.h> 18c5566c22SJunchao Zhang #include <petsc/private/snesimpl.h> /* For SNES_Solve event */ 19c5566c22SJunchao Zhang #include "ex55.h" 20c5566c22SJunchao Zhang 21c5566c22SJunchao Zhang /* ------------------------------------------------------------------- */ 22c5566c22SJunchao Zhang /* 23c5566c22SJunchao Zhang FormInitialGuess - Forms initial approximation. 24c5566c22SJunchao Zhang 25c5566c22SJunchao Zhang Input Parameters: 26c5566c22SJunchao Zhang da - The DM 27c5566c22SJunchao Zhang user - user-defined application context 28c5566c22SJunchao Zhang 29c5566c22SJunchao Zhang Output Parameter: 30c5566c22SJunchao Zhang X - vector 31c5566c22SJunchao Zhang */ 329371c9d4SSatish Balay static PetscErrorCode FormInitialGuess(DM da, AppCtx *user, Vec X) { 33c5566c22SJunchao Zhang PetscInt i, j, Mx, My, xs, ys, xm, ym; 34c5566c22SJunchao Zhang PetscReal lambda, temp1, temp, hx, hy; 35c5566c22SJunchao Zhang PetscScalar **x; 36c5566c22SJunchao Zhang 37c5566c22SJunchao Zhang PetscFunctionBeginUser; 38c5566c22SJunchao Zhang 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)); 39c5566c22SJunchao Zhang 40c5566c22SJunchao Zhang lambda = user->param; 41c5566c22SJunchao Zhang hx = 1.0 / (PetscReal)(Mx - 1); 42c5566c22SJunchao Zhang hy = 1.0 / (PetscReal)(My - 1); 43c5566c22SJunchao Zhang temp1 = lambda / (lambda + 1.0); 44c5566c22SJunchao Zhang 45c5566c22SJunchao Zhang /* 46c5566c22SJunchao Zhang Get a pointer to vector data. 47c5566c22SJunchao Zhang - For default PETSc vectors, VecGetArray() returns a pointer to 48c5566c22SJunchao Zhang the data array. Otherwise, the routine is implementation dependent. 49c5566c22SJunchao Zhang - You MUST call VecRestoreArray() when you no longer need access to 50c5566c22SJunchao Zhang the array. 51c5566c22SJunchao Zhang */ 52c5566c22SJunchao Zhang PetscCall(DMDAVecGetArray(da, X, &x)); 53c5566c22SJunchao Zhang 54c5566c22SJunchao Zhang /* 55c5566c22SJunchao Zhang Get local grid boundaries (for 2-dimensional DMDA): 56c5566c22SJunchao Zhang xs, ys - starting grid indices (no ghost points) 57c5566c22SJunchao Zhang xm, ym - widths of local grid (no ghost points) 58c5566c22SJunchao Zhang 59c5566c22SJunchao Zhang */ 60c5566c22SJunchao Zhang PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &xm, &ym, NULL)); 61c5566c22SJunchao Zhang 62c5566c22SJunchao Zhang /* 63c5566c22SJunchao Zhang Compute initial guess over the locally owned part of the grid 64c5566c22SJunchao Zhang */ 65c5566c22SJunchao Zhang for (j = ys; j < ys + ym; j++) { 66c5566c22SJunchao Zhang temp = (PetscReal)(PetscMin(j, My - j - 1)) * hy; 67c5566c22SJunchao Zhang for (i = xs; i < xs + xm; i++) { 68c5566c22SJunchao Zhang if (i == 0 || j == 0 || i == Mx - 1 || j == My - 1) { 69c5566c22SJunchao Zhang /* boundary conditions are all zero Dirichlet */ 70c5566c22SJunchao Zhang x[j][i] = 0.0; 71c5566c22SJunchao Zhang } else { 72c5566c22SJunchao Zhang x[j][i] = temp1 * PetscSqrtReal(PetscMin((PetscReal)(PetscMin(i, Mx - i - 1)) * hx, temp)); 73c5566c22SJunchao Zhang } 74c5566c22SJunchao Zhang } 75c5566c22SJunchao Zhang } 76c5566c22SJunchao Zhang 77c5566c22SJunchao Zhang /* 78c5566c22SJunchao Zhang Restore vector 79c5566c22SJunchao Zhang */ 80c5566c22SJunchao Zhang PetscCall(DMDAVecRestoreArray(da, X, &x)); 81c5566c22SJunchao Zhang PetscFunctionReturn(0); 82c5566c22SJunchao Zhang } 83c5566c22SJunchao Zhang 84c5566c22SJunchao Zhang /* 85c5566c22SJunchao Zhang FormExactSolution - Forms MMS solution 86c5566c22SJunchao Zhang 87c5566c22SJunchao Zhang Input Parameters: 88c5566c22SJunchao Zhang da - The DM 89c5566c22SJunchao Zhang user - user-defined application context 90c5566c22SJunchao Zhang 91c5566c22SJunchao Zhang Output Parameter: 92c5566c22SJunchao Zhang X - vector 93c5566c22SJunchao Zhang */ 949371c9d4SSatish Balay static PetscErrorCode FormExactSolution(DM da, AppCtx *user, Vec U) { 95c5566c22SJunchao Zhang DM coordDA; 96c5566c22SJunchao Zhang Vec coordinates; 97c5566c22SJunchao Zhang DMDACoor2d **coords; 98c5566c22SJunchao Zhang PetscScalar **u; 99c5566c22SJunchao Zhang PetscInt xs, ys, xm, ym, i, j; 100c5566c22SJunchao Zhang 101c5566c22SJunchao Zhang PetscFunctionBeginUser; 102c5566c22SJunchao Zhang PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &xm, &ym, NULL)); 103c5566c22SJunchao Zhang PetscCall(DMGetCoordinateDM(da, &coordDA)); 104c5566c22SJunchao Zhang PetscCall(DMGetCoordinates(da, &coordinates)); 105c5566c22SJunchao Zhang PetscCall(DMDAVecGetArray(coordDA, coordinates, &coords)); 106c5566c22SJunchao Zhang PetscCall(DMDAVecGetArray(da, U, &u)); 107c5566c22SJunchao Zhang for (j = ys; j < ys + ym; ++j) { 1089371c9d4SSatish Balay for (i = xs; i < xs + xm; ++i) { user->mms_solution(user, &coords[j][i], &u[j][i]); } 109c5566c22SJunchao Zhang } 110c5566c22SJunchao Zhang PetscCall(DMDAVecRestoreArray(da, U, &u)); 111c5566c22SJunchao Zhang PetscCall(DMDAVecRestoreArray(coordDA, coordinates, &coords)); 112c5566c22SJunchao Zhang PetscFunctionReturn(0); 113c5566c22SJunchao Zhang } 114c5566c22SJunchao Zhang 1159371c9d4SSatish Balay static PetscErrorCode ZeroBCSolution(AppCtx *user, const DMDACoor2d *c, PetscScalar *u) { 116c5566c22SJunchao Zhang u[0] = 0.; 117c5566c22SJunchao Zhang return 0; 118c5566c22SJunchao Zhang } 119c5566c22SJunchao Zhang 120c5566c22SJunchao Zhang /* The functions below evaluate the MMS solution u(x,y) and associated forcing 121c5566c22SJunchao Zhang 122c5566c22SJunchao Zhang f(x,y) = -u_xx - u_yy - lambda exp(u) 123c5566c22SJunchao Zhang 124c5566c22SJunchao Zhang such that u(x,y) is an exact solution with f(x,y) as the right hand side forcing term. 125c5566c22SJunchao Zhang */ 1269371c9d4SSatish Balay static PetscErrorCode MMSSolution1(AppCtx *user, const DMDACoor2d *c, PetscScalar *u) { 127c5566c22SJunchao Zhang PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 128c5566c22SJunchao Zhang u[0] = x * (1 - x) * y * (1 - y); 129c5566c22SJunchao Zhang PetscLogFlops(5); 130c5566c22SJunchao Zhang return 0; 131c5566c22SJunchao Zhang } 1329371c9d4SSatish Balay static PetscErrorCode MMSForcing1(AppCtx *user, const DMDACoor2d *c, PetscScalar *f) { 133c5566c22SJunchao Zhang PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 134c5566c22SJunchao Zhang f[0] = 2 * x * (1 - x) + 2 * y * (1 - y) - user->param * PetscExpReal(x * (1 - x) * y * (1 - y)); 135c5566c22SJunchao Zhang return 0; 136c5566c22SJunchao Zhang } 137c5566c22SJunchao Zhang 1389371c9d4SSatish Balay static PetscErrorCode MMSSolution2(AppCtx *user, const DMDACoor2d *c, PetscScalar *u) { 139c5566c22SJunchao Zhang PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 140c5566c22SJunchao Zhang u[0] = PetscSinReal(PETSC_PI * x) * PetscSinReal(PETSC_PI * y); 141c5566c22SJunchao Zhang PetscLogFlops(5); 142c5566c22SJunchao Zhang return 0; 143c5566c22SJunchao Zhang } 1449371c9d4SSatish Balay static PetscErrorCode MMSForcing2(AppCtx *user, const DMDACoor2d *c, PetscScalar *f) { 145c5566c22SJunchao Zhang PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 146c5566c22SJunchao Zhang 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)); 147c5566c22SJunchao Zhang return 0; 148c5566c22SJunchao Zhang } 149c5566c22SJunchao Zhang 1509371c9d4SSatish Balay static PetscErrorCode MMSSolution3(AppCtx *user, const DMDACoor2d *c, PetscScalar *u) { 151c5566c22SJunchao Zhang PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 152c5566c22SJunchao Zhang u[0] = PetscSinReal(user->m * PETSC_PI * x * (1 - y)) * PetscSinReal(user->n * PETSC_PI * y * (1 - x)); 153c5566c22SJunchao Zhang PetscLogFlops(5); 154c5566c22SJunchao Zhang return 0; 155c5566c22SJunchao Zhang } 1569371c9d4SSatish Balay static PetscErrorCode MMSForcing3(AppCtx *user, const DMDACoor2d *c, PetscScalar *f) { 157c5566c22SJunchao Zhang PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 158c5566c22SJunchao Zhang PetscReal m = user->m, n = user->n, lambda = user->param; 1599371c9d4SSatish Balay 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))); 160c5566c22SJunchao Zhang return 0; 161c5566c22SJunchao Zhang } 162c5566c22SJunchao Zhang 1639371c9d4SSatish Balay static PetscErrorCode MMSSolution4(AppCtx *user, const DMDACoor2d *c, PetscScalar *u) { 164c5566c22SJunchao Zhang const PetscReal Lx = 1., Ly = 1.; 165c5566c22SJunchao Zhang PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 166c5566c22SJunchao Zhang u[0] = (PetscPowReal(x, 4) - PetscSqr(Lx) * PetscSqr(x)) * (PetscPowReal(y, 4) - PetscSqr(Ly) * PetscSqr(y)); 167c5566c22SJunchao Zhang PetscLogFlops(9); 168c5566c22SJunchao Zhang return 0; 169c5566c22SJunchao Zhang } 1709371c9d4SSatish Balay static PetscErrorCode MMSForcing4(AppCtx *user, const DMDACoor2d *c, PetscScalar *f) { 171c5566c22SJunchao Zhang const PetscReal Lx = 1., Ly = 1.; 172c5566c22SJunchao Zhang PetscReal x = PetscRealPart(c->x), y = PetscRealPart(c->y); 1739371c9d4SSatish Balay 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)))); 174c5566c22SJunchao Zhang return 0; 175c5566c22SJunchao Zhang } 176c5566c22SJunchao Zhang 177c5566c22SJunchao Zhang /* ------------------------------------------------------------------- */ 178c5566c22SJunchao Zhang /* 179c5566c22SJunchao Zhang FormFunctionLocal - Evaluates nonlinear function, F(x) on local process patch 180c5566c22SJunchao Zhang 181c5566c22SJunchao Zhang */ 1829371c9d4SSatish Balay static PetscErrorCode FormFunctionLocal(DMDALocalInfo *info, PetscScalar **x, PetscScalar **f, AppCtx *user) { 183c5566c22SJunchao Zhang PetscInt i, j; 184c5566c22SJunchao Zhang PetscReal lambda, hx, hy, hxdhy, hydhx; 185c5566c22SJunchao Zhang PetscScalar u, ue, uw, un, us, uxx, uyy, mms_solution, mms_forcing; 186c5566c22SJunchao Zhang DMDACoor2d c; 187c5566c22SJunchao Zhang 188c5566c22SJunchao Zhang PetscFunctionBeginUser; 189c5566c22SJunchao Zhang lambda = user->param; 190c5566c22SJunchao Zhang hx = 1.0 / (PetscReal)(info->mx - 1); 191c5566c22SJunchao Zhang hy = 1.0 / (PetscReal)(info->my - 1); 192c5566c22SJunchao Zhang hxdhy = hx / hy; 193c5566c22SJunchao Zhang hydhx = hy / hx; 194c5566c22SJunchao Zhang /* 195c5566c22SJunchao Zhang Compute function over the locally owned part of the grid 196c5566c22SJunchao Zhang */ 197c5566c22SJunchao Zhang for (j = info->ys; j < info->ys + info->ym; j++) { 198c5566c22SJunchao Zhang for (i = info->xs; i < info->xs + info->xm; i++) { 199c5566c22SJunchao Zhang if (i == 0 || j == 0 || i == info->mx - 1 || j == info->my - 1) { 2009371c9d4SSatish Balay c.x = i * hx; 2019371c9d4SSatish Balay c.y = j * hy; 202c5566c22SJunchao Zhang PetscCall(user->mms_solution(user, &c, &mms_solution)); 203c5566c22SJunchao Zhang f[j][i] = 2.0 * (hydhx + hxdhy) * (x[j][i] - mms_solution); 204c5566c22SJunchao Zhang } else { 205c5566c22SJunchao Zhang u = x[j][i]; 206c5566c22SJunchao Zhang uw = x[j][i - 1]; 207c5566c22SJunchao Zhang ue = x[j][i + 1]; 208c5566c22SJunchao Zhang un = x[j - 1][i]; 209c5566c22SJunchao Zhang us = x[j + 1][i]; 210c5566c22SJunchao Zhang 211c5566c22SJunchao Zhang /* Enforce boundary conditions at neighboring points -- setting these values causes the Jacobian to be symmetric. */ 2129371c9d4SSatish Balay if (i - 1 == 0) { 2139371c9d4SSatish Balay c.x = (i - 1) * hx; 2149371c9d4SSatish Balay c.y = j * hy; 2159371c9d4SSatish Balay PetscCall(user->mms_solution(user, &c, &uw)); 2169371c9d4SSatish Balay } 2179371c9d4SSatish Balay if (i + 1 == info->mx - 1) { 2189371c9d4SSatish Balay c.x = (i + 1) * hx; 2199371c9d4SSatish Balay c.y = j * hy; 2209371c9d4SSatish Balay PetscCall(user->mms_solution(user, &c, &ue)); 2219371c9d4SSatish Balay } 2229371c9d4SSatish Balay if (j - 1 == 0) { 2239371c9d4SSatish Balay c.x = i * hx; 2249371c9d4SSatish Balay c.y = (j - 1) * hy; 2259371c9d4SSatish Balay PetscCall(user->mms_solution(user, &c, &un)); 2269371c9d4SSatish Balay } 2279371c9d4SSatish Balay if (j + 1 == info->my - 1) { 2289371c9d4SSatish Balay c.x = i * hx; 2299371c9d4SSatish Balay c.y = (j + 1) * hy; 2309371c9d4SSatish Balay PetscCall(user->mms_solution(user, &c, &us)); 2319371c9d4SSatish Balay } 232c5566c22SJunchao Zhang 233c5566c22SJunchao Zhang uxx = (2.0 * u - uw - ue) * hydhx; 234c5566c22SJunchao Zhang uyy = (2.0 * u - un - us) * hxdhy; 235c5566c22SJunchao Zhang mms_forcing = 0; 2369371c9d4SSatish Balay c.x = i * hx; 2379371c9d4SSatish Balay c.y = j * hy; 238c5566c22SJunchao Zhang if (user->mms_forcing) PetscCall(user->mms_forcing(user, &c, &mms_forcing)); 239c5566c22SJunchao Zhang f[j][i] = uxx + uyy - hx * hy * (lambda * PetscExpScalar(u) + mms_forcing); 240c5566c22SJunchao Zhang } 241c5566c22SJunchao Zhang } 242c5566c22SJunchao Zhang } 243c5566c22SJunchao Zhang PetscCall(PetscLogFlops(11.0 * info->ym * info->xm)); 244c5566c22SJunchao Zhang PetscFunctionReturn(0); 245c5566c22SJunchao Zhang } 246c5566c22SJunchao Zhang 247c5566c22SJunchao Zhang /* FormObjectiveLocal - Evaluates nonlinear function, F(x) on local process patch */ 2489371c9d4SSatish Balay static PetscErrorCode FormObjectiveLocal(DMDALocalInfo *info, PetscScalar **x, PetscReal *obj, AppCtx *user) { 249c5566c22SJunchao Zhang PetscInt i, j; 250c5566c22SJunchao Zhang PetscReal lambda, hx, hy, hxdhy, hydhx, sc, lobj = 0; 251c5566c22SJunchao Zhang PetscScalar u, ue, uw, un, us, uxux, uyuy; 252c5566c22SJunchao Zhang MPI_Comm comm; 253c5566c22SJunchao Zhang 254c5566c22SJunchao Zhang PetscFunctionBeginUser; 255c5566c22SJunchao Zhang *obj = 0; 256c5566c22SJunchao Zhang PetscCall(PetscObjectGetComm((PetscObject)info->da, &comm)); 257c5566c22SJunchao Zhang lambda = user->param; 258c5566c22SJunchao Zhang hx = 1.0 / (PetscReal)(info->mx - 1); 259c5566c22SJunchao Zhang hy = 1.0 / (PetscReal)(info->my - 1); 260c5566c22SJunchao Zhang sc = hx * hy * lambda; 261c5566c22SJunchao Zhang hxdhy = hx / hy; 262c5566c22SJunchao Zhang hydhx = hy / hx; 263c5566c22SJunchao Zhang /* 264c5566c22SJunchao Zhang Compute function over the locally owned part of the grid 265c5566c22SJunchao Zhang */ 266c5566c22SJunchao Zhang for (j = info->ys; j < info->ys + info->ym; j++) { 267c5566c22SJunchao Zhang for (i = info->xs; i < info->xs + info->xm; i++) { 268c5566c22SJunchao Zhang if (i == 0 || j == 0 || i == info->mx - 1 || j == info->my - 1) { 269c5566c22SJunchao Zhang lobj += PetscRealPart((hydhx + hxdhy) * x[j][i] * x[j][i]); 270c5566c22SJunchao Zhang } else { 271c5566c22SJunchao Zhang u = x[j][i]; 272c5566c22SJunchao Zhang uw = x[j][i - 1]; 273c5566c22SJunchao Zhang ue = x[j][i + 1]; 274c5566c22SJunchao Zhang un = x[j - 1][i]; 275c5566c22SJunchao Zhang us = x[j + 1][i]; 276c5566c22SJunchao Zhang 277c5566c22SJunchao Zhang if (i - 1 == 0) uw = 0.; 278c5566c22SJunchao Zhang if (i + 1 == info->mx - 1) ue = 0.; 279c5566c22SJunchao Zhang if (j - 1 == 0) un = 0.; 280c5566c22SJunchao Zhang if (j + 1 == info->my - 1) us = 0.; 281c5566c22SJunchao Zhang 282c5566c22SJunchao Zhang /* F[u] = 1/2\int_{\omega}\nabla^2u(x)*u(x)*dx */ 283c5566c22SJunchao Zhang 284c5566c22SJunchao Zhang uxux = u * (2. * u - ue - uw) * hydhx; 285c5566c22SJunchao Zhang uyuy = u * (2. * u - un - us) * hxdhy; 286c5566c22SJunchao Zhang 287c5566c22SJunchao Zhang lobj += PetscRealPart(0.5 * (uxux + uyuy) - sc * PetscExpScalar(u)); 288c5566c22SJunchao Zhang } 289c5566c22SJunchao Zhang } 290c5566c22SJunchao Zhang } 291c5566c22SJunchao Zhang PetscCall(PetscLogFlops(12.0 * info->ym * info->xm)); 292c5566c22SJunchao Zhang PetscCallMPI(MPI_Allreduce(&lobj, obj, 1, MPIU_REAL, MPIU_SUM, comm)); 293c5566c22SJunchao Zhang PetscFunctionReturn(0); 294c5566c22SJunchao Zhang } 295c5566c22SJunchao Zhang 296c5566c22SJunchao Zhang /* 297c5566c22SJunchao Zhang FormJacobianLocal - Evaluates Jacobian matrix on local process patch 298c5566c22SJunchao Zhang */ 2999371c9d4SSatish Balay static PetscErrorCode FormJacobianLocal(DMDALocalInfo *info, PetscScalar **x, Mat jac, Mat jacpre, AppCtx *user) { 300c5566c22SJunchao Zhang PetscInt i, j, k; 301c5566c22SJunchao Zhang MatStencil col[5], row; 302c5566c22SJunchao Zhang PetscScalar lambda, v[5], hx, hy, hxdhy, hydhx, sc; 303c5566c22SJunchao Zhang DM coordDA; 304c5566c22SJunchao Zhang Vec coordinates; 305c5566c22SJunchao Zhang DMDACoor2d **coords; 306c5566c22SJunchao Zhang 307c5566c22SJunchao Zhang PetscFunctionBeginUser; 308c5566c22SJunchao Zhang lambda = user->param; 309c5566c22SJunchao Zhang /* Extract coordinates */ 310c5566c22SJunchao Zhang PetscCall(DMGetCoordinateDM(info->da, &coordDA)); 311c5566c22SJunchao Zhang PetscCall(DMGetCoordinates(info->da, &coordinates)); 312c5566c22SJunchao Zhang PetscCall(DMDAVecGetArray(coordDA, coordinates, &coords)); 313c5566c22SJunchao Zhang hx = info->xm > 1 ? PetscRealPart(coords[info->ys][info->xs + 1].x) - PetscRealPart(coords[info->ys][info->xs].x) : 1.0; 314c5566c22SJunchao Zhang hy = info->ym > 1 ? PetscRealPart(coords[info->ys + 1][info->xs].y) - PetscRealPart(coords[info->ys][info->xs].y) : 1.0; 315c5566c22SJunchao Zhang PetscCall(DMDAVecRestoreArray(coordDA, coordinates, &coords)); 316c5566c22SJunchao Zhang hxdhy = hx / hy; 317c5566c22SJunchao Zhang hydhx = hy / hx; 318c5566c22SJunchao Zhang sc = hx * hy * lambda; 319c5566c22SJunchao Zhang 320c5566c22SJunchao Zhang /* 321c5566c22SJunchao Zhang Compute entries for the locally owned part of the Jacobian. 322c5566c22SJunchao Zhang - Currently, all PETSc parallel matrix formats are partitioned by 323c5566c22SJunchao Zhang contiguous chunks of rows across the processors. 324c5566c22SJunchao Zhang - Each processor needs to insert only elements that it owns 325c5566c22SJunchao Zhang locally (but any non-local elements will be sent to the 326c5566c22SJunchao Zhang appropriate processor during matrix assembly). 327c5566c22SJunchao Zhang - Here, we set all entries for a particular row at once. 328c5566c22SJunchao Zhang - We can set matrix entries either using either 329c5566c22SJunchao Zhang MatSetValuesLocal() or MatSetValues(), as discussed above. 330c5566c22SJunchao Zhang */ 331c5566c22SJunchao Zhang for (j = info->ys; j < info->ys + info->ym; j++) { 332c5566c22SJunchao Zhang for (i = info->xs; i < info->xs + info->xm; i++) { 3339371c9d4SSatish Balay row.j = j; 3349371c9d4SSatish Balay row.i = i; 335c5566c22SJunchao Zhang /* boundary points */ 336c5566c22SJunchao Zhang if (i == 0 || j == 0 || i == info->mx - 1 || j == info->my - 1) { 337c5566c22SJunchao Zhang v[0] = 2.0 * (hydhx + hxdhy); 338c5566c22SJunchao Zhang PetscCall(MatSetValuesStencil(jacpre, 1, &row, 1, &row, v, INSERT_VALUES)); 339c5566c22SJunchao Zhang } else { 340c5566c22SJunchao Zhang k = 0; 341c5566c22SJunchao Zhang /* interior grid points */ 342c5566c22SJunchao Zhang if (j - 1 != 0) { 343c5566c22SJunchao Zhang v[k] = -hxdhy; 3449371c9d4SSatish Balay col[k].j = j - 1; 3459371c9d4SSatish Balay col[k].i = i; 346c5566c22SJunchao Zhang k++; 347c5566c22SJunchao Zhang } 348c5566c22SJunchao Zhang if (i - 1 != 0) { 349c5566c22SJunchao Zhang v[k] = -hydhx; 3509371c9d4SSatish Balay col[k].j = j; 3519371c9d4SSatish Balay col[k].i = i - 1; 352c5566c22SJunchao Zhang k++; 353c5566c22SJunchao Zhang } 354c5566c22SJunchao Zhang 3559371c9d4SSatish Balay v[k] = 2.0 * (hydhx + hxdhy) - sc * PetscExpScalar(x[j][i]); 3569371c9d4SSatish Balay col[k].j = row.j; 3579371c9d4SSatish Balay col[k].i = row.i; 3589371c9d4SSatish Balay k++; 359c5566c22SJunchao Zhang 360c5566c22SJunchao Zhang if (i + 1 != info->mx - 1) { 361c5566c22SJunchao Zhang v[k] = -hydhx; 3629371c9d4SSatish Balay col[k].j = j; 3639371c9d4SSatish Balay col[k].i = i + 1; 364c5566c22SJunchao Zhang k++; 365c5566c22SJunchao Zhang } 366c5566c22SJunchao Zhang if (j + 1 != info->mx - 1) { 367c5566c22SJunchao Zhang v[k] = -hxdhy; 3689371c9d4SSatish Balay col[k].j = j + 1; 3699371c9d4SSatish Balay col[k].i = i; 370c5566c22SJunchao Zhang k++; 371c5566c22SJunchao Zhang } 372c5566c22SJunchao Zhang PetscCall(MatSetValuesStencil(jacpre, 1, &row, k, col, v, INSERT_VALUES)); 373c5566c22SJunchao Zhang } 374c5566c22SJunchao Zhang } 375c5566c22SJunchao Zhang } 376c5566c22SJunchao Zhang 377c5566c22SJunchao Zhang /* 378c5566c22SJunchao Zhang Assemble matrix, using the 2-step process: 379c5566c22SJunchao Zhang MatAssemblyBegin(), MatAssemblyEnd(). 380c5566c22SJunchao Zhang */ 381c5566c22SJunchao Zhang PetscCall(MatAssemblyBegin(jacpre, MAT_FINAL_ASSEMBLY)); 382c5566c22SJunchao Zhang PetscCall(MatAssemblyEnd(jacpre, MAT_FINAL_ASSEMBLY)); 383c5566c22SJunchao Zhang 384c5566c22SJunchao Zhang /* 385c5566c22SJunchao Zhang Tell the matrix we will never add a new nonzero location to the 386c5566c22SJunchao Zhang matrix. If we do, it will generate an error. 387c5566c22SJunchao Zhang */ 388c5566c22SJunchao Zhang PetscCall(MatSetOption(jac, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE)); 389c5566c22SJunchao Zhang PetscFunctionReturn(0); 390c5566c22SJunchao Zhang } 391c5566c22SJunchao Zhang 3929371c9d4SSatish Balay static PetscErrorCode FormFunctionMatlab(SNES snes, Vec X, Vec F, void *ptr) { 393c5566c22SJunchao Zhang #if PetscDefined(HAVE_MATLAB_ENGINE) 394c5566c22SJunchao Zhang AppCtx *user = (AppCtx *)ptr; 395c5566c22SJunchao Zhang PetscInt Mx, My; 396c5566c22SJunchao Zhang PetscReal lambda, hx, hy; 397c5566c22SJunchao Zhang Vec localX, localF; 398c5566c22SJunchao Zhang MPI_Comm comm; 399c5566c22SJunchao Zhang DM da; 400c5566c22SJunchao Zhang 401c5566c22SJunchao Zhang PetscFunctionBeginUser; 402c5566c22SJunchao Zhang PetscCall(SNESGetDM(snes, &da)); 403c5566c22SJunchao Zhang PetscCall(DMGetLocalVector(da, &localX)); 404c5566c22SJunchao Zhang PetscCall(DMGetLocalVector(da, &localF)); 405c5566c22SJunchao Zhang PetscCall(PetscObjectSetName((PetscObject)localX, "localX")); 406c5566c22SJunchao Zhang PetscCall(PetscObjectSetName((PetscObject)localF, "localF")); 407c5566c22SJunchao Zhang 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)); 408c5566c22SJunchao Zhang 409c5566c22SJunchao Zhang lambda = user->param; 410c5566c22SJunchao Zhang hx = 1.0 / (PetscReal)(Mx - 1); 411c5566c22SJunchao Zhang hy = 1.0 / (PetscReal)(My - 1); 412c5566c22SJunchao Zhang 413c5566c22SJunchao Zhang PetscCall(PetscObjectGetComm((PetscObject)snes, &comm)); 414c5566c22SJunchao Zhang /* 415c5566c22SJunchao Zhang Scatter ghost points to local vector,using the 2-step process 416c5566c22SJunchao Zhang DMGlobalToLocalBegin(),DMGlobalToLocalEnd(). 417c5566c22SJunchao Zhang By placing code between these two statements, computations can be 418c5566c22SJunchao Zhang done while messages are in transition. 419c5566c22SJunchao Zhang */ 420c5566c22SJunchao Zhang PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, localX)); 421c5566c22SJunchao Zhang PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, localX)); 422c5566c22SJunchao Zhang PetscCall(PetscMatlabEnginePut(PETSC_MATLAB_ENGINE_(comm), (PetscObject)localX)); 423c5566c22SJunchao Zhang PetscCall(PetscMatlabEngineEvaluate(PETSC_MATLAB_ENGINE_(comm), "localF=ex5m(localX,%18.16e,%18.16e,%18.16e)", (double)hx, (double)hy, (double)lambda)); 424c5566c22SJunchao Zhang PetscCall(PetscMatlabEngineGet(PETSC_MATLAB_ENGINE_(comm), (PetscObject)localF)); 425c5566c22SJunchao Zhang 426c5566c22SJunchao Zhang /* 427c5566c22SJunchao Zhang Insert values into global vector 428c5566c22SJunchao Zhang */ 429c5566c22SJunchao Zhang PetscCall(DMLocalToGlobalBegin(da, localF, INSERT_VALUES, F)); 430c5566c22SJunchao Zhang PetscCall(DMLocalToGlobalEnd(da, localF, INSERT_VALUES, F)); 431c5566c22SJunchao Zhang PetscCall(DMRestoreLocalVector(da, &localX)); 432c5566c22SJunchao Zhang PetscCall(DMRestoreLocalVector(da, &localF)); 433c5566c22SJunchao Zhang PetscFunctionReturn(0); 434c5566c22SJunchao Zhang #else 435c5566c22SJunchao Zhang return 0; /* Never called */ 436c5566c22SJunchao Zhang #endif 437c5566c22SJunchao Zhang } 438c5566c22SJunchao Zhang 439c5566c22SJunchao Zhang /* ------------------------------------------------------------------- */ 440c5566c22SJunchao Zhang /* 441c5566c22SJunchao Zhang Applies some sweeps on nonlinear Gauss-Seidel on each process 442c5566c22SJunchao Zhang 443c5566c22SJunchao Zhang */ 4449371c9d4SSatish Balay static PetscErrorCode NonlinearGS(SNES snes, Vec X, Vec B, void *ctx) { 445c5566c22SJunchao Zhang PetscInt i, j, k, Mx, My, xs, ys, xm, ym, its, tot_its, sweeps, l; 446c5566c22SJunchao Zhang PetscReal lambda, hx, hy, hxdhy, hydhx, sc; 447c5566c22SJunchao Zhang PetscScalar **x, **b, bij, F, F0 = 0, J, u, un, us, ue, eu, uw, uxx, uyy, y; 448c5566c22SJunchao Zhang PetscReal atol, rtol, stol; 449c5566c22SJunchao Zhang DM da; 450c5566c22SJunchao Zhang AppCtx *user; 451c5566c22SJunchao Zhang Vec localX, localB; 452c5566c22SJunchao Zhang 453c5566c22SJunchao Zhang PetscFunctionBeginUser; 454c5566c22SJunchao Zhang tot_its = 0; 455c5566c22SJunchao Zhang PetscCall(SNESNGSGetSweeps(snes, &sweeps)); 456c5566c22SJunchao Zhang PetscCall(SNESNGSGetTolerances(snes, &atol, &rtol, &stol, &its)); 457c5566c22SJunchao Zhang PetscCall(SNESGetDM(snes, &da)); 458c5566c22SJunchao Zhang PetscCall(DMGetApplicationContext(da, &user)); 459c5566c22SJunchao Zhang 460c5566c22SJunchao Zhang 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)); 461c5566c22SJunchao Zhang 462c5566c22SJunchao Zhang lambda = user->param; 463c5566c22SJunchao Zhang hx = 1.0 / (PetscReal)(Mx - 1); 464c5566c22SJunchao Zhang hy = 1.0 / (PetscReal)(My - 1); 465c5566c22SJunchao Zhang sc = hx * hy * lambda; 466c5566c22SJunchao Zhang hxdhy = hx / hy; 467c5566c22SJunchao Zhang hydhx = hy / hx; 468c5566c22SJunchao Zhang 469c5566c22SJunchao Zhang PetscCall(DMGetLocalVector(da, &localX)); 470*48a46eb9SPierre Jolivet if (B) PetscCall(DMGetLocalVector(da, &localB)); 471c5566c22SJunchao Zhang for (l = 0; l < sweeps; l++) { 472c5566c22SJunchao Zhang PetscCall(DMGlobalToLocalBegin(da, X, INSERT_VALUES, localX)); 473c5566c22SJunchao Zhang PetscCall(DMGlobalToLocalEnd(da, X, INSERT_VALUES, localX)); 474c5566c22SJunchao Zhang if (B) { 475c5566c22SJunchao Zhang PetscCall(DMGlobalToLocalBegin(da, B, INSERT_VALUES, localB)); 476c5566c22SJunchao Zhang PetscCall(DMGlobalToLocalEnd(da, B, INSERT_VALUES, localB)); 477c5566c22SJunchao Zhang } 478c5566c22SJunchao Zhang /* 479c5566c22SJunchao Zhang Get a pointer to vector data. 480c5566c22SJunchao Zhang - For default PETSc vectors, VecGetArray() returns a pointer to 481c5566c22SJunchao Zhang the data array. Otherwise, the routine is implementation dependent. 482c5566c22SJunchao Zhang - You MUST call VecRestoreArray() when you no longer need access to 483c5566c22SJunchao Zhang the array. 484c5566c22SJunchao Zhang */ 485c5566c22SJunchao Zhang PetscCall(DMDAVecGetArray(da, localX, &x)); 486c5566c22SJunchao Zhang if (B) PetscCall(DMDAVecGetArray(da, localB, &b)); 487c5566c22SJunchao Zhang /* 488c5566c22SJunchao Zhang Get local grid boundaries (for 2-dimensional DMDA): 489c5566c22SJunchao Zhang xs, ys - starting grid indices (no ghost points) 490c5566c22SJunchao Zhang xm, ym - widths of local grid (no ghost points) 491c5566c22SJunchao Zhang */ 492c5566c22SJunchao Zhang PetscCall(DMDAGetCorners(da, &xs, &ys, NULL, &xm, &ym, NULL)); 493c5566c22SJunchao Zhang 494c5566c22SJunchao Zhang for (j = ys; j < ys + ym; j++) { 495c5566c22SJunchao Zhang for (i = xs; i < xs + xm; i++) { 496c5566c22SJunchao Zhang if (i == 0 || j == 0 || i == Mx - 1 || j == My - 1) { 497c5566c22SJunchao Zhang /* boundary conditions are all zero Dirichlet */ 498c5566c22SJunchao Zhang x[j][i] = 0.0; 499c5566c22SJunchao Zhang } else { 500c5566c22SJunchao Zhang if (B) bij = b[j][i]; 501c5566c22SJunchao Zhang else bij = 0.; 502c5566c22SJunchao Zhang 503c5566c22SJunchao Zhang u = x[j][i]; 504c5566c22SJunchao Zhang un = x[j - 1][i]; 505c5566c22SJunchao Zhang us = x[j + 1][i]; 506c5566c22SJunchao Zhang ue = x[j][i - 1]; 507c5566c22SJunchao Zhang uw = x[j][i + 1]; 508c5566c22SJunchao Zhang 509c5566c22SJunchao Zhang for (k = 0; k < its; k++) { 510c5566c22SJunchao Zhang eu = PetscExpScalar(u); 511c5566c22SJunchao Zhang uxx = (2.0 * u - ue - uw) * hydhx; 512c5566c22SJunchao Zhang uyy = (2.0 * u - un - us) * hxdhy; 513c5566c22SJunchao Zhang F = uxx + uyy - sc * eu - bij; 514c5566c22SJunchao Zhang if (k == 0) F0 = F; 515c5566c22SJunchao Zhang J = 2.0 * (hydhx + hxdhy) - sc * eu; 516c5566c22SJunchao Zhang y = F / J; 517c5566c22SJunchao Zhang u -= y; 518c5566c22SJunchao Zhang tot_its++; 519c5566c22SJunchao Zhang 5209371c9d4SSatish Balay if (atol > PetscAbsReal(PetscRealPart(F)) || rtol * PetscAbsReal(PetscRealPart(F0)) > PetscAbsReal(PetscRealPart(F)) || stol * PetscAbsReal(PetscRealPart(u)) > PetscAbsReal(PetscRealPart(y))) { break; } 521c5566c22SJunchao Zhang } 522c5566c22SJunchao Zhang x[j][i] = u; 523c5566c22SJunchao Zhang } 524c5566c22SJunchao Zhang } 525c5566c22SJunchao Zhang } 526c5566c22SJunchao Zhang /* 527c5566c22SJunchao Zhang Restore vector 528c5566c22SJunchao Zhang */ 529c5566c22SJunchao Zhang PetscCall(DMDAVecRestoreArray(da, localX, &x)); 530c5566c22SJunchao Zhang PetscCall(DMLocalToGlobalBegin(da, localX, INSERT_VALUES, X)); 531c5566c22SJunchao Zhang PetscCall(DMLocalToGlobalEnd(da, localX, INSERT_VALUES, X)); 532c5566c22SJunchao Zhang } 533c5566c22SJunchao Zhang PetscCall(PetscLogFlops(tot_its * (21.0))); 534c5566c22SJunchao Zhang PetscCall(DMRestoreLocalVector(da, &localX)); 535c5566c22SJunchao Zhang if (B) { 536c5566c22SJunchao Zhang PetscCall(DMDAVecRestoreArray(da, localB, &b)); 537c5566c22SJunchao Zhang PetscCall(DMRestoreLocalVector(da, &localB)); 538c5566c22SJunchao Zhang } 539c5566c22SJunchao Zhang PetscFunctionReturn(0); 540c5566c22SJunchao Zhang } 541c5566c22SJunchao Zhang 5429371c9d4SSatish Balay int main(int argc, char **argv) { 543c5566c22SJunchao Zhang SNES snes; /* nonlinear solver */ 544c5566c22SJunchao Zhang Vec x; /* solution vector */ 545c5566c22SJunchao Zhang AppCtx user; /* user-defined work context */ 546c5566c22SJunchao Zhang PetscInt its; /* iterations for convergence */ 547c5566c22SJunchao Zhang PetscReal bratu_lambda_max = 6.81; 548c5566c22SJunchao Zhang PetscReal bratu_lambda_min = 0.; 549c5566c22SJunchao Zhang PetscInt MMS = 1; 550c5566c22SJunchao Zhang PetscBool flg = PETSC_FALSE, setMMS; 551c5566c22SJunchao Zhang DM da; 552c5566c22SJunchao Zhang Vec r = NULL; 553c5566c22SJunchao Zhang KSP ksp; 554c5566c22SJunchao Zhang PetscInt lits, slits; 555c5566c22SJunchao Zhang PetscBool useKokkos = PETSC_FALSE; 556c5566c22SJunchao Zhang 557c5566c22SJunchao Zhang /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 558c5566c22SJunchao Zhang Initialize program 559c5566c22SJunchao Zhang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 560c5566c22SJunchao Zhang 561327415f7SBarry Smith PetscFunctionBeginUser; 562c5566c22SJunchao Zhang PetscCall(PetscInitialize(&argc, &argv, (char *)0, help)); 563c5566c22SJunchao Zhang 564c5566c22SJunchao Zhang PetscCall(PetscOptionsGetBool(NULL, NULL, "-use_kokkos", &useKokkos, NULL)); 565c5566c22SJunchao Zhang 566c5566c22SJunchao Zhang /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 567c5566c22SJunchao Zhang Initialize problem parameters 568c5566c22SJunchao Zhang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 569c5566c22SJunchao Zhang user.param = 6.0; 570c5566c22SJunchao Zhang PetscCall(PetscOptionsGetReal(NULL, NULL, "-par", &user.param, NULL)); 571c5566c22SJunchao Zhang 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); 572c5566c22SJunchao Zhang PetscCall(PetscOptionsGetInt(NULL, NULL, "-mms", &MMS, &setMMS)); 573c5566c22SJunchao Zhang if (MMS == 3) { 574c5566c22SJunchao Zhang PetscInt mPar = 2, nPar = 1; 575c5566c22SJunchao Zhang PetscCall(PetscOptionsGetInt(NULL, NULL, "-m_par", &mPar, NULL)); 576c5566c22SJunchao Zhang PetscCall(PetscOptionsGetInt(NULL, NULL, "-n_par", &nPar, NULL)); 577c5566c22SJunchao Zhang user.m = PetscPowInt(2, mPar); 578c5566c22SJunchao Zhang user.n = PetscPowInt(2, nPar); 579c5566c22SJunchao Zhang } 580c5566c22SJunchao Zhang 581c5566c22SJunchao Zhang /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 582c5566c22SJunchao Zhang Create nonlinear solver context 583c5566c22SJunchao Zhang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 584c5566c22SJunchao Zhang PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes)); 585c5566c22SJunchao Zhang PetscCall(SNESSetCountersReset(snes, PETSC_FALSE)); 586c5566c22SJunchao Zhang PetscCall(SNESSetNGS(snes, NonlinearGS, NULL)); 587c5566c22SJunchao Zhang 588c5566c22SJunchao Zhang /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 589c5566c22SJunchao Zhang Create distributed array (DMDA) to manage parallel grid and vectors 590c5566c22SJunchao Zhang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 591c5566c22SJunchao Zhang 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)); 592c5566c22SJunchao Zhang PetscCall(DMSetFromOptions(da)); 593c5566c22SJunchao Zhang PetscCall(DMSetUp(da)); 594c5566c22SJunchao Zhang PetscCall(DMDASetUniformCoordinates(da, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0)); 595c5566c22SJunchao Zhang PetscCall(DMSetApplicationContext(da, &user)); 596c5566c22SJunchao Zhang PetscCall(SNESSetDM(snes, da)); 597c5566c22SJunchao Zhang /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 598c5566c22SJunchao Zhang Extract global vectors from DMDA; then duplicate for remaining 599c5566c22SJunchao Zhang vectors that are the same types 600c5566c22SJunchao Zhang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 601c5566c22SJunchao Zhang PetscCall(DMCreateGlobalVector(da, &x)); 602c5566c22SJunchao Zhang 603c5566c22SJunchao Zhang /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 604c5566c22SJunchao Zhang Set local function evaluation routine 605c5566c22SJunchao Zhang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 606c5566c22SJunchao Zhang switch (MMS) { 6079371c9d4SSatish Balay case 0: 6089371c9d4SSatish Balay user.mms_solution = ZeroBCSolution; 6099371c9d4SSatish Balay user.mms_forcing = NULL; 6109371c9d4SSatish Balay break; 6119371c9d4SSatish Balay case 1: 6129371c9d4SSatish Balay user.mms_solution = MMSSolution1; 6139371c9d4SSatish Balay user.mms_forcing = MMSForcing1; 6149371c9d4SSatish Balay break; 6159371c9d4SSatish Balay case 2: 6169371c9d4SSatish Balay user.mms_solution = MMSSolution2; 6179371c9d4SSatish Balay user.mms_forcing = MMSForcing2; 6189371c9d4SSatish Balay break; 6199371c9d4SSatish Balay case 3: 6209371c9d4SSatish Balay user.mms_solution = MMSSolution3; 6219371c9d4SSatish Balay user.mms_forcing = MMSForcing3; 6229371c9d4SSatish Balay break; 6239371c9d4SSatish Balay case 4: 6249371c9d4SSatish Balay user.mms_solution = MMSSolution4; 6259371c9d4SSatish Balay user.mms_forcing = MMSForcing4; 6269371c9d4SSatish Balay break; 627c5566c22SJunchao Zhang default: SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_USER, "Unknown MMS type %" PetscInt_FMT, MMS); 628c5566c22SJunchao Zhang } 629c5566c22SJunchao Zhang 630c5566c22SJunchao Zhang if (useKokkos) { 631c5566c22SJunchao Zhang PetscCheck(MMS == 1, PETSC_COMM_WORLD, PETSC_ERR_USER, "FormFunctionLocalVec_Kokkos only works with MMS 1"); 632c5566c22SJunchao Zhang PetscCall(DMDASNESSetFunctionLocalVec(da, INSERT_VALUES, (DMDASNESFunctionVec)FormFunctionLocalVec, &user)); 633c5566c22SJunchao Zhang } else { 634c5566c22SJunchao Zhang PetscCall(DMDASNESSetFunctionLocal(da, INSERT_VALUES, (DMDASNESFunction)FormFunctionLocal, &user)); 635c5566c22SJunchao Zhang } 636c5566c22SJunchao Zhang 637c5566c22SJunchao Zhang PetscCall(PetscOptionsGetBool(NULL, NULL, "-fd", &flg, NULL)); 638c5566c22SJunchao Zhang if (!flg) { 639c5566c22SJunchao Zhang if (useKokkos) PetscCall(DMDASNESSetJacobianLocalVec(da, (DMDASNESJacobianVec)FormJacobianLocalVec, &user)); 640c5566c22SJunchao Zhang else PetscCall(DMDASNESSetJacobianLocal(da, (DMDASNESJacobian)FormJacobianLocal, &user)); 641c5566c22SJunchao Zhang } 642c5566c22SJunchao Zhang 643c5566c22SJunchao Zhang PetscCall(PetscOptionsGetBool(NULL, NULL, "-obj", &flg, NULL)); 644c5566c22SJunchao Zhang if (flg) { 645c5566c22SJunchao Zhang if (useKokkos) PetscCall(DMDASNESSetObjectiveLocalVec(da, (DMDASNESObjectiveVec)FormObjectiveLocalVec, &user)); 646c5566c22SJunchao Zhang else PetscCall(DMDASNESSetObjectiveLocal(da, (DMDASNESObjective)FormObjectiveLocal, &user)); 647c5566c22SJunchao Zhang } 648c5566c22SJunchao Zhang 649c5566c22SJunchao Zhang if (PetscDefined(HAVE_MATLAB_ENGINE)) { 650c5566c22SJunchao Zhang PetscBool matlab_function = PETSC_FALSE; 651c5566c22SJunchao Zhang PetscCall(PetscOptionsGetBool(NULL, NULL, "-matlab_function", &matlab_function, 0)); 652c5566c22SJunchao Zhang if (matlab_function) { 653c5566c22SJunchao Zhang PetscCall(VecDuplicate(x, &r)); 654c5566c22SJunchao Zhang PetscCall(SNESSetFunction(snes, r, FormFunctionMatlab, &user)); 655c5566c22SJunchao Zhang } 656c5566c22SJunchao Zhang } 657c5566c22SJunchao Zhang 658c5566c22SJunchao Zhang /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 659c5566c22SJunchao Zhang Customize nonlinear solver; set runtime options 660c5566c22SJunchao Zhang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 661c5566c22SJunchao Zhang PetscCall(SNESSetFromOptions(snes)); 662c5566c22SJunchao Zhang 663c5566c22SJunchao Zhang PetscCall(FormInitialGuess(da, &user, x)); 664c5566c22SJunchao Zhang 665c5566c22SJunchao Zhang /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 666c5566c22SJunchao Zhang Solve nonlinear system 667c5566c22SJunchao Zhang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 668c5566c22SJunchao Zhang PetscCall(SNESSolve(snes, NULL, x)); 669c5566c22SJunchao Zhang PetscCall(SNESGetIterationNumber(snes, &its)); 670c5566c22SJunchao Zhang 671c5566c22SJunchao Zhang PetscCall(SNESGetLinearSolveIterations(snes, &slits)); 672c5566c22SJunchao Zhang PetscCall(SNESGetKSP(snes, &ksp)); 673c5566c22SJunchao Zhang PetscCall(KSPGetTotalIterations(ksp, &lits)); 674c5566c22SJunchao Zhang 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); 675c5566c22SJunchao Zhang /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 676c5566c22SJunchao Zhang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 677c5566c22SJunchao Zhang 678c5566c22SJunchao Zhang /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 679c5566c22SJunchao Zhang If using MMS, check the l_2 error 680c5566c22SJunchao Zhang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 681c5566c22SJunchao Zhang if (setMMS) { 682c5566c22SJunchao Zhang Vec e; 683c5566c22SJunchao Zhang PetscReal errorl2, errorinf; 684c5566c22SJunchao Zhang PetscInt N; 685c5566c22SJunchao Zhang 686c5566c22SJunchao Zhang PetscCall(VecDuplicate(x, &e)); 687c5566c22SJunchao Zhang PetscCall(PetscObjectViewFromOptions((PetscObject)x, NULL, "-sol_view")); 688c5566c22SJunchao Zhang PetscCall(FormExactSolution(da, &user, e)); 689c5566c22SJunchao Zhang PetscCall(PetscObjectViewFromOptions((PetscObject)e, NULL, "-exact_view")); 690c5566c22SJunchao Zhang PetscCall(VecAXPY(e, -1.0, x)); 691c5566c22SJunchao Zhang PetscCall(PetscObjectViewFromOptions((PetscObject)e, NULL, "-error_view")); 692c5566c22SJunchao Zhang PetscCall(VecNorm(e, NORM_2, &errorl2)); 693c5566c22SJunchao Zhang PetscCall(VecNorm(e, NORM_INFINITY, &errorinf)); 694c5566c22SJunchao Zhang PetscCall(VecGetSize(e, &N)); 695c5566c22SJunchao Zhang PetscCall(PetscPrintf(PETSC_COMM_WORLD, "N: %" PetscInt_FMT " error L2 %g inf %g\n", N, (double)(errorl2 / PetscSqrtReal((PetscReal)N)), (double)errorinf)); 696c5566c22SJunchao Zhang PetscCall(VecDestroy(&e)); 697c5566c22SJunchao Zhang PetscCall(PetscLogEventSetDof(SNES_Solve, 0, N)); 698c5566c22SJunchao Zhang PetscCall(PetscLogEventSetError(SNES_Solve, 0, errorl2 / PetscSqrtReal(N))); 699c5566c22SJunchao Zhang } 700c5566c22SJunchao Zhang 701c5566c22SJunchao Zhang /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 702c5566c22SJunchao Zhang Free work space. All PETSc objects should be destroyed when they 703c5566c22SJunchao Zhang are no longer needed. 704c5566c22SJunchao Zhang - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 705c5566c22SJunchao Zhang PetscCall(VecDestroy(&r)); 706c5566c22SJunchao Zhang PetscCall(VecDestroy(&x)); 707c5566c22SJunchao Zhang PetscCall(SNESDestroy(&snes)); 708c5566c22SJunchao Zhang PetscCall(DMDestroy(&da)); 709c5566c22SJunchao Zhang PetscCall(PetscFinalize()); 710c5566c22SJunchao Zhang return 0; 711c5566c22SJunchao Zhang } 712c5566c22SJunchao Zhang 713c5566c22SJunchao Zhang /*TEST 714c5566c22SJunchao Zhang build: 715c5566c22SJunchao Zhang requires: kokkos_kernels 716c5566c22SJunchao Zhang depends: ex55k.kokkos.cxx 717c5566c22SJunchao Zhang 718c5566c22SJunchao Zhang testset: 719c5566c22SJunchao Zhang output_file: output/ex55_asm_0.out 720c5566c22SJunchao Zhang requires: !single 721c5566c22SJunchao Zhang args: -mms 1 -par 0.0 -snes_monitor_short -snes_converged_reason -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 722c5566c22SJunchao Zhang filter: grep -v "type" 723c5566c22SJunchao Zhang 724c5566c22SJunchao Zhang test: 725c5566c22SJunchao Zhang suffix: asm_0 726c5566c22SJunchao Zhang test: 727c5566c22SJunchao Zhang suffix: asm_0_kok 728c5566c22SJunchao Zhang args: -use_kokkos 1 -dm_mat_type aijkokkos -dm_vec_type kokkos 729c5566c22SJunchao Zhang 730c5566c22SJunchao Zhang TEST*/ 731