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, <ogmap));
1969566063dSJacob Faibussowitsch PetscCall(MatSetLocalToGlobalMapping(*J, ltogmap, ltogmap));
1979566063dSJacob Faibussowitsch PetscCall(MatSetDM(*J, dm));
1983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
199a12302e2SJed Brown }
200