xref: /petsc/src/ksp/pc/impls/is/pcis.c (revision feefa0e191a340680bb02e1467a36facdcb0b150)
123ce1328SBarry Smith 
25e5bbd0aSStefano Zampini #include <petsc/private/pcisimpl.h> /*I "petscpc.h" I*/
3831a100dSStefano Zampini 
4d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCISSetUseStiffnessScaling_IS(PC pc, PetscBool use)
5d71ae5a4SJacob Faibussowitsch {
6b965d45eSStefano Zampini   PC_IS *pcis = (PC_IS *)pc->data;
7b965d45eSStefano Zampini 
8b965d45eSStefano Zampini   PetscFunctionBegin;
9b965d45eSStefano Zampini   pcis->use_stiffness_scaling = use;
103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
11b965d45eSStefano Zampini }
12b965d45eSStefano Zampini 
13b965d45eSStefano Zampini /*@
14f1580f4eSBarry Smith   PCISSetUseStiffnessScaling - Tells `PCIS` to construct partition of unity using
15f1580f4eSBarry Smith   the local matrices' diagonal entries
16b965d45eSStefano Zampini 
17f1580f4eSBarry Smith   Logically Collective
18b965d45eSStefano Zampini 
19b965d45eSStefano Zampini   Input Parameters:
20b965d45eSStefano Zampini + pc  - the preconditioning context
2120f4b53cSBarry Smith - use - whether or not it should use matrix diagonal to build partition of unity.
22b965d45eSStefano Zampini 
23b965d45eSStefano Zampini   Level: intermediate
24b965d45eSStefano Zampini 
25*feefa0e1SJacob Faibussowitsch   Developer Notes:
26f1580f4eSBarry Smith   There is no manual page for `PCIS` nor some of its methods
27b965d45eSStefano Zampini 
28f1580f4eSBarry Smith .seealso: `PCIS`, `PCBDDC`
29b965d45eSStefano Zampini @*/
30d71ae5a4SJacob Faibussowitsch PetscErrorCode PCISSetUseStiffnessScaling(PC pc, PetscBool use)
31d71ae5a4SJacob Faibussowitsch {
32b965d45eSStefano Zampini   PetscFunctionBegin;
33b965d45eSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
34064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveBool(pc, use, 2);
35cac4c232SBarry Smith   PetscTryMethod(pc, "PCISSetUseStiffnessScaling_C", (PC, PetscBool), (pc, use));
363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37b965d45eSStefano Zampini }
38b965d45eSStefano Zampini 
39d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCISSetSubdomainDiagonalScaling_IS(PC pc, Vec scaling_factors)
40d71ae5a4SJacob Faibussowitsch {
41ba1573a8SStefano Zampini   PC_IS *pcis = (PC_IS *)pc->data;
42ba1573a8SStefano Zampini 
43ba1573a8SStefano Zampini   PetscFunctionBegin;
449566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)scaling_factors));
459566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->D));
46ba1573a8SStefano Zampini   pcis->D = scaling_factors;
47a007db60SStefano Zampini   if (pc->setupcalled) {
48a007db60SStefano Zampini     PetscInt sn;
49a007db60SStefano Zampini 
509566063dSJacob Faibussowitsch     PetscCall(VecGetSize(pcis->D, &sn));
51a007db60SStefano Zampini     if (sn == pcis->n) {
529566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->D, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
539566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->D, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
549566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&pcis->D));
559566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(pcis->vec1_B, &pcis->D));
569566063dSJacob Faibussowitsch       PetscCall(VecCopy(pcis->vec1_B, pcis->D));
5763a3b9bcSJacob 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);
58a007db60SStefano Zampini   }
593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
60ba1573a8SStefano Zampini }
61ba1573a8SStefano Zampini 
62ba1573a8SStefano Zampini /*@
63f1580f4eSBarry Smith   PCISSetSubdomainDiagonalScaling - Set diagonal scaling for `PCIS`.
64ba1573a8SStefano Zampini 
65f1580f4eSBarry Smith   Logically Collective
66ba1573a8SStefano Zampini 
67ba1573a8SStefano Zampini   Input Parameters:
68ba1573a8SStefano Zampini + pc              - the preconditioning context
69ba1573a8SStefano Zampini - scaling_factors - scaling factors for the subdomain
70ba1573a8SStefano Zampini 
71ba1573a8SStefano Zampini   Level: intermediate
72ba1573a8SStefano Zampini 
73f1580f4eSBarry Smith   Note:
74f1580f4eSBarry Smith   Intended for use with jumping coefficients cases.
75ba1573a8SStefano Zampini 
76*feefa0e1SJacob Faibussowitsch   Developer Notes:
77f1580f4eSBarry Smith   There is no manual page for `PCIS` nor some of its methods
78f1580f4eSBarry Smith 
79f1580f4eSBarry Smith .seealso: `PCIS`, `PCBDDC`
80ba1573a8SStefano Zampini @*/
81d71ae5a4SJacob Faibussowitsch PetscErrorCode PCISSetSubdomainDiagonalScaling(PC pc, Vec scaling_factors)
82d71ae5a4SJacob Faibussowitsch {
83ba1573a8SStefano Zampini   PetscFunctionBegin;
84ba1573a8SStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
85a007db60SStefano Zampini   PetscValidHeaderSpecific(scaling_factors, VEC_CLASSID, 2);
86cac4c232SBarry Smith   PetscTryMethod(pc, "PCISSetSubdomainDiagonalScaling_C", (PC, Vec), (pc, scaling_factors));
873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
88ba1573a8SStefano Zampini }
89ba1573a8SStefano Zampini 
90d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCISSetSubdomainScalingFactor_IS(PC pc, PetscScalar scal)
91d71ae5a4SJacob Faibussowitsch {
92831a100dSStefano Zampini   PC_IS *pcis = (PC_IS *)pc->data;
93831a100dSStefano Zampini 
94831a100dSStefano Zampini   PetscFunctionBegin;
95831a100dSStefano Zampini   pcis->scaling_factor = scal;
9648a46eb9SPierre Jolivet   if (pcis->D) PetscCall(VecSet(pcis->D, pcis->scaling_factor));
973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
98831a100dSStefano Zampini }
99831a100dSStefano Zampini 
100831a100dSStefano Zampini /*@
101f1580f4eSBarry Smith   PCISSetSubdomainScalingFactor - Set scaling factor for `PCIS`.
102831a100dSStefano Zampini 
10320f4b53cSBarry Smith   Not Collective
104831a100dSStefano Zampini 
105831a100dSStefano Zampini   Input Parameters:
106831a100dSStefano Zampini + pc   - the preconditioning context
107831a100dSStefano Zampini - scal - scaling factor for the subdomain
108831a100dSStefano Zampini 
109831a100dSStefano Zampini   Level: intermediate
110831a100dSStefano Zampini 
111f1580f4eSBarry Smith   Note:
112f1580f4eSBarry Smith   Intended for use with the jumping coefficients cases.
113831a100dSStefano Zampini 
114*feefa0e1SJacob Faibussowitsch   Developer Notes:
115f1580f4eSBarry Smith   There is no manual page for `PCIS` nor some of its methods
116f1580f4eSBarry Smith 
117f1580f4eSBarry Smith .seealso: `PCIS`, `PCBDDC`
118831a100dSStefano Zampini @*/
119d71ae5a4SJacob Faibussowitsch PetscErrorCode PCISSetSubdomainScalingFactor(PC pc, PetscScalar scal)
120d71ae5a4SJacob Faibussowitsch {
121831a100dSStefano Zampini   PetscFunctionBegin;
122831a100dSStefano Zampini   PetscValidHeaderSpecific(pc, PC_CLASSID, 1);
123cac4c232SBarry Smith   PetscTryMethod(pc, "PCISSetSubdomainScalingFactor_C", (PC, PetscScalar), (pc, scal));
1243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
125831a100dSStefano Zampini }
126831a100dSStefano Zampini 
127d71ae5a4SJacob Faibussowitsch PetscErrorCode PCISSetUp(PC pc, PetscBool computematrices, PetscBool computesolvers)
128d71ae5a4SJacob Faibussowitsch {
129b4319ba4SBarry Smith   PC_IS    *pcis = (PC_IS *)(pc->data);
130bf327c11SStefano Zampini   Mat_IS   *matis;
1315e8657edSStefano Zampini   MatReuse  reuse;
13285c21eb1SStefano Zampini   PetscBool flg, issbaij;
133b4319ba4SBarry Smith 
134b4319ba4SBarry Smith   PetscFunctionBegin;
1359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATIS, &flg));
13628b400f6SJacob Faibussowitsch   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Requires preconditioning matrix of type MATIS");
13785c21eb1SStefano Zampini   matis = (Mat_IS *)pc->pmat->data;
1382f37b69bSStefano Zampini   if (pc->useAmat) {
1399566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)pc->mat, MATIS, &flg));
14028b400f6SJacob Faibussowitsch     PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_ARG_WRONG, "Requires linear system matrix of type MATIS");
1412f37b69bSStefano Zampini   }
142b4319ba4SBarry Smith 
1435e8657edSStefano Zampini   /* first time creation, get info on substructuring */
1445e8657edSStefano Zampini   if (!pc->setupcalled) {
1455e8657edSStefano Zampini     PetscInt  n_I;
1465e8657edSStefano Zampini     PetscInt *idx_I_local, *idx_B_local, *idx_I_global, *idx_B_global;
1476f516dd7SStefano Zampini     PetscBT   bt;
1485e8657edSStefano Zampini     PetscInt  i, j;
149b4319ba4SBarry Smith 
150892d8026SStefano Zampini     /* get info on mapping */
1519566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)matis->rmapping));
1529566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingDestroy(&pcis->mapping));
153e432b41dSStefano Zampini     pcis->mapping = matis->rmapping;
1549566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetSize(pcis->mapping, &pcis->n));
1559566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetInfo(pcis->mapping, &(pcis->n_neigh), &(pcis->neigh), &(pcis->n_shared), &(pcis->shared)));
156892d8026SStefano Zampini 
157b4319ba4SBarry Smith     /* Identifying interior and interface nodes, in local numbering */
1589566063dSJacob Faibussowitsch     PetscCall(PetscBTCreate(pcis->n, &bt));
1594843afd6SStefano Zampini     for (i = 0; i < pcis->n_neigh; i++)
16048a46eb9SPierre Jolivet       for (j = 0; j < pcis->n_shared[i]; j++) PetscCall(PetscBTSet(bt, pcis->shared[i][j]));
161892d8026SStefano Zampini 
162da81f932SPierre Jolivet     /* Creating local and global index sets for interior and interface nodes. */
1639566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n, &idx_I_local));
1649566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n, &idx_B_local));
165b4319ba4SBarry Smith     for (i = 0, pcis->n_B = 0, n_I = 0; i < pcis->n; i++) {
1666f516dd7SStefano Zampini       if (!PetscBTLookup(bt, i)) {
1672fa5cd67SKarl Rupp         idx_I_local[n_I] = i;
1682fa5cd67SKarl Rupp         n_I++;
1692fa5cd67SKarl Rupp       } else {
1702fa5cd67SKarl Rupp         idx_B_local[pcis->n_B] = i;
1712fa5cd67SKarl Rupp         pcis->n_B++;
1722fa5cd67SKarl Rupp       }
173b4319ba4SBarry Smith     }
1746f516dd7SStefano Zampini 
175b4319ba4SBarry Smith     /* Getting the global numbering */
176b4319ba4SBarry Smith     idx_B_global = idx_I_local + n_I; /* Just avoiding allocating extra memory, since we have vacant space */
177b4319ba4SBarry Smith     idx_I_global = idx_B_local + pcis->n_B;
1789566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(pcis->mapping, pcis->n_B, idx_B_local, idx_B_global));
1799566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingApply(pcis->mapping, n_I, idx_I_local, idx_I_global));
1802fa5cd67SKarl Rupp 
1815e8657edSStefano Zampini     /* Creating the index sets */
1829566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pcis->n_B, idx_B_local, PETSC_COPY_VALUES, &pcis->is_B_local));
1839566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), pcis->n_B, idx_B_global, PETSC_COPY_VALUES, &pcis->is_B_global));
1849566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n_I, idx_I_local, PETSC_COPY_VALUES, &pcis->is_I_local));
1859566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)pc), n_I, idx_I_global, PETSC_COPY_VALUES, &pcis->is_I_global));
1862fa5cd67SKarl Rupp 
1875e8657edSStefano Zampini     /* Freeing memory */
1889566063dSJacob Faibussowitsch     PetscCall(PetscFree(idx_B_local));
1899566063dSJacob Faibussowitsch     PetscCall(PetscFree(idx_I_local));
1909566063dSJacob Faibussowitsch     PetscCall(PetscBTDestroy(&bt));
191b4319ba4SBarry Smith 
1925e8657edSStefano Zampini     /* Creating work vectors and arrays */
1939566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(matis->x, &pcis->vec1_N));
1949566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_N, &pcis->vec2_N));
1959566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &pcis->vec1_D));
1969566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(pcis->vec1_D, pcis->n - pcis->n_B, PETSC_DECIDE));
1979566063dSJacob Faibussowitsch     PetscCall(VecSetType(pcis->vec1_D, ((PetscObject)pcis->vec1_N)->type_name));
1989566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_D, &pcis->vec2_D));
1999566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_D, &pcis->vec3_D));
2009566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_D, &pcis->vec4_D));
2019566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &pcis->vec1_B));
2029566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(pcis->vec1_B, pcis->n_B, PETSC_DECIDE));
2039566063dSJacob Faibussowitsch     PetscCall(VecSetType(pcis->vec1_B, ((PetscObject)pcis->vec1_N)->type_name));
2049566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_B, &pcis->vec2_B));
2059566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(pcis->vec1_B, &pcis->vec3_B));
2069566063dSJacob Faibussowitsch     PetscCall(MatCreateVecs(pc->pmat, &pcis->vec1_global, NULL));
2079566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(pcis->n, &pcis->work_N));
2085e8657edSStefano Zampini     /* scaling vector */
209bf83c2afSStefano Zampini     if (!pcis->D) { /* it can happen that the user passed in a scaling vector via PCISSetSubdomainDiagonalScaling */
2109566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(pcis->vec1_B, &pcis->D));
2119566063dSJacob Faibussowitsch       PetscCall(VecSet(pcis->D, pcis->scaling_factor));
212bf83c2afSStefano Zampini     }
213b4319ba4SBarry Smith 
214b4319ba4SBarry Smith     /* Creating the scatter contexts */
2159566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(pcis->vec1_N, pcis->is_I_local, pcis->vec1_D, (IS)0, &pcis->N_to_D));
2169566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(pcis->vec1_global, pcis->is_I_global, pcis->vec1_D, (IS)0, &pcis->global_to_D));
2179566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(pcis->vec1_N, pcis->is_B_local, pcis->vec1_B, (IS)0, &pcis->N_to_B));
2189566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(pcis->vec1_global, pcis->is_B_global, pcis->vec1_B, (IS)0, &pcis->global_to_B));
219b4319ba4SBarry Smith 
2205e8657edSStefano Zampini     /* map from boundary to local */
2219566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingCreateIS(pcis->is_B_local, &pcis->BtoNmap));
2225e8657edSStefano Zampini   }
2235e8657edSStefano Zampini 
224a007db60SStefano Zampini   {
225a007db60SStefano Zampini     PetscInt sn;
226a007db60SStefano Zampini 
2279566063dSJacob Faibussowitsch     PetscCall(VecGetSize(pcis->D, &sn));
228a007db60SStefano Zampini     if (sn == pcis->n) {
2299566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->D, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
2309566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->D, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
2319566063dSJacob Faibussowitsch       PetscCall(VecDestroy(&pcis->D));
2329566063dSJacob Faibussowitsch       PetscCall(VecDuplicate(pcis->vec1_B, &pcis->D));
2339566063dSJacob Faibussowitsch       PetscCall(VecCopy(pcis->vec1_B, pcis->D));
23463a3b9bcSJacob 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);
235a007db60SStefano Zampini   }
236a007db60SStefano Zampini 
2375e8657edSStefano Zampini   /*
2385e8657edSStefano Zampini     Extracting the blocks A_II, A_BI, A_IB and A_BB from A. If the numbering
2395e8657edSStefano Zampini     is such that interior nodes come first than the interface ones, we have
2405e8657edSStefano Zampini 
2415e8657edSStefano Zampini         [ A_II | A_IB ]
2425e8657edSStefano Zampini     A = [------+------]
2435e8657edSStefano Zampini         [ A_BI | A_BB ]
2445e8657edSStefano Zampini   */
245d9869140SStefano Zampini   if (computematrices) {
2462f37b69bSStefano Zampini     PetscBool amat = (PetscBool)(pc->mat != pc->pmat && pc->useAmat);
2472f37b69bSStefano Zampini     PetscInt  bs, ibs;
2482f37b69bSStefano Zampini 
2495e8657edSStefano Zampini     reuse = MAT_INITIAL_MATRIX;
2503975b054SStefano Zampini     if (pcis->reusesubmatrices && pc->setupcalled) {
2515e8657edSStefano Zampini       if (pc->flag == SAME_NONZERO_PATTERN) {
2525e8657edSStefano Zampini         reuse = MAT_REUSE_MATRIX;
2535e8657edSStefano Zampini       } else {
2545e8657edSStefano Zampini         reuse = MAT_INITIAL_MATRIX;
2555e8657edSStefano Zampini       }
2565e8657edSStefano Zampini     }
2575e8657edSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
2589566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcis->A_II));
2599566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcis->pA_II));
2609566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcis->A_IB));
2619566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcis->A_BI));
2629566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcis->A_BB));
2635e8657edSStefano Zampini     }
2645e8657edSStefano Zampini 
2659566063dSJacob Faibussowitsch     PetscCall(ISLocalToGlobalMappingGetBlockSize(pcis->mapping, &ibs));
2669566063dSJacob Faibussowitsch     PetscCall(MatGetBlockSize(matis->A, &bs));
2679566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(matis->A, pcis->is_I_local, pcis->is_I_local, reuse, &pcis->pA_II));
2682f37b69bSStefano Zampini     if (amat) {
2692f37b69bSStefano Zampini       Mat_IS *amatis = (Mat_IS *)pc->mat->data;
2709566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(amatis->A, pcis->is_I_local, pcis->is_I_local, reuse, &pcis->A_II));
2712f37b69bSStefano Zampini     } else {
2729566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference((PetscObject)pcis->pA_II));
2739566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&pcis->A_II));
2742f37b69bSStefano Zampini       pcis->A_II = pcis->pA_II;
2752f37b69bSStefano Zampini     }
2769566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(pcis->A_II, bs == ibs ? bs : 1));
2779566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(pcis->pA_II, bs == ibs ? bs : 1));
2789566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrix(matis->A, pcis->is_B_local, pcis->is_B_local, reuse, &pcis->A_BB));
2799566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompare((PetscObject)matis->A, MATSEQSBAIJ, &issbaij));
2805e8657edSStefano Zampini     if (!issbaij) {
2819566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(matis->A, pcis->is_I_local, pcis->is_B_local, reuse, &pcis->A_IB));
2829566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(matis->A, pcis->is_B_local, pcis->is_I_local, reuse, &pcis->A_BI));
2835e8657edSStefano Zampini     } else {
2845e8657edSStefano Zampini       Mat newmat;
285d9869140SStefano Zampini 
2869566063dSJacob Faibussowitsch       PetscCall(MatConvert(matis->A, MATSEQBAIJ, MAT_INITIAL_MATRIX, &newmat));
2879566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(newmat, pcis->is_I_local, pcis->is_B_local, reuse, &pcis->A_IB));
2889566063dSJacob Faibussowitsch       PetscCall(MatCreateSubMatrix(newmat, pcis->is_B_local, pcis->is_I_local, reuse, &pcis->A_BI));
2899566063dSJacob Faibussowitsch       PetscCall(MatDestroy(&newmat));
2905e8657edSStefano Zampini     }
2919566063dSJacob Faibussowitsch     PetscCall(MatSetBlockSize(pcis->A_BB, bs == ibs ? bs : 1));
292d9869140SStefano Zampini   }
2935e8657edSStefano Zampini 
294bf83c2afSStefano Zampini   /* Creating scaling vector D */
2959566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)pc)->options, ((PetscObject)pc)->prefix, "-pc_is_use_stiffness_scaling", &pcis->use_stiffness_scaling, NULL));
296bf83c2afSStefano Zampini   if (pcis->use_stiffness_scaling) {
29715f235b8SStefano Zampini     PetscScalar *a;
29815f235b8SStefano Zampini     PetscInt     i, n;
29915f235b8SStefano Zampini 
300d9869140SStefano Zampini     if (pcis->A_BB) {
3019566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(pcis->A_BB, pcis->D));
302d9869140SStefano Zampini     } else {
3039566063dSJacob Faibussowitsch       PetscCall(MatGetDiagonal(matis->A, pcis->vec1_N));
3049566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(pcis->N_to_B, pcis->vec1_N, pcis->D, INSERT_VALUES, SCATTER_FORWARD));
3059566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(pcis->N_to_B, pcis->vec1_N, pcis->D, INSERT_VALUES, SCATTER_FORWARD));
306d9869140SStefano Zampini     }
3079566063dSJacob Faibussowitsch     PetscCall(VecAbs(pcis->D));
3089566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(pcis->D, &n));
3099566063dSJacob Faibussowitsch     PetscCall(VecGetArray(pcis->D, &a));
3109371c9d4SSatish Balay     for (i = 0; i < n; i++)
3119371c9d4SSatish Balay       if (PetscAbsScalar(a[i]) < PETSC_SMALL) a[i] = 1.0;
3129566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(pcis->D, &a));
313ba1573a8SStefano Zampini   }
3149566063dSJacob Faibussowitsch   PetscCall(VecSet(pcis->vec1_global, 0.0));
3159566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, pcis->D, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE));
3169566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, pcis->D, pcis->vec1_global, ADD_VALUES, SCATTER_REVERSE));
3179566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->global_to_B, pcis->vec1_global, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
3189566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->global_to_B, pcis->vec1_global, pcis->vec1_B, INSERT_VALUES, SCATTER_FORWARD));
3199566063dSJacob Faibussowitsch   PetscCall(VecPointwiseDivide(pcis->D, pcis->D, pcis->vec1_B));
320b4319ba4SBarry Smith   /* See historical note 01, at the bottom of this file. */
321b4319ba4SBarry Smith 
3225e8657edSStefano Zampini   /* Creating the KSP contexts for the local Dirichlet and Neumann problems */
3235e8657edSStefano Zampini   if (computesolvers) {
324b4319ba4SBarry Smith     PC pc_ctx;
3255e8657edSStefano Zampini 
3265e8657edSStefano Zampini     pcis->pure_neumann = matis->pure_neumann;
327b4319ba4SBarry Smith     /* Dirichlet */
3289566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PETSC_COMM_SELF, &pcis->ksp_D));
3299566063dSJacob Faibussowitsch     PetscCall(KSPSetErrorIfNotConverged(pcis->ksp_D, pc->erroriffailure));
3309566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcis->ksp_D, (PetscObject)pc, 1));
3319566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(pcis->ksp_D, pcis->A_II, pcis->A_II));
3329566063dSJacob Faibussowitsch     PetscCall(KSPSetOptionsPrefix(pcis->ksp_D, "is_localD_"));
3339566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(pcis->ksp_D, &pc_ctx));
3349566063dSJacob Faibussowitsch     PetscCall(PCSetType(pc_ctx, PCLU));
3359566063dSJacob Faibussowitsch     PetscCall(KSPSetType(pcis->ksp_D, KSPPREONLY));
3369566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(pcis->ksp_D));
337b4319ba4SBarry Smith     /* the vectors in the following line are dummy arguments, just telling the KSP the vector size. Values are not used */
3389566063dSJacob Faibussowitsch     PetscCall(KSPSetUp(pcis->ksp_D));
339b4319ba4SBarry Smith     /* Neumann */
3409566063dSJacob Faibussowitsch     PetscCall(KSPCreate(PETSC_COMM_SELF, &pcis->ksp_N));
3419566063dSJacob Faibussowitsch     PetscCall(KSPSetErrorIfNotConverged(pcis->ksp_N, pc->erroriffailure));
3429566063dSJacob Faibussowitsch     PetscCall(PetscObjectIncrementTabLevel((PetscObject)pcis->ksp_N, (PetscObject)pc, 1));
3439566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(pcis->ksp_N, matis->A, matis->A));
3449566063dSJacob Faibussowitsch     PetscCall(KSPSetOptionsPrefix(pcis->ksp_N, "is_localN_"));
3459566063dSJacob Faibussowitsch     PetscCall(KSPGetPC(pcis->ksp_N, &pc_ctx));
3469566063dSJacob Faibussowitsch     PetscCall(PCSetType(pc_ctx, PCLU));
3479566063dSJacob Faibussowitsch     PetscCall(KSPSetType(pcis->ksp_N, KSPPREONLY));
3489566063dSJacob Faibussowitsch     PetscCall(KSPSetFromOptions(pcis->ksp_N));
349b4319ba4SBarry Smith     {
3509371c9d4SSatish 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;
3519371c9d4SSatish Balay       PetscReal fixed_factor, floating_factor;
352b4319ba4SBarry Smith 
3539566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetReal(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_damp_fixed", &fixed_factor, &damp_fixed));
3542fa5cd67SKarl Rupp       if (!damp_fixed) fixed_factor = 0.0;
3559566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_damp_fixed", &damp_fixed, NULL));
356b4319ba4SBarry Smith 
3579566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_remove_nullspace_fixed", &remove_nullspace_fixed, NULL));
358b4319ba4SBarry Smith 
359d0609cedSBarry Smith       PetscCall(PetscOptionsGetReal(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_set_damping_factor_floating", &floating_factor, &set_damping_factor_floating));
3602fa5cd67SKarl Rupp       if (!set_damping_factor_floating) floating_factor = 0.0;
3619566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_set_damping_factor_floating", &set_damping_factor_floating, NULL));
3622fa5cd67SKarl Rupp       if (!set_damping_factor_floating) floating_factor = 1.e-12;
363b4319ba4SBarry Smith 
3649566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_not_damp_floating", &not_damp_floating, NULL));
365b4319ba4SBarry Smith 
3669566063dSJacob Faibussowitsch       PetscCall(PetscOptionsGetBool(((PetscObject)pc_ctx)->options, ((PetscObject)pc_ctx)->prefix, "-pc_is_not_remove_nullspace_floating", &not_remove_nullspace_floating, NULL));
367b4319ba4SBarry Smith 
368b4319ba4SBarry Smith       if (pcis->pure_neumann) { /* floating subdomain */
369b4319ba4SBarry Smith         if (!(not_damp_floating)) {
3709566063dSJacob Faibussowitsch           PetscCall(PCFactorSetShiftType(pc_ctx, MAT_SHIFT_NONZERO));
3719566063dSJacob Faibussowitsch           PetscCall(PCFactorSetShiftAmount(pc_ctx, floating_factor));
372b4319ba4SBarry Smith         }
373b4319ba4SBarry Smith         if (!(not_remove_nullspace_floating)) {
374b4319ba4SBarry Smith           MatNullSpace nullsp;
3759566063dSJacob Faibussowitsch           PetscCall(MatNullSpaceCreate(PETSC_COMM_SELF, PETSC_TRUE, 0, NULL, &nullsp));
3769566063dSJacob Faibussowitsch           PetscCall(MatSetNullSpace(matis->A, nullsp));
3779566063dSJacob Faibussowitsch           PetscCall(MatNullSpaceDestroy(&nullsp));
378b4319ba4SBarry Smith         }
379b4319ba4SBarry Smith       } else { /* fixed subdomain */
380b4319ba4SBarry Smith         if (damp_fixed) {
3819566063dSJacob Faibussowitsch           PetscCall(PCFactorSetShiftType(pc_ctx, MAT_SHIFT_NONZERO));
3829566063dSJacob Faibussowitsch           PetscCall(PCFactorSetShiftAmount(pc_ctx, floating_factor));
383b4319ba4SBarry Smith         }
384b4319ba4SBarry Smith         if (remove_nullspace_fixed) {
385b4319ba4SBarry Smith           MatNullSpace nullsp;
3869566063dSJacob Faibussowitsch           PetscCall(MatNullSpaceCreate(PETSC_COMM_SELF, PETSC_TRUE, 0, NULL, &nullsp));
3879566063dSJacob Faibussowitsch           PetscCall(MatSetNullSpace(matis->A, nullsp));
3889566063dSJacob Faibussowitsch           PetscCall(MatNullSpaceDestroy(&nullsp));
389b4319ba4SBarry Smith         }
390b4319ba4SBarry Smith       }
391b4319ba4SBarry Smith     }
392b4319ba4SBarry Smith     /* the vectors in the following line are dummy arguments, just telling the KSP the vector size. Values are not used */
3939566063dSJacob Faibussowitsch     PetscCall(KSPSetUp(pcis->ksp_N));
394b4319ba4SBarry Smith   }
3953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
396b4319ba4SBarry Smith }
397b4319ba4SBarry Smith 
398b4319ba4SBarry Smith /*
399b4319ba4SBarry Smith    PCISDestroy -
400b4319ba4SBarry Smith */
401d71ae5a4SJacob Faibussowitsch PetscErrorCode PCISDestroy(PC pc)
402d71ae5a4SJacob Faibussowitsch {
403747c8291SStefano Zampini   PC_IS *pcis;
404b4319ba4SBarry Smith 
405b4319ba4SBarry Smith   PetscFunctionBegin;
4063ba16761SJacob Faibussowitsch   if (!pc) PetscFunctionReturn(PETSC_SUCCESS);
407747c8291SStefano Zampini   pcis = (PC_IS *)(pc->data);
4089566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcis->is_B_local));
4099566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcis->is_I_local));
4109566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcis->is_B_global));
4119566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&pcis->is_I_global));
4129566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcis->A_II));
4139566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcis->pA_II));
4149566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcis->A_IB));
4159566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcis->A_BI));
4169566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&pcis->A_BB));
4179566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->D));
4189566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcis->ksp_N));
4199566063dSJacob Faibussowitsch   PetscCall(KSPDestroy(&pcis->ksp_D));
4209566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec1_N));
4219566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec2_N));
4229566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec1_D));
4239566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec2_D));
4249566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec3_D));
4259566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec4_D));
4269566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec1_B));
4279566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec2_B));
4289566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec3_B));
4299566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&pcis->vec1_global));
4309566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcis->global_to_D));
4319566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcis->N_to_B));
4329566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcis->N_to_D));
4339566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&pcis->global_to_B));
4349566063dSJacob Faibussowitsch   PetscCall(PetscFree(pcis->work_N));
43548a46eb9SPierre Jolivet   if (pcis->n_neigh > -1) PetscCall(ISLocalToGlobalMappingRestoreInfo(pcis->mapping, &(pcis->n_neigh), &(pcis->neigh), &(pcis->n_shared), &(pcis->shared)));
4369566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&pcis->mapping));
4379566063dSJacob Faibussowitsch   PetscCall(ISLocalToGlobalMappingDestroy(&pcis->BtoNmap));
4389566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCISSetUseStiffnessScaling_C", NULL));
4399566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCISSetSubdomainScalingFactor_C", NULL));
4409566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCISSetSubdomainDiagonalScaling_C", NULL));
4413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
442b4319ba4SBarry Smith }
443b4319ba4SBarry Smith 
444b4319ba4SBarry Smith /*
445b4319ba4SBarry Smith    PCISCreate -
446b4319ba4SBarry Smith */
447d71ae5a4SJacob Faibussowitsch PetscErrorCode PCISCreate(PC pc)
448d71ae5a4SJacob Faibussowitsch {
449b4319ba4SBarry Smith   PC_IS *pcis = (PC_IS *)(pc->data);
450b4319ba4SBarry Smith 
451b4319ba4SBarry Smith   PetscFunctionBegin;
452747c8291SStefano Zampini   if (!pcis) {
4534dfa11a4SJacob Faibussowitsch     PetscCall(PetscNew(&pcis));
454747c8291SStefano Zampini     pc->data = pcis;
455747c8291SStefano Zampini   }
4567dbfca69SStefano Zampini   pcis->n_neigh          = -1;
457831a100dSStefano Zampini   pcis->scaling_factor   = 1.0;
4583975b054SStefano Zampini   pcis->reusesubmatrices = PETSC_TRUE;
459831a100dSStefano Zampini   /* composing functions */
4609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCISSetUseStiffnessScaling_C", PCISSetUseStiffnessScaling_IS));
4619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCISSetSubdomainScalingFactor_C", PCISSetSubdomainScalingFactor_IS));
4629566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)pc, "PCISSetSubdomainDiagonalScaling_C", PCISSetSubdomainDiagonalScaling_IS));
4633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
464b4319ba4SBarry Smith }
465b4319ba4SBarry Smith 
466b4319ba4SBarry Smith /*
467b4319ba4SBarry Smith    PCISApplySchur -
468b4319ba4SBarry Smith 
469b4319ba4SBarry Smith    Input parameters:
470b4319ba4SBarry Smith .  pc - preconditioner context
471b4319ba4SBarry Smith .  v - vector to which the Schur complement is to be applied (it is NOT modified inside this function, UNLESS vec2_B is null)
472b4319ba4SBarry Smith 
473b4319ba4SBarry Smith    Output parameters:
474b4319ba4SBarry Smith .  vec1_B - result of Schur complement applied to chunk
475b4319ba4SBarry Smith .  vec2_B - garbage (used as work space), or null (and v is used as workspace)
476b4319ba4SBarry Smith .  vec1_D - garbage (used as work space)
477b4319ba4SBarry Smith .  vec2_D - garbage (used as work space)
478b4319ba4SBarry Smith 
479b4319ba4SBarry Smith */
480d71ae5a4SJacob Faibussowitsch PetscErrorCode PCISApplySchur(PC pc, Vec v, Vec vec1_B, Vec vec2_B, Vec vec1_D, Vec vec2_D)
481d71ae5a4SJacob Faibussowitsch {
482b4319ba4SBarry Smith   PC_IS *pcis = (PC_IS *)(pc->data);
483b4319ba4SBarry Smith 
484b4319ba4SBarry Smith   PetscFunctionBegin;
4852fa5cd67SKarl Rupp   if (!vec2_B) vec2_B = v;
486b4319ba4SBarry Smith 
4879566063dSJacob Faibussowitsch   PetscCall(MatMult(pcis->A_BB, v, vec1_B));
4889566063dSJacob Faibussowitsch   PetscCall(MatMult(pcis->A_IB, v, vec1_D));
4899566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcis->ksp_D, vec1_D, vec2_D));
4909566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcis->ksp_D, pc, vec2_D));
4919566063dSJacob Faibussowitsch   PetscCall(MatMult(pcis->A_BI, vec2_D, vec2_B));
4929566063dSJacob Faibussowitsch   PetscCall(VecAXPY(vec1_B, -1.0, vec2_B));
4933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
494b4319ba4SBarry Smith }
495b4319ba4SBarry Smith 
496b4319ba4SBarry Smith /*
497b4319ba4SBarry Smith   PCISScatterArrayNToVecB - Scatters interface node values from a big array (of all local nodes, interior or interface,
498b4319ba4SBarry Smith   including ghosts) into an interface vector, when in SCATTER_FORWARD mode, or vice-versa, when in SCATTER_REVERSE
499b4319ba4SBarry Smith   mode.
500b4319ba4SBarry Smith 
501*feefa0e1SJacob Faibussowitsch   Input Parameters:
502*feefa0e1SJacob Faibussowitsch + pc      - preconditioner context
503b4319ba4SBarry Smith . array_N - [when in SCATTER_FORWARD mode] Array to be scattered into the vector
504*feefa0e1SJacob Faibussowitsch - v_B     - [when in SCATTER_REVERSE mode] Vector to be scattered into the array
505b4319ba4SBarry Smith 
506*feefa0e1SJacob Faibussowitsch   Output Parameter:
507*feefa0e1SJacob Faibussowitsch + array_N - [when in SCATTER_REVERSE mode] Array to receive the scattered vector
508*feefa0e1SJacob Faibussowitsch - v_B     - [when in SCATTER_FORWARD mode] Vector to receive the scattered array
509b4319ba4SBarry Smith 
510f1580f4eSBarry Smith   Note:
511b4319ba4SBarry Smith   The entries in the array that do not correspond to interface nodes remain unaltered.
512b4319ba4SBarry Smith */
513d71ae5a4SJacob Faibussowitsch PetscErrorCode PCISScatterArrayNToVecB(PetscScalar *array_N, Vec v_B, InsertMode imode, ScatterMode smode, PC pc)
514d71ae5a4SJacob Faibussowitsch {
5155d0c19d7SBarry Smith   PetscInt        i;
5165d0c19d7SBarry Smith   const PetscInt *idex;
517b4319ba4SBarry Smith   PetscScalar    *array_B;
518b4319ba4SBarry Smith   PC_IS          *pcis = (PC_IS *)(pc->data);
519b4319ba4SBarry Smith 
520b4319ba4SBarry Smith   PetscFunctionBegin;
5219566063dSJacob Faibussowitsch   PetscCall(VecGetArray(v_B, &array_B));
5229566063dSJacob Faibussowitsch   PetscCall(ISGetIndices(pcis->is_B_local, &idex));
523b4319ba4SBarry Smith 
524b4319ba4SBarry Smith   if (smode == SCATTER_FORWARD) {
525b4319ba4SBarry Smith     if (imode == INSERT_VALUES) {
5262fa5cd67SKarl Rupp       for (i = 0; i < pcis->n_B; i++) array_B[i] = array_N[idex[i]];
527b4319ba4SBarry Smith     } else { /* ADD_VALUES */
5282fa5cd67SKarl Rupp       for (i = 0; i < pcis->n_B; i++) array_B[i] += array_N[idex[i]];
529b4319ba4SBarry Smith     }
530b4319ba4SBarry Smith   } else { /* SCATTER_REVERSE */
531b4319ba4SBarry Smith     if (imode == INSERT_VALUES) {
5322fa5cd67SKarl Rupp       for (i = 0; i < pcis->n_B; i++) array_N[idex[i]] = array_B[i];
533b4319ba4SBarry Smith     } else { /* ADD_VALUES */
5342fa5cd67SKarl Rupp       for (i = 0; i < pcis->n_B; i++) array_N[idex[i]] += array_B[i];
535b4319ba4SBarry Smith     }
536b4319ba4SBarry Smith   }
5379566063dSJacob Faibussowitsch   PetscCall(ISRestoreIndices(pcis->is_B_local, &idex));
5389566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(v_B, &array_B));
5393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
540b4319ba4SBarry Smith }
541b4319ba4SBarry Smith 
542b4319ba4SBarry Smith /*
543b4319ba4SBarry Smith    PCISApplyInvSchur - Solves the Neumann problem related to applying the inverse of the Schur complement.
544b4319ba4SBarry Smith    More precisely, solves the problem:
545b4319ba4SBarry Smith                                         [ A_II  A_IB ] [ . ]   [ 0 ]
546b4319ba4SBarry Smith                                         [            ] [   ] = [   ]
547b4319ba4SBarry Smith                                         [ A_BI  A_BB ] [ x ]   [ b ]
548b4319ba4SBarry Smith 
549b4319ba4SBarry Smith    Input parameters:
550b4319ba4SBarry Smith .  pc - preconditioner context
551b4319ba4SBarry Smith .  b - vector of local interface nodes (including ghosts)
552b4319ba4SBarry Smith 
553b4319ba4SBarry Smith    Output parameters:
554b4319ba4SBarry Smith .  x - vector of local interface nodes (including ghosts); returns the application of the inverse of the Schur
555b4319ba4SBarry Smith        complement to b
556b4319ba4SBarry Smith .  vec1_N - vector of local nodes (interior and interface, including ghosts); returns garbage (used as work space)
557b4319ba4SBarry Smith .  vec2_N - vector of local nodes (interior and interface, including ghosts); returns garbage (used as work space)
558b4319ba4SBarry Smith 
559b4319ba4SBarry Smith */
560d71ae5a4SJacob Faibussowitsch PetscErrorCode PCISApplyInvSchur(PC pc, Vec b, Vec x, Vec vec1_N, Vec vec2_N)
561d71ae5a4SJacob Faibussowitsch {
562b4319ba4SBarry Smith   PC_IS *pcis = (PC_IS *)(pc->data);
563b4319ba4SBarry Smith 
564b4319ba4SBarry Smith   PetscFunctionBegin;
565b4319ba4SBarry Smith   /*
566b4319ba4SBarry Smith     Neumann solvers.
567b4319ba4SBarry Smith     Applying the inverse of the local Schur complement, i.e, solving a Neumann
568b4319ba4SBarry Smith     Problem with zero at the interior nodes of the RHS and extracting the interface
569b4319ba4SBarry Smith     part of the solution. inverse Schur complement is applied to b and the result
570b4319ba4SBarry Smith     is stored in x.
571b4319ba4SBarry Smith   */
572b4319ba4SBarry Smith   /* Setting the RHS vec1_N */
5739566063dSJacob Faibussowitsch   PetscCall(VecSet(vec1_N, 0.0));
5749566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->N_to_B, b, vec1_N, INSERT_VALUES, SCATTER_REVERSE));
5759566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->N_to_B, b, vec1_N, INSERT_VALUES, SCATTER_REVERSE));
576b4319ba4SBarry Smith   /* Checking for consistency of the RHS */
577b4319ba4SBarry Smith   {
578ace3abfcSBarry Smith     PetscBool flg = PETSC_FALSE;
5799566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, NULL, "-pc_is_check_consistency", &flg, NULL));
580b4319ba4SBarry Smith     if (flg) {
581b4319ba4SBarry Smith       PetscScalar average;
5823050cee2SBarry Smith       PetscViewer viewer;
5839566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pc), &viewer));
5843050cee2SBarry Smith 
5859566063dSJacob Faibussowitsch       PetscCall(VecSum(vec1_N, &average));
586b4319ba4SBarry Smith       average = average / ((PetscReal)pcis->n);
5879566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPushSynchronized(viewer));
588b4319ba4SBarry Smith       if (pcis->pure_neumann) {
58963a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Subdomain %04d is floating. Average = % 1.14e\n", PetscGlobalRank, (double)PetscAbsScalar(average)));
590b4319ba4SBarry Smith       } else {
59163a3b9bcSJacob Faibussowitsch         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Subdomain %04d is fixed.    Average = % 1.14e\n", PetscGlobalRank, (double)PetscAbsScalar(average)));
592b4319ba4SBarry Smith       }
5939566063dSJacob Faibussowitsch       PetscCall(PetscViewerFlush(viewer));
5949566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPopSynchronized(viewer));
595b4319ba4SBarry Smith     }
596b4319ba4SBarry Smith   }
597b4319ba4SBarry Smith   /* Solving the system for vec2_N */
5989566063dSJacob Faibussowitsch   PetscCall(KSPSolve(pcis->ksp_N, vec1_N, vec2_N));
5999566063dSJacob Faibussowitsch   PetscCall(KSPCheckSolve(pcis->ksp_N, pc, vec2_N));
600b4319ba4SBarry Smith   /* Extracting the local interface vector out of the solution */
6019566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(pcis->N_to_B, vec2_N, x, INSERT_VALUES, SCATTER_FORWARD));
6029566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(pcis->N_to_B, vec2_N, x, INSERT_VALUES, SCATTER_FORWARD));
6033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
604b4319ba4SBarry Smith }
605