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