Actual source code: ex316.c
1: static char help[] = "Tests MatISFixLocalEmpty() with a blocked local to global mapping.\n\n";
3: #include <petscmat.h>
5: int main(int argc, char **args)
6: {
7: Mat A, B;
8: ISLocalToGlobalMapping map, rl2g, cl2g;
9: PetscScalar v;
10: PetscInt *idxs, N, i, j, rbs, cbs, bs = 2, nl = 4;
11: PetscMPIInt rank, size;
12: PetscBool partial = PETSC_FALSE, drop, flg;
14: PetscFunctionBeginUser;
15: PetscCall(PetscInitialize(&argc, &args, NULL, help));
16: PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
17: PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
18: PetscCall(PetscOptionsGetInt(NULL, NULL, "-bs", &bs, NULL));
19: PetscCall(PetscOptionsGetInt(NULL, NULL, "-nl", &nl, NULL));
20: PetscCall(PetscOptionsGetBool(NULL, NULL, "-partial", &partial, NULL));
22: /* subdomains sharing a block of degrees of freedom, as in a finite element decomposition */
23: PetscCall(PetscMalloc1(nl, &idxs));
24: for (i = 0; i < nl; i++) idxs[i] = rank * (nl - 1) + i;
25: PetscCall(ISLocalToGlobalMappingCreate(PETSC_COMM_WORLD, bs, nl, idxs, PETSC_OWN_POINTER, &map));
27: N = (size * (nl - 1) + 1) * bs;
28: PetscCall(MatCreateIS(PETSC_COMM_WORLD, bs, PETSC_DECIDE, PETSC_DECIDE, N, N, map, map, &A));
29: PetscCall(MatISSetPreallocation(A, 3, NULL, 3, NULL));
31: /* leave the last local block without any entry, so that MatISFixLocalEmpty() drops it;
32: with -partial the last subdomain instead leaves a single degree of freedom out, which
33: breaks the block and must make every process give up the block size
34: */
35: for (i = 0; i < nl * bs; i++) {
36: drop = (PetscBool)(i / bs == nl - 1);
37: if (partial && rank == size - 1) drop = (PetscBool)(i == nl * bs - 1);
38: if (drop) continue;
39: v = 2.0;
40: PetscCall(MatSetValuesLocal(A, 1, &i, 1, &i, &v, ADD_VALUES));
41: for (j = i - 1; j <= i + 1; j += 2) {
42: if (j < 0 || j >= (partial && rank == size - 1 ? nl * bs - 1 : (nl - 1) * bs)) continue;
43: v = -1.0;
44: PetscCall(MatSetValuesLocal(A, 1, &i, 1, &j, &v, ADD_VALUES));
45: }
46: }
47: PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
48: PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
49: PetscCall(MatConvert(A, MATAIJ, MAT_INITIAL_MATRIX, &B));
51: PetscCall(MatGetLocalToGlobalMapping(A, &rl2g, &cl2g));
52: PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g, &rbs));
53: PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g, &cbs));
54: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Block sizes before MatISFixLocalEmpty %" PetscInt_FMT " %" PetscInt_FMT "\n", rbs, cbs));
56: PetscCall(MatISFixLocalEmpty(A, PETSC_TRUE));
57: PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
58: PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
60: PetscCall(MatGetLocalToGlobalMapping(A, &rl2g, &cl2g));
61: PetscCall(ISLocalToGlobalMappingGetBlockSize(rl2g, &rbs));
62: PetscCall(ISLocalToGlobalMappingGetBlockSize(cl2g, &cbs));
63: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Block sizes after MatISFixLocalEmpty %" PetscInt_FMT " %" PetscInt_FMT "\n", rbs, cbs));
65: PetscCall(MatMultEqual(A, B, 5, &flg));
66: PetscCheck(flg, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "MatISFixLocalEmpty changed the operator");
68: PetscCall(MatDestroy(&A));
69: PetscCall(MatDestroy(&B));
70: PetscCall(ISLocalToGlobalMappingDestroy(&map));
71: PetscCall(PetscFinalize());
72: return 0;
73: }
75: /*TEST
77: test:
78: suffix: 1
79: nsize: 1
81: test:
82: suffix: 2
83: nsize: 3
85: test:
86: suffix: 1_partial
87: nsize: 1
88: args: -partial
90: test:
91: suffix: 2_partial
92: nsize: 3
93: args: -partial
95: TEST*/