1 #include <../src/dm/impls/composite/packimpl.h> /*I "petscdmcomposite.h" I*/
2 #include <petsc/private/isimpl.h>
3 #include <petsc/private/glvisviewerimpl.h>
4 #include <petscds.h>
5
6 /*@C
7 DMCompositeSetCoupling - Sets user provided routines that compute the coupling between the
8 separate components `DM` in a `DMCOMPOSITE` to build the correct matrix nonzero structure.
9
10 Logically Collective; No Fortran Support
11
12 Input Parameters:
13 + dm - the composite object
14 - FormCoupleLocations - routine to set the nonzero locations in the matrix
15
16 Level: advanced
17
18 Notes:
19 See `DMSetApplicationContext()` and `DMGetApplicationContext()` for how to get user information into
20 this routine
21
22 The provided function should have a signature matching
23 .vb
24 PetscErrorCode your_form_couple_method(DM dm, Mat J, PetscInt *dnz, PetscInt *onz, PetscInt rstart, PetscInt nrows, PetscInt start, PetscInt end);
25 .ve
26 where
27 + dm - the composite object
28 . J - the constructed matrix, or `NULL`. If provided, the function should fill the existing nonzero pattern with zeros (only `dm` and `rstart` are valid in this case).
29 . dnz - array counting the number of on-diagonal non-zero entries per row, where on-diagonal means that this process owns both the row and column
30 . onz - array counting the number of off-diagonal non-zero entries per row, where off-diagonal means that this process owns the row
31 . rstart - offset into `*nz` arrays, for local row index `r`, update `onz[r - rstart]` or `dnz[r - rstart]`
32 . nrows - number of owned global rows
33 . start - the first owned global index
34 - end - the last owned global index + 1
35
36 If `J` is not `NULL`, then the only other valid parameter is `rstart`
37
38 The user coupling function has a weird and poorly documented interface and is not tested, it should be removed
39
40 .seealso: `DMCOMPOSITE`, `DM`
41 @*/
DMCompositeSetCoupling(DM dm,PetscErrorCode (* FormCoupleLocations)(DM,Mat,PetscInt *,PetscInt *,PetscInt,PetscInt,PetscInt,PetscInt))42 PetscErrorCode DMCompositeSetCoupling(DM dm, PetscErrorCode (*FormCoupleLocations)(DM, Mat, PetscInt *, PetscInt *, PetscInt, PetscInt, PetscInt, PetscInt))
43 {
44 DM_Composite *com = (DM_Composite *)dm->data;
45 PetscBool flg;
46
47 PetscFunctionBegin;
48 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
49 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
50 com->FormCoupleLocations = FormCoupleLocations;
51 PetscFunctionReturn(PETSC_SUCCESS);
52 }
53
DMDestroy_Composite(DM dm)54 static PetscErrorCode DMDestroy_Composite(DM dm)
55 {
56 struct DMCompositeLink *next, *prev;
57 DM_Composite *com = (DM_Composite *)dm->data;
58
59 PetscFunctionBegin;
60 next = com->next;
61 while (next) {
62 prev = next;
63 next = next->next;
64 PetscCall(DMDestroy(&prev->dm));
65 PetscCall(PetscFree(prev->grstarts));
66 PetscCall(PetscFree(prev));
67 }
68 PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", NULL));
69 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */
70 PetscCall(PetscFree(com));
71 PetscFunctionReturn(PETSC_SUCCESS);
72 }
73
DMView_Composite(DM dm,PetscViewer v)74 static PetscErrorCode DMView_Composite(DM dm, PetscViewer v)
75 {
76 PetscBool isascii;
77 DM_Composite *com = (DM_Composite *)dm->data;
78
79 PetscFunctionBegin;
80 PetscCall(PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &isascii));
81 if (isascii) {
82 struct DMCompositeLink *lnk = com->next;
83 PetscInt i;
84
85 PetscCall(PetscViewerASCIIPrintf(v, "DM (%s)\n", ((PetscObject)dm)->prefix ? ((PetscObject)dm)->prefix : "no prefix"));
86 PetscCall(PetscViewerASCIIPrintf(v, " contains %" PetscInt_FMT " DMs\n", com->nDM));
87 PetscCall(PetscViewerASCIIPushTab(v));
88 for (i = 0; lnk; lnk = lnk->next, i++) {
89 PetscCall(PetscViewerASCIIPrintf(v, "Link %" PetscInt_FMT ": DM of type %s\n", i, ((PetscObject)lnk->dm)->type_name));
90 PetscCall(PetscViewerASCIIPushTab(v));
91 PetscCall(DMView(lnk->dm, v));
92 PetscCall(PetscViewerASCIIPopTab(v));
93 }
94 PetscCall(PetscViewerASCIIPopTab(v));
95 }
96 PetscFunctionReturn(PETSC_SUCCESS);
97 }
98
DMSetUp_Composite(DM dm)99 static PetscErrorCode DMSetUp_Composite(DM dm)
100 {
101 PetscInt nprev = 0;
102 PetscMPIInt rank, size;
103 DM_Composite *com = (DM_Composite *)dm->data;
104 struct DMCompositeLink *next = com->next;
105 PetscLayout map;
106
107 PetscFunctionBegin;
108 PetscCheck(!com->setup, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Packer has already been setup");
109 PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &map));
110 PetscCall(PetscLayoutSetLocalSize(map, com->n));
111 PetscCall(PetscLayoutSetSize(map, PETSC_DETERMINE));
112 PetscCall(PetscLayoutSetBlockSize(map, 1));
113 PetscCall(PetscLayoutSetUp(map));
114 PetscCall(PetscLayoutGetSize(map, &com->N));
115 PetscCall(PetscLayoutGetRange(map, &com->rstart, NULL));
116 PetscCall(PetscLayoutDestroy(&map));
117
118 /* now set the rstart for each linked vector */
119 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
120 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size));
121 while (next) {
122 next->rstart = nprev;
123 nprev += next->n;
124 next->grstart = com->rstart + next->rstart;
125 PetscCall(PetscMalloc1(size, &next->grstarts));
126 PetscCallMPI(MPI_Allgather(&next->grstart, 1, MPIU_INT, next->grstarts, 1, MPIU_INT, PetscObjectComm((PetscObject)dm)));
127 next = next->next;
128 }
129 com->setup = PETSC_TRUE;
130 PetscFunctionReturn(PETSC_SUCCESS);
131 }
132
133 /*@
134 DMCompositeGetNumberDM - Gets the number of `DM` objects in the `DMCOMPOSITE`
135 representation.
136
137 Not Collective
138
139 Input Parameter:
140 . dm - the `DMCOMPOSITE` object
141
142 Output Parameter:
143 . nDM - the number of `DM`
144
145 Level: beginner
146
147 .seealso: `DMCOMPOSITE`, `DM`
148 @*/
DMCompositeGetNumberDM(DM dm,PetscInt * nDM)149 PetscErrorCode DMCompositeGetNumberDM(DM dm, PetscInt *nDM)
150 {
151 DM_Composite *com = (DM_Composite *)dm->data;
152 PetscBool flg;
153
154 PetscFunctionBegin;
155 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
156 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
157 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
158 *nDM = com->nDM;
159 PetscFunctionReturn(PETSC_SUCCESS);
160 }
161
162 /*@C
163 DMCompositeGetAccess - Allows one to access the individual packed vectors in their global
164 representation.
165
166 Collective
167
168 Input Parameters:
169 + dm - the `DMCOMPOSITE` object
170 - gvec - the global vector
171
172 Output Parameter:
173 . ... - the packed parallel vectors, `NULL` for those that are not needed
174
175 Level: advanced
176
177 Note:
178 Use `DMCompositeRestoreAccess()` to return the vectors when you no longer need them
179
180 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeGetEntries()`, `DMCompositeScatter()`
181 @*/
DMCompositeGetAccess(DM dm,Vec gvec,...)182 PetscErrorCode DMCompositeGetAccess(DM dm, Vec gvec, ...)
183 {
184 va_list Argp;
185 struct DMCompositeLink *next;
186 DM_Composite *com = (DM_Composite *)dm->data;
187 PetscInt readonly;
188 PetscBool flg;
189
190 PetscFunctionBegin;
191 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
192 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2);
193 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
194 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
195 next = com->next;
196 if (!com->setup) PetscCall(DMSetUp(dm));
197
198 PetscCall(VecLockGet(gvec, &readonly));
199 /* loop over packed objects, handling one at a time */
200 va_start(Argp, gvec);
201 while (next) {
202 Vec *vec;
203 vec = va_arg(Argp, Vec *);
204 if (vec) {
205 PetscCall(DMGetGlobalVector(next->dm, vec));
206 if (readonly) {
207 const PetscScalar *array;
208 PetscCall(VecGetArrayRead(gvec, &array));
209 PetscCall(VecPlaceArray(*vec, array + next->rstart));
210 PetscCall(VecLockReadPush(*vec));
211 PetscCall(VecRestoreArrayRead(gvec, &array));
212 } else {
213 PetscScalar *array;
214 PetscCall(VecGetArray(gvec, &array));
215 PetscCall(VecPlaceArray(*vec, array + next->rstart));
216 PetscCall(VecRestoreArray(gvec, &array));
217 }
218 }
219 next = next->next;
220 }
221 va_end(Argp);
222 PetscFunctionReturn(PETSC_SUCCESS);
223 }
224
225 /*@
226 DMCompositeGetAccessArray - Allows one to access the individual packed vectors in their global
227 representation.
228
229 Collective
230
231 Input Parameters:
232 + dm - the `DMCOMPOSITE`
233 . pvec - packed vector
234 . nwanted - number of vectors wanted
235 - wanted - sorted array of integers indicating thde vectors wanted, or `NULL` to get all vectors, length `nwanted`
236
237 Output Parameter:
238 . vecs - array of requested global vectors (must be previously allocated and of length `nwanted`)
239
240 Level: advanced
241
242 Note:
243 Use `DMCompositeRestoreAccessArray()` to return the vectors when you no longer need them
244
245 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeGetAccess()`, `DMCompositeGetEntries()`, `DMCompositeScatter()`, `DMCompositeGather()`
246 @*/
DMCompositeGetAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt wanted[],Vec vecs[])247 PetscErrorCode DMCompositeGetAccessArray(DM dm, Vec pvec, PetscInt nwanted, const PetscInt wanted[], Vec vecs[])
248 {
249 struct DMCompositeLink *link;
250 PetscInt i, wnum;
251 DM_Composite *com = (DM_Composite *)dm->data;
252 PetscInt readonly;
253 PetscBool flg;
254
255 PetscFunctionBegin;
256 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
257 PetscValidHeaderSpecific(pvec, VEC_CLASSID, 2);
258 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
259 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
260 if (!com->setup) PetscCall(DMSetUp(dm));
261
262 PetscCall(VecLockGet(pvec, &readonly));
263 for (i = 0, wnum = 0, link = com->next; link && wnum < nwanted; i++, link = link->next) {
264 if (!wanted || i == wanted[wnum]) {
265 Vec v;
266 PetscCall(DMGetGlobalVector(link->dm, &v));
267 if (readonly) {
268 const PetscScalar *array;
269 PetscCall(VecGetArrayRead(pvec, &array));
270 PetscCall(VecPlaceArray(v, array + link->rstart));
271 PetscCall(VecLockReadPush(v));
272 PetscCall(VecRestoreArrayRead(pvec, &array));
273 } else {
274 PetscScalar *array;
275 PetscCall(VecGetArray(pvec, &array));
276 PetscCall(VecPlaceArray(v, array + link->rstart));
277 PetscCall(VecRestoreArray(pvec, &array));
278 }
279 vecs[wnum++] = v;
280 }
281 }
282 PetscFunctionReturn(PETSC_SUCCESS);
283 }
284
285 /*@
286 DMCompositeGetLocalAccessArray - Allows one to access the individual
287 packed vectors in their local representation.
288
289 Collective
290
291 Input Parameters:
292 + dm - the `DMCOMPOSITE`
293 . pvec - packed vector
294 . nwanted - number of vectors wanted
295 - wanted - sorted array of vectors wanted, or `NULL` to get all vectors, length `nwanted`
296
297 Output Parameter:
298 . vecs - array of requested local vectors (must be allocated and of length `nwanted`)
299
300 Level: advanced
301
302 Note:
303 Use `DMCompositeRestoreLocalAccessArray()` to return the vectors
304 when you no longer need them.
305
306 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeRestoreLocalAccessArray()`, `DMCompositeGetAccess()`,
307 `DMCompositeGetEntries()`, `DMCompositeScatter()`, `DMCompositeGather()`
308 @*/
DMCompositeGetLocalAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt wanted[],Vec vecs[])309 PetscErrorCode DMCompositeGetLocalAccessArray(DM dm, Vec pvec, PetscInt nwanted, const PetscInt wanted[], Vec vecs[])
310 {
311 struct DMCompositeLink *link;
312 PetscInt i, wnum;
313 DM_Composite *com = (DM_Composite *)dm->data;
314 PetscInt readonly;
315 PetscInt nlocal = 0;
316 PetscBool flg;
317
318 PetscFunctionBegin;
319 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
320 PetscValidHeaderSpecific(pvec, VEC_CLASSID, 2);
321 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
322 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
323 if (!com->setup) PetscCall(DMSetUp(dm));
324
325 PetscCall(VecLockGet(pvec, &readonly));
326 for (i = 0, wnum = 0, link = com->next; link && wnum < nwanted; i++, link = link->next) {
327 if (!wanted || i == wanted[wnum]) {
328 Vec v;
329 PetscCall(DMGetLocalVector(link->dm, &v));
330 if (readonly) {
331 const PetscScalar *array;
332 PetscCall(VecGetArrayRead(pvec, &array));
333 PetscCall(VecPlaceArray(v, array + nlocal));
334 // this method does not make sense. The local vectors are not updated with a global-to-local and the user can not do it because it is locked
335 PetscCall(VecLockReadPush(v));
336 PetscCall(VecRestoreArrayRead(pvec, &array));
337 } else {
338 PetscScalar *array;
339 PetscCall(VecGetArray(pvec, &array));
340 PetscCall(VecPlaceArray(v, array + nlocal));
341 PetscCall(VecRestoreArray(pvec, &array));
342 }
343 vecs[wnum++] = v;
344 }
345
346 nlocal += link->nlocal;
347 }
348 PetscFunctionReturn(PETSC_SUCCESS);
349 }
350
351 /*@C
352 DMCompositeRestoreAccess - Returns the vectors obtained with `DMCompositeGetAccess()`
353 representation.
354
355 Collective
356
357 Input Parameters:
358 + dm - the `DMCOMPOSITE` object
359 . gvec - the global vector
360 - ... - the individual parallel vectors, `NULL` for those that are not needed
361
362 Level: advanced
363
364 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
365 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeScatter()`,
366 `DMCompositeGetAccess()`
367 @*/
DMCompositeRestoreAccess(DM dm,Vec gvec,...)368 PetscErrorCode DMCompositeRestoreAccess(DM dm, Vec gvec, ...)
369 {
370 va_list Argp;
371 struct DMCompositeLink *next;
372 DM_Composite *com = (DM_Composite *)dm->data;
373 PetscInt readonly;
374 PetscBool flg;
375
376 PetscFunctionBegin;
377 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
378 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2);
379 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
380 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
381 next = com->next;
382 if (!com->setup) PetscCall(DMSetUp(dm));
383
384 PetscCall(VecLockGet(gvec, &readonly));
385 /* loop over packed objects, handling one at a time */
386 va_start(Argp, gvec);
387 while (next) {
388 Vec *vec;
389 vec = va_arg(Argp, Vec *);
390 if (vec) {
391 PetscCall(VecResetArray(*vec));
392 if (readonly) PetscCall(VecLockReadPop(*vec));
393 PetscCall(DMRestoreGlobalVector(next->dm, vec));
394 }
395 next = next->next;
396 }
397 va_end(Argp);
398 PetscFunctionReturn(PETSC_SUCCESS);
399 }
400
401 /*@
402 DMCompositeRestoreAccessArray - Returns the vectors obtained with `DMCompositeGetAccessArray()`
403
404 Collective
405
406 Input Parameters:
407 + dm - the `DMCOMPOSITE` object
408 . pvec - packed vector
409 . nwanted - number of vectors wanted
410 . wanted - sorted array of vectors wanted, or `NULL` to restore all vectors
411 - vecs - array of global vectors
412
413 Level: advanced
414
415 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeRestoreAccess()`, `DMCompositeRestoreEntries()`, `DMCompositeScatter()`, `DMCompositeGather()`
416 @*/
DMCompositeRestoreAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt wanted[],Vec vecs[])417 PetscErrorCode DMCompositeRestoreAccessArray(DM dm, Vec pvec, PetscInt nwanted, const PetscInt wanted[], Vec vecs[])
418 {
419 struct DMCompositeLink *link;
420 PetscInt i, wnum;
421 DM_Composite *com = (DM_Composite *)dm->data;
422 PetscInt readonly;
423 PetscBool flg;
424
425 PetscFunctionBegin;
426 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
427 PetscValidHeaderSpecific(pvec, VEC_CLASSID, 2);
428 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
429 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
430 if (!com->setup) PetscCall(DMSetUp(dm));
431
432 PetscCall(VecLockGet(pvec, &readonly));
433 for (i = 0, wnum = 0, link = com->next; link && wnum < nwanted; i++, link = link->next) {
434 if (!wanted || i == wanted[wnum]) {
435 PetscCall(VecResetArray(vecs[wnum]));
436 if (readonly) PetscCall(VecLockReadPop(vecs[wnum]));
437 PetscCall(DMRestoreGlobalVector(link->dm, &vecs[wnum]));
438 wnum++;
439 }
440 }
441 PetscFunctionReturn(PETSC_SUCCESS);
442 }
443
444 /*@
445 DMCompositeRestoreLocalAccessArray - Returns the vectors obtained with `DMCompositeGetLocalAccessArray()`.
446
447 Collective
448
449 Input Parameters:
450 + dm - the `DMCOMPOSITE` object
451 . pvec - packed vector
452 . nwanted - number of vectors wanted
453 . wanted - sorted array of vectors wanted, or `NULL` to restore all vectors
454 - vecs - array of local vectors
455
456 Level: advanced
457
458 Note:
459 `nwanted` and `wanted` must match the values given to `DMCompositeGetLocalAccessArray()`
460 otherwise the call will fail.
461
462 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeGetLocalAccessArray()`, `DMCompositeRestoreAccessArray()`,
463 `DMCompositeRestoreAccess()`, `DMCompositeRestoreEntries()`,
464 `DMCompositeScatter()`, `DMCompositeGather()`
465 @*/
DMCompositeRestoreLocalAccessArray(DM dm,Vec pvec,PetscInt nwanted,const PetscInt wanted[],Vec * vecs)466 PetscErrorCode DMCompositeRestoreLocalAccessArray(DM dm, Vec pvec, PetscInt nwanted, const PetscInt wanted[], Vec *vecs)
467 {
468 struct DMCompositeLink *link;
469 PetscInt i, wnum;
470 DM_Composite *com = (DM_Composite *)dm->data;
471 PetscInt readonly;
472 PetscBool flg;
473
474 PetscFunctionBegin;
475 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
476 PetscValidHeaderSpecific(pvec, VEC_CLASSID, 2);
477 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
478 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
479 if (!com->setup) PetscCall(DMSetUp(dm));
480
481 PetscCall(VecLockGet(pvec, &readonly));
482 for (i = 0, wnum = 0, link = com->next; link && wnum < nwanted; i++, link = link->next) {
483 if (!wanted || i == wanted[wnum]) {
484 PetscCall(VecResetArray(vecs[wnum]));
485 if (readonly) PetscCall(VecLockReadPop(vecs[wnum]));
486 PetscCall(DMRestoreLocalVector(link->dm, &vecs[wnum]));
487 wnum++;
488 }
489 }
490 PetscFunctionReturn(PETSC_SUCCESS);
491 }
492
493 /*@C
494 DMCompositeScatter - Scatters from a global packed vector into its individual local vectors
495
496 Collective
497
498 Input Parameters:
499 + dm - the `DMCOMPOSITE` object
500 . gvec - the global vector
501 - ... - the individual sequential vectors, `NULL` for those that are not needed
502
503 Level: advanced
504
505 Note:
506 `DMCompositeScatterArray()` is a non-variadic alternative that is often more convenient for library callers and is
507 accessible from Fortran.
508
509 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
510 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
511 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
512 `DMCompositeScatterArray()`
513 @*/
DMCompositeScatter(DM dm,Vec gvec,...)514 PetscErrorCode DMCompositeScatter(DM dm, Vec gvec, ...)
515 {
516 va_list Argp;
517 struct DMCompositeLink *next;
518 PETSC_UNUSED PetscInt cnt;
519 DM_Composite *com = (DM_Composite *)dm->data;
520 PetscBool flg;
521
522 PetscFunctionBegin;
523 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
524 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2);
525 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
526 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
527 if (!com->setup) PetscCall(DMSetUp(dm));
528
529 /* loop over packed objects, handling one at a time */
530 va_start(Argp, gvec);
531 for (cnt = 3, next = com->next; next; cnt++, next = next->next) {
532 Vec local;
533 local = va_arg(Argp, Vec);
534 if (local) {
535 Vec global;
536 const PetscScalar *array;
537 PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidHeaderSpecific(local, VEC_CLASSID, (int)cnt));
538 PetscCall(DMGetGlobalVector(next->dm, &global));
539 PetscCall(VecGetArrayRead(gvec, &array));
540 PetscCall(VecPlaceArray(global, array + next->rstart));
541 PetscCall(DMGlobalToLocalBegin(next->dm, global, INSERT_VALUES, local));
542 PetscCall(DMGlobalToLocalEnd(next->dm, global, INSERT_VALUES, local));
543 PetscCall(VecRestoreArrayRead(gvec, &array));
544 PetscCall(VecResetArray(global));
545 PetscCall(DMRestoreGlobalVector(next->dm, &global));
546 }
547 }
548 va_end(Argp);
549 PetscFunctionReturn(PETSC_SUCCESS);
550 }
551
552 /*@
553 DMCompositeScatterArray - Scatters from a global packed vector into its individual local vectors
554
555 Collective
556
557 Input Parameters:
558 + dm - the `DMCOMPOSITE` object
559 . gvec - the global vector
560 - lvecs - array of local vectors, NULL for any that are not needed
561
562 Level: advanced
563
564 Note:
565 This is a non-variadic alternative to `DMCompositeScatter()`
566
567 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`
568 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
569 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
570 @*/
DMCompositeScatterArray(DM dm,Vec gvec,Vec * lvecs)571 PetscErrorCode DMCompositeScatterArray(DM dm, Vec gvec, Vec *lvecs)
572 {
573 struct DMCompositeLink *next;
574 PetscInt i;
575 DM_Composite *com = (DM_Composite *)dm->data;
576 PetscBool flg;
577
578 PetscFunctionBegin;
579 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
580 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2);
581 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
582 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
583 if (!com->setup) PetscCall(DMSetUp(dm));
584
585 /* loop over packed objects, handling one at a time */
586 for (i = 0, next = com->next; next; next = next->next, i++) {
587 if (lvecs[i]) {
588 Vec global;
589 const PetscScalar *array;
590 PetscValidHeaderSpecific(lvecs[i], VEC_CLASSID, 3);
591 PetscCall(DMGetGlobalVector(next->dm, &global));
592 PetscCall(VecGetArrayRead(gvec, &array));
593 PetscCall(VecPlaceArray(global, (PetscScalar *)array + next->rstart));
594 PetscCall(DMGlobalToLocalBegin(next->dm, global, INSERT_VALUES, lvecs[i]));
595 PetscCall(DMGlobalToLocalEnd(next->dm, global, INSERT_VALUES, lvecs[i]));
596 PetscCall(VecRestoreArrayRead(gvec, &array));
597 PetscCall(VecResetArray(global));
598 PetscCall(DMRestoreGlobalVector(next->dm, &global));
599 }
600 }
601 PetscFunctionReturn(PETSC_SUCCESS);
602 }
603
604 /*@C
605 DMCompositeGather - Gathers into a global packed vector from its individual local vectors
606
607 Collective
608
609 Input Parameters:
610 + dm - the `DMCOMPOSITE` object
611 . imode - `INSERT_VALUES` or `ADD_VALUES`
612 . gvec - the global vector
613 - ... - the individual sequential vectors, `NULL` for any that are not needed
614
615 Level: advanced
616
617 Fortran Notes:
618 Fortran users should use `DMCompositeGatherArray()`
619
620 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
621 `DMCompositeScatter()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
622 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
623 @*/
DMCompositeGather(DM dm,InsertMode imode,Vec gvec,...)624 PetscErrorCode DMCompositeGather(DM dm, InsertMode imode, Vec gvec, ...)
625 {
626 va_list Argp;
627 struct DMCompositeLink *next;
628 DM_Composite *com = (DM_Composite *)dm->data;
629 PETSC_UNUSED PetscInt cnt;
630 PetscBool flg;
631
632 PetscFunctionBegin;
633 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
634 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 3);
635 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
636 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
637 if (!com->setup) PetscCall(DMSetUp(dm));
638
639 /* loop over packed objects, handling one at a time */
640 va_start(Argp, gvec);
641 for (cnt = 3, next = com->next; next; cnt++, next = next->next) {
642 Vec local;
643 local = va_arg(Argp, Vec);
644 if (local) {
645 PetscScalar *array;
646 Vec global;
647 PetscDisableStaticAnalyzerForExpressionUnderstandingThatThisIsDangerousAndBugprone(PetscValidHeaderSpecific(local, VEC_CLASSID, (int)cnt));
648 PetscCall(DMGetGlobalVector(next->dm, &global));
649 PetscCall(VecGetArray(gvec, &array));
650 PetscCall(VecPlaceArray(global, array + next->rstart));
651 PetscCall(DMLocalToGlobalBegin(next->dm, local, imode, global));
652 PetscCall(DMLocalToGlobalEnd(next->dm, local, imode, global));
653 PetscCall(VecRestoreArray(gvec, &array));
654 PetscCall(VecResetArray(global));
655 PetscCall(DMRestoreGlobalVector(next->dm, &global));
656 }
657 }
658 va_end(Argp);
659 PetscFunctionReturn(PETSC_SUCCESS);
660 }
661
662 /*@
663 DMCompositeGatherArray - Gathers into a global packed vector from its individual local vectors
664
665 Collective
666
667 Input Parameters:
668 + dm - the `DMCOMPOSITE` object
669 . gvec - the global vector
670 . imode - `INSERT_VALUES` or `ADD_VALUES`
671 - lvecs - the individual sequential vectors, NULL for any that are not needed
672
673 Level: advanced
674
675 Note:
676 This is a non-variadic alternative to `DMCompositeGather()`.
677
678 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
679 `DMCompositeScatter()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
680 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`,
681 @*/
DMCompositeGatherArray(DM dm,InsertMode imode,Vec gvec,Vec * lvecs)682 PetscErrorCode DMCompositeGatherArray(DM dm, InsertMode imode, Vec gvec, Vec *lvecs)
683 {
684 struct DMCompositeLink *next;
685 DM_Composite *com = (DM_Composite *)dm->data;
686 PetscInt i;
687 PetscBool flg;
688
689 PetscFunctionBegin;
690 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
691 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 3);
692 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
693 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
694 if (!com->setup) PetscCall(DMSetUp(dm));
695
696 /* loop over packed objects, handling one at a time */
697 for (next = com->next, i = 0; next; next = next->next, i++) {
698 if (lvecs[i]) {
699 PetscScalar *array;
700 Vec global;
701 PetscValidHeaderSpecific(lvecs[i], VEC_CLASSID, 4);
702 PetscCall(DMGetGlobalVector(next->dm, &global));
703 PetscCall(VecGetArray(gvec, &array));
704 PetscCall(VecPlaceArray(global, array + next->rstart));
705 PetscCall(DMLocalToGlobalBegin(next->dm, lvecs[i], imode, global));
706 PetscCall(DMLocalToGlobalEnd(next->dm, lvecs[i], imode, global));
707 PetscCall(VecRestoreArray(gvec, &array));
708 PetscCall(VecResetArray(global));
709 PetscCall(DMRestoreGlobalVector(next->dm, &global));
710 }
711 }
712 PetscFunctionReturn(PETSC_SUCCESS);
713 }
714
715 /*@
716 DMCompositeAddDM - adds a `DM` vector to a `DMCOMPOSITE`
717
718 Collective
719
720 Input Parameters:
721 + dmc - the `DMCOMPOSITE` object
722 - dm - the `DM` object
723
724 Level: advanced
725
726 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeGather()`, `DMCreateGlobalVector()`,
727 `DMCompositeScatter()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
728 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
729 @*/
DMCompositeAddDM(DM dmc,DM dm)730 PetscErrorCode DMCompositeAddDM(DM dmc, DM dm)
731 {
732 PetscInt n, nlocal;
733 struct DMCompositeLink *mine, *next;
734 Vec global, local;
735 DM_Composite *com = (DM_Composite *)dmc->data;
736 PetscBool flg;
737
738 PetscFunctionBegin;
739 PetscValidHeaderSpecific(dmc, DM_CLASSID, 1);
740 PetscValidHeaderSpecific(dm, DM_CLASSID, 2);
741 PetscCall(PetscObjectTypeCompare((PetscObject)dmc, DMCOMPOSITE, &flg));
742 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
743 next = com->next;
744 PetscCheck(!com->setup, PetscObjectComm((PetscObject)dmc), PETSC_ERR_ARG_WRONGSTATE, "Cannot add a DM once you have used the DMComposite");
745
746 /* create new link */
747 PetscCall(PetscNew(&mine));
748 PetscCall(PetscObjectReference((PetscObject)dm));
749 PetscCall(DMCreateGlobalVector(dm, &global)); // Not using DMGetGlobalVector() since it will stash the vector with a type decided by dm,
750 PetscCall(VecGetLocalSize(global, &n)); // while we may want to set dmc's vectype later, say via DMSetFromOptions(dmc), and we
751 PetscCall(VecDestroy(&global)); // want to propagate the type to dm.
752 PetscCall(DMCreateLocalVector(dm, &local)); // Not using DMGetLocalVector(), same reason as above.
753 PetscCall(VecGetSize(local, &nlocal));
754 PetscCall(VecDestroy(&local));
755
756 mine->n = n;
757 mine->nlocal = nlocal;
758 mine->dm = dm;
759 mine->next = NULL;
760 com->n += n;
761 com->nghost += nlocal;
762
763 /* add to end of list */
764 if (!next) com->next = mine;
765 else {
766 while (next->next) next = next->next;
767 next->next = mine;
768 }
769 com->nDM++;
770 com->nmine++;
771 PetscFunctionReturn(PETSC_SUCCESS);
772 }
773
774 #include <petscdraw.h>
775 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
776
VecView_DMComposite(Vec gvec,PetscViewer viewer)777 static PetscErrorCode VecView_DMComposite(Vec gvec, PetscViewer viewer)
778 {
779 DM dm;
780 struct DMCompositeLink *next;
781 PetscBool isdraw;
782 DM_Composite *com;
783
784 PetscFunctionBegin;
785 PetscCall(VecGetDM(gvec, &dm));
786 PetscCheck(dm, PetscObjectComm((PetscObject)gvec), PETSC_ERR_ARG_WRONG, "Vector not generated from a DMComposite");
787 com = (DM_Composite *)dm->data;
788 next = com->next;
789
790 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
791 if (!isdraw) {
792 /* do I really want to call this? */
793 PetscCall(VecView_MPI(gvec, viewer));
794 } else {
795 PetscInt cnt = 0;
796
797 /* loop over packed objects, handling one at a time */
798 while (next) {
799 Vec vec;
800 const PetscScalar *array;
801 PetscInt bs;
802
803 /* Should use VecGetSubVector() eventually, but would need to forward the DM for that to work */
804 PetscCall(DMGetGlobalVector(next->dm, &vec));
805 PetscCall(VecGetArrayRead(gvec, &array));
806 PetscCall(VecPlaceArray(vec, (PetscScalar *)array + next->rstart));
807 PetscCall(VecRestoreArrayRead(gvec, &array));
808 PetscCall(VecView(vec, viewer));
809 PetscCall(VecResetArray(vec));
810 PetscCall(VecGetBlockSize(vec, &bs));
811 PetscCall(DMRestoreGlobalVector(next->dm, &vec));
812 PetscCall(PetscViewerDrawBaseAdd(viewer, bs));
813 cnt += bs;
814 next = next->next;
815 }
816 PetscCall(PetscViewerDrawBaseAdd(viewer, -cnt));
817 }
818 PetscFunctionReturn(PETSC_SUCCESS);
819 }
820
DMCreateGlobalVector_Composite(DM dm,Vec * gvec)821 static PetscErrorCode DMCreateGlobalVector_Composite(DM dm, Vec *gvec)
822 {
823 DM_Composite *com = (DM_Composite *)dm->data;
824
825 PetscFunctionBegin;
826 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
827 PetscCall(DMSetFromOptions(dm));
828 PetscCall(DMSetUp(dm));
829 PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), gvec));
830 PetscCall(VecSetType(*gvec, dm->vectype));
831 PetscCall(VecSetSizes(*gvec, com->n, com->N));
832 PetscCall(VecSetDM(*gvec, dm));
833 PetscCall(VecSetOperation(*gvec, VECOP_VIEW, (PetscErrorCodeFn *)VecView_DMComposite));
834 PetscFunctionReturn(PETSC_SUCCESS);
835 }
836
DMCreateLocalVector_Composite(DM dm,Vec * lvec)837 static PetscErrorCode DMCreateLocalVector_Composite(DM dm, Vec *lvec)
838 {
839 DM_Composite *com = (DM_Composite *)dm->data;
840
841 PetscFunctionBegin;
842 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
843 if (!com->setup) {
844 PetscCall(DMSetFromOptions(dm));
845 PetscCall(DMSetUp(dm));
846 }
847 PetscCall(VecCreate(PETSC_COMM_SELF, lvec));
848 PetscCall(VecSetType(*lvec, dm->vectype));
849 PetscCall(VecSetSizes(*lvec, com->nghost, PETSC_DECIDE));
850 PetscCall(VecSetDM(*lvec, dm));
851 PetscFunctionReturn(PETSC_SUCCESS);
852 }
853
854 /*@C
855 DMCompositeGetISLocalToGlobalMappings - gets an `ISLocalToGlobalMapping` for each `DM` in the `DMCOMPOSITE`, maps to the composite global space
856
857 Collective; No Fortran Support
858
859 Input Parameter:
860 . dm - the `DMCOMPOSITE` object
861
862 Output Parameter:
863 . ltogs - the individual mappings for each packed vector. Note that this includes
864 all the ghost points that individual ghosted `DMDA` may have.
865
866 Level: advanced
867
868 Note:
869 Each entry of `ltogs` should be destroyed with `ISLocalToGlobalMappingDestroy()`, `ltogs` should be freed with `PetscFree()`.
870
871 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
872 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetAccess()`, `DMCompositeScatter()`,
873 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
874 @*/
DMCompositeGetISLocalToGlobalMappings(DM dm,ISLocalToGlobalMapping * ltogs[])875 PetscErrorCode DMCompositeGetISLocalToGlobalMappings(DM dm, ISLocalToGlobalMapping *ltogs[])
876 {
877 PetscInt i, *idx, n, cnt;
878 struct DMCompositeLink *next;
879 PetscMPIInt rank;
880 DM_Composite *com = (DM_Composite *)dm->data;
881 PetscBool flg;
882
883 PetscFunctionBegin;
884 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
885 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
886 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
887 PetscCall(DMSetUp(dm));
888 PetscCall(PetscMalloc1(com->nDM, ltogs));
889 next = com->next;
890 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
891
892 /* loop over packed objects, handling one at a time */
893 cnt = 0;
894 while (next) {
895 ISLocalToGlobalMapping ltog;
896 PetscMPIInt size;
897 const PetscInt *suboff, *indices;
898 Vec global;
899
900 /* Get sub-DM global indices for each local dof */
901 PetscCall(DMGetLocalToGlobalMapping(next->dm, <og));
902 PetscCall(ISLocalToGlobalMappingGetSize(ltog, &n));
903 PetscCall(ISLocalToGlobalMappingGetIndices(ltog, &indices));
904 PetscCall(PetscMalloc1(n, &idx));
905
906 /* Get the offsets for the sub-DM global vector */
907 PetscCall(DMGetGlobalVector(next->dm, &global));
908 PetscCall(VecGetOwnershipRanges(global, &suboff));
909 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)global), &size));
910
911 /* Shift the sub-DM definition of the global space to the composite global space */
912 for (i = 0; i < n; i++) {
913 PetscInt subi = indices[i], lo = 0, hi = size, t;
914 /* There's no consensus on what a negative index means,
915 except for skipping when setting the values in vectors and matrices */
916 if (subi < 0) {
917 idx[i] = subi - next->grstarts[rank];
918 continue;
919 }
920 /* Binary search to find which rank owns subi */
921 while (hi - lo > 1) {
922 t = lo + (hi - lo) / 2;
923 if (suboff[t] > subi) hi = t;
924 else lo = t;
925 }
926 idx[i] = subi - suboff[lo] + next->grstarts[lo];
927 }
928 PetscCall(ISLocalToGlobalMappingRestoreIndices(ltog, &indices));
929 PetscCall(ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)dm), 1, n, idx, PETSC_OWN_POINTER, &(*ltogs)[cnt]));
930 PetscCall(DMRestoreGlobalVector(next->dm, &global));
931 next = next->next;
932 cnt++;
933 }
934 PetscFunctionReturn(PETSC_SUCCESS);
935 }
936
937 /*@C
938 DMCompositeGetLocalISs - Gets index sets for each component of a composite local vector
939
940 Not Collective; No Fortran Support
941
942 Input Parameter:
943 . dm - the `DMCOMPOSITE`
944
945 Output Parameter:
946 . is - array of serial index sets for each component of the `DMCOMPOSITE`
947
948 Level: intermediate
949
950 Notes:
951 At present, a composite local vector does not normally exist. This function is used to provide index sets for
952 `MatGetLocalSubMatrix()`. In the future, the scatters for each entry in the `DMCOMPOSITE` may be merged into a single
953 scatter to a composite local vector. The user should not typically need to know which is being done.
954
955 To get the composite global indices at all local points (including ghosts), use `DMCompositeGetISLocalToGlobalMappings()`.
956
957 To get index sets for pieces of the composite global vector, use `DMCompositeGetGlobalISs()`.
958
959 Each returned `IS` should be destroyed with `ISDestroy()`, the array should be freed with `PetscFree()`.
960
961 Fortran Note:
962 Use `DMCompositeRestoreLocalISs()` to release the `is`.
963
964 .seealso: `DMCOMPOSITE`, `DM`, `DMCompositeGetGlobalISs()`, `DMCompositeGetISLocalToGlobalMappings()`, `MatGetLocalSubMatrix()`,
965 `MatCreateLocalRef()`, `DMCompositeGetNumberDM()`
966 @*/
DMCompositeGetLocalISs(DM dm,IS * is[])967 PetscErrorCode DMCompositeGetLocalISs(DM dm, IS *is[])
968 {
969 DM_Composite *com = (DM_Composite *)dm->data;
970 struct DMCompositeLink *link;
971 PetscInt cnt, start;
972 PetscBool flg;
973
974 PetscFunctionBegin;
975 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
976 PetscAssertPointer(is, 2);
977 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
978 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
979 PetscCall(PetscMalloc1(com->nmine, is));
980 for (cnt = 0, start = 0, link = com->next; link; start += link->nlocal, cnt++, link = link->next) {
981 PetscInt bs;
982 PetscCall(ISCreateStride(PETSC_COMM_SELF, link->nlocal, start, 1, &(*is)[cnt]));
983 PetscCall(DMGetBlockSize(link->dm, &bs));
984 PetscCall(ISSetBlockSize((*is)[cnt], bs));
985 }
986 PetscFunctionReturn(PETSC_SUCCESS);
987 }
988
989 /*@C
990 DMCompositeGetGlobalISs - Gets the index sets for each composed object in a `DMCOMPOSITE`
991
992 Collective
993
994 Input Parameter:
995 . dm - the `DMCOMPOSITE` object
996
997 Output Parameter:
998 . is - the array of index sets
999
1000 Level: advanced
1001
1002 Notes:
1003 The `is` entries should be destroyed with `ISDestroy()`, `is` should be freed with `PetscFree()`
1004
1005 These could be used to extract a subset of vector entries for a "multi-physics" preconditioner
1006
1007 Use `DMCompositeGetLocalISs()` for index sets in the packed local numbering, and
1008 `DMCompositeGetISLocalToGlobalMappings()` for to map local sub-`DM` (including ghost) indices to packed global
1009 indices.
1010
1011 Fortran Note:
1012 Use `DMCompositeRestoreGlobalISs()` to release the `is`.
1013
1014 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
1015 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetAccess()`, `DMCompositeScatter()`,
1016 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
1017 @*/
DMCompositeGetGlobalISs(DM dm,IS * is[])1018 PetscErrorCode DMCompositeGetGlobalISs(DM dm, IS *is[])
1019 {
1020 PetscInt cnt = 0;
1021 struct DMCompositeLink *next;
1022 PetscMPIInt rank;
1023 DM_Composite *com = (DM_Composite *)dm->data;
1024 PetscBool flg;
1025
1026 PetscFunctionBegin;
1027 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1028 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
1029 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
1030 PetscCheck(dm->setupcalled, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Must call DMSetUp() before");
1031 PetscCall(PetscMalloc1(com->nDM, is));
1032 next = com->next;
1033 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1034
1035 /* loop over packed objects, handling one at a time */
1036 while (next) {
1037 PetscDS prob;
1038
1039 PetscCall(ISCreateStride(PetscObjectComm((PetscObject)dm), next->n, next->grstart, 1, &(*is)[cnt]));
1040 PetscCall(DMGetDS(dm, &prob));
1041 if (prob) {
1042 MatNullSpace space;
1043 Mat pmat;
1044 PetscObject disc;
1045 PetscInt Nf;
1046
1047 PetscCall(PetscDSGetNumFields(prob, &Nf));
1048 if (cnt < Nf) {
1049 PetscCall(PetscDSGetDiscretization(prob, cnt, &disc));
1050 PetscCall(PetscObjectQuery(disc, "nullspace", (PetscObject *)&space));
1051 if (space) PetscCall(PetscObjectCompose((PetscObject)(*is)[cnt], "nullspace", (PetscObject)space));
1052 PetscCall(PetscObjectQuery(disc, "nearnullspace", (PetscObject *)&space));
1053 if (space) PetscCall(PetscObjectCompose((PetscObject)(*is)[cnt], "nearnullspace", (PetscObject)space));
1054 PetscCall(PetscObjectQuery(disc, "pmat", (PetscObject *)&pmat));
1055 if (pmat) PetscCall(PetscObjectCompose((PetscObject)(*is)[cnt], "pmat", (PetscObject)pmat));
1056 }
1057 }
1058 cnt++;
1059 next = next->next;
1060 }
1061 PetscFunctionReturn(PETSC_SUCCESS);
1062 }
1063
DMCreateFieldIS_Composite(DM dm,PetscInt * numFields,char *** fieldNames,IS ** fields)1064 static PetscErrorCode DMCreateFieldIS_Composite(DM dm, PetscInt *numFields, char ***fieldNames, IS **fields)
1065 {
1066 PetscInt nDM;
1067 DM *dms;
1068 PetscInt i;
1069
1070 PetscFunctionBegin;
1071 PetscCall(DMCompositeGetNumberDM(dm, &nDM));
1072 if (numFields) *numFields = nDM;
1073 PetscCall(DMCompositeGetGlobalISs(dm, fields));
1074 if (fieldNames) {
1075 PetscCall(PetscMalloc1(nDM, &dms));
1076 PetscCall(PetscMalloc1(nDM, fieldNames));
1077 PetscCall(DMCompositeGetEntriesArray(dm, dms));
1078 for (i = 0; i < nDM; i++) {
1079 char buf[256];
1080 const char *splitname;
1081
1082 /* Split naming precedence: object name, prefix, number */
1083 splitname = ((PetscObject)dm)->name;
1084 if (!splitname) {
1085 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dms[i], &splitname));
1086 if (splitname) {
1087 size_t len;
1088 PetscCall(PetscStrncpy(buf, splitname, sizeof(buf)));
1089 buf[sizeof(buf) - 1] = 0;
1090 PetscCall(PetscStrlen(buf, &len));
1091 if (buf[len - 1] == '_') buf[len - 1] = 0; /* Remove trailing underscore if it was used */
1092 splitname = buf;
1093 }
1094 }
1095 if (!splitname) {
1096 PetscCall(PetscSNPrintf(buf, sizeof(buf), "%" PetscInt_FMT, i));
1097 splitname = buf;
1098 }
1099 PetscCall(PetscStrallocpy(splitname, &(*fieldNames)[i]));
1100 }
1101 PetscCall(PetscFree(dms));
1102 }
1103 PetscFunctionReturn(PETSC_SUCCESS);
1104 }
1105
1106 /*
1107 This could take over from DMCreateFieldIS(), as it is more general,
1108 making DMCreateFieldIS() a special case -- calling with dmlist == NULL;
1109 At this point it's probably best to be less intrusive, however.
1110 */
DMCreateFieldDecomposition_Composite(DM dm,PetscInt * len,char *** namelist,IS ** islist,DM ** dmlist)1111 static PetscErrorCode DMCreateFieldDecomposition_Composite(DM dm, PetscInt *len, char ***namelist, IS **islist, DM **dmlist)
1112 {
1113 PetscInt nDM;
1114 PetscInt i;
1115
1116 PetscFunctionBegin;
1117 PetscCall(DMCreateFieldIS_Composite(dm, len, namelist, islist));
1118 if (dmlist) {
1119 PetscCall(DMCompositeGetNumberDM(dm, &nDM));
1120 PetscCall(PetscMalloc1(nDM, dmlist));
1121 PetscCall(DMCompositeGetEntriesArray(dm, *dmlist));
1122 for (i = 0; i < nDM; i++) PetscCall(PetscObjectReference((PetscObject)((*dmlist)[i])));
1123 }
1124 PetscFunctionReturn(PETSC_SUCCESS);
1125 }
1126
1127 /*@C
1128 DMCompositeGetLocalVectors - Gets local vectors for each part of a `DMCOMPOSITE`
1129 Use `DMCompositeRestoreLocalVectors()` to return them.
1130
1131 Not Collective; No Fortran Support
1132
1133 Input Parameter:
1134 . dm - the `DMCOMPOSITE` object
1135
1136 Output Parameter:
1137 . ... - the individual sequential `Vec`s
1138
1139 Level: advanced
1140
1141 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
1142 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
1143 `DMCompositeRestoreLocalVectors()`, `DMCompositeScatter()`, `DMCompositeGetEntries()`
1144 @*/
DMCompositeGetLocalVectors(DM dm,...)1145 PetscErrorCode DMCompositeGetLocalVectors(DM dm, ...)
1146 {
1147 va_list Argp;
1148 struct DMCompositeLink *next;
1149 DM_Composite *com = (DM_Composite *)dm->data;
1150 PetscBool flg;
1151
1152 PetscFunctionBegin;
1153 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1154 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
1155 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
1156 next = com->next;
1157 /* loop over packed objects, handling one at a time */
1158 va_start(Argp, dm);
1159 while (next) {
1160 Vec *vec;
1161 vec = va_arg(Argp, Vec *);
1162 if (vec) PetscCall(DMGetLocalVector(next->dm, vec));
1163 next = next->next;
1164 }
1165 va_end(Argp);
1166 PetscFunctionReturn(PETSC_SUCCESS);
1167 }
1168
1169 /*@C
1170 DMCompositeRestoreLocalVectors - Restores local vectors for each part of a `DMCOMPOSITE`
1171
1172 Not Collective; No Fortran Support
1173
1174 Input Parameter:
1175 . dm - the `DMCOMPOSITE` object
1176
1177 Output Parameter:
1178 . ... - the individual sequential `Vec`
1179
1180 Level: advanced
1181
1182 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`,
1183 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
1184 `DMCompositeGetLocalVectors()`, `DMCompositeScatter()`, `DMCompositeGetEntries()`
1185 @*/
DMCompositeRestoreLocalVectors(DM dm,...)1186 PetscErrorCode DMCompositeRestoreLocalVectors(DM dm, ...)
1187 {
1188 va_list Argp;
1189 struct DMCompositeLink *next;
1190 DM_Composite *com = (DM_Composite *)dm->data;
1191 PetscBool flg;
1192
1193 PetscFunctionBegin;
1194 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1195 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
1196 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
1197 next = com->next;
1198 /* loop over packed objects, handling one at a time */
1199 va_start(Argp, dm);
1200 while (next) {
1201 Vec *vec;
1202 vec = va_arg(Argp, Vec *);
1203 if (vec) PetscCall(DMRestoreLocalVector(next->dm, vec));
1204 next = next->next;
1205 }
1206 va_end(Argp);
1207 PetscFunctionReturn(PETSC_SUCCESS);
1208 }
1209
1210 /*@C
1211 DMCompositeGetEntries - Gets the `DM` for each entry in a `DMCOMPOSITE`.
1212
1213 Not Collective
1214
1215 Input Parameter:
1216 . dm - the `DMCOMPOSITE` object
1217
1218 Output Parameter:
1219 . ... - the individual entries `DM`
1220
1221 Level: advanced
1222
1223 Fortran Notes:
1224 Use `DMCompositeGetEntriesArray()`
1225
1226 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, `DMCompositeGetEntriesArray()`
1227 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
1228 `DMCompositeRestoreLocalVectors()`, `DMCompositeGetLocalVectors()`, `DMCompositeScatter()`
1229 @*/
DMCompositeGetEntries(DM dm,...)1230 PetscErrorCode DMCompositeGetEntries(DM dm, ...)
1231 {
1232 va_list Argp;
1233 struct DMCompositeLink *next;
1234 DM_Composite *com = (DM_Composite *)dm->data;
1235 PetscBool flg;
1236
1237 PetscFunctionBegin;
1238 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1239 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
1240 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
1241 next = com->next;
1242 /* loop over packed objects, handling one at a time */
1243 va_start(Argp, dm);
1244 while (next) {
1245 DM *dmn;
1246 dmn = va_arg(Argp, DM *);
1247 if (dmn) *dmn = next->dm;
1248 next = next->next;
1249 }
1250 va_end(Argp);
1251 PetscFunctionReturn(PETSC_SUCCESS);
1252 }
1253
1254 /*@
1255 DMCompositeGetEntriesArray - Gets the DM for each entry in a `DMCOMPOSITE`
1256
1257 Not Collective
1258
1259 Input Parameter:
1260 . dm - the `DMCOMPOSITE` object
1261
1262 Output Parameter:
1263 . dms - array of sufficient length (see `DMCompositeGetNumberDM()`) to hold the individual `DM`
1264
1265 Level: advanced
1266
1267 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCreateGlobalVector()`, `DMCompositeGetEntries()`
1268 `DMCompositeGather()`, `DMCompositeCreate()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`,
1269 `DMCompositeRestoreLocalVectors()`, `DMCompositeGetLocalVectors()`, `DMCompositeScatter()`
1270 @*/
DMCompositeGetEntriesArray(DM dm,DM dms[])1271 PetscErrorCode DMCompositeGetEntriesArray(DM dm, DM dms[])
1272 {
1273 struct DMCompositeLink *next;
1274 DM_Composite *com = (DM_Composite *)dm->data;
1275 PetscInt i;
1276 PetscBool flg;
1277
1278 PetscFunctionBegin;
1279 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1280 PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMCOMPOSITE, &flg));
1281 PetscCheck(flg, PetscObjectComm((PetscObject)dm), PETSC_ERR_USER, "Not for type %s", ((PetscObject)dm)->type_name);
1282 /* loop over packed objects, handling one at a time */
1283 for (next = com->next, i = 0; next; next = next->next, i++) dms[i] = next->dm;
1284 PetscFunctionReturn(PETSC_SUCCESS);
1285 }
1286
1287 typedef struct {
1288 DM dm;
1289 PetscViewer *subv;
1290 Vec *vecs;
1291 } GLVisViewerCtx;
1292
DestroyGLVisViewerCtx_Private(PetscCtxRt vctx)1293 static PetscErrorCode DestroyGLVisViewerCtx_Private(PetscCtxRt vctx)
1294 {
1295 GLVisViewerCtx *ctx = *(GLVisViewerCtx **)vctx;
1296 PetscInt i, n;
1297
1298 PetscFunctionBegin;
1299 PetscCall(DMCompositeGetNumberDM(ctx->dm, &n));
1300 for (i = 0; i < n; i++) PetscCall(PetscViewerDestroy(&ctx->subv[i]));
1301 PetscCall(PetscFree2(ctx->subv, ctx->vecs));
1302 PetscCall(DMDestroy(&ctx->dm));
1303 PetscCall(PetscFree(ctx));
1304 PetscFunctionReturn(PETSC_SUCCESS);
1305 }
1306
DMCompositeSampleGLVisFields_Private(PetscObject oX,PetscInt nf,PetscObject oXfield[],void * vctx)1307 static PetscErrorCode DMCompositeSampleGLVisFields_Private(PetscObject oX, PetscInt nf, PetscObject oXfield[], void *vctx)
1308 {
1309 Vec X = (Vec)oX;
1310 GLVisViewerCtx *ctx = (GLVisViewerCtx *)vctx;
1311 PetscInt i, n, cumf;
1312
1313 PetscFunctionBegin;
1314 PetscCall(DMCompositeGetNumberDM(ctx->dm, &n));
1315 PetscCall(DMCompositeGetAccessArray(ctx->dm, X, n, NULL, ctx->vecs));
1316 for (i = 0, cumf = 0; i < n; i++) {
1317 PetscErrorCode (*g2l)(PetscObject, PetscInt, PetscObject[], void *);
1318 void *fctx;
1319 PetscInt nfi;
1320
1321 PetscCall(PetscViewerGLVisGetFields_Internal(ctx->subv[i], &nfi, NULL, NULL, &g2l, NULL, &fctx));
1322 if (!nfi) continue;
1323 if (g2l) PetscCall((*g2l)((PetscObject)ctx->vecs[i], nfi, oXfield + cumf, fctx));
1324 else PetscCall(VecCopy(ctx->vecs[i], (Vec)oXfield[cumf]));
1325 cumf += nfi;
1326 }
1327 PetscCall(DMCompositeRestoreAccessArray(ctx->dm, X, n, NULL, ctx->vecs));
1328 PetscFunctionReturn(PETSC_SUCCESS);
1329 }
1330
DMSetUpGLVisViewer_Composite(PetscObject odm,PetscViewer viewer)1331 static PetscErrorCode DMSetUpGLVisViewer_Composite(PetscObject odm, PetscViewer viewer)
1332 {
1333 DM dm = (DM)odm, *dms;
1334 Vec *Ufds;
1335 GLVisViewerCtx *ctx;
1336 PetscInt i, n, tnf, *sdim;
1337 char **fecs;
1338
1339 PetscFunctionBegin;
1340 PetscCall(PetscNew(&ctx));
1341 PetscCall(PetscObjectReference((PetscObject)dm));
1342 ctx->dm = dm;
1343 PetscCall(DMCompositeGetNumberDM(dm, &n));
1344 PetscCall(PetscMalloc1(n, &dms));
1345 PetscCall(DMCompositeGetEntriesArray(dm, dms));
1346 PetscCall(PetscMalloc2(n, &ctx->subv, n, &ctx->vecs));
1347 for (i = 0, tnf = 0; i < n; i++) {
1348 PetscInt nf;
1349
1350 PetscCall(PetscViewerCreate(PetscObjectComm(odm), &ctx->subv[i]));
1351 PetscCall(PetscViewerSetType(ctx->subv[i], PETSCVIEWERGLVIS));
1352 PetscCall(PetscViewerGLVisSetDM_Internal(ctx->subv[i], (PetscObject)dms[i]));
1353 PetscCall(PetscViewerGLVisGetFields_Internal(ctx->subv[i], &nf, NULL, NULL, NULL, NULL, NULL));
1354 tnf += nf;
1355 }
1356 PetscCall(PetscFree(dms));
1357 PetscCall(PetscMalloc3(tnf, &fecs, tnf, &sdim, tnf, &Ufds));
1358 for (i = 0, tnf = 0; i < n; i++) {
1359 PetscInt *sd, nf, f;
1360 const char **fec;
1361 Vec *Uf;
1362
1363 PetscCall(PetscViewerGLVisGetFields_Internal(ctx->subv[i], &nf, &fec, &sd, NULL, (PetscObject **)&Uf, NULL));
1364 for (f = 0; f < nf; f++) {
1365 PetscCall(PetscStrallocpy(fec[f], &fecs[tnf + f]));
1366 Ufds[tnf + f] = Uf[f];
1367 sdim[tnf + f] = sd[f];
1368 }
1369 tnf += nf;
1370 }
1371 PetscCall(PetscViewerGLVisSetFields(viewer, tnf, (const char **)fecs, sdim, DMCompositeSampleGLVisFields_Private, (PetscObject *)Ufds, ctx, DestroyGLVisViewerCtx_Private));
1372 for (i = 0; i < tnf; i++) PetscCall(PetscFree(fecs[i]));
1373 PetscCall(PetscFree3(fecs, sdim, Ufds));
1374 PetscFunctionReturn(PETSC_SUCCESS);
1375 }
1376
DMRefine_Composite(DM dmi,MPI_Comm comm,DM * fine)1377 static PetscErrorCode DMRefine_Composite(DM dmi, MPI_Comm comm, DM *fine)
1378 {
1379 struct DMCompositeLink *next;
1380 DM_Composite *com = (DM_Composite *)dmi->data;
1381 DM dm;
1382
1383 PetscFunctionBegin;
1384 PetscValidHeaderSpecific(dmi, DM_CLASSID, 1);
1385 if (comm == MPI_COMM_NULL) PetscCall(PetscObjectGetComm((PetscObject)dmi, &comm));
1386 PetscCall(DMSetUp(dmi));
1387 next = com->next;
1388 PetscCall(DMCompositeCreate(comm, fine));
1389
1390 /* loop over packed objects, handling one at a time */
1391 while (next) {
1392 PetscCall(DMRefine(next->dm, comm, &dm));
1393 PetscCall(DMCompositeAddDM(*fine, dm));
1394 PetscCall(PetscObjectDereference((PetscObject)dm));
1395 next = next->next;
1396 }
1397 PetscFunctionReturn(PETSC_SUCCESS);
1398 }
1399
DMCoarsen_Composite(DM dmi,MPI_Comm comm,DM * fine)1400 static PetscErrorCode DMCoarsen_Composite(DM dmi, MPI_Comm comm, DM *fine)
1401 {
1402 struct DMCompositeLink *next;
1403 DM_Composite *com = (DM_Composite *)dmi->data;
1404 DM dm;
1405
1406 PetscFunctionBegin;
1407 PetscValidHeaderSpecific(dmi, DM_CLASSID, 1);
1408 PetscCall(DMSetUp(dmi));
1409 if (comm == MPI_COMM_NULL) PetscCall(PetscObjectGetComm((PetscObject)dmi, &comm));
1410 next = com->next;
1411 PetscCall(DMCompositeCreate(comm, fine));
1412
1413 /* loop over packed objects, handling one at a time */
1414 while (next) {
1415 PetscCall(DMCoarsen(next->dm, comm, &dm));
1416 PetscCall(DMCompositeAddDM(*fine, dm));
1417 PetscCall(PetscObjectDereference((PetscObject)dm));
1418 next = next->next;
1419 }
1420 PetscFunctionReturn(PETSC_SUCCESS);
1421 }
1422
DMCreateInterpolation_Composite(DM coarse,DM fine,Mat * A,Vec * v)1423 static PetscErrorCode DMCreateInterpolation_Composite(DM coarse, DM fine, Mat *A, Vec *v)
1424 {
1425 PetscInt m, n, M, N, nDM, i;
1426 struct DMCompositeLink *nextc;
1427 struct DMCompositeLink *nextf;
1428 Vec gcoarse, gfine, *vecs;
1429 DM_Composite *comcoarse = (DM_Composite *)coarse->data;
1430 DM_Composite *comfine = (DM_Composite *)fine->data;
1431 Mat *mats;
1432
1433 PetscFunctionBegin;
1434 PetscValidHeaderSpecific(coarse, DM_CLASSID, 1);
1435 PetscValidHeaderSpecific(fine, DM_CLASSID, 2);
1436 PetscCall(DMSetUp(coarse));
1437 PetscCall(DMSetUp(fine));
1438 /* use global vectors only for determining matrix layout */
1439 PetscCall(DMGetGlobalVector(coarse, &gcoarse));
1440 PetscCall(DMGetGlobalVector(fine, &gfine));
1441 PetscCall(VecGetLocalSize(gcoarse, &n));
1442 PetscCall(VecGetLocalSize(gfine, &m));
1443 PetscCall(VecGetSize(gcoarse, &N));
1444 PetscCall(VecGetSize(gfine, &M));
1445 PetscCall(DMRestoreGlobalVector(coarse, &gcoarse));
1446 PetscCall(DMRestoreGlobalVector(fine, &gfine));
1447
1448 nDM = comfine->nDM;
1449 PetscCheck(nDM == comcoarse->nDM, PetscObjectComm((PetscObject)fine), PETSC_ERR_ARG_INCOMP, "Fine DMComposite has %" PetscInt_FMT " entries, but coarse has %" PetscInt_FMT, nDM, comcoarse->nDM);
1450 PetscCall(PetscCalloc1(nDM * nDM, &mats));
1451 if (v) PetscCall(PetscCalloc1(nDM, &vecs));
1452
1453 /* loop over packed objects, handling one at a time */
1454 for (nextc = comcoarse->next, nextf = comfine->next, i = 0; nextc; nextc = nextc->next, nextf = nextf->next, i++) {
1455 if (!v) PetscCall(DMCreateInterpolation(nextc->dm, nextf->dm, &mats[i * nDM + i], NULL));
1456 else PetscCall(DMCreateInterpolation(nextc->dm, nextf->dm, &mats[i * nDM + i], &vecs[i]));
1457 }
1458 PetscCall(MatCreateNest(PetscObjectComm((PetscObject)fine), nDM, NULL, nDM, NULL, mats, A));
1459 if (v) PetscCall(VecCreateNest(PetscObjectComm((PetscObject)fine), nDM, NULL, vecs, v));
1460 for (i = 0; i < nDM * nDM; i++) PetscCall(MatDestroy(&mats[i]));
1461 PetscCall(PetscFree(mats));
1462 if (v) {
1463 for (i = 0; i < nDM; i++) PetscCall(VecDestroy(&vecs[i]));
1464 PetscCall(PetscFree(vecs));
1465 }
1466 PetscFunctionReturn(PETSC_SUCCESS);
1467 }
1468
DMGetLocalToGlobalMapping_Composite(DM dm)1469 static PetscErrorCode DMGetLocalToGlobalMapping_Composite(DM dm)
1470 {
1471 DM_Composite *com = (DM_Composite *)dm->data;
1472 ISLocalToGlobalMapping *ltogs;
1473 PetscInt i;
1474
1475 PetscFunctionBegin;
1476 /* Set the ISLocalToGlobalMapping on the new matrix */
1477 PetscCall(DMCompositeGetISLocalToGlobalMappings(dm, <ogs));
1478 PetscCall(ISLocalToGlobalMappingConcatenate(PetscObjectComm((PetscObject)dm), com->nDM, ltogs, &dm->ltogmap));
1479 for (i = 0; i < com->nDM; i++) PetscCall(ISLocalToGlobalMappingDestroy(<ogs[i]));
1480 PetscCall(PetscFree(ltogs));
1481 PetscFunctionReturn(PETSC_SUCCESS);
1482 }
1483
DMCreateColoring_Composite(DM dm,ISColoringType ctype,ISColoring * coloring)1484 static PetscErrorCode DMCreateColoring_Composite(DM dm, ISColoringType ctype, ISColoring *coloring)
1485 {
1486 PetscInt n, i, cnt;
1487 ISColoringValue *colors;
1488 PetscBool dense = PETSC_FALSE;
1489 ISColoringValue maxcol = 0;
1490 DM_Composite *com = (DM_Composite *)dm->data;
1491
1492 PetscFunctionBegin;
1493 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1494 PetscCheck(ctype != IS_COLORING_LOCAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only global coloring supported");
1495 PetscCheck(ctype == IS_COLORING_GLOBAL, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Unknown ISColoringType");
1496 n = com->n;
1497 PetscCall(PetscMalloc1(n, &colors)); /* freed in ISColoringDestroy() */
1498
1499 PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dmcomposite_dense_jacobian", &dense, NULL));
1500 if (dense) {
1501 PetscCall(ISColoringValueCast(com->N, &maxcol));
1502 for (i = 0; i < n; i++) PetscCall(ISColoringValueCast(com->rstart + i, colors + i));
1503 } else {
1504 struct DMCompositeLink *next = com->next;
1505 PetscMPIInt rank;
1506
1507 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1508 cnt = 0;
1509 while (next) {
1510 ISColoring lcoloring;
1511
1512 PetscCall(DMCreateColoring(next->dm, IS_COLORING_GLOBAL, &lcoloring));
1513 for (i = 0; i < lcoloring->N; i++) PetscCall(ISColoringValueCast(maxcol + lcoloring->colors[i], colors + cnt++));
1514 maxcol += lcoloring->n;
1515 PetscCall(ISColoringDestroy(&lcoloring));
1516 next = next->next;
1517 }
1518 }
1519 PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)dm), maxcol, n, colors, PETSC_OWN_POINTER, coloring));
1520 PetscFunctionReturn(PETSC_SUCCESS);
1521 }
1522
DMGlobalToLocalBegin_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)1523 static PetscErrorCode DMGlobalToLocalBegin_Composite(DM dm, Vec gvec, InsertMode mode, Vec lvec)
1524 {
1525 struct DMCompositeLink *next;
1526 const PetscScalar *garray, *garrayhead;
1527 PetscScalar *larray, *larrayhead;
1528 DM_Composite *com = (DM_Composite *)dm->data;
1529
1530 PetscFunctionBegin;
1531 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1532 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2);
1533
1534 if (!com->setup) PetscCall(DMSetUp(dm));
1535
1536 PetscCall(VecGetArrayRead(gvec, &garray));
1537 garrayhead = garray;
1538 PetscCall(VecGetArray(lvec, &larray));
1539 larrayhead = larray;
1540
1541 /* loop over packed objects, handling one at a time */
1542 next = com->next;
1543 while (next) {
1544 Vec local, global;
1545 PetscInt N;
1546
1547 PetscCall(DMGetGlobalVector(next->dm, &global));
1548 PetscCall(VecGetLocalSize(global, &N));
1549 PetscCall(VecPlaceArray(global, garrayhead));
1550 PetscCall(DMGetLocalVector(next->dm, &local));
1551 PetscCall(VecPlaceArray(local, larrayhead));
1552 PetscCall(DMGlobalToLocalBegin(next->dm, global, mode, local));
1553 PetscCall(DMGlobalToLocalEnd(next->dm, global, mode, local));
1554 PetscCall(VecResetArray(global));
1555 PetscCall(VecResetArray(local));
1556 PetscCall(DMRestoreGlobalVector(next->dm, &global));
1557 PetscCall(DMRestoreLocalVector(next->dm, &local));
1558
1559 larrayhead += next->nlocal;
1560 garrayhead += next->n;
1561 next = next->next;
1562 }
1563 PetscCall(VecRestoreArrayRead(gvec, &garray));
1564 PetscCall(VecRestoreArray(lvec, &larray));
1565 PetscFunctionReturn(PETSC_SUCCESS);
1566 }
1567
DMGlobalToLocalEnd_Composite(DM dm,Vec gvec,InsertMode mode,Vec lvec)1568 static PetscErrorCode DMGlobalToLocalEnd_Composite(DM dm, Vec gvec, InsertMode mode, Vec lvec)
1569 {
1570 PetscFunctionBegin;
1571 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1572 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 2);
1573 PetscValidHeaderSpecific(lvec, VEC_CLASSID, 4);
1574 PetscFunctionReturn(PETSC_SUCCESS);
1575 }
1576
DMLocalToGlobalBegin_Composite(DM dm,Vec lvec,InsertMode mode,Vec gvec)1577 static PetscErrorCode DMLocalToGlobalBegin_Composite(DM dm, Vec lvec, InsertMode mode, Vec gvec)
1578 {
1579 struct DMCompositeLink *next;
1580 const PetscScalar *larray, *larrayhead;
1581 PetscScalar *garray, *garrayhead;
1582 DM_Composite *com = (DM_Composite *)dm->data;
1583
1584 PetscFunctionBegin;
1585 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1586 PetscValidHeaderSpecific(lvec, VEC_CLASSID, 2);
1587 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 4);
1588
1589 if (!com->setup) PetscCall(DMSetUp(dm));
1590
1591 PetscCall(VecGetArrayRead(lvec, &larray));
1592 larrayhead = larray;
1593 PetscCall(VecGetArray(gvec, &garray));
1594 garrayhead = garray;
1595
1596 /* loop over packed objects, handling one at a time */
1597 next = com->next;
1598 while (next) {
1599 Vec global, local;
1600
1601 PetscCall(DMGetLocalVector(next->dm, &local));
1602 PetscCall(VecPlaceArray(local, larrayhead));
1603 PetscCall(DMGetGlobalVector(next->dm, &global));
1604 PetscCall(VecPlaceArray(global, garrayhead));
1605 PetscCall(DMLocalToGlobalBegin(next->dm, local, mode, global));
1606 PetscCall(DMLocalToGlobalEnd(next->dm, local, mode, global));
1607 PetscCall(VecResetArray(local));
1608 PetscCall(VecResetArray(global));
1609 PetscCall(DMRestoreGlobalVector(next->dm, &global));
1610 PetscCall(DMRestoreLocalVector(next->dm, &local));
1611
1612 garrayhead += next->n;
1613 larrayhead += next->nlocal;
1614 next = next->next;
1615 }
1616
1617 PetscCall(VecRestoreArray(gvec, &garray));
1618 PetscCall(VecRestoreArrayRead(lvec, &larray));
1619 PetscFunctionReturn(PETSC_SUCCESS);
1620 }
1621
DMLocalToGlobalEnd_Composite(DM dm,Vec lvec,InsertMode mode,Vec gvec)1622 static PetscErrorCode DMLocalToGlobalEnd_Composite(DM dm, Vec lvec, InsertMode mode, Vec gvec)
1623 {
1624 PetscFunctionBegin;
1625 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1626 PetscValidHeaderSpecific(lvec, VEC_CLASSID, 2);
1627 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 4);
1628 PetscFunctionReturn(PETSC_SUCCESS);
1629 }
1630
DMLocalToLocalBegin_Composite(DM dm,Vec vec1,InsertMode mode,Vec vec2)1631 static PetscErrorCode DMLocalToLocalBegin_Composite(DM dm, Vec vec1, InsertMode mode, Vec vec2)
1632 {
1633 struct DMCompositeLink *next;
1634 const PetscScalar *array1, *array1head;
1635 PetscScalar *array2, *array2head;
1636 DM_Composite *com = (DM_Composite *)dm->data;
1637
1638 PetscFunctionBegin;
1639 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1640 PetscValidHeaderSpecific(vec1, VEC_CLASSID, 2);
1641 PetscValidHeaderSpecific(vec2, VEC_CLASSID, 4);
1642
1643 if (!com->setup) PetscCall(DMSetUp(dm));
1644
1645 PetscCall(VecGetArrayRead(vec1, &array1));
1646 array1head = array1;
1647 PetscCall(VecGetArray(vec2, &array2));
1648 array2head = array2;
1649
1650 /* loop over packed objects, handling one at a time */
1651 next = com->next;
1652 while (next) {
1653 Vec local1, local2;
1654
1655 PetscCall(DMGetLocalVector(next->dm, &local1));
1656 PetscCall(VecPlaceArray(local1, array1head));
1657 PetscCall(DMGetLocalVector(next->dm, &local2));
1658 PetscCall(VecPlaceArray(local2, array2head));
1659 PetscCall(DMLocalToLocalBegin(next->dm, local1, mode, local2));
1660 PetscCall(DMLocalToLocalEnd(next->dm, local1, mode, local2));
1661 PetscCall(VecResetArray(local2));
1662 PetscCall(DMRestoreLocalVector(next->dm, &local2));
1663 PetscCall(VecResetArray(local1));
1664 PetscCall(DMRestoreLocalVector(next->dm, &local1));
1665
1666 array1head += next->nlocal;
1667 array2head += next->nlocal;
1668 next = next->next;
1669 }
1670
1671 PetscCall(VecRestoreArrayRead(vec1, &array1));
1672 PetscCall(VecRestoreArray(vec2, &array2));
1673 PetscFunctionReturn(PETSC_SUCCESS);
1674 }
1675
DMLocalToLocalEnd_Composite(DM dm,Vec lvec,InsertMode mode,Vec gvec)1676 static PetscErrorCode DMLocalToLocalEnd_Composite(DM dm, Vec lvec, InsertMode mode, Vec gvec)
1677 {
1678 PetscFunctionBegin;
1679 PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1680 PetscValidHeaderSpecific(lvec, VEC_CLASSID, 2);
1681 PetscValidHeaderSpecific(gvec, VEC_CLASSID, 4);
1682 PetscFunctionReturn(PETSC_SUCCESS);
1683 }
1684
1685 /*MC
1686 DMCOMPOSITE = "composite" - A `DM` object that is used to manage data for a collection of `DM`
1687
1688 Level: intermediate
1689
1690 .seealso: `DMType`, `DM`, `DMDACreate()`, `DMCreate()`, `DMSetType()`, `DMCompositeCreate()`
1691 M*/
1692
DMCreate_Composite(DM p)1693 PETSC_EXTERN PetscErrorCode DMCreate_Composite(DM p)
1694 {
1695 DM_Composite *com;
1696
1697 PetscFunctionBegin;
1698 PetscCall(PetscNew(&com));
1699 p->data = com;
1700 com->n = 0;
1701 com->nghost = 0;
1702 com->next = NULL;
1703 com->nDM = 0;
1704
1705 p->ops->createglobalvector = DMCreateGlobalVector_Composite;
1706 p->ops->createlocalvector = DMCreateLocalVector_Composite;
1707 p->ops->getlocaltoglobalmapping = DMGetLocalToGlobalMapping_Composite;
1708 p->ops->createfieldis = DMCreateFieldIS_Composite;
1709 p->ops->createfielddecomposition = DMCreateFieldDecomposition_Composite;
1710 p->ops->refine = DMRefine_Composite;
1711 p->ops->coarsen = DMCoarsen_Composite;
1712 p->ops->createinterpolation = DMCreateInterpolation_Composite;
1713 p->ops->creatematrix = DMCreateMatrix_Composite;
1714 p->ops->getcoloring = DMCreateColoring_Composite;
1715 p->ops->globaltolocalbegin = DMGlobalToLocalBegin_Composite;
1716 p->ops->globaltolocalend = DMGlobalToLocalEnd_Composite;
1717 p->ops->localtoglobalbegin = DMLocalToGlobalBegin_Composite;
1718 p->ops->localtoglobalend = DMLocalToGlobalEnd_Composite;
1719 p->ops->localtolocalbegin = DMLocalToLocalBegin_Composite;
1720 p->ops->localtolocalend = DMLocalToLocalEnd_Composite;
1721 p->ops->destroy = DMDestroy_Composite;
1722 p->ops->view = DMView_Composite;
1723 p->ops->setup = DMSetUp_Composite;
1724
1725 PetscCall(PetscObjectComposeFunction((PetscObject)p, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Composite));
1726 PetscFunctionReturn(PETSC_SUCCESS);
1727 }
1728
1729 /*@
1730 DMCompositeCreate - Creates a `DMCOMPOSITE`, used to generate "composite"
1731 vectors made up of several subvectors.
1732
1733 Collective
1734
1735 Input Parameter:
1736 . comm - the processors that will share the global vector
1737
1738 Output Parameter:
1739 . packer - the `DMCOMPOSITE` object
1740
1741 Level: advanced
1742
1743 .seealso: `DMCOMPOSITE`, `DM`, `DMDestroy()`, `DMCompositeAddDM()`, `DMCompositeScatter()`, `DMCreate()`
1744 `DMCompositeGather()`, `DMCreateGlobalVector()`, `DMCompositeGetISLocalToGlobalMappings()`, `DMCompositeGetAccess()`
1745 `DMCompositeGetLocalVectors()`, `DMCompositeRestoreLocalVectors()`, `DMCompositeGetEntries()`
1746 @*/
DMCompositeCreate(MPI_Comm comm,DM * packer)1747 PetscErrorCode DMCompositeCreate(MPI_Comm comm, DM *packer)
1748 {
1749 PetscFunctionBegin;
1750 PetscAssertPointer(packer, 2);
1751 PetscCall(DMCreate(comm, packer));
1752 PetscCall(DMSetType(*packer, DMCOMPOSITE));
1753 PetscFunctionReturn(PETSC_SUCCESS);
1754 }
1755