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