xref: /petsc/src/ksp/pc/impls/is/pcis.c (revision f1580f4e3ce5d5b2393648fd039d0d41b440385d)
123ce1328SBarry Smith 
25e5bbd0aSStefano Zampini #include <petsc/private/pcisimpl.h> /*I "petscpc.h" I*/
3831a100dSStefano Zampini 
49371c9d4SSatish Balay static PetscErrorCode PCISSetUseStiffnessScaling_IS(PC pc, PetscBool use) {
5b965d45eSStefano Zampini   PC_IS *pcis = (PC_IS *)pc->data;
6b965d45eSStefano Zampini 
7b965d45eSStefano Zampini   PetscFunctionBegin;
8b965d45eSStefano Zampini   pcis->use_stiffness_scaling = use;
9b965d45eSStefano Zampini   PetscFunctionReturn(0);
10b965d45eSStefano Zampini }
11b965d45eSStefano Zampini 
12b965d45eSStefano Zampini /*@
13*f1580f4eSBarry Smith    PCISSetUseStiffnessScaling - Tells `PCIS` to construct partition of unity using
14*f1580f4eSBarry Smith                               the local matrices' diagonal entries
15b965d45eSStefano Zampini 
16*f1580f4eSBarry Smith    Logically Collective
17b965d45eSStefano Zampini 
18b965d45eSStefano Zampini    Input Parameters:
19b965d45eSStefano Zampini +  pc - the preconditioning context
20b965d45eSStefano Zampini -  use - whether or not pcis use matrix diagonal to build partition of unity.
21b965d45eSStefano Zampini 
22b965d45eSStefano Zampini    Level: intermediate
23b965d45eSStefano Zampini 
24*f1580f4eSBarry Smith    Developer Note:
25*f1580f4eSBarry Smith    There is no manual page for `PCIS` nor some of its methods
26b965d45eSStefano Zampini 
27*f1580f4eSBarry Smith .seealso: `PCIS`, `PCBDDC`
28b965d45eSStefano Zampini @*/
299371c9d4SSatish Balay PetscErrorCode PCISSetUseStiffnessScaling(PC pc, PetscBool use) {
30b965d45eSStefano Zampini   PetscFunctionBegin;
31b965d45eSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
32064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveBool(pc, use, 2);
33cac4c232SBarry Smith   PetscTryMethod(pc, "PCISSetUseStiffnessScaling_C", (PC, PetscBool), (pc, use));
34b965d45eSStefano Zampini   PetscFunctionReturn(0);
35b965d45eSStefano Zampini }
36b965d45eSStefano Zampini 
379371c9d4SSatish Balay static PetscErrorCode PCISSetSubdomainDiagonalScaling_IS(PC pc, Vec scaling_factors) {
38ba1573a8SStefano Zampini   PC_IS *pcis = (PC_IS *)pc->data;
39ba1573a8SStefano Zampini 
40ba1573a8SStefano Zampini   PetscFunctionBegin;
419566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)scaling_factors));
429566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->D));
43ba1573a8SStefano Zampini   pcis->D = scaling_factors;
44a007db60SStefano Zampini   if (pc->setupcalled) {
45a007db60SStefano Zampini     PetscInt sn;
46a007db60SStefano Zampini 
479566063dSJacob Faibussowitsch     PetscCall(VecGetSize(pcis->D, &sn));
48a007db60SStefano Zampini     if (sn == pcis->n) {
499566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->D, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
509566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->D, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
519566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&pcis->D));
529566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(pcis->vec1_B, &pcis->D));
539566063dSJacob Faibussowitsch       PetscCall(VecCopy(pcis->vec1_B, pcis->D));
5463a3b9bcSJacob Faibussowitsch     } else PetscCheck(sn == pcis->n_B, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Invalid size for scaling vector. Expected %" PetscInt_FMT " (or full %" PetscInt_FMT "), found %" PetscInt_FMT, pcis->n_B, pcis->n, sn);
55a007db60SStefano Zampini   }
56ba1573a8SStefano Zampini   PetscFunctionReturn(0);
57ba1573a8SStefano Zampini }
58ba1573a8SStefano Zampini 
59ba1573a8SStefano Zampini /*@
60*f1580f4eSBarry Smith    PCISSetSubdomainDiagonalScaling - Set diagonal scaling for `PCIS`.
61ba1573a8SStefano Zampini 
62*f1580f4eSBarry Smith    Logically Collective
63ba1573a8SStefano Zampini 
64ba1573a8SStefano Zampini    Input Parameters:
65ba1573a8SStefano Zampini +  pc - the preconditioning context
66ba1573a8SStefano Zampini -  scaling_factors - scaling factors for the subdomain
67ba1573a8SStefano Zampini 
68ba1573a8SStefano Zampini    Level: intermediate
69ba1573a8SStefano Zampini 
70*f1580f4eSBarry Smith    Note:
71*f1580f4eSBarry Smith    Intended for use with jumping coefficients cases.
72ba1573a8SStefano Zampini 
73*f1580f4eSBarry Smith    Developer Note:
74*f1580f4eSBarry Smith    There is no manual page for `PCIS` nor some of its methods
75*f1580f4eSBarry Smith 
76*f1580f4eSBarry Smith .seealso: `PCIS`, `PCBDDC`
77ba1573a8SStefano Zampini @*/
789371c9d4SSatish Balay PetscErrorCode PCISSetSubdomainDiagonalScaling(PC pc, Vec scaling_factors) {
79ba1573a8SStefano Zampini   PetscFunctionBegin;
80ba1573a8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
81a007db60SStefano Zampini   PetscValidHeaderSpecific(scaling_factors, VEC_CLASSID, 2);
82cac4c232SBarry Smith   PetscTryMethod(pc, "PCISSetSubdomainDiagonalScaling_C", (PC, Vec), (pc, scaling_factors));
83ba1573a8SStefano Zampini   PetscFunctionReturn(0);
84ba1573a8SStefano Zampini }
85ba1573a8SStefano Zampini 
869371c9d4SSatish Balay static PetscErrorCode PCISSetSubdomainScalingFactor_IS(PC pc, PetscScalar scal) {
87831a100dSStefano Zampini   PC_IS *pcis = (PC_IS *)pc->data;
88831a100dSStefano Zampini 
89831a100dSStefano Zampini   PetscFunctionBegin;
90831a100dSStefano Zampini   pcis->scaling_factor = scal;
9148a46eb9SPierre Jolivet   if (pcis->D) PetscCall(VecSet(pcis->D, pcis->scaling_factor));
92831a100dSStefano Zampini   PetscFunctionReturn(0);
93831a100dSStefano Zampini }
94831a100dSStefano Zampini 
95831a100dSStefano Zampini /*@
96*f1580f4eSBarry Smith  PCISSetSubdomainScalingFactor - Set scaling factor for `PCIS`.
97831a100dSStefano Zampini 
98831a100dSStefano Zampini    Not collective
99831a100dSStefano Zampini 
100831a100dSStefano Zampini    Input Parameters:
101831a100dSStefano Zampini +  pc - the preconditioning context
102831a100dSStefano Zampini -  scal - scaling factor for the subdomain
103831a100dSStefano Zampini 
104831a100dSStefano Zampini    Level: intermediate
105831a100dSStefano Zampini 
106*f1580f4eSBarry Smith    Note:
107*f1580f4eSBarry Smith    Intended for use with the jumping coefficients cases.
108831a100dSStefano Zampini 
109*f1580f4eSBarry Smith    Developer Note:
110*f1580f4eSBarry Smith    There is no manual page for `PCIS` nor some of its methods
111*f1580f4eSBarry Smith 
112*f1580f4eSBarry Smith .seealso: `PCIS`, `PCBDDC`
113831a100dSStefano Zampini @*/
1149371c9d4SSatish Balay PetscErrorCode PCISSetSubdomainScalingFactor(PC pc, PetscScalar scal) {
115831a100dSStefano Zampini   PetscFunctionBegin;
116831a100dSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
117cac4c232SBarry Smith   PetscTryMethod(pc, "PCISSetSubdomainScalingFactor_C", (PC, PetscScalar), (pc, scal));
118831a100dSStefano Zampini   PetscFunctionReturn(0);
119831a100dSStefano Zampini }
120831a100dSStefano Zampini 
1219371c9d4SSatish Balay PetscErrorCode PCISSetUp(PC pc, PetscBool computematrices, PetscBool computesolvers) {
122b4319ba4SBarry Smith   PC_IS    *pcis = (PC_IS *)(pc->data);
123bf327c11SStefano Zampini   Mat_IS   *matis;
1245e8657edSStefano Zampini   MatReuse  reuse;
12585c21eb1SStefano Zampini   PetscBool flg, issbaij;
126b4319ba4SBarry Smith 
127b4319ba4SBarry Smith   PetscFunctionBegin;
1289566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATIS, &flg));
12928b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Requires preconditioning matrix of type MATIS");
13085c21eb1SStefano Zampini   matis = (Mat_IS *)pc->pmat->data;
1312f37b69bSStefano Zampini   if (pc->useAmat) {
1329566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pc->mat, MATIS, &flg));
13328b400f6SJacob Faibussowitsch     PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Requires linear system matrix of type MATIS");
1342f37b69bSStefano Zampini   }
135b4319ba4SBarry Smith 
1365e8657edSStefano Zampini   /* first time creation, get info on substructuring */
1375e8657edSStefano Zampini   if (!pc->setupcalled) {
1385e8657edSStefano Zampini     PetscInt  n_I;
1395e8657edSStefano Zampini     PetscInt *idx_I_local, *idx_B_local, *idx_I_global, *idx_B_global;
1406f516dd7SStefano Zampini     PetscBT   bt;
1415e8657edSStefano Zampini     PetscInt  i, j;
142b4319ba4SBarry Smith 
143892d8026SStefano Zampini     /* get info on mapping */
1449566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->rmapping));
1459566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&pcis->mapping));
146e432b41dSStefano Zampini     pcis->mapping = matis->rmapping;
1479566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(pcis->mapping, &pcis->n));
1489566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetInfo(pcis->mapping, &(pcis->n_neigh), &(pcis->neigh), &(pcis->n_shared), &(pcis->shared)));
149892d8026SStefano Zampini 
150b4319ba4SBarry Smith     /* Identifying interior and interface nodes, in local numbering */
1519566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(pcis->n, &bt));
1524843afd6SStefano Zampini     for (i = 0; i < pcis->n_neigh; i++)
15348a46eb9SPierre Jolivet       for (j = 0; j < pcis->n_shared[i]; j++) PetscCall(PetscBTSet(bt, pcis->shared[i][j]));
154892d8026SStefano Zampini 
1555e8657edSStefano Zampini     /* Creating local and global index sets for interior and inteface nodes. */
1569566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n, &idx_I_local));
1579566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n, &idx_B_local));
158b4319ba4SBarry Smith     for (i = 0, pcis->n_B = 0, n_I = 0; i < pcis->n; i++) {
1596f516dd7SStefano Zampini       if (!PetscBTLookup(bt, i)) {
1602fa5cd67SKarl Rupp         idx_I_local[n_I] = i;
1612fa5cd67SKarl Rupp         n_I++;
1622fa5cd67SKarl Rupp       } else {
1632fa5cd67SKarl Rupp         idx_B_local[pcis->n_B] = i;
1642fa5cd67SKarl Rupp         pcis->n_B++;
1652fa5cd67SKarl Rupp       }
166b4319ba4SBarry Smith     }
1676f516dd7SStefano Zampini 
168b4319ba4SBarry Smith     /* Getting the global numbering */
169b4319ba4SBarry Smith     idx_B_global = idx_I_local + n_I; /* Just avoiding allocating extra memory, since we have vacant space */
170b4319ba4SBarry Smith     idx_I_global = idx_B_local + pcis->n_B;
1719566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(pcis->mapping, pcis->n_B, idx_B_local, idx_B_global));
1729566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(pcis->mapping, n_I, idx_I_local, idx_I_global));
1732fa5cd67SKarl Rupp 
1745e8657edSStefano Zampini     /* Creating the index sets */
1759566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pcis->n_B, idx_B_local, PETSC_COPY_VALUES, &pcis->is_B_local));
1769566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), pcis->n_B, idx_B_global, PETSC_COPY_VALUES, &pcis->is_B_global));
1779566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n_I, idx_I_local, PETSC_COPY_VALUES, &pcis->is_I_local));
1789566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), n_I, idx_I_global, PETSC_COPY_VALUES, &pcis->is_I_global));
1792fa5cd67SKarl Rupp 
1805e8657edSStefano Zampini     /* Freeing memory */
1819566063dSJacob Faibussowitsch     PetscCall(PetscFree(idx_B_local));
1829566063dSJacob Faibussowitsch     PetscCall(PetscFree(idx_I_local));
1839566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&bt));
184b4319ba4SBarry Smith 
1855e8657edSStefano Zampini     /* Creating work vectors and arrays */
1869566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(matis->x, &pcis->vec1_N));
1879566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_N, &pcis->vec2_N));
1889566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &pcis->vec1_D));
1899566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(pcis->vec1_D, pcis->n - pcis->n_B, PETSC_DECIDE));
1909566063dSJacob Faibussowitsch     PetscCall(VecSetType(pcis->vec1_D, ((PetscObject)pcis->vec1_N)->type_name));
1919566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_D, &pcis->vec2_D));
1929566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_D, &pcis->vec3_D));
1939566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_D, &pcis->vec4_D));
1949566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &pcis->vec1_B));
1959566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(pcis->vec1_B, pcis->n_B, PETSC_DECIDE));
1969566063dSJacob Faibussowitsch     PetscCall(VecSetType(pcis->vec1_B, ((PetscObject)pcis->vec1_N)->type_name));
1979566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_B, &pcis->vec2_B));
1989566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_B, &pcis->vec3_B));
1999566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(pc->pmat, &pcis->vec1_global, NULL));
2009566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n, &pcis->work_N));
2015e8657edSStefano Zampini     /* scaling vector */
202bf83c2afSStefano Zampini     if (!pcis->D) { /* it can happen that the user passed in a scaling vector via PCISSetSubdomainDiagonalScaling */
2039566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(pcis->vec1_B, &pcis->D));
2049566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->D, pcis->scaling_factor));
205bf83c2afSStefano Zampini     }
206b4319ba4SBarry Smith 
207b4319ba4SBarry Smith     /* Creating the scatter contexts */
2089566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(pcis->vec1_N, pcis->is_I_local, pcis->vec1_D, (IS)0, &pcis->N_to_D));
2099566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(pcis->vec1_global, pcis->is_I_global, pcis->vec1_D, (IS)0, &pcis->global_to_D));
2109566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(pcis->vec1_N, pcis->is_B_local, pcis->vec1_B, (IS)0, &pcis->N_to_B));
2119566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(pcis->vec1_global, pcis->is_B_global, pcis->vec1_B, (IS)0, &pcis->global_to_B));
212b4319ba4SBarry Smith 
2135e8657edSStefano Zampini     /* map from boundary to local */
2149566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(pcis->is_B_local, &pcis->BtoNmap));
2155e8657edSStefano Zampini   }
2165e8657edSStefano Zampini 
217a007db60SStefano Zampini   {
218a007db60SStefano Zampini     PetscInt sn;
219a007db60SStefano Zampini 
2209566063dSJacob Faibussowitsch     PetscCall(VecGetSize(pcis->D, &sn));
221a007db60SStefano Zampini     if (sn == pcis->n) {
2229566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->D, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
2239566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->D, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
2249566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&pcis->D));
2259566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(pcis->vec1_B, &pcis->D));
2269566063dSJacob Faibussowitsch       PetscCall(VecCopy(pcis->vec1_B, pcis->D));
22763a3b9bcSJacob Faibussowitsch     } else PetscCheck(sn == pcis->n_B, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Invalid size for scaling vector. Expected %" PetscInt_FMT " (or full %" PetscInt_FMT "), found %" PetscInt_FMT, pcis->n_B, pcis->n, sn);
228a007db60SStefano Zampini   }
229a007db60SStefano Zampini 
2305e8657edSStefano Zampini   /*
2315e8657edSStefano Zampini     Extracting the blocks A_II, A_BI, A_IB and A_BB from A. If the numbering
2325e8657edSStefano Zampini     is such that interior nodes come first than the interface ones, we have
2335e8657edSStefano Zampini 
2345e8657edSStefano Zampini         [ A_II | A_IB ]
2355e8657edSStefano Zampini     A = [------+------]
2365e8657edSStefano Zampini         [ A_BI | A_BB ]
2375e8657edSStefano Zampini   */
238d9869140SStefano Zampini   if (computematrices) {
2392f37b69bSStefano Zampini     PetscBool amat = (PetscBool)(pc->mat != pc->pmat && pc->useAmat);
2402f37b69bSStefano Zampini     PetscInt  bs, ibs;
2412f37b69bSStefano Zampini 
2425e8657edSStefano Zampini     reuse = MAT_INITIAL_MATRIX;
2433975b054SStefano Zampini     if (pcis->reusesubmatrices && pc->setupcalled) {
2445e8657edSStefano Zampini       if (pc->flag == SAME_NONZERO_PATTERN) {
2455e8657edSStefano Zampini         reuse = MAT_REUSE_MATRIX;
2465e8657edSStefano Zampini       } else {
2475e8657edSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2485e8657edSStefano Zampini       }
2495e8657edSStefano Zampini     }
2505e8657edSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
2519566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcis->A_II));
2529566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcis->pA_II));
2539566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcis->A_IB));
2549566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcis->A_BI));
2559566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcis->A_BB));
2565e8657edSStefano Zampini     }
2575e8657edSStefano Zampini 
2589566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(pcis->mapping, &ibs));
2599566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(matis->A, &bs));
2609566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(matis->A, pcis->is_I_local, pcis->is_I_local, reuse, &pcis->pA_II));
2612f37b69bSStefano Zampini     if (amat) {
2622f37b69bSStefano Zampini       Mat_IS *amatis = (Mat_IS *)pc->mat->data;
2639566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(amatis->A, pcis->is_I_local, pcis->is_I_local, reuse, &pcis->A_II));
2642f37b69bSStefano Zampini     } else {
2659566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)pcis->pA_II));
2669566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcis->A_II));
2672f37b69bSStefano Zampini       pcis->A_II = pcis->pA_II;
2682f37b69bSStefano Zampini     }
2699566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(pcis->A_II, bs == ibs ? bs : 1));
2709566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(pcis->pA_II, bs == ibs ? bs : 1));
2719566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(matis->A, pcis->is_B_local, pcis->is_B_local, reuse, &pcis->A_BB));
2729566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &issbaij));
2735e8657edSStefano Zampini     if (!issbaij) {
2749566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(matis->A, pcis->is_I_local, pcis->is_B_local, reuse, &pcis->A_IB));
2759566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(matis->A, pcis->is_B_local, pcis->is_I_local, reuse, &pcis->A_BI));
2765e8657edSStefano Zampini     } else {
2775e8657edSStefano Zampini       Mat newmat;
278d9869140SStefano Zampini 
2799566063dSJacob Faibussowitsch       PetscCall(MatConvert(matis->A, MATSEQBAIJ, MAT_INITIAL_MATRIX, &newmat));
2809566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(newmat, pcis->is_I_local, pcis->is_B_local, reuse, &pcis->A_IB));
2819566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(newmat, pcis->is_B_local, pcis->is_I_local, reuse, &pcis->A_BI));
2829566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&newmat));
2835e8657edSStefano Zampini     }
2849566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(pcis->A_BB, bs == ibs ? bs : 1));
285d9869140SStefano Zampini   }
2865e8657edSStefano Zampini 
287bf83c2afSStefano Zampini   /* Creating scaling vector D */
2889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)pc)->options, ((PetscObject)pc)->prefix, "-pc_is_use_stiffness_scaling", &pcis->use_stiffness_scaling, NULL));
289bf83c2afSStefano Zampini   if (pcis->use_stiffness_scaling) {
29015f235b8SStefano Zampini     PetscScalar *a;
29115f235b8SStefano Zampini     PetscInt     i, n;
29215f235b8SStefano Zampini 
293d9869140SStefano Zampini     if (pcis->A_BB) {
2949566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(pcis->A_BB, pcis->D));
295d9869140SStefano Zampini     } else {
2969566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(matis->A, pcis->vec1_N));
2979566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_N, pcis->D, INSERT_VALUES, SCATTER_FORWARD));
2989566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_N, pcis->D, INSERT_VALUES, SCATTER_FORWARD));
299d9869140SStefano Zampini     }
3009566063dSJacob Faibussowitsch     PetscCall(VecAbs(pcis->D));
3019566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(pcis->D, &n));
3029566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcis->D, &a));
3039371c9d4SSatish Balay     for (i = 0; i < n; i++)
3049371c9d4SSatish Balay       if (PetscAbsScalar(a[i]) < PETSC_SMALL) a[i] = 1.0;
3059566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcis->D, &a));
306ba1573a8SStefano Zampini   }
3079566063dSJacob Faibussowitsch   PetscCall(VecSet(pcis->vec1_global, 0.0));
3089566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, pcis->D, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE));
3099566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, pcis->D, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE));
3109566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_global, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
3119566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_global, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
3129566063dSJacob Faibussowitsch   PetscCall(VecPointwiseDivide(pcis->D, pcis->D, pcis->vec1_B));
313b4319ba4SBarry Smith   /* See historical note 01, at the bottom of this file. */
314b4319ba4SBarry Smith 
3155e8657edSStefano Zampini   /* Creating the KSP contexts for the local Dirichlet and Neumann problems */
3165e8657edSStefano Zampini   if (computesolvers) {
317b4319ba4SBarry Smith     PC pc_ctx;
3185e8657edSStefano Zampini 
3195e8657edSStefano Zampini     pcis->pure_neumann = matis->pure_neumann;
320b4319ba4SBarry Smith     /* Dirichlet */
3219566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PETSC_COMM_SELF, &pcis->ksp_D));
3229566063dSJacob Faibussowitsch     PetscCall(KSPSetErrorIfNotConverged(pcis->ksp_D, pc->erroriffailure));
3239566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcis->ksp_D, (PetscObject)pc, 1));
3249566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(pcis->ksp_D, pcis->A_II, pcis->A_II));
3259566063dSJacob Faibussowitsch     PetscCall(KSPSetOptionsPrefix(pcis->ksp_D, "is_localD_"));
3269566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(pcis->ksp_D, &pc_ctx));
3279566063dSJacob Faibussowitsch     PetscCall(PCSetType(pc_ctx, PCLU));
3289566063dSJacob Faibussowitsch     PetscCall(KSPSetType(pcis->ksp_D, KSPPREONLY));
3299566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(pcis->ksp_D));
330b4319ba4SBarry Smith     /* the vectors in the following line are dummy arguments, just telling the KSP the vector size. Values are not used */
3319566063dSJacob Faibussowitsch     PetscCall(KSPSetUp(pcis->ksp_D));
332b4319ba4SBarry Smith     /* Neumann */
3339566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PETSC_COMM_SELF, &pcis->ksp_N));
3349566063dSJacob Faibussowitsch     PetscCall(KSPSetErrorIfNotConverged(pcis->ksp_N, pc->erroriffailure));
3359566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcis->ksp_N, (PetscObject)pc, 1));
3369566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(pcis->ksp_N, matis->A, matis->A));
3379566063dSJacob Faibussowitsch     PetscCall(KSPSetOptionsPrefix(pcis->ksp_N, "is_localN_"));
3389566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(pcis->ksp_N, &pc_ctx));
3399566063dSJacob Faibussowitsch     PetscCall(PCSetType(pc_ctx, PCLU));
3409566063dSJacob Faibussowitsch     PetscCall(KSPSetType(pcis->ksp_N, KSPPREONLY));
3419566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(pcis->ksp_N));
342b4319ba4SBarry Smith     {
3439371c9d4SSatish Balay       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;
3449371c9d4SSatish Balay       PetscReal fixed_factor, floating_factor;
345b4319ba4SBarry Smith 
3469566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_damp_fixed", &fixed_factor, &damp_fixed));
3472fa5cd67SKarl Rupp       if (!damp_fixed) fixed_factor = 0.0;
3489566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_damp_fixed", &damp_fixed, NULL));
349b4319ba4SBarry Smith 
3509566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_remove_nullspace_fixed", &remove_nullspace_fixed, NULL));
351b4319ba4SBarry Smith 
352d0609cedSBarry Smith       PetscCall(PetscOptionsGetReal(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_set_damping_factor_floating", &floating_factor, &set_damping_factor_floating));
3532fa5cd67SKarl Rupp       if (!set_damping_factor_floating) floating_factor = 0.0;
3549566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_set_damping_factor_floating", &set_damping_factor_floating, NULL));
3552fa5cd67SKarl Rupp       if (!set_damping_factor_floating) floating_factor = 1.e-12;
356b4319ba4SBarry Smith 
3579566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_not_damp_floating", &not_damp_floating, NULL));
358b4319ba4SBarry Smith 
3599566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_not_remove_nullspace_floating", &not_remove_nullspace_floating, NULL));
360b4319ba4SBarry Smith 
361b4319ba4SBarry Smith       if (pcis->pure_neumann) { /* floating subdomain */
362b4319ba4SBarry Smith         if (!(not_damp_floating)) {
3639566063dSJacob Faibussowitsch           PetscCall(PCFactorSetShiftType(pc_ctx, MAT_SHIFT_NONZERO));
3649566063dSJacob Faibussowitsch           PetscCall(PCFactorSetShiftAmount(pc_ctx, floating_factor));
365b4319ba4SBarry Smith         }
366b4319ba4SBarry Smith         if (!(not_remove_nullspace_floating)) {
367b4319ba4SBarry Smith           MatNullSpace nullsp;
3689566063dSJacob Faibussowitsch           PetscCall(MatNullSpaceCreate(PETSC_COMM_SELF, PETSC_TRUE, 0, NULL, &nullsp));
3699566063dSJacob Faibussowitsch           PetscCall(MatSetNullSpace(matis->A, nullsp));
3709566063dSJacob Faibussowitsch           PetscCall(MatNullSpaceDestroy(&nullsp));
371b4319ba4SBarry Smith         }
372b4319ba4SBarry Smith       } else { /* fixed subdomain */
373b4319ba4SBarry Smith         if (damp_fixed) {
3749566063dSJacob Faibussowitsch           PetscCall(PCFactorSetShiftType(pc_ctx, MAT_SHIFT_NONZERO));
3759566063dSJacob Faibussowitsch           PetscCall(PCFactorSetShiftAmount(pc_ctx, floating_factor));
376b4319ba4SBarry Smith         }
377b4319ba4SBarry Smith         if (remove_nullspace_fixed) {
378b4319ba4SBarry Smith           MatNullSpace nullsp;
3799566063dSJacob Faibussowitsch           PetscCall(MatNullSpaceCreate(PETSC_COMM_SELF, PETSC_TRUE, 0, NULL, &nullsp));
3809566063dSJacob Faibussowitsch           PetscCall(MatSetNullSpace(matis->A, nullsp));
3819566063dSJacob Faibussowitsch           PetscCall(MatNullSpaceDestroy(&nullsp));
382b4319ba4SBarry Smith         }
383b4319ba4SBarry Smith       }
384b4319ba4SBarry Smith     }
385b4319ba4SBarry Smith     /* the vectors in the following line are dummy arguments, just telling the KSP the vector size. Values are not used */
3869566063dSJacob Faibussowitsch     PetscCall(KSPSetUp(pcis->ksp_N));
387b4319ba4SBarry Smith   }
388b4319ba4SBarry Smith   PetscFunctionReturn(0);
389b4319ba4SBarry Smith }
390b4319ba4SBarry Smith 
391b4319ba4SBarry Smith /*
392b4319ba4SBarry Smith    PCISDestroy -
393b4319ba4SBarry Smith */
3949371c9d4SSatish Balay PetscErrorCode PCISDestroy(PC pc) {
395747c8291SStefano Zampini   PC_IS *pcis;
396b4319ba4SBarry Smith 
397b4319ba4SBarry Smith   PetscFunctionBegin;
398747c8291SStefano Zampini   if (!pc) PetscFunctionReturn(0);
399747c8291SStefano Zampini   pcis = (PC_IS *)(pc->data);
4009566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcis->is_B_local));
4019566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcis->is_I_local));
4029566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcis->is_B_global));
4039566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcis->is_I_global));
4049566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcis->A_II));
4059566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcis->pA_II));
4069566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcis->A_IB));
4079566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcis->A_BI));
4089566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcis->A_BB));
4099566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->D));
4109566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcis->ksp_N));
4119566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcis->ksp_D));
4129566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec1_N));
4139566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec2_N));
4149566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec1_D));
4159566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec2_D));
4169566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec3_D));
4179566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec4_D));
4189566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec1_B));
4199566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec2_B));
4209566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec3_B));
4219566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec1_global));
4229566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcis->global_to_D));
4239566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcis->N_to_B));
4249566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcis->N_to_D));
4259566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcis->global_to_B));
4269566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcis->work_N));
42748a46eb9SPierre Jolivet   if (pcis->n_neigh > -1) PetscCall(ISLocalToGlobalMappingRestoreInfo(pcis->mapping, &(pcis->n_neigh), &(pcis->neigh), &(pcis->n_shared), &(pcis->shared)));
4289566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&pcis->mapping));
4299566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&pcis->BtoNmap));
4309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCISSetUseStiffnessScaling_C", NULL));
4319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCISSetSubdomainScalingFactor_C", NULL));
4329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCISSetSubdomainDiagonalScaling_C", NULL));
433b4319ba4SBarry Smith   PetscFunctionReturn(0);
434b4319ba4SBarry Smith }
435b4319ba4SBarry Smith 
436b4319ba4SBarry Smith /*
437b4319ba4SBarry Smith    PCISCreate -
438b4319ba4SBarry Smith */
4399371c9d4SSatish Balay PetscErrorCode PCISCreate(PC pc) {
440b4319ba4SBarry Smith   PC_IS *pcis = (PC_IS *)(pc->data);
441b4319ba4SBarry Smith 
442b4319ba4SBarry Smith   PetscFunctionBegin;
443747c8291SStefano Zampini   if (!pcis) {
444747c8291SStefano Zampini     PetscCall(PetscNewLog(pc, &pcis));
445747c8291SStefano Zampini     pc->data = pcis;
446747c8291SStefano Zampini   }
4477dbfca69SStefano Zampini   pcis->n_neigh          = -1;
448831a100dSStefano Zampini   pcis->scaling_factor   = 1.0;
4493975b054SStefano Zampini   pcis->reusesubmatrices = PETSC_TRUE;
450831a100dSStefano Zampini   /* composing functions */
4519566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCISSetUseStiffnessScaling_C", PCISSetUseStiffnessScaling_IS));
4529566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCISSetSubdomainScalingFactor_C", PCISSetSubdomainScalingFactor_IS));
4539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCISSetSubdomainDiagonalScaling_C", PCISSetSubdomainDiagonalScaling_IS));
454b4319ba4SBarry Smith   PetscFunctionReturn(0);
455b4319ba4SBarry Smith }
456b4319ba4SBarry Smith 
457b4319ba4SBarry Smith /*
458b4319ba4SBarry Smith    PCISApplySchur -
459b4319ba4SBarry Smith 
460b4319ba4SBarry Smith    Input parameters:
461b4319ba4SBarry Smith .  pc - preconditioner context
462b4319ba4SBarry Smith .  v - vector to which the Schur complement is to be applied (it is NOT modified inside this function, UNLESS vec2_B is null)
463b4319ba4SBarry Smith 
464b4319ba4SBarry Smith    Output parameters:
465b4319ba4SBarry Smith .  vec1_B - result of Schur complement applied to chunk
466b4319ba4SBarry Smith .  vec2_B - garbage (used as work space), or null (and v is used as workspace)
467b4319ba4SBarry Smith .  vec1_D - garbage (used as work space)
468b4319ba4SBarry Smith .  vec2_D - garbage (used as work space)
469b4319ba4SBarry Smith 
470b4319ba4SBarry Smith */
4719371c9d4SSatish Balay PetscErrorCode PCISApplySchur(PC pc, Vec v, Vec vec1_B, Vec vec2_B, Vec vec1_D, Vec vec2_D) {
472b4319ba4SBarry Smith   PC_IS *pcis = (PC_IS *)(pc->data);
473b4319ba4SBarry Smith 
474b4319ba4SBarry Smith   PetscFunctionBegin;
4752fa5cd67SKarl Rupp   if (!vec2_B) vec2_B = v;
476b4319ba4SBarry Smith 
4779566063dSJacob Faibussowitsch   PetscCall(MatMult(pcis->A_BB, v, vec1_B));
4789566063dSJacob Faibussowitsch   PetscCall(MatMult(pcis->A_IB, v, vec1_D));
4799566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcis->ksp_D, vec1_D, vec2_D));
4809566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcis->ksp_D, pc, vec2_D));
4819566063dSJacob Faibussowitsch   PetscCall(MatMult(pcis->A_BI, vec2_D, vec2_B));
4829566063dSJacob Faibussowitsch   PetscCall(VecAXPY(vec1_B, -1.0, vec2_B));
483b4319ba4SBarry Smith   PetscFunctionReturn(0);
484b4319ba4SBarry Smith }
485b4319ba4SBarry Smith 
486b4319ba4SBarry Smith /*
487b4319ba4SBarry Smith    PCISScatterArrayNToVecB - Scatters interface node values from a big array (of all local nodes, interior or interface,
488b4319ba4SBarry Smith    including ghosts) into an interface vector, when in SCATTER_FORWARD mode, or vice-versa, when in SCATTER_REVERSE
489b4319ba4SBarry Smith    mode.
490b4319ba4SBarry Smith 
491b4319ba4SBarry Smith    Input parameters:
492b4319ba4SBarry Smith .  pc - preconditioner context
493b4319ba4SBarry Smith .  array_N - [when in SCATTER_FORWARD mode] Array to be scattered into the vector
494b4319ba4SBarry Smith .  v_B - [when in SCATTER_REVERSE mode] Vector to be scattered into the array
495b4319ba4SBarry Smith 
496b4319ba4SBarry Smith    Output parameter:
497b4319ba4SBarry Smith .  array_N - [when in SCATTER_REVERSE mode] Array to receive the scattered vector
498b4319ba4SBarry Smith .  v_B - [when in SCATTER_FORWARD mode] Vector to receive the scattered array
499b4319ba4SBarry Smith 
500*f1580f4eSBarry Smith    Note:
501b4319ba4SBarry Smith    The entries in the array that do not correspond to interface nodes remain unaltered.
502b4319ba4SBarry Smith */
5039371c9d4SSatish Balay PetscErrorCode PCISScatterArrayNToVecB(PetscScalar *array_N, Vec v_B, InsertMode imode, ScatterMode smode, PC pc) {
5045d0c19d7SBarry Smith   PetscInt        i;
5055d0c19d7SBarry Smith   const PetscInt *idex;
506b4319ba4SBarry Smith   PetscScalar    *array_B;
507b4319ba4SBarry Smith   PC_IS          *pcis = (PC_IS *)(pc->data);
508b4319ba4SBarry Smith 
509b4319ba4SBarry Smith   PetscFunctionBegin;
5109566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v_B, &array_B));
5119566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(pcis->is_B_local, &idex));
512b4319ba4SBarry Smith 
513b4319ba4SBarry Smith   if (smode == SCATTER_FORWARD) {
514b4319ba4SBarry Smith     if (imode == INSERT_VALUES) {
5152fa5cd67SKarl Rupp       for (i = 0; i < pcis->n_B; i++) array_B[i] = array_N[idex[i]];
516b4319ba4SBarry Smith     } else { /* ADD_VALUES */
5172fa5cd67SKarl Rupp       for (i = 0; i < pcis->n_B; i++) array_B[i] += array_N[idex[i]];
518b4319ba4SBarry Smith     }
519b4319ba4SBarry Smith   } else { /* SCATTER_REVERSE */
520b4319ba4SBarry Smith     if (imode == INSERT_VALUES) {
5212fa5cd67SKarl Rupp       for (i = 0; i < pcis->n_B; i++) array_N[idex[i]] = array_B[i];
522b4319ba4SBarry Smith     } else { /* ADD_VALUES */
5232fa5cd67SKarl Rupp       for (i = 0; i < pcis->n_B; i++) array_N[idex[i]] += array_B[i];
524b4319ba4SBarry Smith     }
525b4319ba4SBarry Smith   }
5269566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(pcis->is_B_local, &idex));
5279566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v_B, &array_B));
528b4319ba4SBarry Smith   PetscFunctionReturn(0);
529b4319ba4SBarry Smith }
530b4319ba4SBarry Smith 
531b4319ba4SBarry Smith /*
532b4319ba4SBarry Smith    PCISApplyInvSchur - Solves the Neumann problem related to applying the inverse of the Schur complement.
533b4319ba4SBarry Smith    More precisely, solves the problem:
534b4319ba4SBarry Smith                                         [ A_II  A_IB ] [ . ]   [ 0 ]
535b4319ba4SBarry Smith                                         [            ] [   ] = [   ]
536b4319ba4SBarry Smith                                         [ A_BI  A_BB ] [ x ]   [ b ]
537b4319ba4SBarry Smith 
538b4319ba4SBarry Smith    Input parameters:
539b4319ba4SBarry Smith .  pc - preconditioner context
540b4319ba4SBarry Smith .  b - vector of local interface nodes (including ghosts)
541b4319ba4SBarry Smith 
542b4319ba4SBarry Smith    Output parameters:
543b4319ba4SBarry Smith .  x - vector of local interface nodes (including ghosts); returns the application of the inverse of the Schur
544b4319ba4SBarry Smith        complement to b
545b4319ba4SBarry Smith .  vec1_N - vector of local nodes (interior and interface, including ghosts); returns garbage (used as work space)
546b4319ba4SBarry Smith .  vec2_N - vector of local nodes (interior and interface, including ghosts); returns garbage (used as work space)
547b4319ba4SBarry Smith 
548b4319ba4SBarry Smith */
5499371c9d4SSatish Balay PetscErrorCode PCISApplyInvSchur(PC pc, Vec b, Vec x, Vec vec1_N, Vec vec2_N) {
550b4319ba4SBarry Smith   PC_IS *pcis = (PC_IS *)(pc->data);
551b4319ba4SBarry Smith 
552b4319ba4SBarry Smith   PetscFunctionBegin;
553b4319ba4SBarry Smith   /*
554b4319ba4SBarry Smith     Neumann solvers.
555b4319ba4SBarry Smith     Applying the inverse of the local Schur complement, i.e, solving a Neumann
556b4319ba4SBarry Smith     Problem with zero at the interior nodes of the RHS and extracting the interface
557b4319ba4SBarry Smith     part of the solution. inverse Schur complement is applied to b and the result
558b4319ba4SBarry Smith     is stored in x.
559b4319ba4SBarry Smith   */
560b4319ba4SBarry Smith   /* Setting the RHS vec1_N */
5619566063dSJacob Faibussowitsch   PetscCall(VecSet(vec1_N, 0.0));
5629566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->N_to_B, b, vec1_N, INSERT_VALUES, SCATTER_REVERSE));
5639566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->N_to_B, b, vec1_N, INSERT_VALUES, SCATTER_REVERSE));
564b4319ba4SBarry Smith   /* Checking for consistency of the RHS */
565b4319ba4SBarry Smith   {
566ace3abfcSBarry Smith     PetscBool flg = PETSC_FALSE;
5679566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, NULL, "-pc_is_check_consistency", &flg, NULL));
568b4319ba4SBarry Smith     if (flg) {
569b4319ba4SBarry Smith       PetscScalar average;
5703050cee2SBarry Smith       PetscViewer viewer;
5719566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc), &viewer));
5723050cee2SBarry Smith 
5739566063dSJacob Faibussowitsch       PetscCall(VecSum(vec1_N, &average));
574b4319ba4SBarry Smith       average = average / ((PetscReal)pcis->n);
5759566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
576b4319ba4SBarry Smith       if (pcis->pure_neumann) {
57763a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Subdomain %04d is floating. Average = % 1.14e\n", PetscGlobalRank, (double)PetscAbsScalar(average)));
578b4319ba4SBarry Smith       } else {
57963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Subdomain %04d is fixed.    Average = % 1.14e\n", PetscGlobalRank, (double)PetscAbsScalar(average)));
580b4319ba4SBarry Smith       }
5819566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
5829566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
583b4319ba4SBarry Smith     }
584b4319ba4SBarry Smith   }
585b4319ba4SBarry Smith   /* Solving the system for vec2_N */
5869566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcis->ksp_N, vec1_N, vec2_N));
5879566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcis->ksp_N, pc, vec2_N));
588b4319ba4SBarry Smith   /* Extracting the local interface vector out of the solution */
5899566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->N_to_B, vec2_N, x, INSERT_VALUES, SCATTER_FORWARD));
5909566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->N_to_B, vec2_N, x, INSERT_VALUES, SCATTER_FORWARD));
591b4319ba4SBarry Smith   PetscFunctionReturn(0);
592b4319ba4SBarry Smith }
593