xref: /petsc/src/dm/impls/composite/packm.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
1a12302e2SJed Brown 
2ccd284c7SBarry Smith #include <../src/dm/impls/composite/packimpl.h> /*I  "petscdmcomposite.h"  I*/
3a12302e2SJed Brown 
49371c9d4SSatish Balay static PetscErrorCode DMCreateMatrix_Composite_Nest(DM dm, Mat *J) {
5b989ae6dSJed Brown   const DM_Composite           *com = (DM_Composite *)dm->data;
6b989ae6dSJed Brown   const struct DMCompositeLink *rlink, *clink;
7b989ae6dSJed Brown   IS                           *isg;
8b989ae6dSJed Brown   Mat                          *submats;
9b989ae6dSJed Brown   PetscInt                      i, j, n;
10a12302e2SJed Brown 
11a12302e2SJed Brown   PetscFunctionBegin;
129ae5db72SJed Brown   n = com->nDM; /* Total number of entries */
13b989ae6dSJed Brown 
14b989ae6dSJed Brown   /* Explicit index sets are not required for MatCreateNest, but getting them here allows MatNest to do consistency
15b989ae6dSJed Brown    * checking and allows ISEqual to compare by identity instead of by contents. */
169566063dSJacob Faibussowitsch   PetscCall(DMCompositeGetGlobalISs(dm, &isg));
17b989ae6dSJed Brown 
18b989ae6dSJed Brown   /* Get submatrices */
199566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n * n, &submats));
20b989ae6dSJed Brown   for (i = 0, rlink = com->next; rlink; i++, rlink = rlink->next) {
21b989ae6dSJed Brown     for (j = 0, clink = com->next; clink; j++, clink = clink->next) {
220298fd71SBarry Smith       Mat sub = NULL;
23b989ae6dSJed Brown       if (i == j) {
249566063dSJacob Faibussowitsch         PetscCall(DMCreateMatrix(rlink->dm, &sub));
2528b400f6SJacob Faibussowitsch       } else PetscCheck(!com->FormCoupleLocations, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot manage off-diagonal parts yet");
26b989ae6dSJed Brown       submats[i * n + j] = sub;
27b989ae6dSJed Brown     }
28b989ae6dSJed Brown   }
29b989ae6dSJed Brown 
309566063dSJacob Faibussowitsch   PetscCall(MatCreateNest(PetscObjectComm((PetscObject)dm), n, isg, n, isg, submats, J));
31b989ae6dSJed Brown 
32b989ae6dSJed Brown   /* Disown references */
339566063dSJacob Faibussowitsch   for (i = 0; i < n; i++) PetscCall(ISDestroy(&isg[i]));
349566063dSJacob Faibussowitsch   PetscCall(PetscFree(isg));
35b989ae6dSJed Brown 
36b989ae6dSJed Brown   for (i = 0; i < n * n; i++) {
379566063dSJacob Faibussowitsch     if (submats[i]) PetscCall(MatDestroy(&submats[i]));
38b989ae6dSJed Brown   }
399566063dSJacob Faibussowitsch   PetscCall(PetscFree(submats));
40a12302e2SJed Brown   PetscFunctionReturn(0);
41a12302e2SJed Brown }
42a12302e2SJed Brown 
439371c9d4SSatish Balay static PetscErrorCode DMCreateMatrix_Composite_AIJ(DM dm, Mat *J) {
44a12302e2SJed Brown   DM_Composite           *com = (DM_Composite *)dm->data;
453bf036e2SBarry Smith   struct DMCompositeLink *next;
46a12302e2SJed Brown   PetscInt                m, *dnz, *onz, i, j, mA;
47a12302e2SJed Brown   Mat                     Atmp;
48a12302e2SJed Brown   PetscMPIInt             rank;
49fcfd50ebSBarry Smith   PetscBool               dense = PETSC_FALSE;
50a12302e2SJed Brown 
51a12302e2SJed Brown   PetscFunctionBegin;
52a12302e2SJed Brown   /* use global vector to determine layout needed for matrix */
53a12302e2SJed Brown   m = com->n;
54a12302e2SJed Brown 
559566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)dm), J));
569566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(*J, m, m, PETSC_DETERMINE, PETSC_DETERMINE));
579566063dSJacob Faibussowitsch   PetscCall(MatSetType(*J, dm->mattype));
58a12302e2SJed Brown 
59a12302e2SJed Brown   /*
60a12302e2SJed Brown      Extremely inefficient but will compute entire Jacobian for testing
61a12302e2SJed Brown   */
629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dmcomposite_dense_jacobian", &dense, NULL));
63a12302e2SJed Brown   if (dense) {
64a12302e2SJed Brown     PetscInt     rstart, rend, *indices;
65a12302e2SJed Brown     PetscScalar *values;
66a12302e2SJed Brown 
67a12302e2SJed Brown     mA = com->N;
689566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJSetPreallocation(*J, mA, NULL, mA - m, NULL));
699566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(*J, mA, NULL));
70a12302e2SJed Brown 
719566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(*J, &rstart, &rend));
729566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(mA, &values, mA, &indices));
739566063dSJacob Faibussowitsch     PetscCall(PetscArrayzero(values, mA));
74a12302e2SJed Brown     for (i = 0; i < mA; i++) indices[i] = i;
75*48a46eb9SPierre Jolivet     for (i = rstart; i < rend; i++) PetscCall(MatSetValues(*J, 1, &i, mA, indices, values, INSERT_VALUES));
769566063dSJacob Faibussowitsch     PetscCall(PetscFree2(values, indices));
779566063dSJacob Faibussowitsch     PetscCall(MatAssemblyBegin(*J, MAT_FINAL_ASSEMBLY));
789566063dSJacob Faibussowitsch     PetscCall(MatAssemblyEnd(*J, MAT_FINAL_ASSEMBLY));
79a12302e2SJed Brown     PetscFunctionReturn(0);
80a12302e2SJed Brown   }
81a12302e2SJed Brown 
829566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
83d0609cedSBarry Smith   MatPreallocateBegin(PetscObjectComm((PetscObject)dm), m, m, dnz, onz);
84a12302e2SJed Brown   /* loop over packed objects, handling one at at time */
85a12302e2SJed Brown   next = com->next;
86a12302e2SJed Brown   while (next) {
87a12302e2SJed Brown     PetscInt        nc, rstart, *ccols, maxnc;
88a12302e2SJed Brown     const PetscInt *cols, *rstarts;
89a12302e2SJed Brown     PetscMPIInt     proc;
90a12302e2SJed Brown 
919566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(next->dm, &Atmp));
929566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(Atmp, &rstart, NULL));
939566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRanges(Atmp, &rstarts));
949566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(Atmp, &mA, NULL));
95a12302e2SJed Brown 
96a12302e2SJed Brown     maxnc = 0;
97a12302e2SJed Brown     for (i = 0; i < mA; i++) {
989566063dSJacob Faibussowitsch       PetscCall(MatGetRow(Atmp, rstart + i, &nc, NULL, NULL));
99a12302e2SJed Brown       maxnc = PetscMax(nc, maxnc);
1009566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(Atmp, rstart + i, &nc, NULL, NULL));
101a12302e2SJed Brown     }
1029566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxnc, &ccols));
103a12302e2SJed Brown     for (i = 0; i < mA; i++) {
1049566063dSJacob Faibussowitsch       PetscCall(MatGetRow(Atmp, rstart + i, &nc, &cols, NULL));
105a12302e2SJed Brown       /* remap the columns taking into how much they are shifted on each process */
106a12302e2SJed Brown       for (j = 0; j < nc; j++) {
107a12302e2SJed Brown         proc = 0;
108a12302e2SJed Brown         while (cols[j] >= rstarts[proc + 1]) proc++;
109a12302e2SJed Brown         ccols[j] = cols[j] + next->grstarts[proc] - rstarts[proc];
110a12302e2SJed Brown       }
1119566063dSJacob Faibussowitsch       PetscCall(MatPreallocateSet(com->rstart + next->rstart + i, nc, ccols, dnz, onz));
1129566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(Atmp, rstart + i, &nc, &cols, NULL));
113a12302e2SJed Brown     }
1149566063dSJacob Faibussowitsch     PetscCall(PetscFree(ccols));
1159566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Atmp));
116a12302e2SJed Brown     next = next->next;
117a12302e2SJed Brown   }
1181baa6e33SBarry Smith   if (com->FormCoupleLocations) PetscCall((*com->FormCoupleLocations)(dm, NULL, dnz, onz, __rstart, __nrows, __start, __end));
1199566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(*J, 0, dnz, 0, onz));
1209566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(*J, 0, dnz));
121d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
122a12302e2SJed Brown 
123fcfd50ebSBarry Smith   if (dm->prealloc_only) PetscFunctionReturn(0);
124ff6157d0SJed Brown 
125a12302e2SJed Brown   next = com->next;
126a12302e2SJed Brown   while (next) {
127a12302e2SJed Brown     PetscInt           nc, rstart, row, maxnc, *ccols;
128a12302e2SJed Brown     const PetscInt    *cols, *rstarts;
129a12302e2SJed Brown     const PetscScalar *values;
130a12302e2SJed Brown     PetscMPIInt        proc;
131a12302e2SJed Brown 
1329566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(next->dm, &Atmp));
1339566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(Atmp, &rstart, NULL));
1349566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRanges(Atmp, &rstarts));
1359566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(Atmp, &mA, NULL));
136a12302e2SJed Brown     maxnc = 0;
137a12302e2SJed Brown     for (i = 0; i < mA; i++) {
1389566063dSJacob Faibussowitsch       PetscCall(MatGetRow(Atmp, rstart + i, &nc, NULL, NULL));
139a12302e2SJed Brown       maxnc = PetscMax(nc, maxnc);
1409566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(Atmp, rstart + i, &nc, NULL, NULL));
141a12302e2SJed Brown     }
1429566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxnc, &ccols));
143a12302e2SJed Brown     for (i = 0; i < mA; i++) {
1449566063dSJacob Faibussowitsch       PetscCall(MatGetRow(Atmp, rstart + i, &nc, (const PetscInt **)&cols, &values));
145a12302e2SJed Brown       for (j = 0; j < nc; j++) {
146a12302e2SJed Brown         proc = 0;
147a12302e2SJed Brown         while (cols[j] >= rstarts[proc + 1]) proc++;
148a12302e2SJed Brown         ccols[j] = cols[j] + next->grstarts[proc] - rstarts[proc];
149a12302e2SJed Brown       }
150a12302e2SJed Brown       row = com->rstart + next->rstart + i;
1519566063dSJacob Faibussowitsch       PetscCall(MatSetValues(*J, 1, &row, nc, ccols, values, INSERT_VALUES));
1529566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(Atmp, rstart + i, &nc, (const PetscInt **)&cols, &values));
153a12302e2SJed Brown     }
1549566063dSJacob Faibussowitsch     PetscCall(PetscFree(ccols));
1559566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Atmp));
156a12302e2SJed Brown     next = next->next;
157a12302e2SJed Brown   }
158a12302e2SJed Brown   if (com->FormCoupleLocations) {
159a12302e2SJed Brown     PetscInt __rstart;
1609566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(*J, &__rstart, NULL));
1619566063dSJacob Faibussowitsch     PetscCall((*com->FormCoupleLocations)(dm, *J, NULL, NULL, __rstart, 0, 0, 0));
162a12302e2SJed Brown   }
1639566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*J, MAT_FINAL_ASSEMBLY));
1649566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*J, MAT_FINAL_ASSEMBLY));
165a12302e2SJed Brown   PetscFunctionReturn(0);
166a12302e2SJed Brown }
167a12302e2SJed Brown 
1689371c9d4SSatish Balay PetscErrorCode DMCreateMatrix_Composite(DM dm, Mat *J) {
169a12302e2SJed Brown   PetscBool              usenest;
17045b6f7e9SBarry Smith   ISLocalToGlobalMapping ltogmap;
171a12302e2SJed Brown 
172a12302e2SJed Brown   PetscFunctionBegin;
1739566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(dm));
1749566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
1759566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATNEST, &usenest));
1761baa6e33SBarry Smith   if (usenest) PetscCall(DMCreateMatrix_Composite_Nest(dm, J));
1771baa6e33SBarry Smith   else PetscCall(DMCreateMatrix_Composite_AIJ(dm, J));
178a12302e2SJed Brown 
1799566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(dm, &ltogmap));
1809566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(*J, ltogmap, ltogmap));
1819566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
182a12302e2SJed Brown   PetscFunctionReturn(0);
183a12302e2SJed Brown }
184