Actual source code: ex76.c

  1: #include <petscksp.h>
  2: #include <petsc/private/petscimpl.h>

  4: static char help[] = "Solves a linear system using PCHPDDM.\n\n";

  6: int main(int argc, char **args)
  7: {
  8:   Vec             b;            /* computed solution and RHS */
  9:   Mat             A, aux, X, B; /* linear system matrix */
 10:   KSP             ksp;          /* linear solver context */
 11:   PC              pc;
 12:   IS              is, sizes;
 13:   const PetscInt *idx;
 14:   PetscMPIInt     rank, size;
 15:   PetscInt        m, N = 1;
 16:   PetscLayout     map;
 17:   PetscViewer     viewer;
 18:   char            dir[PETSC_MAX_PATH_LEN], name[PETSC_MAX_PATH_LEN], type[256];
 19:   PetscBool3      share = PETSC_BOOL3_UNKNOWN;
 20:   PetscBool       flg, set, transpose = PETSC_FALSE, skip_set_from_options = PETSC_FALSE;

 22:   PetscFunctionBeginUser;
 23:   PetscCall(PetscInitialize(&argc, &args, NULL, help));
 24:   PetscCall(PetscLogDefaultBegin());
 25:   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
 26:   PetscCheck(size == 4, PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE, "This example requires 4 processes");
 27:   PetscCall(PetscOptionsGetInt(NULL, NULL, "-rhs", &N, NULL));
 28:   PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
 29:   PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
 30:   PetscCall(PetscStrncpy(dir, ".", sizeof(dir)));
 31:   PetscCall(PetscOptionsGetString(NULL, NULL, "-load_dir", dir, sizeof(dir), NULL));
 32:   /* loading matrices */
 33:   PetscCall(PetscSNPrintf(name, sizeof(name), "%s/sizes_%d.dat", dir, size));
 34:   PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, name, FILE_MODE_READ, &viewer));
 35:   PetscCall(ISCreate(PETSC_COMM_WORLD, &sizes));
 36:   PetscCall(ISLoad(sizes, viewer));
 37:   PetscCall(ISGetIndices(sizes, &idx));
 38:   PetscCall(MatSetSizes(A, idx[0], idx[1], idx[2], idx[3]));
 39:   PetscCall(MatCreate(PETSC_COMM_WORLD, &X));
 40:   PetscCall(MatSetSizes(X, idx[4], idx[4], PETSC_DETERMINE, PETSC_DETERMINE));
 41:   PetscCall(MatSetUp(X));
 42:   PetscCall(ISRestoreIndices(sizes, &idx));
 43:   PetscCall(ISDestroy(&sizes));
 44:   PetscCall(PetscViewerDestroy(&viewer));
 45:   PetscCall(PetscSNPrintf(name, sizeof(name), "%s/A.dat", dir));
 46:   PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, name, FILE_MODE_READ, &viewer));
 47:   PetscCall(MatLoad(A, viewer));
 48:   PetscCall(PetscViewerDestroy(&viewer));
 49:   PetscCall(PetscSNPrintf(name, sizeof(name), "%s/is_%d.dat", dir, size));
 50:   PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, name, FILE_MODE_READ, &viewer));
 51:   PetscCall(ISCreate(PETSC_COMM_WORLD, &sizes));
 52:   PetscCall(MatGetLayouts(X, &map, NULL));
 53:   PetscCall(ISSetLayout(sizes, map));
 54:   PetscCall(ISLoad(sizes, viewer));
 55:   PetscCall(ISGetLocalSize(sizes, &m));
 56:   PetscCall(ISGetIndices(sizes, &idx));
 57:   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, m, idx, PETSC_COPY_VALUES, &is));
 58:   PetscCall(ISRestoreIndices(sizes, &idx));
 59:   PetscCall(ISDestroy(&sizes));
 60:   PetscCall(MatGetBlockSize(A, &m));
 61:   PetscCall(ISSetBlockSize(is, m));
 62:   PetscCall(PetscViewerDestroy(&viewer));
 63:   PetscCall(PetscSNPrintf(name, sizeof(name), "%s/Neumann_%d.dat", dir, size));
 64:   PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, name, FILE_MODE_READ, &viewer));
 65:   PetscCall(MatLoad(X, viewer));
 66:   PetscCall(PetscViewerDestroy(&viewer));
 67:   PetscCall(MatGetDiagonalBlock(X, &B));
 68:   PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &aux));
 69:   PetscCall(MatDestroy(&X));
 70:   flg = PETSC_FALSE;
 71:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-sort", &flg, NULL));
 72:   if (flg) {
 73:     Mat B;
 74:     IS  perm;

 76:     PetscCall(ISSortPermutation(is, PETSC_FALSE, &perm));
 77:     PetscCall(ISSort(is));
 78:     PetscCall(MatPermute(aux, perm, perm, &B));
 79:     PetscCall(ISDestroy(&perm));
 80:     PetscCall(MatDestroy(&aux));
 81:     aux = B;
 82:     PetscCall(PetscOptionsGetBool(NULL, NULL, "-reset_is_block_size", &flg, NULL));
 83:     if (flg) {
 84:       PetscCall(ISSetBlockSize(is, 1));
 85:       flg = PETSC_FALSE;
 86:     }
 87:   }
 88:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-pc_hpddm_levels_1_st_share_sub_ksp", &flg, &set));
 89:   if (flg) { /* PETSc LU/Cholesky is struggling numerically for bs > 1          */
 90:              /* only set the proper bs for the geneo_share_* tests, 1 otherwise */
 91:     PetscCall(MatSetBlockSizesFromMats(aux, A, A));
 92:     share = PETSC_BOOL3_TRUE;
 93:   } else if (set) share = PETSC_BOOL3_FALSE;
 94:   PetscCall(MatSetOption(A, MAT_SYMMETRIC, PETSC_TRUE));
 95:   PetscCall(MatSetOption(aux, MAT_SYMMETRIC, PETSC_TRUE));
 96:   /* ready for testing */
 97:   PetscOptionsBegin(PETSC_COMM_WORLD, "", "", "");
 98:   PetscCall(PetscStrncpy(type, MATAIJ, sizeof(type)));
 99:   PetscCall(PetscOptionsFList("-mat_type", "Matrix type", "MatSetType", MatList, type, type, sizeof(type), &flg));
