static PetscErrorCode FormJacobianLocal_KU(User user,DMDALocalInfo *info,DMDALocalInfo *infok,const PetscScalar u[],const PetscScalar k[],Mat Bku) { PetscErrorCode ierr; PetscInt i; PetscReal hx = 1./(info->mx-1); PetscFunctionBeginUser; if (!Bku) PetscFunctionReturn(0); /* Not assembling this block */ for (i=infok->xs; i<infok->xs+infok->xm; i++) { PetscInt row = i-infok->gxs,cols[2]; PetscScalar vals[2]; const PetscScalar ubar = 0.5*(u[i]+u[i+1]), ubar_L = 0.5, ubar_R = 0.5, gradu = (u[i+1]-u[i])/hx, gradu_L = -1./hx, gradu_R = 1./hx, g = 1. + PetscSqr(gradu), g_gradu = 2.*gradu, w = 1./(1.+ubar) + 1./g, w_ubar = -1./PetscSqr(1.+ubar), w_gradu = -g_gradu/PetscSqr(g), iw = 1./w, iw_ubar = -w_ubar * PetscSqr(iw), iw_gradu = -w_gradu * PetscSqr(iw); cols[0] = i-info->gxs; vals[0] = -hx*(iw_ubar*ubar_L + iw_gradu*gradu_L); cols[1] = i+1-info->gxs; vals[1] = -hx*(iw_ubar*ubar_R + iw_gradu*gradu_R); ierr = MatSetValuesLocal(Bku,1,&row,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* RHSMatrixLaplacian - User-provided routine to compute the right-hand-side matrix for the Laplacian operator Input Parameters: ts - the TS context t - current time (ignored) X - current solution (ignored) dummy - optional user-defined context, as set by TSetRHSJacobian() Output Parameters: AA - Jacobian matrix BB - optionally different matrix from which the preconditioner is built str - flag indicating matrix structure */ PetscErrorCode RHSMatrixLaplaciangllDM(TS ts,PetscReal t,Vec X,Mat A,Mat BB,void *ctx) { PetscReal **temp; PetscReal vv; AppCtx *appctx = (AppCtx*)ctx; /* user-defined application context */ PetscErrorCode ierr; PetscInt i,xs,xn,l,j; PetscInt *rowsDM; PetscBool flg = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,NULL,"-gll_mf",&flg,NULL);CHKERRQ(ierr); if (!flg) { /* Creates the element stiffness matrix for the given gll */ ierr = PetscGLLElementLaplacianCreate(&appctx->SEMop.gll,&temp);CHKERRQ(ierr); /* workarround for clang analyzer warning: Division by zero */ if (appctx->param.N <= 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_WRONG,"Spectral element order should be > 1"); /* scale by the size of the element */ for (i=0; i<appctx->param.N; i++) { vv=-appctx->param.mu*2.0/appctx->param.Le; for (j=0; j<appctx->param.N; j++) temp[i][j]=temp[i][j]*vv; } ierr = MatSetOption(A,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); ierr = DMDAGetCorners(appctx->da,&xs,NULL,NULL,&xn,NULL,NULL);CHKERRQ(ierr); xs = xs/(appctx->param.N-1); xn = xn/(appctx->param.N-1); ierr = PetscMalloc1(appctx->param.N,&rowsDM);CHKERRQ(ierr); /* loop over local elements */ for (j=xs; j<xs+xn; j++) { for (l=0; l<appctx->param.N; l++) { rowsDM[l] = 1+(j-xs)*(appctx->param.N-1)+l; } ierr = MatSetValuesLocal(A,appctx->param.N,rowsDM,appctx->param.N,rowsDM,&temp[0][0],ADD_VALUES);CHKERRQ(ierr); } ierr = PetscFree(rowsDM);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecReciprocal(appctx->SEMop.mass);CHKERRQ(ierr); ierr = MatDiagonalScale(A,appctx->SEMop.mass,0);CHKERRQ(ierr); ierr = VecReciprocal(appctx->SEMop.mass);CHKERRQ(ierr); ierr = PetscGLLElementLaplacianDestroy(&appctx->SEMop.gll,&temp);CHKERRQ(ierr); } else { ierr = MatSetType(A,MATSHELL);CHKERRQ(ierr); ierr = MatSetUp(A);CHKERRQ(ierr); ierr = MatShellSetContext(A,appctx);CHKERRQ(ierr); ierr = MatShellSetOperation(A,MATOP_MULT,(void (*)(void))MatMult_Laplacian);CHKERRQ(ierr); } return 0; }
static PetscErrorCode FormJacobianLocal_U(User user,DMDALocalInfo *info,const PetscScalar u[],const PetscScalar k[],Mat Buu) { PetscReal hx = 1./info->mx; PetscErrorCode ierr; PetscInt i; PetscFunctionBeginUser; for (i=info->xs; i<info->xs+info->xm; i++) { PetscInt row = i-info->gxs,cols[] = {row-1,row,row+1}; PetscScalar val = 1./hx; if (i == 0) { ierr = MatSetValuesLocal(Buu,1,&row,1,&row,&val,INSERT_VALUES);CHKERRQ(ierr); } else if (i == info->mx-1) { ierr = MatSetValuesLocal(Buu,1,&row,1,&row,&val,INSERT_VALUES);CHKERRQ(ierr); } else { PetscScalar vals[] = {-k[i-1]/hx,(k[i-1]+k[i])/hx,-k[i]/hx}; ierr = MatSetValuesLocal(Buu,1,&row,3,cols,vals,INSERT_VALUES);CHKERRQ(ierr); } } PetscFunctionReturn(0); }
static PetscErrorCode FormJacobianLocal_K(User user,DMDALocalInfo *info,const PetscScalar u[],const PetscScalar k[],Mat Bkk) { PetscReal hx = 1./info->mx; PetscErrorCode ierr; PetscInt i; PetscFunctionBeginUser; for (i=info->xs; i<info->xs+info->xm; i++) { PetscInt row = i-info->gxs; PetscScalar vals[] = {hx*(PetscExpScalar(k[i]-1.)+1.)}; ierr = MatSetValuesLocal(Bkk,1,&row,1,&row,vals,INSERT_VALUES);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/* RHSMatrixAdvection - User-provided routine to compute the right-hand-side matrix for the Advection (gradient) operator. Input Parameters: ts - the TS context t - current time global_in - global input vector dummy - optional user-defined context, as set by TSetRHSJacobian() Output Parameters: AA - Jacobian matrix BB - optionally different preconditioning matrix str - flag indicating matrix structure */ PetscErrorCode RHSMatrixAdvectiongllDM(TS ts,PetscReal t,Vec X,Mat A,Mat BB,void *ctx) { PetscReal **temp; AppCtx *appctx = (AppCtx*)ctx; /* user-defined application context */ PetscErrorCode ierr; PetscInt xs,xn,l,j; PetscInt *rowsDM; PetscBool flg = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,NULL,"-gll_mf",&flg,NULL);CHKERRQ(ierr); if (!flg) { /* Creates the advection matrix for the given gll */ ierr = PetscGLLElementAdvectionCreate(&appctx->SEMop.gll,&temp);CHKERRQ(ierr); ierr = MatSetOption(A,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); ierr = DMDAGetCorners(appctx->da,&xs,NULL,NULL,&xn,NULL,NULL);CHKERRQ(ierr); xs = xs/(appctx->param.N-1); xn = xn/(appctx->param.N-1); ierr = PetscMalloc1(appctx->param.N,&rowsDM);CHKERRQ(ierr); for (j=xs; j<xs+xn; j++) { for (l=0; l<appctx->param.N; l++) { rowsDM[l] = 1+(j-xs)*(appctx->param.N-1)+l; } ierr = MatSetValuesLocal(A,appctx->param.N,rowsDM,appctx->param.N,rowsDM,&temp[0][0],ADD_VALUES);CHKERRQ(ierr); } ierr = PetscFree(rowsDM);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecReciprocal(appctx->SEMop.mass);CHKERRQ(ierr); ierr = MatDiagonalScale(A,appctx->SEMop.mass,0);CHKERRQ(ierr); ierr = VecReciprocal(appctx->SEMop.mass);CHKERRQ(ierr); ierr = PetscGLLElementAdvectionDestroy(&appctx->SEMop.gll,&temp);CHKERRQ(ierr); } else { ierr = MatSetType(A,MATSHELL);CHKERRQ(ierr); ierr = MatSetUp(A);CHKERRQ(ierr); ierr = MatShellSetContext(A,appctx);CHKERRQ(ierr); ierr = MatShellSetOperation(A,MATOP_MULT,(void (*)(void))MatMult_Advection);CHKERRQ(ierr); } return 0; }
/* We integrate over each cell (i, j+1)----(i+1, j+1) | \ | | \ | | \ | | \ | | \ | | \ | | \ | (i, j)----(i+1, j) However, the element stiffness matrix for the identity in linear elements is 1 /2 1 1\ - |1 2 1| 12 \1 1 2/ no matter what the shape of the triangle. The Laplacian stiffness matrix is 1 / (x_2 - x_1)^2 + (y_2 - y_1)^2 -(x_2 - x_0)(x_2 - x_1) - (y_2 - y_1)(y_2 - y_0) (x_1 - x_0)(x_2 - x_1) + (y_1 - y_0)(y_2 - y_1)\ - |-(x_2 - x_0)(x_2 - x_1) - (y_2 - y_1)(y_2 - y_0) (x_2 - x_0)^2 + (y_2 - y_0)^2 -(x_1 - x_0)(x_2 - x_0) - (y_1 - y_0)(y_2 - y_0)| A \ (x_1 - x_0)(x_2 - x_1) + (y_1 - y_0)(y_2 - y_1) -(x_1 - x_0)(x_2 - x_0) - (y_1 - y_0)(y_2 - y_0) (x_1 - x_0)^2 + (y_1 - y_0)^2 / where A is the area of the triangle, and (x_i, y_i) is its i'th vertex. */ PetscErrorCode ComputeMatrix(KSP ksp, Mat J, Mat jac, MatStructure *flag,void *ctx) { UserContext *user = (UserContext*)ctx; /* not being used! PetscScalar identity[9] = {0.16666666667, 0.08333333333, 0.08333333333, 0.08333333333, 0.16666666667, 0.08333333333, 0.08333333333, 0.08333333333, 0.16666666667}; */ PetscScalar values[3][3]; PetscInt idx[3]; PetscScalar hx, hy, hx2, hy2, area,phi_dt2; PetscInt i,mx,my,xm,ym,xs,ys; PetscInt ne,nc; const PetscInt *e; PetscErrorCode ierr; DM da; PetscFunctionBeginUser; ierr = KSPGetDM(ksp,&da);CHKERRQ(ierr); ierr = DMDAGetInfo(da, 0, &mx, &my, 0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); hx = 1.0 / (mx-1); hy = 1.0 / (my-1); area = 0.5*hx*hy; phi_dt2 = user->phi*user->dt*user->dt; hx2 = hx*hx/area*phi_dt2; hy2 = hy*hy/area*phi_dt2; /* initially all elements have identical geometry so all element stiffness are identical */ values[0][0] = hx2 + hy2; values[0][1] = -hy2; values[0][2] = -hx2; values[1][0] = -hy2; values[1][1] = hy2; values[1][2] = 0.0; values[2][0] = -hx2; values[2][1] = 0.0; values[2][2] = hx2; ierr = DMDAGetElements(da,&ne,&nc,&e);CHKERRQ(ierr); for (i=0; i<ne; i++) { idx[0] = e[3*i]; idx[1] = e[3*i+1]; idx[2] = e[3*i+2]; ierr = MatSetValuesLocal(jac,3,idx,3,idx,(PetscScalar*)values,ADD_VALUES);CHKERRQ(ierr); } ierr = DMDARestoreElements(da,&ne,&nc,&e);CHKERRQ(ierr); ierr = MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode FormJacobianLocal_UK(User user,DMDALocalInfo *info,DMDALocalInfo *infok,const PetscScalar u[],const PetscScalar k[],Mat Buk) { PetscReal hx = 1./info->mx; PetscErrorCode ierr; PetscInt i; PetscInt row,cols[2]; PetscScalar vals[2]; PetscFunctionBeginUser; if (!Buk) PetscFunctionReturn(0); /* Not assembling this block */ for (i=info->xs; i<info->xs+info->xm; i++) { if (i == 0 || i == info->mx-1) continue; row = i-info->gxs; cols[0] = i-1-infok->gxs; vals[0] = (u[i]-u[i-1])/hx; cols[1] = i-infok->gxs; vals[1] = (u[i]-u[i+1])/hx; ierr = MatSetValuesLocal(Buk,1,&row,2,cols,vals,INSERT_VALUES);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M) { Mat_IS *matis = (Mat_IS*)(mat->data); Mat local_mat; /* info on mat */ PetscInt bs,rows,cols,lrows,lcols; PetscInt local_rows,local_cols; PetscBool isdense,issbaij,isseqaij; PetscMPIInt nsubdomains; /* values insertion */ PetscScalar *array; /* work */ PetscErrorCode ierr; PetscFunctionBegin; /* get info from mat */ ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr); if (nsubdomains == 1) { if (reuse == MAT_INITIAL_MATRIX) { ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&(*M));CHKERRQ(ierr); } else { ierr = MatCopy(matis->A,*M,SAME_NONZERO_PATTERN);CHKERRQ(ierr); } PetscFunctionReturn(0); } ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr); ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr); ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr); ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); if (reuse == MAT_INITIAL_MATRIX) { MatType new_mat_type; PetscBool issbaij_red; /* determining new matrix type */ ierr = MPIU_Allreduce(&issbaij,&issbaij_red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); if (issbaij_red) { new_mat_type = MATSBAIJ; } else { if (bs>1) { new_mat_type = MATBAIJ; } else { new_mat_type = MATAIJ; } } ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr); ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr); ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr); ierr = MatSetType(*M,new_mat_type);CHKERRQ(ierr); ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr); } else { PetscInt mbs,mrows,mcols,mlrows,mlcols; /* some checks */ ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr); ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr); ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr); if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows); if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols); if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows); if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols); if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs); ierr = MatZeroEntries(*M);CHKERRQ(ierr); } if (issbaij) { ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr); } else { ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr); local_mat = matis->A; } /* Set values */ ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr); if (isdense) { /* special case for dense local matrices */ PetscInt i,*dummy_rows,*dummy_cols; if (local_rows != local_cols) { ierr = PetscMalloc2(local_rows,&dummy_rows,local_cols,&dummy_cols);CHKERRQ(ierr); for (i=0;i<local_rows;i++) dummy_rows[i] = i; for (i=0;i<local_cols;i++) dummy_cols[i] = i; } else { ierr = PetscMalloc1(local_rows,&dummy_rows);CHKERRQ(ierr); for (i=0;i<local_rows;i++) dummy_rows[i] = i; dummy_cols = dummy_rows; } ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr); ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr); ierr = MatSetValuesLocal(*M,local_rows,dummy_rows,local_cols,dummy_cols,array,ADD_VALUES);CHKERRQ(ierr); ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr); if (dummy_rows != dummy_cols) { ierr = PetscFree2(dummy_rows,dummy_cols);CHKERRQ(ierr); } else { ierr = PetscFree(dummy_rows);CHKERRQ(ierr); } } else if (isseqaij) { PetscInt i,nvtxs,*xadj,*adjncy; PetscBool done; ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__); ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr); for (i=0;i<nvtxs;i++) { ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr); } ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr); if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__); ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr); } else { /* very basic values insertion for all other matrix types */ PetscInt i; for (i=0;i<local_rows;i++) { PetscInt j; const PetscInt *local_indices_cols; ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr); ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr); ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr); } } ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatDestroy(&local_mat);CHKERRQ(ierr); ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); if (isdense) { ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode SetUpMatrices(AppCtx *user) { PetscErrorCode ierr; PetscInt nele,nen,i,n; const PetscInt *ele; PetscScalar dt=user->dt,h; PetscInt idx[2]; PetscScalar eM_0[2][2],eM_2[2][2]; Mat M =user->M; Mat M_0=user->M_0; PetscInt Mda; PetscFunctionBeginUser; ierr = MatGetLocalSize(M,&n,NULL);CHKERRQ(ierr); ierr = DMDAGetInfo(user->da1,NULL,&Mda,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); if (user->periodic) h = (user->xmax-user->xmin)/Mda; else h = (user->xmax-user->xmin)/(Mda-1.0); if (user->lumpedmass) { eM_0[0][0] = h/2.0; eM_0[1][1] = h/2.0; eM_0[0][1] = eM_0[1][0] = 0.0; } else { eM_0[0][0]=eM_0[1][1]=h/3.0; eM_0[0][1]=eM_0[1][0]=h/6.0; } eM_2[0][0]=eM_2[1][1]=1.0/h; eM_2[0][1]=eM_2[1][0]=-1.0/h; /* Get local element info */ ierr = DMDAGetElements(user->da1,&nele,&nen,&ele);CHKERRQ(ierr); for (i=0; i < nele; i++) { idx[0] = ele[2*i]; idx[1] = ele[2*i+1]; PetscInt row,cols[4],r,row_M_0,cols2[2]; PetscScalar vals[4],vals_M_0[2],vals2[2]; for (r=0; r<2; r++) { row_M_0 = idx[r]; vals_M_0[0]=eM_0[r][0]; vals_M_0[1]=eM_0[r][1]; ierr = MatSetValuesLocal(M_0,1,&row_M_0,2,idx,vals_M_0,ADD_VALUES);CHKERRQ(ierr); row = 3*idx[r]; cols[0] = 3*idx[0]; vals[0] = dt*eM_2[r][0]*user->Mv; cols[1] = 3*idx[1]; vals[1] = dt*eM_2[r][1]*user->Mv; cols[2] = 3*idx[0]+1; vals[2] = eM_0[r][0]; cols[3] = 3*idx[1]+1; vals[3] = eM_0[r][1]; /* Insert values in matrix M for 1st dof */ ierr = MatSetValuesLocal(M,1,&row,4,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 3*idx[r]+1; cols[0] = 3*idx[0]; vals[0] = -eM_0[r][0]; cols[1] = 3*idx[1]; vals[1] = -eM_0[r][1]; cols[2] = 3*idx[0]+1; vals[2] = 2.0*user->kav*eM_2[r][0]; cols[3] = 3*idx[1]+1; vals[3] = 2.0*user->kav*eM_2[r][1]; /* Insert values in matrix M for 2nd dof */ ierr = MatSetValuesLocal(M,1,&row,4,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 3*idx[r]+2; cols2[0] = 3*idx[0]+2; vals2[0] = eM_0[r][0] + user->dt*2.0*user->L*user->kaeta*eM_2[r][0]; cols2[1] = 3*idx[1]+2; vals2[1] = eM_0[r][1] + user->dt*2.0*user->L*user->kaeta*eM_2[r][1]; ierr = MatSetValuesLocal(M,1,&row,2,cols2,vals2,ADD_VALUES);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); }
PetscErrorCode SetUpMatrices(AppCtx *user) { PetscErrorCode ierr; PetscInt nele,nen,i,j; const PetscInt *ele; PetscScalar dt=user->dt; PetscScalar 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; /* 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,DM_BOUNDARY_NONE,DM_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]; 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 = 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); }
PETSC_EXTERN void PETSC_STDCALL matsetvalueslocal_(Mat *mat,PetscInt *nrow, PetscInt irow[],PetscInt *ncol, PetscInt icol[], PetscScalar y[],InsertMode *addv, int *ierr ) { *ierr = MatSetValuesLocal(*mat,*nrow,irow,*ncol,icol,y,*addv); }
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); }
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); }
PetscErrorCode FormOperator(DM networkdm,Mat A,Vec b) { PetscErrorCode ierr; Vec localb; Branch *branch; Node *node; PetscInt e,v,vStart,vEnd,eStart, eEnd; PetscInt lofst,lofst_to,lofst_fr,row[2],col[6]; PetscBool ghost; const PetscInt *cone; PetscScalar *barr,val[6]; PetscFunctionBegin; ierr = DMGetLocalVector(networkdm,&localb);CHKERRQ(ierr); ierr = VecSet(b,0.0);CHKERRQ(ierr); ierr = VecSet(localb,0.0);CHKERRQ(ierr); ierr = MatZeroEntries(A);CHKERRQ(ierr); ierr = VecGetArray(localb,&barr);CHKERRQ(ierr); /* We can define the current as a "edge characteristic" and the voltage and the voltage as a "vertex characteristic". With that, we can iterate the list of edges and vertices, query the associated voltages and currents and use them to write the Kirchoff equations. */ /* Branch equations: i/r + uj - ui = battery */ ierr = DMNetworkGetEdgeRange(networkdm,&eStart,&eEnd);CHKERRQ(ierr); for (e = 0; e < eEnd; e++) { ierr = DMNetworkGetComponent(networkdm,e,0,NULL,(void**)&branch);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,e,&lofst);CHKERRQ(ierr); ierr = DMNetworkGetConnectedVertices(networkdm,e,&cone);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,cone[0],&lofst_fr);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,cone[1],&lofst_to);CHKERRQ(ierr); barr[lofst] = branch->bat; row[0] = lofst; col[0] = lofst; val[0] = 1; col[1] = lofst_to; val[1] = 1; col[2] = lofst_fr; val[2] = -1; ierr = MatSetValuesLocal(A,1,row,3,col,val,ADD_VALUES);CHKERRQ(ierr); /* from node */ ierr = DMNetworkGetComponent(networkdm,cone[0],0,NULL,(void**)&node);CHKERRQ(ierr); if (!node->gr) { row[0] = lofst_fr; col[0] = lofst; val[0] = 1; ierr = MatSetValuesLocal(A,1,row,1,col,val,ADD_VALUES);CHKERRQ(ierr); } /* to node */ ierr = DMNetworkGetComponent(networkdm,cone[1],0,NULL,(void**)&node);CHKERRQ(ierr); if (!node->gr) { row[0] = lofst_to; col[0] = lofst; val[0] = -1; ierr = MatSetValuesLocal(A,1,row,1,col,val,ADD_VALUES);CHKERRQ(ierr); } } ierr = DMNetworkGetVertexRange(networkdm,&vStart,&vEnd);CHKERRQ(ierr); for (v = vStart; v < vEnd; v++) { ierr = DMNetworkIsGhostVertex(networkdm,v,&ghost);CHKERRQ(ierr); if (!ghost) { ierr = DMNetworkGetComponent(networkdm,v,0,NULL,(void**)&node);CHKERRQ(ierr); ierr = DMNetworkGetVariableOffset(networkdm,v,&lofst);CHKERRQ(ierr); if (node->gr) { row[0] = lofst; col[0] = lofst; val[0] = 1; ierr = MatSetValuesLocal(A,1,row,1,col,val,ADD_VALUES);CHKERRQ(ierr); } else { barr[lofst] -= node->inj; } } } ierr = VecRestoreArray(localb,&barr);CHKERRQ(ierr); ierr = DMLocalToGlobalBegin(networkdm,localb,ADD_VALUES,b);CHKERRQ(ierr); ierr = DMLocalToGlobalEnd(networkdm,localb,ADD_VALUES,b);CHKERRQ(ierr); ierr = DMRestoreLocalVector(networkdm,&localb);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* FormHessian - Evaluates Hessian matrix. Input Parameters: . tao - the Tao context . x - input vector . ptr - optional user-defined context, as set by TaoSetHessianRoutine() Output Parameters: . A - Hessian matrix . B - optionally different preconditioning matrix Notes: Due to mesh point reordering with DMs, we must always work with the local mesh points, and then transform them to the new global numbering with the local-to-global mapping. We cannot work directly with the global numbers for the original uniprocessor mesh! Two methods are available for imposing this transformation when setting matrix entries: (A) MatSetValuesLocal(), using the local ordering (including ghost points!) - Do the following two steps once, before calling TaoSolve() - Use DMGetISLocalToGlobalMapping() to extract the local-to-global map from the DM - Associate this map with the matrix by calling MatSetLocalToGlobalMapping() - Then set matrix entries using the local ordering by calling MatSetValuesLocal() (B) MatSetValues(), using the global ordering - Use DMGetGlobalIndices() to extract the local-to-global map - Then apply this map explicitly yourself - Set matrix entries using the global ordering by calling MatSetValues() Option (A) seems cleaner/easier in many cases, and is the procedure used in this example. */ PetscErrorCode FormHessian(Tao tao,Vec X,Mat Hptr, Mat Hessian, void *ptr) { PetscErrorCode ierr; AppCtx *user = (AppCtx *) ptr; PetscInt i,j,k,row; PetscInt mx=user->mx, my=user->my; PetscInt xs,xm,gxs,gxm,ys,ym,gys,gym,col[7]; PetscReal hx=1.0/(mx+1), hy=1.0/(my+1), hydhx=hy/hx, hxdhy=hx/hy; PetscReal rhx=mx+1, rhy=my+1; PetscReal f1,f2,f3,f4,f5,f6,d1,d2,d3,d4,d5,d6,d7,d8,xc,xl,xr,xt,xb,xlt,xrb; PetscReal hl,hr,ht,hb,hc,htl,hbr; PetscReal *x,*left,*right,*bottom,*top; PetscReal v[7]; Vec localX = user->localX; PetscBool assembled; /* Set various matrix options */ ierr = MatSetOption(Hessian,MAT_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr); /* Initialize matrix entries to zero */ ierr = MatAssembled(Hessian,&assembled);CHKERRQ(ierr); if (assembled){ierr = MatZeroEntries(Hessian);CHKERRQ(ierr);} /* Get local mesh boundaries */ ierr = DMDAGetCorners(user->dm,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr); ierr = DMDAGetGhostCorners(user->dm,&gxs,&gys,NULL,&gxm,&gym,NULL);CHKERRQ(ierr); /* Scatter ghost points to local vector */ ierr = DMGlobalToLocalBegin(user->dm,X,INSERT_VALUES,localX);CHKERRQ(ierr); ierr = DMGlobalToLocalEnd(user->dm,X,INSERT_VALUES,localX);CHKERRQ(ierr); /* Get pointers to vector data */ ierr = VecGetArray(localX,&x);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); /* Compute Hessian over the locally owned part of the mesh */ for (i=xs; i< xs+xm; i++){ for (j=ys; j<ys+ym; j++){ row=(j-gys)*gxm + (i-gxs); xc = x[row]; xlt=xrb=xl=xr=xb=xt=xc; /* Left side */ if (i==gxs){ xl= left[j-ys+1]; xlt = left[j-ys+2]; } else { xl = x[row-1]; } if (j==gys){ xb=bottom[i-xs+1]; xrb = bottom[i-xs+2]; } else { xb = x[row-gxm]; } if (i+1 == gxs+gxm){ xr=right[j-ys+1]; xrb = right[j-ys]; } else { xr = x[row+1]; } if (j+1==gys+gym){ xt=top[i-xs+1]; xlt = top[i-xs]; }else { xt = x[row+gxm]; } if (i>gxs && j+1<gys+gym){ xlt = x[row-1+gxm]; } if (j>gys && i+1<gxs+gxm){ xrb = x[row+1-gxm]; } d1 = (xc-xl)*rhx; d2 = (xc-xr)*rhx; d3 = (xc-xt)*rhy; d4 = (xc-xb)*rhy; d5 = (xrb-xr)*rhy; d6 = (xrb-xb)*rhx; d7 = (xlt-xl)*rhy; d8 = (xlt-xt)*rhx; f1 = PetscSqrtScalar( 1.0 + d1*d1 + d7*d7); f2 = PetscSqrtScalar( 1.0 + d1*d1 + d4*d4); f3 = PetscSqrtScalar( 1.0 + d3*d3 + d8*d8); f4 = PetscSqrtScalar( 1.0 + d3*d3 + d2*d2); f5 = PetscSqrtScalar( 1.0 + d2*d2 + d5*d5); f6 = PetscSqrtScalar( 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*=0.5; hr*=0.5; ht*=0.5; hb*=0.5; hbr*=0.5; htl*=0.5; hc*=0.5; k=0; if (j>0){ v[k]=hb; col[k]=row - gxm; k++; } if (j>0 && i < mx -1){ v[k]=hbr; col[k]=row - gxm+1; k++; } if (i>0){ v[k]= hl; col[k]=row - 1; k++; } v[k]= hc; col[k]=row; k++; if (i < mx-1 ){ v[k]= hr; col[k]=row+1; k++; } if (i>0 && j < my-1 ){ v[k]= htl; col[k] = row+gxm-1; k++; } if (j < my-1 ){ v[k]= ht; col[k] = row+gxm; k++; } /* Set matrix values using local numbering, which was defined earlier, in the main routine. */ ierr = MatSetValuesLocal(Hessian,1,&row,k,col,v,INSERT_VALUES);CHKERRQ(ierr); } } /* Restore vectors */ ierr = VecRestoreArray(localX,&x);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(Hessian,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(Hessian,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = PetscLogFlops(199*xm*ym);CHKERRQ(ierr); return 0; }
/* The element stiffness matrix for the identity in linear elements is 1 /2 1 1\ - |1 2 1| 12 \1 1 2/ no matter what the shape of the triangle. */ PetscErrorCode TaylorGalerkinStepIIMomentum(DM da, UserContext *user) { MPI_Comm comm; KSP ksp; Mat mat; Vec rhs_u, rhs_v; PetscScalar identity[9] = {0.16666666667, 0.08333333333, 0.08333333333, 0.08333333333, 0.16666666667, 0.08333333333, 0.08333333333, 0.08333333333, 0.16666666667}; PetscScalar *u_n, *v_n, *mu_n; PetscScalar *u_phi, *v_phi; PetscScalar *rho_u_phi, *rho_v_phi; PetscInt idx[3]; PetscScalar values_u[3]; PetscScalar values_v[3]; PetscScalar psi_x[3], psi_y[3]; PetscScalar mu, tau_xx, tau_xy, tau_yy; PetscReal hx, hy, area; const PetscInt *necon; PetscInt j, k, e, ne, nc, mx, my; PetscErrorCode ierr; PetscFunctionBeginUser; ierr = PetscObjectGetComm((PetscObject) da, &comm);CHKERRQ(ierr); ierr = DMSetMatType(da,MATAIJ);CHKERRQ(ierr); ierr = DMCreateMatrix(da, &mat);CHKERRQ(ierr); ierr = MatSetOption(mat,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); ierr = DMGetGlobalVector(da, &rhs_u);CHKERRQ(ierr); ierr = DMGetGlobalVector(da, &rhs_v);CHKERRQ(ierr); ierr = KSPCreate(comm, &ksp);CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = DMDAGetInfo(da, 0, &mx, &my, 0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); hx = 1.0 / (PetscReal)(mx-1); hy = 1.0 / (PetscReal)(my-1); area = 0.5*hx*hy; ierr = VecGetArray(user->sol_n.u, &u_n);CHKERRQ(ierr); ierr = VecGetArray(user->sol_n.v, &v_n);CHKERRQ(ierr); ierr = VecGetArray(user->mu, &mu_n);CHKERRQ(ierr); ierr = VecGetArray(user->sol_phi.u, &u_phi);CHKERRQ(ierr); ierr = VecGetArray(user->sol_phi.v, &v_phi);CHKERRQ(ierr); ierr = VecGetArray(user->sol_phi.rho_u, &rho_u_phi);CHKERRQ(ierr); ierr = VecGetArray(user->sol_phi.rho_v, &rho_v_phi);CHKERRQ(ierr); ierr = DMDAGetElements(da, &ne, &nc, &necon);CHKERRQ(ierr); for (e = 0; e < ne; e++) { for (j = 0; j < 3; j++) { idx[j] = necon[3*e+j]; values_u[j] = 0.0; values_v[j] = 0.0; } /* Get basis function deriatives (we need the orientation of the element here) */ if (idx[1] > idx[0]) { psi_x[0] = -hy; psi_x[1] = hy; psi_x[2] = 0.0; psi_y[0] = -hx; psi_y[1] = 0.0; psi_y[2] = hx; } else { psi_x[0] = hy; psi_x[1] = -hy; psi_x[2] = 0.0; psi_y[0] = hx; psi_y[1] = 0.0; psi_y[2] = -hx; } /* <\nabla\psi, F^{n+\phi}_e>: Divergence of the element-averaged convective fluxes */ for (j = 0; j < 3; j++) { values_u[j] += psi_x[j]*rho_u_phi[e]*u_phi[e] + psi_y[j]*rho_u_phi[e]*v_phi[e]; values_v[j] += psi_x[j]*rho_v_phi[e]*u_phi[e] + psi_y[j]*rho_v_phi[e]*v_phi[e]; } /* -<\nabla\psi, F^n_v>: Divergence of the viscous fluxes */ for (j = 0; j < 3; j++) { /* \tau_{xx} = 2/3 \mu(T) (2 {\partial u\over\partial x} - {\partial v\over\partial y}) */ /* \tau_{xy} = \mu(T) ( {\partial u\over\partial y} + {\partial v\over\partial x}) */ /* \tau_{yy} = 2/3 \mu(T) (2 {\partial v\over\partial y} - {\partial u\over\partial x}) */ mu = 0.0; tau_xx = 0.0; tau_xy = 0.0; tau_yy = 0.0; for (k = 0; k < 3; k++) { mu += mu_n[idx[k]]; tau_xx += 2.0*psi_x[k]*u_n[idx[k]] - psi_y[k]*v_n[idx[k]]; tau_xy += psi_y[k]*u_n[idx[k]] + psi_x[k]*v_n[idx[k]]; tau_yy += 2.0*psi_y[k]*v_n[idx[k]] - psi_x[k]*u_n[idx[k]]; } mu /= 3.0; tau_xx *= (2.0/3.0)*mu; tau_xy *= mu; tau_yy *= (2.0/3.0)*mu; values_u[j] -= area*(psi_x[j]*tau_xx + psi_y[j]*tau_xy); values_v[j] -= area*(psi_x[j]*tau_xy + psi_y[j]*tau_yy); } /* Accumulate to global structures */ ierr = VecSetValuesLocal(rhs_u, 3, idx, values_u, ADD_VALUES);CHKERRQ(ierr); ierr = VecSetValuesLocal(rhs_v, 3, idx, values_v, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesLocal(mat, 3, idx, 3, idx, identity, ADD_VALUES);CHKERRQ(ierr); } ierr = DMDARestoreElements(da, &ne, &nc, &necon);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_n.u, &u_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_n.v, &v_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->mu, &mu_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_phi.u, &u_phi);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_phi.v, &v_phi);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_phi.rho_u, &rho_u_phi);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_phi.rho_v, &rho_v_phi);CHKERRQ(ierr); ierr = VecAssemblyBegin(rhs_u);CHKERRQ(ierr); ierr = VecAssemblyBegin(rhs_v);CHKERRQ(ierr); ierr = MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecAssemblyEnd(rhs_u);CHKERRQ(ierr); ierr = VecAssemblyEnd(rhs_v);CHKERRQ(ierr); ierr = MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecScale(rhs_u,user->dt);CHKERRQ(ierr); ierr = VecScale(rhs_v,user->dt);CHKERRQ(ierr); ierr = KSPSetOperators(ksp, mat, mat, DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = KSPSolve(ksp, rhs_u, user->sol_np1.rho_u);CHKERRQ(ierr); ierr = KSPSolve(ksp, rhs_v, user->sol_np1.rho_v);CHKERRQ(ierr); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = MatDestroy(&mat);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(da, &rhs_u);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(da, &rhs_v);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* Notice that this requires the previous momentum solution. The element stiffness matrix for the identity in linear elements is 1 /2 1 1\ - |1 2 1| 12 \1 1 2/ no matter what the shape of the triangle. */ PetscErrorCode TaylorGalerkinStepIIMassEnergy(DM da, UserContext *user) { MPI_Comm comm; Mat mat; Vec rhs_m, rhs_e; PetscScalar identity[9] = {0.16666666667, 0.08333333333, 0.08333333333, 0.08333333333, 0.16666666667, 0.08333333333, 0.08333333333, 0.08333333333, 0.16666666667}; PetscScalar *u_n, *v_n, *p_n, *t_n, *mu_n, *kappa_n; PetscScalar *rho_n, *rho_u_n, *rho_v_n, *rho_e_n; PetscScalar *u_phi, *v_phi; PetscScalar *rho_u_np1, *rho_v_np1; PetscInt idx[3]; PetscScalar psi_x[3], psi_y[3]; PetscScalar values_m[3]; PetscScalar values_e[3]; PetscScalar phi = user->phi; PetscScalar mu, kappa, tau_xx, tau_xy, tau_yy, q_x, q_y; PetscReal hx, hy, area; KSP ksp; const PetscInt *necon; PetscInt j, k, e, ne, nc, mx, my; PetscErrorCode ierr; PetscFunctionBeginUser; ierr = PetscObjectGetComm((PetscObject) da, &comm);CHKERRQ(ierr); ierr = DMSetMatType(da,MATAIJ);CHKERRQ(ierr); ierr = DMCreateMatrix(da, &mat);CHKERRQ(ierr); ierr = MatSetOption(mat,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); ierr = DMGetGlobalVector(da, &rhs_m);CHKERRQ(ierr); ierr = DMGetGlobalVector(da, &rhs_e);CHKERRQ(ierr); ierr = KSPCreate(comm, &ksp);CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = DMDAGetInfo(da, 0, &mx, &my, 0,0,0,0,0,0,0,0,0,0);CHKERRQ(ierr); hx = 1.0 / (PetscReal)(mx-1); hy = 1.0 / (PetscReal)(my-1); area = 0.5*hx*hy; ierr = VecGetArray(user->sol_n.u, &u_n);CHKERRQ(ierr); ierr = VecGetArray(user->sol_n.v, &v_n);CHKERRQ(ierr); ierr = VecGetArray(user->sol_n.p, &p_n);CHKERRQ(ierr); ierr = VecGetArray(user->sol_n.t, &t_n);CHKERRQ(ierr); ierr = VecGetArray(user->mu, &mu_n);CHKERRQ(ierr); ierr = VecGetArray(user->kappa, &kappa_n);CHKERRQ(ierr); ierr = VecGetArray(user->sol_n.rho, &rho_n);CHKERRQ(ierr); ierr = VecGetArray(user->sol_n.rho_u, &rho_u_n);CHKERRQ(ierr); ierr = VecGetArray(user->sol_n.rho_v, &rho_v_n);CHKERRQ(ierr); ierr = VecGetArray(user->sol_n.rho_e, &rho_e_n);CHKERRQ(ierr); ierr = VecGetArray(user->sol_phi.u, &u_phi);CHKERRQ(ierr); ierr = VecGetArray(user->sol_phi.v, &v_phi);CHKERRQ(ierr); ierr = VecGetArray(user->sol_np1.rho_u, &rho_u_np1);CHKERRQ(ierr); ierr = VecGetArray(user->sol_np1.rho_v, &rho_v_np1);CHKERRQ(ierr); ierr = DMDAGetElements(da, &ne, &nc, &necon);CHKERRQ(ierr); for (e = 0; e < ne; e++) { for (j = 0; j < 3; j++) { idx[j] = necon[3*e+j]; values_m[j] = 0.0; values_e[j] = 0.0; } /* Get basis function deriatives (we need the orientation of the element here) */ if (idx[1] > idx[0]) { psi_x[0] = -hy; psi_x[1] = hy; psi_x[2] = 0.0; psi_y[0] = -hx; psi_y[1] = 0.0; psi_y[2] = hx; } else { psi_x[0] = hy; psi_x[1] = -hy; psi_x[2] = 0.0; psi_y[0] = hx; psi_y[1] = 0.0; psi_y[2] = -hx; } /* <\nabla\psi, F^*>: Divergence of the predicted convective fluxes */ for (j = 0; j < 3; j++) { values_m[j] += (psi_x[j]*(phi*rho_u_np1[idx[j]] + rho_u_n[idx[j]]) + psi_y[j]*(rho_v_np1[idx[j]] + rho_v_n[idx[j]]))/3.0; values_e[j] += values_m[j]*((rho_e_n[idx[j]] + p_n[idx[j]]) / rho_n[idx[j]]); } /* -<\nabla\psi, F^n_v>: Divergence of the viscous fluxes */ for (j = 0; j < 3; j++) { /* \tau_{xx} = 2/3 \mu(T) (2 {\partial u\over\partial x} - {\partial v\over\partial y}) */ /* \tau_{xy} = \mu(T) ( {\partial u\over\partial y} + {\partial v\over\partial x}) */ /* \tau_{yy} = 2/3 \mu(T) (2 {\partial v\over\partial y} - {\partial u\over\partial x}) */ /* q_x = -\kappa(T) {\partial T\over\partial x} */ /* q_y = -\kappa(T) {\partial T\over\partial y} */ /* above code commeted out - causing ininitialized variables. */ q_x =0; q_y =0; mu = 0.0; kappa = 0.0; tau_xx = 0.0; tau_xy = 0.0; tau_yy = 0.0; for (k = 0; k < 3; k++) { mu += mu_n[idx[k]]; kappa += kappa_n[idx[k]]; tau_xx += 2.0*psi_x[k]*u_n[idx[k]] - psi_y[k]*v_n[idx[k]]; tau_xy += psi_y[k]*u_n[idx[k]] + psi_x[k]*v_n[idx[k]]; tau_yy += 2.0*psi_y[k]*v_n[idx[k]] - psi_x[k]*u_n[idx[k]]; q_x += psi_x[k]*t_n[idx[k]]; q_y += psi_y[k]*t_n[idx[k]]; } mu /= 3.0; kappa /= 3.0; tau_xx *= (2.0/3.0)*mu; tau_xy *= mu; tau_yy *= (2.0/3.0)*mu; values_e[j] -= area*(psi_x[j]*(u_phi[e]*tau_xx + v_phi[e]*tau_xy + q_x) + psi_y[j]*(u_phi[e]*tau_xy + v_phi[e]*tau_yy + q_y)); } /* Accumulate to global structures */ ierr = VecSetValuesLocal(rhs_m, 3, idx, values_m, ADD_VALUES);CHKERRQ(ierr); ierr = VecSetValuesLocal(rhs_e, 3, idx, values_e, ADD_VALUES);CHKERRQ(ierr); ierr = MatSetValuesLocal(mat, 3, idx, 3, idx, identity, ADD_VALUES);CHKERRQ(ierr); } ierr = DMDARestoreElements(da, &ne, &nc, &necon);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_n.u, &u_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_n.v, &v_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_n.p, &p_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_n.t, &t_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->mu, &mu_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->kappa, &kappa_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_n.rho, &rho_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_n.rho_u, &rho_u_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_n.rho_v, &rho_v_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_n.rho_e, &rho_e_n);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_phi.u, &u_phi);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_phi.v, &v_phi);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_np1.rho_u, &rho_u_np1);CHKERRQ(ierr); ierr = VecRestoreArray(user->sol_np1.rho_v, &rho_v_np1);CHKERRQ(ierr); ierr = VecAssemblyBegin(rhs_m);CHKERRQ(ierr); ierr = VecAssemblyBegin(rhs_e);CHKERRQ(ierr); ierr = MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecAssemblyEnd(rhs_m);CHKERRQ(ierr); ierr = VecAssemblyEnd(rhs_e);CHKERRQ(ierr); ierr = MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecScale(rhs_m, user->dt);CHKERRQ(ierr); ierr = VecScale(rhs_e, user->dt);CHKERRQ(ierr); ierr = KSPSetOperators(ksp, mat, mat, DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = KSPSolve(ksp, rhs_m, user->sol_np1.rho);CHKERRQ(ierr); ierr = KSPSolve(ksp, rhs_e, user->sol_np1.rho_e);CHKERRQ(ierr); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = MatDestroy(&mat);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(da, &rhs_m);CHKERRQ(ierr); ierr = DMRestoreGlobalVector(da, &rhs_e);CHKERRQ(ierr); PetscFunctionReturn(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 . flag - flag indicating matrix structure */ PetscErrorCode FormJacobian(SNES snes,Vec X,Mat J,Mat jac,void *ptr) { AppCtx *user = (AppCtx*)ptr; PetscInt i,j,Nvlocal,col[50],ierr; PetscScalar alpha,lambda,value[50]; Vec localX = user->localX; VecScatter scatter; PetscScalar *x; #if defined(UNUSED_VARIABLES) PetscScalar two = 2.0,one = 1.0; PetscInt row,Nvglobal,Neglobal; PetscInt *gloInd; Nvglobal = user->Nvglobal; Neglobal = user->Neglobal; gloInd = user->gloInd; #endif /*printf("Entering into FormJacobian \n");*/ Nvlocal = user->Nvlocal; lambda = user->non_lin_param; alpha = user->lin_param; scatter = user->scatter; /* PDE : L(u) + lambda*u*u +alpha*u = 0 where L(u) is the approximate Laplacian as described in the beginning of this code First scatter the distributed vector X into local vector localX (that includes values for ghost nodes. If we wish, we can put some other work between VecScatterBegin() and VecScatterEnd() to overlap the communication with computation. */ ierr = VecScatterBegin(scatter,X,localX,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd(scatter,X,localX,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); /* Get pointer to vector data */ ierr = VecGetArray(localX,&x);CHKERRQ(ierr); for (i=0; i < Nvlocal; i++) { col[0] = i; value[0] = user->itot[i] - 2.0*lambda*x[i] - alpha; for (j = 0; j < user->itot[i]; j++) { col[j+1] = user->AdjM[i][j]; value[j+1] = -1.0; } /* Set the matrix values in the local ordering. Note that in order to use this feature we must call the routine MatSetLocalToGlobalMapping() after the matrix has been created. */ ierr = MatSetValuesLocal(jac,1,&i,1+user->itot[i],col,value,INSERT_VALUES);CHKERRQ(ierr); } /* Assemble matrix, using the 2-step process: MatAssemblyBegin(), MatAssemblyEnd(). Between these two calls, the pointer to vector data has been restored to demonstrate the use of overlapping communicationn with computation. */ ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecRestoreArray(localX,&x);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); /* MatView(jac,PETSC_VIEWER_STDOUT_SELF); */ return 0; }
/* FormHessian computes the quadratic term in the quadratic objective function Notice that the objective function in this problem is quadratic (therefore a constant hessian). If using a nonquadratic solver, then you might want to reconsider this function */ PetscErrorCode FormHessian(Tao tao,Vec X,Mat hes, Mat Hpre, void *ptr) { AppCtx* user=(AppCtx*)ptr; PetscErrorCode ierr; PetscInt i,j,k; PetscInt col[5],row,nx,ny,xs,xm,gxs,gxm,ys,ym,gys,gym; PetscReal one=1.0, two=2.0, six=6.0,pi=4.0*atan(1.0); PetscReal hx,hy,hxhy,hxhx,hyhy; PetscReal xi,v[5]; PetscReal ecc=user->ecc, trule1,trule2,trule3,trule4,trule5,trule6; PetscReal vmiddle, vup, vdown, vleft, vright; PetscBool assembled; nx=user->nx; ny=user->ny; hx=two*pi/(nx+1.0); hy=two*user->b/(ny+1.0); hxhy=hx*hy; hxhx=one/(hx*hx); hyhy=one/(hy*hy); /* Get local grid boundaries */ ierr = DMDAGetCorners(user->dm,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr); ierr = DMDAGetGhostCorners(user->dm,&gxs,&gys,NULL,&gxm,&gym,NULL);CHKERRQ(ierr); ierr = MatAssembled(hes,&assembled);CHKERRQ(ierr); if (assembled){ierr = MatZeroEntries(hes);CHKERRQ(ierr);} for (i=xs; i< xs+xm; i++){ xi=(i+1)*hx; trule1=hxhy*( p(xi,ecc) + p(xi+hx,ecc) + p(xi,ecc) ) / six; /* L(i,j) */ trule2=hxhy*( p(xi,ecc) + p(xi-hx,ecc) + p(xi,ecc) ) / six; /* U(i,j) */ trule3=hxhy*( p(xi,ecc) + p(xi+hx,ecc) + p(xi+hx,ecc) ) / six; /* U(i+1,j) */ trule4=hxhy*( p(xi,ecc) + p(xi-hx,ecc) + p(xi-hx,ecc) ) / six; /* L(i-1,j) */ trule5=trule1; /* L(i,j-1) */ trule6=trule2; /* U(i,j+1) */ vdown=-(trule5+trule2)*hyhy; vleft=-hxhx*(trule2+trule4); vright= -hxhx*(trule1+trule3); vup=-hyhy*(trule1+trule6); vmiddle=(hxhx)*(trule1+trule2+trule3+trule4)+hyhy*(trule1+trule2+trule5+trule6); v[0]=0; v[1]=0; v[2]=0; v[3]=0; v[4]=0; for (j=ys; j<ys+ym; j++){ row=(j-gys)*gxm + (i-gxs); k=0; if (j>gys){ v[k]=vdown; col[k]=row - gxm; k++; } if (i>gxs){ v[k]= vleft; col[k]=row - 1; k++; } v[k]= vmiddle; col[k]=row; k++; if (i+1 < gxs+gxm){ v[k]= vright; col[k]=row+1; k++; } if (j+1 <gys+gym){ v[k]= vup; col[k] = row+gxm; k++; } ierr = MatSetValuesLocal(hes,1,&row,k,col,v,INSERT_VALUES);CHKERRQ(ierr); } } /* Assemble matrix, using the 2-step process: MatAssemblyBegin(), MatAssemblyEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ ierr = MatAssemblyBegin(hes,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(hes,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(hes,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); ierr = MatSetOption(hes,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); ierr = PetscLogFlops(9*xm*ym+49*xm);CHKERRQ(ierr); ierr = MatNorm(hes,NORM_1,&hx);CHKERRQ(ierr); return 0; }
/* FormJacobian - Evaluates Jacobian matrix. Input Parameters: . ot - the OT context . x - input vector . ptr - optional user-defined context, as set by OTSetJacobian() Output Parameters: . A - Jacobian matrix . B - optionally different preconditioning matrix . flag - flag indicating matrix structure Notes: Due to grid point reordering with DAs, we must always work with the local grid points, and then transform them to the new global numbering with the "ltog" mapping (via DAGetGlobalIndices()). We cannot work directly with the global numbers for the original uniprocessor grid! Two methods are available for imposing this transformation when setting matrix entries: (A) MatSetValuesLocal(), using the local ordering (including ghost points!) - Use DAGetGlobalIndices() to extract the local-to-global map - Associate this map with the matrix by calling MatSetLocalToGlobalMapping() once - Set matrix entries using the local ordering by calling MatSetValuesLocal() (B) MatSetValues(), using the global ordering - Use DAGetGlobalIndices() to extract the local-to-global map - Then apply this map explicitly yourself - Set matrix entries using the global ordering by calling MatSetValues() Option (A) seems cleaner/easier in many cases, and is the procedure used in this example. */ int FormJacobian(TAO_SOLVER ot,Vec X,Mat *JJ,void *ptr) { AppCtx *user = (AppCtx *) ptr; /* user-defined application context */ Mat jac=*JJ; Vec localX=user->localX; // local vector int info, i, j, row, mx, my, col[5]; int xs, ys, xm, ym, gxs, gys, gxm, gym; PetscScalar two = 2.0, one = 1.0, lambda, v[5], hx, hy, hxdhy, hydhx, sc, *x; mx = user->mx; my = user->my; lambda = user->param; hx = one/(double)(mx-1); hy = one/(double)(my-1); sc = hx*hy; hxdhy = hx/hy; hydhx = hy/hx; /* Scatter ghost points to local vector, using the 2-step process DAGlobalToLocalBegin(), DAGlobalToLocalEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ // info = DAGetLocalVector(user->da,&(user->localX)); CHKERRQ(info); info = DAGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); info = DAGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX); CHKERRQ(info); /* Get pointer to vector data */ info = VecGetArray(localX,&x); CHKERRQ(info); /* Get local grid boundaries */ 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); /* 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=ys; j<ys+ym; j++) { row = (j - gys)*gxm + xs - gxs - 1; for (i=xs; i<xs+xm; i++) { row++; /* boundary points */ if (i == 0 || j == 0 || i == mx-1 || j == my-1 ) { info = MatSetValuesLocal(jac,1,&row,1,&row,&one,INSERT_VALUES); CHKERRQ(info); continue; } /* interior grid points */ v[0] = -hxdhy; col[0] = row - gxm; v[1] = -hydhx; col[1] = row - 1; v[2] = two*(hydhx + hxdhy) - sc*lambda*exp(x[row]); col[2] = row; v[3] = -hydhx; col[3] = row + 1; v[4] = -hxdhy; col[4] = row + gxm; info = MatSetValuesLocal(jac,1,&row,5,col,v,INSERT_VALUES); CHKERRQ(info); } } /* Assemble matrix, using the 2-step process: MatAssemblyBegin(), MatAssemblyEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ info = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY); CHKERRQ(info); info = VecRestoreArray(localX,&x); CHKERRQ(info); info = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY); CHKERRQ(info); /* Set flag to indicate that the Jacobian matrix retains an identical nonzero structure throughout all nonlinear iterations (although the values of the entries change). Thus, we can save some work in setting up the preconditioner (e.g., no need to redo symbolic factorization for ILU/ICC preconditioners). - If the nonzero structure of the matrix is different during successive linear solves, then the flag DIFFERENT_NONZERO_PATTERN must be used instead. If you are unsure whether the matrix structure has changed or not, use the flag DIFFERENT_NONZERO_PATTERN. - Caution: If you specify SAME_NONZERO_PATTERN, PETSc believes your assertion and does not check the structure of the matrix. If you erroneously claim that the structure is the same when it actually is not, the new preconditioner will not function correctly. Thus, use this optimization feature with caution! */ /* Tell the matrix we will never add a new nonzero location to the matrix. If we do it will generate an error. */ info = MatSetOption(jac,MAT_NEW_NONZERO_LOCATION_ERR);CHKERRQ(info); return 0; }
int main(int argc,char *argv[]) { char mat_type[256] = "aij"; /* default matrix type */ PetscErrorCode ierr; MPI_Comm comm; PetscMPIInt rank,size; DM slice; PetscInt i,bs=1,N=5,n,m,rstart,ghosts[2],*d_nnz,*o_nnz,dfill[4]={1,0,0,1},ofill[4]={1,1,1,1}; PetscReal alpha =1,K=1,rho0=1,u0=0,sigma=0.2; PetscBool useblock=PETSC_TRUE; PetscScalar *xx; Mat A; Vec x,b,lf; ierr = PetscInitialize(&argc,&argv,0,help);CHKERRQ(ierr); comm = PETSC_COMM_WORLD; ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); ierr = PetscOptionsBegin(comm,0,"Options for DMSliced test",0);CHKERRQ(ierr); { ierr = PetscOptionsInt("-n","Global number of nodes","",N,&N,NULL);CHKERRQ(ierr); ierr = PetscOptionsInt("-bs","Block size (1 or 2)","",bs,&bs,NULL);CHKERRQ(ierr); if (bs != 1) { if (bs != 2) SETERRQ(PETSC_COMM_WORLD,1,"Block size must be 1 or 2"); ierr = PetscOptionsReal("-alpha","Inverse time step for wave operator","",alpha,&alpha,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-K","Bulk modulus of compressibility","",K,&K,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-rho0","Reference density","",rho0,&rho0,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-u0","Reference velocity","",u0,&u0,NULL);CHKERRQ(ierr); ierr = PetscOptionsReal("-sigma","Width of Gaussian density perturbation","",sigma,&sigma,NULL);CHKERRQ(ierr); ierr = PetscOptionsBool("-block","Use block matrix assembly","",useblock,&useblock,NULL);CHKERRQ(ierr); } ierr = PetscOptionsString("-sliced_mat_type","Matrix type to use (aij or baij)","",mat_type,mat_type,sizeof(mat_type),NULL);CHKERRQ(ierr); } ierr = PetscOptionsEnd();CHKERRQ(ierr); /* Split ownership, set up periodic grid in 1D */ n = PETSC_DECIDE; ierr = PetscSplitOwnership(comm,&n,&N);CHKERRQ(ierr); rstart = 0; ierr = MPI_Scan(&n,&rstart,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); rstart -= n; ghosts[0] = (N+rstart-1)%N; ghosts[1] = (rstart+n)%N; ierr = PetscMalloc2(n,PetscInt,&d_nnz,n,PetscInt,&o_nnz);CHKERRQ(ierr); for (i=0; i<n; i++) { if (size > 1 && (i==0 || i==n-1)) { d_nnz[i] = 2; o_nnz[i] = 1; } else { d_nnz[i] = 3; o_nnz[i] = 0; } } ierr = DMSlicedCreate(comm,bs,n,2,ghosts,d_nnz,o_nnz,&slice);CHKERRQ(ierr); /* Currently does not copy X_nnz so we can't free them until after DMSlicedGetMatrix */ if (!useblock) {ierr = DMSlicedSetBlockFills(slice,dfill,ofill);CHKERRQ(ierr);} /* Irrelevant for baij formats */ ierr = DMSetMatType(slice,mat_type);CHKERRQ(ierr); ierr = DMCreateMatrix(slice,&A);CHKERRQ(ierr); ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr); ierr = MatSetOption(A,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); ierr = DMCreateGlobalVector(slice,&x);CHKERRQ(ierr); ierr = VecDuplicate(x,&b);CHKERRQ(ierr); ierr = VecGhostGetLocalForm(x,&lf);CHKERRQ(ierr); ierr = VecGetSize(lf,&m);CHKERRQ(ierr); if (m != (n+2)*bs) SETERRQ2(PETSC_COMM_SELF,1,"size of local form %D, expected %D",m,(n+2)*bs); ierr = VecGetArray(lf,&xx);CHKERRQ(ierr); for (i=0; i<n; i++) { PetscInt row[2],col[9],im,ip; PetscScalar v[12]; const PetscReal xref = 2.0*(rstart+i)/N - 1; /* [-1,1] */ const PetscReal h = 1.0/N; /* grid spacing */ im = (i==0) ? n : i-1; ip = (i==n-1) ? n+1 : i+1; switch (bs) { case 1: /* Laplacian with periodic boundaries */ col[0] = im; col[1] = i; col[2] = ip; v[0] = -h; v[1] = 2*h; v[2] = -h; ierr = MatSetValuesLocal(A,1,&i,3,col,v,INSERT_VALUES);CHKERRQ(ierr); xx[i] = sin(xref*PETSC_PI); break; case 2: /* Linear acoustic wave operator in variables [rho, u], central differences, periodic, timestep 1/alpha */ v[0] = -0.5*u0; v[1] = -0.5*K; v[2] = alpha; v[3] = 0; v[4] = 0.5*u0; v[5] = 0.5*K; v[6] = -0.5/rho0; v[7] = -0.5*u0; v[8] = 0; v[9] = alpha; v[10] = 0.5/rho0; v[11] = 0.5*u0; if (useblock) { row[0] = i; col[0] = im; col[1] = i; col[2] = ip; ierr = MatSetValuesBlockedLocal(A,1,row,3,col,v,INSERT_VALUES);CHKERRQ(ierr); } else { row[0] = 2*i; row[1] = 2*i+1; col[0] = 2*im; col[1] = 2*im+1; col[2] = 2*i; col[3] = 2*ip; col[4] = 2*ip+1; v[3] = v[4]; v[4] = v[5]; /* pack values in first row */ ierr = MatSetValuesLocal(A,1,row,5,col,v,INSERT_VALUES);CHKERRQ(ierr); col[2] = 2*i+1; v[8] = v[9]; v[9] = v[10]; v[10] = v[11]; /* pack values in second row */ ierr = MatSetValuesLocal(A,1,row+1,5,col,v+6,INSERT_VALUES);CHKERRQ(ierr); } /* Set current state (gaussian density perturbation) */ xx[2*i] = 0.2*exp(-PetscSqr(xref)/(2*PetscSqr(sigma))); xx[2*i+1] = 0; break; default: SETERRQ1(PETSC_COMM_SELF,1,"not implemented for block size %D",bs); } } ierr = VecRestoreArray(lf,&xx);CHKERRQ(ierr); ierr = VecGhostRestoreLocalForm(x,&lf);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatMult(A,x,b);CHKERRQ(ierr); ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = VecView(x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = VecView(b,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); /* Update the ghosted values, view the result on rank 0. */ ierr = VecGhostUpdateBegin(b,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecGhostUpdateEnd(b,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); if (!rank) { ierr = VecGhostGetLocalForm(b,&lf);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(PETSC_VIEWER_STDOUT_SELF,"Local form of b on rank 0, last two nodes are ghost nodes\n");CHKERRQ(ierr); ierr = VecView(lf,PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); ierr = VecGhostRestoreLocalForm(b,&lf);CHKERRQ(ierr); } ierr = DMDestroy(&slice);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
PetscErrorCode FormHessian(Tao tao, Vec X, Mat A, Mat Hpre, void*ctx) { AppCtx *user= (AppCtx*) ctx; PetscErrorCode ierr; PetscInt i,j,k; PetscInt col[5],row; PetscInt xs,xm,gxs,gxm,ys,ym,gys,gym; PetscReal v[5]; PetscReal hx=1.0/(user->mx+1), hy=1.0/(user->my+1), hxhx=1.0/(hx*hx), hyhy=1.0/(hy*hy), area=0.5*hx*hy; /* Compute the quadratic term in the objective function */ /* Get local grid boundaries */ PetscFunctionBegin; ierr = DMDAGetCorners(user->dm,&xs,&ys,NULL,&xm,&ym,NULL);CHKERRQ(ierr); ierr = DMDAGetGhostCorners(user->dm,&gxs,&gys,NULL,&gxm,&gym,NULL);CHKERRQ(ierr); for (j=ys; j<ys+ym; j++){ for (i=xs; i< xs+xm; i++){ row=(j-gys)*gxm + (i-gxs); k=0; if (j>gys){ v[k]=-2*hyhy; col[k]=row - gxm; k++; } if (i>gxs){ v[k]= -2*hxhx; col[k]=row - 1; k++; } v[k]= 4.0*(hxhx+hyhy); col[k]=row; k++; if (i+1 < gxs+gxm){ v[k]= -2.0*hxhx; col[k]=row+1; k++; } if (j+1 <gys+gym){ v[k]= -2*hyhy; col[k] = row+gxm; k++; } ierr = MatSetValuesLocal(A,1,&row,k,col,v,INSERT_VALUES);CHKERRQ(ierr); } } /* Assemble matrix, using the 2-step process: MatAssemblyBegin(), MatAssemblyEnd(). By placing code between these two statements, computations can be done while messages are in transition. */ ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,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 = MatScale(A,area);CHKERRQ(ierr); ierr = MatSetOption(A,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); ierr = MatSetOption(A,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); ierr = PetscLogFlops(9*xm*ym+49*xm);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode SetUpMatrices(AppCtx* user) { PetscErrorCode ierr; PetscInt nele,nen,i; const PetscInt *ele; PetscScalar dt=user->dt; Vec coords; const PetscScalar *_coords; PetscScalar x[3],y[3],xx[3],yy[3],w; PetscInt idx[3]; PetscScalar phi[3],phider[3][2]; PetscScalar eM_0[3][3],eM_2[3][3]; Mat M=user->M; PetscScalar gamma=user->gamma,theta_c=user->theta_c; PetscInt m; PetscInt j,k; PetscInt row,cols[6],r; PetscScalar vals[6]; PetscInt n,rstart; IS isrow,iscol; PetscFunctionBegin; /* Get ghosted coordinates */ ierr = DMDAGetGhostedCoordinates(user->da,&coords);CHKERRQ(ierr); ierr = VecGetArrayRead(coords,&_coords);CHKERRQ(ierr); /* 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]; ierr = PetscMemzero(xx,3*sizeof(PetscScalar));CHKERRQ(ierr); ierr = PetscMemzero(yy,3*sizeof(PetscScalar));CHKERRQ(ierr); Gausspoints(xx,yy,&w,x,y); eM_0[0][0]=eM_0[0][1]=eM_0[0][2]=0.0; eM_0[1][0]=eM_0[1][1]=eM_0[1][2]=0.0; eM_0[2][0]=eM_0[2][1]=eM_0[2][2]=0.0; eM_2[0][0]=eM_2[0][1]=eM_2[0][2]=0.0; eM_2[1][0]=eM_2[1][1]=eM_2[1][2]=0.0; eM_2[2][0]=eM_2[2][1]=eM_2[2][2]=0.0; for(m=0;m<3;m++) { ierr = PetscMemzero(phi,3*sizeof(PetscScalar));CHKERRQ(ierr); phider[0][0]=phider[0][1]=0.0; phider[1][0]=phider[1][1]=0.0; phider[2][0]=phider[2][1]=0.0; ShapefunctionsT3(phi,phider,xx[m],yy[m],x,y); for(j=0;j<3;j++) { for(k=0;k<3;k++) { eM_0[k][j] += phi[j]*phi[k]*w; eM_2[k][j] += phider[j][0]*phider[k][0]*w + phider[j][1]*phider[k][1]*w; } } } for(r=0;r<3;r++) { row = 2*idx[r]; cols[0] = 2*idx[0]; vals[0] = dt*eM_2[r][0]; cols[1] = 2*idx[0]+1; vals[1] = eM_0[r][0]; cols[2] = 2*idx[1]; vals[2] = dt*eM_2[r][1]; cols[3] = 2*idx[1]+1; vals[3] = eM_0[r][1]; cols[4] = 2*idx[2]; vals[4] = dt*eM_2[r][2]; cols[5] = 2*idx[2]+1; vals[5] = eM_0[r][2]; /* Insert values in matrix M for 1st dof */ ierr = MatSetValuesLocal(M,1,&row,6,cols,vals,ADD_VALUES);CHKERRQ(ierr); row = 2*idx[r]+1; cols[0] = 2*idx[0]; vals[0] = -eM_0[r][0]; cols[1] = 2*idx[0]+1; vals[1] = gamma*eM_2[r][0]-theta_c*eM_0[r][0]; cols[2] = 2*idx[1]; vals[2] = -eM_0[r][1]; cols[3] = 2*idx[1]+1; vals[3] = gamma*eM_2[r][1]-theta_c*eM_0[r][1]; cols[4] = 2*idx[2]; vals[4] = -eM_0[r][2]; cols[5] = 2*idx[2]+1; vals[5] = gamma*eM_2[r][2]-theta_c*eM_2[r][2]; /* Insert values in matrix M for 2nd dof */ ierr = MatSetValuesLocal(M,1,&row,6,cols,vals,ADD_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); /* Create ISs to extract matrix M_0 from M */ ierr = MatGetLocalSize(M,&n,PETSC_NULL);CHKERRQ(ierr); ierr = MatGetOwnershipRange(M,&rstart,PETSC_NULL);CHKERRQ(ierr); ierr = ISCreateStride(PETSC_COMM_WORLD,n/2,rstart,2,&isrow);CHKERRQ(ierr); ierr = ISCreateStride(PETSC_COMM_WORLD,n/2,rstart+1,2,&iscol);CHKERRQ(ierr); /* Extract M_0 from M */ ierr = MatGetSubMatrix(M,isrow,iscol,MAT_INITIAL_MATRIX,&user->M_0);CHKERRQ(ierr); ierr = VecCreate(PETSC_COMM_WORLD,&user->u);CHKERRQ(ierr); ierr = VecSetSizes(user->u,n/2,PETSC_DECIDE);CHKERRQ(ierr); ierr = VecSetFromOptions(user->u);CHKERRQ(ierr); ierr = VecDuplicate(user->u,&user->work1);CHKERRQ(ierr); ierr = ISDestroy(&isrow);CHKERRQ(ierr); ierr = ISDestroy(&iscol);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* WholeMSurfHessian - Evaluates Hessian over the whole grid Input: daapplication - TAO application object da - distributed array X - the current point, at which the function and gradient are evaluated ptr - user-defined application context Output: H - Hessian at X */ static int WholeMSurfHessian(TAO_APPLICATION daapplication, DA da, Vec X, Mat H, void *ptr) { AppCtx *user = (AppCtx*)ptr; Vec localX; int info; PetscInt i, j, ind[4]; PetscInt xs, xm, gxs, gxm, xe, ys, ym, gys, gym, ye; double smallH[4][4]; double **x; double hx, hy, area, byhxhx, byhyhy; double dvdx, dvdy, flow, fup; double areadivf, areadivf3; PetscTruth assembled; hx = user->hx; hy = user->hy; area = user->area; byhxhx = 1.0 / (hx * hx); byhyhy = 1.0 / (hy * hy); info = DAGetLocalVector(da, &localX); CHKERRQ(info); info = MatAssembled(H,&assembled); CHKERRQ(info); if (assembled){info = MatZeroEntries(H); CHKERRQ(info);} info = DAGlobalToLocalBegin(da, X, INSERT_VALUES, localX); CHKERRQ(info); info = DAGlobalToLocalEnd(da, X, INSERT_VALUES, localX); CHKERRQ(info); info = DAVecGetArray(da, localX, (void**)&x); CHKERRQ(info); info = DAGetCorners(da, &xs, &ys, TAO_NULL, &xm, &ym, TAO_NULL); CHKERRQ(info); info = DAGetGhostCorners(da, &gxs, &gys, TAO_NULL, &gxm, &gym, TAO_NULL); CHKERRQ(info); xe = gxs + gxm - 1; ye = gys + gym - 1; for (j = ys; j < ye; j++) { for (i = xs; i < xe; i++) { /* 0 is 0,0; 1 is 1,0; 2 is 0,1; 3 is 1,1 */ dvdx = (x[j][i] - x[j][i+1]) / hx; /* lower triangle contribution */ dvdy = (x[j][i] - x[j+1][i]) / hy; flow = sqrt( 1 + dvdx * dvdx + dvdy * dvdy ); dvdx = dvdx / hx; dvdy = dvdy / hy; areadivf = area / flow; areadivf3 = areadivf / (flow * flow); smallH[0][0] = areadivf * (byhxhx + byhyhy) - areadivf3 * (dvdx + dvdy) * (dvdx + dvdy); smallH[0][1] = areadivf * (-byhxhx) + areadivf3 * (dvdx + dvdy) * (dvdx); smallH[0][2] = areadivf * (-byhyhy) + areadivf3 * (dvdx + dvdy) * (dvdy); smallH[0][3] = 0.0; smallH[1][1] = areadivf * byhxhx - areadivf3 * dvdx * dvdx; smallH[1][2] = areadivf3 * (-dvdx) * dvdy; smallH[2][2] = areadivf * byhyhy - areadivf3 * dvdy * dvdy; /* upper triangle contribution */ dvdx = (x[j+1][i+1] - x[j+1][i]) / hx; dvdy = (x[j+1][i+1] - x[j][i+1]) / hy; fup = sqrt( 1 + dvdx * dvdx + dvdy * dvdy ); dvdx = dvdx / hx; dvdy = dvdy / hy; areadivf = area / fup; areadivf3 = areadivf / (fup * fup); smallH[1][1] += areadivf * byhyhy - areadivf3 * dvdy * dvdy; smallH[1][2] += areadivf3 * (-dvdy) * dvdx; smallH[2][2] += areadivf * byhxhx - areadivf3 * (dvdx * dvdx); smallH[1][3] = areadivf * (-byhyhy) + areadivf3 * (dvdx + dvdy) * dvdy; smallH[2][3] = areadivf * (-byhxhx) + areadivf3 * (dvdx + dvdy) * dvdx; smallH[3][3] = areadivf * (byhxhx + byhyhy) - areadivf3 * (dvdx + dvdy) * (dvdx + dvdy); smallH[1][0] = smallH[0][1]; smallH[2][0] = smallH[0][2]; smallH[3][0] = smallH[0][3]; smallH[2][1] = smallH[1][2]; smallH[3][1] = smallH[1][3]; smallH[3][2] = smallH[2][3]; ind[0] = (j-gys) * gxm + (i-gxs); ind[1] = ind[0] + 1; ind[2] = ind[0] + gxm; ind[3] = ind[2] + 1; info = MatSetValuesLocal(H,4,ind,4,ind,(PetscScalar*)smallH,ADD_VALUES); CHKERRQ(info); } } info = DAVecRestoreArray(da, localX, (void**)&x); CHKERRQ(info); info = MatAssemblyBegin(H, MAT_FINAL_ASSEMBLY); CHKERRQ(info); info = MatAssemblyEnd(H, MAT_FINAL_ASSEMBLY); CHKERRQ(info); info = MatSetOption(H, MAT_SYMMETRIC, PETSC_TRUE); CHKERRQ(info); info = DARestoreLocalVector(da, &localX); CHKERRQ(info); info = PetscLogFlops((xe-xs) * (ye-ys) * 83 + 4); CHKERRQ(info); return 0; } /* WholeMSurfHessian */