PetscErrorCode FormInitialGuess(SNES snes,Vec X,void *ctx) { AppCtx *user; PetscInt i,j,xs,ys,xm,ym; PetscErrorCode ierr; PetscReal tleft; PetscScalar **x; DM da; PetscFunctionBeginUser; ierr = SNESGetDM(snes,&da);CHKERRQ(ierr); ierr = DMGetApplicationContext(da,&user);CHKERRQ(ierr); tleft = user->tleft; /* Get ghost points */ ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); ierr = DMDAVecGetArray(da,X,&x);CHKERRQ(ierr); /* Compute initial guess */ for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { x[j][i] = tleft; } } ierr = DMDAVecRestoreArray(da,X,&x);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FormPsiAndInitialGuess(DM da,Vec U0,PetscBool feasible) { ObsCtx *user; PetscErrorCode ierr; PetscInt i,j,Mx,My,xs,ys,xm,ym; DM coordDA; Vec coordinates; DMDACoor2d **coords; PetscReal **psi, **u0, **uexact, x, y, r, afree = 0.69797, A = 0.68026, B = 0.47152, pi = 3.1415926; PetscFunctionBeginUser; ierr = DMGetApplicationContext(da,&user);CHKERRQ(ierr); ierr = 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); ierr = DMDAGetCorners(da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL);CHKERRQ(ierr); ierr = DMGetCoordinateDM(da, &coordDA);CHKERRQ(ierr); ierr = DMGetCoordinates(da, &coordinates);CHKERRQ(ierr); ierr = DMDAVecGetArray(coordDA, coordinates, &coords);CHKERRQ(ierr); ierr = DMDAVecGetArray(da, user->psi, &psi);CHKERRQ(ierr); ierr = DMDAVecGetArray(da, U0, &u0);CHKERRQ(ierr); ierr = DMDAVecGetArray(da, user->uexact, &uexact);CHKERRQ(ierr); for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { x = coords[j][i].x; y = coords[j][i].y; r = sqrt(x * x + y * y); if (r <= 1.0) { psi[j][i] = sqrt(1.0 - r * r); } else { psi[j][i] = -1.0; } if (r <= afree) { uexact[j][i] = psi[j][i]; /* on the obstacle */ } else { uexact[j][i] = - A * log(r) + B; /* solves the laplace eqn */ } if (feasible) { if (i == 0 || j == 0 || i == Mx-1 || j == My-1) { u0[j][i] = uexact[j][i]; } else { /* initial guess is admissible: it is above the obstacle */ u0[j][i] = uexact[j][i] + cos(pi * x / 4) * cos(pi * y / 4); } } else { u0[j][i] = 0.; } } } ierr = DMDAVecRestoreArray(da, user->psi, &psi);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da, U0, &u0);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da, user->uexact, &uexact);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(coordDA, coordinates, &coords);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FormPsiAndExactSoln(DM da) { ObsCtx *user; PetscErrorCode ierr; DMDALocalInfo info; PetscInt i,j; DM coordDA; Vec coordinates; DMDACoor2d **coords; PetscReal **psi, **uexact, r; const PetscReal afree = 0.69797, A = 0.68026, B = 0.47152; PetscFunctionBeginUser; ierr = DMGetApplicationContext(da,&user);CHKERRQ(ierr); ierr = DMDAGetLocalInfo(da,&info); CHKERRQ(ierr); ierr = DMGetCoordinateDM(da, &coordDA);CHKERRQ(ierr); ierr = DMGetCoordinates(da, &coordinates);CHKERRQ(ierr); ierr = DMDAVecGetArray(coordDA, coordinates, &coords);CHKERRQ(ierr); ierr = DMDAVecGetArray(da, user->psi, &psi);CHKERRQ(ierr); ierr = DMDAVecGetArray(da, user->uexact, &uexact);CHKERRQ(ierr); for (j=info.ys; j<info.ys+info.ym; j++) { for (i=info.xs; i<info.xs+info.xm; i++) { r = PetscSqrtReal(pow(coords[j][i].x,2) + pow(coords[j][i].y,2)); if (r <= 1.0) psi[j][i] = PetscSqrtReal(1.0 - r * r); else psi[j][i] = -1.0; if (r <= afree) uexact[j][i] = psi[j][i]; /* on the obstacle */ else uexact[j][i] = - A * PetscLogReal(r) + B; /* solves the laplace eqn */ } } ierr = DMDAVecRestoreArray(da, user->psi, &psi);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da, user->uexact, &uexact);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(coordDA, coordinates, &coords);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ DMPlexClone - Creates a DMPlex object with the same mesh as the original. Collective on MPI_Comm Input Parameter: . dm - The original DMPlex object Output Parameter: . newdm - The new DMPlex object Level: beginner .keywords: DMPlex, create @*/ PetscErrorCode DMPlexClone(DM dm, DM *newdm) { DM_Plex *mesh; Vec coords; void *ctx; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscValidPointer(newdm,2); ierr = DMCreate(PetscObjectComm((PetscObject)dm), newdm);CHKERRQ(ierr); ierr = PetscSFDestroy(&(*newdm)->sf);CHKERRQ(ierr); ierr = PetscObjectReference((PetscObject) dm->sf);CHKERRQ(ierr); (*newdm)->sf = dm->sf; mesh = (DM_Plex*) dm->data; mesh->refct++; (*newdm)->data = mesh; ierr = PetscObjectChangeTypeName((PetscObject) *newdm, DMPLEX);CHKERRQ(ierr); ierr = DMInitialize_Plex(*newdm);CHKERRQ(ierr); ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr); ierr = DMSetApplicationContext(*newdm, ctx);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr); if (coords) { ierr = DMSetCoordinatesLocal(*newdm, coords);CHKERRQ(ierr); } else { ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); if (coords) {ierr = DMSetCoordinates(*newdm, coords);CHKERRQ(ierr);} } PetscFunctionReturn(0); }
PetscErrorCode DMCreateSubDM_DA(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) { DM_DA *da = (DM_DA*) dm->data; PetscSection section; PetscErrorCode ierr; PetscFunctionBegin; if (subdm) { PetscSF sf; Vec coords; void *ctx; /* Cannot use DMClone since the dof stuff is mixed in. Ugh ierr = DMClone(dm, subdm);CHKERRQ(ierr); */ ierr = DMCreate(PetscObjectComm((PetscObject)dm), subdm);CHKERRQ(ierr); ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); ierr = DMSetPointSF(*subdm, sf);CHKERRQ(ierr); ierr = DMGetApplicationContext(dm, &ctx);CHKERRQ(ierr); ierr = DMSetApplicationContext(*subdm, ctx);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(dm, &coords);CHKERRQ(ierr); if (coords) { ierr = DMSetCoordinatesLocal(*subdm, coords);CHKERRQ(ierr); } else { ierr = DMGetCoordinates(dm, &coords);CHKERRQ(ierr); if (coords) {ierr = DMSetCoordinates(*subdm, coords);CHKERRQ(ierr);} } ierr = DMSetType(*subdm, DMDA);CHKERRQ(ierr); ierr = DMSetDimension(*subdm, dm->dim);CHKERRQ(ierr); ierr = DMDASetSizes(*subdm, da->M, da->N, da->P);CHKERRQ(ierr); ierr = DMDASetNumProcs(*subdm, da->m, da->n, da->p);CHKERRQ(ierr); ierr = DMDASetBoundaryType(*subdm, da->bx, da->by, da->bz);CHKERRQ(ierr); ierr = DMDASetDof(*subdm, numFields);CHKERRQ(ierr); ierr = DMDASetStencilType(*subdm, da->stencil_type);CHKERRQ(ierr); ierr = DMDASetStencilWidth(*subdm, da->s);CHKERRQ(ierr); ierr = DMDASetOwnershipRanges(*subdm, da->lx, da->ly, da->lz);CHKERRQ(ierr); } ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); if (section) { ierr = DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);CHKERRQ(ierr); } else { if (is) { PetscInt *indices, cnt = 0, dof = da->w, i, j; ierr = PetscMalloc1(da->Nlocal*numFields/dof, &indices);CHKERRQ(ierr); for (i = da->base/dof; i < (da->base+da->Nlocal)/dof; ++i) { for (j = 0; j < numFields; ++j) { indices[cnt++] = dof*i + fields[j]; } } if (cnt != da->Nlocal*numFields/dof) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Count %d does not equal expected value %d", cnt, da->Nlocal*numFields/dof); ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cnt, indices, PETSC_OWN_POINTER, is);CHKERRQ(ierr); } } PetscFunctionReturn(0); }
PetscErrorCode ComputeRHS(KSP ksp,Vec b,void *ctx) { PetscErrorCode ierr; PetscInt mx; PetscScalar h; Vec x; DM da; PetscFunctionBeginUser; ierr = KSPGetDM(ksp,&da);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&mx,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); ierr = DMGetApplicationContext(da,&x);CHKERRQ(ierr); h = 2.0*PETSC_PI/((mx)); ierr = VecCopy(x,b);CHKERRQ(ierr); ierr = VecScale(b,h);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode MyDMComputeFunction(DM dm,Vec x,Vec F) { PetscErrorCode ierr; Mat J; PetscFunctionBegin; ierr = DMGetApplicationContext(dm,&J);CHKERRQ(ierr); if (!J) { ierr = DMCreateMatrix(dm,MATAIJ,&J);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject)J,"DM",(PetscObject)PETSC_NULL);CHKERRQ(ierr); ierr = FormMatrix(dm,J);CHKERRQ(ierr); ierr = DMSetApplicationContext(dm,J);CHKERRQ(ierr); ierr = DMSetApplicationContextDestroy(dm,(PetscErrorCode (*)(void**))MatDestroy);CHKERRQ(ierr); } ierr = MatMult(J,x,F);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode MyComputeFunction(SNES snes,Vec x,Vec F,void *ctx) { PetscErrorCode ierr; Mat J; DM dm; PetscFunctionBeginUser; ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); ierr = DMGetApplicationContext(dm,&J);CHKERRQ(ierr); if (!J) { ierr = DMCreateMatrix(dm,MATAIJ,&J);CHKERRQ(ierr); ierr = MatSetDM(J, PETSC_NULL);CHKERRQ(ierr); ierr = FormMatrix(dm,J);CHKERRQ(ierr); ierr = DMSetApplicationContext(dm,J);CHKERRQ(ierr); ierr = DMSetApplicationContextDestroy(dm,(PetscErrorCode (*)(void**))MatDestroy);CHKERRQ(ierr); } ierr = MatMult(J,x,F);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode Monitor(SNES snes,PetscInt its,PetscReal rnorm,void *dummy) { UserCtx *user; PetscErrorCode ierr; PetscInt m,N; PetscScalar *w,*dw; Vec u_lambda,U,F,Uexact; DM packer; PetscReal norm; DM da; PetscFunctionBeginUser; ierr = SNESGetDM(snes,&packer);CHKERRQ(ierr); ierr = DMGetApplicationContext(packer,&user);CHKERRQ(ierr); ierr = SNESGetSolution(snes,&U);CHKERRQ(ierr); ierr = DMCompositeGetAccess(packer,U,&w,&u_lambda);CHKERRQ(ierr); ierr = VecView(u_lambda,user->u_lambda_viewer);CHKERRQ(ierr); ierr = DMCompositeRestoreAccess(packer,U,&w,&u_lambda);CHKERRQ(ierr); ierr = SNESGetFunction(snes,&F,0,0);CHKERRQ(ierr); ierr = DMCompositeGetAccess(packer,F,&w,&u_lambda);CHKERRQ(ierr); /* ierr = VecView(u_lambda,user->fu_lambda_viewer); */ ierr = DMCompositeRestoreAccess(packer,U,&w,&u_lambda);CHKERRQ(ierr); ierr = DMCompositeGetEntries(packer,&m,&da);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&N,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); ierr = VecDuplicate(U,&Uexact);CHKERRQ(ierr); ierr = ExactSolution(packer,Uexact);CHKERRQ(ierr); ierr = VecAXPY(Uexact,-1.0,U);CHKERRQ(ierr); ierr = DMCompositeGetAccess(packer,Uexact,&dw,&u_lambda);CHKERRQ(ierr); ierr = VecStrideNorm(u_lambda,0,NORM_2,&norm);CHKERRQ(ierr); norm = norm/PetscSqrtReal((PetscReal)N-1.); if (dw) ierr = PetscPrintf(PETSC_COMM_WORLD,"Norm of error %g Error at x = 0 %g\n",(double)norm,(double)PetscRealPart(dw[0]));CHKERRQ(ierr); ierr = VecView(u_lambda,user->fu_lambda_viewer);CHKERRQ(ierr); ierr = DMCompositeRestoreAccess(packer,Uexact,&dw,&u_lambda);CHKERRQ(ierr); ierr = VecDestroy(&Uexact);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* Applies some sweeps on nonlinear Gauss-Seidel on each process */ PetscErrorCode NonlinearGS(SNES snes,Vec X, Vec B, void *ctx) { PetscInt i,j,k,Mx,My,xs,ys,xm,ym,its,tot_its,sweeps,l; PetscErrorCode ierr; PetscReal lambda,hx,hy,hxdhy,hydhx,sc; PetscScalar **x,**b,bij,F,F0=0,J,u,un,us,ue,eu,uw,uxx,uyy,y; PetscReal atol,rtol,stol; DM da; AppCtx *user; Vec localX,localB; PetscFunctionBeginUser; tot_its = 0; ierr = SNESNGSGetSweeps(snes,&sweeps);CHKERRQ(ierr); ierr = SNESNGSGetTolerances(snes,&atol,&rtol,&stol,&its);CHKERRQ(ierr); ierr = SNESGetDM(snes,&da);CHKERRQ(ierr); ierr = DMGetApplicationContext(da,(void**)&user);CHKERRQ(ierr); ierr = 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);CHKERRQ(ierr); lambda = user->param; hx = 1.0/(PetscReal)(Mx-1); hy = 1.0/(PetscReal)(My-1); sc = hx*hy*lambda; hxdhy = hx/hy; hydhx = hy/hx; ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr); if (B) { ierr = DMGetLocalVector(da,&localB);CHKERRQ(ierr); } for (l=0; l<sweeps; l++) { ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); if (B) { ierr = DMGlobalToLocalBegin(da,B,INSERT_VALUES,localB);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,B,INSERT_VALUES,localB);CHKERRQ(ierr); } /* Get a pointer to vector data. - For default PETSc vectors, VecGetArray() returns a pointer to the data array. Otherwise, the routine is implementation dependent. - You MUST call VecRestoreArray() when you no longer need access to the array. */ ierr = DMDAVecGetArray(da,localX,&x);CHKERRQ(ierr); if (B) ierr = DMDAVecGetArray(da,localB,&b);CHKERRQ(ierr); /* Get local grid boundaries (for 2-dimensional DMDA): xs, ys - starting grid indices (no ghost points) xm, ym - widths of local grid (no ghost points) */ ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr); for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { if (i == 0 || j == 0 || i == Mx-1 || j == My-1) { /* boundary conditions are all zero Dirichlet */ x[j][i] = 0.0; } else { if (B) bij = b[j][i]; else bij = 0.; u = x[j][i]; un = x[j-1][i]; us = x[j+1][i]; ue = x[j][i-1]; uw = x[j][i+1]; for (k=0; k<its; k++) { eu = PetscExpScalar(u); uxx = (2.0*u - ue - uw)*hydhx; uyy = (2.0*u - un - us)*hxdhy; F = uxx + uyy - sc*eu - bij; if (k == 0) F0 = F; J = 2.0*(hydhx + hxdhy) - sc*eu; y = F/J; u -= y; tot_its++; if (atol > PetscAbsReal(PetscRealPart(F)) || rtol*PetscAbsReal(PetscRealPart(F0)) > PetscAbsReal(PetscRealPart(F)) || stol*PetscAbsReal(PetscRealPart(u)) > PetscAbsReal(PetscRealPart(y))) { break; } } x[j][i] = u; } } } /* Restore vector */ ierr = DMDAVecRestoreArray(da,localX,&x);CHKERRQ(ierr); ierr = DMLocalToGlobalBegin(da,localX,INSERT_VALUES,X);CHKERRQ(ierr); ierr = DMLocalToGlobalEnd(da,localX,INSERT_VALUES,X);CHKERRQ(ierr); } ierr = PetscLogFlops(tot_its*(21.0));CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr); if (B) { ierr = DMDAVecRestoreArray(da,localB,&b);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localB);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@ PetscConvEstGetConvRate - Returns an estimate of the convergence rate for the discretization Not collective Input Parameter: . ce - The PetscConvEst object Output Parameter: . alpha - The convergence rate for each field Note: The convergence rate alpha is defined by $ || u_h - u_exact || < C h^alpha where u_h is the discrete solution, and h is a measure of the discretization size. We solve a series of problems on refined meshes, calculate an error based upon the exact solution in the DS, and then fit the result to our model above using linear regression. Options database keys: . -snes_convergence_estimate : Execute convergence estimation and print out the rate Level: intermediate .keywords: PetscConvEst, convergence .seealso: PetscConvEstSetSolver(), PetscConvEstCreate(), PetscConvEstGetConvRate() @*/ PetscErrorCode PetscConvEstGetConvRate(PetscConvEst ce, PetscReal alpha[]) { DM *dm; PetscObject disc; MPI_Comm comm; const char *uname, *dmname; void *ctx; Vec u; PetscReal t = 0.0, *x, *y, slope, intercept; PetscInt *dof, dim, Nr = ce->Nr, r, f, oldlevel, oldnlev; PetscLogEvent event; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject) ce, &comm);CHKERRQ(ierr); ierr = DMGetDimension(ce->idm, &dim);CHKERRQ(ierr); ierr = DMGetApplicationContext(ce->idm, &ctx);CHKERRQ(ierr); ierr = DMPlexSetRefinementUniform(ce->idm, PETSC_TRUE);CHKERRQ(ierr); ierr = DMGetRefineLevel(ce->idm, &oldlevel);CHKERRQ(ierr); ierr = PetscMalloc2((Nr+1), &dm, (Nr+1)*ce->Nf, &dof);CHKERRQ(ierr); dm[0] = ce->idm; for (f = 0; f < ce->Nf; ++f) alpha[f] = 0.0; /* Loop over meshes */ ierr = PetscLogEventRegister("ConvEst Error", PETSC_OBJECT_CLASSID, &event);CHKERRQ(ierr); for (r = 0; r <= Nr; ++r) { PetscLogStage stage; char stageName[PETSC_MAX_PATH_LEN]; ierr = PetscSNPrintf(stageName, PETSC_MAX_PATH_LEN-1, "ConvEst Refinement Level %D", r);CHKERRQ(ierr); ierr = PetscLogStageRegister(stageName, &stage);CHKERRQ(ierr); ierr = PetscLogStagePush(stage);CHKERRQ(ierr); if (r > 0) { ierr = DMRefine(dm[r-1], MPI_COMM_NULL, &dm[r]);CHKERRQ(ierr); ierr = DMSetCoarseDM(dm[r], dm[r-1]);CHKERRQ(ierr); ierr = DMCopyDisc(ce->idm, dm[r]);CHKERRQ(ierr); ierr = DMCopyTransform(ce->idm, dm[r]);CHKERRQ(ierr); ierr = PetscObjectGetName((PetscObject) dm[r-1], &dmname);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) dm[r], dmname);CHKERRQ(ierr); for (f = 0; f <= ce->Nf; ++f) { PetscErrorCode (*nspconstr)(DM, PetscInt, MatNullSpace *); ierr = DMGetNullSpaceConstructor(dm[r-1], f, &nspconstr);CHKERRQ(ierr); ierr = DMSetNullSpaceConstructor(dm[r], f, nspconstr);CHKERRQ(ierr); } } ierr = DMViewFromOptions(dm[r], NULL, "-conv_dm_view");CHKERRQ(ierr); /* Create solution */ ierr = DMCreateGlobalVector(dm[r], &u);CHKERRQ(ierr); ierr = DMGetField(dm[r], 0, NULL, &disc);CHKERRQ(ierr); ierr = PetscObjectGetName(disc, &uname);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) u, uname);CHKERRQ(ierr); /* Setup solver */ ierr = SNESReset(ce->snes);CHKERRQ(ierr); ierr = SNESSetDM(ce->snes, dm[r]);CHKERRQ(ierr); ierr = DMPlexSetSNESLocalFEM(dm[r], ctx, ctx, ctx);CHKERRQ(ierr); ierr = SNESSetFromOptions(ce->snes);CHKERRQ(ierr); /* Create initial guess */ ierr = DMProjectFunction(dm[r], t, ce->initGuess, ce->ctxs, INSERT_VALUES, u);CHKERRQ(ierr); ierr = SNESSolve(ce->snes, NULL, u);CHKERRQ(ierr); ierr = PetscLogEventBegin(event, ce, 0, 0, 0);CHKERRQ(ierr); ierr = DMComputeL2FieldDiff(dm[r], t, ce->exactSol, ce->ctxs, u, &ce->errors[r*ce->Nf]);CHKERRQ(ierr); ierr = PetscLogEventEnd(event, ce, 0, 0, 0);CHKERRQ(ierr); for (f = 0; f < ce->Nf; ++f) { PetscSection s, fs; PetscInt lsize; /* Could use DMGetOutputDM() to add in Dirichlet dofs */ ierr = DMGetSection(dm[r], &s);CHKERRQ(ierr); ierr = PetscSectionGetField(s, f, &fs);CHKERRQ(ierr); ierr = PetscSectionGetConstrainedStorageSize(fs, &lsize);CHKERRQ(ierr); ierr = MPI_Allreduce(&lsize, &dof[r*ce->Nf+f], 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) ce->snes));CHKERRQ(ierr); ierr = PetscLogEventSetDof(event, f, dof[r*ce->Nf+f]);CHKERRQ(ierr); ierr = PetscLogEventSetError(event, f, ce->errors[r*ce->Nf+f]);CHKERRQ(ierr); } /* Monitor */ if (ce->monitor) { PetscReal *errors = &ce->errors[r*ce->Nf]; ierr = PetscPrintf(comm, "L_2 Error: ");CHKERRQ(ierr); if (ce->Nf > 1) {ierr = PetscPrintf(comm, "[");CHKERRQ(ierr);} for (f = 0; f < ce->Nf; ++f) { if (f > 0) {ierr = PetscPrintf(comm, ", ");CHKERRQ(ierr);} if (errors[f] < 1.0e-11) {ierr = PetscPrintf(comm, "< 1e-11");CHKERRQ(ierr);} else {ierr = PetscPrintf(comm, "%g", (double)errors[f]);CHKERRQ(ierr);} } if (ce->Nf > 1) {ierr = PetscPrintf(comm, "]");CHKERRQ(ierr);} ierr = PetscPrintf(comm, "\n");CHKERRQ(ierr); } if (!r) { /* PCReset() does not wipe out the level structure */ KSP ksp; PC pc; ierr = SNESGetKSP(ce->snes, &ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PCMGGetLevels(pc, &oldnlev);CHKERRQ(ierr); } /* Cleanup */ ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); } for (r = 1; r <= Nr; ++r) { ierr = DMDestroy(&dm[r]);CHKERRQ(ierr); } /* Fit convergence rate */ ierr = PetscMalloc2(Nr+1, &x, Nr+1, &y);CHKERRQ(ierr); for (f = 0; f < ce->Nf; ++f) { for (r = 0; r <= Nr; ++r) { x[r] = PetscLog10Real(dof[r*ce->Nf+f]); y[r] = PetscLog10Real(ce->errors[r*ce->Nf+f]); } ierr = PetscLinearRegression(Nr+1, x, y, &slope, &intercept);CHKERRQ(ierr); /* Since h^{-dim} = N, lg err = s lg N + b = -s dim lg h + b */ alpha[f] = -slope * dim; } ierr = PetscFree2(x, y);CHKERRQ(ierr); ierr = PetscFree2(dm, dof);CHKERRQ(ierr); /* Restore solver */ ierr = SNESReset(ce->snes);CHKERRQ(ierr); { /* PCReset() does not wipe out the level structure */ KSP ksp; PC pc; ierr = SNESGetKSP(ce->snes, &ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PCMGSetLevels(pc, oldnlev, NULL);CHKERRQ(ierr); ierr = DMSetRefineLevel(ce->idm, oldlevel);CHKERRQ(ierr); /* The damn DMCoarsen() calls in PCMG can reset this */ } ierr = SNESSetDM(ce->snes, ce->idm);CHKERRQ(ierr); ierr = DMPlexSetSNESLocalFEM(ce->idm, ctx, ctx, ctx);CHKERRQ(ierr); ierr = SNESSetFromOptions(ce->snes);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* FormInitialGuess - Forms initial approximation. Input Parameters: dm - The DM context X - vector Output Parameter: X - vector */ PetscErrorCode FormInitialGuess(SNES snes,Vec X,void *ctx) { AppCtx *user; PetscInt i,j,Mx,My,xs,ys,xm,ym; PetscErrorCode ierr; PetscReal lambda,hx,hy; PETSC_UNUSED PetscReal temp1; Field **x; DM da; PetscFunctionBeginUser; ierr = SNESGetDM(snes,&da);CHKERRQ(ierr); ierr = DMGetApplicationContext(da,&user);CHKERRQ(ierr); ierr = 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);CHKERRQ(ierr); lambda = user->lambda; hx = 1.0/(PetscReal)(Mx-1); hy = 1.0/(PetscReal)(My-1); if (lambda == 0.0) temp1 = 0.0; else temp1 = lambda/(lambda + 1.0); /* Get a pointer to vector data. - For default PETSc vectors, VecGetArray() returns a pointer to the data array. Otherwise, the routine is implementation dependent. - You MUST call VecRestoreArray() when you no longer need access to the array. */ ierr = DMDAVecGetArray(da,X,&x);CHKERRQ(ierr); /* Get local grid boundaries (for 2-dimensional DMDA): xs, ys - starting grid indices (no ghost points) xm, ym - widths of local grid (no ghost points) */ ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr); /* Compute initial guess over the locally owned part of the grid */ for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { #define CHECK_SOLUTION #if defined(CHECK_SOLUTION) ierr = ExactSolution(i*hx, j*hy, &x[j][i]);CHKERRQ(ierr); #else if (i == 0 || j == 0 || i == Mx-1 || j == My-1) { /* Boundary conditions are usually zero Dirichlet */ ierr = ExactSolution(i*hx, j*hy, &x[j][i]);CHKERRQ(ierr); } else { PetscReal temp = (PetscReal)(PetscMin(j,My-j-1))*hy; x[j][i].u = temp1*PetscSqrtReal(PetscMin((PetscReal)(PetscMin(i,Mx-i-1))*hx,temp)); x[j][i].v = temp1*PetscSqrtReal(PetscMin((PetscReal)(PetscMin(i,Mx-i-1))*hx,temp)); x[j][i].p = 1.0; } #endif } } /* Restore vector */ ierr = DMDAVecRestoreArray(da,X,&x);CHKERRQ(ierr); PetscFunctionReturn(0); }