100:   PetscOptionsEnd();
101:   PetscCall(MatConvert(A, type, MAT_INPLACE_MATRIX, &A));
102:   PetscCall(MatConvert(aux, type, MAT_INPLACE_MATRIX, &aux));
103:   PetscCall(KSPCreate(PETSC_COMM_WORLD, &ksp));
104:   PetscCall(KSPSetOperators(ksp, A, A));
105:   PetscCall(KSPGetPC(ksp, &pc));
106:   PetscCall(PCSetType(pc, PCHPDDM));
107: #if PetscDefined(HAVE_HPDDM) && PetscDefined(HAVE_DYNAMIC_LIBRARIES) && PetscDefined(USE_SHARED_LIBRARIES)
108:   flg = PETSC_FALSE;
109:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-reset", &flg, NULL));
110:   if (flg) {
111:     PetscCall(PetscOptionsSetValue(NULL, "-pc_hpddm_block_splitting", "true"));
112:     PetscCall(PCSetFromOptions(pc));
113:     PetscCall(PCSetUp(pc));
114:     PetscCall(PetscOptionsClearValue(NULL, "-pc_hpddm_block_splitting"));
115:   }
116:   PetscCall(PCHPDDMSetAuxiliaryMat(pc, is, aux, NULL, NULL));
117:   PetscCall(PCHPDDMHasNeumannMat(pc, PETSC_FALSE)); /* PETSC_TRUE is fine as well, just testing */
118:   if (share == PETSC_BOOL3_UNKNOWN) PetscCall(PCHPDDMSetSTShareSubKSP(pc, PetscBool3ToBool(share)));
119:   flg = PETSC_FALSE;
120:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-set_rhs", &flg, NULL));
121:   if (flg) {          /* user-provided RHS for concurrent generalized eigenvalue problems                          */
122:     Mat      a, c, P; /* usually assembled automatically in PCHPDDM, this is solely for testing PCHPDDMSetRHSMat() */
123:     PetscInt rstart, rend, location;

125:     PetscCall(MatDuplicate(aux, MAT_DO_NOT_COPY_VALUES, &B)); /* duplicate so that MatStructure is SAME_NONZERO_PATTERN */
126:     PetscCall(MatGetDiagonalBlock(A, &a));
127:     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
128:     PetscCall(ISGetLocalSize(is, &m));
129:     PetscCall(MatCreateSeqAIJ(PETSC_COMM_SELF, rend - rstart, m, 1, NULL, &P));
130:     for (m = rstart; m < rend; ++m) {
131:       PetscCall(ISLocate(is, m, &location));
132:       PetscCheck(location >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "IS of the auxiliary Mat does not include all local rows of A");
133:       PetscCall(MatSetValue(P, m - rstart, location, 1.0, INSERT_VALUES));
134:     }
135:     PetscCall(MatAssemblyBegin(P, MAT_FINAL_ASSEMBLY));
136:     PetscCall(MatAssemblyEnd(P, MAT_FINAL_ASSEMBLY));
137:     PetscCall(PetscObjectTypeCompare((PetscObject)a, MATSEQAIJ, &flg));
138:     if (flg) PetscCall(MatPtAP(a, P, MAT_INITIAL_MATRIX, 1.0, &X)); // MatPtAP() is used to extend diagonal blocks with zeros on the overlap
139:     else {                                                          // workaround for MatPtAP() limitations with some types
140:       PetscCall(MatConvert(a, MATSEQAIJ, MAT_INITIAL_MATRIX, &c));
141:       PetscCall(MatPtAP(c, P, MAT_INITIAL_MATRIX, 1.0, &X));
142:       PetscCall(MatDestroy(&c));
143:     }
144:     PetscCall(MatDestroy(&P));
145:     PetscCall(MatAXPY(B, 1.0, X, SUBSET_NONZERO_PATTERN));
146:     PetscCall(MatDestroy(&X));
147:     PetscCall(MatSetOption(B, MAT_SYMMETRIC, PETSC_TRUE));
148:     PetscCall(PCHPDDMSetRHSMat(pc, B));
149:     PetscCall(MatDestroy(&B));
150:   }
151: #else
152:   (void)share;
153: #endif
154:   PetscCall(MatDestroy(&aux));
155:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-skip_set_from_options", &skip_set_from_options, NULL));
156:   if (!skip_set_from_options) PetscCall(KSPSetFromOptions(ksp));
157:   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCASM, &flg));
158:   if (flg) {
159:     flg = PETSC_FALSE;
160:     PetscCall(PetscOptionsGetBool(NULL, NULL, "-pc_hpddm_define_subdomains", &flg, NULL));
161:     if (flg) {
162:       IS rows;

164:       PetscCall(MatGetOwnershipIS(A, &rows, NULL));
165:       PetscCall(PCASMSetLocalSubdomains(pc, 1, &is, &rows));
166:       PetscCall(ISDestroy(&rows));
167:     }
168:   }
169:   PetscCall(ISDestroy(&is));
170:   PetscCall(MatCreateVecs(A, NULL, &b));
171:   PetscCall(VecSet(b, 1.0));
172:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-transpose", &transpose, NULL));
173:   if (!transpose) PetscCall(KSPSolve(ksp, b, b));
174:   else PetscCall(KSPSolveTranspose(ksp, b, b));
175:   PetscCall(VecGetLocalSize(b, &m));
176:   PetscCall(VecDestroy(&b));
177:   if (N > 1) {
178:     KSPType type;
179:     VecType vt;

181:     PetscCall(PetscOptionsClearValue(NULL, "-ksp_converged_reason"));
182:     PetscCall(KSPSetFromOptions(ksp));
183:     PetscCall(MatGetVecType(A, &vt));
184:     PetscCall(MatCreateDenseFromVecType(PETSC_COMM_WORLD, vt, m, PETSC_DECIDE, PETSC_DECIDE, N, PETSC_DECIDE, NULL, &B));
185:     PetscCall(MatCreateDenseFromVecType(PETSC_COMM_WORLD, vt, m, PETSC_DECIDE, PETSC_DECIDE, N, PETSC_DECIDE, NULL, &X));
186:     PetscCall(MatSetRandom(B, NULL));
187:     /* this is algorithmically optimal in the sense that blocks of vectors are coarsened or interpolated using matrix--matrix operations */
188:     /* PCHPDDM however heavily relies on MPI[S]BAIJ format for which there is no efficient MatProduct implementation */
189:     if (!transpose) PetscCall(KSPMatSolve(ksp, B, X));
190:     else PetscCall(KSPMatSolveTranspose(ksp, B, X));
191:     PetscCall(KSPGetType(ksp, &type));
192:     PetscCall(PetscStrcmp(type, KSPHPDDM, &flg));
193: #if PetscDefined(HAVE_HPDDM)
194:     if (flg) {
195:       PetscReal    norm;
196:       KSPHPDDMType type;

198:       PetscCall(KSPHPDDMGetType(ksp, &type));
199:       if (type == KSP_HPDDM_TYPE_PREONLY || type == KSP_HPDDM_TYPE_CG || type == KSP_HPDDM_TYPE_GMRES || type == KSP_HPDDM_TYPE_GCRODR) {
200:         Mat C;

202:         PetscCall(MatDuplicate(X, MAT_DO_NOT_COPY_VALUES, &C));
203:         PetscCall(KSPSetMatSolveBatchSize(ksp, 1));
204:         if (!transpose) PetscCall(KSPMatSolve(ksp, B, C));
205:         else PetscCall(KSPMatSolveTranspose(ksp, B, C));
206:         PetscCall(MatAYPX(C, -1.0, X, SAME_NONZERO_PATTERN));
207:         PetscCall(MatNorm(C, NORM_INFINITY, &norm));
208:         PetscCall(MatDestroy(&C));
209:         PetscCheck(norm <= 100 * PETSC_MACHINE_EPSILON, PetscObjectComm((PetscObject)pc), PETSC_ERR_PLIB, "KSPMatSolve%s() and KSPSolve%s() difference has nonzero norm %g with pseudo-block KSPHPDDMType %s", (transpose ? "Transpose" : ""), (transpose ? "Transpose" : ""), (double)norm, KSPHPDDMTypes[type]);
210:       }
211:     }
212: #endif
213:     PetscCall(MatDestroy(&X));
214:     PetscCall(MatDestroy(&B));
215:   }
216:   PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCHPDDM, &flg));
217: #if PetscDefined(HAVE_HPDDM) && PetscDefined(HAVE_DYNAMIC_LIBRARIES) && PetscDefined(USE_SHARED_LIBRARIES)
218:   if (flg) PetscCall(PCHPDDMGetSTShareSubKSP(pc, &flg));
219: #endif
220:   if (flg && PetscDefined(USE_LOG)) {
221:     PetscCall(PetscOptionsHasName(NULL, NULL, "-pc_hpddm_harmonic_overlap", &flg));
222:     if (!flg) {
223:       PetscLogEvent      event;
224:       PetscEventPerfInfo info1, info2;

226:       PetscCall(PetscLogEventRegister("MatLUFactorSym", PC_CLASSID, &event));
227:       PetscCall(PetscLogEventGetPerfInfo(PETSC_DETERMINE, event, &info1));
228:       PetscCall(PetscLogEventRegister("MatLUFactorNum", PC_CLASSID, &event));
229:       PetscCall(PetscLogEventGetPerfInfo(PETSC_DETERMINE, event, &info2));
230:       if (!info1.count && !info2.count) {
231:         PetscCall(PetscLogEventRegister("MatCholFctrSym", PC_CLASSID, &event));
232:         PetscCall(PetscLogEventGetPerfInfo(PETSC_DETERMINE, event, &info1));
233:         PetscCall(PetscLogEventRegister("MatCholFctrNum", PC_CLASSID, &event));
234:         PetscCall(PetscLogEventGetPerfInfo(PETSC_DETERMINE, event, &info2));
235:         PetscCheck(info2.count > info1.count, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cholesky numerical factorization (%d) not called more times than Cholesky symbolic factorization (%d), broken -pc_hpddm_levels_1_st_share_sub_ksp", info2.count, info1.count);
236:       } else PetscCheck(info2.count > info1.count, PETSC_COMM_SELF, PETSC_ERR_PLIB, "LU numerical factorization (%d) not called more times than LU symbolic factorization (%d), broken -pc_hpddm_levels_1_st_share_sub_ksp", info2.count, info1.count);
237:     }
238:   }
239: #if PetscDefined(HAVE_HPDDM) && PetscDefined(HAVE_DYNAMIC_LIBRARIES) && PetscDefined(USE_SHARED_LIBRARIES)
240:   if (N == 1) {
241:     flg = PETSC_FALSE;
242:     PetscCall(PetscOptionsGetBool(NULL, NULL, "-successive_solves", &flg, NULL));
243:     if (flg) {
244:       KSPConvergedReason reason[2];
245:       PetscInt           iterations[3];

247:       PetscCall(KSPGetConvergedReason(ksp, reason));
248:       PetscCall(KSPGetTotalIterations(ksp, iterations));
249:       if (!skip_set_from_options) PetscCall(PetscOptionsClearValue(NULL, "-ksp_converged_reason"));
250:       PetscCall(KSPSetFromOptions(ksp));
251:       flg = PETSC_FALSE;
252:       PetscCall(PetscOptionsGetBool(NULL, NULL, "-pc_hpddm_block_splitting", &flg, NULL));
253:       if (!flg) {
254:         PetscCall(PetscSNPrintf(name, sizeof(name), "%s/sizes_%d.dat", dir, size));
255:         PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, name, FILE_MODE_READ, &viewer));
256:         PetscCall(ISCreate(PETSC_COMM_WORLD, &sizes));
257:         PetscCall(ISLoad(sizes, viewer));
258:         PetscCall(ISGetIndices(sizes, &idx));
259:         PetscCall(MatCreate(PETSC_COMM_WORLD, &X));
260:         PetscCall(MatSetSizes(X, idx[4], idx[4], PETSC_DETERMINE, PETSC_DETERMINE));
261:         PetscCall(MatSetUp(X));
262:         PetscCall(ISRestoreIndices(sizes, &idx));
263:         PetscCall(ISDestroy(&sizes));
264:         PetscCall(PetscViewerDestroy(&viewer));
265:         PetscCall(PetscSNPrintf(name, sizeof(name), "%s/is_%d.dat", dir, size));
266:         PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, name, FILE_MODE_READ, &viewer));
267:         PetscCall(ISCreate(PETSC_COMM_WORLD, &sizes));
268:         PetscCall(MatGetLayouts(X, &map, NULL));
269:         PetscCall(ISSetLayout(sizes, map));
270:         PetscCall(ISLoad(sizes, viewer));
271:         PetscCall(ISGetLocalSize(sizes, &m));
272:         PetscCall(ISGetIndices(sizes, &idx));
273:         PetscCall(ISCreateGeneral(PETSC_COMM_SELF, m, idx, PETSC_COPY_VALUES, &is));
274:         PetscCall(ISRestoreIndices(sizes, &idx));
275:         PetscCall(ISDestroy(&sizes));
276:         PetscCall(MatGetBlockSize(A, &m));
277:         PetscCall(ISSetBlockSize(is, m));
278:         PetscCall(PetscViewerDestroy(&viewer));
279:         PetscCall(PetscSNPrintf(name, sizeof(name), "%s/Neumann_%d.dat", dir, size));
280:         PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, name, FILE_MODE_READ, &viewer));
281:         PetscCall(MatLoad(X, viewer));
282:         PetscCall(PetscViewerDestroy(&viewer));
283:         PetscCall(MatGetDiagonalBlock(X, &B));
284:         PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &aux));
285:         PetscCall(MatDestroy(&X));
286:         PetscCall(MatSetBlockSizesFromMats(aux, A, A));
287:         PetscCall(MatSetOption(aux, MAT_SYMMETRIC, PETSC_TRUE));
288:         PetscCall(MatConvert(aux, type, MAT_INPLACE_MATRIX, &aux));
289:       }
290:       PetscCall(MatCreateVecs(A, NULL, &b));
291:       PetscCall(PetscObjectStateIncrease((PetscObject)A));
292:       if (!flg) PetscCall(PCHPDDMSetAuxiliaryMat(pc, NULL, aux, NULL, NULL));
293:       PetscCall(VecSet(b, 1.0));
294:       if (!transpose) PetscCall(KSPSolve(ksp, b, b));
295:       else PetscCall(KSPSolveTranspose(ksp, b, b));
296:       PetscCall(KSPGetConvergedReason(ksp, reason + 1));
297:       PetscCall(KSPGetTotalIterations(ksp, iterations + 1));
298:       iterations[1] -= iterations[0];
299:       if (!skip_set_from_options) {
300:         PetscCheck(reason[0] == reason[1] && PetscAbs(iterations[0] - iterations[1]) <= 3, PetscObjectComm((PetscObject)ksp), PETSC_ERR_PLIB, "Successive calls to KSPSolve%s() did not converge for the same reason (%s v. %s) or with the same number of iterations (+/- 3, %" PetscInt_FMT " v. %" PetscInt_FMT ")", (transpose ? "Transpose" : ""), KSPConvergedReasons[reason[0]], KSPConvergedReasons[reason[1]], iterations[0], iterations[1]);
301:       } else {
302:         reason[0] = reason[1];
303:         PetscCall(PetscOptionsClearValue(NULL, "-ksp_converged_reason"));
304:         PetscCall(KSPSetFromOptions(ksp));
305:       }
306:       PetscCall(PetscObjectStateIncrease((PetscObject)A));
307:       if (!flg) PetscCall(PCHPDDMSetAuxiliaryMat(pc, is, aux, NULL, NULL));
308:       PetscCall(PCSetFromOptions(pc));
309:       PetscCall(VecSet(b, 1.0));
310:       if (!transpose) PetscCall(KSPSolve(ksp, b, b));
311:       else PetscCall(KSPSolveTranspose(ksp, b, b));
312:       PetscCall(KSPGetConvergedReason(ksp, reason + 1));
313:       PetscCall(KSPGetTotalIterations(ksp, iterations + 2));
314:       iterations[2] -= iterations[0] + iterations[1];
315:       if (skip_set_from_options) iterations[0] = iterations[1];
316:       PetscCheck(reason[0] == reason[1] && PetscAbs(iterations[0] - iterations[2]) <= 3, PetscObjectComm((PetscObject)ksp), PETSC_ERR_PLIB, "Successive calls to KSPSolve%s() did not converge for the same reason (%s v. %s) or with the same number of iterations (+/- 3, %" PetscInt_FMT " v. %" PetscInt_FMT ")", (transpose ? "Transpose" : ""), KSPConvergedReasons[reason[0]], KSPConvergedReasons[reason[1]], iterations[0], iterations[2]);
317:       PetscCall(VecDestroy(&b));
318:       PetscCall(ISDestroy(&is));
319:       PetscCall(MatDestroy(&aux));
320:     }
321:   }
322:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-viewer", &flg, NULL));
323:   if (flg) {
324:     PetscCall(PetscObjectTypeCompare((PetscObject)pc, PCHPDDM, &flg));
325:     if (flg) {
326:       PetscCall(PetscStrncpy(dir, "XXXXXX", sizeof(dir)));
327:       if (rank == 0) PetscCall(PetscMkdtemp(dir));
328:       PetscCallMPI(MPI_Bcast(dir, 6, MPI_CHAR, 0, PETSC_COMM_WORLD));
329:       for (PetscInt i = 0; i < 2; ++i) {
330:         PetscCall(PetscSNPrintf(name, sizeof(name), "%s/%s", dir, i == 0 ? "A" : "A.dat"));
331:         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_WORLD, name, &viewer));
332:         PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO_DETAIL));
333:         PetscCall(PCView(pc, viewer));
334:         PetscCall(PetscViewerPopFormat(viewer));
335:         PetscCall(PetscViewerDestroy(&viewer));
336:       }
337:       PetscCallMPI(MPI_Barrier(PETSC_COMM_WORLD));
338:       if (rank == 0) PetscCall(PetscRMTree(dir));
339:     }
340:   }
341: #endif
342:   PetscCall(KSPDestroy(&ksp));
343:   PetscCall(MatDestroy(&A));
344:   PetscCall(PetscFinalize());
345:   return 0;
346: }

