int main(int argc, char **argv){ PetscErrorCode ierr; Vec x,b; Mat A; KSP ksp; ierr=PetscInitialize(&argc,&argv,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); PetscPrintf(PETSC_COMM_WORLD,"]> Initializing PETSc/SLEPc\n"); /*Load data*/ ierr=loadInputs(&A,&b,&x);CHKERRQ(ierr); PetscPrintf(PETSC_COMM_WORLD,"]> Data loaded\n"); /*Create the KSP context and setup*/ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPFGMRES);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = KSPSetUp(ksp);CHKERRQ(ierr); PetscPrintf(PETSC_COMM_WORLD,"]> Krylov Solver settings done\n"); /*Solve the system*/ PetscPrintf(PETSC_COMM_WORLD,"]> Krylov Solver Launching solving process\n"); ierr = KSPSolve(ksp, b, x); CHKERRQ(ierr); PetscPrintf(PETSC_COMM_WORLD,"]> Krylov Solver System solved\n"); /*Clean*/ ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); PetscPrintf(PETSC_COMM_WORLD,"]> Cleaned structures, finalizing\n"); /*Finalize PETSc*/ PetscFinalize(); return 0; }
int main(int argc,char **argv) { PetscErrorCode ierr; PetscInt i; KSP ksp; DM da; Vec x; PetscInitialize(&argc,&argv,(char*)0,help); ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = DMDACreate1d(PETSC_COMM_WORLD,DMDA_BOUNDARY_PERIODIC,-3,2,1,0,&da);CHKERRQ(ierr); ierr = KSPSetDM(ksp,da);CHKERRQ(ierr); ierr = KSPSetComputeRHS(ksp,ComputeRHS,NULL);CHKERRQ(ierr); ierr = KSPSetComputeOperators(ksp,ComputeMatrix,NULL);CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = DMCreateGlobalVector(da,&x);CHKERRQ(ierr); ierr = ComputeInitialSolution(da,x);CHKERRQ(ierr); ierr = DMSetApplicationContext(da,x);CHKERRQ(ierr); ierr = KSPSetUp(ksp);CHKERRQ(ierr); ierr = VecView(x,PETSC_VIEWER_DRAW_WORLD);CHKERRQ(ierr); for (i=0; i<10; i++) { ierr = KSPSolve(ksp,NULL,x);CHKERRQ(ierr); ierr = VecView(x,PETSC_VIEWER_DRAW_WORLD);CHKERRQ(ierr); } ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = DMDestroy(&da);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
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"); }
double SFieldSolveFor(SField sfv, double *Y, unsigned int yCount) { mySField sf = static_cast<mySField>(sfv); assert(yCount <= sf->maxN); assert(Y); assert(sf->running); sf->Y = Y; sf->curN = yCount; // -------------- SOLVE PetscErrorCode ierr; PetscLogDouble tic,toc; PetscTime(&tic); int pt[sf->d]; ierr = MatZeroEntries(sf->J); CHKERRQ(ierr); JacobianOnD(sf->J, sf->F, 0, pt, sf); ierr = MatAssemblyBegin(sf->J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); ierr = MatAssemblyEnd(sf->J,MAT_FINAL_ASSEMBLY); CHKERRQ(ierr); PetscTime(&toc); sf->timeAssembly += toc-tic; PetscTime(&tic); ierr = VecZeroEntries(sf->U); CHKERRQ(ierr); ierr = KSPSetOperators(sf->ksp, sf->J, sf->J); CHKERRQ(ierr); ierr = KSPSetUp(sf->ksp); CHKERRQ(ierr); ierr = KSPSolve(sf->ksp,sf->F,sf->U); CHKERRQ(ierr); PetscTime(&toc); sf->timeSolver += toc-tic; return Integrate(sf->U,pt,0,sf); }
static PetscErrorCode PCSetUp_KSP(PC pc) { PetscErrorCode ierr; PC_KSP *jac = (PC_KSP*)pc->data; Mat mat; PetscBool A; PetscFunctionBegin; if (!jac->ksp) {ierr = PCKSPCreateKSP_KSP(pc);CHKERRQ(ierr);} ierr = KSPSetFromOptions(jac->ksp);CHKERRQ(ierr); if (jac->use_true_matrix) mat = pc->mat; else mat = pc->pmat; ierr = KSPGetOperatorsSet(jac->ksp,&A,PETSC_NULL);CHKERRQ(ierr); if (!A) { ierr = KSPSetOperators(jac->ksp,mat,pc->pmat,pc->flag);CHKERRQ(ierr); } else if (pc->flag != SAME_PRECONDITIONER) { Mat Amat,Bmat; ierr = KSPGetOperators(jac->ksp,&Amat,&Bmat,PETSC_NULL);CHKERRQ(ierr); if (Amat == mat && Bmat == pc->pmat) { /* The user has not replaced the matrices so we are expected to forward the update. This incorrectly diagnoses * changed matrices at the top level as the user manually changing the inner matrices, but we have no way to * identify that in this context. The longer term solution is to track matrix state internally. */ ierr = KSPSetOperators(jac->ksp,mat,pc->pmat,pc->flag);CHKERRQ(ierr); } } ierr = KSPSetUp(jac->ksp);CHKERRQ(ierr); PetscFunctionReturn(0); }
void PETSc::Solve(void) { //start_clock("Before Assemble matrix and vector"); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); ierr = VecAssemblyBegin(x); ierr = VecAssemblyEnd(x); ierr = VecAssemblyBegin(b); ierr = VecAssemblyEnd(b); //stop_clock("After Assembly matrix and vector"); KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN); KSPSetType(ksp,KSPBCGSL); KSPBCGSLSetEll(ksp,2); //KSPGetPC(ksp, &pc); //PCSetType(pc, PCJACOBI); KSPSetFromOptions(ksp); KSPSetUp(ksp); //start_clock("Before KSPSolve"); KSPSolve(ksp,b,x); //stop_clock("After KSPSolve"); }
int main(int argc,char **args) { KSP ksp; /* linear solver context */ Mat A; /* matrix */ Vec x,b; /* approx solution, RHS, exact solution */ PetscViewer fd; /* viewer */ PetscErrorCode ierr; PetscInitialize(&argc,&args,(char *)0,help); fd = PETSC_VIEWER_SOCKET_WORLD; ierr = VecCreate(PETSC_COMM_WORLD,&b);CHKERRQ(ierr); ierr = VecLoad(b,fd);CHKERRQ(ierr); ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr); ierr = MatLoad(A,fd);CHKERRQ(ierr); ierr = VecDuplicate(b,&x);CHKERRQ(ierr); ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,A,A,SAME_NONZERO_PATTERN);CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = KSPSetUp(ksp);CHKERRQ(ierr); ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr); ierr = VecView(x,fd);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
int main(int argc,char **argv) { KSP ksp; DM da; UserContext user; const char *bcTypes[2] = {"dirichlet","neumann"}; PetscErrorCode ierr; PetscInt bc; Vec b,x; PetscInitialize(&argc,&argv,(char *)0,help); ierr = KSPCreate(PETSC_COMM_WORLD,&ksp); CHKERRQ(ierr); ierr = DMDACreate2d(PETSC_COMM_WORLD, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE,DMDA_STENCIL_STAR,-3,-3,PETSC_DECIDE,PETSC_DECIDE,1,1,0,0,&da); CHKERRQ(ierr); ierr = DMDASetUniformCoordinates(da,0,1,0,1,0,0); CHKERRQ(ierr); ierr = DMDASetFieldName(da,0,"Pressure"); CHKERRQ(ierr); ierr = PetscOptionsBegin(PETSC_COMM_WORLD, "", "Options for the inhomogeneous Poisson equation", "DMqq"); user.rho = 1.0; ierr = PetscOptionsReal("-rho", "The conductivity", "ex29.c", user.rho, &user.rho, PETSC_NULL); CHKERRQ(ierr); user.nu = 0.1; ierr = PetscOptionsReal("-nu", "The width of the Gaussian source", "ex29.c", user.nu, &user.nu, PETSC_NULL); CHKERRQ(ierr); bc = (PetscInt)DIRICHLET; ierr = PetscOptionsEList("-bc_type","Type of boundary condition","ex29.c",bcTypes,2,bcTypes[0],&bc,PETSC_NULL); CHKERRQ(ierr); user.bcType = (BCType)bc; ierr = PetscOptionsEnd(); ierr = KSPSetComputeRHS(ksp,ComputeRHS,&user); CHKERRQ(ierr); ierr = KSPSetComputeOperators(ksp,ComputeMatrix,&user); CHKERRQ(ierr); ierr = KSPSetDM(ksp,da); CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp); CHKERRQ(ierr); ierr = KSPSetUp(ksp); CHKERRQ(ierr); ierr = KSPSolve(ksp,PETSC_NULL,PETSC_NULL); CHKERRQ(ierr); ierr = KSPGetSolution(ksp,&x); CHKERRQ(ierr); ierr = KSPGetRhs(ksp,&b); CHKERRQ(ierr); ierr = DMDestroy(&da); CHKERRQ(ierr); ierr = KSPDestroy(&ksp); CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
static PetscErrorCode KSPComputeShifts_GMRES(KSP ksp) { PetscErrorCode ierr; KSP_AGMRES *agmres = (KSP_AGMRES*)(ksp->data); KSP kspgmres; Mat Amat, Pmat; MatStructure flag; PetscInt max_k = agmres->max_k; PC pc; PetscInt m; PetscScalar *Rshift, *Ishift; PetscFunctionBegin; /* Perform one cycle of classical GMRES (with the Arnoldi process) to get the Hessenberg matrix We assume here that the ksp is AGMRES and that the operators for the linear system have been set in this ksp */ ierr = KSPCreate(PetscObjectComm((PetscObject)ksp), &kspgmres);CHKERRQ(ierr); if (!ksp->pc) { ierr = KSPGetPC(ksp,&ksp->pc);CHKERRQ(ierr); } ierr = PCGetOperators(ksp->pc, &Amat, &Pmat);CHKERRQ(ierr); ierr = KSPSetOperators(kspgmres, Amat, Pmat);CHKERRQ(ierr); ierr = KSPSetFromOptions(kspgmres);CHKERRQ(ierr); ierr = PetscOptionsHasName(NULL, "-ksp_view", &flg);CHKERRQ(ierr); if (flag) { ierr = PetscOptionsClearValue("-ksp_view");CHKERRQ(ierr); } ierr = KSPSetType(kspgmres, KSPGMRES);CHKERRQ(ierr); ierr = KSPGMRESSetRestart(kspgmres, max_k);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = KSPSetPC(kspgmres, pc);CHKERRQ(ierr); /* Copy common options */ kspgmres->pc_side = ksp->pc_side; /* Setup KSP context */ ierr = KSPSetComputeEigenvalues(kspgmres, PETSC_TRUE);CHKERRQ(ierr); ierr = KSPSetUp(kspgmres);CHKERRQ(ierr); kspgmres->max_it = max_k; /* Restrict the maximum number of iterations to one cycle of GMRES */ kspgmres->rtol = ksp->rtol; ierr = KSPSolve(kspgmres, ksp->vec_rhs, ksp->vec_sol);CHKERRQ(ierr); ksp->guess_zero = PETSC_FALSE; ksp->rnorm = kspgmres->rnorm; ksp->its = kspgmres->its; if (kspgmres->reason == KSP_CONVERGED_RTOL) { ksp->reason = KSP_CONVERGED_RTOL; PetscFunctionReturn(0); } else ksp->reason = KSP_CONVERGED_ITERATING; /* Now, compute the Shifts values */ ierr = PetscMalloc2(max_k,&Rshift,max_k,&Ishift);CHKERRQ(ierr); ierr = KSPComputeEigenvalues(kspgmres, max_k, Rshift, Ishift, &m);CHKERRQ(ierr); if (m < max_k) SETERRQ(PetscObjectComm((PetscObject)ksp),PETSC_ERR_PLIB, "Unable to compute the Shifts for the Newton basis"); else { ierr = KSPAGMRESLejaOrdering(Rshift, Ishift, agmres->Rshift, agmres->Ishift, max_k);CHKERRQ(ierr); agmres->HasShifts = PETSC_TRUE; } /* Restore KSP view options */ if (flg) { ierr = PetscOptionsSetValue("-ksp_view", "");CHKERRQ(ierr); } PetscFunctionReturn(0); }
static PetscErrorCode PCBDDCScalingSetUp_Deluxe_Private(PC pc) { PC_BDDC *pcbddc=(PC_BDDC*)pc->data; PCBDDCDeluxeScaling deluxe_ctx=pcbddc->deluxe_ctx; PCBDDCSubSchurs sub_schurs = pcbddc->sub_schurs; PetscErrorCode ierr; PetscFunctionBegin; if (!sub_schurs->n_subs) { PetscFunctionReturn(0); } /* Create work vectors for sequential part of deluxe */ ierr = MatCreateVecs(sub_schurs->S_Ej_all,&deluxe_ctx->seq_work1,&deluxe_ctx->seq_work2);CHKERRQ(ierr); /* Compute deluxe sequential scatter */ if (sub_schurs->reuse_mumps && !sub_schurs->is_dir) { PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps; ierr = PetscObjectReference((PetscObject)reuse_mumps->correction_scatter_B);CHKERRQ(ierr); deluxe_ctx->seq_scctx = reuse_mumps->correction_scatter_B; } else { ierr = VecScatterCreate(pcbddc->work_scaling,sub_schurs->is_Ej_all,deluxe_ctx->seq_work1,NULL,&deluxe_ctx->seq_scctx);CHKERRQ(ierr); } /* Create Mat object for deluxe scaling */ ierr = PetscObjectReference((PetscObject)sub_schurs->S_Ej_all);CHKERRQ(ierr); deluxe_ctx->seq_mat = sub_schurs->S_Ej_all; if (sub_schurs->sum_S_Ej_all) { /* if this matrix is present, then we need to create the KSP object to invert it */ PC pc_temp; MatSolverPackage solver=NULL; char ksp_prefix[256]; size_t len; ierr = KSPCreate(PETSC_COMM_SELF,&deluxe_ctx->seq_ksp);CHKERRQ(ierr); ierr = KSPSetOperators(deluxe_ctx->seq_ksp,sub_schurs->sum_S_Ej_all,sub_schurs->sum_S_Ej_all);CHKERRQ(ierr); ierr = KSPSetType(deluxe_ctx->seq_ksp,KSPPREONLY);CHKERRQ(ierr); ierr = KSPGetPC(deluxe_ctx->seq_ksp,&pc_temp);CHKERRQ(ierr); ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr); ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr); ierr = PCFactorGetMatSolverPackage(pc_temp,(const MatSolverPackage*)&solver);CHKERRQ(ierr); if (solver) { PC new_pc; PCType type; ierr = PCGetType(pc_temp,&type);CHKERRQ(ierr); ierr = KSPGetPC(deluxe_ctx->seq_ksp,&new_pc);CHKERRQ(ierr); ierr = PCSetType(new_pc,type);CHKERRQ(ierr); ierr = PCFactorSetMatSolverPackage(new_pc,solver);CHKERRQ(ierr); } ierr = PetscStrlen(((PetscObject)(pcbddc->ksp_D))->prefix,&len);CHKERRQ(ierr); len -= 10; /* remove "dirichlet_" */ ierr = PetscStrncpy(ksp_prefix,((PetscObject)(pcbddc->ksp_D))->prefix,len+1);CHKERRQ(ierr); ierr = PetscStrcat(ksp_prefix,"deluxe_");CHKERRQ(ierr); ierr = KSPSetOptionsPrefix(deluxe_ctx->seq_ksp,ksp_prefix);CHKERRQ(ierr); ierr = KSPSetFromOptions(deluxe_ctx->seq_ksp);CHKERRQ(ierr); ierr = KSPSetUp(deluxe_ctx->seq_ksp);CHKERRQ(ierr); } PetscFunctionReturn(0); }
/*@ MatSchurComplementComputeExplicitOperator - Compute the Schur complement matrix explicitly Collective on Mat Input Parameter: . M - the matrix obtained with MatCreateSchurComplement() Output Parameter: . S - the Schur complement matrix Note: This can be expensive, so it is mainly for testing Level: advanced .seealso: MatCreateSchurComplement(), MatSchurComplementUpdate() @*/ PetscErrorCode MatSchurComplementComputeExplicitOperator(Mat M, Mat *S) { Mat B, C, D; KSP ksp; PC pc; PetscBool isLU, isILU; PetscReal fill = 2.0; PetscErrorCode ierr; PetscFunctionBegin; ierr = MatSchurComplementGetSubMatrices(M, NULL, NULL, &B, &C, &D);CHKERRQ(ierr); ierr = MatSchurComplementGetKSP(M, &ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject) pc, PCLU, &isLU);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject) pc, PCILU, &isILU);CHKERRQ(ierr); if (isLU || isILU) { Mat fact, Bd, AinvB, AinvBd; PetscReal eps = 1.0e-10; /* This can be sped up for banded LU */ ierr = KSPSetUp(ksp);CHKERRQ(ierr); ierr = PCFactorGetMatrix(pc, &fact);CHKERRQ(ierr); ierr = MatConvert(B, MATDENSE, MAT_INITIAL_MATRIX, &Bd);CHKERRQ(ierr); ierr = MatDuplicate(Bd, MAT_DO_NOT_COPY_VALUES, &AinvBd);CHKERRQ(ierr); ierr = MatMatSolve(fact, Bd, AinvBd);CHKERRQ(ierr); ierr = MatDestroy(&Bd);CHKERRQ(ierr); ierr = MatChop(AinvBd, eps);CHKERRQ(ierr); ierr = MatConvert(AinvBd, MATAIJ, MAT_INITIAL_MATRIX, &AinvB);CHKERRQ(ierr); ierr = MatDestroy(&AinvBd);CHKERRQ(ierr); ierr = MatMatMult(C, AinvB, MAT_INITIAL_MATRIX, fill, S);CHKERRQ(ierr); ierr = MatDestroy(&AinvB);CHKERRQ(ierr); } else { Mat Ainvd, Ainv; ierr = PCComputeExplicitOperator(pc, &Ainvd);CHKERRQ(ierr); ierr = MatConvert(Ainvd, MATAIJ, MAT_INITIAL_MATRIX, &Ainv);CHKERRQ(ierr); ierr = MatDestroy(&Ainvd);CHKERRQ(ierr); #if 0 /* Symmetric version */ ierr = MatPtAP(Ainv, B, MAT_INITIAL_MATRIX, fill, S);CHKERRQ(ierr); #else /* Nonsymmetric version */ ierr = MatMatMatMult(C, Ainv, B, MAT_INITIAL_MATRIX, fill, S);CHKERRQ(ierr); #endif ierr = MatDestroy(&Ainv);CHKERRQ(ierr); } ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD, PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr); ierr = MatView(*S, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); if (D) { MatInfo info; ierr = MatGetInfo(D, MAT_GLOBAL_SUM, &info);CHKERRQ(ierr); if (info.nz_used) SETERRQ(PetscObjectComm((PetscObject) M), PETSC_ERR_SUP, "Not yet implemented"); } PetscFunctionReturn(0); }
void SingleLongPipe::initialize() { MatCreate(PETSC_COMM_WORLD, &M); MatSetSizes(M, local_n, local_n, global_n, global_n); MatSetFromOptions(M); MatMPIAIJSetPreallocation(M, 2, nullptr, 2, nullptr); MatSeqAIJSetPreallocation(M, 2, nullptr); MatSetUp(M); KSPCreate(PETSC_COMM_WORLD, &ksp); KSPSetOperators(ksp, M, M); KSPSetFromOptions(ksp); KSPSetUp(ksp); }
static PetscErrorCode TaoSetup_BLMVM(Tao tao) { TAO_BLMVM *blmP = (TAO_BLMVM *)tao->data; PetscInt n,N; PetscErrorCode ierr; KSP H0ksp; PetscFunctionBegin; /* Existence of tao->solution checked in TaoSetup() */ ierr = VecDuplicate(tao->solution,&blmP->Xold);CHKERRQ(ierr); ierr = VecDuplicate(tao->solution,&blmP->Gold);CHKERRQ(ierr); ierr = VecDuplicate(tao->solution, &blmP->unprojected_gradient);CHKERRQ(ierr); if (!tao->stepdirection) { ierr = VecDuplicate(tao->solution, &tao->stepdirection);CHKERRQ(ierr); } if (!tao->gradient) { ierr = VecDuplicate(tao->solution,&tao->gradient);CHKERRQ(ierr); } if (!tao->XL) { ierr = VecDuplicate(tao->solution,&tao->XL);CHKERRQ(ierr); ierr = VecSet(tao->XL,PETSC_NINFINITY);CHKERRQ(ierr); } if (!tao->XU) { ierr = VecDuplicate(tao->solution,&tao->XU);CHKERRQ(ierr); ierr = VecSet(tao->XU,PETSC_INFINITY);CHKERRQ(ierr); } /* Create matrix for the limited memory approximation */ ierr = VecGetLocalSize(tao->solution,&n);CHKERRQ(ierr); ierr = VecGetSize(tao->solution,&N);CHKERRQ(ierr); ierr = MatCreateLMVM(((PetscObject)tao)->comm,n,N,&blmP->M);CHKERRQ(ierr); ierr = MatLMVMAllocateVectors(blmP->M,tao->solution);CHKERRQ(ierr); /* If the user has set a matrix to solve as the initial H0, set the options prefix here, and set up the KSP */ if (blmP->H0) { const char *prefix; PC H0pc; ierr = MatLMVMSetH0(blmP->M, blmP->H0);CHKERRQ(ierr); ierr = MatLMVMGetH0KSP(blmP->M, &H0ksp);CHKERRQ(ierr); ierr = TaoGetOptionsPrefix(tao, &prefix);CHKERRQ(ierr); ierr = KSPSetOptionsPrefix(H0ksp, prefix);CHKERRQ(ierr); ierr = PetscObjectAppendOptionsPrefix((PetscObject)H0ksp, "tao_h0_");CHKERRQ(ierr); ierr = KSPGetPC(H0ksp, &H0pc);CHKERRQ(ierr); ierr = PetscObjectAppendOptionsPrefix((PetscObject)H0pc, "tao_h0_");CHKERRQ(ierr); ierr = KSPSetFromOptions(H0ksp);CHKERRQ(ierr); ierr = KSPSetUp(H0ksp);CHKERRQ(ierr); } PetscFunctionReturn(0); }
void createOuterKsp(OuterContext* ctx) { KSPCreate((ctx->data)->commAll, &(ctx->outerKsp)); PetscObjectIncrementTabLevel((PetscObject)(ctx->outerKsp), PETSC_NULL, 0); KSPSetType(ctx->outerKsp, KSPFGMRES); KSPSetTolerances(ctx->outerKsp, 1.0e-12, 1.0e-12, PETSC_DEFAULT, 50); KSPSetPC(ctx->outerKsp, ctx->outerPC); KSPSetOptionsPrefix(ctx->outerKsp, "outer_"); KSPSetFromOptions(ctx->outerKsp); KSPSetOperators(ctx->outerKsp, ctx->outerMat, ctx->outerMat, SAME_NONZERO_PATTERN); KSPSetUp(ctx->outerKsp); }
/*@ MatSchurComplementComputeExplicitOperator - Compute the Schur complement matrix explicitly Collective on Mat Input Parameter: . M - the matrix obtained with MatCreateSchurComplement() Output Parameter: . S - the Schur complement matrix Note: This can be expensive, so it is mainly for testing Level: advanced .seealso: MatCreateSchurComplement(), MatSchurComplementUpdate() @*/ PetscErrorCode MatSchurComplementComputeExplicitOperator(Mat M, Mat *S) { Mat B, C, D; KSP ksp; PC pc; PetscBool isLU, isILU; PetscReal fill = 2.0; PetscErrorCode ierr; PetscFunctionBegin; ierr = MatSchurComplementGetSubMatrices(M, NULL, NULL, &B, &C, &D);CHKERRQ(ierr); ierr = MatSchurComplementGetKSP(M, &ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject) pc, PCLU, &isLU);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject) pc, PCILU, &isILU);CHKERRQ(ierr); if (isLU || isILU) { Mat fact, Bd, AinvB, AinvBd; PetscReal eps = 1.0e-10; /* This can be sped up for banded LU */ ierr = KSPSetUp(ksp);CHKERRQ(ierr); ierr = PCFactorGetMatrix(pc, &fact);CHKERRQ(ierr); ierr = MatConvert(B, MATDENSE, MAT_INITIAL_MATRIX, &Bd);CHKERRQ(ierr); ierr = MatDuplicate(Bd, MAT_DO_NOT_COPY_VALUES, &AinvBd);CHKERRQ(ierr); ierr = MatMatSolve(fact, Bd, AinvBd);CHKERRQ(ierr); ierr = MatDestroy(&Bd);CHKERRQ(ierr); ierr = MatChop(AinvBd, eps);CHKERRQ(ierr); ierr = MatConvert(AinvBd, MATAIJ, MAT_INITIAL_MATRIX, &AinvB);CHKERRQ(ierr); ierr = MatDestroy(&AinvBd);CHKERRQ(ierr); ierr = MatMatMult(C, AinvB, MAT_INITIAL_MATRIX, fill, S);CHKERRQ(ierr); ierr = MatDestroy(&AinvB);CHKERRQ(ierr); } else { Mat Ainvd, Ainv; ierr = PCComputeExplicitOperator(pc, &Ainvd);CHKERRQ(ierr); ierr = MatConvert(Ainvd, MATAIJ, MAT_INITIAL_MATRIX, &Ainv);CHKERRQ(ierr); ierr = MatDestroy(&Ainvd);CHKERRQ(ierr); #if 0 /* Symmetric version */ ierr = MatPtAP(Ainv, B, MAT_INITIAL_MATRIX, fill, S);CHKERRQ(ierr); #else /* Nonsymmetric version */ ierr = MatMatMatMult(C, Ainv, B, MAT_INITIAL_MATRIX, fill, S);CHKERRQ(ierr); #endif ierr = MatDestroy(&Ainv);CHKERRQ(ierr); } if (D) { ierr = MatAXPY(*S, -1.0, D, DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); } ierr = MatScale(*S,-1.0);CHKERRQ(ierr); PetscFunctionReturn(0); }
int main(int argc, char **argv) { PetscErrorCode ierr; Mat A; KSP ksp; PC pc; IS zero, one; MatNullSpace nullsp; Vec x, b; MPI_Comm comm; PetscInitialize(&argc, &argv, NULL, NULL); comm = PETSC_COMM_WORLD; ierr = MatCreate(comm, &A);CHKERRQ(ierr); ierr = MatSetSizes(A, 4, 4, PETSC_DECIDE, PETSC_DECIDE);CHKERRQ(ierr); ierr = MatSetUp(A);CHKERRQ(ierr); ierr = MatSetFromOptions(A);CHKERRQ(ierr); ierr = MatCreateVecs(A, &x, &b);CHKERRQ(ierr); ierr = VecSet(x, 2.0);CHKERRQ(ierr); ierr = VecSet(b, 12.0);CHKERRQ(ierr); ierr = MatDiagonalSet(A, x, INSERT_VALUES);CHKERRQ(ierr); ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = ISCreateStride(comm, 2, 0, 1, &zero);CHKERRQ(ierr); ierr = ISCreateStride(comm, 2, 2, 1, &one);CHKERRQ(ierr); ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, &nullsp);CHKERRQ(ierr); ierr = PetscObjectCompose((PetscObject)zero, "nullspace",(PetscObject)nullsp);CHKERRQ(ierr); ierr = KSPCreate(comm, &ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp, A, A);CHKERRQ(ierr); ierr = KSPSetUp(ksp);CHKERRQ(ierr); ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = PCFieldSplitSetIS(pc, "0", zero); ierr = PCFieldSplitSetIS(pc, "1", one); ierr = KSPSolve(ksp, b, x);CHKERRQ(ierr); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullsp);CHKERRQ(ierr); ierr = ISDestroy(&zero);CHKERRQ(ierr); ierr = ISDestroy(&one);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); PetscFinalize(); return 0; }
int main(int argc,char **args) { KSP ksp; Mat A; Vec x,b; PetscViewer fd; char file[PETSC_MAX_PATH_LEN]; PetscErrorCode ierr; PetscBool flg,preload = PETSC_TRUE; PetscInitialize(&argc,&args,(char*)0,help); ierr = PetscLogDefaultBegin();CHKERRQ(ierr); ierr = PetscOptionsGetString(NULL,NULL,"-f",file,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr); PetscPreLoadBegin(preload,"Load system"); /* Load the matrix and vector; then destroy the viewer. */ ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr); ierr = MatSetFromOptions(A);CHKERRQ(ierr); ierr = PetscViewerBinaryOpen(PETSC_COMM_WORLD,file,FILE_MODE_READ,&fd);CHKERRQ(ierr); ierr = MatLoad(A,fd);CHKERRQ(ierr); ierr = PetscViewerDestroy(&fd);CHKERRQ(ierr); ierr = MatCreateVecs(A,&x,&b);CHKERRQ(ierr); ierr = VecSetFromOptions(b);CHKERRQ(ierr); ierr = VecSet(b,1.0);CHKERRQ(ierr); ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,A,A);CHKERRQ(ierr); ierr = KSPSetUp(ksp);CHKERRQ(ierr); ierr = KSPSetUpOnBlocks(ksp);CHKERRQ(ierr); PetscPreLoadStage("KSPSolve"); ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); PetscPreLoadEnd(); ierr = PetscLogView_VecScatter(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
static PetscErrorCode KSPSetUp_SpecEst(KSP ksp) { KSP_SpecEst *spec = (KSP_SpecEst*)ksp->data; PetscErrorCode ierr; PetscBool nonzero; PetscFunctionBegin; ierr = KSPSetPC(spec->kspest,ksp->pc);CHKERRQ(ierr); ierr = KSPSetPC(spec->kspcheap,ksp->pc);CHKERRQ(ierr); ierr = KSPGetInitialGuessNonzero(ksp,&nonzero);CHKERRQ(ierr); ierr = KSPSetInitialGuessNonzero(spec->kspest,nonzero);CHKERRQ(ierr); ierr = KSPSetInitialGuessNonzero(spec->kspcheap,nonzero);CHKERRQ(ierr); ierr = KSPSetComputeSingularValues(spec->kspest,PETSC_TRUE);CHKERRQ(ierr); ierr = KSPSetUp(spec->kspest);CHKERRQ(ierr); spec->current = PETSC_FALSE; PetscFunctionReturn(0); }
static PetscErrorCode PCSetUp_KSP(PC pc) { PetscErrorCode ierr; PC_KSP *jac = (PC_KSP*)pc->data; Mat mat; PetscFunctionBegin; if (!jac->ksp) { ierr = PCKSPCreateKSP_KSP(pc);CHKERRQ(ierr); ierr = KSPSetFromOptions(jac->ksp);CHKERRQ(ierr); } if (pc->useAmat) mat = pc->mat; else mat = pc->pmat; ierr = KSPSetOperators(jac->ksp,mat,pc->pmat);CHKERRQ(ierr); ierr = KSPSetUp(jac->ksp);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ STMatSetUp - Build the preconditioner matrix used in STMatSolve(). Collective on ST Input Parameters: + st - the spectral transformation context . sigma - the shift - coeffs - the coefficients Note: This function is not intended to be called by end users, but by SLEPc solvers that use ST. It builds matrix st->P as follows, then calls KSPSetUp(). .vb If (coeffs): st->P = Sum_{i=0:nmat-1} coeffs[i]*sigma^i*A_i. else st->P = Sum_{i=0:nmat-1} sigma^i*A_i .ve Level: developer .seealso: STMatSolve() @*/ PetscErrorCode STMatSetUp(ST st,PetscScalar sigma,PetscScalar *coeffs) { PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(st,ST_CLASSID,1); PetscValidLogicalCollectiveScalar(st,sigma,2); PetscValidScalarPointer(coeffs,2); STCheckMatrices(st,1); ierr = PetscLogEventBegin(ST_MatSetUp,st,0,0,0);CHKERRQ(ierr); ierr = STMatMAXPY_Private(st,sigma,0.0,0,coeffs,PETSC_TRUE,&st->P);CHKERRQ(ierr); if (!st->ksp) { ierr = STGetKSP(st,&st->ksp);CHKERRQ(ierr); } ierr = KSPSetOperators(st->ksp,st->P,st->P);CHKERRQ(ierr); ierr = KSPSetUp(st->ksp);CHKERRQ(ierr); ierr = PetscLogEventEnd(ST_MatSetUp,st,0,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode PCSetUp_KSP(PC pc) { PetscErrorCode ierr; PC_KSP *jac = (PC_KSP*)pc->data; Mat mat; PetscTruth A; PetscFunctionBegin; if (!jac->ksp) {ierr = PCKSPCreateKSP_KSP(pc);CHKERRQ(ierr);} ierr = KSPSetFromOptions(jac->ksp);CHKERRQ(ierr); if (jac->use_true_matrix) mat = pc->mat; else mat = pc->pmat; ierr = KSPGetOperatorsSet(jac->ksp,&A,PETSC_NULL);CHKERRQ(ierr); if (!A) { ierr = KSPSetOperators(jac->ksp,mat,pc->pmat,pc->flag);CHKERRQ(ierr); } ierr = KSPSetUp(jac->ksp);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode ComputeKSPFETIDP(DomainData dd, KSP ksp_bddc, KSP *ksp_fetidp) { PetscErrorCode ierr; KSP temp_ksp; PC pc,D; Mat F; PetscFunctionBeginUser; ierr = KSPGetPC(ksp_bddc,&pc);CHKERRQ(ierr); ierr = PCBDDCCreateFETIDPOperators(pc,&F,&D);CHKERRQ(ierr); ierr = KSPCreate(PetscObjectComm((PetscObject)F),&temp_ksp);CHKERRQ(ierr); ierr = KSPSetOperators(temp_ksp,F,F);CHKERRQ(ierr); ierr = KSPSetType(temp_ksp,KSPCG);CHKERRQ(ierr); ierr = KSPSetPC(temp_ksp,D);CHKERRQ(ierr); ierr = KSPSetComputeSingularValues(temp_ksp,PETSC_TRUE);CHKERRQ(ierr); ierr = KSPSetFromOptions(temp_ksp);CHKERRQ(ierr); ierr = KSPSetUp(temp_ksp);CHKERRQ(ierr); *ksp_fetidp = temp_ksp; ierr = MatDestroy(&F);CHKERRQ(ierr); ierr = PCDestroy(&D);CHKERRQ(ierr); PetscFunctionReturn(0); }
void PETSc::Solve_withPureNeumann(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); KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN); //KSPSetType(ksp,KSPMINRES); //KSPSetType(ksp,KSPGMRES); //KSPSetType(ksp,KSPBCGS); KSPSetType(ksp,KSPBCGSL); KSPBCGSLSetEll(ksp,2); //KSPGetPC(ksp, &pc); //PCSetType(pc, PCASM); //PCSetType(pc, PCMG); //PCMGSetLevels(pc, 3, &PETSC_COMM_WORLD); //PCMGSetType(pc,PC_MG_MULTIPLICATIVE); //PCMGSetCycleType(pc,PC_MG_CYCLE_V); // 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"); }
void Field_solver::create_solver_and_preconditioner( KSP *ksp, PC *pc, Mat *A ) { PetscReal rtol = 1.e-12; // Default. // Possible to specify from command line using '-ksp_rtol' option. PetscErrorCode ierr; ierr = KSPCreate( PETSC_COMM_WORLD, ksp ); CHKERRXX(ierr); ierr = KSPSetOperators( *ksp, *A, *A, DIFFERENT_NONZERO_PATTERN ); CHKERRXX(ierr); //ierr = KSPSetOperators( *ksp, *A, *A ); CHKERRXX(ierr); ierr = KSPGetPC( *ksp, pc ); CHKERRXX(ierr); ierr = PCSetType( *pc, PCGAMG ); CHKERRXX(ierr); ierr = KSPSetType( *ksp, KSPGMRES ); CHKERRXX(ierr); ierr = KSPSetTolerances( *ksp, rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT); CHKERRXX(ierr); ierr = KSPSetFromOptions( *ksp ); CHKERRXX(ierr); ierr = KSPSetInitialGuessNonzero( *ksp, PETSC_TRUE ); CHKERRXX( ierr ); // For test purposes //ierr = KSPSetInitialGuessNonzero( *ksp, PETSC_FALSE ); CHKERRXX( ierr ); ierr = KSPSetUp( *ksp ); CHKERRXX(ierr); return; }
PetscErrorCode PCSetUp_MG(PC pc) { PC_MG *mg = (PC_MG*)pc->data; PC_MG_Levels **mglevels = mg->levels; PetscErrorCode ierr; PetscInt i,n = mglevels[0]->levels; PC cpc; PetscBool dump = PETSC_FALSE,opsset,use_amat,missinginterpolate = PETSC_FALSE; Mat dA,dB; Vec tvec; DM *dms; PetscViewer viewer = 0; PetscFunctionBegin; /* FIX: Move this to PCSetFromOptions_MG? */ if (mg->usedmfornumberoflevels) { PetscInt levels; ierr = DMGetRefineLevel(pc->dm,&levels);CHKERRQ(ierr); levels++; if (levels > n) { /* the problem is now being solved on a finer grid */ ierr = PCMGSetLevels(pc,levels,NULL);CHKERRQ(ierr); n = levels; ierr = PCSetFromOptions(pc);CHKERRQ(ierr); /* it is bad to call this here, but otherwise will never be called for the new hierarchy */ mglevels = mg->levels; } } ierr = KSPGetPC(mglevels[0]->smoothd,&cpc);CHKERRQ(ierr); /* If user did not provide fine grid operators OR operator was not updated since last global KSPSetOperators() */ /* so use those from global PC */ /* Is this what we always want? What if user wants to keep old one? */ ierr = KSPGetOperatorsSet(mglevels[n-1]->smoothd,NULL,&opsset);CHKERRQ(ierr); if (opsset) { Mat mmat; ierr = KSPGetOperators(mglevels[n-1]->smoothd,NULL,&mmat);CHKERRQ(ierr); if (mmat == pc->pmat) opsset = PETSC_FALSE; } if (!opsset) { ierr = PCGetUseAmat(pc,&use_amat);CHKERRQ(ierr); if(use_amat){ ierr = PetscInfo(pc,"Using outer operators to define finest grid operator \n because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n");CHKERRQ(ierr); ierr = KSPSetOperators(mglevels[n-1]->smoothd,pc->mat,pc->pmat);CHKERRQ(ierr); } else { ierr = PetscInfo(pc,"Using matrix (pmat) operators to define finest grid operator \n because PCMGGetSmoother(pc,nlevels-1,&ksp);KSPSetOperators(ksp,...); was not called.\n");CHKERRQ(ierr); ierr = KSPSetOperators(mglevels[n-1]->smoothd,pc->pmat,pc->pmat);CHKERRQ(ierr); } } for (i=n-1; i>0; i--) { if (!(mglevels[i]->interpolate || mglevels[i]->restrct)) { missinginterpolate = PETSC_TRUE; continue; } } /* Skipping if user has provided all interpolation/restriction needed (since DM might not be able to produce them (when coming from SNES/TS) Skipping for galerkin==2 (externally managed hierarchy such as ML and GAMG). Cleaner logic here would be great. Wrap ML/GAMG as DMs? */ if (missinginterpolate && pc->dm && mg->galerkin != 2 && !pc->setupcalled) { /* construct the interpolation from the DMs */ Mat p; Vec rscale; ierr = PetscMalloc1(n,&dms);CHKERRQ(ierr); dms[n-1] = pc->dm; /* Separately create them so we do not get DMKSP interference between levels */ for (i=n-2; i>-1; i--) {ierr = DMCoarsen(dms[i+1],MPI_COMM_NULL,&dms[i]);CHKERRQ(ierr);} for (i=n-2; i>-1; i--) { DMKSP kdm; PetscBool dmhasrestrict; ierr = KSPSetDM(mglevels[i]->smoothd,dms[i]);CHKERRQ(ierr); if (mg->galerkin) {ierr = KSPSetDMActive(mglevels[i]->smoothd,PETSC_FALSE);CHKERRQ(ierr);} ierr = DMGetDMKSPWrite(dms[i],&kdm);CHKERRQ(ierr); /* Ugly hack so that the next KSPSetUp() will use the RHS that we set. A better fix is to change dmActive to take * a bitwise OR of computing the matrix, RHS, and initial iterate. */ kdm->ops->computerhs = NULL; kdm->rhsctx = NULL; if (!mglevels[i+1]->interpolate) { ierr = DMCreateInterpolation(dms[i],dms[i+1],&p,&rscale);CHKERRQ(ierr); ierr = PCMGSetInterpolation(pc,i+1,p);CHKERRQ(ierr); if (rscale) {ierr = PCMGSetRScale(pc,i+1,rscale);CHKERRQ(ierr);} ierr = VecDestroy(&rscale);CHKERRQ(ierr); ierr = MatDestroy(&p);CHKERRQ(ierr); } ierr = DMHasCreateRestriction(dms[i],&dmhasrestrict);CHKERRQ(ierr); if (dmhasrestrict && !mglevels[i+1]->restrct){ ierr = DMCreateRestriction(dms[i],dms[i+1],&p);CHKERRQ(ierr); ierr = PCMGSetRestriction(pc,i+1,p);CHKERRQ(ierr); ierr = MatDestroy(&p);CHKERRQ(ierr); } } for (i=n-2; i>-1; i--) {ierr = DMDestroy(&dms[i]);CHKERRQ(ierr);} ierr = PetscFree(dms);CHKERRQ(ierr); } if (pc->dm && !pc->setupcalled) { /* finest smoother also gets DM but it is not active, independent of whether galerkin==2 */ ierr = KSPSetDM(mglevels[n-1]->smoothd,pc->dm);CHKERRQ(ierr); ierr = KSPSetDMActive(mglevels[n-1]->smoothd,PETSC_FALSE);CHKERRQ(ierr); } if (mg->galerkin == 1) { Mat B; /* currently only handle case where mat and pmat are the same on coarser levels */ ierr = KSPGetOperators(mglevels[n-1]->smoothd,&dA,&dB);CHKERRQ(ierr); if (!pc->setupcalled) { for (i=n-2; i>-1; i--) { if (!mglevels[i+1]->restrct && !mglevels[i+1]->interpolate) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must provide interpolation or restriction for each MG level except level 0"); if (!mglevels[i+1]->interpolate) { ierr = PCMGSetInterpolation(pc,i+1,mglevels[i+1]->restrct);CHKERRQ(ierr); } if (!mglevels[i+1]->restrct) { ierr = PCMGSetRestriction(pc,i+1,mglevels[i+1]->interpolate);CHKERRQ(ierr); } if (mglevels[i+1]->interpolate == mglevels[i+1]->restrct) { ierr = MatPtAP(dB,mglevels[i+1]->interpolate,MAT_INITIAL_MATRIX,1.0,&B);CHKERRQ(ierr); } else { ierr = MatMatMatMult(mglevels[i+1]->restrct,dB,mglevels[i+1]->interpolate,MAT_INITIAL_MATRIX,1.0,&B);CHKERRQ(ierr); } ierr = KSPSetOperators(mglevels[i]->smoothd,B,B);CHKERRQ(ierr); if (i != n-2) {ierr = PetscObjectDereference((PetscObject)dB);CHKERRQ(ierr);} dB = B; } if (n > 1) {ierr = PetscObjectDereference((PetscObject)dB);CHKERRQ(ierr);} } else { for (i=n-2; i>-1; i--) { if (!mglevels[i+1]->restrct && !mglevels[i+1]->interpolate) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONGSTATE,"Must provide interpolation or restriction for each MG level except level 0"); if (!mglevels[i+1]->interpolate) { ierr = PCMGSetInterpolation(pc,i+1,mglevels[i+1]->restrct);CHKERRQ(ierr); } if (!mglevels[i+1]->restrct) { ierr = PCMGSetRestriction(pc,i+1,mglevels[i+1]->interpolate);CHKERRQ(ierr); } ierr = KSPGetOperators(mglevels[i]->smoothd,NULL,&B);CHKERRQ(ierr); if (mglevels[i+1]->interpolate == mglevels[i+1]->restrct) { ierr = MatPtAP(dB,mglevels[i+1]->interpolate,MAT_REUSE_MATRIX,1.0,&B);CHKERRQ(ierr); } else { ierr = MatMatMatMult(mglevels[i+1]->restrct,dB,mglevels[i+1]->interpolate,MAT_REUSE_MATRIX,1.0,&B);CHKERRQ(ierr); } ierr = KSPSetOperators(mglevels[i]->smoothd,B,B);CHKERRQ(ierr); dB = B; } } } else if (!mg->galerkin && pc->dm && pc->dm->x) { /* need to restrict Jacobian location to coarser meshes for evaluation */ for (i=n-2; i>-1; i--) { Mat R; Vec rscale; if (!mglevels[i]->smoothd->dm->x) { Vec *vecs; ierr = KSPCreateVecs(mglevels[i]->smoothd,1,&vecs,0,NULL);CHKERRQ(ierr); mglevels[i]->smoothd->dm->x = vecs[0]; ierr = PetscFree(vecs);CHKERRQ(ierr); } ierr = PCMGGetRestriction(pc,i+1,&R);CHKERRQ(ierr); ierr = PCMGGetRScale(pc,i+1,&rscale);CHKERRQ(ierr); ierr = MatRestrict(R,mglevels[i+1]->smoothd->dm->x,mglevels[i]->smoothd->dm->x);CHKERRQ(ierr); ierr = VecPointwiseMult(mglevels[i]->smoothd->dm->x,mglevels[i]->smoothd->dm->x,rscale);CHKERRQ(ierr); } } if (!mg->galerkin && pc->dm) { for (i=n-2; i>=0; i--) { DM dmfine,dmcoarse; Mat Restrict,Inject; Vec rscale; ierr = KSPGetDM(mglevels[i+1]->smoothd,&dmfine);CHKERRQ(ierr); ierr = KSPGetDM(mglevels[i]->smoothd,&dmcoarse);CHKERRQ(ierr); ierr = PCMGGetRestriction(pc,i+1,&Restrict);CHKERRQ(ierr); ierr = PCMGGetRScale(pc,i+1,&rscale);CHKERRQ(ierr); Inject = NULL; /* Callback should create it if it needs Injection */ ierr = DMRestrict(dmfine,Restrict,rscale,Inject,dmcoarse);CHKERRQ(ierr); } } if (!pc->setupcalled) { for (i=0; i<n; i++) { ierr = KSPSetFromOptions(mglevels[i]->smoothd);CHKERRQ(ierr); } for (i=1; i<n; i++) { if (mglevels[i]->smoothu && (mglevels[i]->smoothu != mglevels[i]->smoothd)) { ierr = KSPSetFromOptions(mglevels[i]->smoothu);CHKERRQ(ierr); } } /* insure that if either interpolation or restriction is set the other other one is set */ for (i=1; i<n; i++) { ierr = PCMGGetInterpolation(pc,i,NULL);CHKERRQ(ierr); ierr = PCMGGetRestriction(pc,i,NULL);CHKERRQ(ierr); } for (i=0; i<n-1; i++) { if (!mglevels[i]->b) { Vec *vec; ierr = KSPCreateVecs(mglevels[i]->smoothd,1,&vec,0,NULL);CHKERRQ(ierr); ierr = PCMGSetRhs(pc,i,*vec);CHKERRQ(ierr); ierr = VecDestroy(vec);CHKERRQ(ierr); ierr = PetscFree(vec);CHKERRQ(ierr); } if (!mglevels[i]->r && i) { ierr = VecDuplicate(mglevels[i]->b,&tvec);CHKERRQ(ierr); ierr = PCMGSetR(pc,i,tvec);CHKERRQ(ierr); ierr = VecDestroy(&tvec);CHKERRQ(ierr); } if (!mglevels[i]->x) { ierr = VecDuplicate(mglevels[i]->b,&tvec);CHKERRQ(ierr); ierr = PCMGSetX(pc,i,tvec);CHKERRQ(ierr); ierr = VecDestroy(&tvec);CHKERRQ(ierr); } } if (n != 1 && !mglevels[n-1]->r) { /* PCMGSetR() on the finest level if user did not supply it */ Vec *vec; ierr = KSPCreateVecs(mglevels[n-1]->smoothd,1,&vec,0,NULL);CHKERRQ(ierr); ierr = PCMGSetR(pc,n-1,*vec);CHKERRQ(ierr); ierr = VecDestroy(vec);CHKERRQ(ierr); ierr = PetscFree(vec);CHKERRQ(ierr); } } if (pc->dm) { /* need to tell all the coarser levels to rebuild the matrix using the DM for that level */ for (i=0; i<n-1; i++) { if (mglevels[i]->smoothd->setupstage != KSP_SETUP_NEW) mglevels[i]->smoothd->setupstage = KSP_SETUP_NEWMATRIX; } } for (i=1; i<n; i++) { if (mglevels[i]->smoothu == mglevels[i]->smoothd || mg->am == PC_MG_FULL || mg->am == PC_MG_KASKADE || mg->cyclesperpcapply > 1){ /* if doing only down then initial guess is zero */ ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothd,PETSC_TRUE);CHKERRQ(ierr); } if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} ierr = KSPSetUp(mglevels[i]->smoothd);CHKERRQ(ierr); if (mglevels[i]->smoothd->reason == KSP_DIVERGED_PCSETUP_FAILED) { pc->failedreason = PC_SUBPC_ERROR; } if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} if (!mglevels[i]->residual) { Mat mat; ierr = KSPGetOperators(mglevels[i]->smoothd,NULL,&mat);CHKERRQ(ierr); ierr = PCMGSetResidual(pc,i,PCMGResidualDefault,mat);CHKERRQ(ierr); } } for (i=1; i<n; i++) { if (mglevels[i]->smoothu && mglevels[i]->smoothu != mglevels[i]->smoothd) { Mat downmat,downpmat; /* check if operators have been set for up, if not use down operators to set them */ ierr = KSPGetOperatorsSet(mglevels[i]->smoothu,&opsset,NULL);CHKERRQ(ierr); if (!opsset) { ierr = KSPGetOperators(mglevels[i]->smoothd,&downmat,&downpmat);CHKERRQ(ierr); ierr = KSPSetOperators(mglevels[i]->smoothu,downmat,downpmat);CHKERRQ(ierr); } ierr = KSPSetInitialGuessNonzero(mglevels[i]->smoothu,PETSC_TRUE);CHKERRQ(ierr); if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventBegin(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} ierr = KSPSetUp(mglevels[i]->smoothu);CHKERRQ(ierr); if (mglevels[i]->smoothu->reason == KSP_DIVERGED_PCSETUP_FAILED) { pc->failedreason = PC_SUBPC_ERROR; } if (mglevels[i]->eventsmoothsetup) {ierr = PetscLogEventEnd(mglevels[i]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} } } if (mglevels[0]->eventsmoothsetup) {ierr = PetscLogEventBegin(mglevels[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} ierr = KSPSetUp(mglevels[0]->smoothd);CHKERRQ(ierr); if (mglevels[0]->smoothd->reason == KSP_DIVERGED_PCSETUP_FAILED) { pc->failedreason = PC_SUBPC_ERROR; } if (mglevels[0]->eventsmoothsetup) {ierr = PetscLogEventEnd(mglevels[0]->eventsmoothsetup,0,0,0,0);CHKERRQ(ierr);} /* Dump the interpolation/restriction matrices plus the Jacobian/stiffness on each level. This allows MATLAB users to easily check if the Galerkin condition A_c = R A_f R^T is satisfied. Only support one or the other at the same time. */ #if defined(PETSC_USE_SOCKET_VIEWER) ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_mg_dump_matlab",&dump,NULL);CHKERRQ(ierr); if (dump) viewer = PETSC_VIEWER_SOCKET_(PetscObjectComm((PetscObject)pc)); dump = PETSC_FALSE; #endif ierr = PetscOptionsGetBool(((PetscObject)pc)->options,((PetscObject)pc)->prefix,"-pc_mg_dump_binary",&dump,NULL);CHKERRQ(ierr); if (dump) viewer = PETSC_VIEWER_BINARY_(PetscObjectComm((PetscObject)pc)); if (viewer) { for (i=1; i<n; i++) { ierr = MatView(mglevels[i]->restrct,viewer);CHKERRQ(ierr); } for (i=0; i<n; i++) { ierr = KSPGetPC(mglevels[i]->smoothd,&pc);CHKERRQ(ierr); ierr = MatView(pc->mat,viewer);CHKERRQ(ierr); } } PetscFunctionReturn(0); }
int main(int argc,char **args) { Vec x1,b1,x2,b2; /* solution and RHS vectors for systems #1 and #2 */ Vec u; /* exact solution vector */ Mat C1,C2; /* matrices for systems #1 and #2 */ KSP ksp1,ksp2; /* KSP contexts for systems #1 and #2 */ PetscInt ntimes = 3; /* number of times to solve the linear systems */ PetscLogEvent CHECK_ERROR; /* event number for error checking */ PetscInt ldim,low,high,iglobal,Istart,Iend,Istart2,Iend2; PetscInt Ii,J,i,j,m = 3,n = 2,its,t; PetscErrorCode ierr; PetscBool flg = PETSC_FALSE; PetscScalar v; PetscMPIInt rank,size; #if defined (PETSC_USE_LOG) PetscLogStage stages[3]; #endif PetscInitialize(&argc,&args,(char *)0,help); ierr = PetscOptionsGetInt(PETSC_NULL,"-m",&m,PETSC_NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(PETSC_NULL,"-t",&ntimes,PETSC_NULL);CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); n = 2*size; /* Register various stages for profiling */ ierr = PetscLogStageRegister("Prelim setup",&stages[0]);CHKERRQ(ierr); ierr = PetscLogStageRegister("Linear System 1",&stages[1]);CHKERRQ(ierr); ierr = PetscLogStageRegister("Linear System 2",&stages[2]);CHKERRQ(ierr); /* Register a user-defined event for profiling (error checking). */ CHECK_ERROR = 0; ierr = PetscLogEventRegister("Check Error",KSP_CLASSID,&CHECK_ERROR);CHKERRQ(ierr); /* - - - - - - - - - - - - Stage 0: - - - - - - - - - - - - - - Preliminary Setup - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = PetscLogStagePush(stages[0]);CHKERRQ(ierr); /* Create data structures for first linear system. - Create parallel matrix, specifying only its global dimensions. When using MatCreate(), the matrix format can be specified at runtime. Also, the parallel partitioning of the matrix is determined by PETSc at runtime. - Create parallel vectors. - When using VecSetSizes(), we specify only the vector's global dimension; the parallel partitioning is determined at runtime. - Note: We form 1 vector from scratch and then duplicate as needed. */ ierr = MatCreate(PETSC_COMM_WORLD,&C1);CHKERRQ(ierr); ierr = MatSetSizes(C1,PETSC_DECIDE,PETSC_DECIDE,m*n,m*n);CHKERRQ(ierr); ierr = MatSetFromOptions(C1);CHKERRQ(ierr); ierr = MatSetUp(C1);CHKERRQ(ierr); ierr = MatGetOwnershipRange(C1,&Istart,&Iend);CHKERRQ(ierr); ierr = VecCreate(PETSC_COMM_WORLD,&u);CHKERRQ(ierr); ierr = VecSetSizes(u,PETSC_DECIDE,m*n);CHKERRQ(ierr); ierr = VecSetFromOptions(u);CHKERRQ(ierr); ierr = VecDuplicate(u,&b1);CHKERRQ(ierr); ierr = VecDuplicate(u,&x1);CHKERRQ(ierr); /* Create first linear solver context. Set runtime options (e.g., -pc_type <type>). Note that the first linear system uses the default option names, while the second linear systme uses a different options prefix. */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp1);CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp1);CHKERRQ(ierr); /* Set user-defined monitoring routine for first linear system. */ ierr = PetscOptionsGetBool(PETSC_NULL,"-my_ksp_monitor",&flg,PETSC_NULL);CHKERRQ(ierr); if (flg) {ierr = KSPMonitorSet(ksp1,MyKSPMonitor,PETSC_NULL,0);CHKERRQ(ierr);} /* Create data structures for second linear system. */ ierr = MatCreate(PETSC_COMM_WORLD,&C2);CHKERRQ(ierr); ierr = MatSetSizes(C2,PETSC_DECIDE,PETSC_DECIDE,m*n,m*n);CHKERRQ(ierr); ierr = MatSetFromOptions(C2);CHKERRQ(ierr); ierr = MatSetUp(C2);CHKERRQ(ierr); ierr = MatGetOwnershipRange(C2,&Istart2,&Iend2);CHKERRQ(ierr); ierr = VecDuplicate(u,&b2);CHKERRQ(ierr); ierr = VecDuplicate(u,&x2);CHKERRQ(ierr); /* Create second linear solver context */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp2);CHKERRQ(ierr); /* Set different options prefix for second linear system. Set runtime options (e.g., -s2_pc_type <type>) */ ierr = KSPAppendOptionsPrefix(ksp2,"s2_");CHKERRQ(ierr); ierr = KSPSetFromOptions(ksp2);CHKERRQ(ierr); /* Assemble exact solution vector in parallel. Note that each processor needs to set only its local part of the vector. */ ierr = VecGetLocalSize(u,&ldim);CHKERRQ(ierr); ierr = VecGetOwnershipRange(u,&low,&high);CHKERRQ(ierr); for (i=0; i<ldim; i++) { iglobal = i + low; v = (PetscScalar)(i + 100*rank); ierr = VecSetValues(u,1,&iglobal,&v,ADD_VALUES);CHKERRQ(ierr); } ierr = VecAssemblyBegin(u);CHKERRQ(ierr); ierr = VecAssemblyEnd(u);CHKERRQ(ierr); /* Log the number of flops for computing vector entries */ ierr = PetscLogFlops(2.0*ldim);CHKERRQ(ierr); /* End curent profiling stage */ ierr = PetscLogStagePop();CHKERRQ(ierr); /* -------------------------------------------------------------- Linear solver loop: Solve 2 different linear systems several times in succession -------------------------------------------------------------- */ for (t=0; t<ntimes; t++) { /* - - - - - - - - - - - - Stage 1: - - - - - - - - - - - - - - Assemble and solve first linear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Begin profiling stage #1 */ ierr = PetscLogStagePush(stages[1]);CHKERRQ(ierr); /* Initialize all matrix entries to zero. MatZeroEntries() retains the nonzero structure of the matrix for sparse formats. */ if (t > 0) {ierr = MatZeroEntries(C1);CHKERRQ(ierr);} /* Set matrix entries in parallel. Also, log the number of flops for computing matrix entries. - 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). - Always specify global row and columns of matrix entries. */ for (Ii=Istart; Ii<Iend; Ii++) { v = -1.0; i = Ii/n; j = Ii - i*n; if (i>0) {J = Ii - n; ierr = MatSetValues(C1,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (i<m-1) {J = Ii + n; ierr = MatSetValues(C1,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j>0) {J = Ii - 1; ierr = MatSetValues(C1,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j<n-1) {J = Ii + 1; ierr = MatSetValues(C1,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} v = 4.0; ierr = MatSetValues(C1,1,&Ii,1,&Ii,&v,ADD_VALUES);CHKERRQ(ierr); } for (Ii=Istart; Ii<Iend; Ii++) { /* Make matrix nonsymmetric */ v = -1.0*(t+0.5); i = Ii/n; if (i>0) {J = Ii - n; ierr = MatSetValues(C1,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} } ierr = PetscLogFlops(2.0*(Iend-Istart));CHKERRQ(ierr); /* Assemble matrix, using the 2-step process: MatAssemblyBegin(), MatAssemblyEnd() Computations can be done while messages are in transition by placing code between these two statements. */ ierr = MatAssemblyBegin(C1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(C1,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Indicate same nonzero structure of successive linear system matrices */ ierr = MatSetOption(C1,MAT_NEW_NONZERO_LOCATIONS,PETSC_TRUE);CHKERRQ(ierr); /* Compute right-hand-side vector */ ierr = MatMult(C1,u,b1);CHKERRQ(ierr); /* Set operators. Here the matrix that defines the linear system also serves as the preconditioning matrix. - The flag SAME_NONZERO_PATTERN indicates that the preconditioning matrix has identical nonzero structure as during the last linear solve (although the values of the entries have changed). 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 the second linear solve, 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! */ ierr = KSPSetOperators(ksp1,C1,C1,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* Use the previous solution of linear system #1 as the initial guess for the next solve of linear system #1. The user MUST call KSPSetInitialGuessNonzero() in indicate use of an initial guess vector; otherwise, an initial guess of zero is used. */ if (t>0) { ierr = KSPSetInitialGuessNonzero(ksp1,PETSC_TRUE);CHKERRQ(ierr); } /* Solve the first linear system. Here we explicitly call KSPSetUp() for more detailed performance monitoring of certain preconditioners, such as ICC and ILU. This call is optional, ase KSPSetUp() will automatically be called within KSPSolve() if it hasn't been called already. */ ierr = KSPSetUp(ksp1);CHKERRQ(ierr); ierr = KSPSolve(ksp1,b1,x1);CHKERRQ(ierr); ierr = KSPGetIterationNumber(ksp1,&its);CHKERRQ(ierr); /* Check error of solution to first linear system */ ierr = CheckError(u,x1,b1,its,1.e-4,CHECK_ERROR);CHKERRQ(ierr); /* - - - - - - - - - - - - Stage 2: - - - - - - - - - - - - - - Assemble and solve second linear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Conclude profiling stage #1; begin profiling stage #2 */ ierr = PetscLogStagePop();CHKERRQ(ierr); ierr = PetscLogStagePush(stages[2]);CHKERRQ(ierr); /* Initialize all matrix entries to zero */ if (t > 0) {ierr = MatZeroEntries(C2);CHKERRQ(ierr);} /* Assemble matrix in parallel. Also, log the number of flops for computing matrix entries. - To illustrate the features of parallel matrix assembly, we intentionally set the values differently from the way in which the matrix is distributed across the processors. Each entry that is not owned locally will be sent to the appropriate processor during MatAssemblyBegin() and MatAssemblyEnd(). - For best efficiency the user should strive to set as many entries locally as possible. */ for (i=0; i<m; i++) { for (j=2*rank; j<2*rank+2; j++) { v = -1.0; Ii = j + n*i; if (i>0) {J = Ii - n; ierr = MatSetValues(C2,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (i<m-1) {J = Ii + n; ierr = MatSetValues(C2,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j>0) {J = Ii - 1; ierr = MatSetValues(C2,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j<n-1) {J = Ii + 1; ierr = MatSetValues(C2,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} v = 6.0 + t*0.5; ierr = MatSetValues(C2,1,&Ii,1,&Ii,&v,ADD_VALUES);CHKERRQ(ierr); } } for (Ii=Istart2; Ii<Iend2; Ii++) { /* Make matrix nonsymmetric */ v = -1.0*(t+0.5); i = Ii/n; if (i>0) {J = Ii - n; ierr = MatSetValues(C2,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} } ierr = MatAssemblyBegin(C2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(C2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = PetscLogFlops(2.0*(Iend-Istart));CHKERRQ(ierr); /* Indicate same nonzero structure of successive linear system matrices */ ierr = MatSetOption(C2,MAT_NEW_NONZERO_LOCATIONS,PETSC_FALSE);CHKERRQ(ierr); /* Compute right-hand-side vector */ ierr = MatMult(C2,u,b2);CHKERRQ(ierr); /* Set operators. Here the matrix that defines the linear system also serves as the preconditioning matrix. Indicate same nonzero structure of successive preconditioner matrices by setting flag SAME_NONZERO_PATTERN. */ ierr = KSPSetOperators(ksp2,C2,C2,SAME_NONZERO_PATTERN);CHKERRQ(ierr); /* Solve the second linear system */ ierr = KSPSetUp(ksp2);CHKERRQ(ierr); ierr = KSPSolve(ksp2,b2,x2);CHKERRQ(ierr); ierr = KSPGetIterationNumber(ksp2,&its);CHKERRQ(ierr); /* Check error of solution to second linear system */ ierr = CheckError(u,x2,b2,its,1.e-4,CHECK_ERROR);CHKERRQ(ierr); /* Conclude profiling stage #2 */ ierr = PetscLogStagePop();CHKERRQ(ierr); } /* -------------------------------------------------------------- End of linear solver loop -------------------------------------------------------------- */ /* Free work space. All PETSc objects should be destroyed when they are no longer needed. */ ierr = KSPDestroy(&ksp1);CHKERRQ(ierr); ierr = KSPDestroy(&ksp2);CHKERRQ(ierr); ierr = VecDestroy(&x1);CHKERRQ(ierr); ierr = VecDestroy(&x2);CHKERRQ(ierr); ierr = VecDestroy(&b1);CHKERRQ(ierr); ierr = VecDestroy(&b2);CHKERRQ(ierr); ierr = MatDestroy(&C1);CHKERRQ(ierr); ierr = MatDestroy(&C2);CHKERRQ(ierr); ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
int main(int argc,char **args) { Vec x,b,u; /* approx solution, RHS, exact solution */ Mat A; /* linear system matrix */ KSP ksp; /* KSP context */ KSP *subksp; /* array of local KSP contexts on this processor */ PC pc; /* PC context */ PC subpc; /* PC context for subdomain */ PetscReal norm; /* norm of solution error */ PetscErrorCode ierr; PetscInt i,j,Ii,J,*blks,m = 4,n; PetscMPIInt rank,size; PetscInt its,nlocal,first,Istart,Iend; PetscScalar v,one = 1.0,none = -1.0; PetscBool isbjacobi; PetscInitialize(&argc,&args,(char*)0,help); ierr = PetscOptionsGetInt(NULL,"-m",&m,NULL);CHKERRQ(ierr); ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); n = m+2; /* ------------------------------------------------------------------- Compute the matrix and right-hand-side vector that define the linear system, Ax = b. ------------------------------------------------------------------- */ /* Create and assemble parallel matrix */ ierr = MatCreate(PETSC_COMM_WORLD,&A);CHKERRQ(ierr); ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,m*n,m*n);CHKERRQ(ierr); ierr = MatSetFromOptions(A);CHKERRQ(ierr); ierr = MatMPIAIJSetPreallocation(A,5,NULL,5,NULL);CHKERRQ(ierr); ierr = MatSeqAIJSetPreallocation(A,5,NULL);CHKERRQ(ierr); ierr = MatGetOwnershipRange(A,&Istart,&Iend);CHKERRQ(ierr); for (Ii=Istart; Ii<Iend; Ii++) { v = -1.0; i = Ii/n; j = Ii - i*n; if (i>0) {J = Ii - n; ierr = MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (i<m-1) {J = Ii + n; ierr = MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j>0) {J = Ii - 1; ierr = MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j<n-1) {J = Ii + 1; ierr = MatSetValues(A,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} v = 4.0; ierr = MatSetValues(A,1,&Ii,1,&Ii,&v,ADD_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* Create parallel vectors */ ierr = VecCreate(PETSC_COMM_WORLD,&u);CHKERRQ(ierr); ierr = VecSetSizes(u,PETSC_DECIDE,m*n);CHKERRQ(ierr); ierr = VecSetFromOptions(u);CHKERRQ(ierr); ierr = VecDuplicate(u,&b);CHKERRQ(ierr); ierr = VecDuplicate(b,&x);CHKERRQ(ierr); /* Set exact solution; then compute right-hand-side vector. */ ierr = VecSet(u,one);CHKERRQ(ierr); ierr = MatMult(A,u,b);CHKERRQ(ierr); /* Create linear solver context */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); /* Set operators. Here the matrix that defines the linear system also serves as the preconditioning matrix. */ ierr = KSPSetOperators(ksp,A,A);CHKERRQ(ierr); /* Set default preconditioner for this program to be block Jacobi. This choice can be overridden at runtime with the option -pc_type <type> */ ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCBJACOBI);CHKERRQ(ierr); /* ------------------------------------------------------------------- Define the problem decomposition ------------------------------------------------------------------- */ /* Call PCBJacobiSetTotalBlocks() to set individually the size of each block in the preconditioner. This could also be done with the runtime option -pc_bjacobi_blocks <blocks> Also, see the command PCBJacobiSetLocalBlocks() to set the local blocks. Note: The default decomposition is 1 block per processor. */ ierr = PetscMalloc1(m,&blks);CHKERRQ(ierr); for (i=0; i<m; i++) blks[i] = n; ierr = PCBJacobiSetTotalBlocks(pc,m,blks);CHKERRQ(ierr); ierr = PetscFree(blks);CHKERRQ(ierr); /* ------------------------------------------------------------------- Set the linear solvers for the subblocks ------------------------------------------------------------------- */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Basic method, should be sufficient for the needs of most users. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - By default, the block Jacobi method uses the same solver on each block of the problem. To set the same solver options on all blocks, use the prefix -sub before the usual PC and KSP options, e.g., -sub_pc_type <pc> -sub_ksp_type <ksp> -sub_ksp_rtol 1.e-4 */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Advanced method, setting different solvers for various blocks. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Note that each block's KSP context is completely independent of the others, and the full range of uniprocessor KSP options is available for each block. The following section of code is intended to be a simple illustration of setting different linear solvers for the individual blocks. These choices are obviously not recommended for solving this particular problem. */ ierr = PetscObjectTypeCompare((PetscObject)pc,PCBJACOBI,&isbjacobi);CHKERRQ(ierr); if (isbjacobi) { /* Call KSPSetUp() to set the block Jacobi data structures (including creation of an internal KSP context for each block). Note: KSPSetUp() MUST be called before PCBJacobiGetSubKSP(). */ ierr = KSPSetUp(ksp);CHKERRQ(ierr); /* Extract the array of KSP contexts for the local blocks */ ierr = PCBJacobiGetSubKSP(pc,&nlocal,&first,&subksp);CHKERRQ(ierr); /* Loop over the local blocks, setting various KSP options for each block. */ for (i=0; i<nlocal; i++) { ierr = KSPGetPC(subksp[i],&subpc);CHKERRQ(ierr); if (!rank) { if (i%2) { ierr = PCSetType(subpc,PCILU);CHKERRQ(ierr); } else { ierr = PCSetType(subpc,PCNONE);CHKERRQ(ierr); ierr = KSPSetType(subksp[i],KSPBCGS);CHKERRQ(ierr); ierr = KSPSetTolerances(subksp[i],1.e-6,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); } } else { ierr = PCSetType(subpc,PCJACOBI);CHKERRQ(ierr); ierr = KSPSetType(subksp[i],KSPGMRES);CHKERRQ(ierr); ierr = KSPSetTolerances(subksp[i],1.e-6,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); } } } /* ------------------------------------------------------------------- Solve the linear system ------------------------------------------------------------------- */ /* Set runtime options */ ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); /* Solve the linear system */ ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr); /* ------------------------------------------------------------------- Check solution and clean up ------------------------------------------------------------------- */ /* Check the error */ ierr = VecAXPY(x,none,u);CHKERRQ(ierr); ierr = VecNorm(x,NORM_2,&norm);CHKERRQ(ierr); ierr = KSPGetIterationNumber(ksp,&its);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Norm of error %g iterations %D\n",(double)norm,its);CHKERRQ(ierr); /* Free work space. All PETSc objects should be destroyed when they are no longer needed. */ ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = PetscFinalize(); return 0; }
int main(int argc,char **args) { Mat C; PetscScalar v,none = -1.0; PetscInt i,j,Ii,J,Istart,Iend,N,m = 4,n = 4,its,k; PetscErrorCode ierr; PetscMPIInt size,rank; PetscReal err_norm,res_norm; Vec x,b,u,u_tmp; PC pc; KSP ksp; ierr = PetscInitialize(&argc,&args,(char*)0,help);if (ierr) return ierr; ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,NULL,"-m",&m,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL);CHKERRQ(ierr); N = m*n; /* Generate matrix */ ierr = MatCreate(PETSC_COMM_WORLD,&C);CHKERRQ(ierr); ierr = MatSetSizes(C,PETSC_DECIDE,PETSC_DECIDE,N,N);CHKERRQ(ierr); ierr = MatSetFromOptions(C);CHKERRQ(ierr); ierr = MatSetUp(C);CHKERRQ(ierr); ierr = MatGetOwnershipRange(C,&Istart,&Iend);CHKERRQ(ierr); for (Ii=Istart; Ii<Iend; Ii++) { v = -1.0; i = Ii/n; j = Ii - i*n; if (i>0) {J = Ii - n; ierr = MatSetValues(C,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (i<m-1) {J = Ii + n; ierr = MatSetValues(C,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j>0) {J = Ii - 1; ierr = MatSetValues(C,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} if (j<n-1) {J = Ii + 1; ierr = MatSetValues(C,1,&Ii,1,&J,&v,ADD_VALUES);CHKERRQ(ierr);} v = 4.0; ierr = MatSetValues(C,1,&Ii,1,&Ii,&v,ADD_VALUES);CHKERRQ(ierr); } ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); /* a shift can make C indefinite. Preconditioners LU, ILU (for BAIJ format) and ICC may fail */ /* ierr = MatShift(C,alpha);CHKERRQ(ierr); */ /* ierr = MatView(C,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); */ /* Setup and solve for system */ /* Create vectors. */ ierr = VecCreate(PETSC_COMM_WORLD,&x);CHKERRQ(ierr); ierr = VecSetSizes(x,PETSC_DECIDE,N);CHKERRQ(ierr); ierr = VecSetFromOptions(x);CHKERRQ(ierr); ierr = VecDuplicate(x,&b);CHKERRQ(ierr); ierr = VecDuplicate(x,&u);CHKERRQ(ierr); ierr = VecDuplicate(x,&u_tmp);CHKERRQ(ierr); /* Set exact solution u; then compute right-hand-side vector b. */ ierr = VecSet(u,1.0);CHKERRQ(ierr); ierr = MatMult(C,u,b);CHKERRQ(ierr); for (k=0; k<3; k++) { if (k == 0) { /* CG */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,C,C);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"\n CG: \n");CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPCG);CHKERRQ(ierr); } else if (k == 1) { /* MINRES */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,C,C);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"\n MINRES: \n");CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPMINRES);CHKERRQ(ierr); } else { /* SYMMLQ */ ierr = KSPCreate(PETSC_COMM_WORLD,&ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,C,C);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"\n SYMMLQ: \n");CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPSYMMLQ);CHKERRQ(ierr); } ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); /* ierr = PCSetType(pc,PCICC);CHKERRQ(ierr); */ ierr = PCSetType(pc,PCJACOBI);CHKERRQ(ierr); ierr = KSPSetTolerances(ksp,1.e-7,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); /* Set runtime options, e.g., -ksp_type <type> -pc_type <type> -ksp_monitor -ksp_rtol <rtol> These options will override those specified above as long as KSPSetFromOptions() is called _after_ any other customization routines. */ ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); /* Solve linear system; */ ierr = KSPSetUp(ksp);CHKERRQ(ierr); ierr = KSPSolve(ksp,b,x);CHKERRQ(ierr); ierr = KSPGetIterationNumber(ksp,&its);CHKERRQ(ierr); /* Check error */ ierr = VecCopy(u,u_tmp);CHKERRQ(ierr); ierr = VecAXPY(u_tmp,none,x);CHKERRQ(ierr); ierr = VecNorm(u_tmp,NORM_2,&err_norm);CHKERRQ(ierr); ierr = MatMult(C,x,u_tmp);CHKERRQ(ierr); ierr = VecAXPY(u_tmp,none,b);CHKERRQ(ierr); ierr = VecNorm(u_tmp,NORM_2,&res_norm);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Number of iterations = %3D\n",its);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"Residual norm %g;",(double)res_norm);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD," Error norm %g.\n",(double)err_norm);CHKERRQ(ierr); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); } /* Free work space. All PETSc objects should be destroyed when they are no longer needed. */ ierr = VecDestroy(&b);CHKERRQ(ierr); ierr = VecDestroy(&u);CHKERRQ(ierr); ierr = VecDestroy(&x);CHKERRQ(ierr); ierr = VecDestroy(&u_tmp);CHKERRQ(ierr); ierr = MatDestroy(&C);CHKERRQ(ierr); ierr = PetscFinalize(); return ierr; }
int main(int argc,char **argv) { KSP ksp; PC pc; Mat A,M; Vec X,B,D; MPI_Comm comm; PetscScalar v; KSPConvergedReason reason; PetscInt i,j,its; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscInitialize(&argc,&argv,0,help);CHKERRQ(ierr); ierr = PetscOptionsSetValue("-options_left",PETSC_NULL);CHKERRQ(ierr); comm = MPI_COMM_SELF; /* * Construct the Kershaw matrix * and a suitable rhs / initial guess */ ierr = MatCreateSeqAIJ(comm,4,4,4,0,&A);CHKERRQ(ierr); ierr = VecCreateSeq(comm,4,&B);CHKERRQ(ierr); ierr = VecDuplicate(B,&X);CHKERRQ(ierr); for (i=0; i<4; i++) { v=3; ierr = MatSetValues(A,1,&i,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); v=1; ierr = VecSetValues(B,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); ierr = VecSetValues(X,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); } i=0; v=0; ierr = VecSetValues(X,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); for (i=0; i<3; i++) { v=-2; j=i+1; ierr = MatSetValues(A,1,&i,1,&j,&v,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(A,1,&j,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); } i=0; j=3; v=2; ierr = MatSetValues(A,1,&i,1,&j,&v,INSERT_VALUES);CHKERRQ(ierr); ierr = MatSetValues(A,1,&j,1,&i,&v,INSERT_VALUES);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = VecAssemblyBegin(B);CHKERRQ(ierr); ierr = VecAssemblyEnd(B);CHKERRQ(ierr); printf("\nThe Kershaw matrix:\n\n"); MatView(A,0); /* * A Conjugate Gradient method * with ILU(0) preconditioning */ ierr = KSPCreate(comm,&ksp);CHKERRQ(ierr); ierr = KSPSetOperators(ksp,A,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); ierr = KSPSetType(ksp,KSPCG);CHKERRQ(ierr); ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr); /* * ILU preconditioner; * The iterative method will break down unless you comment in the SetShift * line below, or use the -pc_factor_shift_positive_definite option. * Run the code twice: once as given to see the negative pivot and the * divergence behaviour, then comment in the Shift line, or add the * command line option, and see that the pivots are all positive and * the method converges. */ ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCICC);CHKERRQ(ierr); /* ierr = PCFactorSetShiftType(prec,MAT_SHIFT_POSITIVE_DEFINITE);CHKERRQ(ierr); */ ierr = KSPSetFromOptions(ksp);CHKERRQ(ierr); ierr = KSPSetUp(ksp);CHKERRQ(ierr); /* * Now that the factorisation is done, show the pivots; * note that the last one is negative. This in itself is not an error, * but it will make the iterative method diverge. */ ierr = PCFactorGetMatrix(pc,&M);CHKERRQ(ierr); ierr = VecDuplicate(B,&D);CHKERRQ(ierr); ierr = MatGetDiagonal(M,D);CHKERRQ(ierr); printf("\nPivots:\n\n"); VecView(D,0); /* * Solve the system; * without the shift this will diverge with * an indefinite preconditioner */ ierr = KSPSolve(ksp,B,X);CHKERRQ(ierr); ierr = KSPGetConvergedReason(ksp,&reason);CHKERRQ(ierr); if (reason==KSP_DIVERGED_INDEFINITE_PC) { printf("\nDivergence because of indefinite preconditioner;\n"); printf("Run the executable again but with -pc_factor_shift_positive_definite option.\n"); } else if (reason<0) { printf("\nOther kind of divergence: this should not happen.\n"); } else { ierr = KSPGetIterationNumber(ksp,&its);CHKERRQ(ierr); printf("\nConvergence in %d iterations.\n",(int)its); } printf("\n"); ierr = KSPDestroy(&ksp);CHKERRQ(ierr); ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = VecDestroy(&B);CHKERRQ(ierr); ierr = VecDestroy(&X);CHKERRQ(ierr); ierr = VecDestroy(&D);CHKERRQ(ierr); PetscFinalize(); PetscFunctionReturn(0); }
PetscErrorCode PCISSetUp(PC pc) { PC_IS *pcis = (PC_IS*)(pc->data); Mat_IS *matis; PetscErrorCode ierr; PetscBool flg,issbaij; Vec counter; PetscFunctionBegin; ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&flg);CHKERRQ(ierr); if (!flg) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"Preconditioner type of Neumann Neumman requires matrix of type MATIS"); matis = (Mat_IS*)pc->pmat->data; pcis->pure_neumann = matis->pure_neumann; /* get info on mapping */ ierr = PetscObjectReference((PetscObject)matis->mapping);CHKERRQ(ierr); ierr = ISLocalToGlobalMappingDestroy(&pcis->mapping);CHKERRQ(ierr); pcis->mapping = matis->mapping; ierr = ISLocalToGlobalMappingGetSize(pcis->mapping,&pcis->n);CHKERRQ(ierr); ierr = ISLocalToGlobalMappingGetInfo(pcis->mapping,&(pcis->n_neigh),&(pcis->neigh),&(pcis->n_shared),&(pcis->shared));CHKERRQ(ierr); /* Creating local and global index sets for interior and inteface nodes. */ { PetscInt n_I; PetscInt *idx_I_local,*idx_B_local,*idx_I_global,*idx_B_global; PetscInt *array; PetscInt i,j; /* Identifying interior and interface nodes, in local numbering */ ierr = PetscMalloc1(pcis->n,&array);CHKERRQ(ierr); ierr = PetscMemzero(array,pcis->n*sizeof(PetscInt));CHKERRQ(ierr); for (i=0;i<pcis->n_neigh;i++) for (j=0;j<pcis->n_shared[i];j++) array[pcis->shared[i][j]] += 1; ierr = PetscMalloc1(pcis->n,&idx_I_local);CHKERRQ(ierr); ierr = PetscMalloc1(pcis->n,&idx_B_local);CHKERRQ(ierr); for (i=0, pcis->n_B=0, n_I=0; i<pcis->n; i++) { if (!array[i]) { idx_I_local[n_I] = i; n_I++; } else { idx_B_local[pcis->n_B] = i; pcis->n_B++; } } /* Getting the global numbering */ idx_B_global = idx_I_local + n_I; /* Just avoiding allocating extra memory, since we have vacant space */ idx_I_global = idx_B_local + pcis->n_B; ierr = ISLocalToGlobalMappingApply(pcis->mapping,pcis->n_B,idx_B_local,idx_B_global);CHKERRQ(ierr); ierr = ISLocalToGlobalMappingApply(pcis->mapping,n_I, idx_I_local,idx_I_global);CHKERRQ(ierr); /* Creating the index sets. */ ierr = ISCreateGeneral(PETSC_COMM_SELF,pcis->n_B,idx_B_local,PETSC_COPY_VALUES, &pcis->is_B_local);CHKERRQ(ierr); ierr = ISCreateGeneral(PETSC_COMM_SELF,pcis->n_B,idx_B_global,PETSC_COPY_VALUES,&pcis->is_B_global);CHKERRQ(ierr); ierr = ISCreateGeneral(PETSC_COMM_SELF,n_I,idx_I_local,PETSC_COPY_VALUES, &pcis->is_I_local);CHKERRQ(ierr); ierr = ISCreateGeneral(PETSC_COMM_SELF,n_I,idx_I_global,PETSC_COPY_VALUES,&pcis->is_I_global);CHKERRQ(ierr); /* Freeing memory and restoring arrays */ ierr = PetscFree(idx_B_local);CHKERRQ(ierr); ierr = PetscFree(idx_I_local);CHKERRQ(ierr); ierr = PetscFree(array);CHKERRQ(ierr); } /* Extracting the blocks A_II, A_BI, A_IB and A_BB from A. If the numbering is such that interior nodes come first than the interface ones, we have [ | ] [ A_II | A_IB ] A = [ | ] [-----------+------] [ A_BI | A_BB ] */ ierr = MatGetSubMatrix(matis->A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_II);CHKERRQ(ierr); ierr = MatGetSubMatrix(matis->A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr); ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr); if (!issbaij) { ierr = MatGetSubMatrix(matis->A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr); ierr = MatGetSubMatrix(matis->A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr); } else { Mat newmat; ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&newmat);CHKERRQ(ierr); ierr = MatGetSubMatrix(newmat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr); ierr = MatGetSubMatrix(newmat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr); ierr = MatDestroy(&newmat);CHKERRQ(ierr); } /* Creating work vectors and arrays */ ierr = VecDuplicate(matis->x,&pcis->vec1_N);CHKERRQ(ierr); ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,pcis->n-pcis->n_B,&pcis->vec1_D);CHKERRQ(ierr); ierr = VecDuplicate(pcis->vec1_D,&pcis->vec2_D);CHKERRQ(ierr); ierr = VecDuplicate(pcis->vec1_D,&pcis->vec3_D);CHKERRQ(ierr); ierr = VecDuplicate(pcis->vec1_D,&pcis->vec4_D);CHKERRQ(ierr); ierr = VecCreateSeq(PETSC_COMM_SELF,pcis->n_B,&pcis->vec1_B);CHKERRQ(ierr); ierr = VecDuplicate(pcis->vec1_B,&pcis->vec2_B);CHKERRQ(ierr); ierr = VecDuplicate(pcis->vec1_B,&pcis->vec3_B);CHKERRQ(ierr); ierr = MatCreateVecs(pc->pmat,&pcis->vec1_global,0);CHKERRQ(ierr); ierr = PetscMalloc1(pcis->n,&pcis->work_N);CHKERRQ(ierr); /* Creating the scatter contexts */ ierr = VecScatterCreate(pcis->vec1_global,pcis->is_I_global,pcis->vec1_D,(IS)0,&pcis->global_to_D);CHKERRQ(ierr); ierr = VecScatterCreate(pcis->vec1_N,pcis->is_B_local,pcis->vec1_B,(IS)0,&pcis->N_to_B);CHKERRQ(ierr); ierr = VecScatterCreate(pcis->vec1_global,pcis->is_B_global,pcis->vec1_B,(IS)0,&pcis->global_to_B);CHKERRQ(ierr); /* Creating scaling "matrix" D */ ierr = PetscOptionsGetBool(((PetscObject)pc)->prefix,"-pc_is_use_stiffness_scaling",&pcis->use_stiffness_scaling,NULL);CHKERRQ(ierr); if (!pcis->D) { ierr = VecDuplicate(pcis->vec1_B,&pcis->D);CHKERRQ(ierr); if (!pcis->use_stiffness_scaling) { ierr = VecSet(pcis->D,pcis->scaling_factor);CHKERRQ(ierr); } else { ierr = MatGetDiagonal(matis->A,pcis->vec1_N);CHKERRQ(ierr); ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd (pcis->N_to_B,pcis->vec1_N,pcis->D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); } } ierr = VecCopy(pcis->D,pcis->vec1_B);CHKERRQ(ierr); ierr = MatCreateVecs(pc->pmat,&counter,0);CHKERRQ(ierr); /* temporary auxiliar vector */ ierr = VecSet(counter,0.0);CHKERRQ(ierr); ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterEnd (pcis->global_to_B,pcis->vec1_B,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterBegin(pcis->global_to_B,counter,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd (pcis->global_to_B,counter,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecPointwiseDivide(pcis->D,pcis->D,pcis->vec1_B);CHKERRQ(ierr); ierr = VecDestroy(&counter);CHKERRQ(ierr); /* See historical note 01, at the bottom of this file. */ /* Creating the KSP contexts for the local Dirichlet and Neumann problems. */ if (pcis->computesolvers) { PC pc_ctx; /* Dirichlet */ ierr = KSPCreate(PETSC_COMM_SELF,&pcis->ksp_D);CHKERRQ(ierr); ierr = PetscObjectIncrementTabLevel((PetscObject)pcis->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr); ierr = KSPSetOperators(pcis->ksp_D,pcis->A_II,pcis->A_II);CHKERRQ(ierr); ierr = KSPSetOptionsPrefix(pcis->ksp_D,"is_localD_");CHKERRQ(ierr); ierr = KSPGetPC(pcis->ksp_D,&pc_ctx);CHKERRQ(ierr); ierr = PCSetType(pc_ctx,PCLU);CHKERRQ(ierr); ierr = KSPSetType(pcis->ksp_D,KSPPREONLY);CHKERRQ(ierr); ierr = KSPSetFromOptions(pcis->ksp_D);CHKERRQ(ierr); /* the vectors in the following line are dummy arguments, just telling the KSP the vector size. Values are not used */ ierr = KSPSetUp(pcis->ksp_D);CHKERRQ(ierr); /* Neumann */ ierr = KSPCreate(PETSC_COMM_SELF,&pcis->ksp_N);CHKERRQ(ierr); ierr = PetscObjectIncrementTabLevel((PetscObject)pcis->ksp_N,(PetscObject)pc,1);CHKERRQ(ierr); ierr = KSPSetOperators(pcis->ksp_N,matis->A,matis->A);CHKERRQ(ierr); ierr = KSPSetOptionsPrefix(pcis->ksp_N,"is_localN_");CHKERRQ(ierr); ierr = KSPGetPC(pcis->ksp_N,&pc_ctx);CHKERRQ(ierr); ierr = PCSetType(pc_ctx,PCLU);CHKERRQ(ierr); ierr = KSPSetType(pcis->ksp_N,KSPPREONLY);CHKERRQ(ierr); ierr = KSPSetFromOptions(pcis->ksp_N);CHKERRQ(ierr); { PetscBool damp_fixed = PETSC_FALSE, remove_nullspace_fixed = PETSC_FALSE, set_damping_factor_floating = PETSC_FALSE, not_damp_floating = PETSC_FALSE, not_remove_nullspace_floating = PETSC_FALSE; PetscReal fixed_factor, floating_factor; ierr = PetscOptionsGetReal(((PetscObject)pc_ctx)->prefix,"-pc_is_damp_fixed",&fixed_factor,&damp_fixed);CHKERRQ(ierr); if (!damp_fixed) fixed_factor = 0.0; ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_damp_fixed",&damp_fixed,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_remove_nullspace_fixed",&remove_nullspace_fixed,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(((PetscObject)pc_ctx)->prefix,"-pc_is_set_damping_factor_floating", &floating_factor,&set_damping_factor_floating);CHKERRQ(ierr); if (!set_damping_factor_floating) floating_factor = 0.0; ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_set_damping_factor_floating",&set_damping_factor_floating,NULL);CHKERRQ(ierr); if (!set_damping_factor_floating) floating_factor = 1.e-12; ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_not_damp_floating",¬_damp_floating,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_not_remove_nullspace_floating",¬_remove_nullspace_floating,NULL);CHKERRQ(ierr); if (pcis->pure_neumann) { /* floating subdomain */ if (!(not_damp_floating)) { ierr = PCFactorSetShiftType(pc_ctx,MAT_SHIFT_NONZERO);CHKERRQ(ierr); ierr = PCFactorSetShiftAmount(pc_ctx,floating_factor);CHKERRQ(ierr); } if (!(not_remove_nullspace_floating)) { MatNullSpace nullsp; ierr = MatNullSpaceCreate(PETSC_COMM_SELF,PETSC_TRUE,0,NULL,&nullsp);CHKERRQ(ierr); ierr = KSPSetNullSpace(pcis->ksp_N,nullsp);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullsp);CHKERRQ(ierr); } } else { /* fixed subdomain */ if (damp_fixed) { ierr = PCFactorSetShiftType(pc_ctx,MAT_SHIFT_NONZERO);CHKERRQ(ierr); ierr = PCFactorSetShiftAmount(pc_ctx,floating_factor);CHKERRQ(ierr); } if (remove_nullspace_fixed) { MatNullSpace nullsp; ierr = MatNullSpaceCreate(PETSC_COMM_SELF,PETSC_TRUE,0,NULL,&nullsp);CHKERRQ(ierr); ierr = KSPSetNullSpace(pcis->ksp_N,nullsp);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nullsp);CHKERRQ(ierr); } } } /* the vectors in the following line are dummy arguments, just telling the KSP the vector size. Values are not used */ ierr = KSPSetUp(pcis->ksp_N);CHKERRQ(ierr); } PetscFunctionReturn(0); }