void PETSc::Solve_withPureNeumann_GMRES(void) { ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); ierr = VecAssemblyBegin(x); ierr = VecAssemblyEnd(x); ierr = VecAssemblyBegin(b); ierr = VecAssemblyEnd(b); MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,PETSC_NULL,&nullsp); KSPSetNullSpace(ksp,nullsp); MatNullSpaceRemove(nullsp,b,PETSC_NULL); KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN); KSPSetType(ksp,KSPGMRES); //KSPGetPC(ksp, &pc); //PCSetType(pc, PCASM); KSPSetFromOptions(ksp); KSPSetUp(ksp); //start_clock("Before Petsc Solve in pure neumann solver"); KSPSolve(ksp,b,x); //stop_clock("After Petsc Solve in pure neumann solver"); }
PetscErrorCode ComputeRHS(KSP ksp,Vec b,void *ctx) { UserContext *user = (UserContext*)ctx; PetscErrorCode ierr; PetscInt i,j,mx,my,xm,ym,xs,ys; PetscScalar Hx,Hy; PetscScalar **array; 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); Hx = 1.0 / (PetscReal)(mx-1); Hy = 1.0 / (PetscReal)(my-1); ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0); CHKERRQ(ierr); ierr = DMDAVecGetArray(da, b, &array); CHKERRQ(ierr); for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { array[j][i] = PetscExpScalar(-((PetscReal)i*Hx)*((PetscReal)i*Hx)/user->nu)*PetscExpScalar(-((PetscReal)j*Hy)*((PetscReal)j*Hy)/user->nu)*Hx*Hy; } } ierr = DMDAVecRestoreArray(da, b, &array); CHKERRQ(ierr); ierr = VecAssemblyBegin(b); CHKERRQ(ierr); ierr = VecAssemblyEnd(b); CHKERRQ(ierr); /* force right hand side to be consistent for singular matrix */ /* note this is really a hack, normally the model would provide you with a consistent right handside */ if (user->bcType == NEUMANN) { MatNullSpace nullspace; ierr = MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,&nullspace); CHKERRQ(ierr); ierr = MatNullSpaceRemove(nullspace,b,PETSC_NULL); CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullspace); CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode ComputeRHS(KSP ksp,Vec b,void *ctx) { PetscErrorCode ierr; PetscInt i,j,k,mx,my,mz,xm,ym,zm,xs,ys,zs; PetscScalar Hx,Hy,Hz; PetscScalar ***array; 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); ierr = DMDAGetCorners(da,&xs,&ys,&zs,&xm,&ym,&zm);CHKERRQ(ierr); ierr = DMDAVecGetArray(da, b, &array);CHKERRQ(ierr); for (k=zs; k<zs+zm; k++) { for (j=ys; j<ys+ym; j++) { for (i=xs; i<xs+xm; i++) { array[k][j][i] = 12 * PETSC_PI * PETSC_PI * PetscCosScalar(2*PETSC_PI*(((PetscReal)i+0.5)*Hx)) * PetscCosScalar(2*PETSC_PI*(((PetscReal)j+0.5)*Hy)) * PetscCosScalar(2*PETSC_PI*(((PetscReal)k+0.5)*Hz)) * Hx * Hy * Hz; } } } ierr = DMDAVecRestoreArray(da, b, &array);CHKERRQ(ierr); ierr = VecAssemblyBegin(b);CHKERRQ(ierr); ierr = VecAssemblyEnd(b);CHKERRQ(ierr); /* force right hand side to be consistent for singular matrix */ /* note this is really a hack, normally the model would provide you with a consistent right handside */ ierr = MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,&nullspace);CHKERRQ(ierr); ierr = MatNullSpaceRemove(nullspace,b);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullspace);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode ComputeRHS(KSP ksp,Vec b,void *ctx) { UserContext *user = (UserContext*)ctx; PetscErrorCode ierr; PetscInt i, j, M, N, xm ,ym ,xs, ys; PetscScalar Hx, Hy, pi, uu, tt; PetscScalar **array; DM da; 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); uu = user->uu; tt = user->tt; pi = 4*atan(1.0); Hx = 1.0/(PetscReal)(M); Hy = 1.0/(PetscReal)(N); ierr = DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr); // Fine grid //printf(" M N: %d %d; xm ym: %d %d; xs ys: %d %d\n",M,N,xm,ym,xs,ys); ierr = DMDAVecGetArray(da, b, &array);CHKERRQ(ierr); for (j=ys; j<ys+ym; j++){ for (i=xs; i<xs+xm; i++){ array[j][i] = -PetscCosScalar(uu*pi*((PetscReal)i+0.5)*Hx)*cos(tt*pi*((PetscReal)j+0.5)*Hy)*Hx*Hy; } } ierr = DMDAVecRestoreArray(da, b, &array);CHKERRQ(ierr); ierr = VecAssemblyBegin(b);CHKERRQ(ierr); ierr = VecAssemblyEnd(b);CHKERRQ(ierr); /* force right hand side to be consistent for singular matrix */ /* note this is really a hack, normally the model would provide you with a consistent right handside */ if (user->bcType == NEUMANN) { MatNullSpace nullspace; ierr = MatNullSpaceCreate(PETSC_COMM_WORLD,PETSC_TRUE,0,0,&nullspace);CHKERRQ(ierr); ierr = MatNullSpaceRemove(nullspace,b,PETSC_NULL);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullspace);CHKERRQ(ierr); } PetscFunctionReturn(0); }
PetscErrorCode ComputeRHS(DM da, Vec b, PetscScalar nu) { PetscErrorCode ierr; PetscInt i, j, mx, my, xm, ym, xs, ys; PetscScalar Hx, Hy; PetscScalar** array; PetscFunctionBeginUser; ierr = DMDAGetInfo(da, 0, &mx, &my, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); CHKERRQ(ierr); Hx = 1.0 / (PetscReal)(mx); Hy = 1.0 / (PetscReal)(my); ierr = DMDAGetCorners(da, &xs, &ys, 0, &xm, &ym, 0); CHKERRQ(ierr); ierr = DMDAVecGetArray(da, b, &array); CHKERRQ(ierr); for (j = ys; j < ys + ym; j++) { for (i = xs; i < xs + xm; i++) { array[j][i] = PetscExpScalar(-(((PetscReal)i + 0.5) * Hx) * (((PetscReal)i + 0.5) * Hx) / nu) * PetscExpScalar(-(((PetscReal)j + 0.5) * Hy) * (((PetscReal)j + 0.5) * Hy) / nu) * Hx * Hy * nu; } } ierr = DMDAVecRestoreArray(da, b, &array); CHKERRQ(ierr); ierr = VecAssemblyBegin(b); CHKERRQ(ierr); ierr = VecAssemblyEnd(b); CHKERRQ(ierr); MatNullSpace nullspace; ierr = MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_TRUE, 0, 0, &nullspace); CHKERRQ(ierr); ierr = MatNullSpaceRemove(nullspace, b); CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullspace); CHKERRQ(ierr); PetscFunctionReturn(0); }
/* MatMult_MFFD - Default matrix-free form for Jacobian-vector product, y = F'(u)*a: y ~= (F(u + ha) - F(u))/h, where F = nonlinear function, as set by SNESSetFunction() u = current iterate h = difference interval */ static PetscErrorCode MatMult_MFFD(Mat mat,Vec a,Vec y) { MatMFFD ctx = (MatMFFD)mat->data; PetscScalar h; Vec w,U,F; PetscErrorCode ierr; PetscBool zeroa; PetscFunctionBegin; if (!ctx->current_u) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"MatMFFDSetBase() has not been called, this is often caused by forgetting to call \n\t\tMatAssemblyBegin/End on the first Mat in the SNES compute function"); /* We log matrix-free matrix-vector products separately, so that we can separate the performance monitoring from the cases that use conventional storage. We may eventually modify event logging to associate events with particular objects, hence alleviating the more general problem. */ ierr = PetscLogEventBegin(MATMFFD_Mult,a,y,0,0);CHKERRQ(ierr); w = ctx->w; U = ctx->current_u; F = ctx->current_f; /* Compute differencing parameter */ if (!((PetscObject)ctx)->type_name) { ierr = MatMFFDSetType(mat,MATMFFD_WP);CHKERRQ(ierr); ierr = MatSetFromOptions(mat);CHKERRQ(ierr); } ierr = (*ctx->ops->compute)(ctx,U,a,&h,&zeroa);CHKERRQ(ierr); if (zeroa) { ierr = VecSet(y,0.0);CHKERRQ(ierr); PetscFunctionReturn(0); } if (mat->erroriffailure && PetscIsInfOrNanScalar(h)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Computed Nan differencing parameter h"); if (ctx->checkh) { ierr = (*ctx->checkh)(ctx->checkhctx,U,a,&h);CHKERRQ(ierr); } /* keep a record of the current differencing parameter h */ ctx->currenth = h; #if defined(PETSC_USE_COMPLEX) ierr = PetscInfo2(mat,"Current differencing parameter: %g + %g i\n",(double)PetscRealPart(h),(double)PetscImaginaryPart(h));CHKERRQ(ierr); #else ierr = PetscInfo1(mat,"Current differencing parameter: %15.12e\n",h);CHKERRQ(ierr); #endif if (ctx->historyh && ctx->ncurrenth < ctx->maxcurrenth) { ctx->historyh[ctx->ncurrenth] = h; } ctx->ncurrenth++; #if defined(PETSC_USE_COMPLEX) if (ctx->usecomplex) h = PETSC_i*h; #endif /* w = u + ha */ if (ctx->drscale) { ierr = VecPointwiseMult(ctx->drscale,a,U);CHKERRQ(ierr); ierr = VecAYPX(U,h,w);CHKERRQ(ierr); } else { ierr = VecWAXPY(w,h,a,U);CHKERRQ(ierr); } /* compute func(U) as base for differencing; only needed first time in and not when provided by user */ if (ctx->ncurrenth == 1 && ctx->current_f_allocated) { ierr = (*ctx->func)(ctx->funcctx,U,F);CHKERRQ(ierr); } ierr = (*ctx->func)(ctx->funcctx,w,y);CHKERRQ(ierr); #if defined(PETSC_USE_COMPLEX) if (ctx->usecomplex) { ierr = VecImaginaryPart(y);CHKERRQ(ierr); h = PetscImaginaryPart(h); } else { ierr = VecAXPY(y,-1.0,F);CHKERRQ(ierr); } #else ierr = VecAXPY(y,-1.0,F);CHKERRQ(ierr); #endif ierr = VecScale(y,1.0/h);CHKERRQ(ierr); ierr = VecAXPBY(y,ctx->vshift,ctx->vscale,a);CHKERRQ(ierr); if (ctx->dlscale) { ierr = VecPointwiseMult(y,ctx->dlscale,y);CHKERRQ(ierr); } if (ctx->dshift) { if (!ctx->dshiftw) { ierr = VecDuplicate(y,&ctx->dshiftw);CHKERRQ(ierr); } ierr = VecPointwiseMult(ctx->dshift,a,ctx->dshiftw);CHKERRQ(ierr); ierr = VecAXPY(y,1.0,ctx->dshiftw);CHKERRQ(ierr); } if (mat->nullsp) {ierr = MatNullSpaceRemove(mat->nullsp,y);CHKERRQ(ierr);} ierr = PetscLogEventEnd(MATMFFD_Mult,a,y,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* SNESMatrixFreeMult2_Private - Default matrix-free form for Jacobian-vector product, y = F'(u)*a: y = (F(u + ha) - F(u)) /h, where F = nonlinear function, as set by SNESSetFunction() u = current iterate h = difference interval */ PetscErrorCode SNESMatrixFreeMult2_Private(Mat mat,Vec a,Vec y) { MFCtx_Private *ctx; SNES snes; PetscReal h,norm,sum,umin,noise; PetscScalar hs,dot; Vec w,U,F; PetscErrorCode ierr,(*eval_fct)(SNES,Vec,Vec); MPI_Comm comm; PetscInt iter; PetscFunctionBegin; /* We log matrix-free matrix-vector products separately, so that we can separate the performance monitoring from the cases that use conventional storage. We may eventually modify event logging to associate events with particular objects, hence alleviating the more general problem. */ ierr = PetscLogEventBegin(MATMFFD_Mult,a,y,0,0);CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); ierr = MatShellGetContext(mat,(void**)&ctx);CHKERRQ(ierr); snes = ctx->snes; w = ctx->w; umin = ctx->umin; ierr = SNESGetSolution(snes,&U);CHKERRQ(ierr); eval_fct = SNESComputeFunction; ierr = SNESGetFunction(snes,&F,NULL,NULL);CHKERRQ(ierr); /* Determine a "good" step size, h */ if (ctx->need_h) { /* Use Jorge's method to compute h */ if (ctx->jorge) { ierr = SNESDiffParameterCompute_More(snes,ctx->data,U,a,&noise,&h);CHKERRQ(ierr); /* Use the Brown/Saad method to compute h */ } else { /* Compute error if desired */ ierr = SNESGetIterationNumber(snes,&iter);CHKERRQ(ierr); if ((ctx->need_err) || ((ctx->compute_err_freq) && (ctx->compute_err_iter != iter) && (!((iter-1)%ctx->compute_err_freq)))) { /* Use Jorge's method to compute noise */ ierr = SNESDiffParameterCompute_More(snes,ctx->data,U,a,&noise,&h);CHKERRQ(ierr); ctx->error_rel = PetscSqrtReal(noise); ierr = PetscInfo3(snes,"Using Jorge's noise: noise=%g, sqrt(noise)=%g, h_more=%g\n",(double)noise,(double)ctx->error_rel,(double)h);CHKERRQ(ierr); ctx->compute_err_iter = iter; ctx->need_err = PETSC_FALSE; } ierr = VecDotBegin(U,a,&dot);CHKERRQ(ierr); ierr = VecNormBegin(a,NORM_1,&sum);CHKERRQ(ierr); ierr = VecNormBegin(a,NORM_2,&norm);CHKERRQ(ierr); ierr = VecDotEnd(U,a,&dot);CHKERRQ(ierr); ierr = VecNormEnd(a,NORM_1,&sum);CHKERRQ(ierr); ierr = VecNormEnd(a,NORM_2,&norm);CHKERRQ(ierr); /* Safeguard for step sizes too small */ if (sum == 0.0) { dot = 1.0; norm = 1.0; } else if (PetscAbsScalar(dot) < umin*sum && PetscRealPart(dot) >= 0.0) dot = umin*sum; else if (PetscAbsScalar(dot) < 0.0 && PetscRealPart(dot) > -umin*sum) dot = -umin*sum; h = PetscRealPart(ctx->error_rel*dot/(norm*norm)); } } else h = ctx->h; if (!ctx->jorge || !ctx->need_h) {ierr = PetscInfo1(snes,"h = %g\n",(double)h);CHKERRQ(ierr);} /* Evaluate function at F(u + ha) */ hs = h; ierr = VecWAXPY(w,hs,a,U);CHKERRQ(ierr); ierr = eval_fct(snes,w,y);CHKERRQ(ierr); ierr = VecAXPY(y,-1.0,F);CHKERRQ(ierr); ierr = VecScale(y,1.0/hs);CHKERRQ(ierr); if (ctx->sp) {ierr = MatNullSpaceRemove(ctx->sp,y);CHKERRQ(ierr);} ierr = PetscLogEventEnd(MATMFFD_Mult,a,y,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }