static PetscErrorCode update_dirichlet_sym(ef_bc *bc, Mat A, DM da) { PetscErrorCode ierr; PetscInt i,j,cnt; PetscInt ngx, ngy; PetscScalar v[8]; MatStencil row[8], col; PetscInt level; ef_patch *patch = bc->patch; ierr = DMGetCoarsenLevel(da, &level);CHKERRQ(ierr); ierr = DMDAGetInfo(da, 0, &ngx, &ngy, 0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); for (i = 0; i < 8; i++) v[i] = 0; for (j = patch->corners[level].is[1]; j <= patch->corners[level].ie[1]; j++) { for (i = patch->corners[level].is[0]; i <= patch->corners[level].ie[0]; i++) { col.i = i; col.j = j; cnt = 0; if (i-1 < patch->corners[level].is[0] && i-1 >= 0) { row[cnt].i = i-1; row[cnt].j = j; cnt++; if (j-1 < patch->corners[level].is[1] && j-1 >= 0) { row[cnt].i = i-1; row[cnt].j = j-1; cnt++; } if (j+1 > patch->corners[level].ie[1] && j+1 <= ngy-1) { row[cnt].i = i-1; row[cnt].j = j+1; cnt++; } } if (i+1 > patch->corners[level].ie[0] && i+1 <= ngx-1) { row[cnt].i = i+1; row[cnt].j = j; cnt++; if (j-1 < patch->corners[level].is[1] && j-1 >= 0) { row[cnt].i = i+1; row[cnt].j = j-1; cnt++; } if (j+1 > patch->corners[level].ie[1] && j+1 <= ngy-1) { row[cnt].i = i+1; row[cnt].j = j+1; cnt++; } } if (j-1 < patch->corners[level].is[1] && j-1 >= 0) { row[cnt].i = i; row[cnt].j = j-1; cnt++; } if (j+1 > patch->corners[level].ie[1] && j+1 <= ngy-1) { row[cnt].i = i; row[cnt].j = j+1; cnt++; } ierr = MatSetValuesStencil(A, cnt, row, 1, &col, v, INSERT_VALUES);CHKERRQ(ierr); } } return 0; }
int main(int argc,char **argv) { AppCtx appctx; /* user-defined application context */ TS ts; /* timestepping context */ Vec U; /* approximate solution vector */ PetscErrorCode ierr; PetscReal dt; DM da; PetscInt M; PetscMPIInt rank; PetscBool useLaxWendroff = PETSC_TRUE; /* Initialize program and set problem parameters */ ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); appctx.a = -1.0; ierr = PetscOptionsGetReal(NULL,NULL,"-a",&appctx.a,NULL);CHKERRQ(ierr); ierr = DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_PERIODIC, 60, 1, 1,NULL,&da);CHKERRQ(ierr); ierr = DMSetFromOptions(da);CHKERRQ(ierr); ierr = DMSetUp(da);CHKERRQ(ierr); /* Create vector data structures for approximate and exact solutions */ ierr = DMCreateGlobalVector(da,&U);CHKERRQ(ierr); /* Create timestepping solver context */ ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr); ierr = TSSetDM(ts,da);CHKERRQ(ierr); /* Function evaluation */ ierr = PetscOptionsGetBool(NULL,NULL,"-useLaxWendroff",&useLaxWendroff,NULL);CHKERRQ(ierr); if (useLaxWendroff) { if (!rank) { ierr = PetscPrintf(PETSC_COMM_SELF,"... Use Lax-Wendroff finite volume\n");CHKERRQ(ierr); } ierr = TSSetIFunction(ts,NULL,IFunction_LaxWendroff,&appctx);CHKERRQ(ierr); } else { if (!rank) { ierr = PetscPrintf(PETSC_COMM_SELF,"... Use Lax-LaxFriedrichs finite difference\n");CHKERRQ(ierr); } ierr = TSSetIFunction(ts,NULL,IFunction_LaxFriedrichs,&appctx);CHKERRQ(ierr); } /* Customize timestepping solver */ ierr = DMDAGetInfo(da,PETSC_IGNORE,&M,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); dt = 1.0/(PetscAbsReal(appctx.a)*M); ierr = TSSetTimeStep(ts,dt);CHKERRQ(ierr); ierr = TSSetMaxSteps(ts,100);CHKERRQ(ierr); ierr = TSSetMaxTime(ts,100.0);CHKERRQ(ierr); ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER);CHKERRQ(ierr); ierr = TSSetType(ts,TSBEULER);CHKERRQ(ierr); ierr = TSSetFromOptions(ts);CHKERRQ(ierr); /* Evaluate initial conditions */ ierr = InitialConditions(ts,U,&appctx);CHKERRQ(ierr); /* For testing accuracy of TS with already known solution, e.g., '-ts_monitor_lg_error' */ ierr = TSSetSolutionFunction(ts,(PetscErrorCode (*)(TS,PetscReal,Vec,void*))Solution,&appctx);CHKERRQ(ierr); /* Run the timestepping solver */ ierr = TSSolve(ts,U);CHKERRQ(ierr); /* Free work space */ ierr = TSDestroy(&ts);CHKERRQ(ierr); ierr = VecDestroy(&U);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
PetscErrorCode IJacobian(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal a,Mat *J,Mat *Jpre,MatStructure *flg,void *ctx) { PetscErrorCode ierr; AppCtx *user=(AppCtx*)ctx; DM cda; DMDACoor2d **coors; PetscInt i,j; PetscInt xs,ys,xm,ym,M,N; Vec gc; PetscScalar val[5],xi,yi; MatStencil row,col[5]; PetscScalar c1,c3,c5; PetscFunctionBeginUser; *flg = SAME_NONZERO_PATTERN; ierr = DMDAGetInfo(user->da,NULL,&M,&N,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); ierr = DMGetCoordinateDM(user->da,&cda);CHKERRQ(ierr); ierr = DMDAGetCorners(cda,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(user->da,&gc);CHKERRQ(ierr); ierr = DMDAVecGetArray(cda,gc,&coors);CHKERRQ(ierr); for (i=xs; i < xs+xm; i++) { for (j=ys; j < ys+ym; j++) { xi = coors[j][i].x; yi = coors[j][i].y; PetscInt nc = 0; row.i = i; row.j = j; if (i == 0 || j == 0 || i == M-1 || j == N-1) { if (user->bc == 0) { col[nc].i = i; col[nc].j = j; val[nc++] = 1.0; } else { PetscScalar fthetac,fwc; fthetac = user->ws/(2*user->H)*(user->PM_min - user->Pmax*sin(xi)); fwc = (yi*yi/2.0 - user->ws*yi); if (i==0 && j==0) { col[nc].i = i+1; col[nc].j = j; val[nc++] = fwc/user->dx; col[nc].i = i; col[nc].j = j+1; val[nc++] = -user->disper_coe/user->dy; col[nc].i = i; col[nc].j = j; val[nc++] = -fwc/user->dx + fthetac + user->disper_coe/user->dy; } else if (i==0 && j == N-1) { col[nc].i = i+1; col[nc].j = j; val[nc++] = fwc/user->dx; col[nc].i = i; col[nc].j = j-1; val[nc++] = user->disper_coe/user->dy; col[nc].i = i; col[nc].j = j; val[nc++] = -fwc/user->dx + fthetac - user->disper_coe/user->dy; } else if (i== M-1 && j == 0) { col[nc].i = i-1; col[nc].j = j; val[nc++] = -fwc/user->dx; col[nc].i = i; col[nc].j = j+1; val[nc++] = -user->disper_coe/user->dy; col[nc].i = i; col[nc].j = j; val[nc++] = fwc/user->dx + fthetac + user->disper_coe/user->dy; } else if (i == M-1 && j == N-1) { col[nc].i = i-1; col[nc].j = j; val[nc++] = -fwc/user->dx; col[nc].i = i; col[nc].j = j-1; val[nc++] = user->disper_coe/user->dy; col[nc].i = i; col[nc].j = j; val[nc++] = fwc/user->dx + fthetac - user->disper_coe/user->dy; } else if (i==0) { col[nc].i = i+1; col[nc].j = j; val[nc++] = fwc/user->dx; col[nc].i = i; col[nc].j = j+1; val[nc++] = -user->disper_coe/(2*user->dy); col[nc].i = i; col[nc].j = j-1; val[nc++] = user->disper_coe/(2*user->dy); col[nc].i = i; col[nc].j = j; val[nc++] = -fwc/user->dx + fthetac; } else if (i == M-1) { col[nc].i = i-1; col[nc].j = j; val[nc++] = -fwc/user->dx; col[nc].i = i; col[nc].j = j+1; val[nc++] = -user->disper_coe/(2*user->dy); col[nc].i = i; col[nc].j = j-1; val[nc++] = user->disper_coe/(2*user->dy); col[nc].i = i; col[nc].j = j; val[nc++] = fwc/user->dx + fthetac; } else if (j==0) { col[nc].i = i+1; col[nc].j = j; val[nc++] = fwc/(2*user->dx); col[nc].i = i-1; col[nc].j = j; val[nc++] = -fwc/(2*user->dx); col[nc].i = i; col[nc].j = j+1; val[nc++] = -user->disper_coe/user->dy; col[nc].i = i; col[nc].j = j; val[nc++] = user->disper_coe/user->dy + fthetac; } else if (j == N-1) { col[nc].i = i+1; col[nc].j = j; val[nc++] = fwc/(2*user->dx); col[nc].i = i-1; col[nc].j = j; val[nc++] = -fwc/(2*user->dx); col[nc].i = i; col[nc].j = j-1; val[nc++] = user->disper_coe/user->dy; col[nc].i = i; col[nc].j = j; val[nc++] = -user->disper_coe/user->dy + fthetac; } } } else { c1 = (yi-user->ws)/(2*user->dx); c3 = (user->ws/(2.0*user->H))*(user->PM_min - user->Pmax*sin(xi))/(2*user->dy); c5 = (PetscPowScalar((user->lambda*user->ws)/(2*user->H),2)*user->q*(1.0-PetscExpScalar(-t/user->lambda)))/(user->dy*user->dy); col[nc].i = i-1; col[nc].j = j; val[nc++] = c1; col[nc].i = i+1; col[nc].j = j; val[nc++] = -c1; col[nc].i = i; col[nc].j = j-1; val[nc++] = c3 + c5; col[nc].i = i; col[nc].j = j+1; val[nc++] = -c3 + c5; col[nc].i = i; col[nc].j = j; val[nc++] = -2*c5 -a; } ierr = MatSetValuesStencil(*Jpre,1,&row,nc,col,val,INSERT_VALUES);CHKERRQ(ierr); } } ierr = DMDAVecRestoreArray(cda,gc,&coors);CHKERRQ(ierr); ierr = MatAssemblyBegin(*Jpre,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(*Jpre,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); if (*J != *Jpre) { ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode IFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,void *ctx) { PetscErrorCode ierr; AppCtx *user=(AppCtx*)ctx; DM cda; DMDACoor2d **coors; PetscScalar **p,**f,**pdot; PetscInt i,j; PetscInt xs,ys,xm,ym,M,N; Vec localX,gc,localXdot; PetscScalar p_adv1,p_adv2,p_diff; PetscFunctionBeginUser; ierr = DMDAGetInfo(user->da,NULL,&M,&N,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); ierr = DMGetCoordinateDM(user->da,&cda); CHKERRQ(ierr); ierr = DMDAGetCorners(cda,&xs,&ys,0,&xm,&ym,0); CHKERRQ(ierr); ierr = DMGetLocalVector(user->da,&localX); CHKERRQ(ierr); ierr = DMGetLocalVector(user->da,&localXdot); CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX); CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX); CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(user->da,Xdot,INSERT_VALUES,localXdot); CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(user->da,Xdot,INSERT_VALUES,localXdot); CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(user->da,&gc); CHKERRQ(ierr); ierr = DMDAVecGetArray(cda,gc,&coors); CHKERRQ(ierr); ierr = DMDAVecGetArray(user->da,localX,&p); CHKERRQ(ierr); ierr = DMDAVecGetArray(user->da,localXdot,&pdot); CHKERRQ(ierr); ierr = DMDAVecGetArray(user->da,F,&f); CHKERRQ(ierr); user->disper_coe = PetscPowScalar((user->lambda*user->ws)/(2*user->H),2)*user->q*(1.0-PetscExpScalar(-t/user->lambda)); for (i=xs; i < xs+xm; i++) { for (j=ys; j < ys+ym; j++) { if (i == 0 || j == 0 || i == M-1 || j == N-1) { ierr = BoundaryConditions(p,coors,i,j,M,N,f,user); CHKERRQ(ierr); } else { ierr = adv1(p,coors[j][i].y,i,j,M,&p_adv1,user); CHKERRQ(ierr); ierr = adv2(p,coors[j][i].x,i,j,N,&p_adv2,user); CHKERRQ(ierr); ierr = diffuse(p,i,j,t,&p_diff,user); CHKERRQ(ierr); f[j][i] = -p_adv1 - p_adv2 + p_diff - pdot[j][i]; } } } ierr = DMDAVecRestoreArray(user->da,localX,&p); CHKERRQ(ierr); ierr = DMDAVecRestoreArray(user->da,localX,&pdot); CHKERRQ(ierr); ierr = DMRestoreLocalVector(user->da,&localX); CHKERRQ(ierr); ierr = DMRestoreLocalVector(user->da,&localXdot); CHKERRQ(ierr); ierr = DMDAVecRestoreArray(user->da,F,&f); CHKERRQ(ierr); ierr = DMDAVecRestoreArray(cda,gc,&coors); CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode DMPatchSolve(DM dm) { MPI_Comm comm; MPI_Comm commz; DM dmc; PetscSF sfz, sfzr; Vec XC; MatStencil patchSize, commSize, gridRank, lower, upper; PetscInt M, N, P, i, j, k, l, m, n, p = 0; PetscMPIInt rank, size; PetscInt debug = 0; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); ierr = DMPatchGetCoarse(dm, &dmc);CHKERRQ(ierr); ierr = DMPatchGetPatchSize(dm, &patchSize);CHKERRQ(ierr); ierr = DMPatchGetCommSize(dm, &commSize);CHKERRQ(ierr); ierr = DMPatchGetCommSize(dm, &commSize);CHKERRQ(ierr); ierr = DMGetGlobalVector(dmc, &XC);CHKERRQ(ierr); ierr = DMDAGetInfo(dmc, 0, &M, &N, &P, &l, &m, &n, 0,0,0,0,0,0);CHKERRQ(ierr); M = PetscMax(M, 1); l = PetscMax(l, 1); N = PetscMax(N, 1); m = PetscMax(m, 1); P = PetscMax(P, 1); n = PetscMax(n, 1); gridRank.i = rank % l; gridRank.j = rank/l % m; gridRank.k = rank/(l*m) % n; if (commSize.i*commSize.j*commSize.k == size || commSize.i*commSize.j*commSize.k == 0) { commSize.i = l; commSize.j = m; commSize.k = n; commz = comm; } else if (commSize.i*commSize.j*commSize.k == 1) { commz = PETSC_COMM_SELF; } else { const PetscMPIInt newComm = ((gridRank.k/commSize.k)*(m/commSize.j) + gridRank.j/commSize.j)*(l/commSize.i) + (gridRank.i/commSize.i); const PetscMPIInt newRank = ((gridRank.k%commSize.k)*commSize.j + gridRank.j%commSize.j)*commSize.i + (gridRank.i%commSize.i); ierr = MPI_Comm_split(comm, newComm, newRank, &commz);CHKERRQ(ierr); if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "Rank %d color %d key %d commz %d\n", rank, newComm, newRank, *((PetscMPIInt*) &commz));CHKERRQ(ierr);} } /* Assumptions: - patchSize divides gridSize - commSize divides gridSize - commSize divides l,m,n Ignore multiple patches per rank for now Multiple ranks per patch: - l,m,n divides patchSize - commSize divides patchSize */ for (k = 0; k < P; k += PetscMax(patchSize.k, 1)) { for (j = 0; j < N; j += PetscMax(patchSize.j, 1)) { for (i = 0; i < M; i += PetscMax(patchSize.i, 1), ++p) { MPI_Comm commp = MPI_COMM_NULL; DM dmz = NULL; #if 0 DM dmf = NULL; Mat interpz = NULL; #endif Vec XZ = NULL; PetscScalar *xcarray = NULL; PetscScalar *xzarray = NULL; if ((gridRank.k/commSize.k == p/(l/commSize.i * m/commSize.j) % n/commSize.k) && (gridRank.j/commSize.j == p/(l/commSize.i) % m/commSize.j) && (gridRank.i/commSize.i == p % l/commSize.i)) { if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, "Rank %d is accepting Patch %d\n", rank, p);CHKERRQ(ierr);} commp = commz; } /* Zoom to coarse patch */ lower.i = i; lower.j = j; lower.k = k; upper.i = i + patchSize.i; upper.j = j + patchSize.j; upper.k = k + patchSize.k; ierr = DMPatchZoom(dmc, XC, lower, upper, commp, &dmz, &sfz, &sfzr);CHKERRQ(ierr); lower.c = 0; /* initialize member, otherwise compiler issues warnings */ upper.c = 0; /* initialize member, otherwise compiler issues warnings */ /* Debug */ ierr = PetscPrintf(comm, "Patch %d: (%d, %d, %d)--(%d, %d, %d)\n", p, lower.i, lower.j, lower.k, upper.i, upper.j, upper.k);CHKERRQ(ierr); if (dmz) {ierr = DMView(dmz, PETSC_VIEWER_STDOUT_(commz));CHKERRQ(ierr);} ierr = PetscSFView(sfz, PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr); ierr = PetscSFView(sfzr, PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr); /* Scatter Xcoarse -> Xzoom */ if (dmz) {ierr = DMGetGlobalVector(dmz, &XZ);CHKERRQ(ierr);} if (XZ) {ierr = VecGetArray(XZ, &xzarray);CHKERRQ(ierr);} ierr = VecGetArray(XC, &xcarray);CHKERRQ(ierr); ierr = PetscSFBcastBegin(sfz, MPIU_SCALAR, xcarray, xzarray);CHKERRQ(ierr); ierr = PetscSFBcastEnd(sfz, MPIU_SCALAR, xcarray, xzarray);CHKERRQ(ierr); ierr = VecRestoreArray(XC, &xcarray);CHKERRQ(ierr); if (XZ) {ierr = VecRestoreArray(XZ, &xzarray);CHKERRQ(ierr);} #if 0 /* Interpolate Xzoom -> Xfine, note that this may be on subcomms */ ierr = DMRefine(dmz, MPI_COMM_NULL, &dmf);CHKERRQ(ierr); ierr = DMCreateInterpolation(dmz, dmf, &interpz, NULL);CHKERRQ(ierr); ierr = DMInterpolate(dmz, interpz, dmf);CHKERRQ(ierr); /* Smooth Xfine using two-step smoother, normal smoother plus Kaczmarz---moves back and forth from dmzoom to dmfine */ /* Compute residual Rfine */ /* Restrict Rfine to Rzoom_restricted */ #endif /* Scatter Rzoom_restricted -> Rcoarse_restricted */ if (XZ) {ierr = VecGetArray(XZ, &xzarray);CHKERRQ(ierr);} ierr = VecGetArray(XC, &xcarray);CHKERRQ(ierr); ierr = PetscSFReduceBegin(sfzr, MPIU_SCALAR, xzarray, xcarray, MPIU_SUM);CHKERRQ(ierr); ierr = PetscSFReduceEnd(sfzr, MPIU_SCALAR, xzarray, xcarray, MPIU_SUM);CHKERRQ(ierr); ierr = VecRestoreArray(XC, &xcarray);CHKERRQ(ierr); if (XZ) {ierr = VecRestoreArray(XZ, &xzarray);CHKERRQ(ierr);} if (dmz) {ierr = DMRestoreGlobalVector(dmz, &XZ);CHKERRQ(ierr);} /* Compute global residual Rcoarse */ /* TauCoarse = Rcoarse - Rcoarse_restricted */ ierr = PetscSFDestroy(&sfz);CHKERRQ(ierr); ierr = PetscSFDestroy(&sfzr);CHKERRQ(ierr); ierr = DMDestroy(&dmz);CHKERRQ(ierr); } } } ierr = DMRestoreGlobalVector(dmc, &XC);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ DMDASetUniformCoordinates - Sets a DMDA coordinates to be a uniform grid Collective on DMDA Input Parameters: + da - the distributed array object . xmin,xmax - extremes in the x direction . ymin,ymax - extremes in the y direction (value ignored for 1 dimensional problems) - zmin,zmax - extremes in the z direction (value ignored for 1 or 2 dimensional problems) Level: beginner .seealso: DMSetCoordinates(), DMGetCoordinates(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d() @*/ PetscErrorCode DMDASetUniformCoordinates(DM da,PetscReal xmin,PetscReal xmax,PetscReal ymin,PetscReal ymax,PetscReal zmin,PetscReal zmax) { MPI_Comm comm; PetscSection section; DM cda; DMBoundaryType bx,by,bz; Vec xcoor; PetscScalar *coors; PetscReal hx,hy,hz_; PetscInt i,j,k,M,N,P,istart,isize,jstart,jsize,kstart,ksize,dim,cnt; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(da,DM_CLASSID,1); ierr = DMDAGetInfo(da,&dim,&M,&N,&P,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); if (xmax < xmin) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_INCOMP,"xmax must be larger than xmin %g %g",(double)xmin,(double)xmax); if ((ymax < ymin) && (dim > 1)) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_INCOMP,"ymax must be larger than ymin %g %g",(double)ymin,(double)ymax); if ((zmax < zmin) && (dim > 2)) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_INCOMP,"zmax must be larger than zmin %g %g",(double)zmin,(double)zmax); ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr); ierr = DMGetDefaultSection(da,§ion);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&istart,&jstart,&kstart,&isize,&jsize,&ksize);CHKERRQ(ierr); ierr = DMGetCoordinateDM(da, &cda);CHKERRQ(ierr); if (section) { /* This would be better as a vector, but this is compatible */ PetscInt numComp[3] = {1, 1, 1}; PetscInt numVertexDof[3] = {1, 1, 1}; ierr = DMDASetFieldName(cda, 0, "x");CHKERRQ(ierr); if (dim > 1) {ierr = DMDASetFieldName(cda, 1, "y");CHKERRQ(ierr);} if (dim > 2) {ierr = DMDASetFieldName(cda, 2, "z");CHKERRQ(ierr);} ierr = DMDACreateSection(cda, numComp, numVertexDof, NULL, NULL);CHKERRQ(ierr); } ierr = DMCreateGlobalVector(cda, &xcoor);CHKERRQ(ierr); if (section) { PetscSection csection; PetscInt vStart, vEnd; ierr = DMGetDefaultGlobalSection(cda,&csection);CHKERRQ(ierr); ierr = VecGetArray(xcoor,&coors);CHKERRQ(ierr); ierr = DMDAGetHeightStratum(da, dim, &vStart, &vEnd);CHKERRQ(ierr); if (bx == DM_BOUNDARY_PERIODIC) hx = (xmax-xmin)/(M+1); else hx = (xmax-xmin)/(M ? M : 1); if (by == DM_BOUNDARY_PERIODIC) hy = (ymax-ymin)/(N+1); else hy = (ymax-ymin)/(N ? N : 1); if (bz == DM_BOUNDARY_PERIODIC) hz_ = (zmax-zmin)/(P+1); else hz_ = (zmax-zmin)/(P ? P : 1); switch (dim) { case 1: for (i = 0; i < isize+1; ++i) { PetscInt v = i+vStart, dof, off; ierr = PetscSectionGetDof(csection, v, &dof);CHKERRQ(ierr); ierr = PetscSectionGetOffset(csection, v, &off);CHKERRQ(ierr); if (off >= 0) { coors[off] = xmin + hx*(i+istart); } } break; case 2: for (j = 0; j < jsize+1; ++j) { for (i = 0; i < isize+1; ++i) { PetscInt v = j*(isize+1)+i+vStart, dof, off; ierr = PetscSectionGetDof(csection, v, &dof);CHKERRQ(ierr); ierr = PetscSectionGetOffset(csection, v, &off);CHKERRQ(ierr); if (off >= 0) { coors[off+0] = xmin + hx*(i+istart); coors[off+1] = ymin + hy*(j+jstart); } } } break; case 3: for (k = 0; k < ksize+1; ++k) { for (j = 0; j < jsize+1; ++j) { for (i = 0; i < isize+1; ++i) { PetscInt v = (k*(jsize+1)+j)*(isize+1)+i+vStart, dof, off; ierr = PetscSectionGetDof(csection, v, &dof);CHKERRQ(ierr); ierr = PetscSectionGetOffset(csection, v, &off);CHKERRQ(ierr); if (off >= 0) { coors[off+0] = xmin + hx*(i+istart); coors[off+1] = ymin + hy*(j+jstart); coors[off+2] = zmin + hz_*(k+kstart); } } } } break; default: SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Cannot create uniform coordinates for this dimension %D\n",dim); } ierr = VecRestoreArray(xcoor,&coors);CHKERRQ(ierr); ierr = DMSetCoordinates(da,xcoor);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)da,(PetscObject)xcoor);CHKERRQ(ierr); ierr = VecDestroy(&xcoor);CHKERRQ(ierr); PetscFunctionReturn(0); } if (dim == 1) { if (bx == DM_BOUNDARY_PERIODIC) hx = (xmax-xmin)/M; else hx = (xmax-xmin)/(M-1); ierr = VecGetArray(xcoor,&coors);CHKERRQ(ierr); for (i=0; i<isize; i++) { coors[i] = xmin + hx*(i+istart); } ierr = VecRestoreArray(xcoor,&coors);CHKERRQ(ierr); } else if (dim == 2) { if (bx == DM_BOUNDARY_PERIODIC) hx = (xmax-xmin)/(M); else hx = (xmax-xmin)/(M-1); if (by == DM_BOUNDARY_PERIODIC) hy = (ymax-ymin)/(N); else hy = (ymax-ymin)/(N-1); ierr = VecGetArray(xcoor,&coors);CHKERRQ(ierr); cnt = 0; for (j=0; j<jsize; j++) { for (i=0; i<isize; i++) { coors[cnt++] = xmin + hx*(i+istart); coors[cnt++] = ymin + hy*(j+jstart); } } ierr = VecRestoreArray(xcoor,&coors);CHKERRQ(ierr); } else if (dim == 3) { if (bx == DM_BOUNDARY_PERIODIC) hx = (xmax-xmin)/(M); else hx = (xmax-xmin)/(M-1); if (by == DM_BOUNDARY_PERIODIC) hy = (ymax-ymin)/(N); else hy = (ymax-ymin)/(N-1); if (bz == DM_BOUNDARY_PERIODIC) hz_ = (zmax-zmin)/(P); else hz_ = (zmax-zmin)/(P-1); ierr = VecGetArray(xcoor,&coors);CHKERRQ(ierr); cnt = 0; for (k=0; k<ksize; k++) { for (j=0; j<jsize; j++) { for (i=0; i<isize; i++) { coors[cnt++] = xmin + hx*(i+istart); coors[cnt++] = ymin + hy*(j+jstart); coors[cnt++] = zmin + hz_*(k+kstart); } } } ierr = VecRestoreArray(xcoor,&coors);CHKERRQ(ierr); } else SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Cannot create uniform coordinates for this dimension %D\n",dim); ierr = DMSetCoordinates(da,xcoor);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)da,(PetscObject)xcoor);CHKERRQ(ierr); ierr = VecDestroy(&xcoor);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* Applies some sweeps on nonlinear Gauss-Seidel on each process */ PetscErrorCode NonlinearGS(SNES snes,Vec X) { PetscInt i,j,Mx,My,xs,ys,xm,ym,its,l; PetscErrorCode ierr; PetscReal hx,hy,hxdhy,hydhx; PetscScalar **x,F,J,u,uxx,uyy; DM da; Vec localX; PetscFunctionBeginUser; ierr = SNESGetTolerances(snes,PETSC_NULL,PETSC_NULL,PETSC_NULL,&its,PETSC_NULL);CHKERRQ(ierr); ierr = SNESShellGetContext(snes,(void**)&da);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); hx = 1.0/(PetscReal)(Mx-1); hy = 1.0/(PetscReal)(My-1); hxdhy = hx/hy; hydhx = hy/hx; ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr); for (l=0; l<its; l++) { ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);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); /* 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,PETSC_NULL,&xm,&ym,PETSC_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 { u = x[j][i]; uxx = (2.0*u - x[j][i-1] - x[j][i+1])*hydhx; uyy = (2.0*u - x[j-1][i] - x[j+1][i])*hxdhy; F = uxx + uyy; J = 2.0*(hydhx + hxdhy); u = u - F/J; 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 = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode InitialConditions(DM da,Vec C) { PetscErrorCode ierr; PetscInt i,I,He,V,xs,xm,Mx,cnt = 0; Concentrations *c; PetscReal hx,x; char string[16]; PetscFunctionBeginUser; ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr); hx = 1.0/(PetscReal)(Mx-1); /* Name each of the concentrations */ for (He=1; He<N+1; He++) { ierr = PetscSNPrintf(string,16,"%d-He",He);CHKERRQ(ierr); ierr = DMDASetFieldName(da,cnt++,string);CHKERRQ(ierr); } for (V=1; V<N+1; V++) { ierr = PetscSNPrintf(string,16,"%d-V",V);CHKERRQ(ierr); ierr = DMDASetFieldName(da,cnt++,string);CHKERRQ(ierr); } for (I=1; I<N+1; I++) { ierr = PetscSNPrintf(string,16,"%d-I",I);CHKERRQ(ierr); ierr = DMDASetFieldName(da,cnt++,string);CHKERRQ(ierr); } for (He=1; He<N+1; He++) { for (V=1; V<N+1; V++) { ierr = PetscSNPrintf(string,16,"%d-He-%d-V",He,V);CHKERRQ(ierr); ierr = DMDASetFieldName(da,cnt++,string);CHKERRQ(ierr); } } /* Get pointer to vector data */ ierr = DMDAVecGetArray(da,C,&c);CHKERRQ(ierr); /* Shift the c pointer to allow accessing with index of 1, instead of 0 */ c = (Concentrations*)(((PetscScalar*)c)-1); /* Get local grid boundaries */ ierr = DMDAGetCorners(da,&xs,PETSC_NULL,PETSC_NULL,&xm,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); /* Compute function over the locally owned part of the grid */ for (i=xs; i<xs+xm; i++) { x = i*hx; for (He=1; He<N+1; He++) { c[i].He[He] = 0.0; } for (V=1; V<N+1; V++) { c[i].V[V] = 1.0; } for (I=1; I<N+1; I++) { c[i].I[I] = 1.0; } for (He=1; He<N+1; He++) { for (V=1; V<N+1; V++) { c[i].HeV[He][V] = 0.0; } } } /* Restore vectors */ c = (Concentrations*)(((PetscScalar*)c)+1); ierr = DMDAVecRestoreArray(da,C,&c);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* IFunction - Evaluates nonlinear function that defines the ODE Input Parameters: . ts - the TS context . U - input vector . ptr - optional user-defined context Output Parameter: . F - function values */ PetscErrorCode IFunction(TS ts,PetscReal ftime,Vec C,Vec Cdot,Vec F,void *ptr) { AppCtx *ctx = (AppCtx*) ptr; DM da; PetscErrorCode ierr; PetscInt xi,Mx,xs,xm,He,he,V,v,I,i; PetscReal hx,sx,x; Concentrations *c,*f; Vec localC; PetscFunctionBeginUser; ierr = TSGetDM(ts,&da);CHKERRQ(ierr); ierr = DMGetLocalVector(da,&localC);CHKERRQ(ierr); ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr); hx = 8.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx); /* F = Cdot + all the diffusion and reaction terms added below */ ierr = VecCopy(Cdot,F);CHKERRQ(ierr); /* Scatter ghost points to local vector,using the 2-step process DMGlobalToLocalBegin(),DMGlobalToLocalEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ ierr = DMGlobalToLocalBegin(da,C,INSERT_VALUES,localC);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,C,INSERT_VALUES,localC);CHKERRQ(ierr); /* Get pointers to vector data */ ierr = DMDAVecGetArray(da,localC,&c);CHKERRQ(ierr); /* Shift the c pointer to allow accessing with index of 1, instead of 0 */ c = (Concentrations*)(((PetscScalar*)c)-1); ierr = DMDAVecGetArray(da,F,&f);CHKERRQ(ierr); f = (Concentrations*)(((PetscScalar*)f)-1); /* Get local grid boundaries */ ierr = DMDAGetCorners(da,&xs,PETSC_NULL,PETSC_NULL,&xm,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); /* Loop over grid points computing ODE terms for each grid point */ for (xi=xs; xi<xs+xm; xi++) { x = xi*hx; /* ------------------------------------------------------------- ---- Compute diffusion over the locally owned part of the grid */ /* He clusters larger than 5 do not diffuse -- are immobile */ for (He=1; He<PetscMin(N+1,6); He++) { f[xi].He[He] -= ctx->HeDiffusion[He]*(-2.0*c[xi].He[He] + c[xi-1].He[He] + c[xi+1].He[He])*sx; } /* V and I clusters ONLY of size 1 diffuse */ f[xi].V[1] -= ctx->VDiffusion[1]*(-2.0*c[xi].V[1] + c[xi-1].V[1] + c[xi+1].V[1])*sx; f[xi].I[1] -= ctx->IDiffusion[1]*(-2.0*c[xi].I[1] + c[xi-1].I[1] + c[xi+1].I[1])*sx; /* Mixed He - V clusters are immobile */ /* ---------------------------------------------------------------- ---- Compute forcing that produces He of cluster size 1 Crude cubic approximation of graph from Tibo's notes */ f[xi].He[1] -= ctx->forcingScale*PetscMax(0.0,0.0006*x*x*x - 0.0087*x*x + 0.0300*x); /* Are V or I produced? */ if (ctx->noreactions) continue; /* ---------------------------------------------------------------- ---- Compute reaction terms that can create a cluster of given size */ /* He[He] + He[he] -> He[He+he] */ for (He=2; He<N+1; He++) { /* compute all pairs of clusters of smaller size that can combine to create a cluster of size He, remove the upper half since they are symmetric to the lower half of the pairs. For example when He = 5 (cluster size 5) the pairs are 1 4 2 2 3 2 these last two are not needed in the sum since they repeat from above 4 1 this is why he < (He/2) + 1 */ for (he=1; he<(He/2)+1; he++) { f[xi].He[He] -= ctx->reactionScale*c[xi].He[he]*c[xi].He[He-he]; /* remove the two clusters that merged to form the larger cluster */ f[xi].He[he] += ctx->reactionScale*c[xi].He[he]*c[xi].He[He-he]; f[xi].He[He-he] += ctx->reactionScale*c[xi].He[he]*c[xi].He[He-he]; } } /* V[V] + V[v] -> V[V+v] */ for (V=2; V<N+1; V++) { for (v=1; v<(V/2)+1; v++) { f[xi].V[V] -= ctx->reactionScale*c[xi].V[v]*c[xi].V[V-v]; /* remove the clusters that merged to form the larger cluster */ f[xi].V[v] += ctx->reactionScale*c[xi].V[v]*c[xi].V[V-v]; f[xi].V[V-v] += ctx->reactionScale*c[xi].V[v]*c[xi].V[V-v]; } } /* I[I] + I[i] -> I[I+i] */ for (I=2; I<N+1; I++) { for (i=1; i<(I/2)+1; i++) { f[xi].I[I] -= ctx->reactionScale*c[xi].I[i]*c[xi].I[I-i]; /* remove the clusters that merged to form the larger cluster */ f[xi].I[i] += ctx->reactionScale*c[xi].I[i]*c[xi].I[I-i]; f[xi].I[I-i] += ctx->reactionScale*c[xi].I[i]*c[xi].I[I-i]; } } /* He[1] + V[1] -> He[1]-V[1] */ f[xi].HeV[1][1] -= 1000*ctx->reactionScale*c[xi].He[1]*c[xi].V[1]; /* remove the He and V that merged to form the He-V cluster */ f[xi].He[1] += 1000*ctx->reactionScale*c[xi].He[1]*c[xi].V[1]; f[xi].V[1] += 1000*ctx->reactionScale*c[xi].He[1]*c[xi].V[1]; /* He[He]-V[V] + He[he] -> He[He+he]-V[V] */ for (He=1; He<N; He++) { for (V=1; V<N+1; V++) { for (he=1; he<N-He+1; he++) { f[xi].HeV[He+he][V] -= ctx->reactionScale*c[xi].HeV[He][V]*c[xi].He[he]; /* remove the two clusters that merged to form the larger cluster */ f[xi].He[he] += ctx->reactionScale*c[xi].HeV[He][V]*c[xi].He[he]; f[xi].HeV[He][V] += ctx->reactionScale*c[xi].HeV[He][V]*c[xi].He[he]; } } } /* He[He]-V[V] + V[v] -> He[He][V+v] */ for (He=1; He<N+1; He++) { for (V=1; V<N; V++) { for (v=1; v<N-V+1; v++) { f[xi].HeV[He][V+v] -= ctx->reactionScale*c[xi].HeV[He][V]*c[xi].V[v]; /* remove the two clusters that merged to form the larger cluster */ f[xi].V[v] += ctx->reactionScale*c[xi].HeV[He][V]*c[xi].V[v]; f[xi].HeV[He][V] += ctx->reactionScale*c[xi].HeV[He][V]*c[xi].V[v]; } } } /* He[He]-V[V] + He[he]-V[v] -> He[He+he][V+v] */ /* Currently the reaction rates for this are zero */ for (He=1; He<N; He++) { for (V=1; V<N; V++) { for (he=1; he<N-He+1; he++) { for (v=1; v<N-V+1; v++) { f[xi].HeV[He+he][V+v] -= 0.0*c[xi].HeV[He][V]*c[xi].HeV[he][v]; /* remove the two clusters that merged to form the larger cluster */ f[xi].HeV[he][V] += 0.0*c[xi].HeV[He][V]*c[xi].HeV[he][v]; f[xi].HeV[He][V] += 0.0*c[xi].HeV[He][V]*c[xi].HeV[he][v]; } } } } /* V[V] + I[I] -> V[V-I] if V > I else I[I-V] */ if (ctx->nodissociations) continue; /* ------------------------------------------------------------------------- ---- Compute dissociation terms that removes an item from a cluster I assume dissociation means losing only a single item from a cluster I cannot tell from the notes if clusters can break up into any sub-size. */ /* He[He] -> He[He-1] + He[1] */ for (He=2; He<N+1; He++) { f[xi].He[He-1] -= ctx->dissociationScale*c[xi].He[He]; f[xi].He[1] -= ctx->dissociationScale*c[xi].He[He]; f[xi].He[He] += ctx->dissociationScale*c[xi].He[He]; } /* V[V] -> V[V-1] + V[1] */ for (V=2; V<N+1; V++) { f[xi].V[V-1] -= ctx->dissociationScale*c[xi].V[V]; f[xi].V[1] -= ctx->dissociationScale*c[xi].V[V]; f[xi].V[V] += ctx->dissociationScale*c[xi].V[V]; } /* I[I] -> I[I-1] + I[1] */ for (I=2; I<N+1; I++) { f[xi].I[I-1] -= ctx->dissociationScale*c[xi].I[I]; f[xi].I[1] -= ctx->dissociationScale*c[xi].I[I]; f[xi].I[I] += ctx->dissociationScale*c[xi].I[I]; } /* He[1]-V[1] -> He[1] + V[1] */ f[xi].He[1] -= 1000*ctx->reactionScale*c[xi].HeV[1][1]; f[xi].V[1] -= 1000*ctx->reactionScale*c[xi].HeV[1][1]; f[xi].HeV[1][1] += 1000*ctx->reactionScale*c[xi].HeV[1][1]; /* He[He]-V[1] -> He[He] + V[1] */ for (He=2; He<N+1; He++) { f[xi].He[He] -= 1000*ctx->reactionScale*c[xi].HeV[He][1]; f[xi].V[1] -= 1000*ctx->reactionScale*c[xi].HeV[He][1]; f[xi].HeV[He][1] += 1000*ctx->reactionScale*c[xi].HeV[He][1]; } /* He[1]-V[V] -> He[1] + V[V] */ for (V=2; V<N+1; V++) { f[xi].He[1] -= 1000*ctx->reactionScale*c[xi].HeV[1][V]; f[xi].V[V] -= 1000*ctx->reactionScale*c[xi].HeV[1][V]; f[xi].HeV[1][V ] += 1000*ctx->reactionScale*c[xi].HeV[1][V]; } /* He[He]-V[V] -> He[He-1]-V[V] + He[1] */ for (He=2; He<N+1; He++) { for (V=2; V<N+1; V++) { f[xi].He[1] -= 1000*ctx->reactionScale*c[xi].HeV[He][V]; f[xi].HeV[He-1][V] -= 1000*ctx->reactionScale*c[xi].HeV[He][V]; f[xi].HeV[He][V] += 1000*ctx->reactionScale*c[xi].HeV[He][V]; } } /* He[He]-V[V] -> He[He]-V[V-1] + V[1] */ for (He=2; He<N+1; He++) { for (V=2; V<N+1; V++) { f[xi].V[1] -= 1000*ctx->reactionScale*c[xi].HeV[He][V]; f[xi].HeV[He][V-1] -= 1000*ctx->reactionScale*c[xi].HeV[He][V]; f[xi].HeV[He][V] += 1000*ctx->reactionScale*c[xi].HeV[He][V]; } } /* He[He]-V[V] -> He[He]-V[V+1] + I[1] */ } /* Restore vectors */ c = (Concentrations*)(((PetscScalar*)c)+1); ierr = DMDAVecRestoreArray(da,localC,&c);CHKERRQ(ierr); f = (Concentrations*)(((PetscScalar*)f)+1); ierr = DMDAVecRestoreArray(da,F,&f);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localC);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode FormIFunction(TS ts,PetscReal ftime,Vec U,Vec Udot,Vec F,void *ptr) { AppCtx *user=(AppCtx*)ptr; DM da; PetscErrorCode ierr; PetscInt i,Mx,xs,xm; PetscReal hx,sx; PetscScalar *u,*udot,*f; Vec localU; PetscFunctionBegin; ierr = TSGetDM(ts,&da);CHKERRQ(ierr); ierr = DMGetLocalVector(da,&localU);CHKERRQ(ierr); ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE, PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE); hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx); /* Scatter ghost points to local vector,using the 2-step process DMGlobalToLocalBegin(),DMGlobalToLocalEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ ierr = DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU);CHKERRQ(ierr); /* Get pointers to vector data */ ierr = DMDAVecGetArray(da,localU,&u);CHKERRQ(ierr); ierr = DMDAVecGetArray(da,Udot,&udot);CHKERRQ(ierr); ierr = DMDAVecGetArray(da,F,&f);CHKERRQ(ierr); /* Get local grid boundaries */ ierr = DMDAGetCorners(da,&xs,PETSC_NULL,PETSC_NULL,&xm,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); /* Compute function over the locally owned part of the grid */ for (i=xs; i<xs+xm; i++) { if (user->boundary == 0) { /* Dirichlet BC */ if (i == 0 || i == Mx-1) { f[i] = u[i]; /* F = U */ } else { f[i] = udot[i] + (2.*u[i] - u[i-1] - u[i+1])*sx; } } else { /* Neumann BC */ if (i == 0) { f[i] = u[0] - u[1]; } else if (i == Mx-1) { f[i] = u[i] - u[i-1]; } else { f[i] = udot[i] + (2.*u[i] - u[i-1] - u[i+1])*sx; } } } /* Restore vectors */ ierr = DMDAVecRestoreArray(da,localU,&u);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da,Udot,&udot);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da,F,&f);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localU);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode ComputeMatrix(DM da,Mat B) { PetscErrorCode ierr; PetscInt i,j,k,mx,my,mz,xm,ym,zm,xs,ys,zs,dof,k1,k2,k3; PetscScalar *v,*v_neighbor,Hx,Hy,Hz,HxHydHz,HyHzdHx,HxHzdHy; MatStencil row,col; PetscFunctionBegin; ierr = DMDAGetInfo(da,0,&mx,&my,&mz,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr); /* For simplicity, this example only works on mx=my=mz */ if ( mx != my || mx != mz) SETERRQ3(PETSC_COMM_SELF,1,"This example only works with mx %d = my %d = mz %d\n",mx,my,mz); Hx = 1.0 / (PetscReal)(mx-1); Hy = 1.0 / (PetscReal)(my-1); Hz = 1.0 / (PetscReal)(mz-1); HxHydHz = Hx*Hy/Hz; HxHzdHy = Hx*Hz/Hy; HyHzdHx = Hy*Hz/Hx; ierr = PetscMalloc((2*dof*dof+1)*sizeof(PetscScalar),&v);CHKERRQ(ierr); v_neighbor = v + dof*dof; ierr = PetscMemzero(v,(2*dof*dof+1)*sizeof(PetscScalar));CHKERRQ(ierr); k3 = 0; for (k1=0; k1<dof; k1++){ for (k2=0; k2<dof; k2++){ if (k1 == k2){ v[k3] = 2.0*(HxHydHz + HxHzdHy + HyHzdHx); v_neighbor[k3] = -HxHydHz; } else { v[k3] = k1/(dof*dof); ; v_neighbor[k3] = k2/(dof*dof); } k3++; } } ierr = DMDAGetCorners(da,&xs,&ys,&zs,&xm,&ym,&zm);CHKERRQ(ierr); for (k=zs; k<zs+zm; k++){ for (j=ys; j<ys+ym; j++){ for(i=xs; i<xs+xm; i++){ row.i = i; row.j = j; row.k = k; if (i==0 || j==0 || k==0 || i==mx-1 || j==my-1 || k==mz-1){ /* boudary points */ ierr = MatSetValuesBlockedStencil(B,1,&row,1,&row,v,INSERT_VALUES);CHKERRQ(ierr); } else { /* interior points */ /* center */ col.i = i; col.j = j; col.k = k; ierr = MatSetValuesBlockedStencil(B,1,&row,1,&col,v,INSERT_VALUES);CHKERRQ(ierr); /* x neighbors */ col.i = i-1; col.j = j; col.k = k; ierr = MatSetValuesBlockedStencil(B,1,&row,1,&col,v_neighbor,INSERT_VALUES);CHKERRQ(ierr); col.i = i+1; col.j = j; col.k = k; ierr = MatSetValuesBlockedStencil(B,1,&row,1,&col,v_neighbor,INSERT_VALUES);CHKERRQ(ierr); /* y neighbors */ col.i = i; col.j = j-1; col.k = k; ierr = MatSetValuesBlockedStencil(B,1,&row,1,&col,v_neighbor,INSERT_VALUES);CHKERRQ(ierr); col.i = i; col.j = j+1; col.k = k; ierr = MatSetValuesBlockedStencil(B,1,&row,1,&col,v_neighbor,INSERT_VALUES);CHKERRQ(ierr); /* z neighbors */ col.i = i; col.j = j; col.k = k-1; ierr = MatSetValuesBlockedStencil(B,1,&row,1,&col,v_neighbor,INSERT_VALUES);CHKERRQ(ierr); col.i = i; col.j = j; col.k = k+1; ierr = MatSetValuesBlockedStencil(B,1,&row,1,&col,v_neighbor,INSERT_VALUES);CHKERRQ(ierr); } } } } ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = PetscFree(v);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* FormBoundaryConditions - Calculates the boundary conditions for the region. Input Parameter: . user - user-defined application context Output Parameter: . user - user-defined application context */ PetscErrorCode FormBoundaryConditions(SNES snes,AppCtx **ouser) { PetscErrorCode ierr; PetscInt i,j,k,limit=0,maxits=5; PetscInt mx,my; PetscInt bsize=0, lsize=0, tsize=0, rsize=0; PetscScalar one=1.0, two=2.0, three=3.0; PetscScalar det,hx,hy,xt=0,yt=0; PetscReal fnorm, tol=1e-10; PetscScalar u1,u2,nf1,nf2,njac11,njac12,njac21,njac22; PetscScalar b=-0.5, t=0.5, l=-0.5, r=0.5; PetscScalar *boundary; AppCtx *user; DM da; PetscFunctionBeginUser; ierr = SNESGetDM(snes,&da);CHKERRQ(ierr); ierr = PetscNew(AppCtx,&user);CHKERRQ(ierr); *ouser = user; user->lb = .05; user->ub = SNES_VI_INF; 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); /* Check if lower and upper bounds are set */ ierr = PetscOptionsGetScalar(PETSC_NULL, "-lb", &user->lb, 0);CHKERRQ(ierr); ierr = PetscOptionsGetScalar(PETSC_NULL, "-ub", &user->ub, 0);CHKERRQ(ierr); bsize=mx+2; lsize=my+2; rsize=my+2; tsize=mx+2; ierr = PetscMalloc(bsize*sizeof(PetscScalar), &user->bottom);CHKERRQ(ierr); ierr = PetscMalloc(tsize*sizeof(PetscScalar), &user->top);CHKERRQ(ierr); ierr = PetscMalloc(lsize*sizeof(PetscScalar), &user->left);CHKERRQ(ierr); ierr = PetscMalloc(rsize*sizeof(PetscScalar), &user->right);CHKERRQ(ierr); hx= (r-l)/(mx+1.0); hy=(t-b)/(my+1.0); for (j=0; j<4; j++){ if (j==0){ yt=b; xt=l; limit=bsize; boundary=user->bottom; } else if (j==1){ yt=t; xt=l; limit=tsize; boundary=user->top; } else if (j==2){ yt=b; xt=l; limit=lsize; boundary=user->left; } else { // if (j==3) yt=b; xt=r; limit=rsize; boundary=user->right; } for (i=0; i<limit; i++){ u1=xt; u2=-yt; for (k=0; k<maxits; k++){ nf1=u1 + u1*u2*u2 - u1*u1*u1/three-xt; nf2=-u2 - u1*u1*u2 + u2*u2*u2/three-yt; fnorm=PetscRealPart(sqrt(nf1*nf1+nf2*nf2)); if (fnorm <= tol) break; njac11=one+u2*u2-u1*u1; njac12=two*u1*u2; njac21=-two*u1*u2; njac22=-one - u1*u1 + u2*u2; det = njac11*njac22-njac21*njac12; u1 = u1-(njac22*nf1-njac12*nf2)/det; u2 = u2-(njac11*nf2-njac21*nf1)/det; } boundary[i]=u1*u1-u2*u2; if (j==0 || j==1) { xt=xt+hx; } else { // if (j==2 || j==3) yt=yt+hy; } } } PetscFunctionReturn(0); }
/* FormJacobian - Evaluates Jacobian matrix. Input Parameters: . snes - SNES context . X - input vector . ptr - optional user-defined context, as set by SNESSetJacobian() Output Parameters: . tH - Jacobian matrix */ PetscErrorCode FormJacobian(SNES snes, Vec X, Mat *tH, Mat* tHPre, MatStructure* flag, void *ptr) { AppCtx *user; Mat H = *tH; PetscErrorCode ierr; PetscInt i,j,k; PetscInt mx, my; MatStencil row,col[7]; PetscScalar hx=1.0/(mx+1), hy=1.0/(my+1), hydhx=hy/hx, hxdhy=hx/hy; PetscScalar f1,f2,f3,f4,f5,f6,d1,d2,d3,d4,d5,d6,d7,d8,xc,xl,xr,xt,xb,xlt,xrb; PetscScalar hl,hr,ht,hb,hc,htl,hbr; PetscScalar **x, v[7]; PetscBool assembled; PetscInt xs,xm,ys,ym; Vec localX; DM da; PetscFunctionBeginUser; ierr = SNESGetDM(snes,&da);CHKERRQ(ierr); ierr = SNESGetApplicationContext(snes,(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); hx=1.0/(mx+1); hy=1.0/(my+1); hydhx=hy/hx; hxdhy=hx/hy; /* Set various matrix options */ ierr = MatAssembled(H,&assembled);CHKERRQ(ierr); if (assembled){ierr = MatZeroEntries(H);CHKERRQ(ierr);} *flag=SAME_NONZERO_PATTERN; /* Get local vector */ ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr); /* Get ghost points */ ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); /* Get pointers to vector data */ ierr = DMDAVecGetArray(da,localX, &x);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL);CHKERRQ(ierr); /* Compute Jacobian over the locally owned part of the mesh */ for (j=ys; j< ys+ym; j++){ for (i=xs; i< xs+xm; i++){ xc = x[j][i]; xlt=xrb=xl=xr=xb=xt=xc; /* Left */ if (i==0){ xl= user->left[j+1]; xlt = user->left[j+2]; } else { xl = x[j][i-1]; } /* Bottom */ if (j==0){ xb=user->bottom[i+1]; xrb = user->bottom[i+2]; } else { xb = x[j-1][i]; } /* Right */ if (i+1 == mx){ xr=user->right[j+1]; xrb = user->right[j]; } else { xr = x[j][i+1]; } /* Top */ if (j+1==my){ xt=user->top[i+1]; xlt = user->top[i]; }else { xt = x[j+1][i]; } /* Top left */ if (i>0 && j+1<my){ xlt = x[j+1][i-1]; } /* Bottom right */ if (j>0 && i+1<mx){ xrb = x[j-1][i+1]; } d1 = (xc-xl)/hx; d2 = (xc-xr)/hx; d3 = (xc-xt)/hy; d4 = (xc-xb)/hy; d5 = (xrb-xr)/hy; d6 = (xrb-xb)/hx; d7 = (xlt-xl)/hy; d8 = (xlt-xt)/hx; f1 = sqrt( 1.0 + d1*d1 + d7*d7); f2 = sqrt( 1.0 + d1*d1 + d4*d4); f3 = sqrt( 1.0 + d3*d3 + d8*d8); f4 = sqrt( 1.0 + d3*d3 + d2*d2); f5 = sqrt( 1.0 + d2*d2 + d5*d5); f6 = sqrt( 1.0 + d4*d4 + d6*d6); hl = (-hydhx*(1.0+d7*d7)+d1*d7)/(f1*f1*f1)+ (-hydhx*(1.0+d4*d4)+d1*d4)/(f2*f2*f2); hr = (-hydhx*(1.0+d5*d5)+d2*d5)/(f5*f5*f5)+ (-hydhx*(1.0+d3*d3)+d2*d3)/(f4*f4*f4); ht = (-hxdhy*(1.0+d8*d8)+d3*d8)/(f3*f3*f3)+ (-hxdhy*(1.0+d2*d2)+d2*d3)/(f4*f4*f4); hb = (-hxdhy*(1.0+d6*d6)+d4*d6)/(f6*f6*f6)+ (-hxdhy*(1.0+d1*d1)+d1*d4)/(f2*f2*f2); hbr = -d2*d5/(f5*f5*f5) - d4*d6/(f6*f6*f6); htl = -d1*d7/(f1*f1*f1) - d3*d8/(f3*f3*f3); hc = hydhx*(1.0+d7*d7)/(f1*f1*f1) + hxdhy*(1.0+d8*d8)/(f3*f3*f3) + hydhx*(1.0+d5*d5)/(f5*f5*f5) + hxdhy*(1.0+d6*d6)/(f6*f6*f6) + (hxdhy*(1.0+d1*d1)+hydhx*(1.0+d4*d4)-2.0*d1*d4)/(f2*f2*f2) + (hxdhy*(1.0+d2*d2)+hydhx*(1.0+d3*d3)-2.0*d2*d3)/(f4*f4*f4); hl/=2.0; hr/=2.0; ht/=2.0; hb/=2.0; hbr/=2.0; htl/=2.0; hc/=2.0; k=0; row.i = i;row.j= j; /* Bottom */ if (j>0){ v[k]=hb; col[k].i = i; col[k].j=j-1; k++; } /* Bottom right */ if (j>0 && i < mx -1){ v[k]=hbr; col[k].i = i+1; col[k].j = j-1; k++; } /* left */ if (i>0){ v[k]= hl; col[k].i = i-1; col[k].j = j; k++; } /* Centre */ v[k]= hc; col[k].i= row.i; col[k].j = row.j; k++; /* Right */ if (i < mx-1 ){ v[k]= hr; col[k].i= i+1; col[k].j = j;k++; } /* Top left */ if (i>0 && j < my-1 ){ v[k]= htl; col[k].i = i-1;col[k].j = j+1; k++; } /* Top */ if (j < my-1 ){ v[k]= ht; col[k].i = i; col[k].j = j+1; k++; } ierr = MatSetValuesStencil(H,1,&row,k,col,v,INSERT_VALUES);CHKERRQ(ierr); } } /* Assemble the matrix */ ierr = MatAssemblyBegin(H,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da,localX,&x);CHKERRQ(ierr); ierr = MatAssemblyEnd(H,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr); ierr = PetscLogFlops(199*mx*my);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* FormGradient - Evaluates gradient of f. Input Parameters: . snes - the SNES context . X - input vector . ptr - optional user-defined context, as set by SNESSetFunction() Output Parameters: . G - vector containing the newly evaluated gradient */ PetscErrorCode FormGradient(SNES snes, Vec X, Vec G, void *ptr) { AppCtx *user; int ierr; PetscInt i,j; PetscInt mx, my; PetscScalar hx,hy, hydhx, hxdhy; PetscScalar f1,f2,f3,f4,f5,f6,d1,d2,d3,d4,d5,d6,d7,d8,xc,xl,xr,xt,xb,xlt,xrb; PetscScalar df1dxc,df2dxc,df3dxc,df4dxc,df5dxc,df6dxc; PetscScalar **g, **x; PetscInt xs,xm,ys,ym; Vec localX; DM da; PetscFunctionBeginUser; ierr = SNESGetDM(snes,&da);CHKERRQ(ierr); ierr = SNESGetApplicationContext(snes,(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); hx=1.0/(mx+1);hy=1.0/(my+1); hydhx=hy/hx; hxdhy=hx/hy; ierr = VecSet(G,0.0);CHKERRQ(ierr); /* Get local vector */ ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr); /* Get ghost points */ ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); /* Get pointer to local vector data */ ierr = DMDAVecGetArray(da,localX, &x);CHKERRQ(ierr); ierr = DMDAVecGetArray(da,G, &g);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL);CHKERRQ(ierr); /* Compute function over the locally owned part of the mesh */ for (j=ys; j < ys+ym; j++){ for (i=xs; i< xs+xm; i++){ xc = x[j][i]; xlt=xrb=xl=xr=xb=xt=xc; if (i==0){ /* left side */ xl= user->left[j+1]; xlt = user->left[j+2]; } else { xl = x[j][i-1]; } if (j==0){ /* bottom side */ xb=user->bottom[i+1]; xrb = user->bottom[i+2]; } else { xb = x[j-1][i]; } if (i+1 == mx){ /* right side */ xr=user->right[j+1]; xrb = user->right[j]; } else { xr = x[j][i+1]; } if (j+1==0+my){ /* top side */ xt=user->top[i+1]; xlt = user->top[i]; }else { xt = x[j+1][i]; } if (i>0 && j+1<my){ /* left top side */ xlt = x[j+1][i-1]; } if (j>0 && i+1<mx){ /* right bottom */ xrb = x[j-1][i+1]; } d1 = (xc-xl); d2 = (xc-xr); d3 = (xc-xt); d4 = (xc-xb); d5 = (xr-xrb); d6 = (xrb-xb); d7 = (xlt-xl); d8 = (xt-xlt); df1dxc = d1*hydhx; df2dxc = ( d1*hydhx + d4*hxdhy ); df3dxc = d3*hxdhy; df4dxc = ( d2*hydhx + d3*hxdhy ); df5dxc = d2*hydhx; df6dxc = d4*hxdhy; d1 /= hx; d2 /= hx; d3 /= hy; d4 /= hy; d5 /= hy; d6 /= hx; d7 /= hy; d8 /= hx; f1 = sqrt( 1.0 + d1*d1 + d7*d7); f2 = sqrt( 1.0 + d1*d1 + d4*d4); f3 = sqrt( 1.0 + d3*d3 + d8*d8); f4 = sqrt( 1.0 + d3*d3 + d2*d2); f5 = sqrt( 1.0 + d2*d2 + d5*d5); f6 = sqrt( 1.0 + d4*d4 + d6*d6); df1dxc /= f1; df2dxc /= f2; df3dxc /= f3; df4dxc /= f4; df5dxc /= f5; df6dxc /= f6; g[j][i] = (df1dxc+df2dxc+df3dxc+df4dxc+df5dxc+df6dxc )/2.0; } } /* Restore vectors */ ierr = DMDAVecRestoreArray(da,localX, &x);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da,G, &g);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr); ierr = PetscLogFlops(67*mx*my);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode UpdateMatrices(AppCtx *user) { PetscErrorCode ierr; PetscInt i,j,n,Mda,Nda; PetscInt idx[3],*nodes,*connect,k; PetscInt ld,rd,lu,ru; PetscScalar eM_2_odd[3][3],eM_2_even[3][3],h,dt=user->dt; Mat M=user->M; PetscScalar *cv_p,*ci_p,cv_sum,ci_sum; PetscFunctionBeginUser; /* Create the mass matrix M_0 */ ierr = MatGetLocalSize(M,&n,NULL);CHKERRQ(ierr); ierr = VecGetArray(user->cv,&cv_p);CHKERRQ(ierr); ierr = VecGetArray(user->ci,&ci_p);CHKERRQ(ierr); ierr = DMDAGetInfo(user->da1,NULL,&Mda,&Nda,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); ierr = PetscMalloc((Mda+1)*(Nda+1)*sizeof(PetscInt),&nodes);CHKERRQ(ierr); ierr = PetscMalloc(Mda*Nda*2*3*sizeof(PetscInt),&connect);CHKERRQ(ierr); h = 100.0/Mda; for (j=0; j < Nda; j++) { for (i=0; i < Mda; i++) nodes[j*(Mda+1)+i] = j*Mda+i; nodes[j*(Mda+1)+Mda] = j*Mda; } for (i=0; i < Mda; i++) nodes[Nda*(Mda+1)+i]=i; nodes[Nda*(Mda+1)+Mda]=0; k = 0; for (j=0; j<Nda; j++) { for (i=0; i<Mda; i++) { ld = nodes[j*(Mda+1)+i]; rd = nodes[(j+1)*(Mda+1)+i]; ru = nodes[(j+1)*(Mda+1)+i+1]; lu = nodes[j*(Mda+1)+i+1]; connect[k*6] = ld; connect[k*6+1] = lu; connect[k*6+2] = rd; connect[k*6+3] = lu; connect[k*6+4] = ru; connect[k*6+5] = rd; k = k+1; } } for (k=0; k < Mda*Nda*2; k++) { idx[0] = connect[k*3]; idx[1] = connect[k*3+1]; idx[2] = connect[k*3+2]; PetscInt r,row,cols[3]; PetscScalar vals[3]; for (r=0; r<3; r++) { row = 5*idx[r]; cols[0] = 5*idx[0]; vals[0] = 0.0; cols[1] = 5*idx[1]; vals[1] = 0.0; cols[2] = 5*idx[2]; vals[2] = 0.0; /* Insert values in matrix M for 1st dof */ ierr = MatSetValuesLocal(M,1,&row,3,cols,vals,INSERT_VALUES);CHKERRQ(ierr); row = 5*idx[r]+2; cols[0] = 5*idx[0]+2; vals[0] = 0.0; cols[1] = 5*idx[1]+2; vals[1] = 0.0; cols[2] = 5*idx[2]+2; vals[2] = 0.0; /* Insert values in matrix M for 3nd dof */ ierr = MatSetValuesLocal(M,1,&row,3,cols,vals,INSERT_VALUES);CHKERRQ(ierr); } } ierr = MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); eM_2_odd[0][0] = 1.0; eM_2_odd[1][1] = eM_2_odd[2][2] = 0.5; eM_2_odd[0][1] = eM_2_odd[0][2] = eM_2_odd[1][0]= eM_2_odd[2][0] = -0.5; eM_2_odd[1][2] = eM_2_odd[2][1] = 0.0; eM_2_even[1][1] = 1.0; eM_2_even[0][0] = eM_2_even[2][2] = 0.5; eM_2_even[0][1] = eM_2_even[1][0] = eM_2_even[1][2] = eM_2_even[2][1] = -0.5; eM_2_even[0][2] = eM_2_even[2][0] = 0.0; /* Get local element info */ for (k=0; k < Mda*Nda*2; k++) { idx[0] = connect[k*3]; idx[1] = connect[k*3+1]; idx[2] = connect[k*3+2]; PetscInt row,cols[3],r; PetscScalar vals[3]; for (r=0; r<3; r++) { /* cv_sum = (1.0e-3+cv_p[idx[0]] + cv_p[idx[1]] + cv_p[idx[2]])*user->Dv/(3.0*user->kBT); */ /* ci_sum = (1.0e-3+ci_p[idx[0]] + ci_p[idx[1]] + ci_p[idx[2]])*user->Di/(3.0*user->kBT); */ cv_sum = .0000069*user->Dv/(user->kBT); ci_sum = .0000069*user->Di/user->kBT; if (k%2 == 0) { /* odd triangle */ row = 5*idx[r]; cols[0] = 5*idx[0]; vals[0] = dt*eM_2_odd[r][0]*cv_sum; cols[1] = 5*idx[1]; vals[1] = dt*eM_2_odd[r][1]*cv_sum; cols[2] = 5*idx[2]; vals[2] = dt*eM_2_odd[r][2]*cv_sum; /* Insert values in matrix M for 1st dof */ ierr = MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 5*idx[r]+2; cols[0] = 5*idx[0]+2; vals[0] = dt*eM_2_odd[r][0]*ci_sum; cols[1] = 5*idx[1]+2; vals[1] = dt*eM_2_odd[r][1]*ci_sum; cols[2] = 5*idx[2]+2; vals[2] = dt*eM_2_odd[r][2]*ci_sum; ierr = MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);CHKERRQ(ierr); } else { row = 5*idx[r]; cols[0] = 5*idx[0]; vals[0] = dt*eM_2_even[r][0]*cv_sum; cols[1] = 5*idx[1]; vals[1] = dt*eM_2_even[r][1]*cv_sum; cols[2] = 5*idx[2]; vals[2] = dt*eM_2_even[r][2]*cv_sum; /* Insert values in matrix M for 1st dof */ ierr = MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 5*idx[r]+2; cols[0] = 5*idx[0]+2; vals[0] = dt*eM_2_even[r][0]*ci_sum; cols[1] = 5*idx[1]+2; vals[1] = dt*eM_2_even[r][1]*ci_sum; cols[2] = 5*idx[2]+2; vals[2] = dt*eM_2_even[r][2]*ci_sum; /* Insert values in matrix M for 3nd dof */ ierr = MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);CHKERRQ(ierr); } } } ierr = PetscFree(nodes);CHKERRQ(ierr); ierr = PetscFree(connect);CHKERRQ(ierr); ierr = MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecRestoreArray(user->cv,&cv_p);CHKERRQ(ierr); ierr = VecRestoreArray(user->ci,&ci_p);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc, char **argv) { PetscErrorCode info; /* used to check for functions returning nonzeros */ Vec x; /* variables vector */ Vec xl,xu; /* lower and upper bound on variables */ PetscBool flg; /* A return variable when checking for user options */ SNESConvergedReason reason; AppCtx user; /* user-defined work context */ SNES snes; Vec r; PetscReal zero=0.0,thnd=1000; /* Initialize PETSC */ PetscInitialize(&argc, &argv,(char*)0,help); #if defined(PETSC_USE_COMPLEX) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"This example does not work for scalar type complex\n"); #endif /* Set the default values for the problem parameters */ user.nx = 50; user.ny = 50; user.ecc = 0.1; user.b = 10.0; /* Check for any command line arguments that override defaults */ info = PetscOptionsGetReal(NULL,"-ecc",&user.ecc,&flg);CHKERRQ(info); info = PetscOptionsGetReal(NULL,"-b",&user.b,&flg);CHKERRQ(info); /* A two dimensional distributed array will help define this problem, which derives from an elliptic PDE on two dimensional domain. From the distributed array, Create the vectors. */ info = DMDACreate2d(PETSC_COMM_WORLD, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE,DMDA_STENCIL_STAR,-50,-50,PETSC_DECIDE,PETSC_DECIDE,1,1,NULL,NULL,&user.da);CHKERRQ(info); info = DMDAGetInfo(user.da,PETSC_IGNORE,&user.nx,&user.ny,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(info); PetscPrintf(PETSC_COMM_WORLD,"\n---- Journal Bearing Problem -----\n"); PetscPrintf(PETSC_COMM_WORLD,"mx: %d, my: %d, ecc: %4.3f, b:%3.1f \n", user.nx,user.ny,user.ecc,user.b); /* Extract global and local vectors from DA; the vector user.B is used solely as work space for the evaluation of the function, gradient, and Hessian. Duplicate for remaining vectors that are the same types. */ info = DMCreateGlobalVector(user.da,&x);CHKERRQ(info); /* Solution */ info = VecDuplicate(x,&user.B);CHKERRQ(info); /* Linear objective */ info = VecDuplicate(x,&r);CHKERRQ(info); /* Create matrix user.A to store quadratic, Create a local ordering scheme. */ info = DMCreateMatrix(user.da,MATAIJ,&user.A);CHKERRQ(info); /* User defined function -- compute linear term of quadratic */ info = ComputeB(&user);CHKERRQ(info); /* Create nonlinear solver context */ info = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(info); /* Set function evaluation and Jacobian evaluation routines */ info = SNESSetFunction(snes,r,FormGradient,&user);CHKERRQ(info); info = SNESSetJacobian(snes,user.A,user.A,FormHessian,&user);CHKERRQ(info); /* Set the initial solution guess */ info = VecSet(x, zero);CHKERRQ(info); info = SNESSetFromOptions(snes);CHKERRQ(info); /* Set variable bounds */ info = VecDuplicate(x,&xl);CHKERRQ(info); info = VecDuplicate(x,&xu);CHKERRQ(info); info = VecSet(xl,zero);CHKERRQ(info); info = VecSet(xu,thnd);CHKERRQ(info); info = SNESVISetVariableBounds(snes,xl,xu);CHKERRQ(info); /* Solve the application */ info = SNESSolve(snes,NULL,x);CHKERRQ(info); info = SNESGetConvergedReason(snes,&reason);CHKERRQ(info); if (reason <= 0) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"The SNESVI solver did not converge, adjust some parameters, or check the function evaluation routines\n"); /* Free memory */ info = VecDestroy(&x);CHKERRQ(info); info = VecDestroy(&xl);CHKERRQ(info); info = VecDestroy(&xu);CHKERRQ(info); info = VecDestroy(&r);CHKERRQ(info); info = MatDestroy(&user.A);CHKERRQ(info); info = VecDestroy(&user.B);CHKERRQ(info); info = DMDestroy(&user.da);CHKERRQ(info); info = SNESDestroy(&snes);CHKERRQ(info); info = PetscFinalize(); return 0; }
PetscErrorCode VecView_MPI_Draw_DA1d(Vec xin,PetscViewer v) { DM da; PetscErrorCode ierr; PetscMPIInt rank,size,tag1,tag2; PetscInt i,n,N,step,istart,isize,j,nbounds; MPI_Status status; PetscReal coors[4],ymin,ymax,min,max,xmin = 0.0,xmax = 0.0,tmp = 0.0,xgtmp = 0.0; const PetscScalar *array,*xg; PetscDraw draw; PetscBool isnull,showmarkers = PETSC_FALSE; MPI_Comm comm; PetscDrawAxis axis; Vec xcoor; DMBoundaryType bx; const PetscReal *bounds; PetscInt *displayfields; PetscInt k,ndisplayfields; PetscBool hold; PetscFunctionBegin; ierr = PetscViewerDrawGetDraw(v,0,&draw);CHKERRQ(ierr); ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); ierr = PetscViewerDrawGetBounds(v,&nbounds,&bounds);CHKERRQ(ierr); ierr = VecGetDM(xin,&da);CHKERRQ(ierr); if (!da) SETERRQ(PetscObjectComm((PetscObject)xin),PETSC_ERR_ARG_WRONG,"Vector not generated from a DMDA"); ierr = PetscOptionsGetBool(NULL,NULL,"-draw_vec_use_markers",&showmarkers,NULL);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&N,0,0,0,0,0,&step,0,&bx,0,0,0);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&istart,0,0,&isize,0,0);CHKERRQ(ierr); ierr = VecGetArrayRead(xin,&array);CHKERRQ(ierr); ierr = VecGetLocalSize(xin,&n);CHKERRQ(ierr); n = n/step; /* get coordinates of nodes */ ierr = DMGetCoordinates(da,&xcoor);CHKERRQ(ierr); if (!xcoor) { ierr = DMDASetUniformCoordinates(da,0.0,1.0,0.0,0.0,0.0,0.0);CHKERRQ(ierr); ierr = DMGetCoordinates(da,&xcoor);CHKERRQ(ierr); } ierr = VecGetArrayRead(xcoor,&xg);CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)xin,&comm);CHKERRQ(ierr); ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); /* Determine the min and max x coordinate in plot */ if (!rank) { xmin = PetscRealPart(xg[0]); } if (rank == size-1) { xmax = PetscRealPart(xg[n-1]); } ierr = MPI_Bcast(&xmin,1,MPIU_REAL,0,comm);CHKERRQ(ierr); ierr = MPI_Bcast(&xmax,1,MPIU_REAL,size-1,comm);CHKERRQ(ierr); ierr = DMDASelectFields(da,&ndisplayfields,&displayfields);CHKERRQ(ierr); #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X) if (!setjmp(PetscXIOErrorJumpBuf)) XSetIOErrorHandler((XIOErrorHandler)PetscXIOHandler); else { XSetIOErrorHandler(NULL); ierr = PetscDrawSetType(draw,PETSC_DRAW_NULL);CHKERRQ(ierr); PetscFunctionReturn(0); } #endif for (k=0; k<ndisplayfields; k++) { j = displayfields[k]; ierr = PetscViewerDrawGetDraw(v,k,&draw);CHKERRQ(ierr); ierr = PetscDrawCheckResizedWindow(draw);CHKERRQ(ierr); /* Determine the min and max y coordinate in plot */ min = 1.e20; max = -1.e20; for (i=0; i<n; i++) { if (PetscRealPart(array[j+i*step]) < min) min = PetscRealPart(array[j+i*step]); if (PetscRealPart(array[j+i*step]) > max) max = PetscRealPart(array[j+i*step]); } if (min + 1.e-10 > max) { min -= 1.e-5; max += 1.e-5; } if (j < nbounds) { min = PetscMin(min,bounds[2*j]); max = PetscMax(max,bounds[2*j+1]); } ierr = MPI_Reduce(&min,&ymin,1,MPIU_REAL,MPIU_MIN,0,comm);CHKERRQ(ierr); ierr = MPI_Reduce(&max,&ymax,1,MPIU_REAL,MPIU_MAX,0,comm);CHKERRQ(ierr); ierr = PetscViewerDrawGetHold(v,&hold);CHKERRQ(ierr); if (!hold) { ierr = PetscDrawSynchronizedClear(draw);CHKERRQ(ierr); } ierr = PetscViewerDrawGetDrawAxis(v,k,&axis);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)draw,(PetscObject)axis);CHKERRQ(ierr); if (!rank) { const char *title; ierr = PetscDrawAxisSetLimits(axis,xmin,xmax,ymin,ymax);CHKERRQ(ierr); ierr = PetscDrawAxisDraw(axis);CHKERRQ(ierr); ierr = PetscDrawGetCoordinates(draw,coors,coors+1,coors+2,coors+3);CHKERRQ(ierr); ierr = DMDAGetFieldName(da,j,&title);CHKERRQ(ierr); if (title) {ierr = PetscDrawSetTitle(draw,title);CHKERRQ(ierr);} } ierr = MPI_Bcast(coors,4,MPIU_REAL,0,comm);CHKERRQ(ierr); if (rank) { ierr = PetscDrawSetCoordinates(draw,coors[0],coors[1],coors[2],coors[3]);CHKERRQ(ierr); } /* draw local part of vector */ ierr = PetscObjectGetNewTag((PetscObject)xin,&tag1);CHKERRQ(ierr); ierr = PetscObjectGetNewTag((PetscObject)xin,&tag2);CHKERRQ(ierr); if (rank < size-1) { /*send value to right */ ierr = MPI_Send((void*)&array[j+(n-1)*step],1,MPIU_REAL,rank+1,tag1,comm);CHKERRQ(ierr); ierr = MPI_Send((void*)&xg[n-1],1,MPIU_REAL,rank+1,tag1,comm);CHKERRQ(ierr); } if (!rank && bx == DM_BOUNDARY_PERIODIC && size > 1) { /* first processor sends first value to last */ ierr = MPI_Send((void*)&array[j],1,MPIU_REAL,size-1,tag2,comm);CHKERRQ(ierr); } for (i=1; i<n; i++) { ierr = PetscDrawLine(draw,PetscRealPart(xg[i-1]),PetscRealPart(array[j+step*(i-1)]),PetscRealPart(xg[i]),PetscRealPart(array[j+step*i]),PETSC_DRAW_RED);CHKERRQ(ierr); if (showmarkers) { ierr = PetscDrawMarker(draw,PetscRealPart(xg[i-1]),PetscRealPart(array[j+step*(i-1)]),PETSC_DRAW_BLACK);CHKERRQ(ierr); } } if (rank) { /* receive value from left */ ierr = MPI_Recv(&tmp,1,MPIU_REAL,rank-1,tag1,comm,&status);CHKERRQ(ierr); ierr = MPI_Recv(&xgtmp,1,MPIU_REAL,rank-1,tag1,comm,&status);CHKERRQ(ierr); ierr = PetscDrawLine(draw,xgtmp,tmp,PetscRealPart(xg[0]),PetscRealPart(array[j]),PETSC_DRAW_RED);CHKERRQ(ierr); if (showmarkers) { ierr = PetscDrawPoint(draw,xgtmp,tmp,PETSC_DRAW_BLACK);CHKERRQ(ierr); } } if (rank == size-1 && bx == DM_BOUNDARY_PERIODIC && size > 1) { ierr = MPI_Recv(&tmp,1,MPIU_REAL,0,tag2,comm,&status);CHKERRQ(ierr); /* If the mesh is not uniform we do not know the mesh spacing between the last point on the right and the first ghost point */ ierr = PetscDrawLine(draw,PetscRealPart(xg[n-1]),PetscRealPart(array[j+step*(n-1)]),PetscRealPart(xg[n-1]+(xg[n-1]-xg[n-2])),tmp,PETSC_DRAW_RED);CHKERRQ(ierr); if (showmarkers) { ierr = PetscDrawMarker(draw,PetscRealPart(xg[n-2]),PetscRealPart(array[j+step*(n-1)]),PETSC_DRAW_BLACK);CHKERRQ(ierr); } } ierr = PetscDrawSynchronizedFlush(draw);CHKERRQ(ierr); ierr = PetscDrawPause(draw);CHKERRQ(ierr); } #if defined(PETSC_HAVE_SETJMP_H) && defined(PETSC_HAVE_X) XSetIOErrorHandler(NULL); #endif ierr = PetscFree(displayfields);CHKERRQ(ierr); ierr = VecRestoreArrayRead(xcoor,&xg);CHKERRQ(ierr); ierr = VecRestoreArrayRead(xin,&array);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FormFunctionLocal(DMDALocalInfo *info,Field ***x,Field ***f,void *ptr) { /* values for each basis function at each quadrature point */ AppCtx *user = (AppCtx*)ptr; PetscInt i,j,k,l; PetscInt ii,jj,kk; Field ef[NEB]; Field ex[NEB]; CoordField ec[NEB]; PetscErrorCode ierr; PetscInt xs=info->xs,ys=info->ys,zs=info->zs; PetscInt xm=info->xm,ym=info->ym,zm=info->zm; PetscInt xes,yes,zes,xee,yee,zee; PetscInt mx=info->mx,my=info->my,mz=info->mz; DM cda; CoordField ***c; Vec C; PetscFunctionBegin; ierr = DMGetCoordinateDM(info->da,&cda);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(info->da,&C);CHKERRQ(ierr); ierr = DMDAVecGetArray(cda,C,&c);CHKERRQ(ierr); ierr = DMDAGetInfo(info->da,0,&mx,&my,&mz,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); ierr = DMDAGetCorners(info->da,&xs,&ys,&zs,&xm,&ym,&zm);CHKERRQ(ierr); /* loop over elements */ for (k=zs; k<zs+zm; k++) { for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { for (l=0;l<3;l++) { f[k][j][i][l] = 0.; } } } } /* element starts and ends */ xes = xs; yes = ys; zes = zs; xee = xs+xm; yee = ys+ym; zee = zs+zm; if (xs > 0) xes = xs - 1; if (ys > 0) yes = ys - 1; if (zs > 0) zes = zs - 1; if (xs+xm == mx) xee = xs+xm-1; if (ys+ym == my) yee = ys+ym-1; if (zs+zm == mz) zee = zs+zm-1; for (k=zes; k<zee; k++) { for (j=yes; j<yee; j++) { for (i=xes; i<xee; i++) { GatherElementData(mx,my,mz,x,c,i,j,k,ex,ec,user); FormElementJacobian(ex,ec,ef,NULL,user); /* put this element's additions into the residuals */ for (kk=0;kk<NB;kk++){ for (jj=0;jj<NB;jj++) { for (ii=0;ii<NB;ii++) { PetscInt idx = ii + jj*NB + kk*NB*NB; if (k+kk >= zs && j+jj >= ys && i+ii >= xs && k+kk < zs+zm && j+jj < ys+ym && i+ii < xs+xm) { if (OnBoundary(i+ii,j+jj,k+kk,mx,my,mz)) { for (l=0;l<3;l++) f[k+kk][j+jj][i+ii][l] = x[k+kk][j+jj][i+ii][l] - ex[idx][l]; } else { for (l=0;l<3;l++) f[k+kk][j+jj][i+ii][l] += ef[idx][l]; } } } } } } } } ierr = DMDAVecRestoreArray(cda,C,&c);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode SetUpMatrices(AppCtx *user) { PetscErrorCode ierr; PetscInt nele,nen,i,j; const PetscInt *ele; PetscScalar dt=user->dt; Vec coords; const PetscScalar *_coords; PetscScalar x[3],y[3]; PetscInt idx[3]; PetscScalar eM_0[3][3],eM_2_odd[3][3],eM_2_even[3][3]; Mat M =user->M; PetscScalar epsilon=user->epsilon; PetscScalar hx; PetscInt n,Mda,Nda; DM da; PetscFunctionBeginUser; /* Get ghosted coordinates */ ierr = DMGetCoordinatesLocal(user->da,&coords);CHKERRQ(ierr); ierr = VecGetArrayRead(coords,&_coords);CHKERRQ(ierr); /* Create the mass matrix M_0 */ ierr = MatGetLocalSize(M,&n,NULL);CHKERRQ(ierr); /* ierr = MatCreate(PETSC_COMM_WORLD,&user->M_0);CHKERRQ(ierr);*/ ierr = DMDAGetInfo(user->da,NULL,&Mda,&Nda,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); hx = 1.0/(Mda-1); ierr = DMDACreate2d(PETSC_COMM_WORLD,DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE,DMDA_STENCIL_BOX,Mda,Nda,PETSC_DECIDE,PETSC_DECIDE,1,1,NULL,NULL,&da);CHKERRQ(ierr); ierr = DMSetMatType(da,MATAIJ);CHKERRQ(ierr); ierr = DMCreateMatrix(da,&user->M_0);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); eM_0[0][0]=eM_0[1][1]=eM_0[2][2]=hx*hx/12.0; eM_0[0][1]=eM_0[0][2]=eM_0[1][0]=eM_0[1][2]=eM_0[2][0]=eM_0[2][1]=hx*hx/24.0; eM_2_odd[0][0] = eM_2_odd[0][1] = eM_2_odd[0][2] = 0.0; eM_2_odd[1][0] = eM_2_odd[1][1] = eM_2_odd[1][2] = 0.0; eM_2_odd[2][0] = eM_2_odd[2][1] = eM_2_odd[2][2] = 0.0; eM_2_odd[0][0]=1.0; eM_2_odd[1][1]=eM_2_odd[2][2]=0.5; eM_2_odd[0][1]=eM_2_odd[0][2]=eM_2_odd[1][0]=eM_2_odd[2][0]=-0.5; eM_2_even[0][0] = eM_2_even[0][1] = eM_2_even[0][2] = 0.0; eM_2_even[0][0] = eM_2_even[0][1] = eM_2_even[0][2] = 0.0; eM_2_even[0][0] = eM_2_even[0][1] = eM_2_even[0][2] = 0.0; eM_2_even[1][1]=1; eM_2_even[0][0]=eM_2_even[2][2]=0.5; eM_2_even[0][1]=eM_2_even[1][0]=eM_2_even[1][2]=eM_2_even[2][1]=-0.5; /* Get local element info */ ierr = DMDAGetElements(user->da,&nele,&nen,&ele);CHKERRQ(ierr); for (i=0; i < nele; i++) { idx[0] = ele[3*i]; idx[1] = ele[3*i+1]; idx[2] = ele[3*i+2]; x[0] = _coords[2*idx[0]]; y[0] = _coords[2*idx[0]+1]; x[1] = _coords[2*idx[1]]; y[1] = _coords[2*idx[1]+1]; x[2] = _coords[2*idx[2]]; y[2] = _coords[2*idx[2]+1]; PetscInt row,cols[3],r,row_M_0; PetscScalar vals[3],vals_M_0[3]; for (r=0; r<3; r++) { row_M_0 = idx[r]; vals_M_0[0]=eM_0[r][0]; vals_M_0[1]=eM_0[r][1]; vals_M_0[2]=eM_0[r][2]; ierr = MatSetValues(user->M_0,1,&row_M_0,3,idx,vals_M_0,ADD_VALUES);CHKERRQ(ierr); if (y[1]==y[0]) { row = 4*idx[r]; cols[0] = 4*idx[0]; vals[0] = eM_0[r][0]+dt*epsilon*epsilon*eM_2_odd[r][0]; cols[1] = 4*idx[1]; vals[1] = eM_0[r][1]+dt*epsilon*epsilon*eM_2_odd[r][1]; cols[2] = 4*idx[2]; vals[2] = eM_0[r][2]+dt*epsilon*epsilon*eM_2_odd[r][2]; /* Insert values in matrix M for 1st dof */ ierr = MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 4*idx[r]+1; cols[0] = 4*idx[0]+1; vals[0] = eM_0[r][0]+dt*epsilon*epsilon*eM_2_odd[r][0]; cols[1] = 4*idx[1]+1; vals[1] = eM_0[r][1]+dt*epsilon*epsilon*eM_2_odd[r][1]; cols[2] = 4*idx[2]+1; vals[2] = eM_0[r][2]+dt*epsilon*epsilon*eM_2_odd[r][2]; /* Insert values in matrix M for 2nd dof */ ierr = MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 4*idx[r]+2; cols[0] = 4*idx[0]+2; vals[0] = eM_0[r][0]+dt*epsilon*epsilon*eM_2_odd[r][0]; cols[1] = 4*idx[1]+2; vals[1] = eM_0[r][1]+dt*epsilon*epsilon*eM_2_odd[r][1]; cols[2] = 4*idx[2]+2; vals[2] = eM_0[r][2]+dt*epsilon*epsilon*eM_2_odd[r][2]; /* Insert values in matrix M for 3nd dof */ ierr = MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);CHKERRQ(ierr); } else { row = 4*idx[r]; cols[0] = 4*idx[0]; vals[0] = eM_0[r][0]+dt*epsilon*epsilon*eM_2_even[r][0]; cols[1] = 4*idx[1]; vals[1] = eM_0[r][1]+dt*epsilon*epsilon*eM_2_even[r][1]; cols[2] = 4*idx[2]; vals[2] = eM_0[r][2]+dt*epsilon*epsilon*eM_2_even[r][2]; /* Insert values in matrix M for 1st dof */ ierr = MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 4*idx[r]+1; cols[0] = 4*idx[0]+1; vals[0] = eM_0[r][0]+dt*epsilon*epsilon*eM_2_even[r][0]; cols[1] = 4*idx[1]+1; vals[1] = eM_0[r][1]+dt*epsilon*epsilon*eM_2_even[r][1]; cols[2] = 4*idx[2]+1; vals[2] = eM_0[r][2]+dt*epsilon*epsilon*eM_2_even[r][2]; /* Insert values in matrix M for 2nd dof */ ierr = MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 4*idx[r]+2; cols[0] = 4*idx[0]+2; vals[0] = eM_0[r][0]+dt*epsilon*epsilon*eM_2_even[r][0]; cols[1] = 4*idx[1]+2; vals[1] = eM_0[r][1]+dt*epsilon*epsilon*eM_2_even[r][1]; cols[2] = 4*idx[2]+2; vals[2] = eM_0[r][2]+dt*epsilon*epsilon*eM_2_even[r][2]; /* Insert values in matrix M for 3nd dof */ ierr = MatSetValuesLocal(M,1,&row,3,cols,vals,ADD_VALUES);CHKERRQ(ierr); } } } ierr = MatAssemblyBegin(user->M_0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(user->M_0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); PetscScalar vals[9]; vals[0] = -1.0; vals[1] = 0.0; vals[2] = 0.0; vals[3] = 0.0; vals[4] = -1.0; vals[5] = 0.0; vals[6] = 0.0; vals[7] = 0.0; vals[8] = -1.0; for (j=0; j < nele; j++) { idx[0] = ele[3*j]; idx[1] = ele[3*j+1]; idx[2] = ele[3*j+2]; PetscInt r,rows[3],cols[3]; for (r=0; r<3; r++) { rows[0] = 4*idx[0]+r; cols[0] = 4*idx[0]+3; rows[1] = 4*idx[1]+r; cols[1] = 4*idx[1]+3; rows[2] = 4*idx[2]+r; cols[2] = 4*idx[2]+3; ierr = MatSetValuesLocal(M,3,rows,3,cols,vals,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValuesLocal(M,3,cols,3,rows,vals,INSERT_VALUES);CHKERRQ(ierr); } } ierr = DMDARestoreElements(user->da,&nele,&nen,&ele);CHKERRQ(ierr); ierr = VecRestoreArrayRead(coords,&_coords);CHKERRQ(ierr); ierr = MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecCreate(PETSC_COMM_WORLD,&user->u1);CHKERRQ(ierr); ierr = VecSetSizes(user->u1,n/4,PETSC_DECIDE);CHKERRQ(ierr); ierr = VecSetFromOptions(user->u1);CHKERRQ(ierr); ierr = VecDuplicate(user->u1,&user->u2);CHKERRQ(ierr); ierr = VecDuplicate(user->u1,&user->u3);CHKERRQ(ierr); ierr = VecDuplicate(user->u1,&user->work1);CHKERRQ(ierr); ierr = VecDuplicate(user->u1,&user->work2);CHKERRQ(ierr); ierr = VecDuplicate(user->u1,&user->work3);CHKERRQ(ierr); ierr = VecDuplicate(user->u1,&user->work4);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode NonlinearGS(SNES snes,Vec X,Vec B,void *ptr) { /* values for each basis function at each quadrature point */ AppCtx *user = (AppCtx*)ptr; PetscInt i,j,k,l,m,n,s; PetscInt pi,pj,pk; Field ef[1]; Field ex[8]; PetscScalar ej[9]; CoordField ec[8]; PetscScalar pjac[9],pjinv[9]; PetscScalar pf[3],py[3]; PetscErrorCode ierr; PetscInt xs,ys,zs; PetscInt xm,ym,zm; PetscInt mx,my,mz; DM cda; CoordField ***c; Vec C; DM da; Vec Xl,Bl; Field ***x,***b; PetscInt sweeps,its; PetscReal atol,rtol,stol; PetscReal fnorm0 = 0.0,fnorm,ynorm,xnorm = 0.0; PetscFunctionBegin; ierr = SNESNGSGetSweeps(snes,&sweeps);CHKERRQ(ierr); ierr = SNESNGSGetTolerances(snes,&atol,&rtol,&stol,&its);CHKERRQ(ierr); ierr = SNESGetDM(snes,&da);CHKERRQ(ierr); ierr = DMGetLocalVector(da,&Xl);CHKERRQ(ierr); if (B) { ierr = DMGetLocalVector(da,&Bl);CHKERRQ(ierr); } ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,Xl);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,Xl);CHKERRQ(ierr); if (B) { ierr = DMGlobalToLocalBegin(da,B,INSERT_VALUES,Bl);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,B,INSERT_VALUES,Bl);CHKERRQ(ierr); } ierr = DMDAVecGetArray(da,Xl,&x);CHKERRQ(ierr); if (B) ierr = DMDAVecGetArray(da,Bl,&b);CHKERRQ(ierr); ierr = DMGetCoordinateDM(da,&cda);CHKERRQ(ierr); ierr = DMGetCoordinatesLocal(da,&C);CHKERRQ(ierr); ierr = DMDAVecGetArray(cda,C,&c);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&mx,&my,&mz,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&xs,&ys,&zs,&xm,&ym,&zm);CHKERRQ(ierr); for (s=0;s<sweeps;s++) { for (k=zs; k<zs+zm; k++) { for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { if (OnBoundary(i,j,k,mx,my,mz)) { BoundaryValue(i,j,k,mx,my,mz,x[k][j][i],user); } else { for (n=0;n<its;n++) { for (m=0;m<9;m++) pjac[m] = 0.; for (m=0;m<3;m++) pf[m] = 0.; /* gather the elements for this point */ for (pk=-1; pk<1; pk++) { for (pj=-1; pj<1; pj++) { for (pi=-1; pi<1; pi++) { /* check that this element exists */ if (i+pi >= 0 && i+pi < mx-1 && j+pj >= 0 && j+pj < my-1 && k+pk >= 0 && k+pk < mz-1) { /* create the element function and jacobian */ GatherElementData(mx,my,mz,x,c,i+pi,j+pj,k+pk,ex,ec,user); FormPBJacobian(-pi,-pj,-pk,ex,ec,ef,ej,user); /* extract the point named by i,j,k from the whole element jacobian and function */ for (l=0;l<3;l++) { pf[l] += ef[0][l]; for (m=0;m<3;m++) { pjac[3*m+l] += ej[3*m+l]; } } } } } } /* invert */ InvertTensor(pjac,pjinv,NULL); /* apply */ if (B) for (m=0;m<3;m++) { pf[m] -= b[k][j][i][m]; } TensorVector(pjinv,pf,py); xnorm=0.; for (m=0;m<3;m++) { x[k][j][i][m] -= py[m]; xnorm += PetscRealPart(x[k][j][i][m]*x[k][j][i][m]); } fnorm = PetscRealPart(pf[0]*pf[0]+pf[1]*pf[1]+pf[2]*pf[2]); if (n==0) fnorm0 = fnorm; ynorm = PetscRealPart(py[0]*py[0]+py[1]*py[1]+py[2]*py[2]); if (fnorm < atol*atol || fnorm < rtol*rtol*fnorm0 || ynorm < stol*stol*xnorm) break; } } } } } } ierr = DMDAVecRestoreArray(da,Xl,&x);CHKERRQ(ierr); ierr = DMLocalToGlobalBegin(da,Xl,INSERT_VALUES,X);CHKERRQ(ierr); ierr = DMLocalToGlobalEnd(da,Xl,INSERT_VALUES,X);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&Xl);CHKERRQ(ierr); if (B) { ierr = DMDAVecRestoreArray(da,Bl,&b);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&Bl);CHKERRQ(ierr); } ierr = DMDAVecRestoreArray(cda,C,&c);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* IFunction - Evaluates nonlinear function, F(U). Input Parameters: . ts - the TS context . U - input vector . ptr - optional user-defined context, as set by SNESSetFunction() Output Parameter: . F - function vector */ PetscErrorCode IFunction(TS ts,PetscReal ftime,Vec U,Vec Udot,Vec F,void *ptr) { AppCtx *appctx = (AppCtx*)ptr; DM da; PetscErrorCode ierr; PetscInt i,Mx,xs,xm; PetscReal hx,sx; PetscScalar rho,c,rhoxx,cxx,cx,rhox,kcxrhox; Field *u,*f,*udot; Vec localU; PetscFunctionBegin; ierr = TSGetDM(ts,&da);CHKERRQ(ierr); ierr = DMGetLocalVector(da,&localU);CHKERRQ(ierr); ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr); hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx); /* Scatter ghost points to local vector,using the 2-step process DMGlobalToLocalBegin(),DMGlobalToLocalEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ ierr = DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU);CHKERRQ(ierr); /* Get pointers to vector data */ ierr = DMDAVecGetArray(da,localU,&u);CHKERRQ(ierr); ierr = DMDAVecGetArray(da,Udot,&udot);CHKERRQ(ierr); ierr = DMDAVecGetArray(da,F,&f);CHKERRQ(ierr); /* Get local grid boundaries */ ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr); if (!xs) { f[0].rho = udot[0].rho; /* u[0].rho - 0.0; */ f[0].c = udot[0].c; /* u[0].c - 1.0; */ xs++; xm--; } if (xs+xm == Mx) { f[Mx-1].rho = udot[Mx-1].rho; /* u[Mx-1].rho - 1.0; */ f[Mx-1].c = udot[Mx-1].c; /* u[Mx-1].c - 0.0; */ xm--; } /* Compute function over the locally owned part of the grid */ for (i=xs; i<xs+xm; i++) { rho = u[i].rho; rhoxx = (-2.0*rho + u[i-1].rho + u[i+1].rho)*sx; c = u[i].c; cxx = (-2.0*c + u[i-1].c + u[i+1].c)*sx; if (!appctx->upwind) { rhox = .5*(u[i+1].rho - u[i-1].rho)/hx; cx = .5*(u[i+1].c - u[i-1].c)/hx; kcxrhox = appctx->kappa*(cxx*rho + cx*rhox); } else { kcxrhox = appctx->kappa*((u[i+1].c - u[i].c)*u[i+1].rho - (u[i].c - u[i-1].c)*u[i].rho)*sx; } f[i].rho = udot[i].rho - appctx->epsilon*rhoxx + kcxrhox - appctx->mu*PetscAbsScalar(rho)*(1.0 - rho)*PetscMax(0,PetscRealPart(c - appctx->cstar)) + appctx->beta*rho; f[i].c = udot[i].c - appctx->delta*cxx + appctx->lambda*c + appctx->alpha*rho*c/(appctx->gamma + c); } /* Restore vectors */ ierr = DMDAVecRestoreArray(da,localU,&u);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da,Udot,&udot);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da,F,&f);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localU);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc,char **argv) { AppCtx user; /* user-defined work context */ PetscInt mx,my,its; PetscErrorCode ierr; MPI_Comm comm; SNES snes; DM da; Vec x,X,b; PetscBool youngflg,poissonflg,muflg,lambdaflg,view=PETSC_FALSE,viewline=PETSC_FALSE; PetscReal poisson=0.2,young=4e4; char filename[PETSC_MAX_PATH_LEN] = "ex16.vts"; char filename_def[PETSC_MAX_PATH_LEN] = "ex16_def.vts"; ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; ierr = FormElements();CHKERRQ(ierr); comm = PETSC_COMM_WORLD; ierr = SNESCreate(comm,&snes);CHKERRQ(ierr); ierr = DMDACreate3d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,11,2,2,PETSC_DECIDE,PETSC_DECIDE,PETSC_DECIDE,3,1,NULL,NULL,NULL,&da);CHKERRQ(ierr); ierr = DMSetFromOptions(da);CHKERRQ(ierr); ierr = DMSetUp(da);CHKERRQ(ierr); ierr = SNESSetDM(snes,(DM)da);CHKERRQ(ierr); ierr = SNESSetNGS(snes,NonlinearGS,&user);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&mx,&my,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr); user.loading = 0.0; user.arc = PETSC_PI/3.; user.mu = 4.0; user.lambda = 1.0; user.rad = 100.0; user.height = 3.; user.width = 1.; user.ploading = -5e3; ierr = PetscOptionsGetReal(NULL,NULL,"-arc",&user.arc,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,NULL,"-mu",&user.mu,&muflg);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,NULL,"-lambda",&user.lambda,&lambdaflg);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,NULL,"-rad",&user.rad,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,NULL,"-height",&user.height,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,NULL,"-width",&user.width,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,NULL,"-loading",&user.loading,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,NULL,"-ploading",&user.ploading,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,NULL,"-poisson",&poisson,&poissonflg);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,NULL,"-young",&young,&youngflg);CHKERRQ(ierr); if ((youngflg || poissonflg) || !(muflg || lambdaflg)) { /* set the lame' parameters based upon the poisson ratio and young's modulus */ user.lambda = poisson*young / ((1. + poisson)*(1. - 2.*poisson)); user.mu = young/(2.*(1. + poisson)); } ierr = PetscOptionsGetBool(NULL,NULL,"-view",&view,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,NULL,"-view_line",&viewline,NULL);CHKERRQ(ierr); ierr = DMDASetFieldName(da,0,"x_disp");CHKERRQ(ierr); ierr = DMDASetFieldName(da,1,"y_disp");CHKERRQ(ierr); ierr = DMDASetFieldName(da,2,"z_disp");CHKERRQ(ierr); ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr); ierr = DMDASNESSetFunctionLocal(da,INSERT_VALUES,(PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))FormFunctionLocal,&user);CHKERRQ(ierr); ierr = DMDASNESSetJacobianLocal(da,(DMDASNESJacobian)FormJacobianLocal,&user);CHKERRQ(ierr); ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); ierr = FormCoordinates(da,&user);CHKERRQ(ierr); ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr); ierr = DMCreateGlobalVector(da,&b);CHKERRQ(ierr); ierr = InitialGuess(da,&user,x);CHKERRQ(ierr); ierr = FormRHS(da,&user,b);CHKERRQ(ierr); ierr = PetscPrintf(comm,"lambda: %f mu: %f\n",(double)user.lambda,(double)user.mu);CHKERRQ(ierr); /* show a cross-section of the initial state */ if (viewline) { ierr = DisplayLine(snes,x);CHKERRQ(ierr); } /* get the loaded configuration */ ierr = SNESSolve(snes,b,x);CHKERRQ(ierr); ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); ierr = PetscPrintf(comm,"Number of SNES iterations = %D\n", its);CHKERRQ(ierr); ierr = SNESGetSolution(snes,&X);CHKERRQ(ierr); /* show a cross-section of the final state */ if (viewline) { ierr = DisplayLine(snes,X);CHKERRQ(ierr); } if (view) { PetscViewer viewer; Vec coords; ierr = PetscViewerVTKOpen(PETSC_COMM_WORLD,filename,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr); ierr = VecView(x,viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); ierr = DMGetCoordinates(da,&coords);CHKERRQ(ierr); ierr = VecAXPY(coords,1.0,x);CHKERRQ(ierr); ierr = PetscViewerVTKOpen(PETSC_COMM_WORLD,filename_def,FILE_MODE_WRITE,&viewer);CHKERRQ(ierr); ierr = VecView(x,viewer);CHKERRQ(ierr); ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); } ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
int main(int argc,char **argv) { PetscErrorCode ierr; SNES snes; Vec u, r; /* solution, residual vector */ PetscInt Mx,My,its; SNESConvergedReason reason; DM da; ObsCtx user; PetscReal dx,dy,error1,errorinf; PetscBool feasible = PETSC_FALSE,fdflg = PETSC_FALSE; PetscInitialize(&argc,&argv,(char *)0,help); ierr = DMDACreate2d(PETSC_COMM_WORLD, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE, DMDA_STENCIL_STAR, /* nonlinear diffusion but diffusivity depends on soln W not grad W */ -11,-11, /* default to 10x10 grid but override with -da_grid_x, -da_grid_y (or -da_refine) */ PETSC_DECIDE,PETSC_DECIDE, /* num of procs in each dim */ 1, /* dof = 1 */ 1, /* s = 1 (stencil extends out one cell) */ PETSC_NULL,PETSC_NULL, /* no specify proc decomposition */ &da);CHKERRQ(ierr); ierr = DMCreateGlobalVector(da,&u);CHKERRQ(ierr); ierr = VecDuplicate(u,&r);CHKERRQ(ierr); ierr = VecDuplicate(u,&(user.uexact));CHKERRQ(ierr); ierr = VecDuplicate(u,&(user.psi));CHKERRQ(ierr); ierr = PetscOptionsBegin(PETSC_COMM_WORLD,"","options to obstacle problem","");CHKERRQ(ierr); ierr = PetscOptionsBool("-fd","use coloring to compute Jacobian by finite differences",PETSC_NULL,fdflg,&fdflg,PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsBool("-feasible","use feasible initial guess",PETSC_NULL,feasible,&feasible,PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsEnd();CHKERRQ(ierr); ierr = DMDASetUniformCoordinates(da,-2.0,2.0,-2.0,2.0,0.0,1.0);CHKERRQ(ierr); ierr = DMSetApplicationContext(da,&user);CHKERRQ(ierr); ierr = FormPsiAndInitialGuess(da,u,feasible);CHKERRQ(ierr); ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr); ierr = SNESSetDM(snes,da);CHKERRQ(ierr); ierr = SNESSetApplicationContext(snes,&user);CHKERRQ(ierr); ierr = SNESSetType(snes,SNESVINEWTONRSLS);CHKERRQ(ierr); ierr = SNESVISetComputeVariableBounds(snes,&FormBounds);CHKERRQ(ierr); ierr = DMDASNESSetFunctionLocal(da,INSERT_VALUES,(PetscErrorCode (*)(DMDALocalInfo*,void*,void*,void*))FormFunctionLocal,&user);CHKERRQ(ierr); if (!fdflg) { ierr = DMDASNESSetJacobianLocal(da,(PetscErrorCode (*)(DMDALocalInfo*,void*,Mat,Mat,MatStructure*,void*))FormJacobianLocal,&user);CHKERRQ(ierr); } ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); /* report on setup */ 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); dx = 4.0 / (PetscReal)(Mx-1); dy = 4.0 / (PetscReal)(My-1); ierr = PetscPrintf(PETSC_COMM_WORLD, "setup done: square side length = %.3f\n" " grid Mx,My = %D,%D\n" " spacing dx,dy = %.3f,%.3f\n", 4.0, Mx, My, (double)dx, (double)dy);CHKERRQ(ierr); /* solve nonlinear system */ ierr = SNESSolve(snes,PETSC_NULL,u);CHKERRQ(ierr); ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); ierr = SNESGetConvergedReason(snes,&reason);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"number of Newton iterations = %D; result = %s\n", its,SNESConvergedReasons[reason]);CHKERRQ(ierr); /* compare to exact */ ierr = VecWAXPY(r,-1.0,user.uexact,u);CHKERRQ(ierr); /* r = W - Wexact */ ierr = VecNorm(r,NORM_1,&error1);CHKERRQ(ierr); error1 /= (PetscReal)Mx * (PetscReal)My; ierr = VecNorm(r,NORM_INFINITY,&errorinf);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"errors: av |u-uexact| = %.3e\n |u-uexact|_inf = %.3e\n",error1,errorinf);CHKERRQ(ierr); /* Free work space. */ ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&r);CHKERRQ(ierr); ierr = VecDestroy(&(user.psi));CHKERRQ(ierr); ierr = VecDestroy(&(user.uexact));CHKERRQ(ierr); ierr = SNESDestroy(&snes);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = PetscFinalize();CHKERRQ(ierr); return 0; }
/* FormFunction - Evaluates nonlinear function, F(x). Input Parameters: . ts - the TS context . X - input vector . ptr - optional user-defined context, as set by SNESSetFunction() Output Parameter: . F - function vector */ PetscErrorCode FormFunction(TS ts,PetscReal ftime,Vec X,Vec Xdot,Vec F,void *ptr) { DM da; PetscErrorCode ierr; PetscInt i,Mx,xs,xm; PetscReal hx,sx; PetscScalar r,l; Field *x,*xdot,*f; Vec localX,localXdot; UserCtx *ctx = (UserCtx*)ptr; PetscFunctionBegin; ierr = TSGetDM(ts,&da);CHKERRQ(ierr); ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr); ierr = DMGetLocalVector(da,&localXdot);CHKERRQ(ierr); ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE, PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE); hx = 1.0/(PetscReal)Mx; sx = 1.0/(hx*hx); /* Scatter ghost points to local vector,using the 2-step process DMGlobalToLocalBegin(),DMGlobalToLocalEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalBegin(da,Xdot,INSERT_VALUES,localXdot);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,Xdot,INSERT_VALUES,localXdot);CHKERRQ(ierr); /* Get pointers to vector data */ ierr = DMDAVecGetArrayRead(da,localX,&x);CHKERRQ(ierr); ierr = DMDAVecGetArrayRead(da,localXdot,&xdot);CHKERRQ(ierr); ierr = DMDAVecGetArray(da,F,&f);CHKERRQ(ierr); /* Get local grid boundaries */ ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr); /* Compute function over the locally owned part of the grid */ for (i=xs; i<xs+xm; i++) { f[i].w = x[i].w + ctx->kappa*(x[i-1].u + x[i+1].u - 2.0*x[i].u)*sx; if (ctx->cahnhillard) { switch (ctx->energy) { case 1: /* double well */ f[i].w += -x[i].u*x[i].u*x[i].u + x[i].u; break; case 2: /* double obstacle */ f[i].w += x[i].u; break; case 3: /* logarithmic */ if (x[i].u < -1.0 + 2.0*ctx->tol) f[i].w += .5*ctx->theta*(-log(ctx->tol) + log((1.0-x[i].u)/2.0)) + ctx->theta_c*x[i].u; else if (x[i].u > 1.0 - 2.0*ctx->tol) f[i].w += .5*ctx->theta*(-log((1.0+x[i].u)/2.0) + log(ctx->tol)) + ctx->theta_c*x[i].u; else f[i].w += .5*ctx->theta*(-log((1.0+x[i].u)/2.0) + log((1.0-x[i].u)/2.0)) + ctx->theta_c*x[i].u; break; case 4: break; } } f[i].u = xdot[i].u - (x[i-1].w + x[i+1].w - 2.0*x[i].w)*sx; if (ctx->energy==4) { f[i].u = xdot[i].u; /* approximation of \grad (M(u) \grad w), where M(u) = (1-u^2) */ r = (1.0 - x[i+1].u*x[i+1].u)*(x[i+2].w-x[i].w)*.5/hx; l = (1.0 - x[i-1].u*x[i-1].u)*(x[i].w-x[i-2].w)*.5/hx; f[i].u -= (r - l)*.5/hx; f[i].u += 2.0*ctx->theta_c*x[i].u*(x[i+1].u-x[i-1].u)*(x[i+1].u-x[i-1].u)*.25*sx - (ctx->theta - ctx->theta_c*(1-x[i].u*x[i].u))*(x[i+1].u + x[i-1].u - 2.0*x[i].u)*sx; } } /* Restore vectors */ ierr = DMDAVecRestoreArrayRead(da,localXdot,&xdot);CHKERRQ(ierr); ierr = DMDAVecRestoreArrayRead(da,localX,&x);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da,F,&f);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localXdot);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* DMPatchZoom - Create a version of the coarse patch (identified by rank) with halo on communicator commz Collective on DM Input Parameters: + dm - the DM . rank - the rank which holds the given patch - commz - the new communicator for the patch Output Parameters: + dmz - the patch DM . sfz - the PetscSF mapping the patch+halo to the zoomed version . sfzr - the PetscSF mapping the patch to the restricted zoomed version Level: intermediate Note: All processes in commz should have the same rank (could autosplit comm) .seealso: DMPatchSolve() */ PetscErrorCode DMPatchZoom(DM dm, Vec X, MatStencil lower, MatStencil upper, MPI_Comm commz, DM *dmz, PetscSF *sfz, PetscSF *sfzr) { DMDAStencilType st; MatStencil blower, bupper, loclower, locupper; IS is; const PetscInt *ranges, *indices; PetscInt *localPoints = NULL; PetscSFNode *remotePoints = NULL; PetscInt dim, dof; PetscInt M, N, P, rM, rN, rP, halo = 1, sxb, syb, szb, sxr, syr, szr, exr, eyr, ezr, mxb, myb, mzb, i, j, k, q; PetscMPIInt size; PetscErrorCode ierr; PetscFunctionBegin; ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); /* Create patch DM */ ierr = DMDAGetInfo(dm, &dim, &M, &N, &P, 0,0,0, &dof, 0,0,0,0, &st);CHKERRQ(ierr); /* Get piece for rank r, expanded by halo */ bupper.i = PetscMin(M, upper.i + halo); blower.i = PetscMax(lower.i - halo, 0); bupper.j = PetscMin(N, upper.j + halo); blower.j = PetscMax(lower.j - halo, 0); bupper.k = PetscMin(P, upper.k + halo); blower.k = PetscMax(lower.k - halo, 0); rM = bupper.i - blower.i; rN = bupper.j - blower.j; rP = bupper.k - blower.k; if (commz != MPI_COMM_NULL) { ierr = DMDACreate(commz, dmz);CHKERRQ(ierr); ierr = DMSetDimension(*dmz, dim);CHKERRQ(ierr); ierr = DMDASetSizes(*dmz, rM, rN, rP);CHKERRQ(ierr); ierr = DMDASetNumProcs(*dmz, PETSC_DECIDE, PETSC_DECIDE, PETSC_DECIDE);CHKERRQ(ierr); ierr = DMDASetBoundaryType(*dmz, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE);CHKERRQ(ierr); ierr = DMDASetDof(*dmz, dof);CHKERRQ(ierr); ierr = DMDASetStencilType(*dmz, st);CHKERRQ(ierr); ierr = DMDASetStencilWidth(*dmz, 0);CHKERRQ(ierr); ierr = DMDASetOwnershipRanges(*dmz, NULL, NULL, NULL);CHKERRQ(ierr); ierr = DMSetFromOptions(*dmz);CHKERRQ(ierr); ierr = DMSetUp(*dmz);CHKERRQ(ierr); ierr = DMDAGetCorners(*dmz, &sxb, &syb, &szb, &mxb, &myb, &mzb);CHKERRQ(ierr); sxr = PetscMax(sxb, lower.i - blower.i); syr = PetscMax(syb, lower.j - blower.j); szr = PetscMax(szb, lower.k - blower.k); exr = PetscMin(sxb+mxb, upper.i - blower.i); eyr = PetscMin(syb+myb, upper.j - blower.j); ezr = PetscMin(szb+mzb, upper.k - blower.k); ierr = PetscMalloc2(rM*rN*rP,&localPoints,rM*rN*rP,&remotePoints);CHKERRQ(ierr); } else { sxr = syr = szr = exr = eyr = ezr = sxb = syb = szb = mxb = myb = mzb = 0; } /* Create SF for restricted map */ ierr = VecGetOwnershipRanges(X,&ranges);CHKERRQ(ierr); loclower.i = blower.i + sxr; locupper.i = blower.i + exr; loclower.j = blower.j + syr; locupper.j = blower.j + eyr; loclower.k = blower.k + szr; locupper.k = blower.k + ezr; ierr = DMDACreatePatchIS(dm, &loclower, &locupper, &is);CHKERRQ(ierr); ierr = ISGetIndices(is, &indices);CHKERRQ(ierr); q = 0; for (k = szb; k < szb+mzb; ++k) { if ((k < szr) || (k >= ezr)) continue; for (j = syb; j < syb+myb; ++j) { if ((j < syr) || (j >= eyr)) continue; for (i = sxb; i < sxb+mxb; ++i) { const PetscInt lp = ((k-szb)*rN + (j-syb))*rM + i-sxb; PetscInt r; if ((i < sxr) || (i >= exr)) continue; localPoints[q] = lp; ierr = PetscFindInt(indices[q], size+1, ranges, &r);CHKERRQ(ierr); remotePoints[q].rank = r < 0 ? -(r+1) - 1 : r; remotePoints[q].index = indices[q] - ranges[remotePoints[q].rank]; ++q; } } } ierr = ISRestoreIndices(is, &indices);CHKERRQ(ierr); ierr = ISDestroy(&is);CHKERRQ(ierr); ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfzr);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) *sfzr, "Restricted Map");CHKERRQ(ierr); ierr = PetscSFSetGraph(*sfzr, M*N*P, q, localPoints, PETSC_COPY_VALUES, remotePoints, PETSC_COPY_VALUES);CHKERRQ(ierr); /* Create SF for buffered map */ loclower.i = blower.i + sxb; locupper.i = blower.i + sxb+mxb; loclower.j = blower.j + syb; locupper.j = blower.j + syb+myb; loclower.k = blower.k + szb; locupper.k = blower.k + szb+mzb; ierr = DMDACreatePatchIS(dm, &loclower, &locupper, &is);CHKERRQ(ierr); ierr = ISGetIndices(is, &indices);CHKERRQ(ierr); q = 0; for (k = szb; k < szb+mzb; ++k) { for (j = syb; j < syb+myb; ++j) { for (i = sxb; i < sxb+mxb; ++i, ++q) { PetscInt r; localPoints[q] = q; ierr = PetscFindInt(indices[q], size+1, ranges, &r);CHKERRQ(ierr); remotePoints[q].rank = r < 0 ? -(r+1) - 1 : r; remotePoints[q].index = indices[q] - ranges[remotePoints[q].rank]; } } } ierr = ISRestoreIndices(is, &indices);CHKERRQ(ierr); ierr = ISDestroy(&is);CHKERRQ(ierr); ierr = PetscSFCreate(PetscObjectComm((PetscObject)dm), sfz);CHKERRQ(ierr); ierr = PetscObjectSetName((PetscObject) *sfz, "Buffered Map");CHKERRQ(ierr); ierr = PetscSFSetGraph(*sfz, M*N*P, q, localPoints, PETSC_COPY_VALUES, remotePoints, PETSC_COPY_VALUES);CHKERRQ(ierr); ierr = PetscFree2(localPoints, remotePoints);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc,char **argv) { TS ts; /* nonlinear solver */ Vec x,r; /* solution, residual vectors */ Mat J; /* Jacobian matrix */ PetscInt steps,Mx,maxsteps = 10000000; PetscErrorCode ierr; DM da; MatFDColoring matfdcoloring; ISColoring iscoloring; PetscReal dt; PetscReal vbounds[] = {-100000,100000,-1.1,1.1}; PetscBool wait; Vec ul,uh; SNES snes; UserCtx ctx; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Initialize program - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; ctx.kappa = 1.0; ierr = PetscOptionsGetReal(NULL,"-kappa",&ctx.kappa,NULL);CHKERRQ(ierr); ctx.cahnhillard = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,NULL,"-cahn-hillard",&ctx.cahnhillard,NULL);CHKERRQ(ierr); ierr = PetscViewerDrawSetBounds(PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD),2,vbounds);CHKERRQ(ierr); ierr = PetscViewerDrawResize(PETSC_VIEWER_DRAW_(PETSC_COMM_WORLD),600,600);CHKERRQ(ierr); ctx.energy = 1; /* ierr = PetscOptionsGetInt(NULL,NULL,"-energy",&ctx.energy,NULL);CHKERRQ(ierr); */ ierr = PetscOptionsGetInt(NULL,NULL,"-energy",&ctx.energy,NULL);CHKERRQ(ierr); ctx.tol = 1.0e-8; ierr = PetscOptionsGetReal(NULL,"-tol",&ctx.tol,NULL);CHKERRQ(ierr); ctx.theta = .001; ctx.theta_c = 1.0; ierr = PetscOptionsGetReal(NULL,"-theta",&ctx.theta,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,"-theta_c",&ctx.theta_c,NULL);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create distributed array (DMDA) to manage parallel grid and vectors - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = DMDACreate1d(PETSC_COMM_WORLD, DM_BOUNDARY_PERIODIC, -10,2,2,NULL,&da);CHKERRQ(ierr); ierr = DMSetFromOptions(da);CHKERRQ(ierr); ierr = DMSetUp(da);CHKERRQ(ierr); ierr = DMDASetFieldName(da,0,"Biharmonic heat equation: w = -kappa*u_xx");CHKERRQ(ierr); ierr = DMDASetFieldName(da,1,"Biharmonic heat equation: u");CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&Mx,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); dt = 1.0/(10.*ctx.kappa*Mx*Mx*Mx*Mx); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Extract global vectors from DMDA; then duplicate for remaining vectors that are the same types - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr); ierr = VecDuplicate(x,&r);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create timestepping solver context - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr); ierr = TSSetDM(ts,da);CHKERRQ(ierr); ierr = TSSetProblemType(ts,TS_NONLINEAR);CHKERRQ(ierr); ierr = TSSetIFunction(ts,NULL,FormFunction,&ctx);CHKERRQ(ierr); ierr = TSSetDuration(ts,maxsteps,.02);CHKERRQ(ierr); ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create matrix data structure; set Jacobian evaluation routine < Set Jacobian matrix data structure and default Jacobian evaluation routine. User can override with: -snes_mf : matrix-free Newton-Krylov method with no preconditioning (unless user explicitly sets preconditioner) -snes_mf_operator : form preconditioning matrix as set by the user, but use matrix-free approx for Jacobian-vector products within Newton-Krylov method - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); ierr = DMCreateColoring(da,IS_COLORING_GLOBAL,&iscoloring);CHKERRQ(ierr); ierr = DMSetMatType(da,MATAIJ);CHKERRQ(ierr); ierr = DMCreateMatrix(da,&J);CHKERRQ(ierr); ierr = MatFDColoringCreate(J,iscoloring,&matfdcoloring);CHKERRQ(ierr); ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr); ierr = MatFDColoringSetFunction(matfdcoloring,(PetscErrorCode (*)(void))SNESTSFormFunction,ts);CHKERRQ(ierr); ierr = MatFDColoringSetFromOptions(matfdcoloring);CHKERRQ(ierr); ierr = MatFDColoringSetUp(J,iscoloring,matfdcoloring);CHKERRQ(ierr); ierr = SNESSetJacobian(snes,J,J,SNESComputeJacobianDefaultColor,matfdcoloring);CHKERRQ(ierr); { ierr = VecDuplicate(x,&ul);CHKERRQ(ierr); ierr = VecDuplicate(x,&uh);CHKERRQ(ierr); ierr = VecStrideSet(ul,0,PETSC_NINFINITY);CHKERRQ(ierr); ierr = VecStrideSet(ul,1,-1.0);CHKERRQ(ierr); ierr = VecStrideSet(uh,0,PETSC_INFINITY);CHKERRQ(ierr); ierr = VecStrideSet(uh,1,1.0);CHKERRQ(ierr); ierr = TSVISetVariableBounds(ts,ul,uh);CHKERRQ(ierr); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Customize nonlinear solver - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = TSSetType(ts,TSBEULER);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Set initial conditions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = FormInitialSolution(da,x,ctx.kappa);CHKERRQ(ierr); ierr = TSSetInitialTimeStep(ts,0.0,dt);CHKERRQ(ierr); ierr = TSSetSolution(ts,x);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Set runtime options - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = TSSetFromOptions(ts);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Solve nonlinear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = TSSolve(ts,x);CHKERRQ(ierr); wait = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,NULL,"-wait",&wait,NULL);CHKERRQ(ierr); if (wait) { ierr = PetscSleep(-1);CHKERRQ(ierr); } ierr = TSGetTimeStepNumber(ts,&steps);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Free work space. All PETSc objects should be destroyed when they are no longer needed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ { ierr = VecDestroy(&ul);CHKERRQ(ierr); ierr = VecDestroy(&uh);CHKERRQ(ierr); } ierr = MatDestroy(&J);CHKERRQ(ierr); ierr = MatFDColoringDestroy(&matfdcoloring);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&r);CHKERRQ(ierr); ierr = TSDestroy(&ts);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = PetscFinalize(); PetscFunctionReturn(0); }
/* DMDAGetFaceInterpolation - Gets the interpolation for a face based coarse space */ PetscErrorCode DMDAGetFaceInterpolation(DM da,PC_Exotic *exotic,Mat Aglobal,MatReuse reuse,Mat *P) { PetscErrorCode ierr; PetscInt dim,i,j,k,m,n,p,dof,Nint,Nface,Nwire,Nsurf,*Iint,*Isurf,cint = 0,csurf = 0,istart,jstart,kstart,*II,N,c = 0; PetscInt mwidth,nwidth,pwidth,cnt,mp,np,pp,Ntotal,gl[6],*globals,Ng,*IIint,*IIsurf,Nt; Mat Xint, Xsurf,Xint_tmp; IS isint,issurf,is,row,col; ISLocalToGlobalMapping ltg; MPI_Comm comm; Mat A,Aii,Ais,Asi,*Aholder,iAii; MatFactorInfo info; PetscScalar *xsurf,*xint; #if defined(PETSC_USE_DEBUG_foo) PetscScalar tmp; #endif PetscTable ht; PetscFunctionBegin; ierr = DMDAGetInfo(da,&dim,0,0,0,&mp,&np,&pp,&dof,0,0,0,0,0); CHKERRQ(ierr); if (dof != 1) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only for single field problems"); if (dim != 3) SETERRQ(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Only coded for 3d problems"); ierr = DMDAGetCorners(da,0,0,0,&m,&n,&p); CHKERRQ(ierr); ierr = DMDAGetGhostCorners(da,&istart,&jstart,&kstart,&mwidth,&nwidth,&pwidth); CHKERRQ(ierr); istart = istart ? -1 : 0; jstart = jstart ? -1 : 0; kstart = kstart ? -1 : 0; /* the columns of P are the interpolation of each coarse grid point (one for each vertex and edge) to all the local degrees of freedom (this includes the vertices, edges and faces). Xint are the subset of the interpolation into the interior Xface are the interpolation onto faces but not into the interior Xsurf are the interpolation onto the vertices and edges (the surfbasket) Xint Symbolically one could write P = (Xface) after interchanging the rows to match the natural ordering on the domain Xsurf */ N = (m - istart)*(n - jstart)*(p - kstart); Nint = (m-2-istart)*(n-2-jstart)*(p-2-kstart); Nface = 2*((m-2-istart)*(n-2-jstart) + (m-2-istart)*(p-2-kstart) + (n-2-jstart)*(p-2-kstart)); Nwire = 4*((m-2-istart) + (n-2-jstart) + (p-2-kstart)) + 8; Nsurf = Nface + Nwire; ierr = MatCreateSeqDense(MPI_COMM_SELF,Nint,6,NULL,&Xint); CHKERRQ(ierr); ierr = MatCreateSeqDense(MPI_COMM_SELF,Nsurf,6,NULL,&Xsurf); CHKERRQ(ierr); ierr = MatDenseGetArray(Xsurf,&xsurf); CHKERRQ(ierr); /* Require that all 12 edges and 6 faces have at least one grid point. Otherwise some of the columns of Xsurf will be all zero (thus making the coarse matrix singular). */ if (m-istart < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in X direction must be at least 3"); if (n-jstart < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in Y direction must be at least 3"); if (p-kstart < 3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of grid points per process in Z direction must be at least 3"); cnt = 0; for (j=1; j<n-1-jstart; j++) { for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 0*Nsurf] = 1; } for (k=1; k<p-1-kstart; k++) { for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 1*Nsurf] = 1; for (j=1; j<n-1-jstart; j++) { xsurf[cnt++ + 2*Nsurf] = 1; /* these are the interior nodes */ xsurf[cnt++ + 3*Nsurf] = 1; } for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 4*Nsurf] = 1; } for (j=1; j<n-1-jstart; j++) { for (i=1; i<m-istart-1; i++) xsurf[cnt++ + 5*Nsurf] = 1; } #if defined(PETSC_USE_DEBUG_foo) for (i=0; i<Nsurf; i++) { tmp = 0.0; for (j=0; j<6; j++) tmp += xsurf[i+j*Nsurf]; if (PetscAbsScalar(tmp-1.0) > 1.e-10) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong Xsurf interpolation at i %D value %g",i,(double)PetscAbsScalar(tmp)); } #endif ierr = MatDenseRestoreArray(Xsurf,&xsurf); CHKERRQ(ierr); /* ierr = MatView(Xsurf,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);*/ /* I are the indices for all the needed vertices (in global numbering) Iint are the indices for the interior values, I surf for the surface values (This is just for the part of the global matrix obtained with MatGetSubMatrix(), it is NOT the local DMDA ordering.) IIint and IIsurf are the same as the Iint, Isurf except they are in the global numbering */ #define Endpoint(a,start,b) (a == 0 || a == (b-1-start)) ierr = PetscMalloc3(N,&II,Nint,&Iint,Nsurf,&Isurf); CHKERRQ(ierr); ierr = PetscMalloc2(Nint,&IIint,Nsurf,&IIsurf); CHKERRQ(ierr); for (k=0; k<p-kstart; k++) { for (j=0; j<n-jstart; j++) { for (i=0; i<m-istart; i++) { II[c++] = i + j*mwidth + k*mwidth*nwidth; if (!Endpoint(i,istart,m) && !Endpoint(j,jstart,n) && !Endpoint(k,kstart,p)) { IIint[cint] = i + j*mwidth + k*mwidth*nwidth; Iint[cint++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); } else { IIsurf[csurf] = i + j*mwidth + k*mwidth*nwidth; Isurf[csurf++] = i + j*(m-istart) + k*(m-istart)*(n-jstart); } } } } if (c != N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"c != N"); if (cint != Nint) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"cint != Nint"); if (csurf != Nsurf) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"csurf != Nsurf"); ierr = DMGetLocalToGlobalMapping(da,<g); CHKERRQ(ierr); ierr = ISLocalToGlobalMappingApply(ltg,N,II,II); CHKERRQ(ierr); ierr = ISLocalToGlobalMappingApply(ltg,Nint,IIint,IIint); CHKERRQ(ierr); ierr = ISLocalToGlobalMappingApply(ltg,Nsurf,IIsurf,IIsurf); CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)da,&comm); CHKERRQ(ierr); ierr = ISCreateGeneral(comm,N,II,PETSC_COPY_VALUES,&is); CHKERRQ(ierr); ierr = ISCreateGeneral(PETSC_COMM_SELF,Nint,Iint,PETSC_COPY_VALUES,&isint); CHKERRQ(ierr); ierr = ISCreateGeneral(PETSC_COMM_SELF,Nsurf,Isurf,PETSC_COPY_VALUES,&issurf); CHKERRQ(ierr); ierr = PetscFree3(II,Iint,Isurf); CHKERRQ(ierr); ierr = ISSort(is); CHKERRQ(ierr); ierr = MatGetSubMatrices(Aglobal,1,&is,&is,MAT_INITIAL_MATRIX,&Aholder); CHKERRQ(ierr); A = *Aholder; ierr = PetscFree(Aholder); CHKERRQ(ierr); ierr = MatGetSubMatrix(A,isint,isint,MAT_INITIAL_MATRIX,&Aii); CHKERRQ(ierr); ierr = MatGetSubMatrix(A,isint,issurf,MAT_INITIAL_MATRIX,&Ais); CHKERRQ(ierr); ierr = MatGetSubMatrix(A,issurf,isint,MAT_INITIAL_MATRIX,&Asi); CHKERRQ(ierr); /* Solve for the interpolation onto the interior Xint */ ierr = MatMatMult(Ais,Xsurf,MAT_INITIAL_MATRIX,PETSC_DETERMINE,&Xint_tmp); CHKERRQ(ierr); ierr = MatScale(Xint_tmp,-1.0); CHKERRQ(ierr); if (exotic->directSolve) { ierr = MatGetFactor(Aii,MATSOLVERPETSC,MAT_FACTOR_LU,&iAii); CHKERRQ(ierr); ierr = MatFactorInfoInitialize(&info); CHKERRQ(ierr); ierr = MatGetOrdering(Aii,MATORDERINGND,&row,&col); CHKERRQ(ierr); ierr = MatLUFactorSymbolic(iAii,Aii,row,col,&info); CHKERRQ(ierr); ierr = ISDestroy(&row); CHKERRQ(ierr); ierr = ISDestroy(&col); CHKERRQ(ierr); ierr = MatLUFactorNumeric(iAii,Aii,&info); CHKERRQ(ierr); ierr = MatMatSolve(iAii,Xint_tmp,Xint); CHKERRQ(ierr); ierr = MatDestroy(&iAii); CHKERRQ(ierr); } else { Vec b,x; PetscScalar *xint_tmp; ierr = MatDenseGetArray(Xint,&xint); CHKERRQ(ierr); ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,Nint,0,&x); CHKERRQ(ierr); ierr = MatDenseGetArray(Xint_tmp,&xint_tmp); CHKERRQ(ierr); ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,1,Nint,0,&b); CHKERRQ(ierr); ierr = KSPSetOperators(exotic->ksp,Aii,Aii); CHKERRQ(ierr); for (i=0; i<6; i++) { ierr = VecPlaceArray(x,xint+i*Nint); CHKERRQ(ierr); ierr = VecPlaceArray(b,xint_tmp+i*Nint); CHKERRQ(ierr); ierr = KSPSolve(exotic->ksp,b,x); CHKERRQ(ierr); ierr = VecResetArray(x); CHKERRQ(ierr); ierr = VecResetArray(b); CHKERRQ(ierr); } ierr = MatDenseRestoreArray(Xint,&xint); CHKERRQ(ierr); ierr = MatDenseRestoreArray(Xint_tmp,&xint_tmp); CHKERRQ(ierr); ierr = VecDestroy(&x); CHKERRQ(ierr); ierr = VecDestroy(&b); CHKERRQ(ierr); } ierr = MatDestroy(&Xint_tmp); CHKERRQ(ierr); #if defined(PETSC_USE_DEBUG_foo) ierr = MatDenseGetArray(Xint,&xint); CHKERRQ(ierr); for (i=0; i<Nint; i++) { tmp = 0.0; for (j=0; j<6; j++) tmp += xint[i+j*Nint]; if (PetscAbsScalar(tmp-1.0) > 1.e-10) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong Xint interpolation at i %D value %g",i,(double)PetscAbsScalar(tmp)); } ierr = MatDenseRestoreArray(Xint,&xint); CHKERRQ(ierr); /* ierr =MatView(Xint,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ #endif /* total faces */ Ntotal = mp*np*(pp+1) + mp*pp*(np+1) + np*pp*(mp+1); /* For each vertex, edge, face on process (in the same orderings as used above) determine its local number including ghost points */ cnt = 0; { gl[cnt++] = mwidth+1; } { { gl[cnt++] = mwidth*nwidth+1; } { gl[cnt++] = mwidth*nwidth + mwidth; /* these are the interior nodes */ gl[cnt++] = mwidth*nwidth + mwidth+m-istart-1; } { gl[cnt++] = mwidth*nwidth+mwidth*(n-jstart-1)+1; } } { gl[cnt++] = mwidth*nwidth*(p-kstart-1) + mwidth+1; } /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ /* convert that to global numbering and get them on all processes */ ierr = ISLocalToGlobalMappingApply(ltg,6,gl,gl); CHKERRQ(ierr); /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ ierr = PetscMalloc1(6*mp*np*pp,&globals); CHKERRQ(ierr); ierr = MPI_Allgather(gl,6,MPIU_INT,globals,6,MPIU_INT,PetscObjectComm((PetscObject)da)); CHKERRQ(ierr); /* Number the coarse grid points from 0 to Ntotal */ ierr = MatGetSize(Aglobal,&Nt,NULL); CHKERRQ(ierr); ierr = PetscTableCreate(Ntotal/3,Nt+1,&ht); CHKERRQ(ierr); for (i=0; i<6*mp*np*pp; i++) { ierr = PetscTableAddCount(ht,globals[i]+1); CHKERRQ(ierr); } ierr = PetscTableGetCount(ht,&cnt); CHKERRQ(ierr); if (cnt != Ntotal) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Hash table size %D not equal to total number coarse grid points %D",cnt,Ntotal); ierr = PetscFree(globals); CHKERRQ(ierr); for (i=0; i<6; i++) { ierr = PetscTableFind(ht,gl[i]+1,&gl[i]); CHKERRQ(ierr); gl[i]--; } ierr = PetscTableDestroy(&ht); CHKERRQ(ierr); /* PetscIntView(6,gl,PETSC_VIEWER_STDOUT_WORLD); */ /* construct global interpolation matrix */ ierr = MatGetLocalSize(Aglobal,&Ng,NULL); CHKERRQ(ierr); if (reuse == MAT_INITIAL_MATRIX) { ierr = MatCreateAIJ(PetscObjectComm((PetscObject)da),Ng,PETSC_DECIDE,PETSC_DECIDE,Ntotal,Nint+Nsurf,NULL,Nint,NULL,P); CHKERRQ(ierr); } else { ierr = MatZeroEntries(*P); CHKERRQ(ierr); } ierr = MatSetOption(*P,MAT_ROW_ORIENTED,PETSC_FALSE); CHKERRQ(ierr); ierr = MatDenseGetArray(Xint,&xint); CHKERRQ(ierr); ierr = MatSetValues(*P,Nint,IIint,6,gl,xint,INSERT_VALUES); CHKERRQ(ierr); ierr = MatDenseRestoreArray(Xint,&xint); CHKERRQ(ierr); ierr = MatDenseGetArray(Xsurf,&xsurf); CHKERRQ(ierr); ierr = MatSetValues(*P,Nsurf,IIsurf,6,gl,xsurf,INSERT_VALUES); CHKERRQ(ierr); ierr = MatDenseRestoreArray(Xsurf,&xsurf); CHKERRQ(ierr); ierr = MatAssemblyBegin(*P,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(*P,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = PetscFree2(IIint,IIsurf); CHKERRQ(ierr); #if defined(PETSC_USE_DEBUG_foo) { Vec x,y; PetscScalar *yy; ierr = VecCreateMPI(PetscObjectComm((PetscObject)da),Ng,PETSC_DETERMINE,&y); CHKERRQ(ierr); ierr = VecCreateMPI(PetscObjectComm((PetscObject)da),PETSC_DETERMINE,Ntotal,&x); CHKERRQ(ierr); ierr = VecSet(x,1.0); CHKERRQ(ierr); ierr = MatMult(*P,x,y); CHKERRQ(ierr); ierr = VecGetArray(y,&yy); CHKERRQ(ierr); for (i=0; i<Ng; i++) { if (PetscAbsScalar(yy[i]-1.0) > 1.e-10) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Wrong p interpolation at i %D value %g",i,(double)PetscAbsScalar(yy[i])); } ierr = VecRestoreArray(y,&yy); CHKERRQ(ierr); ierr = VecDestroy(x); CHKERRQ(ierr); ierr = VecDestroy(y); CHKERRQ(ierr); } #endif ierr = MatDestroy(&Aii); CHKERRQ(ierr); ierr = MatDestroy(&Ais); CHKERRQ(ierr); ierr = MatDestroy(&Asi); CHKERRQ(ierr); ierr = MatDestroy(&A); CHKERRQ(ierr); ierr = ISDestroy(&is); CHKERRQ(ierr); ierr = ISDestroy(&isint); CHKERRQ(ierr); ierr = ISDestroy(&issurf); CHKERRQ(ierr); ierr = MatDestroy(&Xint); CHKERRQ(ierr); ierr = MatDestroy(&Xsurf); CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode SetUpMatrices(AppCtx *user) { PetscErrorCode ierr; PetscInt nele,nen,i,j,n; const PetscInt *ele; PetscScalar dt=user->dt,hx,hy; PetscInt idx[3],*nodes, *connect, k; PetscScalar eM_0[3][3],eM_2_even[3][3],eM_2_odd[3][3]; PetscScalar cv_sum, ci_sum; Mat M =user->M; Mat M_0=user->M_0; PetscInt Mda=user->Mda, Nda=user->Nda, ld, rd, ru, lu; PetscScalar *cv_p,*ci_p; PetscFunctionBeginUser; /* ierr = MatSetOption(M,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); ierr = MatSetOption(M_0,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);*/ /* Create the mass matrix M_0 */ ierr = VecGetArray(user->cv,&cv_p);CHKERRQ(ierr); ierr = VecGetArray(user->ci,&ci_p);CHKERRQ(ierr); ierr = MatGetLocalSize(M,&n,NULL);CHKERRQ(ierr); ierr = DMDAGetInfo(user->da1,NULL,&Mda,&Nda,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); ierr = PetscMalloc((Mda+1)*(Nda+1)*sizeof(PetscInt),&nodes);CHKERRQ(ierr); ierr = PetscMalloc(Mda*Nda*2*3*sizeof(PetscInt),&connect);CHKERRQ(ierr); hx = (user->xmax-user->xmin)/Mda; hy = (user->ymax-user->ymin)/Nda; for (j=0; j < Nda; j++) { for (i=0; i < Mda; i++) nodes[j*(Mda+1)+i] = j*Mda+i; nodes[j*(Mda+1)+Mda] = j*Mda; } for (i=0; i < Mda; i++) nodes[Nda*(Mda+1)+i] = i; nodes[Nda*(Mda+1)+Mda] = 0; k = 0; for (j=0; j<Nda; j++) { for (i=0; i<Mda; i++) { /* ld = nodes[j][i]; */ ld = nodes[j*(Mda+1)+i]; /* rd = nodes[j+1][i]; */ rd = nodes[(j+1)*(Mda+1)+i]; /* ru = nodes[j+1][i+1]; */ ru = nodes[(j+1)*(Mda+1)+i+1]; /* lu = nodes[j][i+1]; */ lu = nodes[j*(Mda+1)+i+1]; /* connect[k][0]=ld; */ connect[k*6]=ld; /* connect[k][1]=lu; */ connect[k*6+1]=lu; /* connect[k][2]=ru; */ connect[k*6+2]=rd; connect[k*6+3]=lu; connect[k*6+4]=ru; connect[k*6+5]=rd; k = k+1; } } eM_0[0][0]=eM_0[1][1]=eM_0[2][2]=hx*hy/12.0; eM_0[0][1]=eM_0[0][2]=eM_0[1][0]=eM_0[1][2]=eM_0[2][0]=eM_0[2][1]=hx*hy/24.0; eM_2_odd[0][0] = 1.0; eM_2_odd[1][1] = eM_2_odd[2][2] = 0.5; eM_2_odd[0][1] = eM_2_odd[0][2] = eM_2_odd[1][0]= eM_2_odd[2][0] = -0.5; eM_2_odd[1][2] = eM_2_odd[2][1] = 0.0; eM_2_even[1][1] = 1.0; eM_2_even[0][0] = eM_2_even[2][2] = 0.5; eM_2_even[0][1] = eM_2_even[1][0] = eM_2_even[1][2] = eM_2_even[2][1] = -0.5; eM_2_even[0][2] = eM_2_even[2][0] = 0.0; for (k=0; k < Mda*Nda*2; k++) { idx[0] = connect[k*3]; idx[1] = connect[k*3+1]; idx[2] = connect[k*3+2]; PetscInt row,cols[6],r,row_M_0,cols3[3]; PetscScalar vals[6],vals_M_0[3],vals3[3]; for (r=0; r<3; r++) { row_M_0 = connect[k*3+r]; vals_M_0[0]=eM_0[r][0]; vals_M_0[1]=eM_0[r][1]; vals_M_0[2]=eM_0[r][2]; ierr = MatSetValues(M_0,1,&row_M_0,3,idx,vals_M_0,ADD_VALUES);CHKERRQ(ierr); /* cv_sum = (cv_p[idx[0]] + cv_p[idx[1]] + cv_p[idx[2]])*user->Dv/(3.0*user->kBT); */ /* ci_sum = (ci_p[idx[0]] + ci_p[idx[1]] + ci_p[idx[2]])*user->Di/(3.0*user->kBT); */ cv_sum = .0000069*user->Dv/user->kBT; ci_sum = .0000069*user->Di/user->kBT; if (k%2 == 0) { row = 5*idx[r]; cols[0] = 5*idx[0]; vals[0] = dt*eM_2_odd[r][0]*cv_sum; cols[1] = 5*idx[1]; vals[1] = dt*eM_2_odd[r][1]*cv_sum; cols[2] = 5*idx[2]; vals[2] = dt*eM_2_odd[r][2]*cv_sum; cols[3] = 5*idx[0]+1; vals[3] = eM_0[r][0]; cols[4] = 5*idx[1]+1; vals[4] = eM_0[r][1]; cols[5] = 5*idx[2]+1; vals[5] = eM_0[r][2]; ierr = MatSetValuesLocal(M,1,&row,6,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 5*idx[r]+1; cols[0] = 5*idx[0]; vals[0] = -1.0*eM_0[r][0]; cols[1] = 5*idx[1]; vals[1] = -1.0*eM_0[r][1]; cols[2] = 5*idx[2]; vals[2] = -1.0*eM_0[r][2]; cols[3] = 5*idx[0]+1; vals[3] = user->kav*eM_2_odd[r][0]; cols[4] = 5*idx[1]+1; vals[4] = user->kav*eM_2_odd[r][1]; cols[5] = 5*idx[2]+1; vals[5] = user->kav*eM_2_odd[r][2]; ierr = MatSetValuesLocal(M,1,&row,6,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 5*idx[r]+2; cols[0] = 5*idx[0]+2; vals[0] = dt*eM_2_odd[r][0]*ci_sum; cols[1] = 5*idx[1]+2; vals[1] = dt*eM_2_odd[r][1]*ci_sum; cols[2] = 5*idx[2]+2; vals[2] = dt*eM_2_odd[r][2]*ci_sum; cols[3] = 5*idx[0]+3; vals[3] = eM_0[r][0]; cols[4] = 5*idx[1]+3; vals[4] = eM_0[r][1]; cols[5] = 5*idx[2]+3; vals[5] = eM_0[r][2]; ierr = MatSetValuesLocal(M,1,&row,6,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 5*idx[r]+3; cols[0] = 5*idx[0]+2; vals[0] = -1.0*eM_0[r][0]; cols[1] = 5*idx[1]+2; vals[1] = -1.0*eM_0[r][1]; cols[2] = 5*idx[2]+2; vals[2] = -1.0*eM_0[r][2]; cols[3] = 5*idx[0]+3; vals[3] = user->kai*eM_2_odd[r][0]; cols[4] = 5*idx[1]+3; vals[4] = user->kai*eM_2_odd[r][1]; cols[5] = 5*idx[2]+3; vals[5] = user->kai*eM_2_odd[r][2]; ierr = MatSetValuesLocal(M,1,&row,6,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 5*idx[r]+4; /* cols3[0] = 5*idx[0]+4; vals3[0] = eM_0[r][0]/dt + user->L*user->kaeta*dt*eM_2_odd[r][0]; cols3[1] = 5*idx[1]+4; vals3[1] = eM_0[r][1]/dt + user->L*user->kaeta*dt*eM_2_odd[r][1]; cols3[2] = 5*idx[2]+4; vals3[2] = eM_0[r][2]/dt + user->L*user->kaeta*dt*eM_2_odd[r][2]; */ cols3[0] = 5*idx[0]+4; vals3[0] = eM_0[r][0]/dt + user->L*user->kaeta*eM_2_odd[r][0]; cols3[1] = 5*idx[1]+4; vals3[1] = eM_0[r][1]/dt + user->L*user->kaeta*eM_2_odd[r][1]; cols3[2] = 5*idx[2]+4; vals3[2] = eM_0[r][2]/dt + user->L*user->kaeta*eM_2_odd[r][2]; ierr = MatSetValuesLocal(M,1,&row,3,cols3,vals3,ADD_VALUES);CHKERRQ(ierr); } else { row = 5*idx[r]; cols[0] = 5*idx[0]; vals[0] = dt*eM_2_even[r][0]*cv_sum; cols[1] = 5*idx[1]; vals[1] = dt*eM_2_even[r][1]*cv_sum; cols[2] = 5*idx[2]; vals[2] = dt*eM_2_even[r][2]*cv_sum; cols[3] = 5*idx[0]+1; vals[3] = eM_0[r][0]; cols[4] = 5*idx[1]+1; vals[4] = eM_0[r][1]; cols[5] = 5*idx[2]+1; vals[5] = eM_0[r][2]; ierr = MatSetValuesLocal(M,1,&row,6,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 5*idx[r]+1; cols[0] = 5*idx[0]; vals[0] = -1.0*eM_0[r][0]; cols[1] = 5*idx[1]; vals[1] = -1.0*eM_0[r][1]; cols[2] = 5*idx[2]; vals[2] = -1.0*eM_0[r][2]; cols[3] = 5*idx[0]+1; vals[3] = user->kav*eM_2_even[r][0]; cols[4] = 5*idx[1]+1; vals[4] = user->kav*eM_2_even[r][1]; cols[5] = 5*idx[2]+1; vals[5] = user->kav*eM_2_even[r][2]; ierr = MatSetValuesLocal(M,1,&row,6,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 5*idx[r]+2; cols[0] = 5*idx[0]+2; vals[0] = dt*eM_2_even[r][0]*ci_sum; cols[1] = 5*idx[1]+2; vals[1] = dt*eM_2_even[r][1]*ci_sum; cols[2] = 5*idx[2]+2; vals[2] = dt*eM_2_even[r][2]*ci_sum; cols[3] = 5*idx[0]+3; vals[3] = eM_0[r][0]; cols[4] = 5*idx[1]+3; vals[4] = eM_0[r][1]; cols[5] = 5*idx[2]+3; vals[5] = eM_0[r][2]; ierr = MatSetValuesLocal(M,1,&row,6,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 5*idx[r]+3; cols[0] = 5*idx[0]+2; vals[0] = -1.0*eM_0[r][0]; cols[1] = 5*idx[1]+2; vals[1] = -1.0*eM_0[r][1]; cols[2] = 5*idx[2]+2; vals[2] = -1.0*eM_0[r][2]; cols[3] = 5*idx[0]+3; vals[3] = user->kai*eM_2_even[r][0]; cols[4] = 5*idx[1]+3; vals[4] = user->kai*eM_2_even[r][1]; cols[5] = 5*idx[2]+3; vals[5] = user->kai*eM_2_even[r][2]; ierr = MatSetValuesLocal(M,1,&row,6,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 5*idx[r]+4; /* cols3[0] = 5*idx[0]+4; vals3[0] = eM_0[r][0]/dt + user->L*user->kaeta*dt*eM_2_even[r][0]; cols3[1] = 5*idx[1]+4; vals3[1] = eM_0[r][1]/dt + user->L*user->kaeta*dt*eM_2_even[r][1]; cols3[2] = 5*idx[2]+4; vals3[2] = eM_0[r][2]/dt + user->L*user->kaeta*dt*eM_2_even[r][2]; */ cols3[0] = 5*idx[0]+4; vals3[0] = eM_0[r][0]/dt + user->L*user->kaeta*eM_2_even[r][0]; cols3[1] = 5*idx[1]+4; vals3[1] = eM_0[r][1]/dt + user->L*user->kaeta*eM_2_even[r][1]; cols3[2] = 5*idx[2]+4; vals3[2] = eM_0[r][2]/dt + user->L*user->kaeta*eM_2_even[r][2]; ierr = MatSetValuesLocal(M,1,&row,3,cols3,vals3,ADD_VALUES);CHKERRQ(ierr); } } } ierr = PetscFree(nodes);CHKERRQ(ierr); ierr = PetscFree(connect);CHKERRQ(ierr); ierr = VecRestoreArray(user->cv,&cv_p);CHKERRQ(ierr); ierr = VecRestoreArray(user->ci,&ci_p);CHKERRQ(ierr); ierr = MatAssemblyBegin(M_0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(M_0,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = DMDARestoreElements(user->da1,&nele,&nen,&ele);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* IFunction - Evaluates nonlinear function, F(U). Input Parameters: . ts - the TS context . U - input vector . ptr - optional user-defined context, as set by SNESSetFunction() Output Parameter: . F - function vector */ PetscErrorCode IFunction(TS ts,PetscReal ftime,Vec U,Vec Udot,Vec F,void *ptr) { DM da; PetscErrorCode ierr; PetscInt i,c,Mx,xs,xm,N; PetscReal hx,sx,x; PetscScalar uxx; PetscScalar **u,**f,**udot; Vec localU; PetscFunctionBegin; ierr = TSGetDM(ts,&da);CHKERRQ(ierr); ierr = DMGetLocalVector(da,&localU);CHKERRQ(ierr); ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,&N,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE);CHKERRQ(ierr); hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx); /* Scatter ghost points to local vector,using the 2-step process DMGlobalToLocalBegin(),DMGlobalToLocalEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ ierr = DMGlobalToLocalBegin(da,U,INSERT_VALUES,localU);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,U,INSERT_VALUES,localU);CHKERRQ(ierr); /* Get pointers to vector data */ ierr = DMDAVecGetArrayDOF(da,localU,&u);CHKERRQ(ierr); ierr = DMDAVecGetArrayDOF(da,Udot,&udot);CHKERRQ(ierr); ierr = DMDAVecGetArrayDOF(da,F,&f);CHKERRQ(ierr); /* Get local grid boundaries */ ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr); /* Compute function over the locally owned part of the grid */ for (i=xs; i<xs+xm; i++) { x = i*hx; /* diffusion term */ for (c=0; c<N; c++) { uxx = (-2.0*u[i][c] + u[i-1][c] + u[i+1][c])*sx; f[i][c] = udot[i][c] - uxx; } /* reaction terms */ for (c=0; c<N/3; c++) { f[i][c] += 500*u[i][c]*u[i][c] + 500*u[i][c]*u[i][c+1]; f[i][c+1] += -500*u[i][c]*u[i][c] + 500*u[i][c]*u[i][c+1]; f[i][c+2] -= 500*u[i][c]*u[i][c+1]; } /* forcing term */ f[i][0] -= 5*PetscExpScalar((1.0 - x)*(1.0 - x)); } /* Restore vectors */ ierr = DMDAVecRestoreArrayDOF(da,localU,&u);CHKERRQ(ierr); ierr = DMDAVecRestoreArrayDOF(da,Udot,&udot);CHKERRQ(ierr); ierr = DMDAVecRestoreArrayDOF(da,F,&f);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localU);CHKERRQ(ierr); PetscFunctionReturn(0); }
EXTERN_C_BEGIN #undef __FUNCT__ #define __FUNCT__ "DMConvert_DA_Mesh" PetscErrorCode DMConvert_DA_Mesh(DM dm, const DMType newtype, DM *dmNew) { PetscSection section; DM cda; DMDALocalInfo info; Vec coordinates; PetscInt *cone, *coneO; PetscInt dim, M, N, P, numCells, numGlobalCells, numCorners, numVertices, c = 0, v = 0; PetscInt ye, ze; PetscInt debug = 0; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscOptionsGetInt(PETSC_NULL, "-dm_mesh_debug", &debug, PETSC_NULL);CHKERRQ(ierr); ierr = DMDAGetInfo(dm, &dim, &M, &N, &P, 0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); ierr = DMDAGetLocalInfo(dm, &info);CHKERRQ(ierr); if (info.sw > 1) SETERRQ(((PetscObject) dm)->comm, PETSC_ERR_SUP, "Currently, only DMDAs with unti stencil width can be converted to DMMeshes."); /* In order to get a partition of cells, rather than vertices, we give each process the cells between vertices it owns and also higher numbered ghost vertices (vertices to the right and up) */ numCorners = 1 << dim; numCells = ((info.gxm+info.gxs - info.xs) - 1); if (dim > 1) {numCells *= ((info.gym+info.gys - info.ys) - 1);} if (dim > 2) {numCells *= ((info.gzm+info.gzs - info.zs) - 1);} numVertices = (info.gxm+info.gxs - info.xs); if (dim > 1) {numVertices *= (info.gym+info.gys - info.ys);} if (dim > 2) {numVertices *= (info.gzm+info.gzs - info.zs);} numGlobalCells = M-1; if (dim > 1) {numGlobalCells *= N-1;} if (dim > 2) {numGlobalCells *= P-1;} ALE::Obj<PETSC_MESH_TYPE> mesh = new PETSC_MESH_TYPE(((PetscObject) dm)->comm, info.dim, debug); ALE::Obj<PETSC_MESH_TYPE::sieve_type> sieve = new PETSC_MESH_TYPE::sieve_type(((PetscObject) dm)->comm, 0, numCells+numVertices, debug); PETSC_MESH_TYPE::renumbering_type renumbering; mesh->setSieve(sieve); /* Number each cell for the vertex in the lower left corner */ if (dim < 3) {ze = 1; P = 1;} else {ze = info.gzs+info.gzm-1;} if (dim < 2) {ye = 1; N = 1;} else {ye = info.gys+info.gym-1;} for(PetscInt k = info.zs; k < ze; ++k) { for(PetscInt j = info.ys; j < ye; ++j) { for(PetscInt i = info.xs; i < info.gxs+info.gxm-1; ++i, ++c) { PetscInt globalC = (k*(N-1) + j)*(M-1) + i; renumbering[globalC] = c; sieve->setConeSize(c, numCorners); } } } if (c != numCells) {SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Error in generated cell numbering, %d should be %d", c, numCells);} /* Get vertex renumbering */ for(PetscInt k = info.zs; k < info.gzs+info.gzm; ++k) { for(PetscInt j = info.ys; j < info.gys+info.gym; ++j) { for(PetscInt i = info.xs; i < info.gxs+info.gxm; ++i, ++v) { PetscInt globalV = (k*N + j)*M + i + numGlobalCells; renumbering[globalV] = v+numCells; } } } if (v != numVertices) {SETERRQ2(((PetscObject) dm)->comm, PETSC_ERR_PLIB, "Error in generated vertex numbering, %d should be %d", v, numVertices);} /* Calculate support sizes */ for(PetscInt k = info.zs; k < ze; ++k, ++c) { for(PetscInt j = info.ys; j < ye; ++j) { for(PetscInt i = info.xs; i < info.gxs+info.gxm-1; ++i) { for(PetscInt kp = k; kp <= k+(dim>2); ++kp) { for(PetscInt jp = j; jp <= j+(dim>1); ++jp) { for(PetscInt ip = i; ip <= i+1; ++ip) { PetscInt globalV = (kp*N + jp)*M + ip + numGlobalCells; sieve->addSupportSize(renumbering[globalV], 1); } } } } } } sieve->allocate(); ierr = PetscMalloc2(numCorners,PetscInt,&cone,numCorners,PetscInt,&coneO);CHKERRQ(ierr); for(PetscInt v = 0; v < numCorners; ++v) { coneO[v] = 1; } for(PetscInt k = info.zs; k < ze; ++k) { for(PetscInt j = info.ys; j < ye; ++j) { for(PetscInt i = info.xs; i < info.gxs+info.gxm-1; ++i) { PetscInt globalC = (k*(N-1) + j)*(M-1) + i; PetscInt v = 0; cone[v++] = renumbering[(k*N + j)*M + i+0 + numGlobalCells]; cone[v++] = renumbering[(k*N + j)*M + i+1 + numGlobalCells]; if (dim > 1) { cone[v++] = renumbering[(k*N + j+1)*M + i+0 + numGlobalCells]; cone[v++] = renumbering[(k*N + j+1)*M + i+1 + numGlobalCells]; } if (dim > 2) { cone[v++] = renumbering[((k+1)*N + j+0)*M + i+0 + numGlobalCells]; cone[v++] = renumbering[((k+1)*N + j+0)*M + i+1 + numGlobalCells]; cone[v++] = renumbering[((k+1)*N + j+1)*M + i+0 + numGlobalCells]; cone[v++] = renumbering[((k+1)*N + j+1)*M + i+1 + numGlobalCells]; } sieve->setCone(cone, renumbering[globalC]); sieve->setConeOrientation(coneO, renumbering[globalC]); } } } ierr = PetscFree2(cone,coneO);CHKERRQ(ierr); sieve->symmetrize(); mesh->stratify(); /* Create boundary marker */ { const Obj<PETSC_MESH_TYPE::label_type>& boundary = mesh->createLabel("marker"); for(PetscInt k = info.zs; k < info.gzs+info.gzm; ++k) { for(PetscInt j = info.ys; j < info.gys+info.gym; ++j) { if (info.xs == 0) { PetscInt globalV = (k*N + j)*M + info.xs + numGlobalCells; mesh->setValue(boundary, renumbering[globalV], 1); } if (info.gxs+info.gxm-1 == M-1) { PetscInt globalV = (k*N + j)*M + info.gxs+info.gxm-1 + numGlobalCells; mesh->setValue(boundary, renumbering[globalV], 1); } } } if (dim > 1) { for(PetscInt k = info.zs; k < info.gzs+info.gzm; ++k) { for(PetscInt i = info.xs; i < info.gxs+info.gxm; ++i) { if (info.ys == 0) { PetscInt globalV = (k*N + info.ys)*M + i + numGlobalCells; mesh->setValue(boundary, renumbering[globalV], 1); } if (info.gys+info.gym-1 == N-1) { PetscInt globalV = (k*N + info.gys+info.gym-1)*M + i + numGlobalCells; mesh->setValue(boundary, renumbering[globalV], 1); } } } } if (dim > 2) { for(PetscInt j = info.ys; j < info.gys+info.gym; ++j) { for(PetscInt i = info.xs; i < info.gxs+info.gxm; ++i) { if (info.zs == 0) { PetscInt globalV = (info.zs*N + j)*M + i + numGlobalCells; mesh->setValue(boundary, renumbering[globalV], 1); } if (info.gzs+info.gzm-1 == P-1) { PetscInt globalV = ((info.gzs+info.gzm-1)*N + j)*M + i + numGlobalCells; mesh->setValue(boundary, renumbering[globalV], 1); } } } } } /* Create new DM */ ierr = DMMeshCreate(((PetscObject) dm)->comm, dmNew);CHKERRQ(ierr); ierr = DMMeshSetMesh(*dmNew, mesh);CHKERRQ(ierr); /* Set coordinates */ ierr = PetscSectionCreate(((PetscObject) dm)->comm, §ion);CHKERRQ(ierr); ierr = PetscSectionSetChart(section, numCells, numCells+numVertices);CHKERRQ(ierr); for(PetscInt v = numCells; v < numCells+numVertices; ++v) { ierr = PetscSectionSetDof(section, v, dim);CHKERRQ(ierr); } ierr = PetscSectionSetUp(section);CHKERRQ(ierr); ierr = DMMeshSetCoordinateSection(*dmNew, section);CHKERRQ(ierr); ierr = DMDAGetCoordinateDA(dm, &cda);CHKERRQ(ierr); ierr = DMDAGetGhostedCoordinates(dm, &coordinates);CHKERRQ(ierr); { Obj<PETSC_MESH_TYPE::real_section_type> coordSection = mesh->getRealSection("coordinates"); switch(dim) { case 1: { PetscScalar **coords; ierr = DMDAVecGetArrayDOF(cda, coordinates, &coords);CHKERRQ(ierr); for(PetscInt i = info.xs; i < info.gxs+info.gxm; ++i) { PetscInt globalV = i + numGlobalCells; coordSection->updatePoint(renumbering[globalV], coords[i]); } ierr = DMDAVecRestoreArrayDOF(cda, coordinates, &coords);CHKERRQ(ierr); break; } case 2: { PetscScalar ***coords; ierr = DMDAVecGetArrayDOF(cda, coordinates, &coords);CHKERRQ(ierr); for(PetscInt j = info.ys; j < info.gys+info.gym; ++j) { for(PetscInt i = info.xs; i < info.gxs+info.gxm; ++i) { PetscInt globalV = j*M + i + numGlobalCells; coordSection->updatePoint(renumbering[globalV], coords[j][i]); } } ierr = DMDAVecRestoreArrayDOF(cda, coordinates, &coords);CHKERRQ(ierr); break; } case 3: { PetscScalar ****coords; ierr = DMDAVecGetArrayDOF(cda, coordinates, &coords);CHKERRQ(ierr); for(PetscInt k = info.zs; k < info.gzs+info.gzm; ++k, ++v) { for(PetscInt j = info.ys; j < info.gys+info.gym; ++j) { for(PetscInt i = info.xs; i < info.gxs+info.gxm; ++i) { PetscInt globalV = (k*N + j)*M + i + numGlobalCells; coordSection->updatePoint(renumbering[globalV], coords[k][j][i]); } } } ierr = DMDAVecRestoreArrayDOF(cda, coordinates, &coords);CHKERRQ(ierr); break; } default: SETERRQ1(((PetscObject) dm)->comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid DMDA dimension %d", dim); } } /* Get overlap for interdomain communication */ { typedef PETSC_MESH_TYPE::point_type point_type; PETSc::Log::Event("CreateOverlap").begin(); ALE::Obj<PETSC_MESH_TYPE::send_overlap_type> sendParallelMeshOverlap = mesh->getSendOverlap(); ALE::Obj<PETSC_MESH_TYPE::recv_overlap_type> recvParallelMeshOverlap = mesh->getRecvOverlap(); // Can I figure this out in a nicer way? ALE::SetFromMap<std::map<point_type,point_type> > globalPoints(renumbering); ALE::OverlapBuilder<>::constructOverlap(globalPoints, renumbering, sendParallelMeshOverlap, recvParallelMeshOverlap); if (debug) { sendParallelMeshOverlap->view("Send Overlap"); recvParallelMeshOverlap->view("Recieve Overlap"); } mesh->setCalculatedOverlap(true); PETSc::Log::Event("CreateOverlap").end(); } PetscFunctionReturn(0); }