static PetscErrorCode ComputeMatrix(KSP ksp,Mat J,Mat jac,void *ctx) { AppCtx *user = (AppCtx*)ctx; PetscErrorCode ierr; PetscInt i,mx,xm,xs; PetscScalar v[3],h,xlow,xhigh; MatStencil row,col[3]; DM da; PetscFunctionBeginUser; ierr = KSPGetDM(ksp,&da);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&mx,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&xs,0,0,&xm,0,0);CHKERRQ(ierr); h = 1.0/(mx-1); for (i=xs; i<xs+xm; i++) { row.i = i; if (i==0 || i==mx-1) { v[0] = 2.0; ierr = MatSetValuesStencil(jac,1,&row,1,&row,v,INSERT_VALUES);CHKERRQ(ierr); } else { xlow = h*(PetscReal)i - .5*h; xhigh = xlow + h; v[0] = (-1.0 - user->e*PetscSinScalar(2.0*PETSC_PI*user->k*xlow))/h;col[0].i = i-1; v[1] = (2.0 + user->e*PetscSinScalar(2.0*PETSC_PI*user->k*xlow) + user->e*PetscSinScalar(2.0*PETSC_PI*user->k*xhigh))/h;col[1].i = row.i; v[2] = (-1.0 - user->e*PetscSinScalar(2.0*PETSC_PI*user->k*xhigh))/h;col[2].i = i+1; ierr = MatSetValuesStencil(jac,1,&row,3,col,v,INSERT_VALUES);CHKERRQ(ierr); } } ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode ComputeMatrix(KSP ksp,Mat J,Mat jac,MatStructure *str,void *ctx) { PetscErrorCode ierr; PetscInt i,mx,xm,xs; PetscScalar v[7],Hx; MatStencil row,col[7]; PetscScalar lambda; DM da; PetscFunctionBeginUser; ierr = KSPGetDM(ksp,&da);CHKERRQ(ierr); ierr = PetscMemzero(col,7*sizeof(MatStencil));CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&mx,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); Hx = 2.0*PETSC_PI / (PetscReal)(mx); ierr = DMDAGetCorners(da,&xs,0,0,&xm,0,0);CHKERRQ(ierr); lambda = 2.0*Hx; for (i=xs; i<xs+xm; i++) { row.i = i; row.j = 0; row.k = 0; row.c = 0; v[0] = Hx; col[0].i = i; col[0].c = 0; v[1] = lambda; col[1].i = i-1; col[1].c = 1; v[2] = -lambda;col[2].i = i+1; col[2].c = 1; ierr = MatSetValuesStencil(jac,1,&row,3,col,v,INSERT_VALUES);CHKERRQ(ierr); row.i = i; row.j = 0; row.k = 0; row.c = 1; v[0] = lambda; col[0].i = i-1; col[0].c = 0; v[1] = Hx; col[1].i = i; col[1].c = 1; v[2] = -lambda;col[2].i = i+1; col[2].c = 0; ierr = MatSetValuesStencil(jac,1,&row,3,col,v,INSERT_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatView(jac,PETSC_VIEWER_BINARY_(PETSC_COMM_SELF));CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode ComputeJacobian(KSP ksp,Mat J, Mat jac,void *ctx) { PetscErrorCode ierr; PetscInt i, j, M, N, xm, ym, xs, ys, num, numi, numj; PetscScalar v[5], Hx, Hy, HydHx, HxdHy; MatStencil row, col[5]; DM da; MatNullSpace nullspace; PetscFunctionBeginUser; ierr = KSPGetDM(ksp,&da);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&M,&N,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); Hx = 1.0 / (PetscReal)(M); Hy = 1.0 / (PetscReal)(N); HxdHy = Hx/Hy; HydHx = Hy/Hx; ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { row.i = i; row.j = j; if (i==0 || j==0 || i==M-1 || j==N-1) { num=0; numi=0; numj=0; if (j!=0) { v[num] = -HxdHy; col[num].i = i; col[num].j = j-1; num++; numj++; } if (i!=0) { v[num] = -HydHx; col[num].i = i-1; col[num].j = j; num++; numi++; } if (i!=M-1) { v[num] = -HydHx; col[num].i = i+1; col[num].j = j; num++; numi++; } if (j!=N-1) { v[num] = -HxdHy; col[num].i = i; col[num].j = j+1; num++; numj++; } v[num] = ((PetscReal)(numj)*HxdHy + (PetscReal)(numi)*HydHx); col[num].i = i; col[num].j = j; num++; ierr = MatSetValuesStencil(jac,1,&row,num,col,v,INSERT_VALUES);CHKERRQ(ierr); } else { v[0] = -HxdHy; col[0].i = i; col[0].j = j-1; v[1] = -HydHx; col[1].i = i-1; col[1].j = j; v[2] = 2.0*(HxdHy + HydHx); col[2].i = i; col[2].j = j; v[3] = -HydHx; col[3].i = i+1; col[3].j = j; v[4] = -HxdHy; col[4].i = i; col[4].j = j+1; ierr = MatSetValuesStencil(jac,1,&row,5,col,v,INSERT_VALUES);CHKERRQ(ierr); } } } ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,&nullspace);CHKERRQ(ierr); ierr = MatSetNullSpace(J,nullspace);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullspace);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode ComputeMatrix(KSP ksp,Mat J,Mat jac,void *ctx) { PetscErrorCode ierr; PetscInt i,mx,xm,xs; PetscScalar v[3],h; MatStencil row,col[3]; DM da,shell; PetscFunctionBeginUser; ierr = KSPGetDM(ksp,&shell);CHKERRQ(ierr); ierr = DMShellGetContext(shell,(void**)&da);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&mx,0,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&xs,0,0,&xm,0,0);CHKERRQ(ierr); h = 1.0/(mx-1); for (i=xs; i<xs+xm; i++) { row.i = i; if (i==0 || i==mx-1) { v[0] = 2.0/h; ierr = MatSetValuesStencil(jac,1,&row,1,&row,v,INSERT_VALUES);CHKERRQ(ierr); } else { v[0] = (-1.0)/h;col[0].i = i-1; v[1] = (2.0)/h;col[1].i = row.i; v[2] = (-1.0)/h;col[2].i = i+1; ierr = MatSetValuesStencil(jac,1,&row,3,col,v,INSERT_VALUES);CHKERRQ(ierr); } } ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FillMatrix(DM da,Mat A) { PetscErrorCode ierr; PetscInt i,j,k,mx,my,mz,xm,ym,zm,xs,ys,zs,idx; PetscScalar v[7]; MatStencil row,col[7]; PetscFunctionBeginUser; 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 (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; col[0].i=row.i; col[0].j=row.j; col[0].k=row.k; v[0]=6.0; idx=1; if (k>0) { v[idx]=-1.0; col[idx].i=i; col[idx].j=j; col[idx].k=k-1; idx++; } if (j>0) { v[idx]=-1.0; col[idx].i=i; col[idx].j=j-1; col[idx].k=k; idx++; } if (i>0) { v[idx]=-1.0; col[idx].i=i-1; col[idx].j=j; col[idx].k=k; idx++; } if (i<mx-1) { v[idx]=-1.0; col[idx].i=i+1; col[idx].j=j; col[idx].k=k; idx++; } if (j<my-1) { v[idx]=-1.0; col[idx].i=i; col[idx].j=j+1; col[idx].k=k; idx++; } if (k<mz-1) { v[idx]=-1.0; col[idx].i=i; col[idx].j=j; col[idx].k=k+1; idx++; } ierr = MatSetValuesStencil(A,1,&row,idx,col,v,INSERT_VALUES);CHKERRQ(ierr); } } } ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* Produces the second order centered difference diffusion operator on a one dimensional periodic domain */ static PetscErrorCode FormDiffusionJacobian(TS ts,PetscReal t,Vec X,Mat Amat,Mat Pmat,void *ptr) { User user = (User)ptr; PetscErrorCode ierr; DM dm; PetscInt i,xs,xm,j,dof; PetscReal idx,values[3]; MatStencil row,col[3]; PetscFunctionBeginUser; ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); ierr = DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); ierr = DMDAGetCorners(dm,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr); idx = 1.0*user->diffus/user->dx; values[0] = idx; values[1] = -2.0*idx; values[2] = idx; for (i=xs; i<xs+xm; i++) { for (j=0; j<dof; j++) { row.i = i; row.c = j; col[0].i = i-1; col[0].c = j; col[1].i = i; col[1].c = j; col[2].i = i+1; col[2].c = j; ierr = MatSetValuesStencil(Pmat,1,&row,3,col,values,ADD_VALUES);CHKERRQ(ierr); } } ierr = MatAssemblyBegin(Pmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(Pmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode update_dirichlet_sym_3d(ef_bc *bc, Mat A, DM da) { PetscErrorCode ierr; PetscInt i,j,k,cnt; PetscInt ngx, ngy, ngz; PetscScalar v[6]; MatStencil row[6], col; PetscInt level; ef_patch *patch = bc->patch; ierr = DMGetCoarsenLevel(da, &level);CHKERRQ(ierr); ierr = DMDAGetInfo(da, 0, &ngx, &ngy, &ngz,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); for (i = 0; i < 6; i++) v[i] = 0; for (k = patch->corners[level].is[2]; k <= patch->corners[level].ie[2]; k++) { 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; col.k = k; cnt = 0; if (i-1 < patch->corners[level].is[0] && i-1 >= 0) { row[cnt].i = i-1; row[cnt].j = j; row[cnt].k = k; cnt++; } if (i+1 > patch->corners[level].ie[0] && i+1 <= ngx-1) { row[cnt].i = i+1; row[cnt].j = j; row[cnt].k = k; cnt++; } if (j-1 < patch->corners[level].is[1] && j-1 >= 0) { row[cnt].i = i; row[cnt].j = j-1; row[cnt].k = k; cnt++; } if (j+1 > patch->corners[level].ie[1] && j+1 <= ngy-1) { row[cnt].i = i; row[cnt].j = j+1; row[cnt].k = k; cnt++; } if (k-1 < patch->corners[level].is[2] && k-1 >= 0) { row[cnt].i = i; row[cnt].j = j; row[cnt].k = k-1; cnt++; } if (k+1 > patch->corners[level].ie[2] && k+1 <= ngz-1) { row[cnt].i = i; row[cnt].j = j; row[cnt].k = k+1; cnt++; } ierr = MatSetValuesStencil(A, cnt, row, 1, &col, v, INSERT_VALUES);CHKERRQ(ierr); } } } return 0; }
PetscErrorCode FormIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal a,Mat *J,Mat *Jpre,MatStructure *str,void *ctx) { PetscErrorCode ierr; PetscInt i,j,Mx,My,xs,ys,xm,ym,nc; AppCtx *user = (AppCtx*)ctx; DM da = (DM)user->da; MatStencil col[5],row; PetscScalar vals[5],hx,hy,sx,sy; PetscFunctionBeginUser; ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE); ierr = DMDAGetCorners(da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL);CHKERRQ(ierr); hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx); hy = 1.0/(PetscReal)(My-1); sy = 1.0/(hy*hy); for (j=ys; j<ys+ym; j++){ for (i=xs; i<xs+xm; i++){ nc = 0; row.j = j; row.i = i; if (user->boundary == 0 && (i == 0 || i == Mx-1 || j == 0 || j == My-1)) { col[nc].j = j; col[nc].i = i; vals[nc++] = 1.0; } else if (user->boundary > 0 && i == 0) { /* Left Neumann */ col[nc].j = j; col[nc].i = i; vals[nc++] = 1.0; col[nc].j = j; col[nc].i = i+1; vals[nc++] = -1.0; } else if (user->boundary > 0 && i == Mx-1){/* Right Neumann */ col[nc].j = j; col[nc].i = i; vals[nc++] = 1.0; col[nc].j = j; col[nc].i = i-1; vals[nc++] = -1.0; } else if (user->boundary > 0 && j == 0) { /* Bottom Neumann */ col[nc].j = j; col[nc].i = i; vals[nc++] = 1.0; col[nc].j = j+1; col[nc].i = i; vals[nc++] = -1.0; } else if (user->boundary > 0 && j == My-1){/* Top Neumann */ col[nc].j = j; col[nc].i = i; vals[nc++] = 1.0; col[nc].j = j-1; col[nc].i = i; vals[nc++] = -1.0; } else { /* Interior */ col[nc].j = j-1; col[nc].i = i; vals[nc++] = -sy; col[nc].j = j; col[nc].i = i-1; vals[nc++] = -sx; col[nc].j = j; col[nc].i = i; vals[nc++] = 2.0*(sx + sy) + a; col[nc].j = j; col[nc].i = i+1; vals[nc++] = -sx; col[nc].j = j+1; col[nc].i = i; vals[nc++] = -sy; } ierr = MatSetValuesStencil(*Jpre,1,&row,nc,col,vals,INSERT_VALUES);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); } if (user->viewJacobian){ ierr = PetscPrintf(((PetscObject)*Jpre)->comm,"Jpre:\n");CHKERRQ(ierr); ierr = MatView(*Jpre,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode FormJacobianLocal(DMDALocalInfo *info, PetscScalar ***u, Mat J, Mat Jpre, Ctx *usr) { PetscErrorCode ierr; PetscInt i,j,q; PetscReal v[5],diag,x,y; const PetscReal e = usr->eps; MatStencil col[5],row; Spacings s; Wind W; getSpacings(info,&s); diag = e * 2.0 * (1.0/s.hx2 + 1.0/s.hy2); for (j=info->ys; j<info->ys+info->ym; j++) { y = -1.0 + j * s.hy; row.j = j; col[0].j = j; for (i=info->xs; i<info->xs+info->xm; i++) { x = -1.0 + i * s.hx; row.i = i; col[0].i = i; q = 1; if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) { v[0] = 1.0; } else { W = getWind(x,y); v[0] = diag; if (i-1 != 0) { v[q] = - e / s.hx2 - W.x / (2.0 * s.hx); col[q].j = j; col[q].i = i-1; q++; } if (i+1 != info->mx-1) { v[q] = - e / s.hx2 + W.x / (2.0 * s.hx); col[q].j = j; col[q].i = i+1; q++; } if (j-1 != 0) { v[q] = - e / s.hy2 - W.y / (2.0 * s.hy); col[q].j = j-1; col[q].i = i; q++; } if (j+1 != info->my-1) { v[q] = - e / s.hy2 + W.y / (2.0 * s.hy); col[q].j = j+1; col[q].i = i; q++; } } ierr = MatSetValuesStencil(Jpre,1,&row,q,col,v,INSERT_VALUES); 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); } return 0; }
/* FormJacobianLocal - Evaluates Jacobian matrix on local process patch */ PetscErrorCode FormJacobianLocal(DMDALocalInfo *info,PetscScalar **x,Mat A,Mat jac, MatStructure *str,ObsCtx *user) { PetscErrorCode ierr; PetscInt i,j; MatStencil col[5],row; PetscReal v[5],dx,dy,oxx,oyy; PetscFunctionBeginUser; dx = 4.0 / (PetscReal)(info->mx-1); dy = 4.0 / (PetscReal)(info->my-1); oxx = 1.0 / (dx * dx); oyy = 1.0 / (dy * dy); for (j=info->ys; j<info->ys+info->ym; j++) { for (i=info->xs; i<info->xs+info->xm; i++) { row.j = j; row.i = i; if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) { /* boundary */ v[0] = 1.0; ierr = MatSetValuesStencil(jac,1,&row,1,&row,v,INSERT_VALUES);CHKERRQ(ierr); } else { /* interior grid points */ v[0] = -oyy; col[0].j = j - 1; col[0].i = i; v[1] = -oxx; col[1].j = j; col[1].i = i - 1; v[2] = 2.0 * (oxx + oyy); col[2].j = j; col[2].i = i; v[3] = -oxx; col[3].j = j; col[3].i = i + 1; v[4] = -oyy; col[4].j = j + 1; col[4].i = i; ierr = MatSetValuesStencil(jac,1,&row,5,col,v,INSERT_VALUES);CHKERRQ(ierr); } } } /* Assemble matrix, using the 2-step process: */ ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); if (A != jac) { ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } *str = SAME_NONZERO_PATTERN; /* Tell the matrix we will never add a new nonzero location to the matrix. If we do, it will generate an error. */ ierr = MatSetOption(jac,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); ierr = PetscLogFlops(2.0*info->ym*info->xm);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode apply_dirichlet_3d(ef_bc *bc, Mat A, DM da) { PetscErrorCode ierr; PetscInt i,j,k,cnt; PetscInt ngx, ngy, ngz; PetscScalar v[7]; MatStencil row, col[7]; PetscInt level; ef_patch *patch = bc->patch; ierr = DMGetCoarsenLevel(da, &level);CHKERRQ(ierr); ierr = DMDAGetInfo(da, 0, &ngx, &ngy, &ngz,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); v[0] = 1.0; for (k = patch->corners[level].is[2]; k <= patch->corners[level].ie[2]; k++) { 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++) { row.i = i; row.j = j; row.k = k; col[0].i = i; col[0].j = j; col[0].k = k; cnt = 1; if (i != 0) { col[cnt].i = i-1; col[cnt].j = j; col[cnt].k = k; v[cnt] = 0; cnt++; } if (j != 0) { col[cnt].i = i; col[cnt].j = j-1; col[cnt].k = k; v[cnt] = 0; cnt++; } if (k != 0) { col[cnt].i = i; col[cnt].j = j; col[cnt].k = k-1; v[cnt] = 0; cnt++; } if (i != ngx - 1) { col[cnt].i = i+1; col[cnt].j = j; col[cnt].k = k; v[cnt] = 0; cnt++; } if (j != ngy - 1) { col[cnt].i = i; col[cnt].j = j+1; col[cnt].k = k; v[cnt] = 0; cnt++; } if (k != ngz - 1) { col[cnt].i = i; col[cnt].j = j; col[cnt].k = k+1; v[cnt] = 0; cnt++; } ierr = MatSetValuesStencil(A, 1, &row, cnt, col, v, INSERT_VALUES);CHKERRQ(ierr); } } } return 0; }
/* FormJacobianLocal - Evaluates Jacobian matrix on local process patch */ PetscErrorCode FormJacobianLocal(DMDALocalInfo *info,PetscScalar **x,Mat A,Mat jac, ObsCtx *user) { PetscErrorCode ierr; PetscInt i,j; MatStencil col[5],row; PetscReal v[5],dx,dy,oxx,oyy; PetscFunctionBeginUser; dx = 4.0 / (PetscReal)(info->mx-1); dy = 4.0 / (PetscReal)(info->my-1); oxx = dy / dx; oyy = dx / dy; for (j=info->ys; j<info->ys+info->ym; j++) { for (i=info->xs; i<info->xs+info->xm; i++) { row.j = j; row.i = i; if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) { /* boundary */ v[0] = 4.0; ierr = MatSetValuesStencil(jac,1,&row,1,&row,v,INSERT_VALUES);CHKERRQ(ierr); } else { /* interior grid points */ v[0] = -oyy; col[0].j = j - 1; col[0].i = i; v[1] = -oxx; col[1].j = j; col[1].i = i - 1; v[2] = 2.0 * (oxx + oyy); col[2].j = j; col[2].i = i; v[3] = -oxx; col[3].j = j; col[3].i = i + 1; v[4] = -oyy; col[4].j = j + 1; col[4].i = i; ierr = MatSetValuesStencil(jac,1,&row,5,col,v,INSERT_VALUES);CHKERRQ(ierr); } } } /* Assemble matrix, using the 2-step process: */ ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); if (A != jac) { ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } ierr = PetscLogFlops(2.0*info->ym*info->xm);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode ComputeMatrix(KSP ksp,Mat jac,Mat B,MatStructure *stflg,void *ctx) { DM da; PetscErrorCode ierr; PetscInt i,j,k,mx,my,mz,xm,ym,zm,xs,ys,zs; PetscScalar v[7],Hx,Hy,Hz,HxHydHz,HyHzdHx,HxHzdHy; MatStencil row,col[7]; PetscFunctionBeginUser; ierr = KSPGetDM(ksp,&da);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&mx,&my,&mz,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); 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 = 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) { v[0] = 2.0*(HxHydHz + HxHzdHy + HyHzdHx); ierr = MatSetValuesStencil(B,1,&row,1,&row,v,INSERT_VALUES);CHKERRQ(ierr); } else { v[0] = -HxHydHz;col[0].i = i; col[0].j = j; col[0].k = k-1; v[1] = -HxHzdHy;col[1].i = i; col[1].j = j-1; col[1].k = k; v[2] = -HyHzdHx;col[2].i = i-1; col[2].j = j; col[2].k = k; v[3] = 2.0*(HxHydHz + HxHzdHy + HyHzdHx);col[3].i = row.i; col[3].j = row.j; col[3].k = row.k; v[4] = -HyHzdHx;col[4].i = i+1; col[4].j = j; col[4].k = k; v[5] = -HxHzdHy;col[5].i = i; col[5].j = j+1; col[5].k = k; v[6] = -HxHydHz;col[6].i = i; col[6].j = j; col[6].k = k+1; ierr = MatSetValuesStencil(B,1,&row,7,col,v,INSERT_VALUES);CHKERRQ(ierr); } } } } ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); *stflg = SAME_NONZERO_PATTERN; PetscFunctionReturn(0); }
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,c1pos,c1neg,c3pos,c3neg; 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++) { PetscInt nc = 0; xi = coors[j][i].x; yi = coors[j][i].y; row.i = i; row.j = j; c1 = (yi-user->ws)/user->dx; c1pos = PetscMax(c1,0); c1neg = PetscMin(c1,0); c3 = (user->ws/(2.0*user->H))*(user->PM_min - user->Pmax*sin(xi))/user->dy; c3pos = PetscMax(c3,0); c3neg = PetscMin(c3,0); 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++] = c1pos; col[nc].i = i+1; col[nc].j = j; val[nc++] = -c1neg; col[nc].i = i; col[nc].j = j-1; val[nc++] = c3pos + c5; col[nc].i = i; col[nc].j = j+1; val[nc++] = -c3neg + c5; col[nc].i = i; col[nc].j = j; val[nc++] = -c1pos + c1neg -c3pos + c3neg -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 FormIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal a,Mat *J,Mat *Jpre,MatStructure *str,void *ctx) { PetscErrorCode ierr; PetscInt i,rstart,rend,Mx; PetscReal hx,sx; AppCtx *user = (AppCtx*)ctx; DM da; MatStencil col[3],row; PetscInt nc; PetscScalar vals[3]; PetscFunctionBegin; ierr = TSGetDM(ts,&da);CHKERRQ(ierr); ierr = MatGetOwnershipRange(*Jpre,&rstart,&rend);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); for (i=rstart; i<rend; i++) { nc = 0; row.i = i; if (user->boundary == 0 && (i == 0 || i == Mx-1)) { col[nc].i = i; vals[nc++] = 1.0; } else if (user->boundary > 0 && i == 0) { /* Left Neumann */ col[nc].i = i; vals[nc++] = 1.0; col[nc].i = i+1; vals[nc++] = -1.0; } else if (user->boundary > 0 && i == Mx-1) { /* Right Neumann */ col[nc].i = i-1; vals[nc++] = -1.0; col[nc].i = i; vals[nc++] = 1.0; } else { /* Interior */ col[nc].i = i-1; vals[nc++] = -1.0*sx; col[nc].i = i; vals[nc++] = 2.0*sx + a; col[nc].i = i+1; vals[nc++] = -1.0*sx; } ierr = MatSetValuesStencil(*Jpre,1,&row,nc,col,vals,INSERT_VALUES);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); } if (user->viewJacobian){ ierr = PetscPrintf(((PetscObject)*Jpre)->comm,"Jpre:\n");CHKERRQ(ierr); ierr = MatView(*Jpre,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); } PetscFunctionReturn(0); }
// in system form F(t,Y,dot Y) = G(t,Y), compute combined/shifted // Jacobian of F(): // J = (shift) dF/d(dot Y) + dF/dY //IJACOBIAN PetscErrorCode FormIJacobianLocal(DMDALocalInfo *info, double t, Field **aY, Field **aYdot, double shift, Mat J, Mat P, PatternCtx *user) { PetscErrorCode ierr; int i, j, s, c; const double h = user->L / (double)(info->mx), Cu = user->Du / (6.0 * h * h), Cv = user->Dv / (6.0 * h * h); double val[9], CC; MatStencil col[9], row; for (j = info->ys; j < info->ys + info->ym; j++) { row.j = j; for (i = info->xs; i < info->xs + info->xm; i++) { row.i = i; for (c = 0; c < 2; c++) { // u,v equations are c=0,1 row.c = c; CC = (c == 0) ? Cu : Cv; for (s = 0; s < 9; s++) col[s].c = c; col[0].i = i; col[0].j = j; val[0] = shift + 20.0 * CC; col[1].i = i-1; col[1].j = j; val[1] = - 4.0 * CC; col[2].i = i+1; col[2].j = j; val[2] = - 4.0 * CC; col[3].i = i; col[3].j = j-1; val[3] = - 4.0 * CC; col[4].i = i; col[4].j = j+1; val[4] = - 4.0 * CC; col[5].i = i-1; col[5].j = j-1; val[5] = - CC; col[6].i = i-1; col[6].j = j+1; val[6] = - CC; col[7].i = i+1; col[7].j = j-1; val[7] = - CC; col[8].i = i+1; col[8].j = j+1; val[8] = - CC; ierr = MatSetValuesStencil(P,1,&row,9,col,val,INSERT_VALUES); CHKERRQ(ierr); } } } ierr = MatAssemblyBegin(P,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(P,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); if (J != P) { ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); } return 0; }
/* RHSJacobian - User-provided routine to compute the Jacobian of the nonlinear right-hand-side function of the ODE. Input Parameters: ts - the TS context t - current time U - global input vector dummy - optional user-defined context, as set by TSetRHSJacobian() Output Parameters: J - Jacobian matrix Jpre - optionally different preconditioning matrix str - flag indicating matrix structure */ PetscErrorCode RHSJacobian(TS ts,PetscReal t,Vec U,Mat *J,Mat *Jpre,MatStructure *str,void *ctx) { PetscErrorCode ierr; DM da; DMDALocalInfo info; PetscInt i,j; PetscReal hx,hy,sx,sy; PetscFunctionBeginUser; ierr = TSGetDM(ts,&da);CHKERRQ(ierr); ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); hx = 1.0/(PetscReal)(info.mx-1); sx = 1.0/(hx*hx); hy = 1.0/(PetscReal)(info.my-1); sy = 1.0/(hy*hy); for (j=info.ys; j<info.ys+info.ym; j++) { for (i=info.xs; i<info.xs+info.xm; i++) { PetscInt nc = 0; MatStencil row,col[5]; PetscScalar val[5]; row.i = i; row.j = j; if (i == 0 || j == 0 || i == info.mx-1 || j == info.my-1) { col[nc].i = i; col[nc].j = j; val[nc++] = 1.0; } else { col[nc].i = i-1; col[nc].j = j; val[nc++] = sx; col[nc].i = i+1; col[nc].j = j; val[nc++] = sx; col[nc].i = i; col[nc].j = j-1; val[nc++] = sy; col[nc].i = i; col[nc].j = j+1; val[nc++] = sy; col[nc].i = i; col[nc].j = j; val[nc++] = -2*sx - 2*sy; } ierr = MatSetValuesStencil(*Jpre,1,&row,nc,col,val,INSERT_VALUES);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); }
/* FormJacobian - Evaluates Jacobian matrix. Input Parameters: . snes - the SNES context . x - input vector . dummy - optional user-defined context (not used here) Output Parameters: . jac - Jacobian matrix . B - optionally different preconditioning matrix . flag - flag indicating matrix structure */ PetscErrorCode FormJacobian(SNES snes,Vec x,Mat jac,Mat B,void *ctx) { PetscScalar *xx,A[3]; PetscErrorCode ierr; PetscInt i,M,xs,xm; DM da = (DM) ctx; MatStencil row,cols[3]; PetscReal h; PetscFunctionBeginUser; /* Get pointer to vector data */ ierr = DMDAVecGetArrayRead(da,x,&xx);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr); /* Get range of locally owned matrix */ ierr = DMDAGetInfo(da,NULL,&M,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); ierr = MatZeroEntries(jac);CHKERRQ(ierr); h = 1.0/M; /* because of periodic boundary conditions we can simply loop over all local nodes and access to the left and right */ for (i=xs; i<xs+xm; i++) { row.i = i; cols[0].i = i - 1; cols[1].i = i; cols[2].i = i + 1; A[0] = A[2] = 1.0/(h*h); A[1] = -2.0/(h*h); ierr = MatSetValuesStencil(jac,1,&row,3,cols,A,ADD_VALUES);CHKERRQ(ierr); } ierr = DMDAVecRestoreArrayRead(da,x,&xx);CHKERRQ(ierr); ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 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 = (AppCtx*) ptr; Mat H = *tH; PetscErrorCode ierr; PetscInt i,j,k; PetscInt mx=user->mx, my=user->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; PetscScalar *top,*bottom,*left,*right; PetscFunctionBeginUser; /* Set various matrix options */ ierr = MatAssembled(H,&assembled);CHKERRQ(ierr); if (assembled) {ierr = MatZeroEntries(H);CHKERRQ(ierr);} *flag=SAME_NONZERO_PATTERN; /* Get local vectors */ ierr = DMGetLocalVector(user->da,&localX);CHKERRQ(ierr); ierr = VecGetArray(user->Top,&top);CHKERRQ(ierr); ierr = VecGetArray(user->Bottom,&bottom);CHKERRQ(ierr); ierr = VecGetArray(user->Left,&left);CHKERRQ(ierr); ierr = VecGetArray(user->Right,&right);CHKERRQ(ierr); /* Get ghost points */ ierr = DMGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX);CHKERRQ(ierr); /* Get pointers to vector data */ ierr = DMDAVecGetArray(user->da,localX, &x);CHKERRQ(ierr); ierr = DMDAGetCorners(user->da,&xs,&ys,NULL,&xm,&ym,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 = left[j+1]; xlt = left[j+2]; } else xl = x[j][i-1]; /* Bottom */ if (j==0) { xb = bottom[i+1]; xrb = bottom[i+2]; } else xb = x[j-1][i]; /* Right */ if (i+1 == mx) { xr = right[j+1]; xrb = right[j]; } else xr = x[j][i+1]; /* Top */ if (j+1==my) { xt = top[i+1]; xlt = 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 = PetscSqrtReal(1.0 + d1*d1 + d7*d7); f2 = PetscSqrtReal(1.0 + d1*d1 + d4*d4); f3 = PetscSqrtReal(1.0 + d3*d3 + d8*d8); f4 = PetscSqrtReal(1.0 + d3*d3 + d2*d2); f5 = PetscSqrtReal(1.0 + d2*d2 + d5*d5); f6 = PetscSqrtReal(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*d1*d4)/(f2*f2*f2) + (hxdhy*(1.0+d2*d2)+hydhx*(1.0+d3*d3)-2*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); } } ierr = VecRestoreArray(user->Left,&left);CHKERRQ(ierr); ierr = VecRestoreArray(user->Top,&top);CHKERRQ(ierr); ierr = VecRestoreArray(user->Bottom,&bottom);CHKERRQ(ierr); ierr = VecRestoreArray(user->Right,&right);CHKERRQ(ierr); /* Assemble the matrix */ ierr = MatAssemblyBegin(H,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(user->da,localX,&x);CHKERRQ(ierr); ierr = MatAssemblyEnd(H,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = DMRestoreLocalVector(user->da,&localX);CHKERRQ(ierr); ierr = PetscLogFlops(199*mx*my);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* QuadraticH - Evaluates Hessian matrix. Input Parameters: . user - user-defined context, as set by TaoSetHessian() . X - input vector Output Parameter: . H - Hessian matrix */ int QuadraticH(AppCtx *user, Vec X, Mat Hessian) { int info; PetscInt i,j,k; PetscInt mx=user->mx, my=user->my; PetscInt xs,xm,gxs,gxm,ys,ym,gys,gym; double hx=1.0/(mx+1), hy=1.0/(my+1), hydhx=hy/hx, hxdhy=hx/hy; double f1,f2,f3,f4,f5,f6,d1,d2,d3,d4,d5,d6,d7,d8,xc,xl,xr,xt,xb,xlt,xrb; double hl,hr,ht,hb,hc,htl,hbr; PetscScalar **x, v[7]; MatStencil col[7],row; Vec localX; PetscTruth assembled; /* Get local mesh boundaries */ info = DAGetLocalVector(user->da,&localX);CHKERRQ(info); info = DAGetCorners(user->da,&xs,&ys,PETSC_NULL,&xm,&ym,PETSC_NULL); CHKERRQ(info); info = DAGetGhostCorners(user->da,&gxs,&gys,PETSC_NULL,&gxm,&gym,PETSC_NULL); CHKERRQ(info); /* Scatter ghost points to local vector */ info = DAGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); info = DAGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); /* Get pointers to vector data */ info = DAVecGetArray(user->da,localX,(void**)&x); /* Initialize matrix entries to zero */ info = MatAssembled(Hessian,&assembled); CHKERRQ(info); if (assembled){info = MatZeroEntries(Hessian); CHKERRQ(info);} /* Set various matrix options */ info = MatSetOption(Hessian,MAT_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE); CHKERRQ(info); /* Compute Hessian 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 side */ if (i==0){ xl = user->left[j-ys+1]; xlt = user->left[j-ys+2]; } else { xl = x[j][i-1]; } if (j==0){ xb = user->bottom[i-xs+1]; xrb = user->bottom[i-xs+2]; } else { xb = x[j-1][i]; } if (i+1 == mx){ xr = user->right[j-ys+1]; xrb = user->right[j-ys]; } else { xr = x[j][i+1]; } if (j+1==my){ xt = user->top[i-xs+1]; xlt = user->top[i-xs]; }else { xt = x[j+1][i]; } if (i>0 && j+1<my){ xlt = x[j+1][i-1]; } 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*d1*d4)/(f2*f2*f2) + (hxdhy*(1.0+d2*d2)+hydhx*(1.0+d3*d3)-2*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; row.j = j; row.i = i; k=0; if (j>0){ v[k]=hb; col[k].j = j - 1; col[k].i = i; k++; } if (j>0 && i < mx -1){ v[k]=hbr; col[k].j = j - 1; col[k].i = i+1; k++; } if (i>0){ v[k]= hl; col[k].j = j; col[k].i = i-1; k++; } v[k]= hc; col[k].j = j; col[k].i = i; k++; if (i < mx-1 ){ v[k]= hr; col[k].j = j; col[k].i = i+1; k++; } if (i>0 && j < my-1 ){ v[k]= htl; col[k].j = j+1; col[k].i = i-1; k++; } if (j < my-1 ){ v[k]= ht; col[k].j = j+1; col[k].i = i; k++; } /* Set matrix values using local numbering, which was defined earlier, in the main routine. */ info = MatSetValuesStencil(Hessian,1,&row,k,col,v,INSERT_VALUES); CHKERRQ(info); } } /* Restore vectors */ info = DAVecRestoreArray(user->da,localX,(void**)&x); info = DARestoreLocalVector(user->da,&localX); CHKERRQ(info); /* Assemble the matrix */ info = MatAssemblyBegin(Hessian,MAT_FINAL_ASSEMBLY); CHKERRQ(info); info = MatAssemblyEnd(Hessian,MAT_FINAL_ASSEMBLY); CHKERRQ(info); info = PetscLogFlops(199*xm*ym); CHKERRQ(info); return 0; }
int main(int argc,char **argv) { DM da; /* distributed array */ Vec x,b,u; /* approx solution, RHS, exact solution */ Mat A; /* linear system matrix */ KSP ksp; /* linear solver context */ PetscRandom rctx; /* random number generator context */ PetscReal norm; /* norm of solution error */ PetscInt i,j,its; PetscErrorCode ierr; PetscBool flg = PETSC_FALSE; PetscLogStage stage; DMDALocalInfo info; ierr = PetscInitialize(&argc,&argv,(char*)0,help);CHKERRQ(ierr); /* Create distributed array to handle parallel distribution. The problem size will default to 8 by 7, but this can be changed using -da_grid_x M -da_grid_y N */ ierr = DMDACreate2d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE,DMDA_STENCIL_STAR,-8,-7,PETSC_DECIDE,PETSC_DECIDE,1,1,NULL,NULL,&da);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Compute the matrix and right-hand-side vector that define the linear system, Ax = b. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Create parallel matrix preallocated according to the DMDA, format AIJ by default. To use symmetric storage, run with -dm_mat_type sbaij -mat_ignore_lower_triangular */ ierr = DMSetMatType(da,MATAIJ);CHKERRQ(ierr); ierr = DMCreateMatrix(da,&A);CHKERRQ(ierr); /* Set matrix elements for the 2-D, five-point stencil in parallel. - Each processor needs to insert only elements that it owns locally (but any non-local elements will be sent to the appropriate processor during matrix assembly). - Rows and columns are specified by the stencil - Entries are normalized for a domain [0,1]x[0,1] */ ierr = PetscLogStageRegister("Assembly", &stage);CHKERRQ(ierr); ierr = PetscLogStagePush(stage);CHKERRQ(ierr); ierr = DMDAGetLocalInfo(da,&info);CHKERRQ(ierr); for (j=info.ys; j<info.ys+info.ym; j++) { for (i=info.xs; i<info.xs+info.xm; i++) { PetscReal hx = 1./info.mx,hy = 1./info.my; MatStencil row = {0},col[5] = {{0}}; PetscScalar v[5]; PetscInt ncols = 0; row.j = j; row.i = i; col[ncols].j = j; col[ncols].i = i; v[ncols++] = 2*(hx/hy + hy/hx); /* boundaries */ if (i>0) {col[ncols].j = j; col[ncols].i = i-1; v[ncols++] = -hy/hx;} if (i<info.mx-1) {col[ncols].j = j; col[ncols].i = i+1; v[ncols++] = -hy/hx;} if (j>0) {col[ncols].j = j-1; col[ncols].i = i; v[ncols++] = -hx/hy;} if (j<info.my-1) {col[ncols].j = j+1; col[ncols].i = i; v[ncols++] = -hx/hy;} ierr = MatSetValuesStencil(A,1,&row,ncols,col,v,INSERT_VALUES);CHKERRQ(ierr); } } /* Assemble matrix, using the 2-step process: MatAssemblyBegin(), MatAssemblyEnd() Computations can be done while messages are in transition by placing code between these two statements. */ ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = PetscLogStagePop();CHKERRQ(ierr); /* Create parallel vectors compatible with the DMDA. */ ierr = DMCreateGlobalVector(da,&u);CHKERRQ(ierr); ierr = VecDuplicate(u,&b);CHKERRQ(ierr); ierr = VecDuplicate(u,&x);CHKERRQ(ierr); /* Set exact solution; then compute right-hand-side vector. By default we use an exact solution of a vector with all elements of 1.0; Alternatively, using the runtime option -random_sol forms a solution vector with random components. */ ierr = PetscOptionsGetBool(NULL,"-random_exact_sol",&flg,NULL);CHKERRQ(ierr); if (flg) { ierr = PetscRandomCreate(PETSC_COMM_WORLD,&rctx);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr); ierr = VecSetRandom(u,rctx);CHKERRQ(ierr); ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr); } else { ierr = VecSet(u,1.);CHKERRQ(ierr); } ierr = MatMult(A,u,b);CHKERRQ(ierr); /* View the exact solution vector if desired */ flg = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,"-view_exact_sol",&flg,NULL);CHKERRQ(ierr); if (flg) {ierr = VecView(u,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);} /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create the linear solver and set various options - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Create linear solver context */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); /* Set operators. Here the matrix that defines the linear system also serves as the preconditioning matrix. */ ierr = KSPSetOperators(ksp,A,A);CHKERRQ(ierr); /* Set runtime options, e.g., -ksp_type <type> -pc_type <type> -ksp_monitor -ksp_rtol <rtol> These options will override those specified above as long as KSPSetFromOptions() is called _after_ any other customization routines. */ ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Solve the linear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Check solution and clean up - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Check the error */ ierr = VecAXPY(x,-1.,u);CHKERRQ(ierr); ierr = VecNorm(x,NORM_2,&norm);CHKERRQ(ierr); ierr = KSPGetIterationNumber(ksp,&its);CHKERRQ(ierr); /* Print convergence information. PetscPrintf() produces a single print statement from all processes that share a communicator. An alternative is PetscFPrintf(), which prints to a file. */ ierr = PetscPrintf(PETSC_COMM_WORLD,"Norm of error %g iterations %D\n",(double)norm,its);CHKERRQ(ierr); /* Free work space. All PETSc objects should be destroyed when they are no longer needed. */ ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); /* Always call PetscFinalize() before exiting a program. This routine - finalizes the PETSc libraries as well as MPI - provides summary and diagnostic information if certain runtime options are chosen (e.g., -log_summary). */ ierr = PetscFinalize(); return 0; }
int main(int Argc,char **Args) { PetscBool flg; PetscInt n = -6; PetscScalar rho = 1.0; PetscReal h; PetscReal beta = 1.0; DM da; PetscRandom rctx; PetscMPIInt comm_size; Mat H,HtH; PetscInt x, y, xs, ys, xm, ym; PetscReal r1, r2; PetscScalar uxy1, uxy2; MatStencil sxy, sxy_m; PetscScalar val, valconj; Vec b, Htb,xvec; KSP kspmg; PC pcmg; PetscErrorCode ierr; PetscInt ix[1] = {0}; PetscScalar vals[1] = {1.0}; PetscInitialize(&Argc,&Args,(char*)0,help); ierr = PetscOptionsGetInt(NULL,"-size",&n,&flg);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,"-beta",&beta,&flg);CHKERRQ(ierr); ierr = PetscOptionsGetScalar(NULL,"-rho",&rho,&flg);CHKERRQ(ierr); /* Set the fudge parameters, we scale the whole thing by 1/(2*h) later */ h = 1.; rho *= 1./(2.*h); /* Geometry info */ ierr = DMDACreate2d(PETSC_COMM_WORLD, DMDA_BOUNDARY_PERIODIC,DMDA_BOUNDARY_PERIODIC, DMDA_STENCIL_STAR, n, n, PETSC_DECIDE, PETSC_DECIDE, 2 /* this is the # of dof's */, 1, NULL, NULL, &da);CHKERRQ(ierr); /* Random numbers */ ierr = PetscRandomCreate(PETSC_COMM_WORLD,&rctx);CHKERRQ(ierr); ierr = PetscRandomSetFromOptions(rctx);CHKERRQ(ierr); /* Single or multi processor ? */ ierr = MPI_Comm_size(PETSC_COMM_WORLD,&comm_size);CHKERRQ(ierr); /* construct matrix */ ierr = DMSetMatType(da,MATAIJ);CHKERRQ(ierr); ierr = DMCreateMatrix(da, &H);CHKERRQ(ierr); /* get local corners for this processor */ ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); /* Assemble the matrix */ for (x=xs; x<xs+xm; x++) { for (y=ys; y<ys+ym; y++) { /* each lattice point sets only the *forward* pointing parameters (right, down), i.e. Nabla_1^+ and Nabla_2^+. In this way we can use only local random number creation. That means we also have to set the corresponding backward pointing entries. */ /* Compute some normally distributed random numbers via Box-Muller */ ierr = PetscRandomGetValueReal(rctx, &r1);CHKERRQ(ierr); r1 = 1.-r1; /* to change from [0,1) to (0,1], which we need for the log */ ierr = PetscRandomGetValueReal(rctx, &r2);CHKERRQ(ierr); PetscReal R = PetscSqrtReal(-2.*PetscLogReal(r1)); PetscReal c = PetscCosReal(2.*PETSC_PI*r2); PetscReal s = PetscSinReal(2.*PETSC_PI*r2); /* use those to set the field */ uxy1 = PetscExpScalar(((PetscScalar) (R*c/beta))*PETSC_i); uxy2 = PetscExpScalar(((PetscScalar) (R*s/beta))*PETSC_i); sxy.i = x; sxy.j = y; /* the point where we are */ /* center action */ sxy.c = 0; /* spin 0, 0 */ ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy, &rho, ADD_VALUES);CHKERRQ(ierr); sxy.c = 1; /* spin 1, 1 */ val = -rho; ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); sxy_m.i = x+1; sxy_m.j = y; /* right action */ sxy.c = 0; sxy_m.c = 0; /* spin 0, 0 */ val = -uxy1; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy.c = 0; sxy_m.c = 1; /* spin 0, 1 */ val = -uxy1; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy.c = 1; sxy_m.c = 0; /* spin 1, 0 */ val = uxy1; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy.c = 1; sxy_m.c = 1; /* spin 1, 1 */ val = uxy1; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy_m.i = x; sxy_m.j = y+1; /* down action */ sxy.c = 0; sxy_m.c = 0; /* spin 0, 0 */ val = -uxy2; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy.c = 0; sxy_m.c = 1; /* spin 0, 1 */ val = -PETSC_i*uxy2; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy.c = 1; sxy_m.c = 0; /* spin 1, 0 */ val = -PETSC_i*uxy2; valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); sxy.c = 1; sxy_m.c = 1; /* spin 1, 1 */ val = PetscConj(uxy2); valconj = PetscConj(val); ierr = MatSetValuesStencil(H, 1, &sxy_m, 1, &sxy, &val, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesStencil(H, 1, &sxy, 1, &sxy_m, &valconj, ADD_VALUES);CHKERRQ(ierr); } } ierr = MatAssemblyBegin(H, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(H, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* scale H */ ierr = MatScale(H, 1./(2.*h));CHKERRQ(ierr); /* it looks like H is Hermetian */ /* construct normal equations */ ierr = MatMatMult(H, H, MAT_INITIAL_MATRIX, 1., &HtH);CHKERRQ(ierr); /* permutation matrix to check whether H and HtH are identical to the ones in the paper */ /* Mat perm; */ /* ierr = DMCreateMatrix(da, &perm);CHKERRQ(ierr); */ /* PetscInt row, col; */ /* PetscScalar one = 1.0; */ /* for (PetscInt i=0; i<n; i++) { */ /* for (PetscInt j=0; j<n; j++) { */ /* row = (i*n+j)*2; col = i*n+j; */ /* ierr = MatSetValues(perm, 1, &row, 1, &col, &one, INSERT_VALUES);CHKERRQ(ierr); */ /* row = (i*n+j)*2+1; col = i*n+j + n*n; */ /* ierr = MatSetValues(perm, 1, &row, 1, &col, &one, INSERT_VALUES);CHKERRQ(ierr); */ /* } */ /* } */ /* ierr = MatAssemblyBegin(perm, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); */ /* ierr = MatAssemblyEnd(perm, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); */ /* Mat Hperm; */ /* ierr = MatPtAP(H, perm, MAT_INITIAL_MATRIX, 1.0, &Hperm);CHKERRQ(ierr); */ /* ierr = PetscPrintf(PETSC_COMM_WORLD, "Matrix H after construction\n");CHKERRQ(ierr); */ /* ierr = MatView(Hperm, PETSC_VIEWER_STDOUT_(PETSC_COMM_WORLD));CHKERRQ(ierr); */ /* Mat HtHperm; */ /* ierr = MatPtAP(HtH, perm, MAT_INITIAL_MATRIX, 1.0, &HtHperm);CHKERRQ(ierr); */ /* ierr = PetscPrintf(PETSC_COMM_WORLD, "Matrix HtH:\n");CHKERRQ(ierr); */ /* ierr = MatView(HtHperm, PETSC_VIEWER_STDOUT_(PETSC_COMM_WORLD));CHKERRQ(ierr); */ /* right hand side */ ierr = DMCreateGlobalVector(da, &b);CHKERRQ(ierr); ierr = VecSet(b,0.0);CHKERRQ(ierr); ierr = VecSetValues(b, 1, ix, vals, INSERT_VALUES);CHKERRQ(ierr); ierr = VecAssemblyBegin(b);CHKERRQ(ierr); ierr = VecAssemblyEnd(b);CHKERRQ(ierr); /* ierr = VecSetRandom(b, rctx);CHKERRQ(ierr); */ ierr = VecDuplicate(b, &Htb);CHKERRQ(ierr); ierr = MatMultTranspose(H, b, Htb);CHKERRQ(ierr); /* construct solver */ ierr = KSPCreate(PETSC_COMM_WORLD,&kspmg);CHKERRQ(ierr); ierr = KSPSetType(kspmg, KSPCG);CHKERRQ(ierr); ierr = KSPGetPC(kspmg,&pcmg);CHKERRQ(ierr); ierr = PCSetType(pcmg,PCASA);CHKERRQ(ierr); /* maybe user wants to override some of the choices */ ierr = KSPSetFromOptions(kspmg);CHKERRQ(ierr); ierr = KSPSetOperators(kspmg, HtH, HtH, DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = DMDASetRefinementFactor(da, 3, 3, 3);CHKERRQ(ierr); ierr = PCSetDM(pcmg,da);CHKERRQ(ierr); ierr = PCASASetTolerances(pcmg, 1.e-6, 1.e-10,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); ierr = VecDuplicate(b, &xvec);CHKERRQ(ierr); ierr = VecSet(xvec, 0.0);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Solve the linear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = KSPSolve(kspmg, Htb, xvec);CHKERRQ(ierr); /* ierr = VecView(xvec, PETSC_VIEWER_STDOUT_(PETSC_COMM_WORLD));CHKERRQ(ierr); */ ierr = KSPDestroy(&kspmg);CHKERRQ(ierr); ierr = VecDestroy(&xvec);CHKERRQ(ierr); /* seems to be destroyed by KSPDestroy */ ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = VecDestroy(&Htb);CHKERRQ(ierr); ierr = MatDestroy(&HtH);CHKERRQ(ierr); ierr = MatDestroy(&H);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
PetscErrorCode ComputeMatrix(KSP ksp, Mat J,Mat jac, void *ctx) { PetscErrorCode ierr; PetscInt i,j,k,mx,my,mz,xm,ym,zm,xs,ys,zs,num, numi, numj, numk; PetscScalar v[7],Hx,Hy,Hz,HyHzdHx,HxHzdHy,HxHydHz; MatStencil row, col[7]; DM da; MatNullSpace nullspace; PetscFunctionBeginUser; ierr = KSPGetDM(ksp,&da);CHKERRQ(ierr); ierr = DMDAGetInfo(da,0,&mx,&my,&mz,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); Hx = 1.0 / (PetscReal)(mx); Hy = 1.0 / (PetscReal)(my); Hz = 1.0 / (PetscReal)(mz); HyHzdHx = Hy*Hz/Hx; HxHzdHy = Hx*Hz/Hy; HxHydHz = Hx*Hy/Hz; 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) { num = 0; numi=0; numj=0; numk=0; if (k!=0) { v[num] = -HxHydHz; col[num].i = i; col[num].j = j; col[num].k = k-1; num++; numk++; } if (j!=0) { v[num] = -HxHzdHy; col[num].i = i; col[num].j = j-1; col[num].k = k; num++; numj++; } if (i!=0) { v[num] = -HyHzdHx; col[num].i = i-1; col[num].j = j; col[num].k = k; num++; numi++; } if (i!=mx-1) { v[num] = -HyHzdHx; col[num].i = i+1; col[num].j = j; col[num].k = k; num++; numi++; } if (j!=my-1) { v[num] = -HxHzdHy; col[num].i = i; col[num].j = j+1; col[num].k = k; num++; numj++; } if (k!=mz-1) { v[num] = -HxHydHz; col[num].i = i; col[num].j = j; col[num].k = k+1; num++; numk++; } v[num] = (PetscReal)(numk)*HxHydHz + (PetscReal)(numj)*HxHzdHy + (PetscReal)(numi)*HyHzdHx; col[num].i = i; col[num].j = j; col[num].k = k; num++; ierr = MatSetValuesStencil(jac,1,&row,num,col,v,INSERT_VALUES);CHKERRQ(ierr); } else { v[0] = -HxHydHz; col[0].i = i; col[0].j = j; col[0].k = k-1; v[1] = -HxHzdHy; col[1].i = i; col[1].j = j-1; col[1].k = k; v[2] = -HyHzdHx; col[2].i = i-1; col[2].j = j; col[2].k = k; v[3] = 2.0*(HyHzdHx + HxHzdHy + HxHydHz); col[3].i = i; col[3].j = j; col[3].k = k; v[4] = -HyHzdHx; col[4].i = i+1; col[4].j = j; col[4].k = k; v[5] = -HxHzdHy; col[5].i = i; col[5].j = j+1; col[5].k = k; v[6] = -HxHydHz; col[6].i = i; col[6].j = j; col[6].k = k+1; ierr = MatSetValuesStencil(jac,1,&row,7,col,v,INSERT_VALUES);CHKERRQ(ierr); } } } } ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,&nullspace);CHKERRQ(ierr); ierr = MatSetNullSpace(jac,nullspace);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullspace);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FormJacobian(SNES snes,Vec X,Mat jac,Mat B,void *ptr) { AppCtx *user = (AppCtx*)ptr; PetscErrorCode ierr; PetscInt i,j,mx,my,xs,ys,xm,ym; PetscScalar one = 1.0,hx,hy,hxdhy,hydhx,t0,tn,ts,te,tw; PetscScalar dn,ds,de,dw,an,as,ae,aw,bn,bs,be,bw,gn,gs,ge,gw; PetscScalar tleft,tright,beta,bm1,coef; PetscScalar v[5],**x; Vec localX; MatStencil col[5],row; DM da; PetscFunctionBeginUser; ierr = SNESGetDM(snes,&da);CHKERRQ(ierr); ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr); ierr = DMDAGetInfo(da,NULL,&mx,&my,0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); hx = one/(PetscReal)(mx-1); hy = one/(PetscReal)(my-1); hxdhy = hx/hy; hydhx = hy/hx; tleft = user->tleft; tright = user->tright; beta = user->beta; bm1 = user->bm1; coef = user->coef; /* Get ghost points */ ierr = DMGlobalToLocalBegin(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(da,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); ierr = DMDAVecGetArray(da,localX,&x);CHKERRQ(ierr); /* Evaluate Jacobian of function */ for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { t0 = x[j][i]; if (i > 0 && i < mx-1 && j > 0 && j < my-1) { /* general interior volume */ tw = x[j][i-1]; aw = 0.5*(t0 + tw); bw = PetscPowScalar(aw,bm1); /* dw = bw * aw */ dw = PetscPowScalar(aw,beta); gw = coef*bw*(t0 - tw); te = x[j][i+1]; ae = 0.5*(t0 + te); be = PetscPowScalar(ae,bm1); /* de = be * ae; */ de = PetscPowScalar(ae,beta); ge = coef*be*(te - t0); ts = x[j-1][i]; as = 0.5*(t0 + ts); bs = PetscPowScalar(as,bm1); /* ds = bs * as; */ ds = PetscPowScalar(as,beta); gs = coef*bs*(t0 - ts); tn = x[j+1][i]; an = 0.5*(t0 + tn); bn = PetscPowScalar(an,bm1); /* dn = bn * an; */ dn = PetscPowScalar(an,beta); gn = coef*bn*(tn - t0); v[0] = -hxdhy*(ds - gs); col[0].j = j-1; col[0].i = i; v[1] = -hydhx*(dw - gw); col[1].j = j; col[1].i = i-1; v[2] = hxdhy*(ds + dn + gs - gn) + hydhx*(dw + de + gw - ge); col[2].j = row.j = j; col[2].i = row.i = i; v[3] = -hydhx*(de + ge); col[3].j = j; col[3].i = i+1; v[4] = -hxdhy*(dn + gn); col[4].j = j+1; col[4].i = i; ierr = MatSetValuesStencil(jac,1,&row,5,col,v,INSERT_VALUES);CHKERRQ(ierr); } else if (i == 0) { /* left-hand boundary */ tw = tleft; aw = 0.5*(t0 + tw); bw = PetscPowScalar(aw,bm1); /* dw = bw * aw */ dw = PetscPowScalar(aw,beta); gw = coef*bw*(t0 - tw); te = x[j][i + 1]; ae = 0.5*(t0 + te); be = PetscPowScalar(ae,bm1); /* de = be * ae; */ de = PetscPowScalar(ae,beta); ge = coef*be*(te - t0); /* left-hand bottom boundary */ if (j == 0) { tn = x[j+1][i]; an = 0.5*(t0 + tn); bn = PetscPowScalar(an,bm1); /* dn = bn * an; */ dn = PetscPowScalar(an,beta); gn = coef*bn*(tn - t0); v[0] = hxdhy*(dn - gn) + hydhx*(dw + de + gw - ge); col[0].j = row.j = j; col[0].i = row.i = i; v[1] = -hydhx*(de + ge); col[1].j = j; col[1].i = i+1; v[2] = -hxdhy*(dn + gn); col[2].j = j+1; col[2].i = i; ierr = MatSetValuesStencil(jac,1,&row,3,col,v,INSERT_VALUES);CHKERRQ(ierr); /* left-hand interior boundary */ } else if (j < my-1) { ts = x[j-1][i]; as = 0.5*(t0 + ts); bs = PetscPowScalar(as,bm1); /* ds = bs * as; */ ds = PetscPowScalar(as,beta); gs = coef*bs*(t0 - ts); tn = x[j+1][i]; an = 0.5*(t0 + tn); bn = PetscPowScalar(an,bm1); /* dn = bn * an; */ dn = PetscPowScalar(an,beta); gn = coef*bn*(tn - t0); v[0] = -hxdhy*(ds - gs); col[0].j = j-1; col[0].i = i; v[1] = hxdhy*(ds + dn + gs - gn) + hydhx*(dw + de + gw - ge); col[1].j = row.j = j; col[1].i = row.i = i; v[2] = -hydhx*(de + ge); col[2].j = j; col[2].i = i+1; v[3] = -hxdhy*(dn + gn); col[3].j = j+1; col[3].i = i; ierr = MatSetValuesStencil(jac,1,&row,4,col,v,INSERT_VALUES);CHKERRQ(ierr); /* left-hand top boundary */ } else { ts = x[j-1][i]; as = 0.5*(t0 + ts); bs = PetscPowScalar(as,bm1); /* ds = bs * as; */ ds = PetscPowScalar(as,beta); gs = coef*bs*(t0 - ts); v[0] = -hxdhy*(ds - gs); col[0].j = j-1; col[0].i = i; v[1] = hxdhy*(ds + gs) + hydhx*(dw + de + gw - ge); col[1].j = row.j = j; col[1].i = row.i = i; v[2] = -hydhx*(de + ge); col[2].j = j; col[2].i = i+1; ierr = MatSetValuesStencil(jac,1,&row,3,col,v,INSERT_VALUES);CHKERRQ(ierr); } } else if (i == mx-1) { /* right-hand boundary */ tw = x[j][i-1]; aw = 0.5*(t0 + tw); bw = PetscPowScalar(aw,bm1); /* dw = bw * aw */ dw = PetscPowScalar(aw,beta); gw = coef*bw*(t0 - tw); te = tright; ae = 0.5*(t0 + te); be = PetscPowScalar(ae,bm1); /* de = be * ae; */ de = PetscPowScalar(ae,beta); ge = coef*be*(te - t0); /* right-hand bottom boundary */ if (j == 0) { tn = x[j+1][i]; an = 0.5*(t0 + tn); bn = PetscPowScalar(an,bm1); /* dn = bn * an; */ dn = PetscPowScalar(an,beta); gn = coef*bn*(tn - t0); v[0] = -hydhx*(dw - gw); col[0].j = j; col[0].i = i-1; v[1] = hxdhy*(dn - gn) + hydhx*(dw + de + gw - ge); col[1].j = row.j = j; col[1].i = row.i = i; v[2] = -hxdhy*(dn + gn); col[2].j = j+1; col[2].i = i; ierr = MatSetValuesStencil(jac,1,&row,3,col,v,INSERT_VALUES);CHKERRQ(ierr); /* right-hand interior boundary */ } else if (j < my-1) { ts = x[j-1][i]; as = 0.5*(t0 + ts); bs = PetscPowScalar(as,bm1); /* ds = bs * as; */ ds = PetscPowScalar(as,beta); gs = coef*bs*(t0 - ts); tn = x[j+1][i]; an = 0.5*(t0 + tn); bn = PetscPowScalar(an,bm1); /* dn = bn * an; */ dn = PetscPowScalar(an,beta); gn = coef*bn*(tn - t0); v[0] = -hxdhy*(ds - gs); col[0].j = j-1; col[0].i = i; v[1] = -hydhx*(dw - gw); col[1].j = j; col[1].i = i-1; v[2] = hxdhy*(ds + dn + gs - gn) + hydhx*(dw + de + gw - ge); col[2].j = row.j = j; col[2].i = row.i = i; v[3] = -hxdhy*(dn + gn); col[3].j = j+1; col[3].i = i; ierr = MatSetValuesStencil(jac,1,&row,4,col,v,INSERT_VALUES);CHKERRQ(ierr); /* right-hand top boundary */ } else { ts = x[j-1][i]; as = 0.5*(t0 + ts); bs = PetscPowScalar(as,bm1); /* ds = bs * as; */ ds = PetscPowScalar(as,beta); gs = coef*bs*(t0 - ts); v[0] = -hxdhy*(ds - gs); col[0].j = j-1; col[0].i = i; v[1] = -hydhx*(dw - gw); col[1].j = j; col[1].i = i-1; v[2] = hxdhy*(ds + gs) + hydhx*(dw + de + gw - ge); col[2].j = row.j = j; col[2].i = row.i = i; ierr = MatSetValuesStencil(jac,1,&row,3,col,v,INSERT_VALUES);CHKERRQ(ierr); } /* bottom boundary,and i <> 0 or mx-1 */ } else if (j == 0) { tw = x[j][i-1]; aw = 0.5*(t0 + tw); bw = PetscPowScalar(aw,bm1); /* dw = bw * aw */ dw = PetscPowScalar(aw,beta); gw = coef*bw*(t0 - tw); te = x[j][i+1]; ae = 0.5*(t0 + te); be = PetscPowScalar(ae,bm1); /* de = be * ae; */ de = PetscPowScalar(ae,beta); ge = coef*be*(te - t0); tn = x[j+1][i]; an = 0.5*(t0 + tn); bn = PetscPowScalar(an,bm1); /* dn = bn * an; */ dn = PetscPowScalar(an,beta); gn = coef*bn*(tn - t0); v[0] = -hydhx*(dw - gw); col[0].j = j; col[0].i = i-1; v[1] = hxdhy*(dn - gn) + hydhx*(dw + de + gw - ge); col[1].j = row.j = j; col[1].i = row.i = i; v[2] = -hydhx*(de + ge); col[2].j = j; col[2].i = i+1; v[3] = -hxdhy*(dn + gn); col[3].j = j+1; col[3].i = i; ierr = MatSetValuesStencil(jac,1,&row,4,col,v,INSERT_VALUES);CHKERRQ(ierr); /* top boundary,and i <> 0 or mx-1 */ } else if (j == my-1) { tw = x[j][i-1]; aw = 0.5*(t0 + tw); bw = PetscPowScalar(aw,bm1); /* dw = bw * aw */ dw = PetscPowScalar(aw,beta); gw = coef*bw*(t0 - tw); te = x[j][i+1]; ae = 0.5*(t0 + te); be = PetscPowScalar(ae,bm1); /* de = be * ae; */ de = PetscPowScalar(ae,beta); ge = coef*be*(te - t0); ts = x[j-1][i]; as = 0.5*(t0 + ts); bs = PetscPowScalar(as,bm1); /* ds = bs * as; */ ds = PetscPowScalar(as,beta); gs = coef*bs*(t0 - ts); v[0] = -hxdhy*(ds - gs); col[0].j = j-1; col[0].i = i; v[1] = -hydhx*(dw - gw); col[1].j = j; col[1].i = i-1; v[2] = hxdhy*(ds + gs) + hydhx*(dw + de + gw - ge); col[2].j = row.j = j; col[2].i = row.i = i; v[3] = -hydhx*(de + ge); col[3].j = j; col[3].i = i+1; ierr = MatSetValuesStencil(jac,1,&row,4,col,v,INSERT_VALUES);CHKERRQ(ierr); } } } ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = DMDAVecRestoreArray(da,localX,&x);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr); ierr = PetscLogFlops((41.0 + 8.0*POWFLOP)*xm*ym);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode FormJacobianLocal(DMDALocalInfo *info, PetscScalar ***au, Mat J, Mat Jpre, FishCtx *user) { PetscErrorCode ierr; const double hx = 1.0/(info->mx-1), hy = 1.0/(info->my-1), hz = 1.0/(info->mz-1), h = pow(hx*hy*hz,1.0/3.0), cx = h*h / (hx*hx), cy = h*h / (hy*hy), cz = h*h / (hz*hz); int i,j,k,ncols; double v[7]; MatStencil col[7],row; if (user->printevals) { ierr = PetscPrintf(COMM," [Jacobian eval on %d x %d x %d grid]\n", info->mx,info->my,info->mz); CHKERRQ(ierr); } for (k = info->zs; k < info->zs+info->zm; k++) { row.k = k; col[0].k = k; for (j = info->ys; j < info->ys+info->ym; j++) { row.j = j; col[0].j = j; for (i = info->xs; i < info->xs+info->xm; i++) { row.i = i; col[0].i = i; ncols = 1; if ( i==0 || i==info->mx-1 || j==0 || j==info->my-1 || k==0 || k==info->mz-1) { v[0] = 1.0; } else { v[0] = 2.0 * (cx + cy + cz); if (i-1 > 0) { col[ncols].k = k; col[ncols].j = j; col[ncols].i = i-1; v[ncols++] = - cx; } if (i+1 < info->mx-1) { col[ncols].k = k; col[ncols].j = j; col[ncols].i = i+1; v[ncols++] = - cx; } if (j-1 > 0) { col[ncols].k = k; col[ncols].j = j-1; col[ncols].i = i; v[ncols++] = - cy; } if (j+1 < info->my-1) { col[ncols].k = k; col[ncols].j = j+1; col[ncols].i = i; v[ncols++] = - cy; } if (k-1 > 0) { col[ncols].k = k-1; col[ncols].j = j; col[ncols].i = i; v[ncols++] = - cz; } if (k+1 < info->mz-1) { col[ncols].k = k+1; col[ncols].j = j; col[ncols].i = i; v[ncols++] = - cz; } } ierr = MatSetValuesStencil(Jpre,1,&row,ncols,col,v,INSERT_VALUES); 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); } return 0; }
/* FormJacobian - Evaluates Jacobian matrix. Input Parameters: . snes - the SNES context . x - input vector . ptr - optional user-defined context, as set by SNESSetJacobian() Output Parameters: . A - Jacobian matrix . B - optionally different preconditioning matrix */ PetscErrorCode FormJacobian(SNES snes,Vec X,Mat J,Mat jac,void *ptr) { AppCtx *user = (AppCtx*)ptr; /* user-defined application context */ Vec localX; PetscErrorCode ierr; PetscInt i,j,k,Mx,My,Mz; MatStencil col[7],row; PetscInt xs,ys,zs,xm,ym,zm; PetscScalar lambda,v[7],hx,hy,hz,hxhzdhy,hyhzdhx,hxhydhz,sc,***x; DM da; PetscFunctionBeginUser; ierr = SNESGetDM(snes,&da);CHKERRQ(ierr); ierr = DMGetLocalVector(da,&localX);CHKERRQ(ierr); ierr = DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,&Mz,PETSC_IGNORE,PETSC_IGNORE, PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE); lambda = user->param; hx = 1.0/(PetscReal)(Mx-1); hy = 1.0/(PetscReal)(My-1); hz = 1.0/(PetscReal)(Mz-1); sc = hx*hy*hz*lambda; hxhzdhy = hx*hz/hy; hyhzdhx = hy*hz/hx; hxhydhz = hx*hy/hz; /* 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); /* Get pointer to vector data */ ierr = DMDAVecGetArray(da,localX,&x);CHKERRQ(ierr); /* Get local grid boundaries */ ierr = DMDAGetCorners(da,&xs,&ys,&zs,&xm,&ym,&zm);CHKERRQ(ierr); /* Compute entries for the locally owned part of the Jacobian. - Currently, all PETSc parallel matrix formats are partitioned by contiguous chunks of rows across the processors. - Each processor needs to insert only elements that it owns locally (but any non-local elements will be sent to the appropriate processor during matrix assembly). - Here, we set all entries for a particular row at once. - We can set matrix entries either using either MatSetValuesLocal() or MatSetValues(), as discussed above. */ for (k=zs; k<zs+zm; k++) { for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { row.k = k; row.j = j; row.i = i; /* boundary points */ if (i == 0 || j == 0 || k == 0|| i == Mx-1 || j == My-1 || k == Mz-1) { v[0] = 1.0; ierr = MatSetValuesStencil(jac,1,&row,1,&row,v,INSERT_VALUES);CHKERRQ(ierr); } else { /* interior grid points */ v[0] = -hxhydhz; col[0].k=k-1;col[0].j=j; col[0].i = i; v[1] = -hxhzdhy; col[1].k=k; col[1].j=j-1;col[1].i = i; v[2] = -hyhzdhx; col[2].k=k; col[2].j=j; col[2].i = i-1; v[3] = 2.0*(hyhzdhx+hxhzdhy+hxhydhz)-sc*PetscExpScalar(x[k][j][i]);col[3].k=row.k;col[3].j=row.j;col[3].i = row.i; v[4] = -hyhzdhx; col[4].k=k; col[4].j=j; col[4].i = i+1; v[5] = -hxhzdhy; col[5].k=k; col[5].j=j+1;col[5].i = i; v[6] = -hxhydhz; col[6].k=k+1;col[6].j=j; col[6].i = i; ierr = MatSetValuesStencil(jac,1,&row,7,col,v,INSERT_VALUES);CHKERRQ(ierr); } } } } ierr = DMDAVecRestoreArray(da,localX,&x);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localX);CHKERRQ(ierr); /* Assemble matrix, using the 2-step process: MatAssemblyBegin(), MatAssemblyEnd(). */ ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Normally since the matrix has already been assembled above; this would do nothing. But in the matrix free mode -snes_mf_operator this tells the "matrix-free" matrix that a new linear system solve is about to be done. */ ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Tell the matrix we will never add a new nonzero location to the matrix. If we do, it will generate an error. */ ierr = MatSetOption(jac,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode IJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal a,Mat *J,Mat *Jpre,MatStructure *str,void *ctx) { PetscErrorCode ierr; PetscInt i,c,Mx,xs,xm,nc; DM da; MatStencil col[3],row; PetscScalar vals[3],hx,sx; AppCtx *user = (AppCtx*)ctx; PetscInt N = user->N; PetscScalar **u; PetscFunctionBegin; ierr = TSGetDM(ts,&da);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); ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr); hx = 1.0/(PetscReal)(Mx-1); sx = 1.0/(hx*hx); ierr = DMDAVecGetArrayDOF(da,U,&u);CHKERRQ(ierr); ierr = MatZeroEntries(*Jpre);CHKERRQ(ierr); for (i=xs; i<xs+xm; i++) { for (c=0; c<N; c++) { nc = 0; row.c = c; row.i = i; col[nc].c = c; col[nc].i = i-1; vals[nc++] = -sx; col[nc].c = c; col[nc].i = i; vals[nc++] = 2.0*sx + a; col[nc].c = c; col[nc].i = i+1; vals[nc++] = -sx; ierr = MatSetValuesStencil(*Jpre,1,&row,nc,col,vals,ADD_VALUES);CHKERRQ(ierr); } for (c=0; c<N/3; c++) { nc = 0; row.c = c; row.i = i; col[nc].c = c; col[nc].i = i; vals[nc++] = 1000*u[i][c] + 500*u[i][c+1]; col[nc].c = c+1; col[nc].i = i; vals[nc++] = 500*u[i][c]; ierr = MatSetValuesStencil(*Jpre,1,&row,nc,col,vals,ADD_VALUES);CHKERRQ(ierr); nc = 0; row.c = c+1; row.i = i; col[nc].c = c; col[nc].i = i; vals[nc++] = -1000*u[i][c] + 500*u[i][c+1]; col[nc].c = c+1; col[nc].i = i; vals[nc++] = 500*u[i][c]; ierr = MatSetValuesStencil(*Jpre,1,&row,nc,col,vals,ADD_VALUES);CHKERRQ(ierr); nc = 0; row.c = c+2; row.i = i; col[nc].c = c; col[nc].i = i; vals[nc++] = -500*u[i][c+1]; col[nc].c = c+1; col[nc].i = i; vals[nc++] = -500*u[i][c]; ierr = MatSetValuesStencil(*Jpre,1,&row,nc,col,vals,ADD_VALUES);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); } ierr = DMDAVecRestoreArrayDOF(da,U,&u);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* FormJacobianLocal - Evaluates Jacobian matrix. */ PetscErrorCode FormJacobianLocal(DMDALocalInfo *info,PetscScalar **x,Mat jac,AppCtx *user) { MatStencil col[5], row; PetscScalar D, K, A, v[5], hx, hy, hxdhy, hydhx, ux, uy; PetscReal normGradZ; PetscInt i, j,k; PetscErrorCode ierr; PetscFunctionBegin; D = user->D; K = user->K; hx = 1.0/(PetscReal)(info->mx-1); hy = 1.0/(PetscReal)(info->my-1); hxdhy = hx/hy; hydhx = hy/hx; /* Compute entries for the locally owned part of the Jacobian. - Currently, all PETSc parallel matrix formats are partitioned by contiguous chunks of rows across the processors. - Each processor needs to insert only elements that it owns locally (but any non-local elements will be sent to the appropriate processor during matrix assembly). - Here, we set all entries for a particular row at once. - We can set matrix entries either using either MatSetValuesLocal() or MatSetValues(), as discussed above. */ for (j=info->ys; j<info->ys+info->ym; j++) { for (i=info->xs; i<info->xs+info->xm; i++) { row.j = j; row.i = i; if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) { /* boundary points */ v[0] = 1.0; ierr = MatSetValuesStencil(jac,1,&row,1,&row,v,INSERT_VALUES);CHKERRQ(ierr); } else { /* interior grid points */ ux = (x[j][i+1] - x[j][i])/hx; uy = (x[j+1][i] - x[j][i])/hy; normGradZ = PetscRealPart(sqrt(ux*ux + uy*uy)); //PetscPrintf(PETSC_COMM_SELF, "i: %d j: %d normGradZ: %g\n", i, j, normGradZ); if (normGradZ < 1.0e-8) { normGradZ = 1.0e-8; } A = funcA(x[j][i], user); v[0] = -D*hxdhy; col[0].j = j - 1; col[0].i = i; v[1] = -D*hydhx; col[1].j = j; col[1].i = i-1; v[2] = D*2.0*(hydhx + hxdhy) + K*(funcADer(x[j][i], user)*normGradZ - A/normGradZ)*hx*hy; col[2].j = row.j; col[2].i = row.i; v[3] = -D*hydhx + K*A*hx*hy/(2.0*normGradZ); col[3].j = j; col[3].i = i+1; v[4] = -D*hxdhy + K*A*hx*hy/(2.0*normGradZ); col[4].j = j + 1; col[4].i = i; for(k = 0; k < 5; ++k) { if (PetscIsInfOrNanScalar(v[k])) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FP, "Invalid residual: %g", PetscRealPart(v[k])); } ierr = MatSetValuesStencil(jac,1,&row,5,col,v,INSERT_VALUES);CHKERRQ(ierr); } } } /* Assemble matrix, using the 2-step process: MatAssemblyBegin(), MatAssemblyEnd(). */ ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Tell the matrix we will never add a new nonzero location to the matrix. If we do, it will generate an error. */ ierr = MatSetOption(jac,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* FormJacobianLocal - Evaluates Jacobian matrix. */ static PetscErrorCode FormJacobianLocal(DMDALocalInfo *info,PetscScalar **x,Mat B,AppCtx *user) { PetscErrorCode ierr; PetscInt i,j; MatStencil col[9],row; PetscScalar v[9]; PetscReal hx,hy,hxdhy,hydhx,dhx,dhy,sc; PetscFunctionBegin; hx = 1.0/(PetscReal)(info->mx-1); hy = 1.0/(PetscReal)(info->my-1); sc = hx*hy*user->lambda; dhx = 1/hx; dhy = 1/hy; hxdhy = hx/hy; hydhx = hy/hx; /* Compute entries for the locally owned part of the Jacobian. - PETSc parallel matrix formats are partitioned by contiguous chunks of rows across the processors. - Each processor needs to insert only elements that it owns locally (but any non-local elements will be sent to the appropriate processor during matrix assembly). - Here, we set all entries for a particular row at once. */ for (j=info->ys; j<info->ys+info->ym; j++) { for (i=info->xs; i<info->xs+info->xm; i++) { row.j = j; row.i = i; /* boundary points */ if (i == 0 || j == 0 || i == info->mx-1 || j == info->my-1) { v[0] = 1.0; ierr = MatSetValuesStencil(B,1,&row,1,&row,v,INSERT_VALUES);CHKERRQ(ierr); } else { /* interior grid points */ const PetscScalar ux_E = dhx*(x[j][i+1]-x[j][i]), uy_E = 0.25*dhy*(x[j+1][i]+x[j+1][i+1]-x[j-1][i]-x[j-1][i+1]), ux_W = dhx*(x[j][i]-x[j][i-1]), uy_W = 0.25*dhy*(x[j+1][i-1]+x[j+1][i]-x[j-1][i-1]-x[j-1][i]), ux_N = 0.25*dhx*(x[j][i+1]+x[j+1][i+1]-x[j][i-1]-x[j+1][i-1]), uy_N = dhy*(x[j+1][i]-x[j][i]), ux_S = 0.25*dhx*(x[j-1][i+1]+x[j][i+1]-x[j-1][i-1]-x[j][i-1]), uy_S = dhy*(x[j][i]-x[j-1][i]), u = x[j][i], e_E = eta(user,ux_E,uy_E), e_W = eta(user,ux_W,uy_W), e_N = eta(user,ux_N,uy_N), e_S = eta(user,ux_S,uy_S), de_E = deta(user,ux_E,uy_E), de_W = deta(user,ux_W,uy_W), de_N = deta(user,ux_N,uy_N), de_S = deta(user,ux_S,uy_S), skew_E = de_E*ux_E*uy_E, skew_W = de_W*ux_W*uy_W, skew_N = de_N*ux_N*uy_N, skew_S = de_S*ux_S*uy_S, cross_EW = 0.25*(skew_E - skew_W), cross_NS = 0.25*(skew_N - skew_S), newt_E = e_E+de_E*PetscSqr(ux_E), newt_W = e_W+de_W*PetscSqr(ux_W), newt_N = e_N+de_N*PetscSqr(uy_N), newt_S = e_S+de_S*PetscSqr(uy_S); /* interior grid points */ switch (user->jtype) { case 1: /* Jacobian from p=2 */ v[0] = -hxdhy; col[0].j = j-1; col[0].i = i; v[1] = -hydhx; col[1].j = j; col[1].i = i-1; v[2] = 2.0*(hydhx + hxdhy) - sc*PetscExpScalar(u); col[2].j = row.j; col[2].i = row.i; v[3] = -hydhx; col[3].j = j; col[3].i = i+1; v[4] = -hxdhy; col[4].j = j+1; col[4].i = i; ierr = MatSetValuesStencil(B,1,&row,5,col,v,INSERT_VALUES);CHKERRQ(ierr); break; case 2: /* Jacobian arising from Picard linearization */ v[0] = -hxdhy*e_S; col[0].j = j-1; col[0].i = i; v[1] = -hydhx*e_W; col[1].j = j; col[1].i = i-1; v[2] = (e_W+e_E)*hydhx + (e_S+e_N)*hxdhy; col[2].j = row.j; col[2].i = row.i; v[3] = -hydhx*e_E; col[3].j = j; col[3].i = i+1; v[4] = -hxdhy*e_N; col[4].j = j+1; col[4].i = i; ierr = MatSetValuesStencil(B,1,&row,5,col,v,INSERT_VALUES);CHKERRQ(ierr); break; case 3: /* Full Jacobian, but only a star stencil */ col[0].j = j-1; col[0].i = i; col[1].j = j; col[1].i = i-1; col[2].j = j; col[2].i = i; col[3].j = j; col[3].i = i+1; col[4].j = j+1; col[4].i = i; v[0] = -hxdhy*newt_S + cross_EW; v[1] = -hydhx*newt_W + cross_NS; v[2] = hxdhy*(newt_N + newt_S) + hydhx*(newt_E + newt_W) - sc*PetscExpScalar(u); v[3] = -hydhx*newt_E - cross_NS; v[4] = -hxdhy*newt_N - cross_EW; ierr = MatSetValuesStencil(B,1,&row,5,col,v,INSERT_VALUES);CHKERRQ(ierr); break; case 4: /** The Jacobian is * * -div [ eta (grad u) + deta (grad u0 . grad u) grad u0 ] - (eE u0) u * **/ col[0].j = j-1; col[0].i = i-1; col[1].j = j-1; col[1].i = i; col[2].j = j-1; col[2].i = i+1; col[3].j = j; col[3].i = i-1; col[4].j = j; col[4].i = i; col[5].j = j; col[5].i = i+1; col[6].j = j+1; col[6].i = i-1; col[7].j = j+1; col[7].i = i; col[8].j = j+1; col[8].i = i+1; v[0] = -0.25*(skew_S + skew_W); v[1] = -hxdhy*newt_S + cross_EW; v[2] = 0.25*(skew_S + skew_E); v[3] = -hydhx*newt_W + cross_NS; v[4] = hxdhy*(newt_N + newt_S) + hydhx*(newt_E + newt_W) - sc*PetscExpScalar(u); v[5] = -hydhx*newt_E - cross_NS; v[6] = 0.25*(skew_N + skew_W); v[7] = -hxdhy*newt_N - cross_EW; v[8] = -0.25*(skew_N + skew_E); ierr = MatSetValuesStencil(B,1,&row,9,col,v,INSERT_VALUES);CHKERRQ(ierr); break; default: SETERRQ1(((PetscObject)info->da)->comm,PETSC_ERR_SUP,"Jacobian type %d not implemented",user->jtype); } } } } /* Assemble matrix, using the 2-step process: MatAssemblyBegin(), MatAssemblyEnd(). */ ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Tell the matrix we will never add a new nonzero location to the matrix. If we do, it will generate an error. */ ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode RHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat BB,void *ctx) { AppCtx *appctx = (AppCtx*)ctx; /* user-defined application context */ DM da; PetscErrorCode ierr; PetscInt i,j,Mx,My,xs,ys,xm,ym; PetscReal hx,hy,sx,sy; PetscScalar uc,vc; Field **u; Vec localU; MatStencil stencil[6],rowstencil; PetscScalar entries[6]; PetscFunctionBegin; ierr = TSGetDM(ts,&da);CHKERRQ(ierr); ierr = DMGetLocalVector(da,&localU);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 = 2.50/(PetscReal)(Mx); sx = 1.0/(hx*hx); hy = 2.50/(PetscReal)(My); sy = 1.0/(hy*hy); /* 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 = DMDAVecGetArrayRead(da,localU,&u);CHKERRQ(ierr); /* Get local grid boundaries */ ierr = DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr); stencil[0].k = 0; stencil[1].k = 0; stencil[2].k = 0; stencil[3].k = 0; stencil[4].k = 0; stencil[5].k = 0; rowstencil.k = 0; /* Compute function over the locally owned part of the grid */ for (j=ys; j<ys+ym; j++) { stencil[0].j = j-1; stencil[1].j = j+1; stencil[2].j = j; stencil[3].j = j; stencil[4].j = j; stencil[5].j = j; rowstencil.k = 0; rowstencil.j = j; for (i=xs; i<xs+xm; i++) { uc = u[j][i].u; vc = u[j][i].v; /* uxx = (-2.0*uc + u[j][i-1].u + u[j][i+1].u)*sx; uyy = (-2.0*uc + u[j-1][i].u + u[j+1][i].u)*sy; vxx = (-2.0*vc + u[j][i-1].v + u[j][i+1].v)*sx; vyy = (-2.0*vc + u[j-1][i].v + u[j+1][i].v)*sy; f[j][i].u = appctx->D1*(uxx + uyy) - uc*vc*vc + appctx->gamma*(1.0 - uc);*/ stencil[0].i = i; stencil[0].c = 0; entries[0] = appctx->D1*sy; stencil[1].i = i; stencil[1].c = 0; entries[1] = appctx->D1*sy; stencil[2].i = i-1; stencil[2].c = 0; entries[2] = appctx->D1*sx; stencil[3].i = i+1; stencil[3].c = 0; entries[3] = appctx->D1*sx; stencil[4].i = i; stencil[4].c = 0; entries[4] = -2.0*appctx->D1*(sx + sy) - vc*vc - appctx->gamma; stencil[5].i = i; stencil[5].c = 1; entries[5] = -2.0*uc*vc; rowstencil.i = i; rowstencil.c = 0; ierr = MatSetValuesStencil(A,1,&rowstencil,6,stencil,entries,INSERT_VALUES);CHKERRQ(ierr); stencil[0].c = 1; entries[0] = appctx->D2*sy; stencil[1].c = 1; entries[1] = appctx->D2*sy; stencil[2].c = 1; entries[2] = appctx->D2*sx; stencil[3].c = 1; entries[3] = appctx->D2*sx; stencil[4].c = 1; entries[4] = -2.0*appctx->D2*(sx + sy) + 2.0*uc*vc - appctx->gamma - appctx->kappa; stencil[5].c = 0; entries[5] = vc*vc; rowstencil.c = 1; ierr = MatSetValuesStencil(A,1,&rowstencil,6,stencil,entries,INSERT_VALUES);CHKERRQ(ierr); /* f[j][i].v = appctx->D2*(vxx + vyy) + uc*vc*vc - (appctx->gamma + appctx->kappa)*vc; */ } } /* Restore vectors */ ierr = PetscLogFlops(19*xm*ym);CHKERRQ(ierr); ierr = DMDAVecRestoreArrayRead(da,localU,&u);CHKERRQ(ierr); ierr = DMRestoreLocalVector(da,&localU);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatSetOption(A,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); PetscFunctionReturn(0); }