1 #define PETSCDM_DLL 2 3 #include "packimpl.h" /*I "petscdm.h" I*/ 4 5 #undef __FUNCT__ 6 #define __FUNCT__ "DMGetMatrix_Composite_Nest" 7 static PetscErrorCode DMGetMatrix_Composite_Nest(DM dm,const MatType mtype,Mat *J) 8 { 9 const DM_Composite *com = (DM_Composite*)dm->data; 10 const struct DMCompositeLink *rlink,*clink; 11 PetscErrorCode ierr; 12 IS *isg; 13 Mat *submats; 14 PetscInt i,j,n; 15 16 PetscFunctionBegin; 17 n = com->nDM + com->nredundant; /* Total number of entries */ 18 19 /* Explicit index sets are not required for MatCreateNest, but getting them here allows MatNest to do consistency 20 * checking and allows ISEqual to compare by identity instead of by contents. */ 21 ierr = DMCompositeGetGlobalISs(dm,&isg);CHKERRQ(ierr); 22 23 /* Get submatrices */ 24 ierr = PetscMalloc(n*n*sizeof(Mat),&submats);CHKERRQ(ierr); 25 for (i=0,rlink=com->next; rlink; i++,rlink=rlink->next) { 26 for (j=0,clink=com->next; clink; j++,clink=clink->next) { 27 Mat sub = PETSC_NULL; 28 if (i == j) { 29 switch (rlink->type) { 30 case DMCOMPOSITE_ARRAY: 31 ierr = MatCreateMPIDense(((PetscObject)dm)->comm,rlink->n,clink->n,PETSC_DETERMINE,PETSC_DETERMINE,PETSC_NULL,&sub);CHKERRQ(ierr); 32 break; 33 case DMCOMPOSITE_DM: 34 ierr = DMGetMatrix(rlink->dm,PETSC_NULL,&sub);CHKERRQ(ierr); 35 break; 36 default: SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"unknown type"); 37 } 38 } else if (com->FormCoupleLocations) { 39 SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot manage off-diagonal parts yet"); 40 } 41 submats[i*n+j] = sub; 42 } 43 } 44 45 ierr = MatCreateNest(((PetscObject)dm)->comm,n,isg,n,isg,submats,J);CHKERRQ(ierr); 46 47 /* Disown references */ 48 for (i=0; i<n; i++) {ierr = ISDestroy(isg[i]);CHKERRQ(ierr);} 49 ierr = PetscFree(isg);CHKERRQ(ierr); 50 51 for (i=0; i<n*n; i++) { 52 if (submats[i]) {ierr = MatDestroy(submats[i]);CHKERRQ(ierr);} 53 } 54 ierr = PetscFree(submats);CHKERRQ(ierr); 55 PetscFunctionReturn(0); 56 } 57 58 #undef __FUNCT__ 59 #define __FUNCT__ "DMGetMatrix_Composite_AIJ" 60 static PetscErrorCode DMGetMatrix_Composite_AIJ(DM dm,const MatType mtype,Mat *J) 61 { 62 PetscErrorCode ierr; 63 DM_Composite *com = (DM_Composite*)dm->data; 64 struct DMCompositeLink *next = com->next; 65 PetscInt m,*dnz,*onz,i,j,mA; 66 Mat Atmp; 67 PetscMPIInt rank; 68 PetscBool dense = PETSC_FALSE,prealloc_only = PETSC_FALSE; 69 70 PetscFunctionBegin; 71 /* use global vector to determine layout needed for matrix */ 72 m = com->n; 73 74 ierr = MatCreate(((PetscObject)dm)->comm,J);CHKERRQ(ierr); 75 ierr = MatSetSizes(*J,m,m,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 76 ierr = MatSetType(*J,mtype);CHKERRQ(ierr); 77 78 /* 79 Extremely inefficient but will compute entire Jacobian for testing 80 */ 81 ierr = PetscOptionsGetBool(((PetscObject)dm)->prefix,"-dmcomposite_dense_jacobian",&dense,PETSC_NULL);CHKERRQ(ierr); 82 if (dense) { 83 PetscInt rstart,rend,*indices; 84 PetscScalar *values; 85 86 mA = com->N; 87 ierr = MatMPIAIJSetPreallocation(*J,mA,PETSC_NULL,mA-m,PETSC_NULL);CHKERRQ(ierr); 88 ierr = MatSeqAIJSetPreallocation(*J,mA,PETSC_NULL);CHKERRQ(ierr); 89 90 ierr = MatGetOwnershipRange(*J,&rstart,&rend);CHKERRQ(ierr); 91 ierr = PetscMalloc2(mA,PetscScalar,&values,mA,PetscInt,&indices);CHKERRQ(ierr); 92 ierr = PetscMemzero(values,mA*sizeof(PetscScalar));CHKERRQ(ierr); 93 for (i=0; i<mA; i++) indices[i] = i; 94 for (i=rstart; i<rend; i++) { 95 ierr = MatSetValues(*J,1,&i,mA,indices,values,INSERT_VALUES);CHKERRQ(ierr); 96 } 97 ierr = PetscFree2(values,indices);CHKERRQ(ierr); 98 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 99 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 100 PetscFunctionReturn(0); 101 } 102 103 ierr = MPI_Comm_rank(((PetscObject)dm)->comm,&rank);CHKERRQ(ierr); 104 ierr = MatPreallocateInitialize(((PetscObject)dm)->comm,m,m,dnz,onz);CHKERRQ(ierr); 105 /* loop over packed objects, handling one at at time */ 106 next = com->next; 107 while (next) { 108 if (next->type == DMCOMPOSITE_ARRAY) { 109 if (rank == next->rank) { /* zero the "little" block */ 110 for (j=com->rstart+next->rstart; j<com->rstart+next->rstart+next->n; j++) { 111 for (i=com->rstart+next->rstart; i<com->rstart+next->rstart+next->n; i++) { 112 ierr = MatPreallocateSet(j,1,&i,dnz,onz);CHKERRQ(ierr); 113 } 114 } 115 } 116 } else if (next->type == DMCOMPOSITE_DM) { 117 PetscInt nc,rstart,*ccols,maxnc; 118 const PetscInt *cols,*rstarts; 119 PetscMPIInt proc; 120 121 ierr = DMGetMatrix(next->dm,mtype,&Atmp);CHKERRQ(ierr); 122 ierr = MatGetOwnershipRange(Atmp,&rstart,PETSC_NULL);CHKERRQ(ierr); 123 ierr = MatGetOwnershipRanges(Atmp,&rstarts);CHKERRQ(ierr); 124 ierr = MatGetLocalSize(Atmp,&mA,PETSC_NULL);CHKERRQ(ierr); 125 126 maxnc = 0; 127 for (i=0; i<mA; i++) { 128 ierr = MatGetRow(Atmp,rstart+i,&nc,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 129 ierr = MatRestoreRow(Atmp,rstart+i,&nc,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 130 maxnc = PetscMax(nc,maxnc); 131 } 132 ierr = PetscMalloc(maxnc*sizeof(PetscInt),&ccols);CHKERRQ(ierr); 133 for (i=0; i<mA; i++) { 134 ierr = MatGetRow(Atmp,rstart+i,&nc,&cols,PETSC_NULL);CHKERRQ(ierr); 135 /* remap the columns taking into how much they are shifted on each process */ 136 for (j=0; j<nc; j++) { 137 proc = 0; 138 while (cols[j] >= rstarts[proc+1]) proc++; 139 ccols[j] = cols[j] + next->grstarts[proc] - rstarts[proc]; 140 } 141 ierr = MatPreallocateSet(com->rstart+next->rstart+i,nc,ccols,dnz,onz);CHKERRQ(ierr); 142 ierr = MatRestoreRow(Atmp,rstart+i,&nc,&cols,PETSC_NULL);CHKERRQ(ierr); 143 } 144 ierr = PetscFree(ccols);CHKERRQ(ierr); 145 ierr = MatDestroy(Atmp);CHKERRQ(ierr); 146 } else { 147 SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); 148 } 149 next = next->next; 150 } 151 if (com->FormCoupleLocations) { 152 ierr = (*com->FormCoupleLocations)(dm,PETSC_NULL,dnz,onz,__rstart,__nrows,__start,__end);CHKERRQ(ierr); 153 } 154 ierr = MatMPIAIJSetPreallocation(*J,0,dnz,0,onz);CHKERRQ(ierr); 155 ierr = MatSeqAIJSetPreallocation(*J,0,dnz);CHKERRQ(ierr); 156 ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 157 158 ierr = PetscOptionsGetBool(((PetscObject)dm)->prefix,"-dmcomposite_preallocate_only",&prealloc_only,PETSC_NULL);CHKERRQ(ierr); 159 if (prealloc_only) PetscFunctionReturn(0); 160 161 next = com->next; 162 while (next) { 163 if (next->type == DMCOMPOSITE_ARRAY) { 164 if (rank == next->rank) { 165 for (j=com->rstart+next->rstart; j<com->rstart+next->rstart+next->n; j++) { 166 for (i=com->rstart+next->rstart; i<com->rstart+next->rstart+next->n; i++) { 167 ierr = MatSetValue(*J,j,i,0.0,INSERT_VALUES);CHKERRQ(ierr); 168 } 169 } 170 } 171 } else if (next->type == DMCOMPOSITE_DM) { 172 PetscInt nc,rstart,row,maxnc,*ccols; 173 const PetscInt *cols,*rstarts; 174 const PetscScalar *values; 175 PetscMPIInt proc; 176 177 ierr = DMGetMatrix(next->dm,mtype,&Atmp);CHKERRQ(ierr); 178 ierr = MatGetOwnershipRange(Atmp,&rstart,PETSC_NULL);CHKERRQ(ierr); 179 ierr = MatGetOwnershipRanges(Atmp,&rstarts);CHKERRQ(ierr); 180 ierr = MatGetLocalSize(Atmp,&mA,PETSC_NULL);CHKERRQ(ierr); 181 maxnc = 0; 182 for (i=0; i<mA; i++) { 183 ierr = MatGetRow(Atmp,rstart+i,&nc,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 184 ierr = MatRestoreRow(Atmp,rstart+i,&nc,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 185 maxnc = PetscMax(nc,maxnc); 186 } 187 ierr = PetscMalloc(maxnc*sizeof(PetscInt),&ccols);CHKERRQ(ierr); 188 for (i=0; i<mA; i++) { 189 ierr = MatGetRow(Atmp,rstart+i,&nc,(const PetscInt **)&cols,&values);CHKERRQ(ierr); 190 for (j=0; j<nc; j++) { 191 proc = 0; 192 while (cols[j] >= rstarts[proc+1]) proc++; 193 ccols[j] = cols[j] + next->grstarts[proc] - rstarts[proc]; 194 } 195 row = com->rstart+next->rstart+i; 196 ierr = MatSetValues(*J,1,&row,nc,ccols,values,INSERT_VALUES);CHKERRQ(ierr); 197 ierr = MatRestoreRow(Atmp,rstart+i,&nc,(const PetscInt **)&cols,&values);CHKERRQ(ierr); 198 } 199 ierr = PetscFree(ccols);CHKERRQ(ierr); 200 ierr = MatDestroy(Atmp);CHKERRQ(ierr); 201 } else { 202 SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_SUP,"Cannot handle that object type yet"); 203 } 204 next = next->next; 205 } 206 if (com->FormCoupleLocations) { 207 PetscInt __rstart; 208 ierr = MatGetOwnershipRange(*J,&__rstart,PETSC_NULL);CHKERRQ(ierr); 209 ierr = (*com->FormCoupleLocations)(dm,*J,PETSC_NULL,PETSC_NULL,__rstart,0,0,0);CHKERRQ(ierr); 210 } 211 ierr = MatAssemblyBegin(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 212 ierr = MatAssemblyEnd(*J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 213 PetscFunctionReturn(0); 214 } 215 216 #undef __FUNCT__ 217 #define __FUNCT__ "DMGetMatrix_Composite" 218 PetscErrorCode DMGetMatrix_Composite(DM dm,const MatType mtype,Mat *J) 219 { 220 PetscErrorCode ierr; 221 PetscBool usenest; 222 ISLocalToGlobalMapping ltogmap,ltogmapb; 223 224 PetscFunctionBegin; 225 ierr = PetscStrcmp(mtype,MATNEST,&usenest);CHKERRQ(ierr); 226 if (usenest) { 227 ierr = DMGetMatrix_Composite_Nest(dm,mtype,J);CHKERRQ(ierr); 228 } else { 229 ierr = DMGetMatrix_Composite_AIJ(dm,mtype?mtype:MATAIJ,J);CHKERRQ(ierr); 230 } 231 232 ierr = DMGetLocalToGlobalMapping(dm,<ogmap);CHKERRQ(ierr); 233 ierr = DMGetLocalToGlobalMappingBlock(dm,<ogmapb);CHKERRQ(ierr); 234 ierr = MatSetLocalToGlobalMapping(*J,ltogmap,ltogmap);CHKERRQ(ierr); 235 ierr = MatSetLocalToGlobalMappingBlock(*J,ltogmapb,ltogmapb);CHKERRQ(ierr); 236 PetscFunctionReturn(0); 237 } 238