Actual source code: ex19.c
2: static char help[] = "Test leaf sorting in PetscSFSetGraph()\n\n";
4: #include <petscsf.h>
6: typedef struct {
7: MPI_Comm comm;
8: PetscMPIInt rank, size;
9: PetscInt leaveStep, nLeavesPerRank;
10: PetscBool contiguousLeaves;
11: PetscCopyMode localmode, remotemode;
12: PetscInt *ilocal;
13: PetscSFNode *iremote;
14: } AppCtx;
16: static PetscErrorCode GetOptions(MPI_Comm comm, AppCtx *ctx)
17: {
18: ctx->comm = comm;
19: ctx->nLeavesPerRank = 4;
20: ctx->leaveStep = 1;
21: ctx->contiguousLeaves = PETSC_FALSE;
22: ctx->localmode = PETSC_OWN_POINTER;
23: ctx->remotemode = PETSC_OWN_POINTER;
24: ctx->ilocal = NULL;
25: ctx->iremote = NULL;
26: PetscOptionsGetInt(NULL, NULL, "-n_leaves_per_rank", &ctx->nLeavesPerRank, NULL);
27: PetscOptionsGetInt(NULL, NULL, "-leave_step", &ctx->leaveStep, NULL);
28: PetscOptionsGetEnum(NULL, NULL, "-localmode", PetscCopyModes, (PetscEnum *)&ctx->localmode, NULL);
29: PetscOptionsGetEnum(NULL, NULL, "-remotemode", PetscCopyModes, (PetscEnum *)&ctx->remotemode, NULL);
30: ctx->contiguousLeaves = (PetscBool)(ctx->leaveStep == 1);
31: MPI_Comm_size(comm, &ctx->size);
32: MPI_Comm_rank(comm, &ctx->rank);
33: return 0;
34: }
36: static PetscErrorCode PetscSFCheckEqual_Private(PetscSF sf0, PetscSF sf1)
37: {
38: PetscInt nRoot, nLeave;
39: Vec vecRoot0, vecLeave0, vecRoot1, vecLeave1;
40: MPI_Comm comm;
41: PetscBool flg;
43: PetscObjectGetComm((PetscObject)sf0, &comm);
44: PetscSFGetGraph(sf0, &nRoot, NULL, NULL, NULL);
45: PetscSFGetLeafRange(sf0, NULL, &nLeave);
46: nLeave++;
47: VecCreateMPI(comm, nRoot, PETSC_DECIDE, &vecRoot0);
48: VecCreateMPI(comm, nLeave, PETSC_DECIDE, &vecLeave0);
49: VecDuplicate(vecRoot0, &vecRoot1);
50: VecDuplicate(vecLeave0, &vecLeave1);
51: {
52: PetscRandom rand;
54: PetscRandomCreate(comm, &rand);
55: PetscRandomSetFromOptions(rand);
56: VecSetRandom(vecRoot0, rand);
57: VecSetRandom(vecLeave0, rand);
58: VecCopy(vecRoot0, vecRoot1);
59: VecCopy(vecLeave0, vecLeave1);
60: PetscRandomDestroy(&rand);
61: }
63: VecScatterBegin(sf0, vecRoot0, vecLeave0, ADD_VALUES, SCATTER_FORWARD);
64: VecScatterEnd(sf0, vecRoot0, vecLeave0, ADD_VALUES, SCATTER_FORWARD);
65: VecScatterBegin(sf1, vecRoot1, vecLeave1, ADD_VALUES, SCATTER_FORWARD);
66: VecScatterEnd(sf1, vecRoot1, vecLeave1, ADD_VALUES, SCATTER_FORWARD);
67: VecEqual(vecLeave0, vecLeave1, &flg);
70: VecScatterBegin(sf0, vecLeave0, vecRoot0, ADD_VALUES, SCATTER_REVERSE);
71: VecScatterEnd(sf0, vecLeave0, vecRoot0, ADD_VALUES, SCATTER_REVERSE);
72: VecScatterBegin(sf1, vecLeave1, vecRoot1, ADD_VALUES, SCATTER_REVERSE);
73: VecScatterEnd(sf1, vecLeave1, vecRoot1, ADD_VALUES, SCATTER_REVERSE);
74: VecEqual(vecRoot0, vecRoot1, &flg);
77: VecDestroy(&vecRoot0);
78: VecDestroy(&vecRoot1);
79: VecDestroy(&vecLeave0);
80: VecDestroy(&vecLeave1);
81: return 0;
82: }
84: PetscErrorCode CreateSF0(AppCtx *ctx, PetscSF *sf0)
85: {
86: PetscInt j, k, r;
87: PetscInt nLeaves = ctx->nLeavesPerRank * ctx->size;
88: PetscInt nroots = ctx->nLeavesPerRank;
89: PetscSF sf;
90: PetscInt *ilocal;
91: PetscSFNode *iremote;
93: PetscMalloc1(nLeaves + 1, &ctx->ilocal);
94: PetscMalloc1(nLeaves, &ctx->iremote);
95: ilocal = ctx->ilocal;
96: iremote = ctx->iremote;
97: ilocal[nLeaves] = -ctx->leaveStep;
98: PetscSFCreate(ctx->comm, &sf);
99: for (r = 0, j = nLeaves - 1; r < ctx->size; r++) {
100: for (k = 0; k < ctx->nLeavesPerRank; k++, j--) {
101: ilocal[j] = ilocal[j + 1] + ctx->leaveStep;
102: iremote[j].rank = r;
103: iremote[j].index = k;
104: }
105: }
106: PetscSFSetGraph(sf, nroots, nLeaves, ilocal, ctx->localmode, iremote, ctx->remotemode);
107: {
108: const PetscInt *tlocal;
109: PetscBool sorted;
111: PetscSFGetGraph(sf, NULL, NULL, &tlocal, NULL);
113: if (tlocal) {
114: PetscSortedInt(nLeaves, tlocal, &sorted);
116: }
117: }
118: *sf0 = sf;
119: return 0;
120: }
122: PetscErrorCode CreateSF1(AppCtx *ctx, PetscSF *sf1)
123: {
124: PetscInt j, k, r;
125: PetscInt *ilocal = NULL;
126: PetscSFNode *iremote;
127: PetscInt nLeaves = ctx->nLeavesPerRank * ctx->size;
128: PetscInt nroots = ctx->nLeavesPerRank;
129: PetscSF sf;
131: ilocal = NULL;
132: if (!ctx->contiguousLeaves) PetscCalloc1(nLeaves + 1, &ilocal);
133: PetscMalloc1(nLeaves, &iremote);
134: PetscSFCreate(ctx->comm, &sf);
135: for (r = 0, j = 0; r < ctx->size; r++) {
136: for (k = 0; k < ctx->nLeavesPerRank; k++, j++) {
137: if (!ctx->contiguousLeaves) ilocal[j + 1] = ilocal[j] + ctx->leaveStep;
138: iremote[j].rank = r;
139: iremote[j].index = k;
140: }
141: }
143: PetscSFSetGraph(sf, nroots, nLeaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER);
144: if (ctx->contiguousLeaves) {
145: const PetscInt *tlocal;
147: PetscSFGetGraph(sf, NULL, NULL, &tlocal, NULL);
149: }
150: *sf1 = sf;
151: return 0;
152: }
154: int main(int argc, char **argv)
155: {
156: AppCtx ctx;
157: PetscSF sf0, sf1;
158: MPI_Comm comm;
161: PetscInitialize(&argc, &argv, NULL, help);
162: comm = PETSC_COMM_WORLD;
163: GetOptions(comm, &ctx);
165: CreateSF0(&ctx, &sf0);
166: CreateSF1(&ctx, &sf1);
167: PetscSFViewFromOptions(sf0, NULL, "-sf0_view");
168: PetscSFViewFromOptions(sf1, NULL, "-sf1_view");
169: PetscSFCheckEqual_Private(sf0, sf1);
171: if (ctx.localmode != PETSC_OWN_POINTER) PetscFree(ctx.ilocal);
172: if (ctx.remotemode != PETSC_OWN_POINTER) PetscFree(ctx.iremote);
173: PetscSFDestroy(&sf0);
174: PetscSFDestroy(&sf1);
175: PetscFinalize();
176: return 0;
177: }
179: /*TEST
180: testset:
181: suffix: 1
182: nsize: {{1 3}}
183: args: -n_leaves_per_rank {{0 5}} -leave_step {{1 3}}
184: test:
185: suffix: a
186: args: -localmode {{COPY_VALUES OWN_POINTER}} -remotemode {{COPY_VALUES OWN_POINTER}}
187: test:
188: suffix: b
189: args: -localmode USE_POINTER -remotemode {{COPY_VALUES OWN_POINTER USE_POINTER}}
190: TEST*/