static PetscErrorCode PCSetUp_LSC(PC pc) { PC_LSC *lsc = (PC_LSC*)pc->data; Mat L,Lp,B,C; PetscErrorCode ierr; PetscFunctionBegin; ierr = PCLSCAllocate_Private(pc);CHKERRQ(ierr); ierr = PetscObjectQuery((PetscObject)pc->mat,"LSC_L",(PetscObject*)&L);CHKERRQ(ierr); if (!L) {ierr = PetscObjectQuery((PetscObject)pc->pmat,"LSC_L",(PetscObject*)&L);CHKERRQ(ierr);} ierr = PetscObjectQuery((PetscObject)pc->pmat,"LSC_Lp",(PetscObject*)&Lp);CHKERRQ(ierr); if (!Lp) {ierr = PetscObjectQuery((PetscObject)pc->mat,"LSC_Lp",(PetscObject*)&Lp);CHKERRQ(ierr);} if (!L) { ierr = MatSchurComplementGetSubMatrices(pc->mat,NULL,NULL,&B,&C,NULL);CHKERRQ(ierr); if (!lsc->L) { ierr = MatMatMult(C,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&lsc->L);CHKERRQ(ierr); } else { ierr = MatMatMult(C,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&lsc->L);CHKERRQ(ierr); } Lp = L = lsc->L; } if (lsc->scale) { Mat Ap; ierr = MatSchurComplementGetSubMatrices(pc->mat,NULL,&Ap,NULL,NULL,NULL);CHKERRQ(ierr); ierr = MatGetDiagonal(Ap,lsc->scale);CHKERRQ(ierr); /* Should be the mass matrix, but we don't have plumbing for that yet */ ierr = VecReciprocal(lsc->scale);CHKERRQ(ierr); } ierr = KSPSetOperators(lsc->kspL,L,Lp);CHKERRQ(ierr); ierr = KSPSetFromOptions(lsc->kspL);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); }
/*@ 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); }
PetscErrorCode MatSchurComplementGetPmat_Basic(Mat S,MatReuse preuse,Mat *Spmat) { Mat A,B,C,D; Mat_SchurComplement *schur = (Mat_SchurComplement *)S->data; PetscErrorCode ierr; PetscFunctionBegin; if (preuse == MAT_IGNORE_MATRIX) PetscFunctionReturn(0); ierr = MatSchurComplementGetSubMatrices(S,&A,NULL,&B,&C,&D);CHKERRQ(ierr); if (!A) SETERRQ(PetscObjectComm((PetscObject)S),PETSC_ERR_ARG_WRONGSTATE,"Schur complement component matrices unset"); ierr = MatCreateSchurComplementPmat(A,B,C,D,schur->ainvtype,preuse,Spmat);CHKERRQ(ierr); PetscFunctionReturn(0); }
/* Developer Notes: This should be implemented with a MatCreate_SchurComplement() as that is the standard design for new Mat classes. */ PetscErrorCode MatGetSchurComplement_Basic(Mat mat,IS isrow0,IS iscol0,IS isrow1,IS iscol1,MatReuse mreuse,Mat *newmat,MatSchurComplementAinvType ainvtype, MatReuse preuse,Mat *newpmat) { PetscErrorCode ierr; Mat A=0,Ap=0,B=0,C=0,D=0; PetscFunctionBegin; PetscValidHeaderSpecific(mat,MAT_CLASSID,1); PetscValidType(mat,1); PetscValidHeaderSpecific(isrow0,IS_CLASSID,2); PetscValidHeaderSpecific(iscol0,IS_CLASSID,3); PetscValidHeaderSpecific(isrow1,IS_CLASSID,4); PetscValidHeaderSpecific(iscol1,IS_CLASSID,5); if (mreuse == MAT_IGNORE_MATRIX && preuse == MAT_IGNORE_MATRIX) PetscFunctionReturn(0); if (mreuse == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat,MAT_CLASSID,7); if (preuse == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newpmat,MAT_CLASSID,9); if (mat->factortype) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Not for factored matrix"); if (mreuse != MAT_IGNORE_MATRIX) { /* Use MatSchurComplement */ if (mreuse == MAT_REUSE_MATRIX) { ierr = MatSchurComplementGetSubMatrices(*newmat,&A,&Ap,&B,&C,&D);CHKERRQ(ierr); if (!A || !Ap || !B || !C) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Attempting to reuse matrix but Schur complement matrices unset"); if (A != Ap) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_ARG_WRONGSTATE,"Preconditioning matrix does not match operator"); ierr = MatDestroy(&Ap);CHKERRQ(ierr); /* get rid of extra reference */ } } ierr = MatGetSubMatrix(mat,isrow0,iscol0,mreuse,&A);CHKERRQ(ierr); ierr = MatGetSubMatrix(mat,isrow0,iscol1,mreuse,&B);CHKERRQ(ierr); ierr = MatGetSubMatrix(mat,isrow1,iscol0,mreuse,&C);CHKERRQ(ierr); ierr = MatGetSubMatrix(mat,isrow1,iscol1,mreuse,&D);CHKERRQ(ierr); switch (mreuse) { case MAT_INITIAL_MATRIX: ierr = MatCreateSchurComplement(A,A,B,C,D,newmat);CHKERRQ(ierr); break; case MAT_REUSE_MATRIX: ierr = MatSchurComplementUpdateSubMatrices(*newmat,A,A,B,C,D);CHKERRQ(ierr); break; default: if (mreuse != MAT_IGNORE_MATRIX) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Unrecognized value of mreuse"); } if (preuse != MAT_IGNORE_MATRIX) { ierr = MatCreateSchurComplementPmat(A,B,C,D,ainvtype,preuse,newpmat);CHKERRQ(ierr); } ierr = MatDestroy(&A);CHKERRQ(ierr); ierr = MatDestroy(&B);CHKERRQ(ierr); ierr = MatDestroy(&C);CHKERRQ(ierr); ierr = MatDestroy(&D);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode PCApply_LSC(PC pc,Vec x,Vec y) { PC_LSC *lsc = (PC_LSC*)pc->data; Mat A,B,C; PetscErrorCode ierr; PetscFunctionBegin; ierr = MatSchurComplementGetSubMatrices(pc->mat,&A,NULL,&B,&C,NULL);CHKERRQ(ierr); ierr = KSPSolve(lsc->kspL,x,lsc->x1);CHKERRQ(ierr); ierr = MatMult(B,lsc->x1,lsc->x0);CHKERRQ(ierr); if (lsc->scale) { ierr = VecPointwiseMult(lsc->x0,lsc->x0,lsc->scale);CHKERRQ(ierr); } ierr = MatMult(A,lsc->x0,lsc->y0);CHKERRQ(ierr); if (lsc->scale) { ierr = VecPointwiseMult(lsc->y0,lsc->y0,lsc->scale);CHKERRQ(ierr); } ierr = MatMult(C,lsc->y0,lsc->x1);CHKERRQ(ierr); ierr = KSPSolve(lsc->kspL,lsc->x1,y);CHKERRQ(ierr); PetscFunctionReturn(0); }
static PetscErrorCode PCLSCAllocate_Private(PC pc) { PC_LSC *lsc = (PC_LSC*)pc->data; Mat A; PetscErrorCode ierr; PetscFunctionBegin; if (lsc->allocated) PetscFunctionReturn(0); ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&lsc->kspL);CHKERRQ(ierr); ierr = KSPSetErrorIfNotConverged(lsc->kspL,pc->erroriffailure);CHKERRQ(ierr); ierr = PetscObjectIncrementTabLevel((PetscObject)lsc->kspL,(PetscObject)pc,1);CHKERRQ(ierr); ierr = KSPSetType(lsc->kspL,KSPPREONLY);CHKERRQ(ierr); ierr = KSPSetOptionsPrefix(lsc->kspL,((PetscObject)pc)->prefix);CHKERRQ(ierr); ierr = KSPAppendOptionsPrefix(lsc->kspL,"lsc_");CHKERRQ(ierr); ierr = MatSchurComplementGetSubMatrices(pc->mat,&A,NULL,NULL,NULL,NULL);CHKERRQ(ierr); ierr = MatCreateVecs(A,&lsc->x0,&lsc->y0);CHKERRQ(ierr); ierr = MatCreateVecs(pc->pmat,&lsc->x1,NULL);CHKERRQ(ierr); if (lsc->scalediag) { ierr = VecDuplicate(lsc->x0,&lsc->scale);CHKERRQ(ierr); } lsc->allocated = PETSC_TRUE; PetscFunctionReturn(0); }
static PetscErrorCode PCSetUp_PCD_Feelpp(PC pc) { PetscErrorCode ierr; PC_PCD_Feelpp *pcpcd = (PC_PCD_Feelpp*)pc->data; if ( !pcpcd->allocated ) { ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&pcpcd->kspAp);CHKERRQ(ierr); ierr = PetscObjectIncrementTabLevel((PetscObject)pcpcd->kspAp,(PetscObject)pc,1);CHKERRQ(ierr); ierr = KSPSetType(pcpcd->kspAp,KSPPREONLY);CHKERRQ(ierr); ierr = KSPSetOptionsPrefix(pcpcd->kspAp,((PetscObject)pc)->prefix);CHKERRQ(ierr); ierr = KSPAppendOptionsPrefix(pcpcd->kspAp,"pcd_Ap");CHKERRQ(ierr); ierr = KSPSetFromOptions(pcpcd->kspAp);CHKERRQ(ierr); ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&pcpcd->kspMp);CHKERRQ(ierr); ierr = PetscObjectIncrementTabLevel((PetscObject)pcpcd->kspMp,(PetscObject)pc,1);CHKERRQ(ierr); ierr = KSPSetType(pcpcd->kspMp,KSPPREONLY);CHKERRQ(ierr); ierr = KSPSetOptionsPrefix(pcpcd->kspMp,((PetscObject)pc)->prefix);CHKERRQ(ierr); ierr = KSPAppendOptionsPrefix(pcpcd->kspMp,"pcd_Mp");CHKERRQ(ierr); ierr = KSPSetFromOptions(pcpcd->kspMp);CHKERRQ(ierr); #if PETSC_VERSION_LESS_THAN(3,6,0) ierr = MatGetVecs(pcpcd->matFp,&pcpcd->x2,&pcpcd->x1);CHKERRQ(ierr); #else ierr = MatCreateVecs(pcpcd->matFp,&pcpcd->x2,&pcpcd->x1);CHKERRQ(ierr); #endif pcpcd->allocated = PETSC_TRUE; } PetscBool isBTBt; PetscStrcmp(pcpcd->pcdApType,"BTBt",&isBTBt); if ( isBTBt ) { if (!pcpcd->MvDiag ) { #if PETSC_VERSION_LESS_THAN(3,6,0) ierr = MatGetVecs(pcpcd->matMv,&pcpcd->MvDiag,NULL);CHKERRQ(ierr); #else ierr = MatCreateVecs(pcpcd->matMv,&pcpcd->MvDiag,NULL);CHKERRQ(ierr); #endif } Mat B, C; #if PETSC_VERSION_GREATER_OR_EQUAL_THAN( 3,5,0 ) ierr = MatSchurComplementGetSubMatrices(pc->mat,NULL,NULL,&B,&C,NULL);CHKERRQ(ierr); #else ierr = MatSchurComplementGetSubmatrices(pc->mat,NULL,NULL,&B,&C,NULL);CHKERRQ(ierr); #endif ierr = MatGetDiagonal(pcpcd->matMv,pcpcd->MvDiag);CHKERRQ(ierr); ierr = VecReciprocal(pcpcd->MvDiag);CHKERRQ(ierr); // diag(F)^-1 * B ierr = MatDiagonalScale( B, pcpcd->MvDiag ,NULL);CHKERRQ(ierr); // C* diag(F)^-1 * B if ( !pcpcd->matApBTBt ) ierr = MatMatMult(C,B,MAT_INITIAL_MATRIX,PETSC_DEFAULT,&pcpcd->matApBTBt); else ierr = MatMatMult(C,B,MAT_REUSE_MATRIX,PETSC_DEFAULT,&pcpcd->matApBTBt); CHKERRQ(ierr); ierr = VecReciprocal(pcpcd->MvDiag);CHKERRQ(ierr); ierr = MatDiagonalScale( B, pcpcd->MvDiag ,NULL);CHKERRQ(ierr); pcpcd->matAp = pcpcd->matApBTBt; } else pcpcd->matAp = pcpcd->matApLaplacian; #if PETSC_VERSION_GREATER_OR_EQUAL_THAN( 3,5,0 ) ierr = KSPSetOperators(pcpcd->kspAp,pcpcd->matAp,pcpcd->matAp);CHKERRQ(ierr); ierr = KSPSetOperators(pcpcd->kspMp,pcpcd->matMp,pcpcd->matMp);CHKERRQ(ierr); #else ierr = KSPSetOperators(pcpcd->kspAp,pcpcd->matAp,pcpcd->matAp,SAME_PRECONDITIONER);CHKERRQ(ierr); ierr = KSPSetOperators(pcpcd->kspMp,pcpcd->matMp,pcpcd->matMp,SAME_PRECONDITIONER);CHKERRQ(ierr); #endif PetscFunctionReturn(0); }
PetscErrorCode PCBDDCSubSchursSetUp(PCBDDCSubSchurs sub_schurs, Mat S, IS is_A_I, IS is_A_B, PetscInt ncc, IS is_cc[], PetscInt xadj[], PetscInt adjncy[], PetscInt nlayers) { Mat A_II,A_IB,A_BI,A_BB; ISLocalToGlobalMapping BtoNmap,ItoNmap; PetscBT touched; PetscInt i,n_I,n_B,n_local,*local_numbering; PetscBool is_sorted; PetscErrorCode ierr; PetscFunctionBegin; ierr = ISSorted(is_A_I,&is_sorted);CHKERRQ(ierr); if (!is_sorted) { SETERRQ(PetscObjectComm((PetscObject)is_A_I),PETSC_ERR_PLIB,"IS for I dofs should be shorted"); } ierr = ISSorted(is_A_B,&is_sorted);CHKERRQ(ierr); if (!is_sorted) { SETERRQ(PetscObjectComm((PetscObject)is_A_B),PETSC_ERR_PLIB,"IS for B dofs should be shorted"); } /* get sizes */ ierr = ISGetLocalSize(is_A_I,&n_I);CHKERRQ(ierr); ierr = ISGetLocalSize(is_A_B,&n_B);CHKERRQ(ierr); n_local = n_I+n_B; /* maps */ ierr = ISLocalToGlobalMappingCreateIS(is_A_B,&BtoNmap);CHKERRQ(ierr); if (nlayers >= 0 && xadj != NULL && adjncy != NULL) { /* I problems have a different size of the original ones */ ierr = ISLocalToGlobalMappingCreateIS(is_A_I,&ItoNmap);CHKERRQ(ierr); /* allocate some auxiliary space */ ierr = PetscMalloc1(n_local,&local_numbering);CHKERRQ(ierr); ierr = PetscBTCreate(n_local,&touched);CHKERRQ(ierr); } else { ItoNmap = 0; local_numbering = 0; touched = 0; } /* get Schur complement matrices */ ierr = MatSchurComplementGetSubMatrices(S,&A_II,NULL,&A_IB,&A_BI,&A_BB);CHKERRQ(ierr); /* allocate space for schur complements */ ierr = PetscMalloc5(ncc,&sub_schurs->is_AEj_I,ncc,&sub_schurs->is_AEj_B,ncc,&sub_schurs->S_Ej,ncc,&sub_schurs->work1,ncc,&sub_schurs->work2);CHKERRQ(ierr); sub_schurs->n_subs = ncc; /* cycle on subsets and extract schur complements */ for (i=0;i<sub_schurs->n_subs;i++) { Mat AE_II,AE_IE,AE_EI,AE_EE; IS is_I,is_subset_B; /* get IS for subsets in B numbering */ ierr = ISDuplicate(is_cc[i],&sub_schurs->is_AEj_B[i]);CHKERRQ(ierr); ierr = ISSort(sub_schurs->is_AEj_B[i]);CHKERRQ(ierr); ierr = ISGlobalToLocalMappingApplyIS(BtoNmap,IS_GTOLM_DROP,sub_schurs->is_AEj_B[i],&is_subset_B);CHKERRQ(ierr); /* BB block on subset */ ierr = MatGetSubMatrix(A_BB,is_subset_B,is_subset_B,MAT_INITIAL_MATRIX,&AE_EE);CHKERRQ(ierr); if (ItoNmap) { /* is ItoNmap has been computed, extracts only a part of I dofs */ const PetscInt* idx_B; PetscInt n_local_dofs,n_prev_added,j,layer,subset_size; /* all boundary dofs must be skipped when adding layers */ ierr = PetscBTMemzero(n_local,touched);CHKERRQ(ierr); ierr = ISGetIndices(is_A_B,&idx_B);CHKERRQ(ierr); for (j=0;j<n_B;j++) { ierr = PetscBTSet(touched,idx_B[j]);CHKERRQ(ierr); } ierr = ISRestoreIndices(is_A_B,&idx_B);CHKERRQ(ierr); /* add next layers of dofs */ ierr = ISGetLocalSize(is_cc[i],&subset_size);CHKERRQ(ierr); ierr = ISGetIndices(is_cc[i],&idx_B);CHKERRQ(ierr); ierr = PetscMemcpy(local_numbering,idx_B,subset_size*sizeof(PetscInt));CHKERRQ(ierr); ierr = ISRestoreIndices(is_cc[i],&idx_B);CHKERRQ(ierr); n_local_dofs = subset_size; n_prev_added = subset_size; for (layer=0;layer<nlayers;layer++) { PetscInt n_added; if (n_local_dofs == n_I+subset_size) break; if (n_local_dofs > n_I+subset_size) { SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error querying layer %d. Out of bound access (%d > %d)",layer,n_local_dofs,n_I+subset_size); } ierr = PCBDDCAdjGetNextLayer_Private(local_numbering+n_local_dofs,n_prev_added,touched,xadj,adjncy,&n_added);CHKERRQ(ierr); n_prev_added = n_added; n_local_dofs += n_added; if (!n_added) break; } /* IS for I dofs in original numbering and in I numbering */ ierr = ISCreateGeneral(PetscObjectComm((PetscObject)ItoNmap),n_local_dofs-subset_size,local_numbering+subset_size,PETSC_COPY_VALUES,&sub_schurs->is_AEj_I[i]);CHKERRQ(ierr); ierr = ISSort(sub_schurs->is_AEj_I[i]);CHKERRQ(ierr); ierr = ISGlobalToLocalMappingApplyIS(ItoNmap,IS_GTOLM_DROP,sub_schurs->is_AEj_I[i],&is_I);CHKERRQ(ierr); /* II block */ ierr = MatGetSubMatrix(A_II,is_I,is_I,MAT_INITIAL_MATRIX,&AE_II);CHKERRQ(ierr); } else { /* in this case we can take references of already existing IS and matrices for I dofs */ /* IS for I dofs in original numbering */ ierr = PetscObjectReference((PetscObject)is_A_I);CHKERRQ(ierr); sub_schurs->is_AEj_I[i] = is_A_I; /* IS for I dofs in I numbering TODO: "first" argument of ISCreateStride is not general */ ierr = ISCreateStride(PetscObjectComm((PetscObject)is_A_I),n_I,0,1,&is_I);CHKERRQ(ierr); /* II block is the same */ ierr = PetscObjectReference((PetscObject)A_II);CHKERRQ(ierr); AE_II = A_II; } /* IE block */ ierr = MatGetSubMatrix(A_IB,is_I,is_subset_B,MAT_INITIAL_MATRIX,&AE_IE);CHKERRQ(ierr); /* EI block */ ierr = MatGetSubMatrix(A_BI,is_subset_B,is_I,MAT_INITIAL_MATRIX,&AE_EI);CHKERRQ(ierr); /* setup Schur complements on subset */ ierr = MatCreateSchurComplement(AE_II,AE_II,AE_IE,AE_EI,AE_EE,&sub_schurs->S_Ej[i]);CHKERRQ(ierr); ierr = MatGetVecs(sub_schurs->S_Ej[i],&sub_schurs->work1[i],&sub_schurs->work2[i]);CHKERRQ(ierr); if (AE_II == A_II) { /* we can reuse the same ksp */ KSP ksp; ierr = MatSchurComplementGetKSP(S,&ksp);CHKERRQ(ierr); ierr = MatSchurComplementSetKSP(sub_schurs->S_Ej[i],ksp);CHKERRQ(ierr); } else { /* build new ksp object which inherits ksp and pc types from the original one */ KSP origksp,schurksp; PC origpc,schurpc; KSPType ksp_type; PCType pc_type; PetscInt n_internal; ierr = MatSchurComplementGetKSP(S,&origksp);CHKERRQ(ierr); ierr = MatSchurComplementGetKSP(sub_schurs->S_Ej[i],&schurksp);CHKERRQ(ierr); ierr = KSPGetType(origksp,&ksp_type);CHKERRQ(ierr); ierr = KSPSetType(schurksp,ksp_type);CHKERRQ(ierr); ierr = KSPGetPC(schurksp,&schurpc);CHKERRQ(ierr); ierr = KSPGetPC(origksp,&origpc);CHKERRQ(ierr); ierr = PCGetType(origpc,&pc_type);CHKERRQ(ierr); ierr = PCSetType(schurpc,pc_type);CHKERRQ(ierr); ierr = ISGetSize(is_I,&n_internal);CHKERRQ(ierr); if (n_internal) { /* UMFPACK gives error with 0 sized problems */ MatSolverPackage solver=NULL; ierr = PCFactorGetMatSolverPackage(origpc,(const MatSolverPackage*)&solver);CHKERRQ(ierr); if (solver) { ierr = PCFactorSetMatSolverPackage(schurpc,solver);CHKERRQ(ierr); } } ierr = KSPSetUp(schurksp);CHKERRQ(ierr); } /* free */ ierr = MatDestroy(&AE_II);CHKERRQ(ierr); ierr = MatDestroy(&AE_EE);CHKERRQ(ierr); ierr = MatDestroy(&AE_IE);CHKERRQ(ierr); ierr = MatDestroy(&AE_EI);CHKERRQ(ierr); ierr = ISDestroy(&is_I);CHKERRQ(ierr); ierr = ISDestroy(&is_subset_B);CHKERRQ(ierr); } /* free */ ierr = ISLocalToGlobalMappingDestroy(&ItoNmap);CHKERRQ(ierr); ierr = ISLocalToGlobalMappingDestroy(&BtoNmap);CHKERRQ(ierr); ierr = PetscFree(local_numbering);CHKERRQ(ierr); ierr = PetscBTDestroy(&touched);CHKERRQ(ierr); PetscFunctionReturn(0); }