Actual source code: lostnullspace.c

  1: static char help[] = "Losing nullspaces in PCFIELDSPLIT after zeroing rows.\n";

  3: // Contributed by Jeremy Theler

  5: #include <petscksp.h>

  7: int main(int argc, char **args)
  8: {
  9:   KSP             ksp, *sub_ksp;
 10:   Vec             x, b, rigid_mode[6];
 11:   PetscViewer     viewer;
 12:   PetscInt        rows, cols, size, bs, n_splits = 0;
 13:   PetscBool       has_columns = PETSC_FALSE;
 14:   Mat             A, K;
 15:   MatNullSpace    nullsp, near_null_space;
 16:   IS              is_thermal, is_mech;
 17:   PC              pc, pc_thermal, pc_mech;
 18:   const PetscInt *bc_thermal_indexes, *bc_mech_indexes;
 19:   char            datafilespath[PETSC_MAX_PATH_LEN], datafile[PETSC_MAX_PATH_LEN];

 21:   PetscFunctionBeginUser;
 22:   PetscCall(PetscInitialize(&argc, &args, NULL, help));
 23:   PetscCall(PetscOptionsGetString(NULL, NULL, "-datafilespath", datafilespath, sizeof(datafilespath), NULL));

 25:   PetscCall(PetscStrcpy(datafile, datafilespath));
 26:   PetscCall(PetscStrcat(datafile, "/lostnullspace/"));
 27:   PetscCall(PetscStrcat(datafile, "A.bin"));
 28:   PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, datafile, FILE_MODE_READ, &viewer));
 29:   PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
 30:   PetscCall(MatLoad(A, viewer));
 31:   PetscCall(PetscViewerDestroy(&viewer));

 33:   PetscCall(MatGetNearNullSpace(A, &nullsp));
 34:   PetscCall(MatGetSize(A, &rows, &cols));
 35:   PetscCall(MatGetBlockSize(A, &bs));
 36:   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "A has rows = %" PetscInt_FMT ", cols = %" PetscInt_FMT ", bs = %" PetscInt_FMT ", nearnullsp = %p\n", rows, cols, bs, (void *)nullsp));

 38:   PetscCall(PetscStrcpy(datafile, datafilespath));
 39:   PetscCall(PetscStrcat(datafile, "/lostnullspace/"));
 40:   PetscCall(PetscStrcat(datafile, "is.bin"));
 41:   PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, datafile, FILE_MODE_READ, &viewer));

 43:   PetscCall(ISCreate(PETSC_COMM_WORLD, &is_thermal));
 44:   PetscCall(ISLoad(is_thermal, viewer));
 45:   PetscCall(ISGetSize(is_thermal, &size));
 46:   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "thermal field size = %" PetscInt_FMT " \n", size));

 48:   PetscCall(ISCreate(PETSC_COMM_WORLD, &is_mech));
 49:   PetscCall(ISLoad(is_mech, viewer));
 50:   PetscCall(ISGetSize(is_mech, &size));
 51:   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "mechanical field size = %" PetscInt_FMT " \n", size));
 52:   PetscCall(PetscViewerDestroy(&viewer));

 54:   PetscCall(MatCreateVecs(A, &x, &b));

 56:   PetscCall(KSPCreate(PETSC_COMM_WORLD, &ksp));
 57:   PetscCall(KSPSetOperators(ksp, A, A));

 59:   PetscCall(KSPSetType(ksp, KSPPREONLY));

 61:   PetscCall(KSPGetPC(ksp, &pc));
 62:   PetscCall(PCSetType(pc, PCFIELDSPLIT));
 63:   PetscCall(PCFieldSplitSetIS(pc, "thermal", is_thermal));
 64:   PetscCall(PCFieldSplitSetIS(pc, "mechanical", is_mech));
 65:   PetscCall(PCSetUp(pc));
 66:   PetscCall(PCFieldSplitGetSubKSP(pc, &n_splits, &sub_ksp));
 67:   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "n_splits = %" PetscInt_FMT " \n", n_splits));
 68:   PetscCall(KSPSetType(sub_ksp[0], KSPGMRES));

 70:   PetscCall(KSPGetPC(sub_ksp[0], &pc_thermal));
 71:   PetscCall(PCSetType(pc_thermal, PCJACOBI));
 72:   PetscCall(KSPSetFromOptions(sub_ksp[0]));

 74:   PetscCall(KSPSetType(sub_ksp[1], KSPCG));
 75:   PetscCall(KSPGetPC(sub_ksp[1], &pc_mech));
 76:   PetscCall(PCSetType(pc_mech, PCGAMG));
 77:   PetscCall(KSPSetFromOptions(sub_ksp[1]));

 79:   PetscCall(PetscStrcpy(datafile, datafilespath));
 80:   PetscCall(PetscStrcat(datafile, "/lostnullspace/"));
 81:   PetscCall(PetscStrcat(datafile, "rigid-modes.bin"));
 82:   PetscCall(PetscViewerBinaryOpen(PETSC_COMM_WORLD, datafile, FILE_MODE_READ, &viewer));
 83:   for (PetscInt i = 0; i < 6; i++) {
 84:     PetscCall(VecCreate(PETSC_COMM_WORLD, &rigid_mode[i]));
 85:     PetscCall(VecLoad(rigid_mode[i], viewer));
 86:   }
 87:   PetscCall(PetscViewerDestroy(&viewer));

 89:   PetscCall(MatNullSpaceCreate(PETSC_COMM_WORLD, PETSC_FALSE, 6, rigid_mode, &near_null_space));
 90:   PetscCall(KSPGetOperators(sub_ksp[1], &K, PETSC_NULLPTR));
 91:   PetscCall(MatSetNearNullSpace(K, near_null_space));
 92:   PetscCall(MatSetBlockSize(K, 3));

 94:   PetscCall(MatGetSize(K, &rows, &cols));
 95:   PetscCall(MatGetBlockSize(K, &bs));
 96:   PetscCall(MatGetNearNullSpace(K, &nullsp));
 97:   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "K has rows = %" PetscInt_FMT ", cols = %" PetscInt_FMT ", bs = %" PetscInt_FMT ", nearnullsp = %p\n", rows, cols, bs, (void *)nullsp));

 99:   PetscCall(ISGetIndices(is_thermal, &bc_thermal_indexes));
