1ccd284c7SBarry Smith #include <../src/dm/impls/composite/packimpl.h> /*I "petscdmcomposite.h" I*/ 2a12302e2SJed Brown 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 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 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