PETSC_EXTERN void PETSC_STDCALL pcissetsubdomainscalingfactor_(PC pc,PetscScalar *scal, int *__ierr ){ *__ierr = PCISSetSubdomainScalingFactor( (PC)PetscToPointer((pc) ),*scal); }
static PetscErrorCode ComputeKSPBDDC(DomainData dd,Mat A,KSP *ksp) { PetscErrorCode ierr; KSP temp_ksp; PC pc; IS dirichletIS=0,neumannIS=0,*bddc_dofs_splitting; PetscInt localsize,*xadj=NULL,*adjncy=NULL; MatNullSpace near_null_space; PetscFunctionBeginUser; ierr = KSPCreate(dd.gcomm,&temp_ksp);CHKERRQ(ierr); ierr = KSPSetOperators(temp_ksp,A,A);CHKERRQ(ierr); ierr = KSPSetType(temp_ksp,KSPCG);CHKERRQ(ierr); ierr = KSPGetPC(temp_ksp,&pc);CHKERRQ(ierr); ierr = PCSetType(pc,PCBDDC);CHKERRQ(ierr); localsize = dd.xm_l*dd.ym_l*dd.zm_l; /* BDDC customization */ /* jumping coefficients case */ ierr = PCISSetSubdomainScalingFactor(pc,dd.scalingfactor);CHKERRQ(ierr); /* Dofs splitting Simple stride-1 IS It is not needed since, by default, PCBDDC assumes a stride-1 split */ ierr = PetscMalloc1(1,&bddc_dofs_splitting);CHKERRQ(ierr); #if 1 ierr = ISCreateStride(PETSC_COMM_WORLD,localsize,0,1,&bddc_dofs_splitting[0]);CHKERRQ(ierr); ierr = PCBDDCSetDofsSplittingLocal(pc,1,bddc_dofs_splitting);CHKERRQ(ierr); #else /* examples for global ordering */ /* each process lists the nodes it owns */ PetscInt sr,er; ierr = MatGetOwnershipRange(A,&sr,&er);CHKERRQ(ierr); ierr = ISCreateStride(PETSC_COMM_WORLD,er-sr,sr,1,&bddc_dofs_splitting[0]);CHKERRQ(ierr); ierr = PCBDDCSetDofsSplitting(pc,1,bddc_dofs_splitting);CHKERRQ(ierr); /* Split can be passed in a more general way since any process can list any node */ #endif ierr = ISDestroy(&bddc_dofs_splitting[0]);CHKERRQ(ierr); ierr = PetscFree(bddc_dofs_splitting);CHKERRQ(ierr); /* Primal constraints implemented by using a near null space attached to A -> now it passes in only the constants (which in practice is not needed since, by default, PCBDDC build the primal space using constants for quadrature formulas */ #if 0 Vec vecs[2]; PetscRandom rctx; ierr = MatCreateVecs(A,&vecs[0],&vecs[1]);CHKERRQ(ierr); ierr = PetscRandomCreate(dd.gcomm,&rctx);CHKERRQ(ierr); ierr = VecSetRandom(vecs[0],rctx);CHKERRQ(ierr); ierr = VecSetRandom(vecs[1],rctx);CHKERRQ(ierr); ierr = MatNullSpaceCreate(dd.gcomm,PETSC_TRUE,2,vecs,&near_null_space);CHKERRQ(ierr); ierr = VecDestroy(&vecs[0]);CHKERRQ(ierr); ierr = VecDestroy(&vecs[1]);CHKERRQ(ierr); ierr = PetscRandomDestroy(&rctx);CHKERRQ(ierr); #else ierr = MatNullSpaceCreate(dd.gcomm,PETSC_TRUE,0,NULL,&near_null_space);CHKERRQ(ierr); #endif ierr = MatSetNearNullSpace(A,near_null_space);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&near_null_space);CHKERRQ(ierr); /* CSR graph of subdomain dofs */ ierr = BuildCSRGraph(dd,&xadj,&adjncy);CHKERRQ(ierr); ierr = PCBDDCSetLocalAdjacencyGraph(pc,localsize,xadj,adjncy,PETSC_OWN_POINTER);CHKERRQ(ierr); /* Neumann/Dirichlet indices on the global boundary */ if (dd.DBC_zerorows) { /* Only in case you eliminate some rows matrix with zerorows function, you need to set dirichlet indices into PCBDDC data */ ierr = ComputeSpecialBoundaryIndices(dd,&dirichletIS,&neumannIS);CHKERRQ(ierr); ierr = PCBDDCSetNeumannBoundariesLocal(pc,neumannIS);CHKERRQ(ierr); ierr = PCBDDCSetDirichletBoundariesLocal(pc,dirichletIS);CHKERRQ(ierr); } else { if (dd.pure_neumann) { /* In such a case, all interface nodes lying on the global boundary are neumann nodes */ ierr = ComputeSpecialBoundaryIndices(dd,NULL,&neumannIS);CHKERRQ(ierr); ierr = PCBDDCSetNeumannBoundariesLocal(pc,neumannIS);CHKERRQ(ierr); } else { /* It is wrong setting dirichlet indices without having zeroed the corresponding rows in the global matrix */ /* But we can still compute them since nodes near the dirichlet boundaries does not need to be defined as neumann nodes */ ierr = ComputeSpecialBoundaryIndices(dd,&dirichletIS,&neumannIS);CHKERRQ(ierr); ierr = PCBDDCSetNeumannBoundariesLocal(pc,neumannIS);CHKERRQ(ierr); } } /* Pass local null space information to local matrices (needed when using approximate local solvers) */ if (dd.ipx || dd.pure_neumann) { MatNullSpace nsp; Mat local_mat; ierr = MatISGetLocalMat(A,&local_mat);CHKERRQ(ierr); ierr = MatNullSpaceCreate(PETSC_COMM_SELF,PETSC_TRUE,0,NULL,&nsp);CHKERRQ(ierr); ierr = MatSetNullSpace(local_mat,nsp);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&nsp);CHKERRQ(ierr); } ierr = KSPSetComputeSingularValues(temp_ksp,PETSC_TRUE);CHKERRQ(ierr); ierr = KSPSetFromOptions(temp_ksp);CHKERRQ(ierr); ierr = KSPSetUp(temp_ksp);CHKERRQ(ierr); *ksp = temp_ksp; ierr = ISDestroy(&dirichletIS);CHKERRQ(ierr); ierr = ISDestroy(&neumannIS);CHKERRQ(ierr); PetscFunctionReturn(0); }