xref: /petsc/src/vec/is/sf/tests/ex18.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
1f210f596SVaclav Hapla 
2f210f596SVaclav Hapla static char help[] = "Test PetscSFConcatenate()\n\n";
3f210f596SVaclav Hapla 
4f210f596SVaclav Hapla #include <petscsf.h>
5f210f596SVaclav Hapla 
6f210f596SVaclav Hapla typedef struct {
7f210f596SVaclav Hapla   MPI_Comm    comm;
8f210f596SVaclav Hapla   PetscMPIInt rank, size;
9f210f596SVaclav Hapla   PetscInt    leaveStep, nsfs, nLeavesPerRank;
10f210f596SVaclav Hapla   PetscBool   shareRoots, sparseLeaves;
11f210f596SVaclav Hapla } AppCtx;
12f210f596SVaclav Hapla 
13*d71ae5a4SJacob Faibussowitsch static PetscErrorCode GetOptions(MPI_Comm comm, AppCtx *ctx)
14*d71ae5a4SJacob Faibussowitsch {
15f210f596SVaclav Hapla   PetscFunctionBegin;
16f210f596SVaclav Hapla   ctx->comm           = comm;
17f210f596SVaclav Hapla   ctx->nsfs           = 3;
18f210f596SVaclav Hapla   ctx->nLeavesPerRank = 4;
19f210f596SVaclav Hapla   ctx->leaveStep      = 1;
20f210f596SVaclav Hapla   ctx->shareRoots     = PETSC_FALSE;
21f210f596SVaclav Hapla   ctx->sparseLeaves   = PETSC_FALSE;
229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-nsfs", &ctx->nsfs, NULL));
239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-n_leaves_per_rank", &ctx->nLeavesPerRank, NULL));
249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetInt(NULL, NULL, "-leave_step", &ctx->leaveStep, NULL));
259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(NULL, NULL, "-share_roots", &ctx->shareRoots, NULL));
26f210f596SVaclav Hapla   ctx->sparseLeaves = (PetscBool)(ctx->leaveStep != 1);
279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &ctx->size));
289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &ctx->rank));
29f210f596SVaclav Hapla   PetscFunctionReturn(0);
30f210f596SVaclav Hapla }
31f210f596SVaclav Hapla 
32*d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscSFCheckEqual_Private(PetscSF sf0, PetscSF sf1)
33*d71ae5a4SJacob Faibussowitsch {
34f210f596SVaclav Hapla   PetscInt  nRoot, nLeave;
35f210f596SVaclav Hapla   Vec       vecRoot0, vecLeave0, vecRoot1, vecLeave1;
36f210f596SVaclav Hapla   MPI_Comm  comm;
37f210f596SVaclav Hapla   PetscBool flg;
38f210f596SVaclav Hapla 
39f210f596SVaclav Hapla   PetscFunctionBegin;
409566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)sf0, &comm));
419566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sf0, &nRoot, NULL, NULL, NULL));
429566063dSJacob Faibussowitsch   PetscCall(PetscSFGetLeafRange(sf0, NULL, &nLeave));
43f210f596SVaclav Hapla   nLeave++;
449566063dSJacob Faibussowitsch   PetscCall(VecCreateMPI(comm, nRoot, PETSC_DECIDE, &vecRoot0));
459566063dSJacob Faibussowitsch   PetscCall(VecCreateMPI(comm, nLeave, PETSC_DECIDE, &vecLeave0));
469566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(vecRoot0, &vecRoot1));
479566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(vecLeave0, &vecLeave1));
48f210f596SVaclav Hapla   {
49f210f596SVaclav Hapla     PetscRandom rand;
50f210f596SVaclav Hapla 
519566063dSJacob Faibussowitsch     PetscCall(PetscRandomCreate(comm, &rand));
529566063dSJacob Faibussowitsch     PetscCall(PetscRandomSetFromOptions(rand));
539566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(vecRoot0, rand));
549566063dSJacob Faibussowitsch     PetscCall(VecSetRandom(vecLeave0, rand));
559566063dSJacob Faibussowitsch     PetscCall(VecCopy(vecRoot0, vecRoot1));
569566063dSJacob Faibussowitsch     PetscCall(VecCopy(vecLeave0, vecLeave1));
579566063dSJacob Faibussowitsch     PetscCall(PetscRandomDestroy(&rand));
58f210f596SVaclav Hapla   }
59f210f596SVaclav Hapla 
609566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(sf0, vecRoot0, vecLeave0, ADD_VALUES, SCATTER_FORWARD));
619566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(sf0, vecRoot0, vecLeave0, ADD_VALUES, SCATTER_FORWARD));
629566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(sf1, vecRoot1, vecLeave1, ADD_VALUES, SCATTER_FORWARD));
639566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(sf1, vecRoot1, vecLeave1, ADD_VALUES, SCATTER_FORWARD));
649566063dSJacob Faibussowitsch   PetscCall(VecEqual(vecLeave0, vecLeave1, &flg));
65f210f596SVaclav Hapla   PetscCheck(flg, comm, PETSC_ERR_PLIB, "leave vectors differ");
66f210f596SVaclav Hapla 
679566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(sf0, vecLeave0, vecRoot0, ADD_VALUES, SCATTER_REVERSE));
689566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(sf0, vecLeave0, vecRoot0, ADD_VALUES, SCATTER_REVERSE));
699566063dSJacob Faibussowitsch   PetscCall(VecScatterBegin(sf1, vecLeave1, vecRoot1, ADD_VALUES, SCATTER_REVERSE));
709566063dSJacob Faibussowitsch   PetscCall(VecScatterEnd(sf1, vecLeave1, vecRoot1, ADD_VALUES, SCATTER_REVERSE));
719566063dSJacob Faibussowitsch   PetscCall(VecEqual(vecRoot0, vecRoot1, &flg));
72f210f596SVaclav Hapla   PetscCheck(flg, comm, PETSC_ERR_PLIB, "root vectors differ");
73f210f596SVaclav Hapla 
749566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vecRoot0));
759566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vecRoot1));
769566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vecLeave0));
779566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&vecLeave1));
78f210f596SVaclav Hapla   PetscFunctionReturn(0);
79f210f596SVaclav Hapla }
80f210f596SVaclav Hapla 
81*d71ae5a4SJacob Faibussowitsch PetscErrorCode CreateReferenceSF(AppCtx *ctx, PetscSF *refSF)
82*d71ae5a4SJacob Faibussowitsch {
83f210f596SVaclav Hapla   PetscInt     i, j, k, r;
84f210f596SVaclav Hapla   PetscInt    *ilocal = NULL;
85f210f596SVaclav Hapla   PetscSFNode *iremote;
86f210f596SVaclav Hapla   PetscInt     nLeaves = ctx->nsfs * ctx->nLeavesPerRank * ctx->size;
87f210f596SVaclav Hapla   PetscInt     nroots  = ctx->nLeavesPerRank * ctx->nsfs;
88f210f596SVaclav Hapla   PetscSF      sf;
89f210f596SVaclav Hapla 
90f210f596SVaclav Hapla   PetscFunctionBegin;
91f210f596SVaclav Hapla   ilocal = NULL;
9248a46eb9SPierre Jolivet   if (ctx->sparseLeaves) PetscCall(PetscCalloc1(nLeaves + 1, &ilocal));
939566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nLeaves, &iremote));
949566063dSJacob Faibussowitsch   PetscCall(PetscSFCreate(ctx->comm, &sf));
95f210f596SVaclav Hapla   for (i = 0, j = 0; i < ctx->nsfs; i++) {
96f210f596SVaclav Hapla     for (r = 0; r < ctx->size; r++) {
97f210f596SVaclav Hapla       for (k = 0; k < ctx->nLeavesPerRank; k++, j++) {
98ad540459SPierre Jolivet         if (ctx->sparseLeaves) ilocal[j + 1] = ilocal[j] + ctx->leaveStep;
99f210f596SVaclav Hapla         iremote[j].rank  = r;
100f210f596SVaclav Hapla         iremote[j].index = k + i * ctx->nLeavesPerRank;
101f210f596SVaclav Hapla       }
102f210f596SVaclav Hapla     }
103f210f596SVaclav Hapla   }
1049566063dSJacob Faibussowitsch   PetscCall(PetscSFSetGraph(sf, nroots, nLeaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER));
105f210f596SVaclav Hapla   *refSF = sf;
106f210f596SVaclav Hapla   PetscFunctionReturn(0);
107f210f596SVaclav Hapla }
108f210f596SVaclav Hapla 
109*d71ae5a4SJacob Faibussowitsch PetscErrorCode CreateSFs(AppCtx *ctx, PetscSF *newSFs[], PetscInt *leafOffsets[])
110*d71ae5a4SJacob Faibussowitsch {
111f210f596SVaclav Hapla   PetscInt  i;
112f210f596SVaclav Hapla   PetscInt *lOffsets = NULL;
113f210f596SVaclav Hapla   PetscSF  *sfs;
114f210f596SVaclav Hapla   PetscInt  nLeaves = ctx->nLeavesPerRank * ctx->size;
115f210f596SVaclav Hapla   PetscInt  nroots  = ctx->shareRoots ? ctx->nLeavesPerRank * ctx->nsfs : ctx->nLeavesPerRank;
116f210f596SVaclav Hapla 
117f210f596SVaclav Hapla   PetscFunctionBegin;
11848a46eb9SPierre Jolivet   if (ctx->sparseLeaves) PetscCall(PetscCalloc1(ctx->nsfs + 1, &lOffsets));
1199566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ctx->nsfs, &sfs));
120f210f596SVaclav Hapla   for (i = 0; i < ctx->nsfs; i++) {
121f210f596SVaclav Hapla     PetscInt     j, k;
122f210f596SVaclav Hapla     PetscMPIInt  r;
123f210f596SVaclav Hapla     PetscInt    *ilocal = NULL;
124f210f596SVaclav Hapla     PetscSFNode *iremote;
125f210f596SVaclav Hapla 
12648a46eb9SPierre Jolivet     if (ctx->sparseLeaves) PetscCall(PetscCalloc1(nLeaves + 1, &ilocal));
1279566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(nLeaves, &iremote));
128f210f596SVaclav Hapla     for (r = 0, j = 0; r < ctx->size; r++) {
129f210f596SVaclav Hapla       for (k = 0; k < ctx->nLeavesPerRank; k++, j++) {
130ad540459SPierre Jolivet         if (ctx->sparseLeaves) ilocal[j + 1] = ilocal[j] + ctx->leaveStep;
131f210f596SVaclav Hapla         iremote[j].rank  = r;
132f210f596SVaclav Hapla         iremote[j].index = ctx->shareRoots ? k + i * ctx->nLeavesPerRank : k;
133f210f596SVaclav Hapla       }
134f210f596SVaclav Hapla     }
135f210f596SVaclav Hapla     if (ctx->sparseLeaves) lOffsets[i + 1] = lOffsets[i] + ilocal[j];
136f210f596SVaclav Hapla 
1379566063dSJacob Faibussowitsch     PetscCall(PetscSFCreate(ctx->comm, &sfs[i]));
1389566063dSJacob Faibussowitsch     PetscCall(PetscSFSetGraph(sfs[i], nroots, nLeaves, ilocal, PETSC_OWN_POINTER, iremote, PETSC_OWN_POINTER));
139f210f596SVaclav Hapla   }
140f210f596SVaclav Hapla   *newSFs      = sfs;
141f210f596SVaclav Hapla   *leafOffsets = lOffsets;
142f210f596SVaclav Hapla   PetscFunctionReturn(0);
143f210f596SVaclav Hapla }
144f210f596SVaclav Hapla 
145*d71ae5a4SJacob Faibussowitsch PetscErrorCode DestroySFs(AppCtx *ctx, PetscSF *sfs[])
146*d71ae5a4SJacob Faibussowitsch {
147f210f596SVaclav Hapla   PetscInt i;
148f210f596SVaclav Hapla 
149f210f596SVaclav Hapla   PetscFunctionBegin;
15048a46eb9SPierre Jolivet   for (i = 0; i < ctx->nsfs; i++) PetscCall(PetscSFDestroy(&(*sfs)[i]));
1519566063dSJacob Faibussowitsch   PetscCall(PetscFree(*sfs));
152f210f596SVaclav Hapla   PetscFunctionReturn(0);
153f210f596SVaclav Hapla }
154f210f596SVaclav Hapla 
155*d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
156*d71ae5a4SJacob Faibussowitsch {
157f210f596SVaclav Hapla   AppCtx    ctx;
158f210f596SVaclav Hapla   PetscSF   sf, sfRef;
159f210f596SVaclav Hapla   PetscSF  *sfs;
160f210f596SVaclav Hapla   PetscInt *leafOffsets;
161f210f596SVaclav Hapla   MPI_Comm  comm;
162f210f596SVaclav Hapla 
163327415f7SBarry Smith   PetscFunctionBeginUser;
1649566063dSJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
165f210f596SVaclav Hapla   comm = PETSC_COMM_WORLD;
1669566063dSJacob Faibussowitsch   PetscCall(GetOptions(comm, &ctx));
167f210f596SVaclav Hapla 
1689566063dSJacob Faibussowitsch   PetscCall(CreateSFs(&ctx, &sfs, &leafOffsets));
1699566063dSJacob Faibussowitsch   PetscCall(PetscSFConcatenate(comm, ctx.nsfs, sfs, ctx.shareRoots, leafOffsets, &sf));
1709566063dSJacob Faibussowitsch   PetscCall(CreateReferenceSF(&ctx, &sfRef));
1719566063dSJacob Faibussowitsch   PetscCall(PetscSFCheckEqual_Private(sf, sfRef));
172f210f596SVaclav Hapla 
1739566063dSJacob Faibussowitsch   PetscCall(DestroySFs(&ctx, &sfs));
1749566063dSJacob Faibussowitsch   PetscCall(PetscFree(leafOffsets));
1759566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sf));
1769566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfRef));
1779566063dSJacob Faibussowitsch   PetscCall(PetscFinalize());
178b122ec5aSJacob Faibussowitsch   return 0;
179f210f596SVaclav Hapla }
180f210f596SVaclav Hapla 
181f210f596SVaclav Hapla /*TEST
182f210f596SVaclav Hapla   test:
183f210f596SVaclav Hapla     nsize: {{1 3}}
184f210f596SVaclav Hapla     args: -nsfs {{1 3}} -n_leaves_per_rank {{0 1 5}} -leave_step {{1 3}} -share_roots {{true false}}
185f210f596SVaclav Hapla TEST*/
186