100:   PetscCall(ISGetIndices(is_mech, &bc_mech_indexes));

102:   // check that MatZeroRows() without MAT_KEEP_NONZERO_PATTERN does not remove the near null spaces attached to the submatrices
103:   PetscCall(PetscOptionsHasName(PETSC_NULLPTR, PETSC_NULLPTR, "-columns", &has_columns));
104:   if (has_columns == PETSC_TRUE) {
105:     PetscCall(MatZeroRowsColumns(A, 3, bc_mech_indexes, 1, PETSC_NULLPTR, PETSC_NULLPTR));
106:     PetscCall(MatZeroRowsColumns(A, 1, bc_thermal_indexes, 1, PETSC_NULLPTR, PETSC_NULLPTR));
107:   } else {
108:     PetscCall(MatZeroRows(A, 3, bc_mech_indexes, 1, PETSC_NULLPTR, PETSC_NULLPTR));
109:     PetscCall(MatZeroRows(A, 1, bc_thermal_indexes, 1, PETSC_NULLPTR, PETSC_NULLPTR));
110:   }
111:   PetscCall(ISRestoreIndices(is_mech, &bc_mech_indexes));
112:   PetscCall(ISRestoreIndices(is_thermal, &bc_thermal_indexes));

114:   PetscCall(KSPSetFromOptions(ksp));
115:   PetscCall(KSPSetUp(ksp));
116:   PetscCall(KSPSolve(ksp, b, x));

118:   PetscCall(MatDestroy(&A));
119:   PetscCall(KSPDestroy(&ksp));
120:   PetscCall(ISDestroy(&is_mech));
121:   PetscCall(ISDestroy(&is_thermal));
122:   PetscCall(VecDestroy(&x));
123:   PetscCall(VecDestroy(&b));
124:   PetscCall(MatNullSpaceDestroy(&near_null_space));
125:   for (PetscInt i = 0; i < 6; i++) PetscCall(VecDestroy(&rigid_mode[i]));
126:   PetscCall(PetscFree(sub_ksp));
127:   PetscCall(PetscFinalize());
128:   return 0;
129: }

131: /*TEST

133:     test:
134:       requires: datafilespath double !complex !defined(PETSC_USE_64BIT_INDICES)
135:       args: -datafilespath ${DATAFILESPATH} -ksp_view
136:       filter: grep "near null"

138: TEST*/