348: /*TEST

350:    test:
351:       requires: hpddm slepc datafilespath double !complex !defined(PETSC_USE_64BIT_INDICES) defined(PETSC_HAVE_DYNAMIC_LIBRARIES) defined(PETSC_USE_SHARED_LIBRARIES)
352:       nsize: 4
353:       args: -ksp_rtol 1e-3 -ksp_converged_reason -pc_type {{bjacobi hpddm}shared output} -pc_hpddm_coarse_sub_pc_type lu -sub_pc_type lu -options_left no -load_dir ${DATAFILESPATH}/matrices/hpddm/GENEO

355:    testset:
356:       requires: hpddm slepc datafilespath double !complex !defined(PETSC_USE_64BIT_INDICES) defined(PETSC_HAVE_DYNAMIC_LIBRARIES) defined(PETSC_USE_SHARED_LIBRARIES)
357:       suffix: define_subdomains
358:       nsize: 4
359:       args: -ksp_rtol 1e-3 -ksp_converged_reason -pc_hpddm_define_subdomains -options_left no -load_dir ${DATAFILESPATH}/matrices/hpddm/GENEO
360:       test:
361:         args: -pc_type {{asm hpddm}shared output} -pc_hpddm_coarse_sub_pc_type lu -sub_pc_type lu -viewer
362:       test:
363:         args: -pc_type hpddm -pc_hpddm_levels_1_st_pc_type cholesky -pc_hpddm_levels_1_eps_nev 5 -pc_hpddm_coarse_sub_pc_type lu -pc_hpddm_levels_1_sub_pc_type lu -pc_hpddm_coarse_correction none

365:    testset:
366:       requires: hpddm slepc datafilespath double !complex !defined(PETSC_USE_64BIT_INDICES) defined(PETSC_HAVE_DYNAMIC_LIBRARIES) defined(PETSC_USE_SHARED_LIBRARIES)
367:       nsize: 4
368:       args: -ksp_converged_reason -pc_type hpddm -pc_hpddm_levels_1_sub_pc_type cholesky -pc_hpddm_coarse_pc_type redundant -load_dir ${DATAFILESPATH}/matrices/hpddm/GENEO
369:       test:
370:         suffix: geneo
371:         args: -pc_hpddm_coarse_p {{1 2}shared output} -pc_hpddm_levels_1_st_pc_type cholesky -pc_hpddm_levels_1_eps_nev {{5 15}separate output} -mat_type {{aij baij sbaij}shared output}
372:       test:
373:         suffix: geneo_block_splitting
374:         output_file: output/ex76_geneo_pc_hpddm_levels_1_eps_nev-15.out
375:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 1[5-9]/Linear solve converged due to CONVERGED_RTOL iterations 11/g"
376:         args: -pc_hpddm_coarse_p 2 -pc_hpddm_levels_1_eps_nev 15 -pc_hpddm_block_splitting -pc_hpddm_levels_1_st_pc_type lu -pc_hpddm_levels_1_eps_gen_non_hermitian -mat_type {{aij baij sbaij}shared output} -successive_solves -pc_hpddm_levels_1_st_pc_factor_mat_ordering_type rcm
377:       test:
378:         suffix: geneo_block_splitting_cholesky
379:         output_file: output/ex76_geneo_pc_hpddm_levels_1_eps_nev-15.out
380:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 29/Linear solve converged due to CONVERGED_RTOL iterations 11/g"
381:         args: -pc_hpddm_coarse_p 2 -pc_hpddm_levels_1_eps_nev 15 -pc_hpddm_block_splitting -pc_hpddm_levels_1_st_share_sub_ksp -pc_hpddm_levels_1_eps_gen_hermitian -mat_type sbaij -successive_solves -viewer_binary_skip_info
382:       test:
383:         suffix: geneo_share
384:         output_file: output/ex76_geneo_pc_hpddm_levels_1_eps_nev-5.out
385:         args: -pc_hpddm_levels_1_st_pc_type cholesky -pc_hpddm_levels_1_eps_nev 5 -pc_hpddm_levels_1_st_share_sub_ksp -reset {{false true}shared output}
386:       test:
387:         suffix: harmonic_overlap_1_define_false
388:         output_file: output/ex76_geneo_share.out
389:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 1[0-3]/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
390:         args: -pc_hpddm_harmonic_overlap 1 -pc_hpddm_levels_1_eps_nev 30 -pc_hpddm_levels_1_eps_threshold_relative 1e+1 -pc_hpddm_levels_1_st_pc_type cholesky -pc_hpddm_levels_1_eps_pc_type cholesky -pc_hpddm_define_subdomains false -pc_hpddm_levels_1_pc_type asm -pc_hpddm_levels_1_pc_asm_overlap 2 -mat_type {{baij sbaij}shared output}
391:       test:
392:         suffix: harmonic_overlap_1
393:         output_file: output/ex76_geneo_share.out
394:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 1[0-3]/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
395:         args: -pc_hpddm_harmonic_overlap 1 -pc_hpddm_levels_1_eps_nev 30 -pc_hpddm_levels_1_eps_threshold_relative 1e+1 -pc_hpddm_levels_1_st_pc_type lu -pc_hpddm_levels_1_eps_pc_type lu -mat_type baij
396:       test:
397:         requires: cuda
398:         suffix: harmonic_overlap_1_cuda
399:         output_file: output/ex76_geneo_share.out
400:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 1[0-3]/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
401:         args: -pc_hpddm_harmonic_overlap 1 -pc_hpddm_levels_1_eps_nev 30 -pc_hpddm_levels_1_eps_threshold_relative 1e+1 -pc_hpddm_levels_1_st_pc_type lu -pc_hpddm_levels_1_eps_pc_type lu -mat_type aijcusparse
402:       test:
403:         suffix: harmonic_overlap_1_share_petsc
404:         output_file: output/ex76_geneo_share.out
405:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 1[0-3]/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
406:         args: -pc_hpddm_harmonic_overlap 1 -pc_hpddm_levels_1_eps_nev 30 -pc_hpddm_levels_1_eps_threshold_relative 1e+1 -pc_hpddm_levels_1_st_pc_type lu -pc_hpddm_levels_1_st_share_sub_ksp -pc_hpddm_levels_1_sub_pc_factor_mat_solver_type petsc -pc_hpddm_levels_1_eps_pc_type lu -mat_type baij
407:       test:
408:         requires: mumps
409:         suffix: harmonic_overlap_1_share_mumps
410:         output_file: output/ex76_geneo_share.out
411:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 1[0-3]/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
412:         args: -pc_hpddm_harmonic_overlap 1 -pc_hpddm_levels_1_eps_nev 30 -pc_hpddm_levels_1_eps_threshold_relative 1e+1 -pc_hpddm_levels_1_st_share_sub_ksp -pc_hpddm_levels_1_sub_pc_factor_mat_solver_type mumps -pc_hpddm_coarse_pc_type cholesky -pc_hpddm_coarse_pc_factor_mat_solver_type mumps -pc_hpddm_coarse_mat_mumps_icntl_15 1
413:       test:
414:         requires: mumps
415:         suffix: harmonic_overlap_1_share_mumps_not_set_explicitly
416:         output_file: output/ex76_geneo_share.out
417:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 1[0-3]/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
418:         args: -pc_hpddm_harmonic_overlap 1 -pc_hpddm_levels_1_eps_nev 30 -pc_hpddm_levels_1_eps_threshold_relative 1e+1 -pc_hpddm_levels_1_st_share_sub_ksp -pc_hpddm_levels_1_eps_mat_type baij
419:       test:
420:         requires: mkl_pardiso
421:         suffix: harmonic_overlap_1_share_mkl_pardiso
422:         output_file: output/ex76_geneo_share.out
423:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations [12][0-3]/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
424:         args: -pc_hpddm_harmonic_overlap 1 -pc_hpddm_levels_1_eps_nev 30 -pc_hpddm_levels_1_eps_threshold_relative 1e+1 -pc_hpddm_levels_1_st_share_sub_ksp -pc_hpddm_levels_1_eps_mat_type shell -pc_hpddm_levels_1_sub_pc_factor_mat_solver_type mkl_pardiso
425:       test:
426:         requires: mkl_pardiso !mumps
427:         suffix: harmonic_overlap_1_share_mkl_pardiso_no_set_explicitly
428:         output_file: output/ex76_geneo_share.out
429:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations [12][0-3]/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
430:         args: -pc_hpddm_harmonic_overlap 1 -pc_hpddm_levels_1_eps_nev 30 -pc_hpddm_levels_1_eps_threshold_relative 1e+1 -pc_hpddm_levels_1_st_share_sub_ksp -pc_hpddm_levels_1_eps_mat_type shell
431:       test:
432:         suffix: harmonic_overlap_2_threshold_relative
433:         output_file: output/ex76_geneo_share.out
434:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 9/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
435:         args: -pc_hpddm_harmonic_overlap 2 -pc_hpddm_levels_1_svd_nsv 15 -pc_hpddm_levels_1_svd_threshold_relative 1e-1 -pc_hpddm_levels_1_st_share_sub_ksp -mat_type sbaij
436:       test:
437:         suffix: harmonic_overlap_2
438:         output_file: output/ex76_geneo_share.out
439:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 9/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
440:         args: -pc_hpddm_harmonic_overlap 2 -pc_hpddm_levels_1_svd_nsv 12 -pc_hpddm_levels_1_svd_type {{trlanczos randomized}shared output} -pc_hpddm_levels_1_st_share_sub_ksp -mat_type sbaij
441:       test:
442:         requires: cuda
443:         suffix: harmonic_overlap_2_cuda
444:         output_file: output/ex76_geneo_share.out
445:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 9/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
446:         args: -pc_hpddm_harmonic_overlap 2 -pc_hpddm_levels_1_svd_nsv 12 -pc_hpddm_levels_1_svd_type trlanczos -pc_hpddm_levels_1_st_share_sub_ksp -mat_type aijcusparse

448:    testset:
449:       requires: hpddm slepc datafilespath double !complex !defined(PETSC_USE_64BIT_INDICES) defined(PETSC_HAVE_DYNAMIC_LIBRARIES) defined(PETSC_USE_SHARED_LIBRARIES)
450:       nsize: 4
451:       args: -ksp_converged_reason -ksp_max_it 150 -pc_type hpddm -pc_hpddm_levels_1_eps_nev 5 -pc_hpddm_coarse_p 1 -load_dir ${DATAFILESPATH}/matrices/hpddm/GENEO -pc_hpddm_define_subdomains
452:       test:
453:         suffix: geneo_share_cholesky
454:         output_file: output/ex76_geneo_share.out
455:         # extra -pc_hpddm_levels_1_eps_gen_non_hermitian needed to avoid failures with PETSc Cholesky
456:         args: -pc_hpddm_levels_1_sub_pc_type cholesky -pc_hpddm_levels_1_st_pc_type cholesky -mat_type {{aij sbaij}shared output} -pc_hpddm_levels_1_eps_gen_non_hermitian -pc_hpddm_has_neumann -pc_hpddm_levels_1_st_share_sub_ksp {{false true}shared output} -successive_solves
457:       test:
458:         suffix: skip_set_from_options
459:         output_file: output/ex76_geneo_share.out
460:         args: -pc_hpddm_levels_1_sub_pc_type lu -pc_hpddm_has_neumann -pc_hpddm_levels_1_st_share_sub_ksp -successive_solves -skip_set_from_options
461:       test:
462:         suffix: geneo_share_cholesky_matstructure
463:         output_file: output/ex76_geneo_share.out
464:         # extra -pc_hpddm_levels_1_eps_gen_non_hermitian needed to avoid failures with PETSc Cholesky
465:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 14/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
466:         args: -pc_hpddm_levels_1_sub_pc_type cholesky -mat_type {{baij sbaij}shared output} -pc_hpddm_levels_1_eps_gen_non_hermitian -pc_hpddm_levels_1_st_share_sub_ksp -pc_hpddm_levels_1_st_matstructure same -set_rhs {{false true}shared output}
467:       test:
468:         suffix: geneo_transpose
469:         output_file: output/ex76_geneo_share.out
470:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 1[234]/Linear solve converged due to CONVERGED_RTOL iterations 15/g" -e "s/Linear solve converged due to CONVERGED_RTOL iterations 2[26]/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
471:         args: -pc_hpddm_levels_1_sub_pc_type cholesky -pc_hpddm_levels_1_st_pc_type cholesky -pc_hpddm_levels_1_eps_gen_non_hermitian -pc_hpddm_has_neumann -pc_hpddm_levels_1_st_share_sub_ksp -successive_solves -transpose -ksp_use_explicittranspose {{false true}shared output} -pc_hpddm_coarse_correction {{additive deflated balanced}shared output}
472:       test:
473:         TODO: broken # slightly different convergence rate, which may be a sign of something wrong somewhere
474:         requires: cuda
475:         suffix: geneo_transpose_cuda
476:         output_file: output/ex76_geneo_share.out
477:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 1[2-4]/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
478:         args: -pc_hpddm_levels_1_sub_pc_type cholesky -pc_hpddm_levels_1_st_pc_type cholesky -pc_hpddm_levels_1_eps_gen_non_hermitian -pc_hpddm_has_neumann -pc_hpddm_levels_1_st_share_sub_ksp -transpose -pc_hpddm_coarse_correction balanced -mat_type aijcusparse
479:       test:
480:         suffix: geneo_explicittranspose
481:         output_file: output/ex76_geneo_share.out
482:         filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 1[234]/Linear solve converged due to CONVERGED_RTOL iterations 15/g" -e "s/Linear solve converged due to CONVERGED_RTOL iterations 26/Linear solve converged due to CONVERGED_RTOL iterations 15/g"
483:         args: -pc_hpddm_levels_1_sub_pc_type cholesky -pc_hpddm_levels_1_st_pc_type cholesky -pc_hpddm_levels_1_eps_gen_non_hermitian -pc_hpddm_has_neumann -pc_hpddm_levels_1_st_share_sub_ksp -transpose -ksp_use_explicittranspose -rhs 2 -sort -reset_is_block_size {{false true}shared output}
484:       test:
485:         requires: mumps
486:         suffix: geneo_share_lu
487:         output_file: output/ex76_geneo_share.out
488:         # extra -pc_factor_mat_solver_type mumps needed to avoid failures with PETSc LU
489:         args: -pc_hpddm_levels_1_sub_pc_type lu -pc_hpddm_levels_1_st_pc_type lu -mat_type baij -pc_hpddm_levels_1_st_pc_factor_mat_solver_type mumps -pc_hpddm_levels_1_sub_pc_factor_mat_solver_type mumps -pc_hpddm_has_neumann -pc_hpddm_levels_1_st_share_sub_ksp {{false true}shared output} -pc_hpddm_coarse_pc_factor_mat_solver_type mumps -pc_hpddm_coarse_mat_mumps_icntl_15 1
490:       test:
491:         requires: mumps
492:         suffix: geneo_share_lu_matstructure
493:         output_file: output/ex76_geneo_share.out
494:         # extra -pc_factor_mat_solver_type mumps needed to avoid failures with PETSc LU
495:         args: -pc_hpddm_levels_1_sub_pc_type lu -mat_type aij -pc_hpddm_levels_1_sub_pc_factor_mat_solver_type mumps -pc_hpddm_levels_1_st_share_sub_ksp -pc_hpddm_levels_1_st_matstructure {{same different}shared output} -pc_hpddm_levels_1_st_pc_type lu -pc_hpddm_levels_1_st_pc_factor_mat_solver_type mumps -successive_solves -pc_hpddm_levels_1_eps_target 1e-5
496:       test:
497:         suffix: geneo_share_not_asm
498:         output_file: output/ex76_geneo_pc_hpddm_levels_1_eps_nev-5.out
499:         # extra -pc_hpddm_levels_1_eps_gen_non_hermitian needed to avoid failures with PETSc Cholesky
500:         args: -pc_hpddm_levels_1_sub_pc_type cholesky -pc_hpddm_levels_1_st_pc_type cholesky -pc_hpddm_levels_1_eps_gen_non_hermitian -pc_hpddm_has_neumann -pc_hpddm_levels_1_st_share_sub_ksp true -pc_hpddm_levels_1_pc_type gasm -successive_solves
501:       test:
502:         requires: cuda
503:         suffix: geneo_share_not_asm_cuda
504:         output_file: output/ex76_geneo_pc_hpddm_levels_1_eps_nev-5.out
505:         args: -pc_hpddm_levels_1_sub_pc_type cholesky -pc_hpddm_levels_1_st_pc_type cholesky -pc_hpddm_levels_1_eps_gen_non_hermitian -pc_hpddm_has_neumann -pc_hpddm_levels_1_st_share_sub_ksp true -pc_hpddm_levels_1_pc_type gasm -successive_solves -mat_type aijcusparse

507:    test:
508:       requires: hpddm slepc datafilespath double !complex !defined(PETSC_USE_64BIT_INDICES) defined(PETSC_HAVE_DYNAMIC_LIBRARIES) defined(PETSC_USE_SHARED_LIBRARIES)
509:       suffix: fgmres_geneo_20_p_2
510:       nsize: 4
511:       args: -ksp_converged_reason -pc_type hpddm -pc_hpddm_levels_1_sub_pc_type lu -pc_hpddm_levels_1_eps_nev 20 -pc_hpddm_coarse_p 2 -pc_hpddm_coarse_pc_type redundant -ksp_type fgmres -pc_hpddm_coarse_mat_type {{baij sbaij}shared output} -pc_hpddm_log_separate {{false true}shared output} -load_dir ${DATAFILESPATH}/matrices/hpddm/GENEO

513:    testset:
514:       requires: hpddm slepc datafilespath double !complex !defined(PETSC_USE_64BIT_INDICES) defined(PETSC_HAVE_DYNAMIC_LIBRARIES) defined(PETSC_USE_SHARED_LIBRARIES)
515:       output_file: output/ex76_fgmres_geneo_20_p_2.out
516:       nsize: 4
517:       args: -ksp_converged_reason -pc_type hpddm -pc_hpddm_levels_1_sub_pc_type cholesky -pc_hpddm_levels_1_eps_nev 20 -pc_hpddm_levels_2_p 2 -pc_hpddm_levels_2_mat_type {{baij sbaij}shared output} -pc_hpddm_levels_2_eps_nev {{5 20}shared output} -pc_hpddm_levels_2_sub_pc_type cholesky -pc_hpddm_levels_2_ksp_type gmres -ksp_type fgmres -pc_hpddm_coarse_mat_type {{baij sbaij}shared output} -load_dir ${DATAFILESPATH}/matrices/hpddm/GENEO
518:       test:
519:         suffix: fgmres_geneo_20_p_2_geneo
520:         args: -mat_type {{aij sbaij}shared output}
521:       test:
522:         suffix: fgmres_geneo_20_p_2_geneo_algebraic
523:         args: -pc_hpddm_levels_2_st_pc_type mat
524:    # PCHPDDM + KSPHPDDM test to exercise multilevel + multiple RHS in one go
525:    testset:
526:       requires: hpddm slepc datafilespath double !complex !defined(PETSC_USE_64BIT_INDICES) defined(PETSC_HAVE_DYNAMIC_LIBRARIES) defined(PETSC_USE_SHARED_LIBRARIES)
527:       output_file: output/ex76_fgmres_geneo_20_p_2.out
528:       # for -pc_hpddm_coarse_correction additive
529:       filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 37/Linear solve converged due to CONVERGED_RTOL iterations 25/g"
530:       nsize: 4
531:       args: -ksp_converged_reason -pc_type hpddm -pc_hpddm_levels_1_sub_pc_type cholesky -pc_hpddm_levels_1_eps_nev 20 -ksp_type hpddm -ksp_hpddm_variant flexible -pc_hpddm_coarse_mat_type baij -load_dir ${DATAFILESPATH}/matrices/hpddm/GENEO -rhs 4
532:       test:
533:         suffix: fgmres_geneo_20_p_2_geneo_rhs
534:         args: -pc_hpddm_levels_2_p 2 -pc_hpddm_levels_2_mat_type baij -pc_hpddm_levels_2_eps_nev 5 -pc_hpddm_levels_2_sub_pc_type cholesky -pc_hpddm_levels_2_ksp_max_it 10 -pc_hpddm_levels_2_ksp_type hpddm -pc_hpddm_levels_2_ksp_hpddm_type gmres -mat_type aij -pc_hpddm_coarse_correction {{additive deflated balanced}shared output}
535:       test:
536:         requires: cuda
537:         suffix: fgmres_geneo_20_rhs_cuda
538:         args: -mat_type aijcusparse -pc_hpddm_coarse_correction {{deflated balanced}shared output}

540:    testset:
541:       requires: hpddm slepc datafilespath double !complex !defined(PETSC_USE_64BIT_INDICES) defined(PETSC_HAVE_DYNAMIC_LIBRARIES) defined(PETSC_USE_SHARED_LIBRARIES) mumps defined(PETSC_HAVE_OPENMP_SUPPORT)
542:       filter: grep -E -e "Linear solve" -e "      executing" | sed -e "s/MPI =      1/MPI =      2/g" -e "s/OMP =      1/OMP =      2/g"
543:       nsize: 4
544:       args: -ksp_converged_reason -pc_type hpddm -pc_hpddm_levels_1_sub_pc_type cholesky -pc_hpddm_levels_1_eps_nev 15 -pc_hpddm_levels_1_st_pc_type cholesky -pc_hpddm_coarse_p {{1 2}shared output} -load_dir ${DATAFILESPATH}/matrices/hpddm/GENEO -pc_hpddm_coarse_pc_factor_mat_solver_type mumps -pc_hpddm_coarse_mat_mumps_icntl_4 2 -pc_hpddm_coarse_mat_mumps_use_omp_threads {{1 2}shared output}
545:       test:
546:         suffix: geneo_mumps_use_omp_threads_1
547:         output_file: output/ex76_geneo_mumps_use_omp_threads.out
548:         args: -pc_hpddm_coarse_mat_type {{baij sbaij}shared output}
549:       test:
550:         suffix: geneo_mumps_use_omp_threads_2
551:         output_file: output/ex76_geneo_mumps_use_omp_threads.out
552:         args: -pc_hpddm_coarse_mat_type aij -pc_hpddm_levels_1_eps_threshold_absolute 0.4 -pc_hpddm_coarse_pc_type cholesky -pc_hpddm_coarse_mat_filter 1e-12

554:    testset: # converge really poorly because of a tiny -pc_hpddm_levels_1_eps_threshold_absolute, but needed for proper code coverage where some subdomains don't call EPSSolve()
555:       requires: hpddm slepc datafilespath double !complex !defined(PETSC_USE_64BIT_INDICES) defined(PETSC_HAVE_DYNAMIC_LIBRARIES) defined(PETSC_USE_SHARED_LIBRARIES)
556:       nsize: 4
557:       args: -ksp_converged_reason -pc_type hpddm -pc_hpddm_levels_1_sub_pc_type cholesky -pc_hpddm_levels_1_eps_threshold_absolute 0.005 -pc_hpddm_levels_1_eps_use_inertia -load_dir ${DATAFILESPATH}/matrices/hpddm/GENEO -pc_hpddm_levels_1_st_share_sub_ksp -pc_hpddm_define_subdomains -pc_hpddm_has_neumann -ksp_rtol 0.9
558:       filter: sed -e "s/Linear solve converged due to CONVERGED_RTOL iterations 1/Linear solve converged due to CONVERGED_RTOL iterations 141/g"
559:       test:
560:         suffix: inertia_petsc
561:         output_file: output/ex76_1.out
562:         args: -pc_hpddm_levels_1_sub_pc_factor_mat_solver_type petsc
563:       test:
564:         suffix: inertia_mumps
565:         output_file: output/ex76_1.out
566:         requires: mumps

568:    testset:
569:       requires: hpddm slepc datafilespath double !complex !defined(PETSC_USE_64BIT_INDICES) defined(PETSC_HAVE_DYNAMIC_LIBRARIES) defined(PETSC_USE_SHARED_LIBRARIES)
570:       output_file: output/empty.out
571:       nsize: 4
572:       args: -pc_type hpddm -pc_hpddm_levels_1_sub_pc_type cholesky -pc_hpddm_levels_1_eps_nev 20 -rhs 4 -ksp_max_it 20 -ksp_type hpddm -load_dir ${DATAFILESPATH}/matrices/hpddm/GENEO -pc_hpddm_define_subdomains -ksp_error_if_not_converged
573:       test:
574:         suffix: reuse_symbolic
575:         args: -pc_hpddm_coarse_correction {{additive deflated balanced deflated_reversed}shared output} -ksp_pc_side {{left right}shared output} -transpose {{true false}shared output}
576:       test:
577:         requires: cuda
578:         suffix: reuse_symbolic_cuda
579:         args: -pc_hpddm_coarse_correction deflated -ksp_pc_side right -transpose -mat_type aijcusparse

581: TEST*/