1dba47a55SKris Buschelman #define PETSCKSP_DLL 223ce1328SBarry Smith 37c4f633dSBarry Smith #include "../src/ksp/pc/impls/is/pcis.h" 4b4319ba4SBarry Smith 5b4319ba4SBarry Smith /* -------------------------------------------------------------------------- */ 6b4319ba4SBarry Smith /* 7b4319ba4SBarry Smith PCISSetUp - 8b4319ba4SBarry Smith */ 9b4319ba4SBarry Smith #undef __FUNCT__ 10b4319ba4SBarry Smith #define __FUNCT__ "PCISSetUp" 11dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCISSetUp(PC pc) 12b4319ba4SBarry Smith { 13b4319ba4SBarry Smith PC_IS *pcis = (PC_IS*)(pc->data); 14b4319ba4SBarry Smith Mat_IS *matis = (Mat_IS*)pc->mat->data; 1513f74950SBarry Smith PetscInt i; 166849ba73SBarry Smith PetscErrorCode ierr; 17ace3abfcSBarry Smith PetscBool flg; 18b4319ba4SBarry Smith 19b4319ba4SBarry Smith PetscFunctionBegin; 20b4319ba4SBarry Smith ierr = PetscTypeCompare((PetscObject)pc->mat,MATIS,&flg);CHKERRQ(ierr); 21e7e72b3dSBarry Smith if (!flg) SETERRQ(((PetscObject)pc)->comm,PETSC_ERR_ARG_WRONG,"Preconditioner type of Neumann Neumman requires matrix of type MATIS"); 22b4319ba4SBarry Smith 23b4319ba4SBarry Smith pcis->pure_neumann = matis->pure_neumann; 24b4319ba4SBarry Smith 25b4319ba4SBarry Smith /* 26b4319ba4SBarry Smith Creating the local vector vec1_N, containing the inverse of the number 27b4319ba4SBarry Smith of subdomains to which each local node (either owned or ghost) 28b4319ba4SBarry Smith pertains. To accomplish that, we scatter local vectors of 1's to 29b4319ba4SBarry Smith a global vector (adding the values); scatter the result back to 30b4319ba4SBarry Smith local vectors and finally invert the result. 31b4319ba4SBarry Smith */ 32b4319ba4SBarry Smith { 33b4319ba4SBarry Smith Vec counter; 34b4319ba4SBarry Smith ierr = VecDuplicate(matis->x,&pcis->vec1_N);CHKERRQ(ierr); 3523ce1328SBarry Smith ierr = MatGetVecs(pc->pmat,&counter,0);CHKERRQ(ierr); /* temporary auxiliar vector */ 36efb30889SBarry Smith ierr = VecSet(counter,0.0);CHKERRQ(ierr); 37efb30889SBarry Smith ierr = VecSet(pcis->vec1_N,1.0);CHKERRQ(ierr); 38ca9f406cSSatish Balay ierr = VecScatterBegin(matis->ctx,pcis->vec1_N,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 39ca9f406cSSatish Balay ierr = VecScatterEnd (matis->ctx,pcis->vec1_N,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 40ca9f406cSSatish Balay ierr = VecScatterBegin(matis->ctx,counter,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 41ca9f406cSSatish Balay ierr = VecScatterEnd (matis->ctx,counter,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 42b4319ba4SBarry Smith ierr = VecDestroy(counter);CHKERRQ(ierr); 43b4319ba4SBarry Smith } 44b4319ba4SBarry Smith /* 45b4319ba4SBarry Smith Creating local and global index sets for interior and 46b4319ba4SBarry Smith inteface nodes. Notice that interior nodes have D[i]==1.0. 47b4319ba4SBarry Smith */ 48b4319ba4SBarry Smith { 4913f74950SBarry Smith PetscInt n_I; 5013f74950SBarry Smith PetscInt *idx_I_local,*idx_B_local,*idx_I_global,*idx_B_global; 51b4319ba4SBarry Smith PetscScalar *array; 52b4319ba4SBarry Smith /* Identifying interior and interface nodes, in local numbering */ 53b4319ba4SBarry Smith ierr = VecGetSize(pcis->vec1_N,&pcis->n);CHKERRQ(ierr); 54b4319ba4SBarry Smith ierr = VecGetArray(pcis->vec1_N,&array);CHKERRQ(ierr); 5513f74950SBarry Smith ierr = PetscMalloc(pcis->n*sizeof(PetscInt),&idx_I_local);CHKERRQ(ierr); 5613f74950SBarry Smith ierr = PetscMalloc(pcis->n*sizeof(PetscInt),&idx_B_local);CHKERRQ(ierr); 57b4319ba4SBarry Smith for (i=0, pcis->n_B=0, n_I=0; i<pcis->n; i++) { 58b4319ba4SBarry Smith if (array[i] == 1.0) { idx_I_local[n_I] = i; n_I++; } 59b4319ba4SBarry Smith else { idx_B_local[pcis->n_B] = i; pcis->n_B++; } 60b4319ba4SBarry Smith } 61b4319ba4SBarry Smith /* Getting the global numbering */ 62b4319ba4SBarry Smith idx_B_global = idx_I_local + n_I; /* Just avoiding allocating extra memory, since we have vacant space */ 63b4319ba4SBarry Smith idx_I_global = idx_B_local + pcis->n_B; 64b4319ba4SBarry Smith ierr = ISLocalToGlobalMappingApply(matis->mapping,pcis->n_B,idx_B_local,idx_B_global);CHKERRQ(ierr); 65b4319ba4SBarry Smith ierr = ISLocalToGlobalMappingApply(matis->mapping,n_I, idx_I_local,idx_I_global);CHKERRQ(ierr); 66b4319ba4SBarry Smith /* Creating the index sets. */ 6770b3c8c7SBarry Smith ierr = ISCreateGeneral(MPI_COMM_SELF,pcis->n_B,idx_B_local,PETSC_COPY_VALUES, &pcis->is_B_local);CHKERRQ(ierr); 6870b3c8c7SBarry Smith ierr = ISCreateGeneral(MPI_COMM_SELF,pcis->n_B,idx_B_global,PETSC_COPY_VALUES,&pcis->is_B_global);CHKERRQ(ierr); 6970b3c8c7SBarry Smith ierr = ISCreateGeneral(MPI_COMM_SELF,n_I ,idx_I_local,PETSC_COPY_VALUES, &pcis->is_I_local);CHKERRQ(ierr); 7070b3c8c7SBarry Smith ierr = ISCreateGeneral(MPI_COMM_SELF,n_I ,idx_I_global,PETSC_COPY_VALUES,&pcis->is_I_global);CHKERRQ(ierr); 71b4319ba4SBarry Smith /* Freeing memory and restoring arrays */ 72b4319ba4SBarry Smith ierr = PetscFree(idx_B_local);CHKERRQ(ierr); 73b4319ba4SBarry Smith ierr = PetscFree(idx_I_local);CHKERRQ(ierr); 74b4319ba4SBarry Smith ierr = VecRestoreArray(pcis->vec1_N,&array);CHKERRQ(ierr); 75b4319ba4SBarry Smith } 76b4319ba4SBarry Smith 77b4319ba4SBarry Smith /* 78b4319ba4SBarry Smith Extracting the blocks A_II, A_BI, A_IB and A_BB from A. If the numbering 79b4319ba4SBarry Smith is such that interior nodes come first than the interface ones, we have 80b4319ba4SBarry Smith 81b4319ba4SBarry Smith [ | ] 82b4319ba4SBarry Smith [ A_II | A_IB ] 83b4319ba4SBarry Smith A = [ | ] 84b4319ba4SBarry Smith [-----------+------] 85b4319ba4SBarry Smith [ A_BI | A_BB ] 86b4319ba4SBarry Smith */ 87b4319ba4SBarry Smith 884aa3045dSJed Brown ierr = MatGetSubMatrix(matis->A,pcis->is_I_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_II);CHKERRQ(ierr); 894aa3045dSJed Brown ierr = MatGetSubMatrix(matis->A,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr); 904aa3045dSJed Brown ierr = MatGetSubMatrix(matis->A,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr); 914aa3045dSJed Brown ierr = MatGetSubMatrix(matis->A,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr); 92b4319ba4SBarry Smith 93b4319ba4SBarry Smith /* 94b4319ba4SBarry Smith Creating work vectors and arrays 95b4319ba4SBarry Smith */ 96b4319ba4SBarry Smith /* pcis->vec1_N has already been created */ 97b4319ba4SBarry Smith ierr = VecDuplicate(pcis->vec1_N,&pcis->vec2_N);CHKERRQ(ierr); 98b4319ba4SBarry Smith ierr = VecCreateSeq(PETSC_COMM_SELF,pcis->n-pcis->n_B,&pcis->vec1_D);CHKERRQ(ierr); 99b4319ba4SBarry Smith ierr = VecDuplicate(pcis->vec1_D,&pcis->vec2_D);CHKERRQ(ierr); 100b4319ba4SBarry Smith ierr = VecDuplicate(pcis->vec1_D,&pcis->vec3_D);CHKERRQ(ierr); 101b4319ba4SBarry Smith ierr = VecCreateSeq(PETSC_COMM_SELF,pcis->n_B,&pcis->vec1_B);CHKERRQ(ierr); 102b4319ba4SBarry Smith ierr = VecDuplicate(pcis->vec1_B,&pcis->vec2_B);CHKERRQ(ierr); 103b4319ba4SBarry Smith ierr = VecDuplicate(pcis->vec1_B,&pcis->vec3_B);CHKERRQ(ierr); 10423ce1328SBarry Smith ierr = MatGetVecs(pc->pmat,&pcis->vec1_global,0);CHKERRQ(ierr); 105b4319ba4SBarry Smith ierr = PetscMalloc((pcis->n)*sizeof(PetscScalar),&pcis->work_N);CHKERRQ(ierr); 106b4319ba4SBarry Smith 107b4319ba4SBarry Smith /* Creating the scatter contexts */ 10823ce1328SBarry Smith ierr = VecScatterCreate(pcis->vec1_global,pcis->is_I_global,pcis->vec1_D,(IS)0,&pcis->global_to_D);CHKERRQ(ierr); 109b4319ba4SBarry Smith ierr = VecScatterCreate(pcis->vec1_N,pcis->is_B_local,pcis->vec1_B,(IS)0,&pcis->N_to_B);CHKERRQ(ierr); 11023ce1328SBarry Smith ierr = VecScatterCreate(pcis->vec1_global,pcis->is_B_global,pcis->vec1_B,(IS)0,&pcis->global_to_B);CHKERRQ(ierr); 111b4319ba4SBarry Smith 112b4319ba4SBarry Smith /* Creating scaling "matrix" D, from information in vec1_N */ 113b4319ba4SBarry Smith ierr = VecDuplicate(pcis->vec1_B,&pcis->D);CHKERRQ(ierr); 114ca9f406cSSatish Balay ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 115ca9f406cSSatish Balay ierr = VecScatterEnd (pcis->N_to_B,pcis->vec1_N,pcis->D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 116b4319ba4SBarry Smith ierr = VecReciprocal(pcis->D);CHKERRQ(ierr); 117b4319ba4SBarry Smith 118b4319ba4SBarry Smith /* See historical note 01, at the bottom of this file. */ 119b4319ba4SBarry Smith 120b4319ba4SBarry Smith /* 121b4319ba4SBarry Smith Creating the KSP contexts for the local Dirichlet and Neumann problems. 122b4319ba4SBarry Smith */ 123b4319ba4SBarry Smith { 124b4319ba4SBarry Smith PC pc_ctx; 125b4319ba4SBarry Smith /* Dirichlet */ 126b4319ba4SBarry Smith ierr = KSPCreate(PETSC_COMM_SELF,&pcis->ksp_D);CHKERRQ(ierr); 1271cee3971SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)pcis->ksp_D,(PetscObject)pc,1);CHKERRQ(ierr); 128b4319ba4SBarry Smith ierr = KSPSetOperators(pcis->ksp_D,pcis->A_II,pcis->A_II,SAME_PRECONDITIONER);CHKERRQ(ierr); 129b4319ba4SBarry Smith ierr = KSPSetOptionsPrefix(pcis->ksp_D,"is_localD_");CHKERRQ(ierr); 130b4319ba4SBarry Smith ierr = KSPGetPC(pcis->ksp_D,&pc_ctx);CHKERRQ(ierr); 131b4319ba4SBarry Smith ierr = PCSetType(pc_ctx,PCLU);CHKERRQ(ierr); 132b4319ba4SBarry Smith ierr = KSPSetType(pcis->ksp_D,KSPPREONLY);CHKERRQ(ierr); 133b4319ba4SBarry Smith ierr = KSPSetFromOptions(pcis->ksp_D);CHKERRQ(ierr); 134b4319ba4SBarry Smith /* the vectors in the following line are dummy arguments, just telling the KSP the vector size. Values are not used */ 135b4319ba4SBarry Smith ierr = KSPSetUp(pcis->ksp_D);CHKERRQ(ierr); 136b4319ba4SBarry Smith /* Neumann */ 137b4319ba4SBarry Smith ierr = KSPCreate(PETSC_COMM_SELF,&pcis->ksp_N);CHKERRQ(ierr); 1381cee3971SBarry Smith ierr = PetscObjectIncrementTabLevel((PetscObject)pcis->ksp_N,(PetscObject)pc,1);CHKERRQ(ierr); 139b4319ba4SBarry Smith ierr = KSPSetOperators(pcis->ksp_N,matis->A,matis->A,SAME_PRECONDITIONER);CHKERRQ(ierr); 140b4319ba4SBarry Smith ierr = KSPSetOptionsPrefix(pcis->ksp_N,"is_localN_");CHKERRQ(ierr); 141b4319ba4SBarry Smith ierr = KSPGetPC(pcis->ksp_N,&pc_ctx);CHKERRQ(ierr); 142b4319ba4SBarry Smith ierr = PCSetType(pc_ctx,PCLU);CHKERRQ(ierr); 143b4319ba4SBarry Smith ierr = KSPSetType(pcis->ksp_N,KSPPREONLY);CHKERRQ(ierr); 144b4319ba4SBarry Smith ierr = KSPSetFromOptions(pcis->ksp_N);CHKERRQ(ierr); 145b4319ba4SBarry Smith { 146ace3abfcSBarry Smith PetscBool damp_fixed = PETSC_FALSE, 14790d69ab7SBarry Smith remove_nullspace_fixed = PETSC_FALSE, 14890d69ab7SBarry Smith set_damping_factor_floating = PETSC_FALSE, 14990d69ab7SBarry Smith not_damp_floating = PETSC_FALSE, 15090d69ab7SBarry Smith not_remove_nullspace_floating = PETSC_FALSE; 151b4319ba4SBarry Smith PetscReal fixed_factor, 152b4319ba4SBarry Smith floating_factor; 153b4319ba4SBarry Smith 1547adad957SLisandro Dalcin ierr = PetscOptionsGetReal(((PetscObject)pc_ctx)->prefix,"-pc_is_damp_fixed",&fixed_factor,&damp_fixed);CHKERRQ(ierr); 155b4319ba4SBarry Smith if (!damp_fixed) { fixed_factor = 0.0; } 156*acfcf0e5SJed Brown ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_damp_fixed",&damp_fixed,PETSC_NULL);CHKERRQ(ierr); 157b4319ba4SBarry Smith 158*acfcf0e5SJed Brown ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_remove_nullspace_fixed",&remove_nullspace_fixed,PETSC_NULL);CHKERRQ(ierr); 159b4319ba4SBarry Smith 1607adad957SLisandro Dalcin ierr = PetscOptionsGetReal(((PetscObject)pc_ctx)->prefix,"-pc_is_set_damping_factor_floating", 161b4319ba4SBarry Smith &floating_factor,&set_damping_factor_floating);CHKERRQ(ierr); 162b4319ba4SBarry Smith if (!set_damping_factor_floating) { floating_factor = 0.0; } 163*acfcf0e5SJed Brown ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_set_damping_factor_floating",&set_damping_factor_floating,PETSC_NULL);CHKERRQ(ierr); 164b4319ba4SBarry Smith if (!set_damping_factor_floating) { floating_factor = 1.e-12; } 165b4319ba4SBarry Smith 166*acfcf0e5SJed Brown ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_not_damp_floating",¬_damp_floating,PETSC_NULL);CHKERRQ(ierr); 167b4319ba4SBarry Smith 168*acfcf0e5SJed Brown ierr = PetscOptionsGetBool(((PetscObject)pc_ctx)->prefix,"-pc_is_not_remove_nullspace_floating",¬_remove_nullspace_floating,PETSC_NULL);CHKERRQ(ierr); 169b4319ba4SBarry Smith 170b4319ba4SBarry Smith if (pcis->pure_neumann) { /* floating subdomain */ 171b4319ba4SBarry Smith if (!(not_damp_floating)) { 172c88783f4SHong Zhang ierr = PCFactorSetShiftType(pc_ctx,MAT_SHIFT_NONZERO);CHKERRQ(ierr); 173c88783f4SHong Zhang ierr = PCFactorSetShiftAmount(pc_ctx,floating_factor);CHKERRQ(ierr); 174b4319ba4SBarry Smith } 175b4319ba4SBarry Smith if (!(not_remove_nullspace_floating)){ 176b4319ba4SBarry Smith MatNullSpace nullsp; 177ee512c37SSatish Balay ierr = MatNullSpaceCreate(PETSC_COMM_SELF,PETSC_TRUE,0,PETSC_NULL,&nullsp);CHKERRQ(ierr); 178d8fd42c4SBarry Smith ierr = KSPSetNullSpace(pcis->ksp_N,nullsp);CHKERRQ(ierr); 179b4319ba4SBarry Smith ierr = MatNullSpaceDestroy(nullsp);CHKERRQ(ierr); 180b4319ba4SBarry Smith } 181b4319ba4SBarry Smith } else { /* fixed subdomain */ 182b4319ba4SBarry Smith if (damp_fixed) { 183c88783f4SHong Zhang ierr = PCFactorSetShiftType(pc_ctx,MAT_SHIFT_NONZERO);CHKERRQ(ierr); 184c88783f4SHong Zhang ierr = PCFactorSetShiftAmount(pc_ctx,floating_factor);CHKERRQ(ierr); 185b4319ba4SBarry Smith } 186b4319ba4SBarry Smith if (remove_nullspace_fixed) { 187b4319ba4SBarry Smith MatNullSpace nullsp; 188ee512c37SSatish Balay ierr = MatNullSpaceCreate(PETSC_COMM_SELF,PETSC_TRUE,0,PETSC_NULL,&nullsp);CHKERRQ(ierr); 189d8fd42c4SBarry Smith ierr = KSPSetNullSpace(pcis->ksp_N,nullsp);CHKERRQ(ierr); 190b4319ba4SBarry Smith ierr = MatNullSpaceDestroy(nullsp);CHKERRQ(ierr); 191b4319ba4SBarry Smith } 192b4319ba4SBarry Smith } 193b4319ba4SBarry Smith } 194b4319ba4SBarry Smith /* the vectors in the following line are dummy arguments, just telling the KSP the vector size. Values are not used */ 195b4319ba4SBarry Smith ierr = KSPSetUp(pcis->ksp_N);CHKERRQ(ierr); 196b4319ba4SBarry Smith } 197b4319ba4SBarry Smith 1987c334f02SBarry Smith ierr = ISLocalToGlobalMappingGetInfo(((Mat_IS*)(pc->mat->data))->mapping,&(pcis->n_neigh),&(pcis->neigh),&(pcis->n_shared),&(pcis->shared));CHKERRQ(ierr); 199b4319ba4SBarry Smith pcis->ISLocalToGlobalMappingGetInfoWasCalled = PETSC_TRUE; 200b4319ba4SBarry Smith PetscFunctionReturn(0); 201b4319ba4SBarry Smith } 202b4319ba4SBarry Smith 203b4319ba4SBarry Smith /* -------------------------------------------------------------------------- */ 204b4319ba4SBarry Smith /* 205b4319ba4SBarry Smith PCISDestroy - 206b4319ba4SBarry Smith */ 207b4319ba4SBarry Smith #undef __FUNCT__ 208b4319ba4SBarry Smith #define __FUNCT__ "PCISDestroy" 209dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCISDestroy(PC pc) 210b4319ba4SBarry Smith { 211b4319ba4SBarry Smith PC_IS *pcis = (PC_IS*)(pc->data); 212dfbe8321SBarry Smith PetscErrorCode ierr; 213b4319ba4SBarry Smith 214b4319ba4SBarry Smith PetscFunctionBegin; 215b4319ba4SBarry Smith if (pcis->is_B_local) {ierr = ISDestroy(pcis->is_B_local);CHKERRQ(ierr);} 216b4319ba4SBarry Smith if (pcis->is_I_local) {ierr = ISDestroy(pcis->is_I_local);CHKERRQ(ierr);} 217b4319ba4SBarry Smith if (pcis->is_B_global) {ierr = ISDestroy(pcis->is_B_global);CHKERRQ(ierr);} 218b4319ba4SBarry Smith if (pcis->is_I_global) {ierr = ISDestroy(pcis->is_I_global);CHKERRQ(ierr);} 219b4319ba4SBarry Smith if (pcis->A_II) {ierr = MatDestroy(pcis->A_II);CHKERRQ(ierr);} 220b4319ba4SBarry Smith if (pcis->A_IB) {ierr = MatDestroy(pcis->A_IB);CHKERRQ(ierr);} 221b4319ba4SBarry Smith if (pcis->A_BI) {ierr = MatDestroy(pcis->A_BI);CHKERRQ(ierr);} 222b4319ba4SBarry Smith if (pcis->A_BB) {ierr = MatDestroy(pcis->A_BB);CHKERRQ(ierr);} 223b4319ba4SBarry Smith if (pcis->D) {ierr = VecDestroy(pcis->D);CHKERRQ(ierr);} 224b4319ba4SBarry Smith if (pcis->ksp_N) {ierr = KSPDestroy(pcis->ksp_N);CHKERRQ(ierr);} 225b4319ba4SBarry Smith if (pcis->ksp_D) {ierr = KSPDestroy(pcis->ksp_D);CHKERRQ(ierr);} 226b4319ba4SBarry Smith if (pcis->vec1_N) {ierr = VecDestroy(pcis->vec1_N);CHKERRQ(ierr);} 227b4319ba4SBarry Smith if (pcis->vec2_N) {ierr = VecDestroy(pcis->vec2_N);CHKERRQ(ierr);} 228b4319ba4SBarry Smith if (pcis->vec1_D) {ierr = VecDestroy(pcis->vec1_D);CHKERRQ(ierr);} 229b4319ba4SBarry Smith if (pcis->vec2_D) {ierr = VecDestroy(pcis->vec2_D);CHKERRQ(ierr);} 230b4319ba4SBarry Smith if (pcis->vec3_D) {ierr = VecDestroy(pcis->vec3_D);CHKERRQ(ierr);} 231b4319ba4SBarry Smith if (pcis->vec1_B) {ierr = VecDestroy(pcis->vec1_B);CHKERRQ(ierr);} 232b4319ba4SBarry Smith if (pcis->vec2_B) {ierr = VecDestroy(pcis->vec2_B);CHKERRQ(ierr);} 233b4319ba4SBarry Smith if (pcis->vec3_B) {ierr = VecDestroy(pcis->vec3_B);CHKERRQ(ierr);} 234b4319ba4SBarry Smith if (pcis->vec1_global) {ierr = VecDestroy(pcis->vec1_global);CHKERRQ(ierr);} 235b4319ba4SBarry Smith if (pcis->global_to_D) {ierr = VecScatterDestroy(pcis->global_to_D);CHKERRQ(ierr);} 236b4319ba4SBarry Smith if (pcis->N_to_B) {ierr = VecScatterDestroy(pcis->N_to_B);CHKERRQ(ierr);} 237b4319ba4SBarry Smith if (pcis->global_to_B) {ierr = VecScatterDestroy(pcis->global_to_B);CHKERRQ(ierr);} 23805b42c5fSBarry Smith ierr = PetscFree(pcis->work_N);CHKERRQ(ierr); 239b4319ba4SBarry Smith if (pcis->ISLocalToGlobalMappingGetInfoWasCalled) { 240b4319ba4SBarry Smith ierr = ISLocalToGlobalMappingRestoreInfo((ISLocalToGlobalMapping)0,&(pcis->n_neigh),&(pcis->neigh),&(pcis->n_shared),&(pcis->shared));CHKERRQ(ierr); 241b4319ba4SBarry Smith } 242b4319ba4SBarry Smith PetscFunctionReturn(0); 243b4319ba4SBarry Smith } 244b4319ba4SBarry Smith 245b4319ba4SBarry Smith /* -------------------------------------------------------------------------- */ 246b4319ba4SBarry Smith /* 247b4319ba4SBarry Smith PCISCreate - 248b4319ba4SBarry Smith */ 249b4319ba4SBarry Smith #undef __FUNCT__ 250b4319ba4SBarry Smith #define __FUNCT__ "PCISCreate" 251dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCISCreate(PC pc) 252b4319ba4SBarry Smith { 253b4319ba4SBarry Smith PC_IS *pcis = (PC_IS*)(pc->data); 254b4319ba4SBarry Smith 255b4319ba4SBarry Smith PetscFunctionBegin; 256b4319ba4SBarry Smith pcis->is_B_local = 0; 257b4319ba4SBarry Smith pcis->is_I_local = 0; 258b4319ba4SBarry Smith pcis->is_B_global = 0; 259b4319ba4SBarry Smith pcis->is_I_global = 0; 260b4319ba4SBarry Smith pcis->A_II = 0; 261b4319ba4SBarry Smith pcis->A_IB = 0; 262b4319ba4SBarry Smith pcis->A_BI = 0; 263b4319ba4SBarry Smith pcis->A_BB = 0; 264b4319ba4SBarry Smith pcis->D = 0; 265b4319ba4SBarry Smith pcis->ksp_N = 0; 266b4319ba4SBarry Smith pcis->ksp_D = 0; 267b4319ba4SBarry Smith pcis->vec1_N = 0; 268b4319ba4SBarry Smith pcis->vec2_N = 0; 269b4319ba4SBarry Smith pcis->vec1_D = 0; 270b4319ba4SBarry Smith pcis->vec2_D = 0; 271b4319ba4SBarry Smith pcis->vec3_D = 0; 272b4319ba4SBarry Smith pcis->vec1_B = 0; 273b4319ba4SBarry Smith pcis->vec2_B = 0; 274b4319ba4SBarry Smith pcis->vec3_B = 0; 275b4319ba4SBarry Smith pcis->vec1_global = 0; 276b4319ba4SBarry Smith pcis->work_N = 0; 277b4319ba4SBarry Smith pcis->global_to_D = 0; 278b4319ba4SBarry Smith pcis->N_to_B = 0; 279b4319ba4SBarry Smith pcis->global_to_B = 0; 280b4319ba4SBarry Smith pcis->ISLocalToGlobalMappingGetInfoWasCalled = PETSC_FALSE; 281b4319ba4SBarry Smith PetscFunctionReturn(0); 282b4319ba4SBarry Smith } 283b4319ba4SBarry Smith 284b4319ba4SBarry Smith /* -------------------------------------------------------------------------- */ 285b4319ba4SBarry Smith /* 286b4319ba4SBarry Smith PCISApplySchur - 287b4319ba4SBarry Smith 288b4319ba4SBarry Smith Input parameters: 289b4319ba4SBarry Smith . pc - preconditioner context 290b4319ba4SBarry Smith . v - vector to which the Schur complement is to be applied (it is NOT modified inside this function, UNLESS vec2_B is null) 291b4319ba4SBarry Smith 292b4319ba4SBarry Smith Output parameters: 293b4319ba4SBarry Smith . vec1_B - result of Schur complement applied to chunk 294b4319ba4SBarry Smith . vec2_B - garbage (used as work space), or null (and v is used as workspace) 295b4319ba4SBarry Smith . vec1_D - garbage (used as work space) 296b4319ba4SBarry Smith . vec2_D - garbage (used as work space) 297b4319ba4SBarry Smith 298b4319ba4SBarry Smith */ 299b4319ba4SBarry Smith #undef __FUNCT__ 300b4319ba4SBarry Smith #define __FUNCT__ "PCIterSuApplySchur" 301dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCISApplySchur(PC pc, Vec v, Vec vec1_B, Vec vec2_B, Vec vec1_D, Vec vec2_D) 302b4319ba4SBarry Smith { 303dfbe8321SBarry Smith PetscErrorCode ierr; 304b4319ba4SBarry Smith PC_IS *pcis = (PC_IS*)(pc->data); 305b4319ba4SBarry Smith 306b4319ba4SBarry Smith PetscFunctionBegin; 30713f74950SBarry Smith if (!vec2_B) { vec2_B = v; } 308b4319ba4SBarry Smith 309b4319ba4SBarry Smith ierr = MatMult(pcis->A_BB,v,vec1_B);CHKERRQ(ierr); 310b4319ba4SBarry Smith ierr = MatMult(pcis->A_IB,v,vec1_D);CHKERRQ(ierr); 31123ce1328SBarry Smith ierr = KSPSolve(pcis->ksp_D,vec1_D,vec2_D);CHKERRQ(ierr); 312b4319ba4SBarry Smith ierr = MatMult(pcis->A_BI,vec2_D,vec2_B);CHKERRQ(ierr); 313efb30889SBarry Smith ierr = VecAXPY(vec1_B,-1.0,vec2_B);CHKERRQ(ierr); 314b4319ba4SBarry Smith PetscFunctionReturn(0); 315b4319ba4SBarry Smith } 316b4319ba4SBarry Smith 317b4319ba4SBarry Smith /* -------------------------------------------------------------------------- */ 318b4319ba4SBarry Smith /* 319b4319ba4SBarry Smith PCISScatterArrayNToVecB - Scatters interface node values from a big array (of all local nodes, interior or interface, 320b4319ba4SBarry Smith including ghosts) into an interface vector, when in SCATTER_FORWARD mode, or vice-versa, when in SCATTER_REVERSE 321b4319ba4SBarry Smith mode. 322b4319ba4SBarry Smith 323b4319ba4SBarry Smith Input parameters: 324b4319ba4SBarry Smith . pc - preconditioner context 325b4319ba4SBarry Smith . array_N - [when in SCATTER_FORWARD mode] Array to be scattered into the vector 326b4319ba4SBarry Smith . v_B - [when in SCATTER_REVERSE mode] Vector to be scattered into the array 327b4319ba4SBarry Smith 328b4319ba4SBarry Smith Output parameter: 329b4319ba4SBarry Smith . array_N - [when in SCATTER_REVERSE mode] Array to receive the scattered vector 330b4319ba4SBarry Smith . v_B - [when in SCATTER_FORWARD mode] Vector to receive the scattered array 331b4319ba4SBarry Smith 332b4319ba4SBarry Smith Notes: 333b4319ba4SBarry Smith The entries in the array that do not correspond to interface nodes remain unaltered. 334b4319ba4SBarry Smith */ 335b4319ba4SBarry Smith #undef __FUNCT__ 336b4319ba4SBarry Smith #define __FUNCT__ "PCISScatterArrayNToVecB" 337dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCISScatterArrayNToVecB (PetscScalar *array_N, Vec v_B, InsertMode imode, ScatterMode smode, PC pc) 338b4319ba4SBarry Smith { 3395d0c19d7SBarry Smith PetscInt i; 3405d0c19d7SBarry Smith const PetscInt *idex; 3416849ba73SBarry Smith PetscErrorCode ierr; 342b4319ba4SBarry Smith PetscScalar *array_B; 343b4319ba4SBarry Smith PC_IS *pcis = (PC_IS*)(pc->data); 344b4319ba4SBarry Smith 345b4319ba4SBarry Smith PetscFunctionBegin; 346b4319ba4SBarry Smith ierr = VecGetArray(v_B,&array_B);CHKERRQ(ierr); 347b4319ba4SBarry Smith ierr = ISGetIndices(pcis->is_B_local,&idex);CHKERRQ(ierr); 348b4319ba4SBarry Smith 349b4319ba4SBarry Smith if (smode == SCATTER_FORWARD) { 350b4319ba4SBarry Smith if (imode == INSERT_VALUES) { 351b4319ba4SBarry Smith for (i=0; i<pcis->n_B; i++) { array_B[i] = array_N[idex[i]]; } 352b4319ba4SBarry Smith } else { /* ADD_VALUES */ 353b4319ba4SBarry Smith for (i=0; i<pcis->n_B; i++) { array_B[i] += array_N[idex[i]]; } 354b4319ba4SBarry Smith } 355b4319ba4SBarry Smith } else { /* SCATTER_REVERSE */ 356b4319ba4SBarry Smith if (imode == INSERT_VALUES) { 357b4319ba4SBarry Smith for (i=0; i<pcis->n_B; i++) { array_N[idex[i]] = array_B[i]; } 358b4319ba4SBarry Smith } else { /* ADD_VALUES */ 359b4319ba4SBarry Smith for (i=0; i<pcis->n_B; i++) { array_N[idex[i]] += array_B[i]; } 360b4319ba4SBarry Smith } 361b4319ba4SBarry Smith } 362b4319ba4SBarry Smith ierr = ISRestoreIndices(pcis->is_B_local,&idex);CHKERRQ(ierr); 363b4319ba4SBarry Smith ierr = VecRestoreArray(v_B,&array_B);CHKERRQ(ierr); 364b4319ba4SBarry Smith PetscFunctionReturn(0); 365b4319ba4SBarry Smith } 366b4319ba4SBarry Smith 367b4319ba4SBarry Smith /* -------------------------------------------------------------------------- */ 368b4319ba4SBarry Smith /* 369b4319ba4SBarry Smith PCISApplyInvSchur - Solves the Neumann problem related to applying the inverse of the Schur complement. 370b4319ba4SBarry Smith More precisely, solves the problem: 371b4319ba4SBarry Smith [ A_II A_IB ] [ . ] [ 0 ] 372b4319ba4SBarry Smith [ ] [ ] = [ ] 373b4319ba4SBarry Smith [ A_BI A_BB ] [ x ] [ b ] 374b4319ba4SBarry Smith 375b4319ba4SBarry Smith Input parameters: 376b4319ba4SBarry Smith . pc - preconditioner context 377b4319ba4SBarry Smith . b - vector of local interface nodes (including ghosts) 378b4319ba4SBarry Smith 379b4319ba4SBarry Smith Output parameters: 380b4319ba4SBarry Smith . x - vector of local interface nodes (including ghosts); returns the application of the inverse of the Schur 381b4319ba4SBarry Smith complement to b 382b4319ba4SBarry Smith . vec1_N - vector of local nodes (interior and interface, including ghosts); returns garbage (used as work space) 383b4319ba4SBarry Smith . vec2_N - vector of local nodes (interior and interface, including ghosts); returns garbage (used as work space) 384b4319ba4SBarry Smith 385b4319ba4SBarry Smith */ 386b4319ba4SBarry Smith #undef __FUNCT__ 387b4319ba4SBarry Smith #define __FUNCT__ "PCISApplyInvSchur" 388dba47a55SKris Buschelman PetscErrorCode PETSCKSP_DLLEXPORT PCISApplyInvSchur (PC pc, Vec b, Vec x, Vec vec1_N, Vec vec2_N) 389b4319ba4SBarry Smith { 390dfbe8321SBarry Smith PetscErrorCode ierr; 391b4319ba4SBarry Smith PC_IS *pcis = (PC_IS*)(pc->data); 392b4319ba4SBarry Smith 393b4319ba4SBarry Smith PetscFunctionBegin; 394b4319ba4SBarry Smith /* 395b4319ba4SBarry Smith Neumann solvers. 396b4319ba4SBarry Smith Applying the inverse of the local Schur complement, i.e, solving a Neumann 397b4319ba4SBarry Smith Problem with zero at the interior nodes of the RHS and extracting the interface 398b4319ba4SBarry Smith part of the solution. inverse Schur complement is applied to b and the result 399b4319ba4SBarry Smith is stored in x. 400b4319ba4SBarry Smith */ 401b4319ba4SBarry Smith /* Setting the RHS vec1_N */ 402efb30889SBarry Smith ierr = VecSet(vec1_N,0.0);CHKERRQ(ierr); 403ca9f406cSSatish Balay ierr = VecScatterBegin(pcis->N_to_B,b,vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 404ca9f406cSSatish Balay ierr = VecScatterEnd (pcis->N_to_B,b,vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 405b4319ba4SBarry Smith /* Checking for consistency of the RHS */ 406b4319ba4SBarry Smith { 407ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 408*acfcf0e5SJed Brown ierr = PetscOptionsGetBool(PETSC_NULL,"-pc_is_check_consistency",&flg,PETSC_NULL);CHKERRQ(ierr); 409b4319ba4SBarry Smith if (flg) { 410b4319ba4SBarry Smith PetscScalar average; 4113050cee2SBarry Smith PetscViewer viewer; 4127adad957SLisandro Dalcin ierr = PetscViewerASCIIGetStdout(((PetscObject)pc)->comm,&viewer);CHKERRQ(ierr); 4133050cee2SBarry Smith 414b4319ba4SBarry Smith ierr = VecSum(vec1_N,&average);CHKERRQ(ierr); 415b4319ba4SBarry Smith average = average / ((PetscReal)pcis->n); 416b4319ba4SBarry Smith if (pcis->pure_neumann) { 4173050cee2SBarry Smith 4189f73f8ecSBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d is floating. Average = % 1.14e\n",PetscGlobalRank,PetscAbsScalar(average));CHKERRQ(ierr); 419b4319ba4SBarry Smith } else { 4209f73f8ecSBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"Subdomain %04d is fixed. Average = % 1.14e\n",PetscGlobalRank,PetscAbsScalar(average));CHKERRQ(ierr); 421b4319ba4SBarry Smith } 4223050cee2SBarry Smith ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 423b4319ba4SBarry Smith } 424b4319ba4SBarry Smith } 425b4319ba4SBarry Smith /* Solving the system for vec2_N */ 42623ce1328SBarry Smith ierr = KSPSolve(pcis->ksp_N,vec1_N,vec2_N);CHKERRQ(ierr); 427b4319ba4SBarry Smith /* Extracting the local interface vector out of the solution */ 428ca9f406cSSatish Balay ierr = VecScatterBegin(pcis->N_to_B,vec2_N,x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 429ca9f406cSSatish Balay ierr = VecScatterEnd (pcis->N_to_B,vec2_N,x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 430b4319ba4SBarry Smith PetscFunctionReturn(0); 431b4319ba4SBarry Smith } 432b4319ba4SBarry Smith 433b4319ba4SBarry Smith 434b4319ba4SBarry Smith 435b4319ba4SBarry Smith 436b4319ba4SBarry Smith 437b4319ba4SBarry Smith 438b4319ba4SBarry Smith 439b4319ba4SBarry Smith 440b4319ba4SBarry Smith 441