xref: /petsc/src/dm/impls/composite/packm.c (revision 38130cf1ac21e4cbb24dfd2eae44be5a1b0007e2)
1ccd284c7SBarry Smith #include <../src/dm/impls/composite/packimpl.h> /*I  "petscdmcomposite.h"  I*/
2a12302e2SJed Brown 
DMCreateMatrix_Composite_Nest(DM dm,Mat * J)3d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_Composite_Nest(DM dm, Mat *J)
4d71ae5a4SJacob Faibussowitsch {
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;
23ac530a7eSPierre Jolivet       if (i == j) PetscCall(DMCreateMatrix(rlink->dm, &sub));
24ac530a7eSPierre Jolivet       else PetscCheck(!com->FormCoupleLocations, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Cannot manage off-diagonal parts yet");
25b989ae6dSJed Brown       submats[i * n + j] = sub;
26b989ae6dSJed Brown     }
27b989ae6dSJed Brown   }
28b989ae6dSJed Brown 
299566063dSJacob Faibussowitsch   PetscCall(MatCreateNest(PetscObjectComm((PetscObject)dm), n, isg, n, isg, submats, J));
30b989ae6dSJed Brown 
31b989ae6dSJed Brown   /* Disown references */
329566063dSJacob Faibussowitsch   for (i = 0; i < n; i++) PetscCall(ISDestroy(&isg[i]));
339566063dSJacob Faibussowitsch   PetscCall(PetscFree(isg));
34b989ae6dSJed Brown 
35b989ae6dSJed Brown   for (i = 0; i < n * n; i++) {
369566063dSJacob Faibussowitsch     if (submats[i]) PetscCall(MatDestroy(&submats[i]));
37b989ae6dSJed Brown   }
389566063dSJacob Faibussowitsch   PetscCall(PetscFree(submats));
393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40a12302e2SJed Brown }
41a12302e2SJed Brown 
DMCreateMatrix_Composite_AIJ(DM dm,Mat * J)42d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateMatrix_Composite_AIJ(DM dm, Mat *J)
43d71ae5a4SJacob Faibussowitsch {
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;
7548a46eb9SPierre 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));
793ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
80a12302e2SJed Brown   }
81a12302e2SJed Brown 
829566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
839363767aSZach Atkins   if (dm->prealloc_skip) PetscFunctionReturn(PETSC_SUCCESS);
84d0609cedSBarry Smith   MatPreallocateBegin(PetscObjectComm((PetscObject)dm), m, m, dnz, onz);
8515229ffcSPierre Jolivet   /* loop over packed objects, handling one at a time */
86a12302e2SJed Brown   next = com->next;
87a12302e2SJed Brown   while (next) {
88a12302e2SJed Brown     PetscInt        nc, rstart, *ccols, maxnc;
89a12302e2SJed Brown     const PetscInt *cols, *rstarts;
90a12302e2SJed Brown     PetscMPIInt     proc;
91*c7088584SZach Atkins     MatType         tmp, mat_type_old;
92a12302e2SJed Brown 
93*c7088584SZach Atkins     /* force AIJ matrix to allow queries for preallocation */
94*c7088584SZach Atkins     PetscCall(DMGetMatType(next->dm, &tmp));
95*c7088584SZach Atkins     PetscCall(PetscStrallocpy(tmp, (char **)&mat_type_old));
96*c7088584SZach Atkins     PetscCall(DMSetMatType(next->dm, MATAIJ));
979566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(next->dm, &Atmp));
989566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(Atmp, &rstart, NULL));
999566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRanges(Atmp, &rstarts));
1009566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(Atmp, &mA, NULL));
101a12302e2SJed Brown 
102a12302e2SJed Brown     maxnc = 0;
103a12302e2SJed Brown     for (i = 0; i < mA; i++) {
1049566063dSJacob Faibussowitsch       PetscCall(MatGetRow(Atmp, rstart + i, &nc, NULL, NULL));
105a12302e2SJed Brown       maxnc = PetscMax(nc, maxnc);
1069566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(Atmp, rstart + i, &nc, NULL, NULL));
107a12302e2SJed Brown     }
1089566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxnc, &ccols));
109a12302e2SJed Brown     for (i = 0; i < mA; i++) {
1109566063dSJacob Faibussowitsch       PetscCall(MatGetRow(Atmp, rstart + i, &nc, &cols, NULL));
111a12302e2SJed Brown       /* remap the columns taking into how much they are shifted on each process */
112a12302e2SJed Brown       for (j = 0; j < nc; j++) {
113a12302e2SJed Brown         proc = 0;
114a12302e2SJed Brown         while (cols[j] >= rstarts[proc + 1]) proc++;
115a12302e2SJed Brown         ccols[j] = cols[j] + next->grstarts[proc] - rstarts[proc];
116a12302e2SJed Brown       }
1179566063dSJacob Faibussowitsch       PetscCall(MatPreallocateSet(com->rstart + next->rstart + i, nc, ccols, dnz, onz));
1189566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(Atmp, rstart + i, &nc, &cols, NULL));
119a12302e2SJed Brown     }
1209566063dSJacob Faibussowitsch     PetscCall(PetscFree(ccols));
1219566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Atmp));
122*c7088584SZach Atkins     PetscCall(DMSetMatType(next->dm, mat_type_old));
123*c7088584SZach Atkins     PetscCall(PetscFree(mat_type_old));
124a12302e2SJed Brown     next = next->next;
125a12302e2SJed Brown   }
1261baa6e33SBarry Smith   if (com->FormCoupleLocations) PetscCall((*com->FormCoupleLocations)(dm, NULL, dnz, onz, __rstart, __nrows, __start, __end));
1279566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(*J, 0, dnz, 0, onz));
1289566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(*J, 0, dnz));
129d0609cedSBarry Smith   MatPreallocateEnd(dnz, onz);
130a12302e2SJed Brown 
1313ba16761SJacob Faibussowitsch   if (dm->prealloc_only) PetscFunctionReturn(PETSC_SUCCESS);
132ff6157d0SJed Brown 
133a12302e2SJed Brown   next = com->next;
134a12302e2SJed Brown   while (next) {
135a12302e2SJed Brown     PetscInt           nc, rstart, row, maxnc, *ccols;
136a12302e2SJed Brown     const PetscInt    *cols, *rstarts;
137a12302e2SJed Brown     const PetscScalar *values;
138a12302e2SJed Brown     PetscMPIInt        proc;
139*c7088584SZach Atkins     MatType            tmp, mat_type_old;
140a12302e2SJed Brown 
141*c7088584SZach Atkins     /* force AIJ matrix to allow queries for zeroing initial matrix */
142*c7088584SZach Atkins     PetscCall(DMGetMatType(next->dm, &tmp));
143*c7088584SZach Atkins     PetscCall(PetscStrallocpy(tmp, (char **)&mat_type_old));
144*c7088584SZach Atkins     PetscCall(DMSetMatType(next->dm, MATAIJ));
1459566063dSJacob Faibussowitsch     PetscCall(DMCreateMatrix(next->dm, &Atmp));
1469566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(Atmp, &rstart, NULL));
1479566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRanges(Atmp, &rstarts));
1489566063dSJacob Faibussowitsch     PetscCall(MatGetLocalSize(Atmp, &mA, NULL));
149a12302e2SJed Brown     maxnc = 0;
150a12302e2SJed Brown     for (i = 0; i < mA; i++) {
1519566063dSJacob Faibussowitsch       PetscCall(MatGetRow(Atmp, rstart + i, &nc, NULL, NULL));
152a12302e2SJed Brown       maxnc = PetscMax(nc, maxnc);
1539566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(Atmp, rstart + i, &nc, NULL, NULL));
154a12302e2SJed Brown     }
1559566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(maxnc, &ccols));
156a12302e2SJed Brown     for (i = 0; i < mA; i++) {
157835f2295SStefano Zampini       PetscCall(MatGetRow(Atmp, rstart + i, &nc, &cols, &values));
158a12302e2SJed Brown       for (j = 0; j < nc; j++) {
159a12302e2SJed Brown         proc = 0;
160a12302e2SJed Brown         while (cols[j] >= rstarts[proc + 1]) proc++;
161a12302e2SJed Brown         ccols[j] = cols[j] + next->grstarts[proc] - rstarts[proc];
162a12302e2SJed Brown       }
163a12302e2SJed Brown       row = com->rstart + next->rstart + i;
1649566063dSJacob Faibussowitsch       PetscCall(MatSetValues(*J, 1, &row, nc, ccols, values, INSERT_VALUES));
165835f2295SStefano Zampini       PetscCall(MatRestoreRow(Atmp, rstart + i, &nc, &cols, &values));
166a12302e2SJed Brown     }
1679566063dSJacob Faibussowitsch     PetscCall(PetscFree(ccols));
1689566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&Atmp));
169*c7088584SZach Atkins     PetscCall(DMSetMatType(next->dm, mat_type_old));
170*c7088584SZach Atkins     PetscCall(PetscFree(mat_type_old));
171a12302e2SJed Brown     next = next->next;
172a12302e2SJed Brown   }
173a12302e2SJed Brown   if (com->FormCoupleLocations) {
174a12302e2SJed Brown     PetscInt __rstart;
1759566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(*J, &__rstart, NULL));
1769566063dSJacob Faibussowitsch     PetscCall((*com->FormCoupleLocations)(dm, *J, NULL, NULL, __rstart, 0, 0, 0));
177a12302e2SJed Brown   }
1789566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(*J, MAT_FINAL_ASSEMBLY));
1799566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(*J, MAT_FINAL_ASSEMBLY));
1803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
181a12302e2SJed Brown }
182a12302e2SJed Brown 
DMCreateMatrix_Composite(DM dm,Mat * J)183d71ae5a4SJacob Faibussowitsch PetscErrorCode DMCreateMatrix_Composite(DM dm, Mat *J)
184d71ae5a4SJacob Faibussowitsch {
185a12302e2SJed Brown   PetscBool              usenest;
18645b6f7e9SBarry Smith   ISLocalToGlobalMapping ltogmap;
187a12302e2SJed Brown 
188a12302e2SJed Brown   PetscFunctionBegin;
1899566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(dm));
1909566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
1919566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(dm->mattype, MATNEST, &usenest));
1921baa6e33SBarry Smith   if (usenest) PetscCall(DMCreateMatrix_Composite_Nest(dm, J));
1931baa6e33SBarry Smith   else PetscCall(DMCreateMatrix_Composite_AIJ(dm, J));
194a12302e2SJed Brown 
1959566063dSJacob Faibussowitsch   PetscCall(DMGetLocalToGlobalMapping(dm, &ltogmap));
1969566063dSJacob Faibussowitsch   PetscCall(MatSetLocalToGlobalMapping(*J, ltogmap, ltogmap));
1979566063dSJacob Faibussowitsch   PetscCall(MatSetDM(*J, dm));
1983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
199a12302e2SJed Brown }
200