1 2 /* 3 Support for the parallel AIJ matrix vector multiply 4 */ 5 #include <../src/mat/impls/aij/mpi/mpiaij.h> 6 7 #undef __FUNCT__ 8 #define __FUNCT__ "MatSetUpMultiply_MPIAIJ" 9 PetscErrorCode MatSetUpMultiply_MPIAIJ(Mat mat) 10 { 11 Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 12 Mat_SeqAIJ *B = (Mat_SeqAIJ*)(aij->B->data); 13 PetscErrorCode ierr; 14 PetscInt i,j,*aj = B->j,ec = 0,*garray; 15 IS from,to; 16 Vec gvec; 17 PetscBool useblockis; 18 #if defined (PETSC_USE_CTABLE) 19 PetscTable gid1_lid1; 20 PetscTablePosition tpos; 21 PetscInt gid,lid; 22 #else 23 PetscInt N = mat->cmap->N,*indices; 24 #endif 25 26 PetscFunctionBegin; 27 28 #if defined (PETSC_USE_CTABLE) 29 /* use a table - Mark Adams */ 30 ierr = PetscTableCreate(aij->B->rmap->n,mat->cmap->N+1,&gid1_lid1);CHKERRQ(ierr); 31 for (i=0; i<aij->B->rmap->n; i++) { 32 for (j=0; j<B->ilen[i]; j++) { 33 PetscInt data,gid1 = aj[B->i[i] + j] + 1; 34 ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr); 35 if (!data) { 36 /* one based table */ 37 ierr = PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES);CHKERRQ(ierr); 38 } 39 } 40 } 41 /* form array of columns we need */ 42 ierr = PetscMalloc((ec+1)*sizeof(PetscInt),&garray);CHKERRQ(ierr); 43 ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr); 44 while (tpos) { 45 ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr); 46 gid--; 47 lid--; 48 garray[lid] = gid; 49 } 50 ierr = PetscSortInt(ec,garray);CHKERRQ(ierr); /* sort, and rebuild */ 51 ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr); 52 for (i=0; i<ec; i++) { 53 ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr); 54 } 55 /* compact out the extra columns in B */ 56 for (i=0; i<aij->B->rmap->n; i++) { 57 for (j=0; j<B->ilen[i]; j++) { 58 PetscInt gid1 = aj[B->i[i] + j] + 1; 59 ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr); 60 lid --; 61 aj[B->i[i] + j] = lid; 62 } 63 } 64 aij->B->cmap->n = aij->B->cmap->N = ec; 65 ierr = PetscLayoutSetUp((aij->B->cmap));CHKERRQ(ierr); 66 ierr = PetscTableDestroy(&gid1_lid1);CHKERRQ(ierr); 67 /* Mark Adams */ 68 #else 69 /* Make an array as long as the number of columns */ 70 /* mark those columns that are in aij->B */ 71 ierr = PetscMalloc((N+1)*sizeof(PetscInt),&indices);CHKERRQ(ierr); 72 ierr = PetscMemzero(indices,N*sizeof(PetscInt));CHKERRQ(ierr); 73 for (i=0; i<aij->B->rmap->n; i++) { 74 for (j=0; j<B->ilen[i]; j++) { 75 if (!indices[aj[B->i[i] + j] ]) ec++; 76 indices[aj[B->i[i] + j] ] = 1; 77 } 78 } 79 80 /* form array of columns we need */ 81 ierr = PetscMalloc((ec+1)*sizeof(PetscInt),&garray);CHKERRQ(ierr); 82 ec = 0; 83 for (i=0; i<N; i++) { 84 if (indices[i]) garray[ec++] = i; 85 } 86 87 /* make indices now point into garray */ 88 for (i=0; i<ec; i++) { 89 indices[garray[i]] = i; 90 } 91 92 /* compact out the extra columns in B */ 93 for (i=0; i<aij->B->rmap->n; i++) { 94 for (j=0; j<B->ilen[i]; j++) { 95 aj[B->i[i] + j] = indices[aj[B->i[i] + j]]; 96 } 97 } 98 aij->B->cmap->n = aij->B->cmap->N = ec; 99 ierr = PetscLayoutSetUp((aij->B->cmap));CHKERRQ(ierr); 100 ierr = PetscFree(indices);CHKERRQ(ierr); 101 #endif 102 /* create local vector that is used to scatter into */ 103 ierr = VecCreateSeq(PETSC_COMM_SELF,ec,&aij->lvec);CHKERRQ(ierr); 104 105 /* create two temporary Index sets for build scatter gather */ 106 /* check for the special case where blocks are communicated for faster VecScatterXXX */ 107 useblockis = PETSC_TRUE; 108 if (mat->rmap->bs > 1) { 109 PetscInt bs = mat->rmap->bs,ibs,ga; 110 if (!(ec % bs)) { 111 for (i=0; i<ec/bs; i++) { 112 if ((ga = garray[ibs = i*bs]) % bs) { 113 useblockis = PETSC_FALSE; 114 break; 115 } 116 for (j=1; j<bs; j++) { 117 if (garray[ibs+j] != ga+j) { 118 useblockis = PETSC_FALSE; 119 break; 120 } 121 } 122 if (!useblockis) break; 123 } 124 } 125 } 126 if (useblockis) { 127 PetscInt *ga,bs = mat->rmap->bs,iec = ec/bs; 128 ierr = PetscInfo(mat,"Using block index set to define scatter\n"); 129 ierr = PetscMalloc((ec/mat->rmap->bs)*sizeof(PetscInt),&ga);CHKERRQ(ierr); 130 for (i=0; i<iec; i++) ga[i] = garray[i*bs]/bs; 131 ierr = ISCreateBlock(((PetscObject)mat)->comm,bs,iec,ga,PETSC_OWN_POINTER,&from);CHKERRQ(ierr); 132 } else { 133 ierr = ISCreateGeneral(((PetscObject)mat)->comm,ec,garray,PETSC_COPY_VALUES,&from);CHKERRQ(ierr); 134 } 135 ierr = ISCreateStride(PETSC_COMM_SELF,ec,0,1,&to);CHKERRQ(ierr); 136 137 /* create temporary global vector to generate scatter context */ 138 /* This does not allocate the array's memory so is efficient */ 139 ierr = VecCreateMPIWithArray(((PetscObject)mat)->comm,mat->cmap->n,mat->cmap->N,PETSC_NULL,&gvec);CHKERRQ(ierr); 140 141 /* generate the scatter context */ 142 ierr = VecScatterCreate(gvec,from,aij->lvec,to,&aij->Mvctx);CHKERRQ(ierr); 143 ierr = PetscLogObjectParent(mat,aij->Mvctx);CHKERRQ(ierr); 144 ierr = PetscLogObjectParent(mat,aij->lvec);CHKERRQ(ierr); 145 ierr = PetscLogObjectParent(mat,from);CHKERRQ(ierr); 146 ierr = PetscLogObjectParent(mat,to);CHKERRQ(ierr); 147 aij->garray = garray; 148 ierr = PetscLogObjectMemory(mat,(ec+1)*sizeof(PetscInt));CHKERRQ(ierr); 149 ierr = ISDestroy(&from);CHKERRQ(ierr); 150 ierr = ISDestroy(&to);CHKERRQ(ierr); 151 ierr = VecDestroy(&gvec);CHKERRQ(ierr); 152 PetscFunctionReturn(0); 153 } 154 155 156 #undef __FUNCT__ 157 #define __FUNCT__ "DisAssemble_MPIAIJ" 158 /* 159 Takes the local part of an already assembled MPIAIJ matrix 160 and disassembles it. This is to allow new nonzeros into the matrix 161 that require more communication in the matrix vector multiply. 162 Thus certain data-structures must be rebuilt. 163 164 Kind of slow! But that's what application programmers get when 165 they are sloppy. 166 */ 167 PetscErrorCode DisAssemble_MPIAIJ(Mat A) 168 { 169 Mat_MPIAIJ *aij = (Mat_MPIAIJ*)A->data; 170 Mat B = aij->B,Bnew; 171 Mat_SeqAIJ *Baij = (Mat_SeqAIJ*)B->data; 172 PetscErrorCode ierr; 173 PetscInt i,j,m = B->rmap->n,n = A->cmap->N,col,ct = 0,*garray = aij->garray,*nz,ec; 174 PetscScalar v; 175 176 PetscFunctionBegin; 177 /* free stuff related to matrix-vec multiply */ 178 ierr = VecGetSize(aij->lvec,&ec);CHKERRQ(ierr); /* needed for PetscLogObjectMemory below */ 179 ierr = VecDestroy(&aij->lvec);CHKERRQ(ierr); aij->lvec = 0; 180 ierr = VecScatterDestroy(&aij->Mvctx);CHKERRQ(ierr); aij->Mvctx = 0; 181 if (aij->colmap) { 182 #if defined (PETSC_USE_CTABLE) 183 ierr = PetscTableDestroy(&aij->colmap);CHKERRQ(ierr); 184 #else 185 ierr = PetscFree(aij->colmap);CHKERRQ(ierr); 186 ierr = PetscLogObjectMemory(A,-aij->B->cmap->n*sizeof(PetscInt));CHKERRQ(ierr); 187 #endif 188 } 189 190 /* make sure that B is assembled so we can access its values */ 191 ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 192 ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 193 194 /* invent new B and copy stuff over */ 195 ierr = PetscMalloc((m+1)*sizeof(PetscInt),&nz);CHKERRQ(ierr); 196 for (i=0; i<m; i++) { 197 nz[i] = Baij->i[i+1] - Baij->i[i]; 198 } 199 ierr = MatCreate(PETSC_COMM_SELF,&Bnew);CHKERRQ(ierr); 200 ierr = MatSetSizes(Bnew,m,n,m,n);CHKERRQ(ierr); 201 ierr = MatSetType(Bnew,((PetscObject)B)->type_name);CHKERRQ(ierr); 202 ierr = MatSeqAIJSetPreallocation(Bnew,0,nz);CHKERRQ(ierr); 203 ((Mat_SeqAIJ*)Bnew->data)->nonew = Baij->nonew; /* Inherit insertion error options. */ 204 ierr = PetscFree(nz);CHKERRQ(ierr); 205 for (i=0; i<m; i++) { 206 for (j=Baij->i[i]; j<Baij->i[i+1]; j++) { 207 col = garray[Baij->j[ct]]; 208 v = Baij->a[ct++]; 209 ierr = MatSetValues(Bnew,1,&i,1,&col,&v,B->insertmode);CHKERRQ(ierr); 210 } 211 } 212 ierr = PetscFree(aij->garray);CHKERRQ(ierr); 213 ierr = PetscLogObjectMemory(A,-ec*sizeof(PetscInt));CHKERRQ(ierr); 214 ierr = MatDestroy(&B);CHKERRQ(ierr); 215 ierr = PetscLogObjectParent(A,Bnew);CHKERRQ(ierr); 216 aij->B = Bnew; 217 A->was_assembled = PETSC_FALSE; 218 PetscFunctionReturn(0); 219 } 220 221 /* ugly stuff added for Glenn someday we should fix this up */ 222 223 static PetscInt *auglyrmapd = 0,*auglyrmapo = 0; /* mapping from the local ordering to the "diagonal" and "off-diagonal" 224 parts of the local matrix */ 225 static Vec auglydd = 0,auglyoo = 0; /* work vectors used to scale the two parts of the local matrix */ 226 227 228 #undef __FUNCT__ 229 #define __FUNCT__ "MatMPIAIJDiagonalScaleLocalSetUp" 230 PetscErrorCode MatMPIAIJDiagonalScaleLocalSetUp(Mat inA,Vec scale) 231 { 232 Mat_MPIAIJ *ina = (Mat_MPIAIJ*) inA->data; /*access private part of matrix */ 233 PetscErrorCode ierr; 234 PetscInt i,n,nt,cstart,cend,no,*garray = ina->garray,*lindices; 235 PetscInt *r_rmapd,*r_rmapo; 236 237 PetscFunctionBegin; 238 ierr = MatGetOwnershipRange(inA,&cstart,&cend);CHKERRQ(ierr); 239 ierr = MatGetSize(ina->A,PETSC_NULL,&n);CHKERRQ(ierr); 240 ierr = PetscMalloc((inA->rmap->mapping->n+1)*sizeof(PetscInt),&r_rmapd);CHKERRQ(ierr); 241 ierr = PetscMemzero(r_rmapd,inA->rmap->mapping->n*sizeof(PetscInt));CHKERRQ(ierr); 242 nt = 0; 243 for (i=0; i<inA->rmap->mapping->n; i++) { 244 if (inA->rmap->mapping->indices[i] >= cstart && inA->rmap->mapping->indices[i] < cend) { 245 nt++; 246 r_rmapd[i] = inA->rmap->mapping->indices[i] + 1; 247 } 248 } 249 if (nt != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Hmm nt %D n %D",nt,n); 250 ierr = PetscMalloc((n+1)*sizeof(PetscInt),&auglyrmapd);CHKERRQ(ierr); 251 for (i=0; i<inA->rmap->mapping->n; i++) { 252 if (r_rmapd[i]){ 253 auglyrmapd[(r_rmapd[i]-1)-cstart] = i; 254 } 255 } 256 ierr = PetscFree(r_rmapd);CHKERRQ(ierr); 257 ierr = VecCreateSeq(PETSC_COMM_SELF,n,&auglydd);CHKERRQ(ierr); 258 259 ierr = PetscMalloc((inA->cmap->N+1)*sizeof(PetscInt),&lindices);CHKERRQ(ierr); 260 ierr = PetscMemzero(lindices,inA->cmap->N*sizeof(PetscInt));CHKERRQ(ierr); 261 for (i=0; i<ina->B->cmap->n; i++) { 262 lindices[garray[i]] = i+1; 263 } 264 no = inA->rmap->mapping->n - nt; 265 ierr = PetscMalloc((inA->rmap->mapping->n+1)*sizeof(PetscInt),&r_rmapo);CHKERRQ(ierr); 266 ierr = PetscMemzero(r_rmapo,inA->rmap->mapping->n*sizeof(PetscInt));CHKERRQ(ierr); 267 nt = 0; 268 for (i=0; i<inA->rmap->mapping->n; i++) { 269 if (lindices[inA->rmap->mapping->indices[i]]) { 270 nt++; 271 r_rmapo[i] = lindices[inA->rmap->mapping->indices[i]]; 272 } 273 } 274 if (nt > no) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Hmm nt %D no %D",nt,n); 275 ierr = PetscFree(lindices);CHKERRQ(ierr); 276 ierr = PetscMalloc((nt+1)*sizeof(PetscInt),&auglyrmapo);CHKERRQ(ierr); 277 for (i=0; i<inA->rmap->mapping->n; i++) { 278 if (r_rmapo[i]){ 279 auglyrmapo[(r_rmapo[i]-1)] = i; 280 } 281 } 282 ierr = PetscFree(r_rmapo);CHKERRQ(ierr); 283 ierr = VecCreateSeq(PETSC_COMM_SELF,nt,&auglyoo);CHKERRQ(ierr); 284 285 PetscFunctionReturn(0); 286 } 287 288 #undef __FUNCT__ 289 #define __FUNCT__ "MatMPIAIJDiagonalScaleLocal" 290 PetscErrorCode MatMPIAIJDiagonalScaleLocal(Mat A,Vec scale) 291 { 292 /* This routine should really be abandoned as it duplicates MatDiagonalScaleLocal */ 293 PetscErrorCode ierr; 294 295 PetscFunctionBegin; 296 ierr = PetscTryMethod(A,"MatDiagonalScaleLocal_C",(Mat,Vec),(A,scale));CHKERRQ(ierr); 297 PetscFunctionReturn(0); 298 } 299 300 EXTERN_C_BEGIN 301 #undef __FUNCT__ 302 #define __FUNCT__ "MatDiagonalScaleLocal_MPIAIJ" 303 PetscErrorCode MatDiagonalScaleLocal_MPIAIJ(Mat A,Vec scale) 304 { 305 Mat_MPIAIJ *a = (Mat_MPIAIJ*) A->data; /*access private part of matrix */ 306 PetscErrorCode ierr; 307 PetscInt n,i; 308 PetscScalar *d,*o,*s; 309 310 PetscFunctionBegin; 311 if (!auglyrmapd) { 312 ierr = MatMPIAIJDiagonalScaleLocalSetUp(A,scale);CHKERRQ(ierr); 313 } 314 315 ierr = VecGetArray(scale,&s);CHKERRQ(ierr); 316 317 ierr = VecGetLocalSize(auglydd,&n);CHKERRQ(ierr); 318 ierr = VecGetArray(auglydd,&d);CHKERRQ(ierr); 319 for (i=0; i<n; i++) { 320 d[i] = s[auglyrmapd[i]]; /* copy "diagonal" (true local) portion of scale into dd vector */ 321 } 322 ierr = VecRestoreArray(auglydd,&d);CHKERRQ(ierr); 323 /* column scale "diagonal" portion of local matrix */ 324 ierr = MatDiagonalScale(a->A,PETSC_NULL,auglydd);CHKERRQ(ierr); 325 326 ierr = VecGetLocalSize(auglyoo,&n);CHKERRQ(ierr); 327 ierr = VecGetArray(auglyoo,&o);CHKERRQ(ierr); 328 for (i=0; i<n; i++) { 329 o[i] = s[auglyrmapo[i]]; /* copy "off-diagonal" portion of scale into oo vector */ 330 } 331 ierr = VecRestoreArray(scale,&s);CHKERRQ(ierr); 332 ierr = VecRestoreArray(auglyoo,&o);CHKERRQ(ierr); 333 /* column scale "off-diagonal" portion of local matrix */ 334 ierr = MatDiagonalScale(a->B,PETSC_NULL,auglyoo);CHKERRQ(ierr); 335 336 PetscFunctionReturn(0); 337 } 338 EXTERN_C_END 339 340 341