18a729477SBarry Smith 2c6db04a5SJed Brown #include <../src/mat/impls/aij/mpi/mpiaij.h> /*I "petscmat.h" I*/ 3c6db04a5SJed Brown #include <petscblaslapack.h> 48a729477SBarry Smith 501bebe75SBarry Smith /*MC 601bebe75SBarry Smith MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 701bebe75SBarry Smith 801bebe75SBarry Smith This matrix type is identical to MATSEQAIJ when constructed with a single process communicator, 901bebe75SBarry Smith and MATMPIAIJ otherwise. As a result, for single process communicators, 1001bebe75SBarry Smith MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation is supported 1101bebe75SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 1201bebe75SBarry Smith the above preallocation routines for simplicity. 1301bebe75SBarry Smith 1401bebe75SBarry Smith Options Database Keys: 1501bebe75SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions() 1601bebe75SBarry Smith 179ae82921SPaul Mullowney Developer Notes: Subclasses include MATAIJCUSP, MATAIJCUSPARSE, MATAIJPERM, MATAIJCRL, and also automatically switches over to use inodes when 1801bebe75SBarry Smith enough exist. 1901bebe75SBarry Smith 2001bebe75SBarry Smith Level: beginner 2101bebe75SBarry Smith 2269b1f4b7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ,MATMPIAIJ 2301bebe75SBarry Smith M*/ 2401bebe75SBarry Smith 2501bebe75SBarry Smith /*MC 2601bebe75SBarry Smith MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 2701bebe75SBarry Smith 2801bebe75SBarry Smith This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator, 2901bebe75SBarry Smith and MATMPIAIJCRL otherwise. As a result, for single process communicators, 3001bebe75SBarry Smith MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 3101bebe75SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 3201bebe75SBarry Smith the above preallocation routines for simplicity. 3301bebe75SBarry Smith 3401bebe75SBarry Smith Options Database Keys: 3501bebe75SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions() 3601bebe75SBarry Smith 3701bebe75SBarry Smith Level: beginner 3801bebe75SBarry Smith 3901bebe75SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL 4001bebe75SBarry Smith M*/ 4101bebe75SBarry Smith 42dd6ea824SBarry Smith #undef __FUNCT__ 43f2c98031SJed Brown #define __FUNCT__ "MatFindNonzeroRows_MPIAIJ" 44f2c98031SJed Brown PetscErrorCode MatFindNonzeroRows_MPIAIJ(Mat M,IS *keptrows) 4527d4218bSShri Abhyankar { 4627d4218bSShri Abhyankar PetscErrorCode ierr; 4727d4218bSShri Abhyankar Mat_MPIAIJ *mat = (Mat_MPIAIJ*)M->data; 4827d4218bSShri Abhyankar Mat_SeqAIJ *a = (Mat_SeqAIJ*)mat->A->data; 4927d4218bSShri Abhyankar Mat_SeqAIJ *b = (Mat_SeqAIJ*)mat->B->data; 5027d4218bSShri Abhyankar const PetscInt *ia,*ib; 5127d4218bSShri Abhyankar const MatScalar *aa,*bb; 5227d4218bSShri Abhyankar PetscInt na,nb,i,j,*rows,cnt=0,n0rows; 5327d4218bSShri Abhyankar PetscInt m = M->rmap->n,rstart = M->rmap->rstart; 5427d4218bSShri Abhyankar 5527d4218bSShri Abhyankar PetscFunctionBegin; 5627d4218bSShri Abhyankar *keptrows = 0; 5727d4218bSShri Abhyankar ia = a->i; 5827d4218bSShri Abhyankar ib = b->i; 5927d4218bSShri Abhyankar for (i=0; i<m; i++) { 6027d4218bSShri Abhyankar na = ia[i+1] - ia[i]; 6127d4218bSShri Abhyankar nb = ib[i+1] - ib[i]; 6227d4218bSShri Abhyankar if (!na && !nb) { 6327d4218bSShri Abhyankar cnt++; 6427d4218bSShri Abhyankar goto ok1; 6527d4218bSShri Abhyankar } 6627d4218bSShri Abhyankar aa = a->a + ia[i]; 6727d4218bSShri Abhyankar for (j=0; j<na; j++) { 6827d4218bSShri Abhyankar if (aa[j] != 0.0) goto ok1; 6927d4218bSShri Abhyankar } 7027d4218bSShri Abhyankar bb = b->a + ib[i]; 7127d4218bSShri Abhyankar for (j=0; j <nb; j++) { 7227d4218bSShri Abhyankar if (bb[j] != 0.0) goto ok1; 7327d4218bSShri Abhyankar } 7427d4218bSShri Abhyankar cnt++; 7527d4218bSShri Abhyankar ok1:; 7627d4218bSShri Abhyankar } 7727d4218bSShri Abhyankar ierr = MPI_Allreduce(&cnt,&n0rows,1,MPIU_INT,MPI_SUM,((PetscObject)M)->comm);CHKERRQ(ierr); 7827d4218bSShri Abhyankar if (!n0rows) PetscFunctionReturn(0); 7927d4218bSShri Abhyankar ierr = PetscMalloc((M->rmap->n-cnt)*sizeof(PetscInt),&rows);CHKERRQ(ierr); 8027d4218bSShri Abhyankar cnt = 0; 8127d4218bSShri Abhyankar for (i=0; i<m; i++) { 8227d4218bSShri Abhyankar na = ia[i+1] - ia[i]; 8327d4218bSShri Abhyankar nb = ib[i+1] - ib[i]; 8427d4218bSShri Abhyankar if (!na && !nb) continue; 8527d4218bSShri Abhyankar aa = a->a + ia[i]; 8627d4218bSShri Abhyankar for(j=0; j<na;j++) { 8727d4218bSShri Abhyankar if (aa[j] != 0.0) { 8827d4218bSShri Abhyankar rows[cnt++] = rstart + i; 8927d4218bSShri Abhyankar goto ok2; 9027d4218bSShri Abhyankar } 9127d4218bSShri Abhyankar } 9227d4218bSShri Abhyankar bb = b->a + ib[i]; 9327d4218bSShri Abhyankar for (j=0; j<nb; j++) { 9427d4218bSShri Abhyankar if (bb[j] != 0.0) { 9527d4218bSShri Abhyankar rows[cnt++] = rstart + i; 9627d4218bSShri Abhyankar goto ok2; 9727d4218bSShri Abhyankar } 9827d4218bSShri Abhyankar } 9927d4218bSShri Abhyankar ok2:; 10027d4218bSShri Abhyankar } 10177c8aea5SJed Brown ierr = ISCreateGeneral(((PetscObject)M)->comm,cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr); 10227d4218bSShri Abhyankar PetscFunctionReturn(0); 10327d4218bSShri Abhyankar } 10427d4218bSShri Abhyankar 10527d4218bSShri Abhyankar #undef __FUNCT__ 106f1f41ecbSJed Brown #define __FUNCT__ "MatFindZeroDiagonals_MPIAIJ" 107f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_MPIAIJ(Mat M,IS *zrows) 108f1f41ecbSJed Brown { 109f1f41ecbSJed Brown Mat_MPIAIJ *aij = (Mat_MPIAIJ*)M->data; 110f1f41ecbSJed Brown PetscErrorCode ierr; 111f1f41ecbSJed Brown PetscInt i,rstart,nrows,*rows; 112f1f41ecbSJed Brown 113f1f41ecbSJed Brown PetscFunctionBegin; 114f1f41ecbSJed Brown *zrows = PETSC_NULL; 115f1f41ecbSJed Brown ierr = MatFindZeroDiagonals_SeqAIJ_Private(aij->A,&nrows,&rows);CHKERRQ(ierr); 116f1f41ecbSJed Brown ierr = MatGetOwnershipRange(M,&rstart,PETSC_NULL);CHKERRQ(ierr); 117f1f41ecbSJed Brown for (i=0; i<nrows; i++) rows[i] += rstart; 118f1f41ecbSJed Brown ierr = ISCreateGeneral(((PetscObject)M)->comm,nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr); 119f1f41ecbSJed Brown PetscFunctionReturn(0); 120f1f41ecbSJed Brown } 121f1f41ecbSJed Brown 122f1f41ecbSJed Brown #undef __FUNCT__ 1230716a85fSBarry Smith #define __FUNCT__ "MatGetColumnNorms_MPIAIJ" 1240716a85fSBarry Smith PetscErrorCode MatGetColumnNorms_MPIAIJ(Mat A,NormType type,PetscReal *norms) 1250716a85fSBarry Smith { 1260716a85fSBarry Smith PetscErrorCode ierr; 1270716a85fSBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)A->data; 1280716a85fSBarry Smith PetscInt i,n,*garray = aij->garray; 1290716a85fSBarry Smith Mat_SeqAIJ *a_aij = (Mat_SeqAIJ*) aij->A->data; 1300716a85fSBarry Smith Mat_SeqAIJ *b_aij = (Mat_SeqAIJ*) aij->B->data; 1310716a85fSBarry Smith PetscReal *work; 1320716a85fSBarry Smith 1330716a85fSBarry Smith PetscFunctionBegin; 1340716a85fSBarry Smith ierr = MatGetSize(A,PETSC_NULL,&n);CHKERRQ(ierr); 1350716a85fSBarry Smith ierr = PetscMalloc(n*sizeof(PetscReal),&work);CHKERRQ(ierr); 1360716a85fSBarry Smith ierr = PetscMemzero(work,n*sizeof(PetscReal));CHKERRQ(ierr); 1370716a85fSBarry Smith if (type == NORM_2) { 1380716a85fSBarry Smith for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) { 1390716a85fSBarry Smith work[A->cmap->rstart + a_aij->j[i]] += PetscAbsScalar(a_aij->a[i]*a_aij->a[i]); 1400716a85fSBarry Smith } 1410716a85fSBarry Smith for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) { 1420716a85fSBarry Smith work[garray[b_aij->j[i]]] += PetscAbsScalar(b_aij->a[i]*b_aij->a[i]); 1430716a85fSBarry Smith } 1440716a85fSBarry Smith } else if (type == NORM_1) { 1450716a85fSBarry Smith for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) { 1460716a85fSBarry Smith work[A->cmap->rstart + a_aij->j[i]] += PetscAbsScalar(a_aij->a[i]); 1470716a85fSBarry Smith } 1480716a85fSBarry Smith for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) { 1490716a85fSBarry Smith work[garray[b_aij->j[i]]] += PetscAbsScalar(b_aij->a[i]); 1500716a85fSBarry Smith } 1510716a85fSBarry Smith } else if (type == NORM_INFINITY) { 1520716a85fSBarry Smith for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) { 1530716a85fSBarry Smith work[A->cmap->rstart + a_aij->j[i]] = PetscMax(PetscAbsScalar(a_aij->a[i]), work[A->cmap->rstart + a_aij->j[i]]); 1540716a85fSBarry Smith } 1550716a85fSBarry Smith for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) { 1560716a85fSBarry Smith work[garray[b_aij->j[i]]] = PetscMax(PetscAbsScalar(b_aij->a[i]),work[garray[b_aij->j[i]]]); 1570716a85fSBarry Smith } 1580716a85fSBarry Smith 1590716a85fSBarry Smith } else SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_WRONG,"Unknown NormType"); 1600716a85fSBarry Smith if (type == NORM_INFINITY) { 1610716a85fSBarry Smith ierr = MPI_Allreduce(work,norms,n,MPIU_REAL,MPIU_MAX,A->hdr.comm);CHKERRQ(ierr); 1620716a85fSBarry Smith } else { 1630716a85fSBarry Smith ierr = MPI_Allreduce(work,norms,n,MPIU_REAL,MPIU_SUM,A->hdr.comm);CHKERRQ(ierr); 1640716a85fSBarry Smith } 1650716a85fSBarry Smith ierr = PetscFree(work);CHKERRQ(ierr); 1660716a85fSBarry Smith if (type == NORM_2) { 1678f1a2a5eSBarry Smith for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]); 1680716a85fSBarry Smith } 1690716a85fSBarry Smith PetscFunctionReturn(0); 1700716a85fSBarry Smith } 1710716a85fSBarry Smith 1720716a85fSBarry Smith #undef __FUNCT__ 173dd6ea824SBarry Smith #define __FUNCT__ "MatDistribute_MPIAIJ" 174dd6ea824SBarry Smith /* 175dd6ea824SBarry Smith Distributes a SeqAIJ matrix across a set of processes. Code stolen from 176dd6ea824SBarry Smith MatLoad_MPIAIJ(). Horrible lack of reuse. Should be a routine for each matrix type. 177dd6ea824SBarry Smith 178dd6ea824SBarry Smith Only for square matrices 179dd6ea824SBarry Smith */ 180dd6ea824SBarry Smith PetscErrorCode MatDistribute_MPIAIJ(MPI_Comm comm,Mat gmat,PetscInt m,MatReuse reuse,Mat *inmat) 181dd6ea824SBarry Smith { 182dd6ea824SBarry Smith PetscMPIInt rank,size; 183dd6ea824SBarry Smith PetscInt *rowners,*dlens,*olens,i,rstart,rend,j,jj,nz,*gmataj,cnt,row,*ld; 184dd6ea824SBarry Smith PetscErrorCode ierr; 185dd6ea824SBarry Smith Mat mat; 186dd6ea824SBarry Smith Mat_SeqAIJ *gmata; 187dd6ea824SBarry Smith PetscMPIInt tag; 188dd6ea824SBarry Smith MPI_Status status; 189ace3abfcSBarry Smith PetscBool aij; 190dd6ea824SBarry Smith MatScalar *gmataa,*ao,*ad,*gmataarestore=0; 191dd6ea824SBarry Smith 192dd6ea824SBarry Smith PetscFunctionBegin; 193dd6ea824SBarry Smith CHKMEMQ; 194dd6ea824SBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 195dd6ea824SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 196dd6ea824SBarry Smith if (!rank) { 197251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)gmat,MATSEQAIJ,&aij);CHKERRQ(ierr); 19865e19b50SBarry Smith if (!aij) SETERRQ1(((PetscObject)gmat)->comm,PETSC_ERR_SUP,"Currently no support for input matrix of type %s\n",((PetscObject)gmat)->type_name); 199dd6ea824SBarry Smith } 200dd6ea824SBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 201dd6ea824SBarry Smith ierr = MatCreate(comm,&mat);CHKERRQ(ierr); 202dd6ea824SBarry Smith ierr = MatSetSizes(mat,m,m,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 203a2f3521dSMark F. Adams ierr = MatSetBlockSizes(mat,gmat->rmap->bs,gmat->cmap->bs);CHKERRQ(ierr); 204dd6ea824SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 205dd6ea824SBarry Smith ierr = PetscMalloc((size+1)*sizeof(PetscInt),&rowners);CHKERRQ(ierr); 206dd6ea824SBarry Smith ierr = PetscMalloc2(m,PetscInt,&dlens,m,PetscInt,&olens);CHKERRQ(ierr); 207dd6ea824SBarry Smith ierr = MPI_Allgather(&m,1,MPIU_INT,rowners+1,1,MPIU_INT,comm);CHKERRQ(ierr); 208dd6ea824SBarry Smith rowners[0] = 0; 209dd6ea824SBarry Smith for (i=2; i<=size; i++) { 210dd6ea824SBarry Smith rowners[i] += rowners[i-1]; 211dd6ea824SBarry Smith } 212dd6ea824SBarry Smith rstart = rowners[rank]; 213dd6ea824SBarry Smith rend = rowners[rank+1]; 214dd6ea824SBarry Smith ierr = PetscObjectGetNewTag((PetscObject)mat,&tag);CHKERRQ(ierr); 215dd6ea824SBarry Smith if (!rank) { 216dd6ea824SBarry Smith gmata = (Mat_SeqAIJ*) gmat->data; 217dd6ea824SBarry Smith /* send row lengths to all processors */ 218dd6ea824SBarry Smith for (i=0; i<m; i++) dlens[i] = gmata->ilen[i]; 219dd6ea824SBarry Smith for (i=1; i<size; i++) { 220dd6ea824SBarry Smith ierr = MPI_Send(gmata->ilen + rowners[i],rowners[i+1]-rowners[i],MPIU_INT,i,tag,comm);CHKERRQ(ierr); 221dd6ea824SBarry Smith } 222dd6ea824SBarry Smith /* determine number diagonal and off-diagonal counts */ 223dd6ea824SBarry Smith ierr = PetscMemzero(olens,m*sizeof(PetscInt));CHKERRQ(ierr); 224dd6ea824SBarry Smith ierr = PetscMalloc(m*sizeof(PetscInt),&ld);CHKERRQ(ierr); 225dd6ea824SBarry Smith ierr = PetscMemzero(ld,m*sizeof(PetscInt));CHKERRQ(ierr); 226dd6ea824SBarry Smith jj = 0; 227dd6ea824SBarry Smith for (i=0; i<m; i++) { 228dd6ea824SBarry Smith for (j=0; j<dlens[i]; j++) { 229dd6ea824SBarry Smith if (gmata->j[jj] < rstart) ld[i]++; 230dd6ea824SBarry Smith if (gmata->j[jj] < rstart || gmata->j[jj] >= rend) olens[i]++; 231dd6ea824SBarry Smith jj++; 232dd6ea824SBarry Smith } 233dd6ea824SBarry Smith } 234dd6ea824SBarry Smith /* send column indices to other processes */ 235dd6ea824SBarry Smith for (i=1; i<size; i++) { 236dd6ea824SBarry Smith nz = gmata->i[rowners[i+1]]-gmata->i[rowners[i]]; 237dd6ea824SBarry Smith ierr = MPI_Send(&nz,1,MPIU_INT,i,tag,comm);CHKERRQ(ierr); 238dd6ea824SBarry Smith ierr = MPI_Send(gmata->j + gmata->i[rowners[i]],nz,MPIU_INT,i,tag,comm);CHKERRQ(ierr); 239dd6ea824SBarry Smith } 240dd6ea824SBarry Smith 241dd6ea824SBarry Smith /* send numerical values to other processes */ 242dd6ea824SBarry Smith for (i=1; i<size; i++) { 243dd6ea824SBarry Smith nz = gmata->i[rowners[i+1]]-gmata->i[rowners[i]]; 244dd6ea824SBarry Smith ierr = MPI_Send(gmata->a + gmata->i[rowners[i]],nz,MPIU_SCALAR,i,tag,comm);CHKERRQ(ierr); 245dd6ea824SBarry Smith } 246dd6ea824SBarry Smith gmataa = gmata->a; 247dd6ea824SBarry Smith gmataj = gmata->j; 248dd6ea824SBarry Smith 249dd6ea824SBarry Smith } else { 250dd6ea824SBarry Smith /* receive row lengths */ 251dd6ea824SBarry Smith ierr = MPI_Recv(dlens,m,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr); 252dd6ea824SBarry Smith /* receive column indices */ 253dd6ea824SBarry Smith ierr = MPI_Recv(&nz,1,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr); 254dd6ea824SBarry Smith ierr = PetscMalloc2(nz,PetscScalar,&gmataa,nz,PetscInt,&gmataj);CHKERRQ(ierr); 255dd6ea824SBarry Smith ierr = MPI_Recv(gmataj,nz,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr); 256dd6ea824SBarry Smith /* determine number diagonal and off-diagonal counts */ 257dd6ea824SBarry Smith ierr = PetscMemzero(olens,m*sizeof(PetscInt));CHKERRQ(ierr); 258dd6ea824SBarry Smith ierr = PetscMalloc(m*sizeof(PetscInt),&ld);CHKERRQ(ierr); 259dd6ea824SBarry Smith ierr = PetscMemzero(ld,m*sizeof(PetscInt));CHKERRQ(ierr); 260dd6ea824SBarry Smith jj = 0; 261dd6ea824SBarry Smith for (i=0; i<m; i++) { 262dd6ea824SBarry Smith for (j=0; j<dlens[i]; j++) { 263dd6ea824SBarry Smith if (gmataj[jj] < rstart) ld[i]++; 264dd6ea824SBarry Smith if (gmataj[jj] < rstart || gmataj[jj] >= rend) olens[i]++; 265dd6ea824SBarry Smith jj++; 266dd6ea824SBarry Smith } 267dd6ea824SBarry Smith } 268dd6ea824SBarry Smith /* receive numerical values */ 269dd6ea824SBarry Smith ierr = PetscMemzero(gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); 270dd6ea824SBarry Smith ierr = MPI_Recv(gmataa,nz,MPIU_SCALAR,0,tag,comm,&status);CHKERRQ(ierr); 271dd6ea824SBarry Smith } 272dd6ea824SBarry Smith /* set preallocation */ 273dd6ea824SBarry Smith for (i=0; i<m; i++) { 274dd6ea824SBarry Smith dlens[i] -= olens[i]; 275dd6ea824SBarry Smith } 276dd6ea824SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dlens);CHKERRQ(ierr); 277dd6ea824SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dlens,0,olens);CHKERRQ(ierr); 278dd6ea824SBarry Smith 279dd6ea824SBarry Smith for (i=0; i<m; i++) { 280dd6ea824SBarry Smith dlens[i] += olens[i]; 281dd6ea824SBarry Smith } 282dd6ea824SBarry Smith cnt = 0; 283dd6ea824SBarry Smith for (i=0; i<m; i++) { 284dd6ea824SBarry Smith row = rstart + i; 285dd6ea824SBarry Smith ierr = MatSetValues(mat,1,&row,dlens[i],gmataj+cnt,gmataa+cnt,INSERT_VALUES);CHKERRQ(ierr); 286dd6ea824SBarry Smith cnt += dlens[i]; 287dd6ea824SBarry Smith } 288dd6ea824SBarry Smith if (rank) { 289dd6ea824SBarry Smith ierr = PetscFree2(gmataa,gmataj);CHKERRQ(ierr); 290dd6ea824SBarry Smith } 291dd6ea824SBarry Smith ierr = PetscFree2(dlens,olens);CHKERRQ(ierr); 292dd6ea824SBarry Smith ierr = PetscFree(rowners);CHKERRQ(ierr); 293dd6ea824SBarry Smith ((Mat_MPIAIJ*)(mat->data))->ld = ld; 294dd6ea824SBarry Smith *inmat = mat; 295dd6ea824SBarry Smith } else { /* column indices are already set; only need to move over numerical values from process 0 */ 296dd6ea824SBarry Smith Mat_SeqAIJ *Ad = (Mat_SeqAIJ*)((Mat_MPIAIJ*)((*inmat)->data))->A->data; 297dd6ea824SBarry Smith Mat_SeqAIJ *Ao = (Mat_SeqAIJ*)((Mat_MPIAIJ*)((*inmat)->data))->B->data; 298dd6ea824SBarry Smith mat = *inmat; 299dd6ea824SBarry Smith ierr = PetscObjectGetNewTag((PetscObject)mat,&tag);CHKERRQ(ierr); 300dd6ea824SBarry Smith if (!rank) { 301dd6ea824SBarry Smith /* send numerical values to other processes */ 302dd6ea824SBarry Smith gmata = (Mat_SeqAIJ*) gmat->data; 303dd6ea824SBarry Smith ierr = MatGetOwnershipRanges(mat,(const PetscInt**)&rowners);CHKERRQ(ierr); 304dd6ea824SBarry Smith gmataa = gmata->a; 305dd6ea824SBarry Smith for (i=1; i<size; i++) { 306dd6ea824SBarry Smith nz = gmata->i[rowners[i+1]]-gmata->i[rowners[i]]; 307dd6ea824SBarry Smith ierr = MPI_Send(gmataa + gmata->i[rowners[i]],nz,MPIU_SCALAR,i,tag,comm);CHKERRQ(ierr); 308dd6ea824SBarry Smith } 309dd6ea824SBarry Smith nz = gmata->i[rowners[1]]-gmata->i[rowners[0]]; 310dd6ea824SBarry Smith } else { 311dd6ea824SBarry Smith /* receive numerical values from process 0*/ 312dd6ea824SBarry Smith nz = Ad->nz + Ao->nz; 313dd6ea824SBarry Smith ierr = PetscMalloc(nz*sizeof(PetscScalar),&gmataa);CHKERRQ(ierr); gmataarestore = gmataa; 314dd6ea824SBarry Smith ierr = MPI_Recv(gmataa,nz,MPIU_SCALAR,0,tag,comm,&status);CHKERRQ(ierr); 315dd6ea824SBarry Smith } 316dd6ea824SBarry Smith /* transfer numerical values into the diagonal A and off diagonal B parts of mat */ 317dd6ea824SBarry Smith ld = ((Mat_MPIAIJ*)(mat->data))->ld; 318dd6ea824SBarry Smith ad = Ad->a; 319dd6ea824SBarry Smith ao = Ao->a; 320d0f46423SBarry Smith if (mat->rmap->n) { 321dd6ea824SBarry Smith i = 0; 322dd6ea824SBarry Smith nz = ld[i]; ierr = PetscMemcpy(ao,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ao += nz; gmataa += nz; 323dd6ea824SBarry Smith nz = Ad->i[i+1] - Ad->i[i]; ierr = PetscMemcpy(ad,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ad += nz; gmataa += nz; 324dd6ea824SBarry Smith } 325d0f46423SBarry Smith for (i=1; i<mat->rmap->n; i++) { 326dd6ea824SBarry Smith nz = Ao->i[i] - Ao->i[i-1] - ld[i-1] + ld[i]; ierr = PetscMemcpy(ao,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ao += nz; gmataa += nz; 327dd6ea824SBarry Smith nz = Ad->i[i+1] - Ad->i[i]; ierr = PetscMemcpy(ad,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ad += nz; gmataa += nz; 328dd6ea824SBarry Smith } 329dd6ea824SBarry Smith i--; 330d0f46423SBarry Smith if (mat->rmap->n) { 331dd6ea824SBarry Smith nz = Ao->i[i+1] - Ao->i[i] - ld[i]; ierr = PetscMemcpy(ao,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ao += nz; gmataa += nz; 332dd6ea824SBarry Smith } 333dd6ea824SBarry Smith if (rank) { 334dd6ea824SBarry Smith ierr = PetscFree(gmataarestore);CHKERRQ(ierr); 335dd6ea824SBarry Smith } 336dd6ea824SBarry Smith } 337dd6ea824SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 338dd6ea824SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 339dd6ea824SBarry Smith CHKMEMQ; 340dd6ea824SBarry Smith PetscFunctionReturn(0); 341dd6ea824SBarry Smith } 342dd6ea824SBarry Smith 3430f5bd95cSBarry Smith /* 3440f5bd95cSBarry Smith Local utility routine that creates a mapping from the global column 3459e25ed09SBarry Smith number to the local number in the off-diagonal part of the local 3460f5bd95cSBarry Smith storage of the matrix. When PETSC_USE_CTABLE is used this is scalable at 3470f5bd95cSBarry Smith a slightly higher hash table cost; without it it is not scalable (each processor 3480f5bd95cSBarry Smith has an order N integer array but is fast to acess. 3499e25ed09SBarry Smith */ 3504a2ae208SSatish Balay #undef __FUNCT__ 351ab9863d7SBarry Smith #define __FUNCT__ "MatCreateColmap_MPIAIJ_Private" 352ab9863d7SBarry Smith PetscErrorCode MatCreateColmap_MPIAIJ_Private(Mat mat) 3539e25ed09SBarry Smith { 35444a69424SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 3556849ba73SBarry Smith PetscErrorCode ierr; 356d0f46423SBarry Smith PetscInt n = aij->B->cmap->n,i; 357dbb450caSBarry Smith 3583a40ed3dSBarry Smith PetscFunctionBegin; 3595e1f6667SBarry Smith if (!aij->garray) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"MPIAIJ Matrix was assembled but is missing garray"); 360aa482453SBarry Smith #if defined (PETSC_USE_CTABLE) 361e23dfa41SBarry Smith ierr = PetscTableCreate(n,mat->cmap->N+1,&aij->colmap);CHKERRQ(ierr); 362b1fc9764SSatish Balay for (i=0; i<n; i++){ 3633861aac3SJed Brown ierr = PetscTableAdd(aij->colmap,aij->garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr); 364b1fc9764SSatish Balay } 365b1fc9764SSatish Balay #else 366d0f46423SBarry Smith ierr = PetscMalloc((mat->cmap->N+1)*sizeof(PetscInt),&aij->colmap);CHKERRQ(ierr); 367d0f46423SBarry Smith ierr = PetscLogObjectMemory(mat,mat->cmap->N*sizeof(PetscInt));CHKERRQ(ierr); 368d0f46423SBarry Smith ierr = PetscMemzero(aij->colmap,mat->cmap->N*sizeof(PetscInt));CHKERRQ(ierr); 369905e6a2fSBarry Smith for (i=0; i<n; i++) aij->colmap[aij->garray[i]] = i+1; 370b1fc9764SSatish Balay #endif 3713a40ed3dSBarry Smith PetscFunctionReturn(0); 3729e25ed09SBarry Smith } 3739e25ed09SBarry Smith 37430770e4dSSatish Balay #define MatSetValues_SeqAIJ_A_Private(row,col,value,addv) \ 3750520107fSSatish Balay { \ 3767cd84e04SBarry Smith if (col <= lastcol1) low1 = 0; else high1 = nrow1; \ 377fd3458f5SBarry Smith lastcol1 = col;\ 378fd3458f5SBarry Smith while (high1-low1 > 5) { \ 379fd3458f5SBarry Smith t = (low1+high1)/2; \ 380fd3458f5SBarry Smith if (rp1[t] > col) high1 = t; \ 381fd3458f5SBarry Smith else low1 = t; \ 382ba4e3ef2SSatish Balay } \ 383fd3458f5SBarry Smith for (_i=low1; _i<high1; _i++) { \ 384fd3458f5SBarry Smith if (rp1[_i] > col) break; \ 385fd3458f5SBarry Smith if (rp1[_i] == col) { \ 386fd3458f5SBarry Smith if (addv == ADD_VALUES) ap1[_i] += value; \ 387fd3458f5SBarry Smith else ap1[_i] = value; \ 38830770e4dSSatish Balay goto a_noinsert; \ 3890520107fSSatish Balay } \ 3900520107fSSatish Balay } \ 391e44c0bd4SBarry Smith if (value == 0.0 && ignorezeroentries) {low1 = 0; high1 = nrow1;goto a_noinsert;} \ 392e44c0bd4SBarry Smith if (nonew == 1) {low1 = 0; high1 = nrow1; goto a_noinsert;} \ 393e32f2f54SBarry Smith if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) into matrix", row, col); \ 394fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A,am,1,nrow1,row,col,rmax1,aa,ai,aj,rp1,ap1,aimax,nonew,MatScalar); \ 395669a8dbcSSatish Balay N = nrow1++ - 1; a->nz++; high1++; \ 3960520107fSSatish Balay /* shift up all the later entries in this row */ \ 3970520107fSSatish Balay for (ii=N; ii>=_i; ii--) { \ 398fd3458f5SBarry Smith rp1[ii+1] = rp1[ii]; \ 399fd3458f5SBarry Smith ap1[ii+1] = ap1[ii]; \ 4000520107fSSatish Balay } \ 401fd3458f5SBarry Smith rp1[_i] = col; \ 402fd3458f5SBarry Smith ap1[_i] = value; \ 40330770e4dSSatish Balay a_noinsert: ; \ 404fd3458f5SBarry Smith ailen[row] = nrow1; \ 4050520107fSSatish Balay } 4060a198c4cSBarry Smith 407085a36d4SBarry Smith 40830770e4dSSatish Balay #define MatSetValues_SeqAIJ_B_Private(row,col,value,addv) \ 40930770e4dSSatish Balay { \ 4107cd84e04SBarry Smith if (col <= lastcol2) low2 = 0; else high2 = nrow2; \ 411fd3458f5SBarry Smith lastcol2 = col;\ 412fd3458f5SBarry Smith while (high2-low2 > 5) { \ 413fd3458f5SBarry Smith t = (low2+high2)/2; \ 414fd3458f5SBarry Smith if (rp2[t] > col) high2 = t; \ 415fd3458f5SBarry Smith else low2 = t; \ 416ba4e3ef2SSatish Balay } \ 417fd3458f5SBarry Smith for (_i=low2; _i<high2; _i++) { \ 418fd3458f5SBarry Smith if (rp2[_i] > col) break; \ 419fd3458f5SBarry Smith if (rp2[_i] == col) { \ 420fd3458f5SBarry Smith if (addv == ADD_VALUES) ap2[_i] += value; \ 421fd3458f5SBarry Smith else ap2[_i] = value; \ 42230770e4dSSatish Balay goto b_noinsert; \ 42330770e4dSSatish Balay } \ 42430770e4dSSatish Balay } \ 425e44c0bd4SBarry Smith if (value == 0.0 && ignorezeroentries) {low2 = 0; high2 = nrow2; goto b_noinsert;} \ 426e44c0bd4SBarry Smith if (nonew == 1) {low2 = 0; high2 = nrow2; goto b_noinsert;} \ 427e32f2f54SBarry Smith if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero (%D, %D) into matrix", row, col); \ 428fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(B,bm,1,nrow2,row,col,rmax2,ba,bi,bj,rp2,ap2,bimax,nonew,MatScalar); \ 429669a8dbcSSatish Balay N = nrow2++ - 1; b->nz++; high2++; \ 43030770e4dSSatish Balay /* shift up all the later entries in this row */ \ 43130770e4dSSatish Balay for (ii=N; ii>=_i; ii--) { \ 432fd3458f5SBarry Smith rp2[ii+1] = rp2[ii]; \ 433fd3458f5SBarry Smith ap2[ii+1] = ap2[ii]; \ 43430770e4dSSatish Balay } \ 435fd3458f5SBarry Smith rp2[_i] = col; \ 436fd3458f5SBarry Smith ap2[_i] = value; \ 43730770e4dSSatish Balay b_noinsert: ; \ 438fd3458f5SBarry Smith bilen[row] = nrow2; \ 43930770e4dSSatish Balay } 44030770e4dSSatish Balay 4414a2ae208SSatish Balay #undef __FUNCT__ 4422fd7e33dSBarry Smith #define __FUNCT__ "MatSetValuesRow_MPIAIJ" 4432fd7e33dSBarry Smith PetscErrorCode MatSetValuesRow_MPIAIJ(Mat A,PetscInt row,const PetscScalar v[]) 4442fd7e33dSBarry Smith { 4452fd7e33dSBarry Smith Mat_MPIAIJ *mat = (Mat_MPIAIJ*)A->data; 4462fd7e33dSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)mat->A->data,*b = (Mat_SeqAIJ*)mat->B->data; 4472fd7e33dSBarry Smith PetscErrorCode ierr; 4482fd7e33dSBarry Smith PetscInt l,*garray = mat->garray,diag; 4492fd7e33dSBarry Smith 4502fd7e33dSBarry Smith PetscFunctionBegin; 4512fd7e33dSBarry Smith /* code only works for square matrices A */ 4522fd7e33dSBarry Smith 4532fd7e33dSBarry Smith /* find size of row to the left of the diagonal part */ 4542fd7e33dSBarry Smith ierr = MatGetOwnershipRange(A,&diag,0);CHKERRQ(ierr); 4552fd7e33dSBarry Smith row = row - diag; 4562fd7e33dSBarry Smith for (l=0; l<b->i[row+1]-b->i[row]; l++) { 4572fd7e33dSBarry Smith if (garray[b->j[b->i[row]+l]] > diag) break; 4582fd7e33dSBarry Smith } 4592fd7e33dSBarry Smith ierr = PetscMemcpy(b->a+b->i[row],v,l*sizeof(PetscScalar));CHKERRQ(ierr); 4602fd7e33dSBarry Smith 4612fd7e33dSBarry Smith /* diagonal part */ 4622fd7e33dSBarry Smith ierr = PetscMemcpy(a->a+a->i[row],v+l,(a->i[row+1]-a->i[row])*sizeof(PetscScalar));CHKERRQ(ierr); 4632fd7e33dSBarry Smith 4642fd7e33dSBarry Smith /* right of diagonal part */ 4652fd7e33dSBarry Smith ierr = PetscMemcpy(b->a+b->i[row]+l,v+l+a->i[row+1]-a->i[row],(b->i[row+1]-b->i[row]-l)*sizeof(PetscScalar));CHKERRQ(ierr); 4662fd7e33dSBarry Smith PetscFunctionReturn(0); 4672fd7e33dSBarry Smith } 4682fd7e33dSBarry Smith 4692fd7e33dSBarry Smith #undef __FUNCT__ 4704a2ae208SSatish Balay #define __FUNCT__ "MatSetValues_MPIAIJ" 471b1d57f15SBarry Smith PetscErrorCode MatSetValues_MPIAIJ(Mat mat,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode addv) 4728a729477SBarry Smith { 47344a69424SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 47487828ca2SBarry Smith PetscScalar value; 475dfbe8321SBarry Smith PetscErrorCode ierr; 476d0f46423SBarry Smith PetscInt i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend; 477d0f46423SBarry Smith PetscInt cstart = mat->cmap->rstart,cend = mat->cmap->rend,row,col; 478ace3abfcSBarry Smith PetscBool roworiented = aij->roworiented; 4798a729477SBarry Smith 4800520107fSSatish Balay /* Some Variables required in the macro */ 4814ee7247eSSatish Balay Mat A = aij->A; 4824ee7247eSSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 48357809a77SBarry Smith PetscInt *aimax = a->imax,*ai = a->i,*ailen = a->ilen,*aj = a->j; 484a77337e4SBarry Smith MatScalar *aa = a->a; 485ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 48630770e4dSSatish Balay Mat B = aij->B; 48730770e4dSSatish Balay Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 488d0f46423SBarry Smith PetscInt *bimax = b->imax,*bi = b->i,*bilen = b->ilen,*bj = b->j,bm = aij->B->rmap->n,am = aij->A->rmap->n; 489a77337e4SBarry Smith MatScalar *ba = b->a; 49030770e4dSSatish Balay 491fd3458f5SBarry Smith PetscInt *rp1,*rp2,ii,nrow1,nrow2,_i,rmax1,rmax2,N,low1,high1,low2,high2,t,lastcol1,lastcol2; 4928d76821aSHong Zhang PetscInt nonew; 493a77337e4SBarry Smith MatScalar *ap1,*ap2; 4944ee7247eSSatish Balay 4953a40ed3dSBarry Smith PetscFunctionBegin; 49671fd2e92SBarry Smith if (v) PetscValidScalarPointer(v,6); 4978a729477SBarry Smith for (i=0; i<m; i++) { 4985ef9f2a5SBarry Smith if (im[i] < 0) continue; 4992515c552SBarry Smith #if defined(PETSC_USE_DEBUG) 500e32f2f54SBarry Smith if (im[i] >= mat->rmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",im[i],mat->rmap->N-1); 5010a198c4cSBarry Smith #endif 5024b0e389bSBarry Smith if (im[i] >= rstart && im[i] < rend) { 5034b0e389bSBarry Smith row = im[i] - rstart; 504fd3458f5SBarry Smith lastcol1 = -1; 505fd3458f5SBarry Smith rp1 = aj + ai[row]; 506fd3458f5SBarry Smith ap1 = aa + ai[row]; 507fd3458f5SBarry Smith rmax1 = aimax[row]; 508fd3458f5SBarry Smith nrow1 = ailen[row]; 509fd3458f5SBarry Smith low1 = 0; 510fd3458f5SBarry Smith high1 = nrow1; 511fd3458f5SBarry Smith lastcol2 = -1; 512fd3458f5SBarry Smith rp2 = bj + bi[row]; 513d498b1e9SBarry Smith ap2 = ba + bi[row]; 514fd3458f5SBarry Smith rmax2 = bimax[row]; 515d498b1e9SBarry Smith nrow2 = bilen[row]; 516fd3458f5SBarry Smith low2 = 0; 517fd3458f5SBarry Smith high2 = nrow2; 518fd3458f5SBarry Smith 5191eb62cbbSBarry Smith for (j=0; j<n; j++) { 52016371a99SBarry Smith if (v) {if (roworiented) value = v[i*n+j]; else value = v[i+j*m];} else value = 0.0; 521abc0a331SBarry Smith if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue; 522fd3458f5SBarry Smith if (in[j] >= cstart && in[j] < cend){ 523fd3458f5SBarry Smith col = in[j] - cstart; 5248d76821aSHong Zhang nonew = a->nonew; 52530770e4dSSatish Balay MatSetValues_SeqAIJ_A_Private(row,col,value,addv); 526273d9f13SBarry Smith } else if (in[j] < 0) continue; 5272515c552SBarry Smith #if defined(PETSC_USE_DEBUG) 528cb9801acSJed Brown else if (in[j] >= mat->cmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[j],mat->cmap->N-1); 5290a198c4cSBarry Smith #endif 5301eb62cbbSBarry Smith else { 531227d817aSBarry Smith if (mat->was_assembled) { 532905e6a2fSBarry Smith if (!aij->colmap) { 533ab9863d7SBarry Smith ierr = MatCreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr); 534905e6a2fSBarry Smith } 535aa482453SBarry Smith #if defined (PETSC_USE_CTABLE) 5360f5bd95cSBarry Smith ierr = PetscTableFind(aij->colmap,in[j]+1,&col);CHKERRQ(ierr); 537fa46199cSSatish Balay col--; 538b1fc9764SSatish Balay #else 539905e6a2fSBarry Smith col = aij->colmap[in[j]] - 1; 540b1fc9764SSatish Balay #endif 541ec8511deSBarry Smith if (col < 0 && !((Mat_SeqAIJ*)(aij->A->data))->nonew) { 542ab9863d7SBarry Smith ierr = MatDisAssemble_MPIAIJ(mat);CHKERRQ(ierr); 5434b0e389bSBarry Smith col = in[j]; 5449bf004c3SSatish Balay /* Reinitialize the variables required by MatSetValues_SeqAIJ_B_Private() */ 545f9508a3cSSatish Balay B = aij->B; 546f9508a3cSSatish Balay b = (Mat_SeqAIJ*)B->data; 547e44c0bd4SBarry Smith bimax = b->imax; bi = b->i; bilen = b->ilen; bj = b->j; ba = b->a; 548d498b1e9SBarry Smith rp2 = bj + bi[row]; 549d498b1e9SBarry Smith ap2 = ba + bi[row]; 550d498b1e9SBarry Smith rmax2 = bimax[row]; 551d498b1e9SBarry Smith nrow2 = bilen[row]; 552d498b1e9SBarry Smith low2 = 0; 553d498b1e9SBarry Smith high2 = nrow2; 554d0f46423SBarry Smith bm = aij->B->rmap->n; 555f9508a3cSSatish Balay ba = b->a; 556d6dfbf8fSBarry Smith } 557c48de900SBarry Smith } else col = in[j]; 5588d76821aSHong Zhang nonew = b->nonew; 55930770e4dSSatish Balay MatSetValues_SeqAIJ_B_Private(row,col,value,addv); 5601eb62cbbSBarry Smith } 5611eb62cbbSBarry Smith } 5625ef9f2a5SBarry Smith } else { 5634cb17eb5SBarry Smith if (mat->nooffprocentries) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Setting off process row %D even though MatSetOption(,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) was set",im[i]); 56490f02eecSBarry Smith if (!aij->donotstash) { 5655080c13bSMatthew G Knepley mat->assembled = PETSC_FALSE; 566d36fbae8SSatish Balay if (roworiented) { 567ace3abfcSBarry Smith ierr = MatStashValuesRow_Private(&mat->stash,im[i],n,in,v+i*n,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr); 568d36fbae8SSatish Balay } else { 569ace3abfcSBarry Smith ierr = MatStashValuesCol_Private(&mat->stash,im[i],n,in,v+i,m,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr); 5704b0e389bSBarry Smith } 5711eb62cbbSBarry Smith } 5728a729477SBarry Smith } 57390f02eecSBarry Smith } 5743a40ed3dSBarry Smith PetscFunctionReturn(0); 5758a729477SBarry Smith } 5768a729477SBarry Smith 5774a2ae208SSatish Balay #undef __FUNCT__ 5784a2ae208SSatish Balay #define __FUNCT__ "MatGetValues_MPIAIJ" 579b1d57f15SBarry Smith PetscErrorCode MatGetValues_MPIAIJ(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[]) 580b49de8d1SLois Curfman McInnes { 581b49de8d1SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 582dfbe8321SBarry Smith PetscErrorCode ierr; 583d0f46423SBarry Smith PetscInt i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend; 584d0f46423SBarry Smith PetscInt cstart = mat->cmap->rstart,cend = mat->cmap->rend,row,col; 585b49de8d1SLois Curfman McInnes 5863a40ed3dSBarry Smith PetscFunctionBegin; 587b49de8d1SLois Curfman McInnes for (i=0; i<m; i++) { 588e32f2f54SBarry Smith if (idxm[i] < 0) continue; /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",idxm[i]);*/ 589e32f2f54SBarry Smith if (idxm[i] >= mat->rmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",idxm[i],mat->rmap->N-1); 590b49de8d1SLois Curfman McInnes if (idxm[i] >= rstart && idxm[i] < rend) { 591b49de8d1SLois Curfman McInnes row = idxm[i] - rstart; 592b49de8d1SLois Curfman McInnes for (j=0; j<n; j++) { 593e32f2f54SBarry Smith if (idxn[j] < 0) continue; /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",idxn[j]); */ 594e32f2f54SBarry Smith if (idxn[j] >= mat->cmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",idxn[j],mat->cmap->N-1); 595b49de8d1SLois Curfman McInnes if (idxn[j] >= cstart && idxn[j] < cend){ 596b49de8d1SLois Curfman McInnes col = idxn[j] - cstart; 597b49de8d1SLois Curfman McInnes ierr = MatGetValues(aij->A,1,&row,1,&col,v+i*n+j);CHKERRQ(ierr); 598fa852ad4SSatish Balay } else { 599905e6a2fSBarry Smith if (!aij->colmap) { 600ab9863d7SBarry Smith ierr = MatCreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr); 601905e6a2fSBarry Smith } 602aa482453SBarry Smith #if defined (PETSC_USE_CTABLE) 6030f5bd95cSBarry Smith ierr = PetscTableFind(aij->colmap,idxn[j]+1,&col);CHKERRQ(ierr); 604fa46199cSSatish Balay col --; 605b1fc9764SSatish Balay #else 606905e6a2fSBarry Smith col = aij->colmap[idxn[j]] - 1; 607b1fc9764SSatish Balay #endif 608e60e1c95SSatish Balay if ((col < 0) || (aij->garray[col] != idxn[j])) *(v+i*n+j) = 0.0; 609d9d09a02SSatish Balay else { 610b49de8d1SLois Curfman McInnes ierr = MatGetValues(aij->B,1,&row,1,&col,v+i*n+j);CHKERRQ(ierr); 611b49de8d1SLois Curfman McInnes } 612b49de8d1SLois Curfman McInnes } 613b49de8d1SLois Curfman McInnes } 614a8c6a408SBarry Smith } else { 615e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only local values currently supported"); 616b49de8d1SLois Curfman McInnes } 617b49de8d1SLois Curfman McInnes } 6183a40ed3dSBarry Smith PetscFunctionReturn(0); 619b49de8d1SLois Curfman McInnes } 620bc5ccf88SSatish Balay 621bd0c2dcbSBarry Smith extern PetscErrorCode MatMultDiagonalBlock_MPIAIJ(Mat,Vec,Vec); 622bd0c2dcbSBarry Smith 6234a2ae208SSatish Balay #undef __FUNCT__ 6244a2ae208SSatish Balay #define __FUNCT__ "MatAssemblyBegin_MPIAIJ" 625dfbe8321SBarry Smith PetscErrorCode MatAssemblyBegin_MPIAIJ(Mat mat,MatAssemblyType mode) 626bc5ccf88SSatish Balay { 627bc5ccf88SSatish Balay Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 628dfbe8321SBarry Smith PetscErrorCode ierr; 629b1d57f15SBarry Smith PetscInt nstash,reallocs; 630bc5ccf88SSatish Balay InsertMode addv; 631bc5ccf88SSatish Balay 632bc5ccf88SSatish Balay PetscFunctionBegin; 6334cb17eb5SBarry Smith if (aij->donotstash || mat->nooffprocentries) { 634bc5ccf88SSatish Balay PetscFunctionReturn(0); 635bc5ccf88SSatish Balay } 636bc5ccf88SSatish Balay 637bc5ccf88SSatish Balay /* make sure all processors are either in INSERTMODE or ADDMODE */ 6387adad957SLisandro Dalcin ierr = MPI_Allreduce(&mat->insertmode,&addv,1,MPI_INT,MPI_BOR,((PetscObject)mat)->comm);CHKERRQ(ierr); 639e7e72b3dSBarry Smith if (addv == (ADD_VALUES|INSERT_VALUES)) SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_ARG_WRONGSTATE,"Some processors inserted others added"); 640bc5ccf88SSatish Balay mat->insertmode = addv; /* in case this processor had no cache */ 641bc5ccf88SSatish Balay 642d0f46423SBarry Smith ierr = MatStashScatterBegin_Private(mat,&mat->stash,mat->rmap->range);CHKERRQ(ierr); 6438798bf22SSatish Balay ierr = MatStashGetInfo_Private(&mat->stash,&nstash,&reallocs);CHKERRQ(ierr); 644ae15b995SBarry Smith ierr = PetscInfo2(aij->A,"Stash has %D entries, uses %D mallocs.\n",nstash,reallocs);CHKERRQ(ierr); 645bc5ccf88SSatish Balay PetscFunctionReturn(0); 646bc5ccf88SSatish Balay } 647bc5ccf88SSatish Balay 6484a2ae208SSatish Balay #undef __FUNCT__ 6494a2ae208SSatish Balay #define __FUNCT__ "MatAssemblyEnd_MPIAIJ" 650dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_MPIAIJ(Mat mat,MatAssemblyType mode) 651bc5ccf88SSatish Balay { 652bc5ccf88SSatish Balay Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 65391c97fd4SSatish Balay Mat_SeqAIJ *a=(Mat_SeqAIJ *)aij->A->data; 6546849ba73SBarry Smith PetscErrorCode ierr; 655b1d57f15SBarry Smith PetscMPIInt n; 656b1d57f15SBarry Smith PetscInt i,j,rstart,ncols,flg; 657e44c0bd4SBarry Smith PetscInt *row,*col; 658ace3abfcSBarry Smith PetscBool other_disassembled; 65987828ca2SBarry Smith PetscScalar *val; 660bc5ccf88SSatish Balay InsertMode addv = mat->insertmode; 661bc5ccf88SSatish Balay 66291c97fd4SSatish Balay /* do not use 'b = (Mat_SeqAIJ *)aij->B->data' as B can be reset in disassembly */ 663bc5ccf88SSatish Balay PetscFunctionBegin; 6644cb17eb5SBarry Smith if (!aij->donotstash && !mat->nooffprocentries) { 665a2d1c673SSatish Balay while (1) { 6668798bf22SSatish Balay ierr = MatStashScatterGetMesg_Private(&mat->stash,&n,&row,&col,&val,&flg);CHKERRQ(ierr); 667a2d1c673SSatish Balay if (!flg) break; 668a2d1c673SSatish Balay 669bc5ccf88SSatish Balay for (i=0; i<n;) { 670bc5ccf88SSatish Balay /* Now identify the consecutive vals belonging to the same row */ 671bc5ccf88SSatish Balay for (j=i,rstart=row[j]; j<n; j++) { if (row[j] != rstart) break; } 672bc5ccf88SSatish Balay if (j < n) ncols = j-i; 673bc5ccf88SSatish Balay else ncols = n-i; 674bc5ccf88SSatish Balay /* Now assemble all these values with a single function call */ 675bc5ccf88SSatish Balay ierr = MatSetValues_MPIAIJ(mat,1,row+i,ncols,col+i,val+i,addv);CHKERRQ(ierr); 676bc5ccf88SSatish Balay i = j; 677bc5ccf88SSatish Balay } 678bc5ccf88SSatish Balay } 6798798bf22SSatish Balay ierr = MatStashScatterEnd_Private(&mat->stash);CHKERRQ(ierr); 680bc5ccf88SSatish Balay } 681bc5ccf88SSatish Balay ierr = MatAssemblyBegin(aij->A,mode);CHKERRQ(ierr); 682bc5ccf88SSatish Balay ierr = MatAssemblyEnd(aij->A,mode);CHKERRQ(ierr); 683bc5ccf88SSatish Balay 684bc5ccf88SSatish Balay /* determine if any processor has disassembled, if so we must 685bc5ccf88SSatish Balay also disassemble ourselfs, in order that we may reassemble. */ 686bc5ccf88SSatish Balay /* 687bc5ccf88SSatish Balay if nonzero structure of submatrix B cannot change then we know that 688bc5ccf88SSatish Balay no processor disassembled thus we can skip this stuff 689bc5ccf88SSatish Balay */ 690bc5ccf88SSatish Balay if (!((Mat_SeqAIJ*)aij->B->data)->nonew) { 6917adad957SLisandro Dalcin ierr = MPI_Allreduce(&mat->was_assembled,&other_disassembled,1,MPI_INT,MPI_PROD,((PetscObject)mat)->comm);CHKERRQ(ierr); 692bc5ccf88SSatish Balay if (mat->was_assembled && !other_disassembled) { 693ab9863d7SBarry Smith ierr = MatDisAssemble_MPIAIJ(mat);CHKERRQ(ierr); 694ad59fb31SSatish Balay } 695ad59fb31SSatish Balay } 696bc5ccf88SSatish Balay if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) { 697bc5ccf88SSatish Balay ierr = MatSetUpMultiply_MPIAIJ(mat);CHKERRQ(ierr); 698bc5ccf88SSatish Balay } 6994e0d8c25SBarry Smith ierr = MatSetOption(aij->B,MAT_USE_INODES,PETSC_FALSE);CHKERRQ(ierr); 7004e35b6f3SSatish Balay ierr = MatSetOption(aij->B,MAT_CHECK_COMPRESSED_ROW,PETSC_FALSE);CHKERRQ(ierr); 701bc5ccf88SSatish Balay ierr = MatAssemblyBegin(aij->B,mode);CHKERRQ(ierr); 702bc5ccf88SSatish Balay ierr = MatAssemblyEnd(aij->B,mode);CHKERRQ(ierr); 703bc5ccf88SSatish Balay 7041d79065fSBarry Smith ierr = PetscFree2(aij->rowvalues,aij->rowindices);CHKERRQ(ierr); 705606d414cSSatish Balay aij->rowvalues = 0; 706a30b2313SHong Zhang 707a30b2313SHong Zhang /* used by MatAXPY() */ 70891c97fd4SSatish Balay a->xtoy = 0; ((Mat_SeqAIJ *)aij->B->data)->xtoy = 0; /* b->xtoy = 0 */ 70991c97fd4SSatish Balay a->XtoY = 0; ((Mat_SeqAIJ *)aij->B->data)->XtoY = 0; /* b->XtoY = 0 */ 710a30b2313SHong Zhang 7116bf464f9SBarry Smith ierr = VecDestroy(&aij->diag);CHKERRQ(ierr); 712bd0c2dcbSBarry Smith if (a->inode.size) mat->ops->multdiagonalblock = MatMultDiagonalBlock_MPIAIJ; 713bc5ccf88SSatish Balay PetscFunctionReturn(0); 714bc5ccf88SSatish Balay } 715bc5ccf88SSatish Balay 7164a2ae208SSatish Balay #undef __FUNCT__ 7174a2ae208SSatish Balay #define __FUNCT__ "MatZeroEntries_MPIAIJ" 718dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_MPIAIJ(Mat A) 7191eb62cbbSBarry Smith { 72044a69424SLois Curfman McInnes Mat_MPIAIJ *l = (Mat_MPIAIJ*)A->data; 721dfbe8321SBarry Smith PetscErrorCode ierr; 7223a40ed3dSBarry Smith 7233a40ed3dSBarry Smith PetscFunctionBegin; 72478b31e54SBarry Smith ierr = MatZeroEntries(l->A);CHKERRQ(ierr); 72578b31e54SBarry Smith ierr = MatZeroEntries(l->B);CHKERRQ(ierr); 7263a40ed3dSBarry Smith PetscFunctionReturn(0); 7271eb62cbbSBarry Smith } 7281eb62cbbSBarry Smith 7294a2ae208SSatish Balay #undef __FUNCT__ 7304a2ae208SSatish Balay #define __FUNCT__ "MatZeroRows_MPIAIJ" 7312b40b63fSBarry Smith PetscErrorCode MatZeroRows_MPIAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 7321eb62cbbSBarry Smith { 73344a69424SLois Curfman McInnes Mat_MPIAIJ *l = (Mat_MPIAIJ*)A->data; 7346849ba73SBarry Smith PetscErrorCode ierr; 7357adad957SLisandro Dalcin PetscMPIInt size = l->size,imdex,n,rank = l->rank,tag = ((PetscObject)A)->tag,lastidx = -1; 736d0f46423SBarry Smith PetscInt i,*owners = A->rmap->range; 737b1d57f15SBarry Smith PetscInt *nprocs,j,idx,nsends,row; 738b1d57f15SBarry Smith PetscInt nmax,*svalues,*starts,*owner,nrecvs; 739b1d57f15SBarry Smith PetscInt *rvalues,count,base,slen,*source; 740d0f46423SBarry Smith PetscInt *lens,*lrows,*values,rstart=A->rmap->rstart; 7417adad957SLisandro Dalcin MPI_Comm comm = ((PetscObject)A)->comm; 7421eb62cbbSBarry Smith MPI_Request *send_waits,*recv_waits; 7431eb62cbbSBarry Smith MPI_Status recv_status,*send_status; 74497b48c8fSBarry Smith const PetscScalar *xx; 74597b48c8fSBarry Smith PetscScalar *bb; 7466543fbbaSBarry Smith #if defined(PETSC_DEBUG) 747ace3abfcSBarry Smith PetscBool found = PETSC_FALSE; 7486543fbbaSBarry Smith #endif 7491eb62cbbSBarry Smith 7503a40ed3dSBarry Smith PetscFunctionBegin; 7511eb62cbbSBarry Smith /* first count number of contributors to each processor */ 752b1d57f15SBarry Smith ierr = PetscMalloc(2*size*sizeof(PetscInt),&nprocs);CHKERRQ(ierr); 753b1d57f15SBarry Smith ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr); 754b1d57f15SBarry Smith ierr = PetscMalloc((N+1)*sizeof(PetscInt),&owner);CHKERRQ(ierr); /* see note*/ 7556543fbbaSBarry Smith j = 0; 7561eb62cbbSBarry Smith for (i=0; i<N; i++) { 7576543fbbaSBarry Smith if (lastidx > (idx = rows[i])) j = 0; 7586543fbbaSBarry Smith lastidx = idx; 7596543fbbaSBarry Smith for (; j<size; j++) { 7601eb62cbbSBarry Smith if (idx >= owners[j] && idx < owners[j+1]) { 7616543fbbaSBarry Smith nprocs[2*j]++; 7626543fbbaSBarry Smith nprocs[2*j+1] = 1; 7636543fbbaSBarry Smith owner[i] = j; 7646543fbbaSBarry Smith #if defined(PETSC_DEBUG) 7656543fbbaSBarry Smith found = PETSC_TRUE; 7666543fbbaSBarry Smith #endif 7676543fbbaSBarry Smith break; 7681eb62cbbSBarry Smith } 7691eb62cbbSBarry Smith } 7706543fbbaSBarry Smith #if defined(PETSC_DEBUG) 771e32f2f54SBarry Smith if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index out of range"); 7726543fbbaSBarry Smith found = PETSC_FALSE; 7736543fbbaSBarry Smith #endif 7741eb62cbbSBarry Smith } 775c1dc657dSBarry Smith nsends = 0; for (i=0; i<size; i++) { nsends += nprocs[2*i+1];} 7761eb62cbbSBarry Smith 7777367270fSBarry Smith if (A->nooffproczerorows) { 7787367270fSBarry Smith if (nsends > 1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"You called MatSetOption(,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) but set an off process zero row"); 7797367270fSBarry Smith nrecvs = nsends; 7807367270fSBarry Smith nmax = N; 7817367270fSBarry Smith } else { 7821eb62cbbSBarry Smith /* inform other processors of number of messages and max length*/ 783c1dc657dSBarry Smith ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr); 7847367270fSBarry Smith } 7851eb62cbbSBarry Smith 7861eb62cbbSBarry Smith /* post receives: */ 787b1d57f15SBarry Smith ierr = PetscMalloc((nrecvs+1)*(nmax+1)*sizeof(PetscInt),&rvalues);CHKERRQ(ierr); 788b0a32e0cSBarry Smith ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr); 7891eb62cbbSBarry Smith for (i=0; i<nrecvs; i++) { 790b1d57f15SBarry Smith ierr = MPI_Irecv(rvalues+nmax*i,nmax,MPIU_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);CHKERRQ(ierr); 7911eb62cbbSBarry Smith } 7921eb62cbbSBarry Smith 7931eb62cbbSBarry Smith /* do sends: 7941eb62cbbSBarry Smith 1) starts[i] gives the starting index in svalues for stuff going to 7951eb62cbbSBarry Smith the ith processor 7961eb62cbbSBarry Smith */ 797b1d57f15SBarry Smith ierr = PetscMalloc((N+1)*sizeof(PetscInt),&svalues);CHKERRQ(ierr); 798b0a32e0cSBarry Smith ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr); 799b1d57f15SBarry Smith ierr = PetscMalloc((size+1)*sizeof(PetscInt),&starts);CHKERRQ(ierr); 8001eb62cbbSBarry Smith starts[0] = 0; 801c1dc657dSBarry Smith for (i=1; i<size; i++) { starts[i] = starts[i-1] + nprocs[2*i-2];} 8021eb62cbbSBarry Smith for (i=0; i<N; i++) { 8031eb62cbbSBarry Smith svalues[starts[owner[i]]++] = rows[i]; 8041eb62cbbSBarry Smith } 8051eb62cbbSBarry Smith 8061eb62cbbSBarry Smith starts[0] = 0; 807c1dc657dSBarry Smith for (i=1; i<size+1; i++) { starts[i] = starts[i-1] + nprocs[2*i-2];} 8081eb62cbbSBarry Smith count = 0; 80917699dbbSLois Curfman McInnes for (i=0; i<size; i++) { 810c1dc657dSBarry Smith if (nprocs[2*i+1]) { 811b1d57f15SBarry Smith ierr = MPI_Isend(svalues+starts[i],nprocs[2*i],MPIU_INT,i,tag,comm,send_waits+count++);CHKERRQ(ierr); 8121eb62cbbSBarry Smith } 8131eb62cbbSBarry Smith } 814606d414cSSatish Balay ierr = PetscFree(starts);CHKERRQ(ierr); 8151eb62cbbSBarry Smith 81617699dbbSLois Curfman McInnes base = owners[rank]; 8171eb62cbbSBarry Smith 8181eb62cbbSBarry Smith /* wait on receives */ 8191d79065fSBarry Smith ierr = PetscMalloc2(nrecvs,PetscInt,&lens,nrecvs,PetscInt,&source);CHKERRQ(ierr); 8201eb62cbbSBarry Smith count = nrecvs; slen = 0; 8211eb62cbbSBarry Smith while (count) { 822ca161407SBarry Smith ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr); 8231eb62cbbSBarry Smith /* unpack receives into our local space */ 824b1d57f15SBarry Smith ierr = MPI_Get_count(&recv_status,MPIU_INT,&n);CHKERRQ(ierr); 825d6dfbf8fSBarry Smith source[imdex] = recv_status.MPI_SOURCE; 826d6dfbf8fSBarry Smith lens[imdex] = n; 8271eb62cbbSBarry Smith slen += n; 8281eb62cbbSBarry Smith count--; 8291eb62cbbSBarry Smith } 830606d414cSSatish Balay ierr = PetscFree(recv_waits);CHKERRQ(ierr); 8311eb62cbbSBarry Smith 8321eb62cbbSBarry Smith /* move the data into the send scatter */ 833b1d57f15SBarry Smith ierr = PetscMalloc((slen+1)*sizeof(PetscInt),&lrows);CHKERRQ(ierr); 8341eb62cbbSBarry Smith count = 0; 8351eb62cbbSBarry Smith for (i=0; i<nrecvs; i++) { 8361eb62cbbSBarry Smith values = rvalues + i*nmax; 8371eb62cbbSBarry Smith for (j=0; j<lens[i]; j++) { 8381eb62cbbSBarry Smith lrows[count++] = values[j] - base; 8391eb62cbbSBarry Smith } 8401eb62cbbSBarry Smith } 841606d414cSSatish Balay ierr = PetscFree(rvalues);CHKERRQ(ierr); 8421d79065fSBarry Smith ierr = PetscFree2(lens,source);CHKERRQ(ierr); 843606d414cSSatish Balay ierr = PetscFree(owner);CHKERRQ(ierr); 844606d414cSSatish Balay ierr = PetscFree(nprocs);CHKERRQ(ierr); 8451eb62cbbSBarry Smith 84697b48c8fSBarry Smith /* fix right hand side if needed */ 84797b48c8fSBarry Smith if (x && b) { 84897b48c8fSBarry Smith ierr = VecGetArrayRead(x,&xx);CHKERRQ(ierr); 84997b48c8fSBarry Smith ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 850564f14d6SBarry Smith for (i=0; i<slen; i++) { 85197b48c8fSBarry Smith bb[lrows[i]] = diag*xx[lrows[i]]; 85297b48c8fSBarry Smith } 85397b48c8fSBarry Smith ierr = VecRestoreArrayRead(x,&xx);CHKERRQ(ierr); 85497b48c8fSBarry Smith ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 85597b48c8fSBarry Smith } 8566eb55b6aSBarry Smith /* 8576eb55b6aSBarry Smith Zero the required rows. If the "diagonal block" of the matrix 858a8c7a070SBarry Smith is square and the user wishes to set the diagonal we use separate 8596eb55b6aSBarry Smith code so that MatSetValues() is not called for each diagonal allocating 8606eb55b6aSBarry Smith new memory, thus calling lots of mallocs and slowing things down. 8616eb55b6aSBarry Smith 8626eb55b6aSBarry Smith */ 863e2d53e46SBarry Smith /* must zero l->B before l->A because the (diag) case below may put values into l->B*/ 8642b40b63fSBarry Smith ierr = MatZeroRows(l->B,slen,lrows,0.0,0,0);CHKERRQ(ierr); 865d0f46423SBarry Smith if ((diag != 0.0) && (l->A->rmap->N == l->A->cmap->N)) { 8662b40b63fSBarry Smith ierr = MatZeroRows(l->A,slen,lrows,diag,0,0);CHKERRQ(ierr); 867f4df32b1SMatthew Knepley } else if (diag != 0.0) { 8682b40b63fSBarry Smith ierr = MatZeroRows(l->A,slen,lrows,0.0,0,0);CHKERRQ(ierr); 869fa46199cSSatish Balay if (((Mat_SeqAIJ*)l->A->data)->nonew) { 870e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"MatZeroRows() on rectangular matrices cannot be used with the Mat options\n\ 871512a5fc5SBarry Smith MAT_NEW_NONZERO_LOCATIONS,MAT_NEW_NONZERO_LOCATION_ERR,MAT_NEW_NONZERO_ALLOCATION_ERR"); 8726525c446SSatish Balay } 873e2d53e46SBarry Smith for (i = 0; i < slen; i++) { 874e2d53e46SBarry Smith row = lrows[i] + rstart; 875f4df32b1SMatthew Knepley ierr = MatSetValues(A,1,&row,1,&row,&diag,INSERT_VALUES);CHKERRQ(ierr); 876e2d53e46SBarry Smith } 877e2d53e46SBarry Smith ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 878e2d53e46SBarry Smith ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 8796eb55b6aSBarry Smith } else { 8802b40b63fSBarry Smith ierr = MatZeroRows(l->A,slen,lrows,0.0,0,0);CHKERRQ(ierr); 8816eb55b6aSBarry Smith } 882606d414cSSatish Balay ierr = PetscFree(lrows);CHKERRQ(ierr); 88372dacd9aSBarry Smith 8841eb62cbbSBarry Smith /* wait on sends */ 8851eb62cbbSBarry Smith if (nsends) { 886b0a32e0cSBarry Smith ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr); 887ca161407SBarry Smith ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr); 888606d414cSSatish Balay ierr = PetscFree(send_status);CHKERRQ(ierr); 8891eb62cbbSBarry Smith } 890606d414cSSatish Balay ierr = PetscFree(send_waits);CHKERRQ(ierr); 891606d414cSSatish Balay ierr = PetscFree(svalues);CHKERRQ(ierr); 8923a40ed3dSBarry Smith PetscFunctionReturn(0); 8931eb62cbbSBarry Smith } 8941eb62cbbSBarry Smith 8954a2ae208SSatish Balay #undef __FUNCT__ 8969c7c4993SBarry Smith #define __FUNCT__ "MatZeroRowsColumns_MPIAIJ" 8979c7c4993SBarry Smith PetscErrorCode MatZeroRowsColumns_MPIAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 8989c7c4993SBarry Smith { 8999c7c4993SBarry Smith Mat_MPIAIJ *l = (Mat_MPIAIJ*)A->data; 9009c7c4993SBarry Smith PetscErrorCode ierr; 9019c7c4993SBarry Smith PetscMPIInt size = l->size,imdex,n,rank = l->rank,tag = ((PetscObject)A)->tag,lastidx = -1; 9029c7c4993SBarry Smith PetscInt i,*owners = A->rmap->range; 903564f14d6SBarry Smith PetscInt *nprocs,j,idx,nsends; 9049c7c4993SBarry Smith PetscInt nmax,*svalues,*starts,*owner,nrecvs; 9059c7c4993SBarry Smith PetscInt *rvalues,count,base,slen,*source; 906564f14d6SBarry Smith PetscInt *lens,*lrows,*values,m; 9079c7c4993SBarry Smith MPI_Comm comm = ((PetscObject)A)->comm; 9089c7c4993SBarry Smith MPI_Request *send_waits,*recv_waits; 9099c7c4993SBarry Smith MPI_Status recv_status,*send_status; 9109c7c4993SBarry Smith const PetscScalar *xx; 911564f14d6SBarry Smith PetscScalar *bb,*mask; 912564f14d6SBarry Smith Vec xmask,lmask; 913564f14d6SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)l->B->data; 914564f14d6SBarry Smith const PetscInt *aj, *ii,*ridx; 915564f14d6SBarry Smith PetscScalar *aa; 9169c7c4993SBarry Smith #if defined(PETSC_DEBUG) 9179c7c4993SBarry Smith PetscBool found = PETSC_FALSE; 9189c7c4993SBarry Smith #endif 9199c7c4993SBarry Smith 9209c7c4993SBarry Smith PetscFunctionBegin; 9219c7c4993SBarry Smith /* first count number of contributors to each processor */ 9229c7c4993SBarry Smith ierr = PetscMalloc(2*size*sizeof(PetscInt),&nprocs);CHKERRQ(ierr); 9239c7c4993SBarry Smith ierr = PetscMemzero(nprocs,2*size*sizeof(PetscInt));CHKERRQ(ierr); 9249c7c4993SBarry Smith ierr = PetscMalloc((N+1)*sizeof(PetscInt),&owner);CHKERRQ(ierr); /* see note*/ 9259c7c4993SBarry Smith j = 0; 9269c7c4993SBarry Smith for (i=0; i<N; i++) { 9279c7c4993SBarry Smith if (lastidx > (idx = rows[i])) j = 0; 9289c7c4993SBarry Smith lastidx = idx; 9299c7c4993SBarry Smith for (; j<size; j++) { 9309c7c4993SBarry Smith if (idx >= owners[j] && idx < owners[j+1]) { 9319c7c4993SBarry Smith nprocs[2*j]++; 9329c7c4993SBarry Smith nprocs[2*j+1] = 1; 9339c7c4993SBarry Smith owner[i] = j; 9349c7c4993SBarry Smith #if defined(PETSC_DEBUG) 9359c7c4993SBarry Smith found = PETSC_TRUE; 9369c7c4993SBarry Smith #endif 9379c7c4993SBarry Smith break; 9389c7c4993SBarry Smith } 9399c7c4993SBarry Smith } 9409c7c4993SBarry Smith #if defined(PETSC_DEBUG) 9419c7c4993SBarry Smith if (!found) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index out of range"); 9429c7c4993SBarry Smith found = PETSC_FALSE; 9439c7c4993SBarry Smith #endif 9449c7c4993SBarry Smith } 9459c7c4993SBarry Smith nsends = 0; for (i=0; i<size; i++) { nsends += nprocs[2*i+1];} 9469c7c4993SBarry Smith 9479c7c4993SBarry Smith /* inform other processors of number of messages and max length*/ 9489c7c4993SBarry Smith ierr = PetscMaxSum(comm,nprocs,&nmax,&nrecvs);CHKERRQ(ierr); 9499c7c4993SBarry Smith 9509c7c4993SBarry Smith /* post receives: */ 9519c7c4993SBarry Smith ierr = PetscMalloc((nrecvs+1)*(nmax+1)*sizeof(PetscInt),&rvalues);CHKERRQ(ierr); 9529c7c4993SBarry Smith ierr = PetscMalloc((nrecvs+1)*sizeof(MPI_Request),&recv_waits);CHKERRQ(ierr); 9539c7c4993SBarry Smith for (i=0; i<nrecvs; i++) { 9549c7c4993SBarry Smith ierr = MPI_Irecv(rvalues+nmax*i,nmax,MPIU_INT,MPI_ANY_SOURCE,tag,comm,recv_waits+i);CHKERRQ(ierr); 9559c7c4993SBarry Smith } 9569c7c4993SBarry Smith 9579c7c4993SBarry Smith /* do sends: 9589c7c4993SBarry Smith 1) starts[i] gives the starting index in svalues for stuff going to 9599c7c4993SBarry Smith the ith processor 9609c7c4993SBarry Smith */ 9619c7c4993SBarry Smith ierr = PetscMalloc((N+1)*sizeof(PetscInt),&svalues);CHKERRQ(ierr); 9629c7c4993SBarry Smith ierr = PetscMalloc((nsends+1)*sizeof(MPI_Request),&send_waits);CHKERRQ(ierr); 9639c7c4993SBarry Smith ierr = PetscMalloc((size+1)*sizeof(PetscInt),&starts);CHKERRQ(ierr); 9649c7c4993SBarry Smith starts[0] = 0; 9659c7c4993SBarry Smith for (i=1; i<size; i++) { starts[i] = starts[i-1] + nprocs[2*i-2];} 9669c7c4993SBarry Smith for (i=0; i<N; i++) { 9679c7c4993SBarry Smith svalues[starts[owner[i]]++] = rows[i]; 9689c7c4993SBarry Smith } 9699c7c4993SBarry Smith 9709c7c4993SBarry Smith starts[0] = 0; 9719c7c4993SBarry Smith for (i=1; i<size+1; i++) { starts[i] = starts[i-1] + nprocs[2*i-2];} 9729c7c4993SBarry Smith count = 0; 9739c7c4993SBarry Smith for (i=0; i<size; i++) { 9749c7c4993SBarry Smith if (nprocs[2*i+1]) { 9759c7c4993SBarry Smith ierr = MPI_Isend(svalues+starts[i],nprocs[2*i],MPIU_INT,i,tag,comm,send_waits+count++);CHKERRQ(ierr); 9769c7c4993SBarry Smith } 9779c7c4993SBarry Smith } 9789c7c4993SBarry Smith ierr = PetscFree(starts);CHKERRQ(ierr); 9799c7c4993SBarry Smith 9809c7c4993SBarry Smith base = owners[rank]; 9819c7c4993SBarry Smith 9829c7c4993SBarry Smith /* wait on receives */ 9839c7c4993SBarry Smith ierr = PetscMalloc2(nrecvs,PetscInt,&lens,nrecvs,PetscInt,&source);CHKERRQ(ierr); 9849c7c4993SBarry Smith count = nrecvs; slen = 0; 9859c7c4993SBarry Smith while (count) { 9869c7c4993SBarry Smith ierr = MPI_Waitany(nrecvs,recv_waits,&imdex,&recv_status);CHKERRQ(ierr); 9879c7c4993SBarry Smith /* unpack receives into our local space */ 9889c7c4993SBarry Smith ierr = MPI_Get_count(&recv_status,MPIU_INT,&n);CHKERRQ(ierr); 9899c7c4993SBarry Smith source[imdex] = recv_status.MPI_SOURCE; 9909c7c4993SBarry Smith lens[imdex] = n; 9919c7c4993SBarry Smith slen += n; 9929c7c4993SBarry Smith count--; 9939c7c4993SBarry Smith } 9949c7c4993SBarry Smith ierr = PetscFree(recv_waits);CHKERRQ(ierr); 9959c7c4993SBarry Smith 9969c7c4993SBarry Smith /* move the data into the send scatter */ 9979c7c4993SBarry Smith ierr = PetscMalloc((slen+1)*sizeof(PetscInt),&lrows);CHKERRQ(ierr); 9989c7c4993SBarry Smith count = 0; 9999c7c4993SBarry Smith for (i=0; i<nrecvs; i++) { 10009c7c4993SBarry Smith values = rvalues + i*nmax; 10019c7c4993SBarry Smith for (j=0; j<lens[i]; j++) { 10029c7c4993SBarry Smith lrows[count++] = values[j] - base; 10039c7c4993SBarry Smith } 10049c7c4993SBarry Smith } 10059c7c4993SBarry Smith ierr = PetscFree(rvalues);CHKERRQ(ierr); 10069c7c4993SBarry Smith ierr = PetscFree2(lens,source);CHKERRQ(ierr); 10079c7c4993SBarry Smith ierr = PetscFree(owner);CHKERRQ(ierr); 10089c7c4993SBarry Smith ierr = PetscFree(nprocs);CHKERRQ(ierr); 1009564f14d6SBarry Smith /* lrows are the local rows to be zeroed, slen is the number of local rows */ 10109c7c4993SBarry Smith 1011564f14d6SBarry Smith /* zero diagonal part of matrix */ 1012564f14d6SBarry Smith ierr = MatZeroRowsColumns(l->A,slen,lrows,diag,x,b);CHKERRQ(ierr); 10139c7c4993SBarry Smith 1014564f14d6SBarry Smith /* handle off diagonal part of matrix */ 1015564f14d6SBarry Smith ierr = MatGetVecs(A,&xmask,PETSC_NULL);CHKERRQ(ierr); 1016564f14d6SBarry Smith ierr = VecDuplicate(l->lvec,&lmask);CHKERRQ(ierr); 1017564f14d6SBarry Smith ierr = VecGetArray(xmask,&bb);CHKERRQ(ierr); 10189c7c4993SBarry Smith for (i=0; i<slen; i++) { 1019564f14d6SBarry Smith bb[lrows[i]] = 1; 10209c7c4993SBarry Smith } 1021564f14d6SBarry Smith ierr = VecRestoreArray(xmask,&bb);CHKERRQ(ierr); 1022564f14d6SBarry Smith ierr = VecScatterBegin(l->Mvctx,xmask,lmask,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1023564f14d6SBarry Smith ierr = VecScatterEnd(l->Mvctx,xmask,lmask,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 10246bf464f9SBarry Smith ierr = VecDestroy(&xmask);CHKERRQ(ierr); 1025377aa5a1SBarry Smith if (x) { 1026564f14d6SBarry Smith ierr = VecScatterBegin(l->Mvctx,x,l->lvec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1027564f14d6SBarry Smith ierr = VecScatterEnd(l->Mvctx,x,l->lvec,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1028564f14d6SBarry Smith ierr = VecGetArrayRead(l->lvec,&xx);CHKERRQ(ierr); 1029564f14d6SBarry Smith ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 1030377aa5a1SBarry Smith } 1031377aa5a1SBarry Smith ierr = VecGetArray(lmask,&mask);CHKERRQ(ierr); 1032564f14d6SBarry Smith 1033564f14d6SBarry Smith /* remove zeroed rows of off diagonal matrix */ 1034564f14d6SBarry Smith ii = aij->i; 1035564f14d6SBarry Smith for (i=0; i<slen; i++) { 1036564f14d6SBarry Smith ierr = PetscMemzero(aij->a + ii[lrows[i]],(ii[lrows[i]+1] - ii[lrows[i]])*sizeof(PetscScalar));CHKERRQ(ierr); 10379c7c4993SBarry Smith } 1038564f14d6SBarry Smith 1039564f14d6SBarry Smith /* loop over all elements of off process part of matrix zeroing removed columns*/ 1040564f14d6SBarry Smith if (aij->compressedrow.use){ 1041564f14d6SBarry Smith m = aij->compressedrow.nrows; 1042564f14d6SBarry Smith ii = aij->compressedrow.i; 1043564f14d6SBarry Smith ridx = aij->compressedrow.rindex; 1044564f14d6SBarry Smith for (i=0; i<m; i++){ 1045564f14d6SBarry Smith n = ii[i+1] - ii[i]; 1046564f14d6SBarry Smith aj = aij->j + ii[i]; 1047564f14d6SBarry Smith aa = aij->a + ii[i]; 1048564f14d6SBarry Smith 1049564f14d6SBarry Smith for (j=0; j<n; j++) { 105025266a92SSatish Balay if (PetscAbsScalar(mask[*aj])) { 1051377aa5a1SBarry Smith if (b) bb[*ridx] -= *aa*xx[*aj]; 1052564f14d6SBarry Smith *aa = 0.0; 1053564f14d6SBarry Smith } 1054564f14d6SBarry Smith aa++; 1055564f14d6SBarry Smith aj++; 1056564f14d6SBarry Smith } 1057564f14d6SBarry Smith ridx++; 1058564f14d6SBarry Smith } 1059564f14d6SBarry Smith } else { /* do not use compressed row format */ 1060564f14d6SBarry Smith m = l->B->rmap->n; 1061564f14d6SBarry Smith for (i=0; i<m; i++) { 1062564f14d6SBarry Smith n = ii[i+1] - ii[i]; 1063564f14d6SBarry Smith aj = aij->j + ii[i]; 1064564f14d6SBarry Smith aa = aij->a + ii[i]; 1065564f14d6SBarry Smith for (j=0; j<n; j++) { 106625266a92SSatish Balay if (PetscAbsScalar(mask[*aj])) { 1067377aa5a1SBarry Smith if (b) bb[i] -= *aa*xx[*aj]; 1068564f14d6SBarry Smith *aa = 0.0; 1069564f14d6SBarry Smith } 1070564f14d6SBarry Smith aa++; 1071564f14d6SBarry Smith aj++; 1072564f14d6SBarry Smith } 1073564f14d6SBarry Smith } 1074564f14d6SBarry Smith } 1075377aa5a1SBarry Smith if (x) { 1076564f14d6SBarry Smith ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 1077564f14d6SBarry Smith ierr = VecRestoreArrayRead(l->lvec,&xx);CHKERRQ(ierr); 1078377aa5a1SBarry Smith } 1079377aa5a1SBarry Smith ierr = VecRestoreArray(lmask,&mask);CHKERRQ(ierr); 10806bf464f9SBarry Smith ierr = VecDestroy(&lmask);CHKERRQ(ierr); 10819c7c4993SBarry Smith ierr = PetscFree(lrows);CHKERRQ(ierr); 10829c7c4993SBarry Smith 10839c7c4993SBarry Smith /* wait on sends */ 10849c7c4993SBarry Smith if (nsends) { 10859c7c4993SBarry Smith ierr = PetscMalloc(nsends*sizeof(MPI_Status),&send_status);CHKERRQ(ierr); 10869c7c4993SBarry Smith ierr = MPI_Waitall(nsends,send_waits,send_status);CHKERRQ(ierr); 10879c7c4993SBarry Smith ierr = PetscFree(send_status);CHKERRQ(ierr); 10889c7c4993SBarry Smith } 10899c7c4993SBarry Smith ierr = PetscFree(send_waits);CHKERRQ(ierr); 10909c7c4993SBarry Smith ierr = PetscFree(svalues);CHKERRQ(ierr); 10919c7c4993SBarry Smith 10929c7c4993SBarry Smith PetscFunctionReturn(0); 10939c7c4993SBarry Smith } 10949c7c4993SBarry Smith 10959c7c4993SBarry Smith #undef __FUNCT__ 10964a2ae208SSatish Balay #define __FUNCT__ "MatMult_MPIAIJ" 1097dfbe8321SBarry Smith PetscErrorCode MatMult_MPIAIJ(Mat A,Vec xx,Vec yy) 10981eb62cbbSBarry Smith { 1099416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1100dfbe8321SBarry Smith PetscErrorCode ierr; 1101b1d57f15SBarry Smith PetscInt nt; 1102416022c9SBarry Smith 11033a40ed3dSBarry Smith PetscFunctionBegin; 1104a2ce50c7SBarry Smith ierr = VecGetLocalSize(xx,&nt);CHKERRQ(ierr); 110565e19b50SBarry Smith if (nt != A->cmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Incompatible partition of A (%D) and xx (%D)",A->cmap->n,nt); 1106ca9f406cSSatish Balay ierr = VecScatterBegin(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1107f830108cSBarry Smith ierr = (*a->A->ops->mult)(a->A,xx,yy);CHKERRQ(ierr); 1108ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1109f830108cSBarry Smith ierr = (*a->B->ops->multadd)(a->B,a->lvec,yy,yy);CHKERRQ(ierr); 11103a40ed3dSBarry Smith PetscFunctionReturn(0); 11111eb62cbbSBarry Smith } 11121eb62cbbSBarry Smith 11134a2ae208SSatish Balay #undef __FUNCT__ 1114bd0c2dcbSBarry Smith #define __FUNCT__ "MatMultDiagonalBlock_MPIAIJ" 1115bd0c2dcbSBarry Smith PetscErrorCode MatMultDiagonalBlock_MPIAIJ(Mat A,Vec bb,Vec xx) 1116bd0c2dcbSBarry Smith { 1117bd0c2dcbSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1118bd0c2dcbSBarry Smith PetscErrorCode ierr; 1119bd0c2dcbSBarry Smith 1120bd0c2dcbSBarry Smith PetscFunctionBegin; 1121bd0c2dcbSBarry Smith ierr = MatMultDiagonalBlock(a->A,bb,xx);CHKERRQ(ierr); 1122bd0c2dcbSBarry Smith PetscFunctionReturn(0); 1123bd0c2dcbSBarry Smith } 1124bd0c2dcbSBarry Smith 1125bd0c2dcbSBarry Smith #undef __FUNCT__ 11264a2ae208SSatish Balay #define __FUNCT__ "MatMultAdd_MPIAIJ" 1127dfbe8321SBarry Smith PetscErrorCode MatMultAdd_MPIAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1128da3a660dSBarry Smith { 1129416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1130dfbe8321SBarry Smith PetscErrorCode ierr; 11313a40ed3dSBarry Smith 11323a40ed3dSBarry Smith PetscFunctionBegin; 1133ca9f406cSSatish Balay ierr = VecScatterBegin(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1134f830108cSBarry Smith ierr = (*a->A->ops->multadd)(a->A,xx,yy,zz);CHKERRQ(ierr); 1135ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1136f830108cSBarry Smith ierr = (*a->B->ops->multadd)(a->B,a->lvec,zz,zz);CHKERRQ(ierr); 11373a40ed3dSBarry Smith PetscFunctionReturn(0); 1138da3a660dSBarry Smith } 1139da3a660dSBarry Smith 11404a2ae208SSatish Balay #undef __FUNCT__ 11414a2ae208SSatish Balay #define __FUNCT__ "MatMultTranspose_MPIAIJ" 1142dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_MPIAIJ(Mat A,Vec xx,Vec yy) 1143da3a660dSBarry Smith { 1144416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1145dfbe8321SBarry Smith PetscErrorCode ierr; 1146ace3abfcSBarry Smith PetscBool merged; 1147da3a660dSBarry Smith 11483a40ed3dSBarry Smith PetscFunctionBegin; 1149a5ff213dSBarry Smith ierr = VecScatterGetMerged(a->Mvctx,&merged);CHKERRQ(ierr); 1150da3a660dSBarry Smith /* do nondiagonal part */ 11517c922b88SBarry Smith ierr = (*a->B->ops->multtranspose)(a->B,xx,a->lvec);CHKERRQ(ierr); 1152a5ff213dSBarry Smith if (!merged) { 1153da3a660dSBarry Smith /* send it on its way */ 1154ca9f406cSSatish Balay ierr = VecScatterBegin(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1155da3a660dSBarry Smith /* do local part */ 11567c922b88SBarry Smith ierr = (*a->A->ops->multtranspose)(a->A,xx,yy);CHKERRQ(ierr); 1157da3a660dSBarry Smith /* receive remote parts: note this assumes the values are not actually */ 1158a5ff213dSBarry Smith /* added in yy until the next line, */ 1159ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1160a5ff213dSBarry Smith } else { 1161a5ff213dSBarry Smith /* do local part */ 1162a5ff213dSBarry Smith ierr = (*a->A->ops->multtranspose)(a->A,xx,yy);CHKERRQ(ierr); 1163a5ff213dSBarry Smith /* send it on its way */ 1164ca9f406cSSatish Balay ierr = VecScatterBegin(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1165a5ff213dSBarry Smith /* values actually were received in the Begin() but we need to call this nop */ 1166ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1167a5ff213dSBarry Smith } 11683a40ed3dSBarry Smith PetscFunctionReturn(0); 1169da3a660dSBarry Smith } 1170da3a660dSBarry Smith 1171cd0d46ebSvictorle EXTERN_C_BEGIN 1172cd0d46ebSvictorle #undef __FUNCT__ 11735fbd3699SBarry Smith #define __FUNCT__ "MatIsTranspose_MPIAIJ" 11747087cfbeSBarry Smith PetscErrorCode MatIsTranspose_MPIAIJ(Mat Amat,Mat Bmat,PetscReal tol,PetscBool *f) 1175cd0d46ebSvictorle { 11764f423910Svictorle MPI_Comm comm; 1177cd0d46ebSvictorle Mat_MPIAIJ *Aij = (Mat_MPIAIJ *) Amat->data, *Bij; 117866501d38Svictorle Mat Adia = Aij->A, Bdia, Aoff,Boff,*Aoffs,*Boffs; 1179cd0d46ebSvictorle IS Me,Notme; 11806849ba73SBarry Smith PetscErrorCode ierr; 1181b1d57f15SBarry Smith PetscInt M,N,first,last,*notme,i; 1182b1d57f15SBarry Smith PetscMPIInt size; 1183cd0d46ebSvictorle 1184cd0d46ebSvictorle PetscFunctionBegin; 118542e5f5b4Svictorle 118642e5f5b4Svictorle /* Easy test: symmetric diagonal block */ 118766501d38Svictorle Bij = (Mat_MPIAIJ *) Bmat->data; Bdia = Bij->A; 11885485867bSBarry Smith ierr = MatIsTranspose(Adia,Bdia,tol,f);CHKERRQ(ierr); 1189cd0d46ebSvictorle if (!*f) PetscFunctionReturn(0); 11904f423910Svictorle ierr = PetscObjectGetComm((PetscObject)Amat,&comm);CHKERRQ(ierr); 1191b1d57f15SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1192b1d57f15SBarry Smith if (size == 1) PetscFunctionReturn(0); 119342e5f5b4Svictorle 119442e5f5b4Svictorle /* Hard test: off-diagonal block. This takes a MatGetSubMatrix. */ 1195cd0d46ebSvictorle ierr = MatGetSize(Amat,&M,&N);CHKERRQ(ierr); 1196cd0d46ebSvictorle ierr = MatGetOwnershipRange(Amat,&first,&last);CHKERRQ(ierr); 1197b1d57f15SBarry Smith ierr = PetscMalloc((N-last+first)*sizeof(PetscInt),¬me);CHKERRQ(ierr); 1198cd0d46ebSvictorle for (i=0; i<first; i++) notme[i] = i; 1199cd0d46ebSvictorle for (i=last; i<M; i++) notme[i-last+first] = i; 120070b3c8c7SBarry Smith ierr = ISCreateGeneral(MPI_COMM_SELF,N-last+first,notme,PETSC_COPY_VALUES,&Notme);CHKERRQ(ierr); 1201268466fbSBarry Smith ierr = ISCreateStride(MPI_COMM_SELF,last-first,first,1,&Me);CHKERRQ(ierr); 1202268466fbSBarry Smith ierr = MatGetSubMatrices(Amat,1,&Me,&Notme,MAT_INITIAL_MATRIX,&Aoffs);CHKERRQ(ierr); 120366501d38Svictorle Aoff = Aoffs[0]; 1204268466fbSBarry Smith ierr = MatGetSubMatrices(Bmat,1,&Notme,&Me,MAT_INITIAL_MATRIX,&Boffs);CHKERRQ(ierr); 120566501d38Svictorle Boff = Boffs[0]; 12065485867bSBarry Smith ierr = MatIsTranspose(Aoff,Boff,tol,f);CHKERRQ(ierr); 120766501d38Svictorle ierr = MatDestroyMatrices(1,&Aoffs);CHKERRQ(ierr); 120866501d38Svictorle ierr = MatDestroyMatrices(1,&Boffs);CHKERRQ(ierr); 12096bf464f9SBarry Smith ierr = ISDestroy(&Me);CHKERRQ(ierr); 12106bf464f9SBarry Smith ierr = ISDestroy(&Notme);CHKERRQ(ierr); 12113e0d0d19SHong Zhang ierr = PetscFree(notme);CHKERRQ(ierr); 1212cd0d46ebSvictorle PetscFunctionReturn(0); 1213cd0d46ebSvictorle } 1214cd0d46ebSvictorle EXTERN_C_END 1215cd0d46ebSvictorle 12164a2ae208SSatish Balay #undef __FUNCT__ 12174a2ae208SSatish Balay #define __FUNCT__ "MatMultTransposeAdd_MPIAIJ" 1218dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_MPIAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1219da3a660dSBarry Smith { 1220416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1221dfbe8321SBarry Smith PetscErrorCode ierr; 1222da3a660dSBarry Smith 12233a40ed3dSBarry Smith PetscFunctionBegin; 1224da3a660dSBarry Smith /* do nondiagonal part */ 12257c922b88SBarry Smith ierr = (*a->B->ops->multtranspose)(a->B,xx,a->lvec);CHKERRQ(ierr); 1226da3a660dSBarry Smith /* send it on its way */ 1227ca9f406cSSatish Balay ierr = VecScatterBegin(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1228da3a660dSBarry Smith /* do local part */ 12297c922b88SBarry Smith ierr = (*a->A->ops->multtransposeadd)(a->A,xx,yy,zz);CHKERRQ(ierr); 1230a5ff213dSBarry Smith /* receive remote parts */ 1231ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 12323a40ed3dSBarry Smith PetscFunctionReturn(0); 1233da3a660dSBarry Smith } 1234da3a660dSBarry Smith 12351eb62cbbSBarry Smith /* 12361eb62cbbSBarry Smith This only works correctly for square matrices where the subblock A->A is the 12371eb62cbbSBarry Smith diagonal block 12381eb62cbbSBarry Smith */ 12394a2ae208SSatish Balay #undef __FUNCT__ 12404a2ae208SSatish Balay #define __FUNCT__ "MatGetDiagonal_MPIAIJ" 1241dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_MPIAIJ(Mat A,Vec v) 12421eb62cbbSBarry Smith { 1243dfbe8321SBarry Smith PetscErrorCode ierr; 1244416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 12453a40ed3dSBarry Smith 12463a40ed3dSBarry Smith PetscFunctionBegin; 1247e7e72b3dSBarry Smith if (A->rmap->N != A->cmap->N) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_SUP,"Supports only square matrix where A->A is diag block"); 1248e7e72b3dSBarry Smith if (A->rmap->rstart != A->cmap->rstart || A->rmap->rend != A->cmap->rend) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"row partition must equal col partition"); 12493a40ed3dSBarry Smith ierr = MatGetDiagonal(a->A,v);CHKERRQ(ierr); 12503a40ed3dSBarry Smith PetscFunctionReturn(0); 12511eb62cbbSBarry Smith } 12521eb62cbbSBarry Smith 12534a2ae208SSatish Balay #undef __FUNCT__ 12544a2ae208SSatish Balay #define __FUNCT__ "MatScale_MPIAIJ" 1255f4df32b1SMatthew Knepley PetscErrorCode MatScale_MPIAIJ(Mat A,PetscScalar aa) 1256052efed2SBarry Smith { 1257052efed2SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1258dfbe8321SBarry Smith PetscErrorCode ierr; 12593a40ed3dSBarry Smith 12603a40ed3dSBarry Smith PetscFunctionBegin; 1261f4df32b1SMatthew Knepley ierr = MatScale(a->A,aa);CHKERRQ(ierr); 1262f4df32b1SMatthew Knepley ierr = MatScale(a->B,aa);CHKERRQ(ierr); 12633a40ed3dSBarry Smith PetscFunctionReturn(0); 1264052efed2SBarry Smith } 1265052efed2SBarry Smith 12664a2ae208SSatish Balay #undef __FUNCT__ 12674a2ae208SSatish Balay #define __FUNCT__ "MatDestroy_MPIAIJ" 1268dfbe8321SBarry Smith PetscErrorCode MatDestroy_MPIAIJ(Mat mat) 12691eb62cbbSBarry Smith { 127044a69424SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 1271dfbe8321SBarry Smith PetscErrorCode ierr; 127283e2fdc7SBarry Smith 12733a40ed3dSBarry Smith PetscFunctionBegin; 1274aa482453SBarry Smith #if defined(PETSC_USE_LOG) 1275d0f46423SBarry Smith PetscLogObjectState((PetscObject)mat,"Rows=%D, Cols=%D",mat->rmap->N,mat->cmap->N); 1276a5a9c739SBarry Smith #endif 12778798bf22SSatish Balay ierr = MatStashDestroy_Private(&mat->stash);CHKERRQ(ierr); 12786bf464f9SBarry Smith ierr = VecDestroy(&aij->diag);CHKERRQ(ierr); 12796bf464f9SBarry Smith ierr = MatDestroy(&aij->A);CHKERRQ(ierr); 12806bf464f9SBarry Smith ierr = MatDestroy(&aij->B);CHKERRQ(ierr); 1281aa482453SBarry Smith #if defined (PETSC_USE_CTABLE) 12826bc0bbbfSBarry Smith ierr = PetscTableDestroy(&aij->colmap);CHKERRQ(ierr); 1283b1fc9764SSatish Balay #else 128405b42c5fSBarry Smith ierr = PetscFree(aij->colmap);CHKERRQ(ierr); 1285b1fc9764SSatish Balay #endif 128605b42c5fSBarry Smith ierr = PetscFree(aij->garray);CHKERRQ(ierr); 12876bf464f9SBarry Smith ierr = VecDestroy(&aij->lvec);CHKERRQ(ierr); 12886bf464f9SBarry Smith ierr = VecScatterDestroy(&aij->Mvctx);CHKERRQ(ierr); 128903095fedSBarry Smith ierr = PetscFree2(aij->rowvalues,aij->rowindices);CHKERRQ(ierr); 12908aa348c1SBarry Smith ierr = PetscFree(aij->ld);CHKERRQ(ierr); 1291bf0cc555SLisandro Dalcin ierr = PetscFree(mat->data);CHKERRQ(ierr); 1292901853e0SKris Buschelman 1293dbd8c25aSHong Zhang ierr = PetscObjectChangeTypeName((PetscObject)mat,0);CHKERRQ(ierr); 1294901853e0SKris Buschelman ierr = PetscObjectComposeFunction((PetscObject)mat,"MatStoreValues_C","",PETSC_NULL);CHKERRQ(ierr); 1295901853e0SKris Buschelman ierr = PetscObjectComposeFunction((PetscObject)mat,"MatRetrieveValues_C","",PETSC_NULL);CHKERRQ(ierr); 1296901853e0SKris Buschelman ierr = PetscObjectComposeFunction((PetscObject)mat,"MatGetDiagonalBlock_C","",PETSC_NULL);CHKERRQ(ierr); 1297901853e0SKris Buschelman ierr = PetscObjectComposeFunction((PetscObject)mat,"MatIsTranspose_C","",PETSC_NULL);CHKERRQ(ierr); 1298901853e0SKris Buschelman ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPIAIJSetPreallocation_C","",PETSC_NULL);CHKERRQ(ierr); 1299ff69c46cSKris Buschelman ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPIAIJSetPreallocationCSR_C","",PETSC_NULL);CHKERRQ(ierr); 1300901853e0SKris Buschelman ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDiagonalScaleLocal_C","",PETSC_NULL);CHKERRQ(ierr); 1301471cc821SHong Zhang ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_mpiaij_mpisbaij_C","",PETSC_NULL);CHKERRQ(ierr); 13023a40ed3dSBarry Smith PetscFunctionReturn(0); 13031eb62cbbSBarry Smith } 1304ee50ffe9SBarry Smith 13054a2ae208SSatish Balay #undef __FUNCT__ 13068e2fed03SBarry Smith #define __FUNCT__ "MatView_MPIAIJ_Binary" 1307dfbe8321SBarry Smith PetscErrorCode MatView_MPIAIJ_Binary(Mat mat,PetscViewer viewer) 13088e2fed03SBarry Smith { 13098e2fed03SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 13108e2fed03SBarry Smith Mat_SeqAIJ* A = (Mat_SeqAIJ*)aij->A->data; 13118e2fed03SBarry Smith Mat_SeqAIJ* B = (Mat_SeqAIJ*)aij->B->data; 13126849ba73SBarry Smith PetscErrorCode ierr; 131332dcc486SBarry Smith PetscMPIInt rank,size,tag = ((PetscObject)viewer)->tag; 13146f69ff64SBarry Smith int fd; 1315a788621eSSatish Balay PetscInt nz,header[4],*row_lengths,*range=0,rlen,i; 1316d0f46423SBarry Smith PetscInt nzmax,*column_indices,j,k,col,*garray = aij->garray,cnt,cstart = mat->cmap->rstart,rnz; 13178e2fed03SBarry Smith PetscScalar *column_values; 131885ebf7a4SBarry Smith PetscInt message_count,flowcontrolcount; 1319b37d52dbSMark F. Adams FILE *file; 13208e2fed03SBarry Smith 13218e2fed03SBarry Smith PetscFunctionBegin; 13227adad957SLisandro Dalcin ierr = MPI_Comm_rank(((PetscObject)mat)->comm,&rank);CHKERRQ(ierr); 13237adad957SLisandro Dalcin ierr = MPI_Comm_size(((PetscObject)mat)->comm,&size);CHKERRQ(ierr); 13248e2fed03SBarry Smith nz = A->nz + B->nz; 1325958c9bccSBarry Smith if (!rank) { 13260700a824SBarry Smith header[0] = MAT_FILE_CLASSID; 1327d0f46423SBarry Smith header[1] = mat->rmap->N; 1328d0f46423SBarry Smith header[2] = mat->cmap->N; 13297adad957SLisandro Dalcin ierr = MPI_Reduce(&nz,&header[3],1,MPIU_INT,MPI_SUM,0,((PetscObject)mat)->comm);CHKERRQ(ierr); 13308e2fed03SBarry Smith ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 13316f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,header,4,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 13328e2fed03SBarry Smith /* get largest number of rows any processor has */ 1333d0f46423SBarry Smith rlen = mat->rmap->n; 1334d0f46423SBarry Smith range = mat->rmap->range; 13358e2fed03SBarry Smith for (i=1; i<size; i++) { 13368e2fed03SBarry Smith rlen = PetscMax(rlen,range[i+1] - range[i]); 13378e2fed03SBarry Smith } 13388e2fed03SBarry Smith } else { 13397adad957SLisandro Dalcin ierr = MPI_Reduce(&nz,0,1,MPIU_INT,MPI_SUM,0,((PetscObject)mat)->comm);CHKERRQ(ierr); 1340d0f46423SBarry Smith rlen = mat->rmap->n; 13418e2fed03SBarry Smith } 13428e2fed03SBarry Smith 13438e2fed03SBarry Smith /* load up the local row counts */ 1344b1d57f15SBarry Smith ierr = PetscMalloc((rlen+1)*sizeof(PetscInt),&row_lengths);CHKERRQ(ierr); 1345d0f46423SBarry Smith for (i=0; i<mat->rmap->n; i++) { 13468e2fed03SBarry Smith row_lengths[i] = A->i[i+1] - A->i[i] + B->i[i+1] - B->i[i]; 13478e2fed03SBarry Smith } 13488e2fed03SBarry Smith 13498e2fed03SBarry Smith /* store the row lengths to the file */ 135085ebf7a4SBarry Smith ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr); 1351958c9bccSBarry Smith if (!rank) { 1352d0f46423SBarry Smith ierr = PetscBinaryWrite(fd,row_lengths,mat->rmap->n,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 13538e2fed03SBarry Smith for (i=1; i<size; i++) { 135485ebf7a4SBarry Smith ierr = PetscViewerFlowControlStepMaster(viewer,i,message_count,flowcontrolcount);CHKERRQ(ierr); 13558e2fed03SBarry Smith rlen = range[i+1] - range[i]; 1356a25532f0SBarry Smith ierr = MPIULong_Recv(row_lengths,rlen,MPIU_INT,i,tag,((PetscObject)mat)->comm);CHKERRQ(ierr); 13576f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,row_lengths,rlen,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 13588e2fed03SBarry Smith } 135985ebf7a4SBarry Smith ierr = PetscViewerFlowControlEndMaster(viewer,message_count);CHKERRQ(ierr); 13608e2fed03SBarry Smith } else { 136185ebf7a4SBarry Smith ierr = PetscViewerFlowControlStepWorker(viewer,rank,message_count);CHKERRQ(ierr); 1362a25532f0SBarry Smith ierr = MPIULong_Send(row_lengths,mat->rmap->n,MPIU_INT,0,tag,((PetscObject)mat)->comm);CHKERRQ(ierr); 136385ebf7a4SBarry Smith ierr = PetscViewerFlowControlEndWorker(viewer,message_count);CHKERRQ(ierr); 13648e2fed03SBarry Smith } 13658e2fed03SBarry Smith ierr = PetscFree(row_lengths);CHKERRQ(ierr); 13668e2fed03SBarry Smith 13678e2fed03SBarry Smith /* load up the local column indices */ 13688e2fed03SBarry Smith nzmax = nz; /* )th processor needs space a largest processor needs */ 13697adad957SLisandro Dalcin ierr = MPI_Reduce(&nz,&nzmax,1,MPIU_INT,MPI_MAX,0,((PetscObject)mat)->comm);CHKERRQ(ierr); 1370b1d57f15SBarry Smith ierr = PetscMalloc((nzmax+1)*sizeof(PetscInt),&column_indices);CHKERRQ(ierr); 13718e2fed03SBarry Smith cnt = 0; 1372d0f46423SBarry Smith for (i=0; i<mat->rmap->n; i++) { 13738e2fed03SBarry Smith for (j=B->i[i]; j<B->i[i+1]; j++) { 13748e2fed03SBarry Smith if ( (col = garray[B->j[j]]) > cstart) break; 13758e2fed03SBarry Smith column_indices[cnt++] = col; 13768e2fed03SBarry Smith } 13778e2fed03SBarry Smith for (k=A->i[i]; k<A->i[i+1]; k++) { 13788e2fed03SBarry Smith column_indices[cnt++] = A->j[k] + cstart; 13798e2fed03SBarry Smith } 13808e2fed03SBarry Smith for (; j<B->i[i+1]; j++) { 13818e2fed03SBarry Smith column_indices[cnt++] = garray[B->j[j]]; 13828e2fed03SBarry Smith } 13838e2fed03SBarry Smith } 1384e32f2f54SBarry Smith if (cnt != A->nz + B->nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Internal PETSc error: cnt = %D nz = %D",cnt,A->nz+B->nz); 13858e2fed03SBarry Smith 13868e2fed03SBarry Smith /* store the column indices to the file */ 138785ebf7a4SBarry Smith ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr); 1388958c9bccSBarry Smith if (!rank) { 13898e2fed03SBarry Smith MPI_Status status; 13906f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,column_indices,nz,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 13918e2fed03SBarry Smith for (i=1; i<size; i++) { 139285ebf7a4SBarry Smith ierr = PetscViewerFlowControlStepMaster(viewer,i,message_count,flowcontrolcount);CHKERRQ(ierr); 13937adad957SLisandro Dalcin ierr = MPI_Recv(&rnz,1,MPIU_INT,i,tag,((PetscObject)mat)->comm,&status);CHKERRQ(ierr); 1394e32f2f54SBarry Smith if (rnz > nzmax) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Internal PETSc error: nz = %D nzmax = %D",nz,nzmax); 1395a25532f0SBarry Smith ierr = MPIULong_Recv(column_indices,rnz,MPIU_INT,i,tag,((PetscObject)mat)->comm);CHKERRQ(ierr); 13966f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,column_indices,rnz,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 13978e2fed03SBarry Smith } 139885ebf7a4SBarry Smith ierr = PetscViewerFlowControlEndMaster(viewer,message_count);CHKERRQ(ierr); 13998e2fed03SBarry Smith } else { 140085ebf7a4SBarry Smith ierr = PetscViewerFlowControlStepWorker(viewer,rank,message_count);CHKERRQ(ierr); 14017adad957SLisandro Dalcin ierr = MPI_Send(&nz,1,MPIU_INT,0,tag,((PetscObject)mat)->comm);CHKERRQ(ierr); 1402a25532f0SBarry Smith ierr = MPIULong_Send(column_indices,nz,MPIU_INT,0,tag,((PetscObject)mat)->comm);CHKERRQ(ierr); 140385ebf7a4SBarry Smith ierr = PetscViewerFlowControlEndWorker(viewer,message_count);CHKERRQ(ierr); 14048e2fed03SBarry Smith } 14058e2fed03SBarry Smith ierr = PetscFree(column_indices);CHKERRQ(ierr); 14068e2fed03SBarry Smith 14078e2fed03SBarry Smith /* load up the local column values */ 14088e2fed03SBarry Smith ierr = PetscMalloc((nzmax+1)*sizeof(PetscScalar),&column_values);CHKERRQ(ierr); 14098e2fed03SBarry Smith cnt = 0; 1410d0f46423SBarry Smith for (i=0; i<mat->rmap->n; i++) { 14118e2fed03SBarry Smith for (j=B->i[i]; j<B->i[i+1]; j++) { 14128e2fed03SBarry Smith if ( garray[B->j[j]] > cstart) break; 14138e2fed03SBarry Smith column_values[cnt++] = B->a[j]; 14148e2fed03SBarry Smith } 14158e2fed03SBarry Smith for (k=A->i[i]; k<A->i[i+1]; k++) { 14168e2fed03SBarry Smith column_values[cnt++] = A->a[k]; 14178e2fed03SBarry Smith } 14188e2fed03SBarry Smith for (; j<B->i[i+1]; j++) { 14198e2fed03SBarry Smith column_values[cnt++] = B->a[j]; 14208e2fed03SBarry Smith } 14218e2fed03SBarry Smith } 1422e32f2f54SBarry Smith if (cnt != A->nz + B->nz) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Internal PETSc error: cnt = %D nz = %D",cnt,A->nz+B->nz); 14238e2fed03SBarry Smith 14248e2fed03SBarry Smith /* store the column values to the file */ 142585ebf7a4SBarry Smith ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr); 1426958c9bccSBarry Smith if (!rank) { 14278e2fed03SBarry Smith MPI_Status status; 14286f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,column_values,nz,PETSC_SCALAR,PETSC_TRUE);CHKERRQ(ierr); 14298e2fed03SBarry Smith for (i=1; i<size; i++) { 143085ebf7a4SBarry Smith ierr = PetscViewerFlowControlStepMaster(viewer,i,message_count,flowcontrolcount);CHKERRQ(ierr); 14317adad957SLisandro Dalcin ierr = MPI_Recv(&rnz,1,MPIU_INT,i,tag,((PetscObject)mat)->comm,&status);CHKERRQ(ierr); 1432e32f2f54SBarry Smith if (rnz > nzmax) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Internal PETSc error: nz = %D nzmax = %D",nz,nzmax); 1433a25532f0SBarry Smith ierr = MPIULong_Recv(column_values,rnz,MPIU_SCALAR,i,tag,((PetscObject)mat)->comm);CHKERRQ(ierr); 14346f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,column_values,rnz,PETSC_SCALAR,PETSC_TRUE);CHKERRQ(ierr); 14358e2fed03SBarry Smith } 143685ebf7a4SBarry Smith ierr = PetscViewerFlowControlEndMaster(viewer,message_count);CHKERRQ(ierr); 14378e2fed03SBarry Smith } else { 143885ebf7a4SBarry Smith ierr = PetscViewerFlowControlStepWorker(viewer,rank,message_count);CHKERRQ(ierr); 14397adad957SLisandro Dalcin ierr = MPI_Send(&nz,1,MPIU_INT,0,tag,((PetscObject)mat)->comm);CHKERRQ(ierr); 1440a25532f0SBarry Smith ierr = MPIULong_Send(column_values,nz,MPIU_SCALAR,0,tag,((PetscObject)mat)->comm);CHKERRQ(ierr); 144185ebf7a4SBarry Smith ierr = PetscViewerFlowControlEndWorker(viewer,message_count);CHKERRQ(ierr); 14428e2fed03SBarry Smith } 14438e2fed03SBarry Smith ierr = PetscFree(column_values);CHKERRQ(ierr); 1444b37d52dbSMark F. Adams 1445b37d52dbSMark F. Adams ierr = PetscViewerBinaryGetInfoPointer(viewer,&file);CHKERRQ(ierr); 1446b37d52dbSMark F. Adams if (file) { 1447b37d52dbSMark F. Adams fprintf(file,"-matload_block_size %d\n",(int)mat->rmap->bs); 1448b37d52dbSMark F. Adams } 1449b37d52dbSMark F. Adams 14508e2fed03SBarry Smith PetscFunctionReturn(0); 14518e2fed03SBarry Smith } 14528e2fed03SBarry Smith 14538e2fed03SBarry Smith #undef __FUNCT__ 14544a2ae208SSatish Balay #define __FUNCT__ "MatView_MPIAIJ_ASCIIorDraworSocket" 1455dfbe8321SBarry Smith PetscErrorCode MatView_MPIAIJ_ASCIIorDraworSocket(Mat mat,PetscViewer viewer) 1456416022c9SBarry Smith { 145744a69424SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 1458dfbe8321SBarry Smith PetscErrorCode ierr; 145932dcc486SBarry Smith PetscMPIInt rank = aij->rank,size = aij->size; 1460ace3abfcSBarry Smith PetscBool isdraw,iascii,isbinary; 1461b0a32e0cSBarry Smith PetscViewer sviewer; 1462f3ef73ceSBarry Smith PetscViewerFormat format; 1463416022c9SBarry Smith 14643a40ed3dSBarry Smith PetscFunctionBegin; 1465251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 1466251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1467251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 146832077d6dSBarry Smith if (iascii) { 1469b0a32e0cSBarry Smith ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 1470456192e2SBarry Smith if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 14714e220ebcSLois Curfman McInnes MatInfo info; 1472ace3abfcSBarry Smith PetscBool inodes; 1473923f20ffSKris Buschelman 14747adad957SLisandro Dalcin ierr = MPI_Comm_rank(((PetscObject)mat)->comm,&rank);CHKERRQ(ierr); 1475888f2ed8SSatish Balay ierr = MatGetInfo(mat,MAT_LOCAL,&info);CHKERRQ(ierr); 1476923f20ffSKris Buschelman ierr = MatInodeGetInodeSizes(aij->A,PETSC_NULL,(PetscInt **)&inodes,PETSC_NULL);CHKERRQ(ierr); 14777b23a99aSBarry Smith ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_TRUE);CHKERRQ(ierr); 1478923f20ffSKris Buschelman if (!inodes) { 147977431f27SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local rows %D nz %D nz alloced %D mem %D, not using I-node routines\n", 1480d0f46423SBarry Smith rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(PetscInt)info.memory);CHKERRQ(ierr); 14816831982aSBarry Smith } else { 148277431f27SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local rows %D nz %D nz alloced %D mem %D, using I-node routines\n", 1483d0f46423SBarry Smith rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(PetscInt)info.memory);CHKERRQ(ierr); 14846831982aSBarry Smith } 1485888f2ed8SSatish Balay ierr = MatGetInfo(aij->A,MAT_LOCAL,&info);CHKERRQ(ierr); 148677431f27SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] on-diagonal part: nz %D \n",rank,(PetscInt)info.nz_used);CHKERRQ(ierr); 1487888f2ed8SSatish Balay ierr = MatGetInfo(aij->B,MAT_LOCAL,&info);CHKERRQ(ierr); 148877431f27SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] off-diagonal part: nz %D \n",rank,(PetscInt)info.nz_used);CHKERRQ(ierr); 1489b0a32e0cSBarry Smith ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 14907b23a99aSBarry Smith ierr = PetscViewerASCIISynchronizedAllow(viewer,PETSC_FALSE);CHKERRQ(ierr); 149107d81ca4SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Information on VecScatter used in matrix-vector product: \n");CHKERRQ(ierr); 1492a40aa06bSLois Curfman McInnes ierr = VecScatterView(aij->Mvctx,viewer);CHKERRQ(ierr); 14933a40ed3dSBarry Smith PetscFunctionReturn(0); 1494fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_INFO) { 1495923f20ffSKris Buschelman PetscInt inodecount,inodelimit,*inodes; 1496923f20ffSKris Buschelman ierr = MatInodeGetInodeSizes(aij->A,&inodecount,&inodes,&inodelimit);CHKERRQ(ierr); 1497923f20ffSKris Buschelman if (inodes) { 1498923f20ffSKris Buschelman ierr = PetscViewerASCIIPrintf(viewer,"using I-node (on process 0) routines: found %D nodes, limit used is %D\n",inodecount,inodelimit);CHKERRQ(ierr); 1499d38fa0fbSBarry Smith } else { 1500d38fa0fbSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"not using I-node (on process 0) routines\n");CHKERRQ(ierr); 1501d38fa0fbSBarry Smith } 15023a40ed3dSBarry Smith PetscFunctionReturn(0); 15034aedb280SBarry Smith } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 15044aedb280SBarry Smith PetscFunctionReturn(0); 150508480c60SBarry Smith } 15068e2fed03SBarry Smith } else if (isbinary) { 15078e2fed03SBarry Smith if (size == 1) { 15087adad957SLisandro Dalcin ierr = PetscObjectSetName((PetscObject)aij->A,((PetscObject)mat)->name);CHKERRQ(ierr); 15098e2fed03SBarry Smith ierr = MatView(aij->A,viewer);CHKERRQ(ierr); 15108e2fed03SBarry Smith } else { 15118e2fed03SBarry Smith ierr = MatView_MPIAIJ_Binary(mat,viewer);CHKERRQ(ierr); 15128e2fed03SBarry Smith } 15138e2fed03SBarry Smith PetscFunctionReturn(0); 15140f5bd95cSBarry Smith } else if (isdraw) { 1515b0a32e0cSBarry Smith PetscDraw draw; 1516ace3abfcSBarry Smith PetscBool isnull; 1517b0a32e0cSBarry Smith ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 1518b0a32e0cSBarry Smith ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); if (isnull) PetscFunctionReturn(0); 151919bcc07fSBarry Smith } 152019bcc07fSBarry Smith 152117699dbbSLois Curfman McInnes if (size == 1) { 15227adad957SLisandro Dalcin ierr = PetscObjectSetName((PetscObject)aij->A,((PetscObject)mat)->name);CHKERRQ(ierr); 152378b31e54SBarry Smith ierr = MatView(aij->A,viewer);CHKERRQ(ierr); 15243a40ed3dSBarry Smith } else { 152595373324SBarry Smith /* assemble the entire matrix onto first processor. */ 152695373324SBarry Smith Mat A; 1527ec8511deSBarry Smith Mat_SeqAIJ *Aloc; 1528d0f46423SBarry Smith PetscInt M = mat->rmap->N,N = mat->cmap->N,m,*ai,*aj,row,*cols,i,*ct; 1529dd6ea824SBarry Smith MatScalar *a; 15302ee70a88SLois Curfman McInnes 153132a366e4SMatthew Knepley if (mat->rmap->N > 1024) { 1532ace3abfcSBarry Smith PetscBool flg = PETSC_FALSE; 153332a366e4SMatthew Knepley 1534acfcf0e5SJed Brown ierr = PetscOptionsGetBool(((PetscObject) mat)->prefix, "-mat_ascii_output_large", &flg,PETSC_NULL);CHKERRQ(ierr); 153532a366e4SMatthew Knepley if (!flg) { 1536e7e72b3dSBarry Smith SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_ARG_OUTOFRANGE,"ASCII matrix output not allowed for matrices with more than 1024 rows, use binary format instead.\nYou can override this restriction using -mat_ascii_output_large."); 153732a366e4SMatthew Knepley } 153832a366e4SMatthew Knepley } 15390805154bSBarry Smith 15407adad957SLisandro Dalcin ierr = MatCreate(((PetscObject)mat)->comm,&A);CHKERRQ(ierr); 154117699dbbSLois Curfman McInnes if (!rank) { 1542f69a0ea3SMatthew Knepley ierr = MatSetSizes(A,M,N,M,N);CHKERRQ(ierr); 15433a40ed3dSBarry Smith } else { 1544f69a0ea3SMatthew Knepley ierr = MatSetSizes(A,0,0,M,N);CHKERRQ(ierr); 154595373324SBarry Smith } 1546f204ca49SKris Buschelman /* This is just a temporary matrix, so explicitly using MATMPIAIJ is probably best */ 1547f204ca49SKris Buschelman ierr = MatSetType(A,MATMPIAIJ);CHKERRQ(ierr); 1548f204ca49SKris Buschelman ierr = MatMPIAIJSetPreallocation(A,0,PETSC_NULL,0,PETSC_NULL);CHKERRQ(ierr); 15492b82e772SSatish Balay ierr = MatSetOption(A,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); 155052e6d16bSBarry Smith ierr = PetscLogObjectParent(mat,A);CHKERRQ(ierr); 1551416022c9SBarry Smith 155295373324SBarry Smith /* copy over the A part */ 1553ec8511deSBarry Smith Aloc = (Mat_SeqAIJ*)aij->A->data; 1554d0f46423SBarry Smith m = aij->A->rmap->n; ai = Aloc->i; aj = Aloc->j; a = Aloc->a; 1555d0f46423SBarry Smith row = mat->rmap->rstart; 1556d0f46423SBarry Smith for (i=0; i<ai[m]; i++) {aj[i] += mat->cmap->rstart ;} 155795373324SBarry Smith for (i=0; i<m; i++) { 1558416022c9SBarry Smith ierr = MatSetValues(A,1,&row,ai[i+1]-ai[i],aj,a,INSERT_VALUES);CHKERRQ(ierr); 155995373324SBarry Smith row++; a += ai[i+1]-ai[i]; aj += ai[i+1]-ai[i]; 156095373324SBarry Smith } 15612ee70a88SLois Curfman McInnes aj = Aloc->j; 1562d0f46423SBarry Smith for (i=0; i<ai[m]; i++) {aj[i] -= mat->cmap->rstart;} 156395373324SBarry Smith 156495373324SBarry Smith /* copy over the B part */ 1565ec8511deSBarry Smith Aloc = (Mat_SeqAIJ*)aij->B->data; 1566d0f46423SBarry Smith m = aij->B->rmap->n; ai = Aloc->i; aj = Aloc->j; a = Aloc->a; 1567d0f46423SBarry Smith row = mat->rmap->rstart; 1568b1d57f15SBarry Smith ierr = PetscMalloc((ai[m]+1)*sizeof(PetscInt),&cols);CHKERRQ(ierr); 1569b0a32e0cSBarry Smith ct = cols; 1570bfec09a0SHong Zhang for (i=0; i<ai[m]; i++) {cols[i] = aij->garray[aj[i]];} 157195373324SBarry Smith for (i=0; i<m; i++) { 1572416022c9SBarry Smith ierr = MatSetValues(A,1,&row,ai[i+1]-ai[i],cols,a,INSERT_VALUES);CHKERRQ(ierr); 157395373324SBarry Smith row++; a += ai[i+1]-ai[i]; cols += ai[i+1]-ai[i]; 157495373324SBarry Smith } 1575606d414cSSatish Balay ierr = PetscFree(ct);CHKERRQ(ierr); 15766d4a8577SBarry Smith ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 15776d4a8577SBarry Smith ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 157855843e3eSBarry Smith /* 157955843e3eSBarry Smith Everyone has to call to draw the matrix since the graphics waits are 1580b0a32e0cSBarry Smith synchronized across all processors that share the PetscDraw object 158155843e3eSBarry Smith */ 1582b0a32e0cSBarry Smith ierr = PetscViewerGetSingleton(viewer,&sviewer);CHKERRQ(ierr); 1583e03a110bSBarry Smith if (!rank) { 15847adad957SLisandro Dalcin ierr = PetscObjectSetName((PetscObject)((Mat_MPIAIJ*)(A->data))->A,((PetscObject)mat)->name);CHKERRQ(ierr); 15857566de4bSShri Abhyankar /* Set the type name to MATMPIAIJ so that the correct type can be printed out by PetscObjectPrintClassNamePrefixType() in MatView_SeqAIJ_ASCII()*/ 15867566de4bSShri Abhyankar PetscStrcpy(((PetscObject)((Mat_MPIAIJ*)(A->data))->A)->type_name,MATMPIAIJ); 15876831982aSBarry Smith ierr = MatView(((Mat_MPIAIJ*)(A->data))->A,sviewer);CHKERRQ(ierr); 158895373324SBarry Smith } 1589b0a32e0cSBarry Smith ierr = PetscViewerRestoreSingleton(viewer,&sviewer);CHKERRQ(ierr); 15906bf464f9SBarry Smith ierr = MatDestroy(&A);CHKERRQ(ierr); 159195373324SBarry Smith } 15923a40ed3dSBarry Smith PetscFunctionReturn(0); 15931eb62cbbSBarry Smith } 15941eb62cbbSBarry Smith 15954a2ae208SSatish Balay #undef __FUNCT__ 15964a2ae208SSatish Balay #define __FUNCT__ "MatView_MPIAIJ" 1597dfbe8321SBarry Smith PetscErrorCode MatView_MPIAIJ(Mat mat,PetscViewer viewer) 1598416022c9SBarry Smith { 1599dfbe8321SBarry Smith PetscErrorCode ierr; 1600ace3abfcSBarry Smith PetscBool iascii,isdraw,issocket,isbinary; 1601416022c9SBarry Smith 16023a40ed3dSBarry Smith PetscFunctionBegin; 1603251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1604251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 1605251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 1606251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSOCKET,&issocket);CHKERRQ(ierr); 160732077d6dSBarry Smith if (iascii || isdraw || isbinary || issocket) { 16087b2a1423SBarry Smith ierr = MatView_MPIAIJ_ASCIIorDraworSocket(mat,viewer);CHKERRQ(ierr); 16095cd90555SBarry Smith } else { 1610e32f2f54SBarry Smith SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported by MPIAIJ matrices",((PetscObject)viewer)->type_name); 1611416022c9SBarry Smith } 16123a40ed3dSBarry Smith PetscFunctionReturn(0); 1613416022c9SBarry Smith } 1614416022c9SBarry Smith 16154a2ae208SSatish Balay #undef __FUNCT__ 161641f059aeSBarry Smith #define __FUNCT__ "MatSOR_MPIAIJ" 161741f059aeSBarry Smith PetscErrorCode MatSOR_MPIAIJ(Mat matin,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 16188a729477SBarry Smith { 161944a69424SLois Curfman McInnes Mat_MPIAIJ *mat = (Mat_MPIAIJ*)matin->data; 1620dfbe8321SBarry Smith PetscErrorCode ierr; 16216987fefcSBarry Smith Vec bb1 = 0; 1622ace3abfcSBarry Smith PetscBool hasop; 16238a729477SBarry Smith 16243a40ed3dSBarry Smith PetscFunctionBegin; 162585911e72SJed Brown if (its > 1 || ~flag & SOR_ZERO_INITIAL_GUESS || flag & SOR_EISENSTAT) { 162685911e72SJed Brown ierr = VecDuplicate(bb,&bb1);CHKERRQ(ierr); 162785911e72SJed Brown } 16282798e883SHong Zhang 1629a2b30743SBarry Smith if (flag == SOR_APPLY_UPPER) { 163041f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr); 1631a2b30743SBarry Smith PetscFunctionReturn(0); 1632a2b30743SBarry Smith } 1633a2b30743SBarry Smith 1634c16cb8f2SBarry Smith if ((flag & SOR_LOCAL_SYMMETRIC_SWEEP) == SOR_LOCAL_SYMMETRIC_SWEEP){ 1635da3a660dSBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 163641f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr); 16372798e883SHong Zhang its--; 1638da3a660dSBarry Smith } 16392798e883SHong Zhang 16402798e883SHong Zhang while (its--) { 1641ca9f406cSSatish Balay ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1642ca9f406cSSatish Balay ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 16432798e883SHong Zhang 1644c14dc6b6SHong Zhang /* update rhs: bb1 = bb - B*x */ 1645efb30889SBarry Smith ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr); 1646c14dc6b6SHong Zhang ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr); 16472798e883SHong Zhang 1648c14dc6b6SHong Zhang /* local sweep */ 164941f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_SYMMETRIC_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr); 16502798e883SHong Zhang } 16513a40ed3dSBarry Smith } else if (flag & SOR_LOCAL_FORWARD_SWEEP){ 1652da3a660dSBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 165341f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr); 16542798e883SHong Zhang its--; 1655da3a660dSBarry Smith } 16562798e883SHong Zhang while (its--) { 1657ca9f406cSSatish Balay ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1658ca9f406cSSatish Balay ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 16592798e883SHong Zhang 1660c14dc6b6SHong Zhang /* update rhs: bb1 = bb - B*x */ 1661efb30889SBarry Smith ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr); 1662c14dc6b6SHong Zhang ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr); 1663c14dc6b6SHong Zhang 1664c14dc6b6SHong Zhang /* local sweep */ 166541f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_FORWARD_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr); 16662798e883SHong Zhang } 16673a40ed3dSBarry Smith } else if (flag & SOR_LOCAL_BACKWARD_SWEEP){ 1668da3a660dSBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 166941f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr); 16702798e883SHong Zhang its--; 1671da3a660dSBarry Smith } 16722798e883SHong Zhang while (its--) { 1673ca9f406cSSatish Balay ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1674ca9f406cSSatish Balay ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 16752798e883SHong Zhang 1676c14dc6b6SHong Zhang /* update rhs: bb1 = bb - B*x */ 1677efb30889SBarry Smith ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr); 1678c14dc6b6SHong Zhang ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr); 16792798e883SHong Zhang 1680c14dc6b6SHong Zhang /* local sweep */ 168141f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_BACKWARD_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr); 16822798e883SHong Zhang } 1683a7420bb7SBarry Smith } else if (flag & SOR_EISENSTAT) { 1684a7420bb7SBarry Smith Vec xx1; 1685a7420bb7SBarry Smith 1686a7420bb7SBarry Smith ierr = VecDuplicate(bb,&xx1);CHKERRQ(ierr); 168741f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,(MatSORType)(SOR_ZERO_INITIAL_GUESS | SOR_LOCAL_BACKWARD_SWEEP),fshift,lits,1,xx);CHKERRQ(ierr); 1688a7420bb7SBarry Smith 1689a7420bb7SBarry Smith ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1690a7420bb7SBarry Smith ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1691a7420bb7SBarry Smith if (!mat->diag) { 1692a7420bb7SBarry Smith ierr = MatGetVecs(matin,&mat->diag,PETSC_NULL);CHKERRQ(ierr); 1693a7420bb7SBarry Smith ierr = MatGetDiagonal(matin,mat->diag);CHKERRQ(ierr); 1694a7420bb7SBarry Smith } 1695bd0c2dcbSBarry Smith ierr = MatHasOperation(matin,MATOP_MULT_DIAGONAL_BLOCK,&hasop);CHKERRQ(ierr); 1696bd0c2dcbSBarry Smith if (hasop) { 1697bd0c2dcbSBarry Smith ierr = MatMultDiagonalBlock(matin,xx,bb1);CHKERRQ(ierr); 1698bd0c2dcbSBarry Smith } else { 1699a7420bb7SBarry Smith ierr = VecPointwiseMult(bb1,mat->diag,xx);CHKERRQ(ierr); 1700bd0c2dcbSBarry Smith } 1701887ee2caSBarry Smith ierr = VecAYPX(bb1,(omega-2.0)/omega,bb);CHKERRQ(ierr); 1702887ee2caSBarry Smith 1703a7420bb7SBarry Smith ierr = MatMultAdd(mat->B,mat->lvec,bb1,bb1);CHKERRQ(ierr); 1704a7420bb7SBarry Smith 1705a7420bb7SBarry Smith /* local sweep */ 170641f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,(MatSORType)(SOR_ZERO_INITIAL_GUESS | SOR_LOCAL_FORWARD_SWEEP),fshift,lits,1,xx1);CHKERRQ(ierr); 1707a7420bb7SBarry Smith ierr = VecAXPY(xx,1.0,xx1);CHKERRQ(ierr); 17086bf464f9SBarry Smith ierr = VecDestroy(&xx1);CHKERRQ(ierr); 170944b1af1bSBarry Smith } else SETERRQ(((PetscObject)matin)->comm,PETSC_ERR_SUP,"Parallel SOR not supported"); 1710c14dc6b6SHong Zhang 17116bf464f9SBarry Smith ierr = VecDestroy(&bb1);CHKERRQ(ierr); 17123a40ed3dSBarry Smith PetscFunctionReturn(0); 17138a729477SBarry Smith } 1714a66be287SLois Curfman McInnes 17154a2ae208SSatish Balay #undef __FUNCT__ 171642e855d1Svictor #define __FUNCT__ "MatPermute_MPIAIJ" 171742e855d1Svictor PetscErrorCode MatPermute_MPIAIJ(Mat A,IS rowp,IS colp,Mat *B) 171842e855d1Svictor { 171923f569faSJed Brown MPI_Comm comm; 172023f569faSJed Brown PetscInt first,local_rowsize,local_colsize; 17215d0c19d7SBarry Smith const PetscInt *rows; 172242e855d1Svictor IS crowp,growp,irowp,lrowp,lcolp,icolp; 172342e855d1Svictor PetscErrorCode ierr; 172442e855d1Svictor 172542e855d1Svictor PetscFunctionBegin; 172642e855d1Svictor ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 172723f569faSJed Brown /* make a collective version of 'rowp', this is to be tolerant of users who pass serial index sets */ 172823f569faSJed Brown ierr = ISOnComm(rowp,comm,PETSC_USE_POINTER,&crowp);CHKERRQ(ierr); 172942e855d1Svictor /* collect the global row permutation and invert it */ 173042e855d1Svictor ierr = ISAllGather(crowp,&growp);CHKERRQ(ierr); 173142e855d1Svictor ierr = ISSetPermutation(growp);CHKERRQ(ierr); 17326bf464f9SBarry Smith ierr = ISDestroy(&crowp);CHKERRQ(ierr); 173342e855d1Svictor ierr = ISInvertPermutation(growp,PETSC_DECIDE,&irowp);CHKERRQ(ierr); 173423f569faSJed Brown ierr = ISDestroy(&growp);CHKERRQ(ierr); 173542e855d1Svictor /* get the local target indices */ 173642e855d1Svictor ierr = MatGetOwnershipRange(A,&first,PETSC_NULL);CHKERRQ(ierr); 173723f569faSJed Brown ierr = MatGetLocalSize(A,&local_rowsize,&local_colsize);CHKERRQ(ierr); 173842e855d1Svictor ierr = ISGetIndices(irowp,&rows);CHKERRQ(ierr); 173923f569faSJed Brown ierr = ISCreateGeneral(PETSC_COMM_SELF,local_rowsize,rows+first,PETSC_COPY_VALUES,&lrowp);CHKERRQ(ierr); 174042e855d1Svictor ierr = ISRestoreIndices(irowp,&rows);CHKERRQ(ierr); 17416bf464f9SBarry Smith ierr = ISDestroy(&irowp);CHKERRQ(ierr); 174242e855d1Svictor /* the column permutation is so much easier; 174342e855d1Svictor make a local version of 'colp' and invert it */ 174423f569faSJed Brown ierr = ISOnComm(colp,PETSC_COMM_SELF,PETSC_USE_POINTER,&lcolp);CHKERRQ(ierr); 1745dbf0e21dSBarry Smith ierr = ISSetPermutation(lcolp);CHKERRQ(ierr); 174642e855d1Svictor ierr = ISInvertPermutation(lcolp,PETSC_DECIDE,&icolp);CHKERRQ(ierr); 17476bf464f9SBarry Smith ierr = ISDestroy(&lcolp);CHKERRQ(ierr); 174842e855d1Svictor /* now we just get the submatrix */ 174923f569faSJed Brown ierr = MatGetSubMatrix_MPIAIJ_Private(A,lrowp,icolp,local_colsize,MAT_INITIAL_MATRIX,B);CHKERRQ(ierr); 175042e855d1Svictor /* clean up */ 17516bf464f9SBarry Smith ierr = ISDestroy(&lrowp);CHKERRQ(ierr); 17526bf464f9SBarry Smith ierr = ISDestroy(&icolp);CHKERRQ(ierr); 175342e855d1Svictor PetscFunctionReturn(0); 175442e855d1Svictor } 175542e855d1Svictor 175642e855d1Svictor #undef __FUNCT__ 17574a2ae208SSatish Balay #define __FUNCT__ "MatGetInfo_MPIAIJ" 1758dfbe8321SBarry Smith PetscErrorCode MatGetInfo_MPIAIJ(Mat matin,MatInfoType flag,MatInfo *info) 1759a66be287SLois Curfman McInnes { 1760a66be287SLois Curfman McInnes Mat_MPIAIJ *mat = (Mat_MPIAIJ*)matin->data; 1761a66be287SLois Curfman McInnes Mat A = mat->A,B = mat->B; 1762dfbe8321SBarry Smith PetscErrorCode ierr; 1763329f5518SBarry Smith PetscReal isend[5],irecv[5]; 1764a66be287SLois Curfman McInnes 17653a40ed3dSBarry Smith PetscFunctionBegin; 17664e220ebcSLois Curfman McInnes info->block_size = 1.0; 17674e220ebcSLois Curfman McInnes ierr = MatGetInfo(A,MAT_LOCAL,info);CHKERRQ(ierr); 17684e220ebcSLois Curfman McInnes isend[0] = info->nz_used; isend[1] = info->nz_allocated; isend[2] = info->nz_unneeded; 17694e220ebcSLois Curfman McInnes isend[3] = info->memory; isend[4] = info->mallocs; 17704e220ebcSLois Curfman McInnes ierr = MatGetInfo(B,MAT_LOCAL,info);CHKERRQ(ierr); 17714e220ebcSLois Curfman McInnes isend[0] += info->nz_used; isend[1] += info->nz_allocated; isend[2] += info->nz_unneeded; 17724e220ebcSLois Curfman McInnes isend[3] += info->memory; isend[4] += info->mallocs; 1773a66be287SLois Curfman McInnes if (flag == MAT_LOCAL) { 17744e220ebcSLois Curfman McInnes info->nz_used = isend[0]; 17754e220ebcSLois Curfman McInnes info->nz_allocated = isend[1]; 17764e220ebcSLois Curfman McInnes info->nz_unneeded = isend[2]; 17774e220ebcSLois Curfman McInnes info->memory = isend[3]; 17784e220ebcSLois Curfman McInnes info->mallocs = isend[4]; 1779a66be287SLois Curfman McInnes } else if (flag == MAT_GLOBAL_MAX) { 1780d9822059SBarry Smith ierr = MPI_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,((PetscObject)matin)->comm);CHKERRQ(ierr); 17814e220ebcSLois Curfman McInnes info->nz_used = irecv[0]; 17824e220ebcSLois Curfman McInnes info->nz_allocated = irecv[1]; 17834e220ebcSLois Curfman McInnes info->nz_unneeded = irecv[2]; 17844e220ebcSLois Curfman McInnes info->memory = irecv[3]; 17854e220ebcSLois Curfman McInnes info->mallocs = irecv[4]; 1786a66be287SLois Curfman McInnes } else if (flag == MAT_GLOBAL_SUM) { 1787d9822059SBarry Smith ierr = MPI_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,((PetscObject)matin)->comm);CHKERRQ(ierr); 17884e220ebcSLois Curfman McInnes info->nz_used = irecv[0]; 17894e220ebcSLois Curfman McInnes info->nz_allocated = irecv[1]; 17904e220ebcSLois Curfman McInnes info->nz_unneeded = irecv[2]; 17914e220ebcSLois Curfman McInnes info->memory = irecv[3]; 17924e220ebcSLois Curfman McInnes info->mallocs = irecv[4]; 1793a66be287SLois Curfman McInnes } 17944e220ebcSLois Curfman McInnes info->fill_ratio_given = 0; /* no parallel LU/ILU/Cholesky */ 17954e220ebcSLois Curfman McInnes info->fill_ratio_needed = 0; 17964e220ebcSLois Curfman McInnes info->factor_mallocs = 0; 17973a40ed3dSBarry Smith PetscFunctionReturn(0); 1798a66be287SLois Curfman McInnes } 1799a66be287SLois Curfman McInnes 18004a2ae208SSatish Balay #undef __FUNCT__ 18014a2ae208SSatish Balay #define __FUNCT__ "MatSetOption_MPIAIJ" 1802ace3abfcSBarry Smith PetscErrorCode MatSetOption_MPIAIJ(Mat A,MatOption op,PetscBool flg) 1803c74985f6SBarry Smith { 1804c0bbcb79SLois Curfman McInnes Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1805dfbe8321SBarry Smith PetscErrorCode ierr; 1806c74985f6SBarry Smith 18073a40ed3dSBarry Smith PetscFunctionBegin; 180812c028f9SKris Buschelman switch (op) { 1809512a5fc5SBarry Smith case MAT_NEW_NONZERO_LOCATIONS: 181012c028f9SKris Buschelman case MAT_NEW_NONZERO_ALLOCATION_ERR: 181128b2fa4aSMatthew Knepley case MAT_UNUSED_NONZERO_LOCATION_ERR: 1812a9817697SBarry Smith case MAT_KEEP_NONZERO_PATTERN: 181312c028f9SKris Buschelman case MAT_NEW_NONZERO_LOCATION_ERR: 181412c028f9SKris Buschelman case MAT_USE_INODES: 181512c028f9SKris Buschelman case MAT_IGNORE_ZERO_ENTRIES: 1816fa1f0d2cSMatthew G Knepley MatCheckPreallocated(A,1); 18174e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 18184e0d8c25SBarry Smith ierr = MatSetOption(a->B,op,flg);CHKERRQ(ierr); 181912c028f9SKris Buschelman break; 182012c028f9SKris Buschelman case MAT_ROW_ORIENTED: 18214e0d8c25SBarry Smith a->roworiented = flg; 18224e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 18234e0d8c25SBarry Smith ierr = MatSetOption(a->B,op,flg);CHKERRQ(ierr); 182412c028f9SKris Buschelman break; 18254e0d8c25SBarry Smith case MAT_NEW_DIAGONALS: 1826290bbb0aSBarry Smith ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr); 182712c028f9SKris Buschelman break; 182812c028f9SKris Buschelman case MAT_IGNORE_OFF_PROC_ENTRIES: 18295c0f0b64SBarry Smith a->donotstash = flg; 183012c028f9SKris Buschelman break; 1831ffa07934SHong Zhang case MAT_SPD: 1832ffa07934SHong Zhang A->spd_set = PETSC_TRUE; 1833ffa07934SHong Zhang A->spd = flg; 1834ffa07934SHong Zhang if (flg) { 1835ffa07934SHong Zhang A->symmetric = PETSC_TRUE; 1836ffa07934SHong Zhang A->structurally_symmetric = PETSC_TRUE; 1837ffa07934SHong Zhang A->symmetric_set = PETSC_TRUE; 1838ffa07934SHong Zhang A->structurally_symmetric_set = PETSC_TRUE; 1839ffa07934SHong Zhang } 1840ffa07934SHong Zhang break; 184177e54ba9SKris Buschelman case MAT_SYMMETRIC: 18424e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 184325f421beSHong Zhang break; 184477e54ba9SKris Buschelman case MAT_STRUCTURALLY_SYMMETRIC: 1845eeffb40dSHong Zhang ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 1846eeffb40dSHong Zhang break; 1847bf108f30SBarry Smith case MAT_HERMITIAN: 1848eeffb40dSHong Zhang ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 1849eeffb40dSHong Zhang break; 1850bf108f30SBarry Smith case MAT_SYMMETRY_ETERNAL: 18514e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 185277e54ba9SKris Buschelman break; 185312c028f9SKris Buschelman default: 1854e32f2f54SBarry Smith SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op); 18553a40ed3dSBarry Smith } 18563a40ed3dSBarry Smith PetscFunctionReturn(0); 1857c74985f6SBarry Smith } 1858c74985f6SBarry Smith 18594a2ae208SSatish Balay #undef __FUNCT__ 18604a2ae208SSatish Balay #define __FUNCT__ "MatGetRow_MPIAIJ" 1861b1d57f15SBarry Smith PetscErrorCode MatGetRow_MPIAIJ(Mat matin,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 186239e00950SLois Curfman McInnes { 1863154123eaSLois Curfman McInnes Mat_MPIAIJ *mat = (Mat_MPIAIJ*)matin->data; 186487828ca2SBarry Smith PetscScalar *vworkA,*vworkB,**pvA,**pvB,*v_p; 18656849ba73SBarry Smith PetscErrorCode ierr; 1866d0f46423SBarry Smith PetscInt i,*cworkA,*cworkB,**pcA,**pcB,cstart = matin->cmap->rstart; 1867d0f46423SBarry Smith PetscInt nztot,nzA,nzB,lrow,rstart = matin->rmap->rstart,rend = matin->rmap->rend; 1868b1d57f15SBarry Smith PetscInt *cmap,*idx_p; 186939e00950SLois Curfman McInnes 18703a40ed3dSBarry Smith PetscFunctionBegin; 1871e32f2f54SBarry Smith if (mat->getrowactive) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Already active"); 18727a0afa10SBarry Smith mat->getrowactive = PETSC_TRUE; 18737a0afa10SBarry Smith 187470f0671dSBarry Smith if (!mat->rowvalues && (idx || v)) { 18757a0afa10SBarry Smith /* 18767a0afa10SBarry Smith allocate enough space to hold information from the longest row. 18777a0afa10SBarry Smith */ 18787a0afa10SBarry Smith Mat_SeqAIJ *Aa = (Mat_SeqAIJ*)mat->A->data,*Ba = (Mat_SeqAIJ*)mat->B->data; 1879b1d57f15SBarry Smith PetscInt max = 1,tmp; 1880d0f46423SBarry Smith for (i=0; i<matin->rmap->n; i++) { 18817a0afa10SBarry Smith tmp = Aa->i[i+1] - Aa->i[i] + Ba->i[i+1] - Ba->i[i]; 18827a0afa10SBarry Smith if (max < tmp) { max = tmp; } 18837a0afa10SBarry Smith } 18841d79065fSBarry Smith ierr = PetscMalloc2(max,PetscScalar,&mat->rowvalues,max,PetscInt,&mat->rowindices);CHKERRQ(ierr); 18857a0afa10SBarry Smith } 18867a0afa10SBarry Smith 1887e7e72b3dSBarry Smith if (row < rstart || row >= rend) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only local rows"); 1888abc0e9e4SLois Curfman McInnes lrow = row - rstart; 188939e00950SLois Curfman McInnes 1890154123eaSLois Curfman McInnes pvA = &vworkA; pcA = &cworkA; pvB = &vworkB; pcB = &cworkB; 1891154123eaSLois Curfman McInnes if (!v) {pvA = 0; pvB = 0;} 1892154123eaSLois Curfman McInnes if (!idx) {pcA = 0; if (!v) pcB = 0;} 1893f830108cSBarry Smith ierr = (*mat->A->ops->getrow)(mat->A,lrow,&nzA,pcA,pvA);CHKERRQ(ierr); 1894f830108cSBarry Smith ierr = (*mat->B->ops->getrow)(mat->B,lrow,&nzB,pcB,pvB);CHKERRQ(ierr); 1895154123eaSLois Curfman McInnes nztot = nzA + nzB; 1896154123eaSLois Curfman McInnes 189770f0671dSBarry Smith cmap = mat->garray; 1898154123eaSLois Curfman McInnes if (v || idx) { 1899154123eaSLois Curfman McInnes if (nztot) { 1900154123eaSLois Curfman McInnes /* Sort by increasing column numbers, assuming A and B already sorted */ 1901b1d57f15SBarry Smith PetscInt imark = -1; 1902154123eaSLois Curfman McInnes if (v) { 190370f0671dSBarry Smith *v = v_p = mat->rowvalues; 190439e00950SLois Curfman McInnes for (i=0; i<nzB; i++) { 190570f0671dSBarry Smith if (cmap[cworkB[i]] < cstart) v_p[i] = vworkB[i]; 1906154123eaSLois Curfman McInnes else break; 1907154123eaSLois Curfman McInnes } 1908154123eaSLois Curfman McInnes imark = i; 190970f0671dSBarry Smith for (i=0; i<nzA; i++) v_p[imark+i] = vworkA[i]; 191070f0671dSBarry Smith for (i=imark; i<nzB; i++) v_p[nzA+i] = vworkB[i]; 1911154123eaSLois Curfman McInnes } 1912154123eaSLois Curfman McInnes if (idx) { 191370f0671dSBarry Smith *idx = idx_p = mat->rowindices; 191470f0671dSBarry Smith if (imark > -1) { 191570f0671dSBarry Smith for (i=0; i<imark; i++) { 191670f0671dSBarry Smith idx_p[i] = cmap[cworkB[i]]; 191770f0671dSBarry Smith } 191870f0671dSBarry Smith } else { 1919154123eaSLois Curfman McInnes for (i=0; i<nzB; i++) { 192070f0671dSBarry Smith if (cmap[cworkB[i]] < cstart) idx_p[i] = cmap[cworkB[i]]; 1921154123eaSLois Curfman McInnes else break; 1922154123eaSLois Curfman McInnes } 1923154123eaSLois Curfman McInnes imark = i; 192470f0671dSBarry Smith } 192570f0671dSBarry Smith for (i=0; i<nzA; i++) idx_p[imark+i] = cstart + cworkA[i]; 192670f0671dSBarry Smith for (i=imark; i<nzB; i++) idx_p[nzA+i] = cmap[cworkB[i]]; 192739e00950SLois Curfman McInnes } 19283f97c4b0SBarry Smith } else { 19291ca473b0SSatish Balay if (idx) *idx = 0; 19301ca473b0SSatish Balay if (v) *v = 0; 19311ca473b0SSatish Balay } 1932154123eaSLois Curfman McInnes } 193339e00950SLois Curfman McInnes *nz = nztot; 1934f830108cSBarry Smith ierr = (*mat->A->ops->restorerow)(mat->A,lrow,&nzA,pcA,pvA);CHKERRQ(ierr); 1935f830108cSBarry Smith ierr = (*mat->B->ops->restorerow)(mat->B,lrow,&nzB,pcB,pvB);CHKERRQ(ierr); 19363a40ed3dSBarry Smith PetscFunctionReturn(0); 193739e00950SLois Curfman McInnes } 193839e00950SLois Curfman McInnes 19394a2ae208SSatish Balay #undef __FUNCT__ 19404a2ae208SSatish Balay #define __FUNCT__ "MatRestoreRow_MPIAIJ" 1941b1d57f15SBarry Smith PetscErrorCode MatRestoreRow_MPIAIJ(Mat mat,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 194239e00950SLois Curfman McInnes { 19437a0afa10SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 19443a40ed3dSBarry Smith 19453a40ed3dSBarry Smith PetscFunctionBegin; 1946e7e72b3dSBarry Smith if (!aij->getrowactive) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"MatGetRow() must be called first"); 19477a0afa10SBarry Smith aij->getrowactive = PETSC_FALSE; 19483a40ed3dSBarry Smith PetscFunctionReturn(0); 194939e00950SLois Curfman McInnes } 195039e00950SLois Curfman McInnes 19514a2ae208SSatish Balay #undef __FUNCT__ 19524a2ae208SSatish Balay #define __FUNCT__ "MatNorm_MPIAIJ" 1953dfbe8321SBarry Smith PetscErrorCode MatNorm_MPIAIJ(Mat mat,NormType type,PetscReal *norm) 1954855ac2c5SLois Curfman McInnes { 1955855ac2c5SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 1956ec8511deSBarry Smith Mat_SeqAIJ *amat = (Mat_SeqAIJ*)aij->A->data,*bmat = (Mat_SeqAIJ*)aij->B->data; 1957dfbe8321SBarry Smith PetscErrorCode ierr; 1958d0f46423SBarry Smith PetscInt i,j,cstart = mat->cmap->rstart; 1959329f5518SBarry Smith PetscReal sum = 0.0; 1960a77337e4SBarry Smith MatScalar *v; 196104ca555eSLois Curfman McInnes 19623a40ed3dSBarry Smith PetscFunctionBegin; 196317699dbbSLois Curfman McInnes if (aij->size == 1) { 196414183eadSLois Curfman McInnes ierr = MatNorm(aij->A,type,norm);CHKERRQ(ierr); 196537fa93a5SLois Curfman McInnes } else { 196604ca555eSLois Curfman McInnes if (type == NORM_FROBENIUS) { 196704ca555eSLois Curfman McInnes v = amat->a; 196804ca555eSLois Curfman McInnes for (i=0; i<amat->nz; i++) { 1969aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 1970329f5518SBarry Smith sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 197104ca555eSLois Curfman McInnes #else 197204ca555eSLois Curfman McInnes sum += (*v)*(*v); v++; 197304ca555eSLois Curfman McInnes #endif 197404ca555eSLois Curfman McInnes } 197504ca555eSLois Curfman McInnes v = bmat->a; 197604ca555eSLois Curfman McInnes for (i=0; i<bmat->nz; i++) { 1977aa482453SBarry Smith #if defined(PETSC_USE_COMPLEX) 1978329f5518SBarry Smith sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 197904ca555eSLois Curfman McInnes #else 198004ca555eSLois Curfman McInnes sum += (*v)*(*v); v++; 198104ca555eSLois Curfman McInnes #endif 198204ca555eSLois Curfman McInnes } 1983d9822059SBarry Smith ierr = MPI_Allreduce(&sum,norm,1,MPIU_REAL,MPIU_SUM,((PetscObject)mat)->comm);CHKERRQ(ierr); 19848f1a2a5eSBarry Smith *norm = PetscSqrtReal(*norm); 19853a40ed3dSBarry Smith } else if (type == NORM_1) { /* max column norm */ 1986329f5518SBarry Smith PetscReal *tmp,*tmp2; 1987b1d57f15SBarry Smith PetscInt *jj,*garray = aij->garray; 1988d0f46423SBarry Smith ierr = PetscMalloc((mat->cmap->N+1)*sizeof(PetscReal),&tmp);CHKERRQ(ierr); 1989d0f46423SBarry Smith ierr = PetscMalloc((mat->cmap->N+1)*sizeof(PetscReal),&tmp2);CHKERRQ(ierr); 1990d0f46423SBarry Smith ierr = PetscMemzero(tmp,mat->cmap->N*sizeof(PetscReal));CHKERRQ(ierr); 199104ca555eSLois Curfman McInnes *norm = 0.0; 199204ca555eSLois Curfman McInnes v = amat->a; jj = amat->j; 199304ca555eSLois Curfman McInnes for (j=0; j<amat->nz; j++) { 1994bfec09a0SHong Zhang tmp[cstart + *jj++ ] += PetscAbsScalar(*v); v++; 199504ca555eSLois Curfman McInnes } 199604ca555eSLois Curfman McInnes v = bmat->a; jj = bmat->j; 199704ca555eSLois Curfman McInnes for (j=0; j<bmat->nz; j++) { 1998bfec09a0SHong Zhang tmp[garray[*jj++]] += PetscAbsScalar(*v); v++; 199904ca555eSLois Curfman McInnes } 2000d9822059SBarry Smith ierr = MPI_Allreduce(tmp,tmp2,mat->cmap->N,MPIU_REAL,MPIU_SUM,((PetscObject)mat)->comm);CHKERRQ(ierr); 2001d0f46423SBarry Smith for (j=0; j<mat->cmap->N; j++) { 200204ca555eSLois Curfman McInnes if (tmp2[j] > *norm) *norm = tmp2[j]; 200304ca555eSLois Curfman McInnes } 2004606d414cSSatish Balay ierr = PetscFree(tmp);CHKERRQ(ierr); 2005606d414cSSatish Balay ierr = PetscFree(tmp2);CHKERRQ(ierr); 20063a40ed3dSBarry Smith } else if (type == NORM_INFINITY) { /* max row norm */ 2007329f5518SBarry Smith PetscReal ntemp = 0.0; 2008d0f46423SBarry Smith for (j=0; j<aij->A->rmap->n; j++) { 2009bfec09a0SHong Zhang v = amat->a + amat->i[j]; 201004ca555eSLois Curfman McInnes sum = 0.0; 201104ca555eSLois Curfman McInnes for (i=0; i<amat->i[j+1]-amat->i[j]; i++) { 2012cddf8d76SBarry Smith sum += PetscAbsScalar(*v); v++; 201304ca555eSLois Curfman McInnes } 2014bfec09a0SHong Zhang v = bmat->a + bmat->i[j]; 201504ca555eSLois Curfman McInnes for (i=0; i<bmat->i[j+1]-bmat->i[j]; i++) { 2016cddf8d76SBarry Smith sum += PetscAbsScalar(*v); v++; 201704ca555eSLois Curfman McInnes } 2018515d9167SLois Curfman McInnes if (sum > ntemp) ntemp = sum; 201904ca555eSLois Curfman McInnes } 2020d9822059SBarry Smith ierr = MPI_Allreduce(&ntemp,norm,1,MPIU_REAL,MPIU_MAX,((PetscObject)mat)->comm);CHKERRQ(ierr); 2021ca161407SBarry Smith } else { 2022e7e72b3dSBarry Smith SETERRQ(((PetscObject)mat)->comm,PETSC_ERR_SUP,"No support for two norm"); 202304ca555eSLois Curfman McInnes } 202437fa93a5SLois Curfman McInnes } 20253a40ed3dSBarry Smith PetscFunctionReturn(0); 2026855ac2c5SLois Curfman McInnes } 2027855ac2c5SLois Curfman McInnes 20284a2ae208SSatish Balay #undef __FUNCT__ 20294a2ae208SSatish Balay #define __FUNCT__ "MatTranspose_MPIAIJ" 2030fc4dec0aSBarry Smith PetscErrorCode MatTranspose_MPIAIJ(Mat A,MatReuse reuse,Mat *matout) 2031b7c46309SBarry Smith { 2032b7c46309SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2033da668accSHong Zhang Mat_SeqAIJ *Aloc=(Mat_SeqAIJ*)a->A->data,*Bloc=(Mat_SeqAIJ*)a->B->data; 2034dfbe8321SBarry Smith PetscErrorCode ierr; 2035d0f46423SBarry Smith PetscInt M = A->rmap->N,N = A->cmap->N,ma,na,mb,*ai,*aj,*bi,*bj,row,*cols,*cols_tmp,i,*d_nnz; 2036d0f46423SBarry Smith PetscInt cstart=A->cmap->rstart,ncol; 20373a40ed3dSBarry Smith Mat B; 2038a77337e4SBarry Smith MatScalar *array; 2039b7c46309SBarry Smith 20403a40ed3dSBarry Smith PetscFunctionBegin; 2041e7e72b3dSBarry Smith if (reuse == MAT_REUSE_MATRIX && A == *matout && M != N) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_ARG_SIZ,"Square matrix only for in-place"); 2042da668accSHong Zhang 2043d0f46423SBarry Smith ma = A->rmap->n; na = A->cmap->n; mb = a->B->rmap->n; 2044da668accSHong Zhang ai = Aloc->i; aj = Aloc->j; 2045da668accSHong Zhang bi = Bloc->i; bj = Bloc->j; 2046fc73b1b3SBarry Smith if (reuse == MAT_INITIAL_MATRIX || *matout == A) { 2047fc73b1b3SBarry Smith /* compute d_nnz for preallocation; o_nnz is approximated by d_nnz to avoid communication */ 2048fc73b1b3SBarry Smith ierr = PetscMalloc((1+na)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr); 2049da668accSHong Zhang ierr = PetscMemzero(d_nnz,(1+na)*sizeof(PetscInt));CHKERRQ(ierr); 2050da668accSHong Zhang for (i=0; i<ai[ma]; i++){ 2051da668accSHong Zhang d_nnz[aj[i]] ++; 2052da668accSHong Zhang aj[i] += cstart; /* global col index to be used by MatSetValues() */ 2053d4bb536fSBarry Smith } 2054d4bb536fSBarry Smith 20557adad957SLisandro Dalcin ierr = MatCreate(((PetscObject)A)->comm,&B);CHKERRQ(ierr); 2056d0f46423SBarry Smith ierr = MatSetSizes(B,A->cmap->n,A->rmap->n,N,M);CHKERRQ(ierr); 2057a2f3521dSMark F. Adams ierr = MatSetBlockSizes(B,A->cmap->bs,A->rmap->bs); CHKERRQ(ierr); 20587adad957SLisandro Dalcin ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); 2059da668accSHong Zhang ierr = MatMPIAIJSetPreallocation(B,0,d_nnz,0,d_nnz);CHKERRQ(ierr); 20601d567fd6SHong Zhang ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); 2061fc73b1b3SBarry Smith ierr = PetscFree(d_nnz);CHKERRQ(ierr); 2062fc4dec0aSBarry Smith } else { 2063fc4dec0aSBarry Smith B = *matout; 20646ffab4bbSHong Zhang ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 20656ffab4bbSHong Zhang for (i=0; i<ai[ma]; i++){ 20666ffab4bbSHong Zhang aj[i] += cstart; /* global col index to be used by MatSetValues() */ 20676ffab4bbSHong Zhang } 2068fc4dec0aSBarry Smith } 2069b7c46309SBarry Smith 2070b7c46309SBarry Smith /* copy over the A part */ 2071da668accSHong Zhang array = Aloc->a; 2072d0f46423SBarry Smith row = A->rmap->rstart; 2073da668accSHong Zhang for (i=0; i<ma; i++) { 2074da668accSHong Zhang ncol = ai[i+1]-ai[i]; 2075da668accSHong Zhang ierr = MatSetValues(B,ncol,aj,1,&row,array,INSERT_VALUES);CHKERRQ(ierr); 2076da668accSHong Zhang row++; array += ncol; aj += ncol; 2077b7c46309SBarry Smith } 2078b7c46309SBarry Smith aj = Aloc->j; 2079da668accSHong Zhang for (i=0; i<ai[ma]; i++) aj[i] -= cstart; /* resume local col index */ 2080b7c46309SBarry Smith 2081b7c46309SBarry Smith /* copy over the B part */ 2082fc73b1b3SBarry Smith ierr = PetscMalloc(bi[mb]*sizeof(PetscInt),&cols);CHKERRQ(ierr); 2083fc73b1b3SBarry Smith ierr = PetscMemzero(cols,bi[mb]*sizeof(PetscInt));CHKERRQ(ierr); 2084da668accSHong Zhang array = Bloc->a; 2085d0f46423SBarry Smith row = A->rmap->rstart; 2086da668accSHong Zhang for (i=0; i<bi[mb]; i++) {cols[i] = a->garray[bj[i]];} 208761a2fbbaSHong Zhang cols_tmp = cols; 2088da668accSHong Zhang for (i=0; i<mb; i++) { 2089da668accSHong Zhang ncol = bi[i+1]-bi[i]; 209061a2fbbaSHong Zhang ierr = MatSetValues(B,ncol,cols_tmp,1,&row,array,INSERT_VALUES);CHKERRQ(ierr); 209161a2fbbaSHong Zhang row++; array += ncol; cols_tmp += ncol; 2092b7c46309SBarry Smith } 2093fc73b1b3SBarry Smith ierr = PetscFree(cols);CHKERRQ(ierr); 2094fc73b1b3SBarry Smith 20956d4a8577SBarry Smith ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 20966d4a8577SBarry Smith ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2097815cbec1SBarry Smith if (reuse == MAT_INITIAL_MATRIX || *matout != A) { 20980de55854SLois Curfman McInnes *matout = B; 20990de55854SLois Curfman McInnes } else { 2100eb6b5d47SBarry Smith ierr = MatHeaderMerge(A,B);CHKERRQ(ierr); 21010de55854SLois Curfman McInnes } 21023a40ed3dSBarry Smith PetscFunctionReturn(0); 2103b7c46309SBarry Smith } 2104b7c46309SBarry Smith 21054a2ae208SSatish Balay #undef __FUNCT__ 21064a2ae208SSatish Balay #define __FUNCT__ "MatDiagonalScale_MPIAIJ" 2107dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_MPIAIJ(Mat mat,Vec ll,Vec rr) 2108a008b906SSatish Balay { 21094b967eb1SSatish Balay Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 21104b967eb1SSatish Balay Mat a = aij->A,b = aij->B; 2111dfbe8321SBarry Smith PetscErrorCode ierr; 2112b1d57f15SBarry Smith PetscInt s1,s2,s3; 2113a008b906SSatish Balay 21143a40ed3dSBarry Smith PetscFunctionBegin; 21154b967eb1SSatish Balay ierr = MatGetLocalSize(mat,&s2,&s3);CHKERRQ(ierr); 21164b967eb1SSatish Balay if (rr) { 2117e1311b90SBarry Smith ierr = VecGetLocalSize(rr,&s1);CHKERRQ(ierr); 2118e32f2f54SBarry Smith if (s1!=s3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"right vector non-conforming local size"); 21194b967eb1SSatish Balay /* Overlap communication with computation. */ 2120ca9f406cSSatish Balay ierr = VecScatterBegin(aij->Mvctx,rr,aij->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2121a008b906SSatish Balay } 21224b967eb1SSatish Balay if (ll) { 2123e1311b90SBarry Smith ierr = VecGetLocalSize(ll,&s1);CHKERRQ(ierr); 2124e32f2f54SBarry Smith if (s1!=s2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"left vector non-conforming local size"); 2125f830108cSBarry Smith ierr = (*b->ops->diagonalscale)(b,ll,0);CHKERRQ(ierr); 21264b967eb1SSatish Balay } 21274b967eb1SSatish Balay /* scale the diagonal block */ 2128f830108cSBarry Smith ierr = (*a->ops->diagonalscale)(a,ll,rr);CHKERRQ(ierr); 21294b967eb1SSatish Balay 21304b967eb1SSatish Balay if (rr) { 21314b967eb1SSatish Balay /* Do a scatter end and then right scale the off-diagonal block */ 2132ca9f406cSSatish Balay ierr = VecScatterEnd(aij->Mvctx,rr,aij->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2133f830108cSBarry Smith ierr = (*b->ops->diagonalscale)(b,0,aij->lvec);CHKERRQ(ierr); 21344b967eb1SSatish Balay } 21354b967eb1SSatish Balay 21363a40ed3dSBarry Smith PetscFunctionReturn(0); 2137a008b906SSatish Balay } 2138a008b906SSatish Balay 21394a2ae208SSatish Balay #undef __FUNCT__ 21404a2ae208SSatish Balay #define __FUNCT__ "MatSetUnfactored_MPIAIJ" 2141dfbe8321SBarry Smith PetscErrorCode MatSetUnfactored_MPIAIJ(Mat A) 2142bb5a7306SBarry Smith { 2143bb5a7306SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2144dfbe8321SBarry Smith PetscErrorCode ierr; 21453a40ed3dSBarry Smith 21463a40ed3dSBarry Smith PetscFunctionBegin; 2147bb5a7306SBarry Smith ierr = MatSetUnfactored(a->A);CHKERRQ(ierr); 21483a40ed3dSBarry Smith PetscFunctionReturn(0); 2149bb5a7306SBarry Smith } 2150bb5a7306SBarry Smith 21514a2ae208SSatish Balay #undef __FUNCT__ 21524a2ae208SSatish Balay #define __FUNCT__ "MatEqual_MPIAIJ" 2153ace3abfcSBarry Smith PetscErrorCode MatEqual_MPIAIJ(Mat A,Mat B,PetscBool *flag) 2154d4bb536fSBarry Smith { 2155d4bb536fSBarry Smith Mat_MPIAIJ *matB = (Mat_MPIAIJ*)B->data,*matA = (Mat_MPIAIJ*)A->data; 2156d4bb536fSBarry Smith Mat a,b,c,d; 2157ace3abfcSBarry Smith PetscBool flg; 2158dfbe8321SBarry Smith PetscErrorCode ierr; 2159d4bb536fSBarry Smith 21603a40ed3dSBarry Smith PetscFunctionBegin; 2161d4bb536fSBarry Smith a = matA->A; b = matA->B; 2162d4bb536fSBarry Smith c = matB->A; d = matB->B; 2163d4bb536fSBarry Smith 2164d4bb536fSBarry Smith ierr = MatEqual(a,c,&flg);CHKERRQ(ierr); 2165abc0a331SBarry Smith if (flg) { 2166d4bb536fSBarry Smith ierr = MatEqual(b,d,&flg);CHKERRQ(ierr); 2167d4bb536fSBarry Smith } 21687adad957SLisandro Dalcin ierr = MPI_Allreduce(&flg,flag,1,MPI_INT,MPI_LAND,((PetscObject)A)->comm);CHKERRQ(ierr); 21693a40ed3dSBarry Smith PetscFunctionReturn(0); 2170d4bb536fSBarry Smith } 2171d4bb536fSBarry Smith 21724a2ae208SSatish Balay #undef __FUNCT__ 21734a2ae208SSatish Balay #define __FUNCT__ "MatCopy_MPIAIJ" 2174dfbe8321SBarry Smith PetscErrorCode MatCopy_MPIAIJ(Mat A,Mat B,MatStructure str) 2175cb5b572fSBarry Smith { 2176dfbe8321SBarry Smith PetscErrorCode ierr; 2177cb5b572fSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data; 2178cb5b572fSBarry Smith Mat_MPIAIJ *b = (Mat_MPIAIJ *)B->data; 2179cb5b572fSBarry Smith 2180cb5b572fSBarry Smith PetscFunctionBegin; 218133f4a19fSKris Buschelman /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */ 218233f4a19fSKris Buschelman if ((str != SAME_NONZERO_PATTERN) || (A->ops->copy != B->ops->copy)) { 2183cb5b572fSBarry Smith /* because of the column compression in the off-processor part of the matrix a->B, 2184cb5b572fSBarry Smith the number of columns in a->B and b->B may be different, hence we cannot call 2185cb5b572fSBarry Smith the MatCopy() directly on the two parts. If need be, we can provide a more 2186cb5b572fSBarry Smith efficient copy than the MatCopy_Basic() by first uncompressing the a->B matrices 2187cb5b572fSBarry Smith then copying the submatrices */ 2188cb5b572fSBarry Smith ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr); 2189cb5b572fSBarry Smith } else { 2190cb5b572fSBarry Smith ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr); 2191cb5b572fSBarry Smith ierr = MatCopy(a->B,b->B,str);CHKERRQ(ierr); 2192cb5b572fSBarry Smith } 2193cb5b572fSBarry Smith PetscFunctionReturn(0); 2194cb5b572fSBarry Smith } 2195cb5b572fSBarry Smith 21964a2ae208SSatish Balay #undef __FUNCT__ 21974994cf47SJed Brown #define __FUNCT__ "MatSetUp_MPIAIJ" 21984994cf47SJed Brown PetscErrorCode MatSetUp_MPIAIJ(Mat A) 2199273d9f13SBarry Smith { 2200dfbe8321SBarry Smith PetscErrorCode ierr; 2201273d9f13SBarry Smith 2202273d9f13SBarry Smith PetscFunctionBegin; 2203273d9f13SBarry Smith ierr = MatMPIAIJSetPreallocation(A,PETSC_DEFAULT,0,PETSC_DEFAULT,0);CHKERRQ(ierr); 2204273d9f13SBarry Smith PetscFunctionReturn(0); 2205273d9f13SBarry Smith } 2206273d9f13SBarry Smith 2207ac90fabeSBarry Smith #undef __FUNCT__ 220895b7e79eSJed Brown #define __FUNCT__ "MatAXPYGetPreallocation_MPIAIJ" 220995b7e79eSJed Brown /* This is the same as MatAXPYGetPreallocation_SeqAIJ, except that the local-to-global map is provided */ 221095b7e79eSJed Brown static PetscErrorCode MatAXPYGetPreallocation_MPIAIJ(Mat Y,const PetscInt *yltog,Mat X,const PetscInt *xltog,PetscInt* nnz) 221195b7e79eSJed Brown { 221295b7e79eSJed Brown PetscInt i,m=Y->rmap->N; 221395b7e79eSJed Brown Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data; 221495b7e79eSJed Brown Mat_SeqAIJ *y = (Mat_SeqAIJ*)Y->data; 221595b7e79eSJed Brown const PetscInt *xi = x->i,*yi = y->i; 221695b7e79eSJed Brown 221795b7e79eSJed Brown PetscFunctionBegin; 221895b7e79eSJed Brown /* Set the number of nonzeros in the new matrix */ 221995b7e79eSJed Brown for(i=0; i<m; i++) { 222095b7e79eSJed Brown PetscInt j,k,nzx = xi[i+1] - xi[i],nzy = yi[i+1] - yi[i]; 222195b7e79eSJed Brown const PetscInt *xj = x->j+xi[i],*yj = y->j+yi[i]; 222295b7e79eSJed Brown nnz[i] = 0; 222395b7e79eSJed Brown for (j=0,k=0; j<nzx; j++) { /* Point in X */ 222495b7e79eSJed Brown for (; k<nzy && yltog[yj[k]]<xltog[xj[j]]; k++) nnz[i]++; /* Catch up to X */ 222595b7e79eSJed Brown if (k<nzy && yltog[yj[k]]==xltog[xj[j]]) k++; /* Skip duplicate */ 222695b7e79eSJed Brown nnz[i]++; 222795b7e79eSJed Brown } 222895b7e79eSJed Brown for (; k<nzy; k++) nnz[i]++; 222995b7e79eSJed Brown } 223095b7e79eSJed Brown PetscFunctionReturn(0); 223195b7e79eSJed Brown } 223295b7e79eSJed Brown 223395b7e79eSJed Brown #undef __FUNCT__ 2234ac90fabeSBarry Smith #define __FUNCT__ "MatAXPY_MPIAIJ" 2235f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_MPIAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str) 2236ac90fabeSBarry Smith { 2237dfbe8321SBarry Smith PetscErrorCode ierr; 2238b1d57f15SBarry Smith PetscInt i; 2239ac90fabeSBarry Smith Mat_MPIAIJ *xx = (Mat_MPIAIJ *)X->data,*yy = (Mat_MPIAIJ *)Y->data; 22404ce68768SBarry Smith PetscBLASInt bnz,one=1; 2241ac90fabeSBarry Smith Mat_SeqAIJ *x,*y; 2242ac90fabeSBarry Smith 2243ac90fabeSBarry Smith PetscFunctionBegin; 2244ac90fabeSBarry Smith if (str == SAME_NONZERO_PATTERN) { 2245f4df32b1SMatthew Knepley PetscScalar alpha = a; 2246ac90fabeSBarry Smith x = (Mat_SeqAIJ *)xx->A->data; 2247ac90fabeSBarry Smith y = (Mat_SeqAIJ *)yy->A->data; 22480805154bSBarry Smith bnz = PetscBLASIntCast(x->nz); 2249f4df32b1SMatthew Knepley BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one); 2250ac90fabeSBarry Smith x = (Mat_SeqAIJ *)xx->B->data; 2251ac90fabeSBarry Smith y = (Mat_SeqAIJ *)yy->B->data; 22520805154bSBarry Smith bnz = PetscBLASIntCast(x->nz); 2253f4df32b1SMatthew Knepley BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one); 2254a30b2313SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { 2255f4df32b1SMatthew Knepley ierr = MatAXPY_SeqAIJ(yy->A,a,xx->A,str);CHKERRQ(ierr); 2256c537a176SHong Zhang 2257c537a176SHong Zhang x = (Mat_SeqAIJ *)xx->B->data; 2258a30b2313SHong Zhang y = (Mat_SeqAIJ *)yy->B->data; 2259a30b2313SHong Zhang if (y->xtoy && y->XtoY != xx->B) { 2260a30b2313SHong Zhang ierr = PetscFree(y->xtoy);CHKERRQ(ierr); 22616bf464f9SBarry Smith ierr = MatDestroy(&y->XtoY);CHKERRQ(ierr); 2262c537a176SHong Zhang } 2263a30b2313SHong Zhang if (!y->xtoy) { /* get xtoy */ 2264d0f46423SBarry Smith ierr = MatAXPYGetxtoy_Private(xx->B->rmap->n,x->i,x->j,xx->garray,y->i,y->j,yy->garray,&y->xtoy);CHKERRQ(ierr); 2265a30b2313SHong Zhang y->XtoY = xx->B; 2266407f6b05SHong Zhang ierr = PetscObjectReference((PetscObject)xx->B);CHKERRQ(ierr); 2267c537a176SHong Zhang } 2268f4df32b1SMatthew Knepley for (i=0; i<x->nz; i++) y->a[y->xtoy[i]] += a*(x->a[i]); 2269ac90fabeSBarry Smith } else { 22709f5f6813SShri Abhyankar Mat B; 22719f5f6813SShri Abhyankar PetscInt *nnz_d,*nnz_o; 22729f5f6813SShri Abhyankar ierr = PetscMalloc(yy->A->rmap->N*sizeof(PetscInt),&nnz_d);CHKERRQ(ierr); 22739f5f6813SShri Abhyankar ierr = PetscMalloc(yy->B->rmap->N*sizeof(PetscInt),&nnz_o);CHKERRQ(ierr); 22749f5f6813SShri Abhyankar ierr = MatCreate(((PetscObject)Y)->comm,&B);CHKERRQ(ierr); 2275bc5a2726SShri Abhyankar ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr); 22769f5f6813SShri Abhyankar ierr = MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);CHKERRQ(ierr); 2277a2f3521dSMark F. Adams ierr = MatSetBlockSizes(B,Y->rmap->bs,Y->cmap->bs);CHKERRQ(ierr); 22789f5f6813SShri Abhyankar ierr = MatSetType(B,MATMPIAIJ);CHKERRQ(ierr); 22799f5f6813SShri Abhyankar ierr = MatAXPYGetPreallocation_SeqAIJ(yy->A,xx->A,nnz_d);CHKERRQ(ierr); 228095b7e79eSJed Brown ierr = MatAXPYGetPreallocation_MPIAIJ(yy->B,yy->garray,xx->B,xx->garray,nnz_o);CHKERRQ(ierr); 2281ecd8bba6SJed Brown ierr = MatMPIAIJSetPreallocation(B,0,nnz_d,0,nnz_o);CHKERRQ(ierr); 22829f5f6813SShri Abhyankar ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr); 22839f5f6813SShri Abhyankar ierr = MatHeaderReplace(Y,B); 22849f5f6813SShri Abhyankar ierr = PetscFree(nnz_d);CHKERRQ(ierr); 22859f5f6813SShri Abhyankar ierr = PetscFree(nnz_o);CHKERRQ(ierr); 2286ac90fabeSBarry Smith } 2287ac90fabeSBarry Smith PetscFunctionReturn(0); 2288ac90fabeSBarry Smith } 2289ac90fabeSBarry Smith 22907087cfbeSBarry Smith extern PetscErrorCode MatConjugate_SeqAIJ(Mat); 2291354c94deSBarry Smith 2292354c94deSBarry Smith #undef __FUNCT__ 2293354c94deSBarry Smith #define __FUNCT__ "MatConjugate_MPIAIJ" 22947087cfbeSBarry Smith PetscErrorCode MatConjugate_MPIAIJ(Mat mat) 2295354c94deSBarry Smith { 2296354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX) 2297354c94deSBarry Smith PetscErrorCode ierr; 2298354c94deSBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ *)mat->data; 2299354c94deSBarry Smith 2300354c94deSBarry Smith PetscFunctionBegin; 2301354c94deSBarry Smith ierr = MatConjugate_SeqAIJ(aij->A);CHKERRQ(ierr); 2302354c94deSBarry Smith ierr = MatConjugate_SeqAIJ(aij->B);CHKERRQ(ierr); 2303354c94deSBarry Smith #else 2304354c94deSBarry Smith PetscFunctionBegin; 2305354c94deSBarry Smith #endif 2306354c94deSBarry Smith PetscFunctionReturn(0); 2307354c94deSBarry Smith } 2308354c94deSBarry Smith 230999cafbc1SBarry Smith #undef __FUNCT__ 231099cafbc1SBarry Smith #define __FUNCT__ "MatRealPart_MPIAIJ" 231199cafbc1SBarry Smith PetscErrorCode MatRealPart_MPIAIJ(Mat A) 231299cafbc1SBarry Smith { 231399cafbc1SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 231499cafbc1SBarry Smith PetscErrorCode ierr; 231599cafbc1SBarry Smith 231699cafbc1SBarry Smith PetscFunctionBegin; 231799cafbc1SBarry Smith ierr = MatRealPart(a->A);CHKERRQ(ierr); 231899cafbc1SBarry Smith ierr = MatRealPart(a->B);CHKERRQ(ierr); 231999cafbc1SBarry Smith PetscFunctionReturn(0); 232099cafbc1SBarry Smith } 232199cafbc1SBarry Smith 232299cafbc1SBarry Smith #undef __FUNCT__ 232399cafbc1SBarry Smith #define __FUNCT__ "MatImaginaryPart_MPIAIJ" 232499cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_MPIAIJ(Mat A) 232599cafbc1SBarry Smith { 232699cafbc1SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 232799cafbc1SBarry Smith PetscErrorCode ierr; 232899cafbc1SBarry Smith 232999cafbc1SBarry Smith PetscFunctionBegin; 233099cafbc1SBarry Smith ierr = MatImaginaryPart(a->A);CHKERRQ(ierr); 233199cafbc1SBarry Smith ierr = MatImaginaryPart(a->B);CHKERRQ(ierr); 233299cafbc1SBarry Smith PetscFunctionReturn(0); 233399cafbc1SBarry Smith } 233499cafbc1SBarry Smith 2335103bf8bdSMatthew Knepley #ifdef PETSC_HAVE_PBGL 2336103bf8bdSMatthew Knepley 2337103bf8bdSMatthew Knepley #include <boost/parallel/mpi/bsp_process_group.hpp> 2338a2c909beSMatthew Knepley #include <boost/graph/distributed/ilu_default_graph.hpp> 2339a2c909beSMatthew Knepley #include <boost/graph/distributed/ilu_0_block.hpp> 2340a2c909beSMatthew Knepley #include <boost/graph/distributed/ilu_preconditioner.hpp> 2341103bf8bdSMatthew Knepley #include <boost/graph/distributed/petsc/interface.hpp> 2342a2c909beSMatthew Knepley #include <boost/multi_array.hpp> 2343d0f46423SBarry Smith #include <boost/parallel/distributed_property_map->hpp> 2344103bf8bdSMatthew Knepley 2345103bf8bdSMatthew Knepley #undef __FUNCT__ 2346103bf8bdSMatthew Knepley #define __FUNCT__ "MatILUFactorSymbolic_MPIAIJ" 2347103bf8bdSMatthew Knepley /* 2348103bf8bdSMatthew Knepley This uses the parallel ILU factorization of Peter Gottschling <pgottsch@osl.iu.edu> 2349103bf8bdSMatthew Knepley */ 23500481f469SBarry Smith PetscErrorCode MatILUFactorSymbolic_MPIAIJ(Mat fact,Mat A, IS isrow, IS iscol, const MatFactorInfo *info) 2351103bf8bdSMatthew Knepley { 2352a2c909beSMatthew Knepley namespace petsc = boost::distributed::petsc; 2353a2c909beSMatthew Knepley 2354a2c909beSMatthew Knepley namespace graph_dist = boost::graph::distributed; 2355a2c909beSMatthew Knepley using boost::graph::distributed::ilu_default::process_group_type; 2356a2c909beSMatthew Knepley using boost::graph::ilu_permuted; 2357a2c909beSMatthew Knepley 2358ace3abfcSBarry Smith PetscBool row_identity, col_identity; 2359776b82aeSLisandro Dalcin PetscContainer c; 2360103bf8bdSMatthew Knepley PetscInt m, n, M, N; 2361103bf8bdSMatthew Knepley PetscErrorCode ierr; 2362103bf8bdSMatthew Knepley 2363103bf8bdSMatthew Knepley PetscFunctionBegin; 2364e32f2f54SBarry Smith if (info->levels != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only levels = 0 supported for parallel ilu"); 2365103bf8bdSMatthew Knepley ierr = ISIdentity(isrow, &row_identity);CHKERRQ(ierr); 2366103bf8bdSMatthew Knepley ierr = ISIdentity(iscol, &col_identity);CHKERRQ(ierr); 2367103bf8bdSMatthew Knepley if (!row_identity || !col_identity) { 2368e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Row and column permutations must be identity for parallel ILU"); 2369103bf8bdSMatthew Knepley } 2370103bf8bdSMatthew Knepley 2371103bf8bdSMatthew Knepley process_group_type pg; 2372a2c909beSMatthew Knepley typedef graph_dist::ilu_default::ilu_level_graph_type lgraph_type; 2373a2c909beSMatthew Knepley lgraph_type* lgraph_p = new lgraph_type(petsc::num_global_vertices(A), pg, petsc::matrix_distribution(A, pg)); 2374a2c909beSMatthew Knepley lgraph_type& level_graph = *lgraph_p; 2375a2c909beSMatthew Knepley graph_dist::ilu_default::graph_type& graph(level_graph.graph); 2376a2c909beSMatthew Knepley 2377103bf8bdSMatthew Knepley petsc::read_matrix(A, graph, get(boost::edge_weight, graph)); 2378a2c909beSMatthew Knepley ilu_permuted(level_graph); 2379103bf8bdSMatthew Knepley 2380103bf8bdSMatthew Knepley /* put together the new matrix */ 23817adad957SLisandro Dalcin ierr = MatCreate(((PetscObject)A)->comm, fact);CHKERRQ(ierr); 2382103bf8bdSMatthew Knepley ierr = MatGetLocalSize(A, &m, &n);CHKERRQ(ierr); 2383103bf8bdSMatthew Knepley ierr = MatGetSize(A, &M, &N);CHKERRQ(ierr); 2384719d5645SBarry Smith ierr = MatSetSizes(fact, m, n, M, N);CHKERRQ(ierr); 2385a2f3521dSMark F. Adams ierr = MatSetBlockSizes(fact,A->rmap->bs,A->cmap->bs); CHKERRQ(ierr); 2386719d5645SBarry Smith ierr = MatSetType(fact, ((PetscObject)A)->type_name);CHKERRQ(ierr); 2387719d5645SBarry Smith ierr = MatAssemblyBegin(fact, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2388719d5645SBarry Smith ierr = MatAssemblyEnd(fact, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2389103bf8bdSMatthew Knepley 23907adad957SLisandro Dalcin ierr = PetscContainerCreate(((PetscObject)A)->comm, &c); 2391776b82aeSLisandro Dalcin ierr = PetscContainerSetPointer(c, lgraph_p); 2392719d5645SBarry Smith ierr = PetscObjectCompose((PetscObject) (fact), "graph", (PetscObject) c); 2393bf0cc555SLisandro Dalcin ierr = PetscContainerDestroy(&c); 2394103bf8bdSMatthew Knepley PetscFunctionReturn(0); 2395103bf8bdSMatthew Knepley } 2396103bf8bdSMatthew Knepley 2397103bf8bdSMatthew Knepley #undef __FUNCT__ 2398103bf8bdSMatthew Knepley #define __FUNCT__ "MatLUFactorNumeric_MPIAIJ" 23990481f469SBarry Smith PetscErrorCode MatLUFactorNumeric_MPIAIJ(Mat B,Mat A, const MatFactorInfo *info) 2400103bf8bdSMatthew Knepley { 2401103bf8bdSMatthew Knepley PetscFunctionBegin; 2402103bf8bdSMatthew Knepley PetscFunctionReturn(0); 2403103bf8bdSMatthew Knepley } 2404103bf8bdSMatthew Knepley 2405103bf8bdSMatthew Knepley #undef __FUNCT__ 2406103bf8bdSMatthew Knepley #define __FUNCT__ "MatSolve_MPIAIJ" 2407103bf8bdSMatthew Knepley /* 2408103bf8bdSMatthew Knepley This uses the parallel ILU factorization of Peter Gottschling <pgottsch@osl.iu.edu> 2409103bf8bdSMatthew Knepley */ 2410103bf8bdSMatthew Knepley PetscErrorCode MatSolve_MPIAIJ(Mat A, Vec b, Vec x) 2411103bf8bdSMatthew Knepley { 2412a2c909beSMatthew Knepley namespace graph_dist = boost::graph::distributed; 2413a2c909beSMatthew Knepley 2414a2c909beSMatthew Knepley typedef graph_dist::ilu_default::ilu_level_graph_type lgraph_type; 2415a2c909beSMatthew Knepley lgraph_type* lgraph_p; 2416776b82aeSLisandro Dalcin PetscContainer c; 2417103bf8bdSMatthew Knepley PetscErrorCode ierr; 2418103bf8bdSMatthew Knepley 2419103bf8bdSMatthew Knepley PetscFunctionBegin; 2420103bf8bdSMatthew Knepley ierr = PetscObjectQuery((PetscObject) A, "graph", (PetscObject *) &c);CHKERRQ(ierr); 2421776b82aeSLisandro Dalcin ierr = PetscContainerGetPointer(c, (void **) &lgraph_p);CHKERRQ(ierr); 2422103bf8bdSMatthew Knepley ierr = VecCopy(b, x);CHKERRQ(ierr); 2423a2c909beSMatthew Knepley 2424a2c909beSMatthew Knepley PetscScalar* array_x; 2425a2c909beSMatthew Knepley ierr = VecGetArray(x, &array_x);CHKERRQ(ierr); 2426a2c909beSMatthew Knepley PetscInt sx; 2427a2c909beSMatthew Knepley ierr = VecGetSize(x, &sx);CHKERRQ(ierr); 2428a2c909beSMatthew Knepley 2429a2c909beSMatthew Knepley PetscScalar* array_b; 2430a2c909beSMatthew Knepley ierr = VecGetArray(b, &array_b);CHKERRQ(ierr); 2431a2c909beSMatthew Knepley PetscInt sb; 2432a2c909beSMatthew Knepley ierr = VecGetSize(b, &sb);CHKERRQ(ierr); 2433a2c909beSMatthew Knepley 2434a2c909beSMatthew Knepley lgraph_type& level_graph = *lgraph_p; 2435a2c909beSMatthew Knepley graph_dist::ilu_default::graph_type& graph(level_graph.graph); 2436a2c909beSMatthew Knepley 2437a2c909beSMatthew Knepley typedef boost::multi_array_ref<PetscScalar, 1> array_ref_type; 2438a2c909beSMatthew Knepley array_ref_type ref_b(array_b, boost::extents[num_vertices(graph)]), 2439a2c909beSMatthew Knepley ref_x(array_x, boost::extents[num_vertices(graph)]); 2440a2c909beSMatthew Knepley 2441a2c909beSMatthew Knepley typedef boost::iterator_property_map<array_ref_type::iterator, 2442a2c909beSMatthew Knepley boost::property_map<graph_dist::ilu_default::graph_type, boost::vertex_index_t>::type> gvector_type; 2443a2c909beSMatthew Knepley gvector_type vector_b(ref_b.begin(), get(boost::vertex_index, graph)), 2444a2c909beSMatthew Knepley vector_x(ref_x.begin(), get(boost::vertex_index, graph)); 2445a2c909beSMatthew Knepley 2446a2c909beSMatthew Knepley ilu_set_solve(*lgraph_p, vector_b, vector_x); 2447a2c909beSMatthew Knepley 2448103bf8bdSMatthew Knepley PetscFunctionReturn(0); 2449103bf8bdSMatthew Knepley } 2450103bf8bdSMatthew Knepley #endif 2451103bf8bdSMatthew Knepley 245269db28dcSHong Zhang typedef struct { /* used by MatGetRedundantMatrix() for reusing matredundant */ 245369db28dcSHong Zhang PetscInt nzlocal,nsends,nrecvs; 24541d79065fSBarry Smith PetscMPIInt *send_rank,*recv_rank; 24551d79065fSBarry Smith PetscInt *sbuf_nz,*rbuf_nz,*sbuf_j,**rbuf_j; 245669db28dcSHong Zhang PetscScalar *sbuf_a,**rbuf_a; 2457bf0cc555SLisandro Dalcin PetscErrorCode (*Destroy)(Mat); 245869db28dcSHong Zhang } Mat_Redundant; 245969db28dcSHong Zhang 246069db28dcSHong Zhang #undef __FUNCT__ 246169db28dcSHong Zhang #define __FUNCT__ "PetscContainerDestroy_MatRedundant" 246269db28dcSHong Zhang PetscErrorCode PetscContainerDestroy_MatRedundant(void *ptr) 246369db28dcSHong Zhang { 246469db28dcSHong Zhang PetscErrorCode ierr; 246569db28dcSHong Zhang Mat_Redundant *redund=(Mat_Redundant*)ptr; 246669db28dcSHong Zhang PetscInt i; 246769db28dcSHong Zhang 246869db28dcSHong Zhang PetscFunctionBegin; 24691d79065fSBarry Smith ierr = PetscFree2(redund->send_rank,redund->recv_rank);CHKERRQ(ierr); 247069db28dcSHong Zhang ierr = PetscFree(redund->sbuf_j);CHKERRQ(ierr); 247169db28dcSHong Zhang ierr = PetscFree(redund->sbuf_a);CHKERRQ(ierr); 247269db28dcSHong Zhang for (i=0; i<redund->nrecvs; i++){ 247369db28dcSHong Zhang ierr = PetscFree(redund->rbuf_j[i]);CHKERRQ(ierr); 247469db28dcSHong Zhang ierr = PetscFree(redund->rbuf_a[i]);CHKERRQ(ierr); 247569db28dcSHong Zhang } 24761d79065fSBarry Smith ierr = PetscFree4(redund->sbuf_nz,redund->rbuf_nz,redund->rbuf_j,redund->rbuf_a);CHKERRQ(ierr); 247769db28dcSHong Zhang ierr = PetscFree(redund);CHKERRQ(ierr); 247869db28dcSHong Zhang PetscFunctionReturn(0); 247969db28dcSHong Zhang } 248069db28dcSHong Zhang 248169db28dcSHong Zhang #undef __FUNCT__ 248269db28dcSHong Zhang #define __FUNCT__ "MatDestroy_MatRedundant" 248369db28dcSHong Zhang PetscErrorCode MatDestroy_MatRedundant(Mat A) 248469db28dcSHong Zhang { 248569db28dcSHong Zhang PetscErrorCode ierr; 248669db28dcSHong Zhang PetscContainer container; 248769db28dcSHong Zhang Mat_Redundant *redund=PETSC_NULL; 248869db28dcSHong Zhang 248969db28dcSHong Zhang PetscFunctionBegin; 249069db28dcSHong Zhang ierr = PetscObjectQuery((PetscObject)A,"Mat_Redundant",(PetscObject *)&container);CHKERRQ(ierr); 2491bf0cc555SLisandro Dalcin if (!container) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Container does not exit"); 249269db28dcSHong Zhang ierr = PetscContainerGetPointer(container,(void **)&redund);CHKERRQ(ierr); 2493bf0cc555SLisandro Dalcin A->ops->destroy = redund->Destroy; 249469db28dcSHong Zhang ierr = PetscObjectCompose((PetscObject)A,"Mat_Redundant",0);CHKERRQ(ierr); 2495bf0cc555SLisandro Dalcin if (A->ops->destroy) { 249669db28dcSHong Zhang ierr = (*A->ops->destroy)(A);CHKERRQ(ierr); 2497bf0cc555SLisandro Dalcin } 249869db28dcSHong Zhang PetscFunctionReturn(0); 249969db28dcSHong Zhang } 250069db28dcSHong Zhang 250169db28dcSHong Zhang #undef __FUNCT__ 250269db28dcSHong Zhang #define __FUNCT__ "MatGetRedundantMatrix_MPIAIJ" 250369db28dcSHong Zhang PetscErrorCode MatGetRedundantMatrix_MPIAIJ(Mat mat,PetscInt nsubcomm,MPI_Comm subcomm,PetscInt mlocal_sub,MatReuse reuse,Mat *matredundant) 250469db28dcSHong Zhang { 250569db28dcSHong Zhang PetscMPIInt rank,size; 25067adad957SLisandro Dalcin MPI_Comm comm=((PetscObject)mat)->comm; 250769db28dcSHong Zhang PetscErrorCode ierr; 250869db28dcSHong Zhang PetscInt nsends=0,nrecvs=0,i,rownz_max=0; 250969db28dcSHong Zhang PetscMPIInt *send_rank=PETSC_NULL,*recv_rank=PETSC_NULL; 2510d0f46423SBarry Smith PetscInt *rowrange=mat->rmap->range; 251169db28dcSHong Zhang Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 251269db28dcSHong Zhang Mat A=aij->A,B=aij->B,C=*matredundant; 251369db28dcSHong Zhang Mat_SeqAIJ *a=(Mat_SeqAIJ*)A->data,*b=(Mat_SeqAIJ*)B->data; 251469db28dcSHong Zhang PetscScalar *sbuf_a; 251569db28dcSHong Zhang PetscInt nzlocal=a->nz+b->nz; 2516d0f46423SBarry Smith PetscInt j,cstart=mat->cmap->rstart,cend=mat->cmap->rend,row,nzA,nzB,ncols,*cworkA,*cworkB; 2517d0f46423SBarry Smith PetscInt rstart=mat->rmap->rstart,rend=mat->rmap->rend,*bmap=aij->garray,M,N; 251869db28dcSHong Zhang PetscInt *cols,ctmp,lwrite,*rptr,l,*sbuf_j; 2519a77337e4SBarry Smith MatScalar *aworkA,*aworkB; 2520a77337e4SBarry Smith PetscScalar *vals; 252169db28dcSHong Zhang PetscMPIInt tag1,tag2,tag3,imdex; 252269db28dcSHong Zhang MPI_Request *s_waits1=PETSC_NULL,*s_waits2=PETSC_NULL,*s_waits3=PETSC_NULL, 252369db28dcSHong Zhang *r_waits1=PETSC_NULL,*r_waits2=PETSC_NULL,*r_waits3=PETSC_NULL; 252469db28dcSHong Zhang MPI_Status recv_status,*send_status; 252569db28dcSHong Zhang PetscInt *sbuf_nz=PETSC_NULL,*rbuf_nz=PETSC_NULL,count; 252669db28dcSHong Zhang PetscInt **rbuf_j=PETSC_NULL; 252769db28dcSHong Zhang PetscScalar **rbuf_a=PETSC_NULL; 252869db28dcSHong Zhang Mat_Redundant *redund=PETSC_NULL; 252969db28dcSHong Zhang PetscContainer container; 253069db28dcSHong Zhang 253169db28dcSHong Zhang PetscFunctionBegin; 253269db28dcSHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 253369db28dcSHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 253469db28dcSHong Zhang 253569db28dcSHong Zhang if (reuse == MAT_REUSE_MATRIX) { 253669db28dcSHong Zhang ierr = MatGetSize(C,&M,&N);CHKERRQ(ierr); 2537e32f2f54SBarry Smith if (M != N || M != mat->rmap->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. Wrong global size"); 253869db28dcSHong Zhang ierr = MatGetLocalSize(C,&M,&N);CHKERRQ(ierr); 2539e32f2f54SBarry Smith if (M != N || M != mlocal_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. Wrong local size"); 254069db28dcSHong Zhang ierr = PetscObjectQuery((PetscObject)C,"Mat_Redundant",(PetscObject *)&container);CHKERRQ(ierr); 2541bf0cc555SLisandro Dalcin if (!container) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Container does not exit"); 254269db28dcSHong Zhang ierr = PetscContainerGetPointer(container,(void **)&redund);CHKERRQ(ierr); 2543e32f2f54SBarry Smith if (nzlocal != redund->nzlocal) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Cannot reuse matrix. Wrong nzlocal"); 254469db28dcSHong Zhang 254569db28dcSHong Zhang nsends = redund->nsends; 254669db28dcSHong Zhang nrecvs = redund->nrecvs; 25471d79065fSBarry Smith send_rank = redund->send_rank; 25481d79065fSBarry Smith recv_rank = redund->recv_rank; 25491d79065fSBarry Smith sbuf_nz = redund->sbuf_nz; 25501d79065fSBarry Smith rbuf_nz = redund->rbuf_nz; 255169db28dcSHong Zhang sbuf_j = redund->sbuf_j; 255269db28dcSHong Zhang sbuf_a = redund->sbuf_a; 255369db28dcSHong Zhang rbuf_j = redund->rbuf_j; 255469db28dcSHong Zhang rbuf_a = redund->rbuf_a; 255569db28dcSHong Zhang } 255669db28dcSHong Zhang 255769db28dcSHong Zhang if (reuse == MAT_INITIAL_MATRIX){ 255869db28dcSHong Zhang PetscMPIInt subrank,subsize; 255969db28dcSHong Zhang PetscInt nleftover,np_subcomm; 256069db28dcSHong Zhang /* get the destination processors' id send_rank, nsends and nrecvs */ 256169db28dcSHong Zhang ierr = MPI_Comm_rank(subcomm,&subrank);CHKERRQ(ierr); 256269db28dcSHong Zhang ierr = MPI_Comm_size(subcomm,&subsize);CHKERRQ(ierr); 25631d79065fSBarry Smith ierr = PetscMalloc2(size,PetscMPIInt,&send_rank,size,PetscMPIInt,&recv_rank); 256469db28dcSHong Zhang np_subcomm = size/nsubcomm; 256569db28dcSHong Zhang nleftover = size - nsubcomm*np_subcomm; 256669db28dcSHong Zhang nsends = 0; nrecvs = 0; 256769db28dcSHong Zhang for (i=0; i<size; i++){ /* i=rank*/ 256869db28dcSHong Zhang if (subrank == i/nsubcomm && rank != i){ /* my_subrank == other's subrank */ 256969db28dcSHong Zhang send_rank[nsends] = i; nsends++; 257069db28dcSHong Zhang recv_rank[nrecvs++] = i; 257169db28dcSHong Zhang } 257269db28dcSHong Zhang } 257369db28dcSHong Zhang if (rank >= size - nleftover){/* this proc is a leftover processor */ 257469db28dcSHong Zhang i = size-nleftover-1; 257569db28dcSHong Zhang j = 0; 257669db28dcSHong Zhang while (j < nsubcomm - nleftover){ 257769db28dcSHong Zhang send_rank[nsends++] = i; 257869db28dcSHong Zhang i--; j++; 257969db28dcSHong Zhang } 258069db28dcSHong Zhang } 258169db28dcSHong Zhang 258269db28dcSHong Zhang if (nleftover && subsize == size/nsubcomm && subrank==subsize-1){ /* this proc recvs from leftover processors */ 258369db28dcSHong Zhang for (i=0; i<nleftover; i++){ 258469db28dcSHong Zhang recv_rank[nrecvs++] = size-nleftover+i; 258569db28dcSHong Zhang } 258669db28dcSHong Zhang } 258769db28dcSHong Zhang 258869db28dcSHong Zhang /* allocate sbuf_j, sbuf_a */ 258969db28dcSHong Zhang i = nzlocal + rowrange[rank+1] - rowrange[rank] + 2; 259069db28dcSHong Zhang ierr = PetscMalloc(i*sizeof(PetscInt),&sbuf_j);CHKERRQ(ierr); 259169db28dcSHong Zhang ierr = PetscMalloc((nzlocal+1)*sizeof(PetscScalar),&sbuf_a);CHKERRQ(ierr); 259269db28dcSHong Zhang } /* endof if (reuse == MAT_INITIAL_MATRIX) */ 259369db28dcSHong Zhang 259469db28dcSHong Zhang /* copy mat's local entries into the buffers */ 259569db28dcSHong Zhang if (reuse == MAT_INITIAL_MATRIX){ 259669db28dcSHong Zhang rownz_max = 0; 259769db28dcSHong Zhang rptr = sbuf_j; 259869db28dcSHong Zhang cols = sbuf_j + rend-rstart + 1; 259969db28dcSHong Zhang vals = sbuf_a; 260069db28dcSHong Zhang rptr[0] = 0; 260169db28dcSHong Zhang for (i=0; i<rend-rstart; i++){ 260269db28dcSHong Zhang row = i + rstart; 260369db28dcSHong Zhang nzA = a->i[i+1] - a->i[i]; nzB = b->i[i+1] - b->i[i]; 260469db28dcSHong Zhang ncols = nzA + nzB; 260569db28dcSHong Zhang cworkA = a->j + a->i[i]; cworkB = b->j + b->i[i]; 260669db28dcSHong Zhang aworkA = a->a + a->i[i]; aworkB = b->a + b->i[i]; 260769db28dcSHong Zhang /* load the column indices for this row into cols */ 260869db28dcSHong Zhang lwrite = 0; 260969db28dcSHong Zhang for (l=0; l<nzB; l++) { 261069db28dcSHong Zhang if ((ctmp = bmap[cworkB[l]]) < cstart){ 261169db28dcSHong Zhang vals[lwrite] = aworkB[l]; 261269db28dcSHong Zhang cols[lwrite++] = ctmp; 261369db28dcSHong Zhang } 261469db28dcSHong Zhang } 261569db28dcSHong Zhang for (l=0; l<nzA; l++){ 261669db28dcSHong Zhang vals[lwrite] = aworkA[l]; 261769db28dcSHong Zhang cols[lwrite++] = cstart + cworkA[l]; 261869db28dcSHong Zhang } 261969db28dcSHong Zhang for (l=0; l<nzB; l++) { 262069db28dcSHong Zhang if ((ctmp = bmap[cworkB[l]]) >= cend){ 262169db28dcSHong Zhang vals[lwrite] = aworkB[l]; 262269db28dcSHong Zhang cols[lwrite++] = ctmp; 262369db28dcSHong Zhang } 262469db28dcSHong Zhang } 262569db28dcSHong Zhang vals += ncols; 262669db28dcSHong Zhang cols += ncols; 262769db28dcSHong Zhang rptr[i+1] = rptr[i] + ncols; 262869db28dcSHong Zhang if (rownz_max < ncols) rownz_max = ncols; 262969db28dcSHong Zhang } 2630e32f2f54SBarry Smith if (rptr[rend-rstart] != a->nz + b->nz) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_PLIB, "rptr[%d] %d != %d + %d",rend-rstart,rptr[rend-rstart+1],a->nz,b->nz); 263169db28dcSHong Zhang } else { /* only copy matrix values into sbuf_a */ 263269db28dcSHong Zhang rptr = sbuf_j; 263369db28dcSHong Zhang vals = sbuf_a; 263469db28dcSHong Zhang rptr[0] = 0; 263569db28dcSHong Zhang for (i=0; i<rend-rstart; i++){ 263669db28dcSHong Zhang row = i + rstart; 263769db28dcSHong Zhang nzA = a->i[i+1] - a->i[i]; nzB = b->i[i+1] - b->i[i]; 263869db28dcSHong Zhang ncols = nzA + nzB; 263969db28dcSHong Zhang cworkA = a->j + a->i[i]; cworkB = b->j + b->i[i]; 264069db28dcSHong Zhang aworkA = a->a + a->i[i]; aworkB = b->a + b->i[i]; 264169db28dcSHong Zhang lwrite = 0; 264269db28dcSHong Zhang for (l=0; l<nzB; l++) { 264369db28dcSHong Zhang if ((ctmp = bmap[cworkB[l]]) < cstart) vals[lwrite++] = aworkB[l]; 264469db28dcSHong Zhang } 264569db28dcSHong Zhang for (l=0; l<nzA; l++) vals[lwrite++] = aworkA[l]; 264669db28dcSHong Zhang for (l=0; l<nzB; l++) { 264769db28dcSHong Zhang if ((ctmp = bmap[cworkB[l]]) >= cend) vals[lwrite++] = aworkB[l]; 264869db28dcSHong Zhang } 264969db28dcSHong Zhang vals += ncols; 265069db28dcSHong Zhang rptr[i+1] = rptr[i] + ncols; 265169db28dcSHong Zhang } 265269db28dcSHong Zhang } /* endof if (reuse == MAT_INITIAL_MATRIX) */ 265369db28dcSHong Zhang 265469db28dcSHong Zhang /* send nzlocal to others, and recv other's nzlocal */ 265569db28dcSHong Zhang /*--------------------------------------------------*/ 265669db28dcSHong Zhang if (reuse == MAT_INITIAL_MATRIX){ 265769db28dcSHong Zhang ierr = PetscMalloc2(3*(nsends + nrecvs)+1,MPI_Request,&s_waits3,nsends+1,MPI_Status,&send_status);CHKERRQ(ierr); 265869db28dcSHong Zhang s_waits2 = s_waits3 + nsends; 265969db28dcSHong Zhang s_waits1 = s_waits2 + nsends; 266069db28dcSHong Zhang r_waits1 = s_waits1 + nsends; 266169db28dcSHong Zhang r_waits2 = r_waits1 + nrecvs; 266269db28dcSHong Zhang r_waits3 = r_waits2 + nrecvs; 266369db28dcSHong Zhang } else { 266469db28dcSHong Zhang ierr = PetscMalloc2(nsends + nrecvs +1,MPI_Request,&s_waits3,nsends+1,MPI_Status,&send_status);CHKERRQ(ierr); 266569db28dcSHong Zhang r_waits3 = s_waits3 + nsends; 266669db28dcSHong Zhang } 266769db28dcSHong Zhang 266869db28dcSHong Zhang ierr = PetscObjectGetNewTag((PetscObject)mat,&tag3);CHKERRQ(ierr); 266969db28dcSHong Zhang if (reuse == MAT_INITIAL_MATRIX){ 267069db28dcSHong Zhang /* get new tags to keep the communication clean */ 267169db28dcSHong Zhang ierr = PetscObjectGetNewTag((PetscObject)mat,&tag1);CHKERRQ(ierr); 267269db28dcSHong Zhang ierr = PetscObjectGetNewTag((PetscObject)mat,&tag2);CHKERRQ(ierr); 26731d79065fSBarry Smith ierr = PetscMalloc4(nsends,PetscInt,&sbuf_nz,nrecvs,PetscInt,&rbuf_nz,nrecvs,PetscInt*,&rbuf_j,nrecvs,PetscScalar*,&rbuf_a);CHKERRQ(ierr); 267469db28dcSHong Zhang 267569db28dcSHong Zhang /* post receives of other's nzlocal */ 267669db28dcSHong Zhang for (i=0; i<nrecvs; i++){ 267769db28dcSHong Zhang ierr = MPI_Irecv(rbuf_nz+i,1,MPIU_INT,MPI_ANY_SOURCE,tag1,comm,r_waits1+i);CHKERRQ(ierr); 267869db28dcSHong Zhang } 267969db28dcSHong Zhang /* send nzlocal to others */ 268069db28dcSHong Zhang for (i=0; i<nsends; i++){ 268169db28dcSHong Zhang sbuf_nz[i] = nzlocal; 268269db28dcSHong Zhang ierr = MPI_Isend(sbuf_nz+i,1,MPIU_INT,send_rank[i],tag1,comm,s_waits1+i);CHKERRQ(ierr); 268369db28dcSHong Zhang } 268469db28dcSHong Zhang /* wait on receives of nzlocal; allocate space for rbuf_j, rbuf_a */ 268569db28dcSHong Zhang count = nrecvs; 268669db28dcSHong Zhang while (count) { 268769db28dcSHong Zhang ierr = MPI_Waitany(nrecvs,r_waits1,&imdex,&recv_status);CHKERRQ(ierr); 268869db28dcSHong Zhang recv_rank[imdex] = recv_status.MPI_SOURCE; 268969db28dcSHong Zhang /* allocate rbuf_a and rbuf_j; then post receives of rbuf_j */ 269069db28dcSHong Zhang ierr = PetscMalloc((rbuf_nz[imdex]+1)*sizeof(PetscScalar),&rbuf_a[imdex]);CHKERRQ(ierr); 269169db28dcSHong Zhang 269269db28dcSHong Zhang i = rowrange[recv_status.MPI_SOURCE+1] - rowrange[recv_status.MPI_SOURCE]; /* number of expected mat->i */ 269369db28dcSHong Zhang rbuf_nz[imdex] += i + 2; 269469db28dcSHong Zhang ierr = PetscMalloc(rbuf_nz[imdex]*sizeof(PetscInt),&rbuf_j[imdex]);CHKERRQ(ierr); 269569db28dcSHong Zhang ierr = MPI_Irecv(rbuf_j[imdex],rbuf_nz[imdex],MPIU_INT,recv_status.MPI_SOURCE,tag2,comm,r_waits2+imdex);CHKERRQ(ierr); 269669db28dcSHong Zhang count--; 269769db28dcSHong Zhang } 269869db28dcSHong Zhang /* wait on sends of nzlocal */ 269969db28dcSHong Zhang if (nsends) {ierr = MPI_Waitall(nsends,s_waits1,send_status);CHKERRQ(ierr);} 270069db28dcSHong Zhang /* send mat->i,j to others, and recv from other's */ 270169db28dcSHong Zhang /*------------------------------------------------*/ 270269db28dcSHong Zhang for (i=0; i<nsends; i++){ 270369db28dcSHong Zhang j = nzlocal + rowrange[rank+1] - rowrange[rank] + 1; 270469db28dcSHong Zhang ierr = MPI_Isend(sbuf_j,j,MPIU_INT,send_rank[i],tag2,comm,s_waits2+i);CHKERRQ(ierr); 270569db28dcSHong Zhang } 270669db28dcSHong Zhang /* wait on receives of mat->i,j */ 270769db28dcSHong Zhang /*------------------------------*/ 270869db28dcSHong Zhang count = nrecvs; 270969db28dcSHong Zhang while (count) { 271069db28dcSHong Zhang ierr = MPI_Waitany(nrecvs,r_waits2,&imdex,&recv_status);CHKERRQ(ierr); 2711e32f2f54SBarry Smith if (recv_rank[imdex] != recv_status.MPI_SOURCE) SETERRQ2(PETSC_COMM_SELF,1, "recv_rank %d != MPI_SOURCE %d",recv_rank[imdex],recv_status.MPI_SOURCE); 271269db28dcSHong Zhang count--; 271369db28dcSHong Zhang } 271469db28dcSHong Zhang /* wait on sends of mat->i,j */ 271569db28dcSHong Zhang /*---------------------------*/ 271669db28dcSHong Zhang if (nsends) { 271769db28dcSHong Zhang ierr = MPI_Waitall(nsends,s_waits2,send_status);CHKERRQ(ierr); 271869db28dcSHong Zhang } 271969db28dcSHong Zhang } /* endof if (reuse == MAT_INITIAL_MATRIX) */ 272069db28dcSHong Zhang 272169db28dcSHong Zhang /* post receives, send and receive mat->a */ 272269db28dcSHong Zhang /*----------------------------------------*/ 272369db28dcSHong Zhang for (imdex=0; imdex<nrecvs; imdex++) { 272469db28dcSHong Zhang ierr = MPI_Irecv(rbuf_a[imdex],rbuf_nz[imdex],MPIU_SCALAR,recv_rank[imdex],tag3,comm,r_waits3+imdex);CHKERRQ(ierr); 272569db28dcSHong Zhang } 272669db28dcSHong Zhang for (i=0; i<nsends; i++){ 272769db28dcSHong Zhang ierr = MPI_Isend(sbuf_a,nzlocal,MPIU_SCALAR,send_rank[i],tag3,comm,s_waits3+i);CHKERRQ(ierr); 272869db28dcSHong Zhang } 272969db28dcSHong Zhang count = nrecvs; 273069db28dcSHong Zhang while (count) { 273169db28dcSHong Zhang ierr = MPI_Waitany(nrecvs,r_waits3,&imdex,&recv_status);CHKERRQ(ierr); 2732e32f2f54SBarry Smith if (recv_rank[imdex] != recv_status.MPI_SOURCE) SETERRQ2(PETSC_COMM_SELF,1, "recv_rank %d != MPI_SOURCE %d",recv_rank[imdex],recv_status.MPI_SOURCE); 273369db28dcSHong Zhang count--; 273469db28dcSHong Zhang } 273569db28dcSHong Zhang if (nsends) { 273669db28dcSHong Zhang ierr = MPI_Waitall(nsends,s_waits3,send_status);CHKERRQ(ierr); 273769db28dcSHong Zhang } 273869db28dcSHong Zhang 273969db28dcSHong Zhang ierr = PetscFree2(s_waits3,send_status);CHKERRQ(ierr); 274069db28dcSHong Zhang 274169db28dcSHong Zhang /* create redundant matrix */ 274269db28dcSHong Zhang /*-------------------------*/ 274369db28dcSHong Zhang if (reuse == MAT_INITIAL_MATRIX){ 274469db28dcSHong Zhang /* compute rownz_max for preallocation */ 274569db28dcSHong Zhang for (imdex=0; imdex<nrecvs; imdex++){ 274669db28dcSHong Zhang j = rowrange[recv_rank[imdex]+1] - rowrange[recv_rank[imdex]]; 274769db28dcSHong Zhang rptr = rbuf_j[imdex]; 274869db28dcSHong Zhang for (i=0; i<j; i++){ 274969db28dcSHong Zhang ncols = rptr[i+1] - rptr[i]; 275069db28dcSHong Zhang if (rownz_max < ncols) rownz_max = ncols; 275169db28dcSHong Zhang } 275269db28dcSHong Zhang } 275369db28dcSHong Zhang 275469db28dcSHong Zhang ierr = MatCreate(subcomm,&C);CHKERRQ(ierr); 275569db28dcSHong Zhang ierr = MatSetSizes(C,mlocal_sub,mlocal_sub,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr); 2756a2f3521dSMark F. Adams ierr = MatSetBlockSizes(C,mat->rmap->bs,mat->cmap->bs); CHKERRQ(ierr); 275769db28dcSHong Zhang ierr = MatSetFromOptions(C);CHKERRQ(ierr); 275869db28dcSHong Zhang ierr = MatSeqAIJSetPreallocation(C,rownz_max,PETSC_NULL);CHKERRQ(ierr); 275969db28dcSHong Zhang ierr = MatMPIAIJSetPreallocation(C,rownz_max,PETSC_NULL,rownz_max,PETSC_NULL);CHKERRQ(ierr); 276069db28dcSHong Zhang } else { 276169db28dcSHong Zhang C = *matredundant; 276269db28dcSHong Zhang } 276369db28dcSHong Zhang 276469db28dcSHong Zhang /* insert local matrix entries */ 276569db28dcSHong Zhang rptr = sbuf_j; 276669db28dcSHong Zhang cols = sbuf_j + rend-rstart + 1; 276769db28dcSHong Zhang vals = sbuf_a; 276869db28dcSHong Zhang for (i=0; i<rend-rstart; i++){ 276969db28dcSHong Zhang row = i + rstart; 277069db28dcSHong Zhang ncols = rptr[i+1] - rptr[i]; 277169db28dcSHong Zhang ierr = MatSetValues(C,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr); 277269db28dcSHong Zhang vals += ncols; 277369db28dcSHong Zhang cols += ncols; 277469db28dcSHong Zhang } 277569db28dcSHong Zhang /* insert received matrix entries */ 277669db28dcSHong Zhang for (imdex=0; imdex<nrecvs; imdex++){ 277769db28dcSHong Zhang rstart = rowrange[recv_rank[imdex]]; 277869db28dcSHong Zhang rend = rowrange[recv_rank[imdex]+1]; 277969db28dcSHong Zhang rptr = rbuf_j[imdex]; 278069db28dcSHong Zhang cols = rbuf_j[imdex] + rend-rstart + 1; 278169db28dcSHong Zhang vals = rbuf_a[imdex]; 278269db28dcSHong Zhang for (i=0; i<rend-rstart; i++){ 278369db28dcSHong Zhang row = i + rstart; 278469db28dcSHong Zhang ncols = rptr[i+1] - rptr[i]; 278569db28dcSHong Zhang ierr = MatSetValues(C,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr); 278669db28dcSHong Zhang vals += ncols; 278769db28dcSHong Zhang cols += ncols; 278869db28dcSHong Zhang } 278969db28dcSHong Zhang } 279069db28dcSHong Zhang ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 279169db28dcSHong Zhang ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 279269db28dcSHong Zhang ierr = MatGetSize(C,&M,&N);CHKERRQ(ierr); 2793e32f2f54SBarry Smith if (M != mat->rmap->N || N != mat->cmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"redundant mat size %d != input mat size %d",M,mat->rmap->N); 279469db28dcSHong Zhang if (reuse == MAT_INITIAL_MATRIX) { 279569db28dcSHong Zhang PetscContainer container; 279669db28dcSHong Zhang *matredundant = C; 279769db28dcSHong Zhang /* create a supporting struct and attach it to C for reuse */ 279838f2d2fdSLisandro Dalcin ierr = PetscNewLog(C,Mat_Redundant,&redund);CHKERRQ(ierr); 279969db28dcSHong Zhang ierr = PetscContainerCreate(PETSC_COMM_SELF,&container);CHKERRQ(ierr); 280069db28dcSHong Zhang ierr = PetscContainerSetPointer(container,redund);CHKERRQ(ierr); 280169db28dcSHong Zhang ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_MatRedundant);CHKERRQ(ierr); 2802bf0cc555SLisandro Dalcin ierr = PetscObjectCompose((PetscObject)C,"Mat_Redundant",(PetscObject)container);CHKERRQ(ierr); 2803bf0cc555SLisandro Dalcin ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 280469db28dcSHong Zhang 280569db28dcSHong Zhang redund->nzlocal = nzlocal; 280669db28dcSHong Zhang redund->nsends = nsends; 280769db28dcSHong Zhang redund->nrecvs = nrecvs; 280869db28dcSHong Zhang redund->send_rank = send_rank; 28091d79065fSBarry Smith redund->recv_rank = recv_rank; 281069db28dcSHong Zhang redund->sbuf_nz = sbuf_nz; 28111d79065fSBarry Smith redund->rbuf_nz = rbuf_nz; 281269db28dcSHong Zhang redund->sbuf_j = sbuf_j; 281369db28dcSHong Zhang redund->sbuf_a = sbuf_a; 281469db28dcSHong Zhang redund->rbuf_j = rbuf_j; 281569db28dcSHong Zhang redund->rbuf_a = rbuf_a; 281669db28dcSHong Zhang 2817bf0cc555SLisandro Dalcin redund->Destroy = C->ops->destroy; 281869db28dcSHong Zhang C->ops->destroy = MatDestroy_MatRedundant; 281969db28dcSHong Zhang } 282069db28dcSHong Zhang PetscFunctionReturn(0); 282169db28dcSHong Zhang } 282269db28dcSHong Zhang 282303bc72f1SMatthew Knepley #undef __FUNCT__ 2824c91732d9SHong Zhang #define __FUNCT__ "MatGetRowMaxAbs_MPIAIJ" 2825c91732d9SHong Zhang PetscErrorCode MatGetRowMaxAbs_MPIAIJ(Mat A, Vec v, PetscInt idx[]) 2826c91732d9SHong Zhang { 2827c91732d9SHong Zhang Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2828c91732d9SHong Zhang PetscErrorCode ierr; 2829c91732d9SHong Zhang PetscInt i,*idxb = 0; 2830c91732d9SHong Zhang PetscScalar *va,*vb; 2831c91732d9SHong Zhang Vec vtmp; 2832c91732d9SHong Zhang 2833c91732d9SHong Zhang PetscFunctionBegin; 2834c91732d9SHong Zhang ierr = MatGetRowMaxAbs(a->A,v,idx);CHKERRQ(ierr); 2835c91732d9SHong Zhang ierr = VecGetArray(v,&va);CHKERRQ(ierr); 2836c91732d9SHong Zhang if (idx) { 2837192daf7cSBarry Smith for (i=0; i<A->rmap->n; i++) { 2838d0f46423SBarry Smith if (PetscAbsScalar(va[i])) idx[i] += A->cmap->rstart; 2839c91732d9SHong Zhang } 2840c91732d9SHong Zhang } 2841c91732d9SHong Zhang 2842d0f46423SBarry Smith ierr = VecCreateSeq(PETSC_COMM_SELF,A->rmap->n,&vtmp);CHKERRQ(ierr); 2843c91732d9SHong Zhang if (idx) { 2844d0f46423SBarry Smith ierr = PetscMalloc(A->rmap->n*sizeof(PetscInt),&idxb);CHKERRQ(ierr); 2845c91732d9SHong Zhang } 2846c91732d9SHong Zhang ierr = MatGetRowMaxAbs(a->B,vtmp,idxb);CHKERRQ(ierr); 2847c91732d9SHong Zhang ierr = VecGetArray(vtmp,&vb);CHKERRQ(ierr); 2848c91732d9SHong Zhang 2849d0f46423SBarry Smith for (i=0; i<A->rmap->n; i++){ 2850c91732d9SHong Zhang if (PetscAbsScalar(va[i]) < PetscAbsScalar(vb[i])) { 2851c91732d9SHong Zhang va[i] = vb[i]; 2852c91732d9SHong Zhang if (idx) idx[i] = a->garray[idxb[i]]; 2853c91732d9SHong Zhang } 2854c91732d9SHong Zhang } 2855c91732d9SHong Zhang 2856c91732d9SHong Zhang ierr = VecRestoreArray(v,&va);CHKERRQ(ierr); 2857c91732d9SHong Zhang ierr = VecRestoreArray(vtmp,&vb);CHKERRQ(ierr); 2858c91732d9SHong Zhang ierr = PetscFree(idxb);CHKERRQ(ierr); 28596bf464f9SBarry Smith ierr = VecDestroy(&vtmp);CHKERRQ(ierr); 2860c91732d9SHong Zhang PetscFunctionReturn(0); 2861c91732d9SHong Zhang } 2862c91732d9SHong Zhang 2863c91732d9SHong Zhang #undef __FUNCT__ 2864c87e5d42SMatthew Knepley #define __FUNCT__ "MatGetRowMinAbs_MPIAIJ" 2865c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_MPIAIJ(Mat A, Vec v, PetscInt idx[]) 2866c87e5d42SMatthew Knepley { 2867c87e5d42SMatthew Knepley Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2868c87e5d42SMatthew Knepley PetscErrorCode ierr; 2869c87e5d42SMatthew Knepley PetscInt i,*idxb = 0; 2870c87e5d42SMatthew Knepley PetscScalar *va,*vb; 2871c87e5d42SMatthew Knepley Vec vtmp; 2872c87e5d42SMatthew Knepley 2873c87e5d42SMatthew Knepley PetscFunctionBegin; 2874c87e5d42SMatthew Knepley ierr = MatGetRowMinAbs(a->A,v,idx);CHKERRQ(ierr); 2875c87e5d42SMatthew Knepley ierr = VecGetArray(v,&va);CHKERRQ(ierr); 2876c87e5d42SMatthew Knepley if (idx) { 2877c87e5d42SMatthew Knepley for (i=0; i<A->cmap->n; i++) { 2878c87e5d42SMatthew Knepley if (PetscAbsScalar(va[i])) idx[i] += A->cmap->rstart; 2879c87e5d42SMatthew Knepley } 2880c87e5d42SMatthew Knepley } 2881c87e5d42SMatthew Knepley 2882c87e5d42SMatthew Knepley ierr = VecCreateSeq(PETSC_COMM_SELF,A->rmap->n,&vtmp);CHKERRQ(ierr); 2883c87e5d42SMatthew Knepley if (idx) { 2884c87e5d42SMatthew Knepley ierr = PetscMalloc(A->rmap->n*sizeof(PetscInt),&idxb);CHKERRQ(ierr); 2885c87e5d42SMatthew Knepley } 2886c87e5d42SMatthew Knepley ierr = MatGetRowMinAbs(a->B,vtmp,idxb);CHKERRQ(ierr); 2887c87e5d42SMatthew Knepley ierr = VecGetArray(vtmp,&vb);CHKERRQ(ierr); 2888c87e5d42SMatthew Knepley 2889c87e5d42SMatthew Knepley for (i=0; i<A->rmap->n; i++){ 2890c87e5d42SMatthew Knepley if (PetscAbsScalar(va[i]) > PetscAbsScalar(vb[i])) { 2891c87e5d42SMatthew Knepley va[i] = vb[i]; 2892c87e5d42SMatthew Knepley if (idx) idx[i] = a->garray[idxb[i]]; 2893c87e5d42SMatthew Knepley } 2894c87e5d42SMatthew Knepley } 2895c87e5d42SMatthew Knepley 2896c87e5d42SMatthew Knepley ierr = VecRestoreArray(v,&va);CHKERRQ(ierr); 2897c87e5d42SMatthew Knepley ierr = VecRestoreArray(vtmp,&vb);CHKERRQ(ierr); 2898c87e5d42SMatthew Knepley ierr = PetscFree(idxb);CHKERRQ(ierr); 28996bf464f9SBarry Smith ierr = VecDestroy(&vtmp);CHKERRQ(ierr); 2900c87e5d42SMatthew Knepley PetscFunctionReturn(0); 2901c87e5d42SMatthew Knepley } 2902c87e5d42SMatthew Knepley 2903c87e5d42SMatthew Knepley #undef __FUNCT__ 290403bc72f1SMatthew Knepley #define __FUNCT__ "MatGetRowMin_MPIAIJ" 290503bc72f1SMatthew Knepley PetscErrorCode MatGetRowMin_MPIAIJ(Mat A, Vec v, PetscInt idx[]) 290603bc72f1SMatthew Knepley { 290703bc72f1SMatthew Knepley Mat_MPIAIJ *mat = (Mat_MPIAIJ *) A->data; 2908d0f46423SBarry Smith PetscInt n = A->rmap->n; 2909d0f46423SBarry Smith PetscInt cstart = A->cmap->rstart; 291003bc72f1SMatthew Knepley PetscInt *cmap = mat->garray; 291103bc72f1SMatthew Knepley PetscInt *diagIdx, *offdiagIdx; 291203bc72f1SMatthew Knepley Vec diagV, offdiagV; 291303bc72f1SMatthew Knepley PetscScalar *a, *diagA, *offdiagA; 291403bc72f1SMatthew Knepley PetscInt r; 291503bc72f1SMatthew Knepley PetscErrorCode ierr; 291603bc72f1SMatthew Knepley 291703bc72f1SMatthew Knepley PetscFunctionBegin; 291803bc72f1SMatthew Knepley ierr = PetscMalloc2(n,PetscInt,&diagIdx,n,PetscInt,&offdiagIdx);CHKERRQ(ierr); 2919e64afeacSLisandro Dalcin ierr = VecCreateSeq(((PetscObject)A)->comm, n, &diagV);CHKERRQ(ierr); 2920e64afeacSLisandro Dalcin ierr = VecCreateSeq(((PetscObject)A)->comm, n, &offdiagV);CHKERRQ(ierr); 292103bc72f1SMatthew Knepley ierr = MatGetRowMin(mat->A, diagV, diagIdx);CHKERRQ(ierr); 292203bc72f1SMatthew Knepley ierr = MatGetRowMin(mat->B, offdiagV, offdiagIdx);CHKERRQ(ierr); 292303bc72f1SMatthew Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 292403bc72f1SMatthew Knepley ierr = VecGetArray(diagV, &diagA);CHKERRQ(ierr); 292503bc72f1SMatthew Knepley ierr = VecGetArray(offdiagV, &offdiagA);CHKERRQ(ierr); 292603bc72f1SMatthew Knepley for(r = 0; r < n; ++r) { 2927028cd4eaSSatish Balay if (PetscAbsScalar(diagA[r]) <= PetscAbsScalar(offdiagA[r])) { 292803bc72f1SMatthew Knepley a[r] = diagA[r]; 292903bc72f1SMatthew Knepley idx[r] = cstart + diagIdx[r]; 293003bc72f1SMatthew Knepley } else { 293103bc72f1SMatthew Knepley a[r] = offdiagA[r]; 293203bc72f1SMatthew Knepley idx[r] = cmap[offdiagIdx[r]]; 293303bc72f1SMatthew Knepley } 293403bc72f1SMatthew Knepley } 293503bc72f1SMatthew Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 293603bc72f1SMatthew Knepley ierr = VecRestoreArray(diagV, &diagA);CHKERRQ(ierr); 293703bc72f1SMatthew Knepley ierr = VecRestoreArray(offdiagV, &offdiagA);CHKERRQ(ierr); 29386bf464f9SBarry Smith ierr = VecDestroy(&diagV);CHKERRQ(ierr); 29396bf464f9SBarry Smith ierr = VecDestroy(&offdiagV);CHKERRQ(ierr); 294003bc72f1SMatthew Knepley ierr = PetscFree2(diagIdx, offdiagIdx);CHKERRQ(ierr); 294103bc72f1SMatthew Knepley PetscFunctionReturn(0); 294203bc72f1SMatthew Knepley } 294303bc72f1SMatthew Knepley 29445494a064SHong Zhang #undef __FUNCT__ 2945c87e5d42SMatthew Knepley #define __FUNCT__ "MatGetRowMax_MPIAIJ" 2946c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMax_MPIAIJ(Mat A, Vec v, PetscInt idx[]) 2947c87e5d42SMatthew Knepley { 2948c87e5d42SMatthew Knepley Mat_MPIAIJ *mat = (Mat_MPIAIJ *) A->data; 2949c87e5d42SMatthew Knepley PetscInt n = A->rmap->n; 2950c87e5d42SMatthew Knepley PetscInt cstart = A->cmap->rstart; 2951c87e5d42SMatthew Knepley PetscInt *cmap = mat->garray; 2952c87e5d42SMatthew Knepley PetscInt *diagIdx, *offdiagIdx; 2953c87e5d42SMatthew Knepley Vec diagV, offdiagV; 2954c87e5d42SMatthew Knepley PetscScalar *a, *diagA, *offdiagA; 2955c87e5d42SMatthew Knepley PetscInt r; 2956c87e5d42SMatthew Knepley PetscErrorCode ierr; 2957c87e5d42SMatthew Knepley 2958c87e5d42SMatthew Knepley PetscFunctionBegin; 2959c87e5d42SMatthew Knepley ierr = PetscMalloc2(n,PetscInt,&diagIdx,n,PetscInt,&offdiagIdx);CHKERRQ(ierr); 2960c87e5d42SMatthew Knepley ierr = VecCreateSeq(((PetscObject)A)->comm, n, &diagV);CHKERRQ(ierr); 2961c87e5d42SMatthew Knepley ierr = VecCreateSeq(((PetscObject)A)->comm, n, &offdiagV);CHKERRQ(ierr); 2962c87e5d42SMatthew Knepley ierr = MatGetRowMax(mat->A, diagV, diagIdx);CHKERRQ(ierr); 2963c87e5d42SMatthew Knepley ierr = MatGetRowMax(mat->B, offdiagV, offdiagIdx);CHKERRQ(ierr); 2964c87e5d42SMatthew Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 2965c87e5d42SMatthew Knepley ierr = VecGetArray(diagV, &diagA);CHKERRQ(ierr); 2966c87e5d42SMatthew Knepley ierr = VecGetArray(offdiagV, &offdiagA);CHKERRQ(ierr); 2967c87e5d42SMatthew Knepley for(r = 0; r < n; ++r) { 2968c87e5d42SMatthew Knepley if (PetscAbsScalar(diagA[r]) >= PetscAbsScalar(offdiagA[r])) { 2969c87e5d42SMatthew Knepley a[r] = diagA[r]; 2970c87e5d42SMatthew Knepley idx[r] = cstart + diagIdx[r]; 2971c87e5d42SMatthew Knepley } else { 2972c87e5d42SMatthew Knepley a[r] = offdiagA[r]; 2973c87e5d42SMatthew Knepley idx[r] = cmap[offdiagIdx[r]]; 2974c87e5d42SMatthew Knepley } 2975c87e5d42SMatthew Knepley } 2976c87e5d42SMatthew Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 2977c87e5d42SMatthew Knepley ierr = VecRestoreArray(diagV, &diagA);CHKERRQ(ierr); 2978c87e5d42SMatthew Knepley ierr = VecRestoreArray(offdiagV, &offdiagA);CHKERRQ(ierr); 29796bf464f9SBarry Smith ierr = VecDestroy(&diagV);CHKERRQ(ierr); 29806bf464f9SBarry Smith ierr = VecDestroy(&offdiagV);CHKERRQ(ierr); 2981c87e5d42SMatthew Knepley ierr = PetscFree2(diagIdx, offdiagIdx);CHKERRQ(ierr); 2982c87e5d42SMatthew Knepley PetscFunctionReturn(0); 2983c87e5d42SMatthew Knepley } 2984c87e5d42SMatthew Knepley 2985c87e5d42SMatthew Knepley #undef __FUNCT__ 2986d1adec66SJed Brown #define __FUNCT__ "MatGetSeqNonzeroStructure_MPIAIJ" 2987d1adec66SJed Brown PetscErrorCode MatGetSeqNonzeroStructure_MPIAIJ(Mat mat,Mat *newmat) 29885494a064SHong Zhang { 29895494a064SHong Zhang PetscErrorCode ierr; 2990f6d58c54SBarry Smith Mat *dummy; 29915494a064SHong Zhang 29925494a064SHong Zhang PetscFunctionBegin; 2993f6d58c54SBarry Smith ierr = MatGetSubMatrix_MPIAIJ_All(mat,MAT_DO_NOT_GET_VALUES,MAT_INITIAL_MATRIX,&dummy);CHKERRQ(ierr); 2994f6d58c54SBarry Smith *newmat = *dummy; 2995f6d58c54SBarry Smith ierr = PetscFree(dummy);CHKERRQ(ierr); 29965494a064SHong Zhang PetscFunctionReturn(0); 29975494a064SHong Zhang } 29985494a064SHong Zhang 29997087cfbeSBarry Smith extern PetscErrorCode MatFDColoringApply_AIJ(Mat,MatFDColoring,Vec,MatStructure*,void*); 3000bbead8a2SBarry Smith 3001bbead8a2SBarry Smith #undef __FUNCT__ 3002bbead8a2SBarry Smith #define __FUNCT__ "MatInvertBlockDiagonal_MPIAIJ" 3003713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_MPIAIJ(Mat A,const PetscScalar **values) 3004bbead8a2SBarry Smith { 3005bbead8a2SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*) A->data; 3006bbead8a2SBarry Smith PetscErrorCode ierr; 3007bbead8a2SBarry Smith 3008bbead8a2SBarry Smith PetscFunctionBegin; 3009bbead8a2SBarry Smith ierr = MatInvertBlockDiagonal(a->A,values);CHKERRQ(ierr); 3010bbead8a2SBarry Smith PetscFunctionReturn(0); 3011bbead8a2SBarry Smith } 3012bbead8a2SBarry Smith 3013*73a71a0fSBarry Smith #undef __FUNCT__ 3014*73a71a0fSBarry Smith #define __FUNCT__ "MatSetRandom_MPIAIJ" 3015*73a71a0fSBarry Smith static PetscErrorCode MatSetRandom_MPIAIJ(Mat x,PetscRandom rctx) 3016*73a71a0fSBarry Smith { 3017*73a71a0fSBarry Smith PetscErrorCode ierr; 3018*73a71a0fSBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)x->data; 3019*73a71a0fSBarry Smith 3020*73a71a0fSBarry Smith PetscFunctionBegin; 3021*73a71a0fSBarry Smith ierr = MatSetRandom(aij->A,rctx);CHKERRQ(ierr); 3022*73a71a0fSBarry Smith ierr = MatSetRandom(aij->B,rctx);CHKERRQ(ierr); 3023*73a71a0fSBarry Smith ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3024*73a71a0fSBarry Smith ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3025*73a71a0fSBarry Smith PetscFunctionReturn(0); 3026*73a71a0fSBarry Smith } 3027bbead8a2SBarry Smith 30288a729477SBarry Smith /* -------------------------------------------------------------------*/ 3029cda55fadSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_MPIAIJ, 3030cda55fadSBarry Smith MatGetRow_MPIAIJ, 3031cda55fadSBarry Smith MatRestoreRow_MPIAIJ, 3032cda55fadSBarry Smith MatMult_MPIAIJ, 303397304618SKris Buschelman /* 4*/ MatMultAdd_MPIAIJ, 30347c922b88SBarry Smith MatMultTranspose_MPIAIJ, 30357c922b88SBarry Smith MatMultTransposeAdd_MPIAIJ, 3036103bf8bdSMatthew Knepley #ifdef PETSC_HAVE_PBGL 3037103bf8bdSMatthew Knepley MatSolve_MPIAIJ, 3038103bf8bdSMatthew Knepley #else 3039cda55fadSBarry Smith 0, 3040103bf8bdSMatthew Knepley #endif 3041cda55fadSBarry Smith 0, 3042cda55fadSBarry Smith 0, 304397304618SKris Buschelman /*10*/ 0, 3044cda55fadSBarry Smith 0, 3045cda55fadSBarry Smith 0, 304641f059aeSBarry Smith MatSOR_MPIAIJ, 3047b7c46309SBarry Smith MatTranspose_MPIAIJ, 304897304618SKris Buschelman /*15*/ MatGetInfo_MPIAIJ, 3049cda55fadSBarry Smith MatEqual_MPIAIJ, 3050cda55fadSBarry Smith MatGetDiagonal_MPIAIJ, 3051cda55fadSBarry Smith MatDiagonalScale_MPIAIJ, 3052cda55fadSBarry Smith MatNorm_MPIAIJ, 305397304618SKris Buschelman /*20*/ MatAssemblyBegin_MPIAIJ, 3054cda55fadSBarry Smith MatAssemblyEnd_MPIAIJ, 3055cda55fadSBarry Smith MatSetOption_MPIAIJ, 3056cda55fadSBarry Smith MatZeroEntries_MPIAIJ, 3057d519adbfSMatthew Knepley /*24*/ MatZeroRows_MPIAIJ, 3058cda55fadSBarry Smith 0, 3059103bf8bdSMatthew Knepley #ifdef PETSC_HAVE_PBGL 3060719d5645SBarry Smith 0, 3061103bf8bdSMatthew Knepley #else 3062cda55fadSBarry Smith 0, 3063103bf8bdSMatthew Knepley #endif 3064cda55fadSBarry Smith 0, 3065cda55fadSBarry Smith 0, 30664994cf47SJed Brown /*29*/ MatSetUp_MPIAIJ, 3067103bf8bdSMatthew Knepley #ifdef PETSC_HAVE_PBGL 3068719d5645SBarry Smith 0, 3069103bf8bdSMatthew Knepley #else 3070cda55fadSBarry Smith 0, 3071103bf8bdSMatthew Knepley #endif 3072cda55fadSBarry Smith 0, 3073cda55fadSBarry Smith 0, 3074cda55fadSBarry Smith 0, 3075d519adbfSMatthew Knepley /*34*/ MatDuplicate_MPIAIJ, 3076cda55fadSBarry Smith 0, 3077cda55fadSBarry Smith 0, 3078cda55fadSBarry Smith 0, 3079cda55fadSBarry Smith 0, 3080d519adbfSMatthew Knepley /*39*/ MatAXPY_MPIAIJ, 3081cda55fadSBarry Smith MatGetSubMatrices_MPIAIJ, 3082cda55fadSBarry Smith MatIncreaseOverlap_MPIAIJ, 3083cda55fadSBarry Smith MatGetValues_MPIAIJ, 3084cb5b572fSBarry Smith MatCopy_MPIAIJ, 3085d519adbfSMatthew Knepley /*44*/ MatGetRowMax_MPIAIJ, 3086cda55fadSBarry Smith MatScale_MPIAIJ, 3087cda55fadSBarry Smith 0, 3088cda55fadSBarry Smith 0, 3089564f14d6SBarry Smith MatZeroRowsColumns_MPIAIJ, 3090*73a71a0fSBarry Smith /*49*/ MatSetRandom_MPIAIJ, 3091cda55fadSBarry Smith 0, 3092cda55fadSBarry Smith 0, 3093cda55fadSBarry Smith 0, 3094cda55fadSBarry Smith 0, 3095d519adbfSMatthew Knepley /*54*/ MatFDColoringCreate_MPIAIJ, 3096cda55fadSBarry Smith 0, 3097cda55fadSBarry Smith MatSetUnfactored_MPIAIJ, 309829dcf524SDmitry Karpeev 0, /* MatPermute_MPIAIJ, impl currently broken */ 3099cda55fadSBarry Smith 0, 3100d519adbfSMatthew Knepley /*59*/ MatGetSubMatrix_MPIAIJ, 3101e03a110bSBarry Smith MatDestroy_MPIAIJ, 3102e03a110bSBarry Smith MatView_MPIAIJ, 3103357abbc8SBarry Smith 0, 3104a2243be0SBarry Smith 0, 3105d519adbfSMatthew Knepley /*64*/ 0, 3106a2243be0SBarry Smith 0, 3107a2243be0SBarry Smith 0, 3108a2243be0SBarry Smith 0, 3109a2243be0SBarry Smith 0, 3110d519adbfSMatthew Knepley /*69*/ MatGetRowMaxAbs_MPIAIJ, 3111c87e5d42SMatthew Knepley MatGetRowMinAbs_MPIAIJ, 3112a2243be0SBarry Smith 0, 3113a2243be0SBarry Smith MatSetColoring_MPIAIJ, 3114dcf5cc72SBarry Smith #if defined(PETSC_HAVE_ADIC) 3115779c1a83SBarry Smith MatSetValuesAdic_MPIAIJ, 3116dcf5cc72SBarry Smith #else 3117dcf5cc72SBarry Smith 0, 3118dcf5cc72SBarry Smith #endif 311997304618SKris Buschelman MatSetValuesAdifor_MPIAIJ, 31203acb8795SBarry Smith /*75*/ MatFDColoringApply_AIJ, 312197304618SKris Buschelman 0, 312297304618SKris Buschelman 0, 312397304618SKris Buschelman 0, 3124f1f41ecbSJed Brown MatFindZeroDiagonals_MPIAIJ, 312597304618SKris Buschelman /*80*/ 0, 312697304618SKris Buschelman 0, 312797304618SKris Buschelman 0, 31285bba2384SShri Abhyankar /*83*/ MatLoad_MPIAIJ, 31296284ec50SHong Zhang 0, 31306284ec50SHong Zhang 0, 31316284ec50SHong Zhang 0, 31326284ec50SHong Zhang 0, 3133865e5f61SKris Buschelman 0, 3134d519adbfSMatthew Knepley /*89*/ MatMatMult_MPIAIJ_MPIAIJ, 313526be0446SHong Zhang MatMatMultSymbolic_MPIAIJ_MPIAIJ, 313626be0446SHong Zhang MatMatMultNumeric_MPIAIJ_MPIAIJ, 31377a7894deSKris Buschelman MatPtAP_Basic, 31387a7894deSKris Buschelman MatPtAPSymbolic_MPIAIJ, 3139d519adbfSMatthew Knepley /*94*/ MatPtAPNumeric_MPIAIJ, 31407a7894deSKris Buschelman 0, 31417a7894deSKris Buschelman 0, 31427a7894deSKris Buschelman 0, 31437a7894deSKris Buschelman 0, 3144d519adbfSMatthew Knepley /*99*/ 0, 3145865e5f61SKris Buschelman MatPtAPSymbolic_MPIAIJ_MPIAIJ, 31467a7894deSKris Buschelman MatPtAPNumeric_MPIAIJ_MPIAIJ, 31472fd7e33dSBarry Smith MatConjugate_MPIAIJ, 31482fd7e33dSBarry Smith 0, 3149d519adbfSMatthew Knepley /*104*/MatSetValuesRow_MPIAIJ, 315099cafbc1SBarry Smith MatRealPart_MPIAIJ, 315169db28dcSHong Zhang MatImaginaryPart_MPIAIJ, 315269db28dcSHong Zhang 0, 315369db28dcSHong Zhang 0, 3154d519adbfSMatthew Knepley /*109*/0, 315503bc72f1SMatthew Knepley MatGetRedundantMatrix_MPIAIJ, 31565494a064SHong Zhang MatGetRowMin_MPIAIJ, 31575494a064SHong Zhang 0, 31585494a064SHong Zhang 0, 3159d1adec66SJed Brown /*114*/MatGetSeqNonzeroStructure_MPIAIJ, 3160bd0c2dcbSBarry Smith 0, 3161bd0c2dcbSBarry Smith 0, 3162bd0c2dcbSBarry Smith 0, 3163bd0c2dcbSBarry Smith 0, 31648fb81238SShri Abhyankar /*119*/0, 31658fb81238SShri Abhyankar 0, 31668fb81238SShri Abhyankar 0, 3167d6037b41SHong Zhang 0, 3168b9614d88SDmitry Karpeev MatGetMultiProcBlock_MPIAIJ, 3169f2c98031SJed Brown /*124*/MatFindNonzeroRows_MPIAIJ, 31700716a85fSBarry Smith MatGetColumnNorms_MPIAIJ, 3171bbead8a2SBarry Smith MatInvertBlockDiagonal_MPIAIJ, 3172b9614d88SDmitry Karpeev 0, 317337868618SMatthew G Knepley MatGetSubMatricesParallel_MPIAIJ, 3174187b3c17SHong Zhang /*129*/0, 3175187b3c17SHong Zhang MatTransposeMatMult_MPIAIJ_MPIAIJ, 3176187b3c17SHong Zhang MatTransposeMatMultSymbolic_MPIAIJ_MPIAIJ, 3177187b3c17SHong Zhang MatTransposeMatMultNumeric_MPIAIJ_MPIAIJ, 3178187b3c17SHong Zhang 0, 3179187b3c17SHong Zhang /*134*/0, 3180187b3c17SHong Zhang 0, 3181187b3c17SHong Zhang 0, 3182187b3c17SHong Zhang 0, 3183187b3c17SHong Zhang 0 3184bd0c2dcbSBarry Smith }; 318536ce4990SBarry Smith 31862e8a6d31SBarry Smith /* ----------------------------------------------------------------------------------------*/ 31872e8a6d31SBarry Smith 3188fb2e594dSBarry Smith EXTERN_C_BEGIN 31894a2ae208SSatish Balay #undef __FUNCT__ 31904a2ae208SSatish Balay #define __FUNCT__ "MatStoreValues_MPIAIJ" 31917087cfbeSBarry Smith PetscErrorCode MatStoreValues_MPIAIJ(Mat mat) 31922e8a6d31SBarry Smith { 31932e8a6d31SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ *)mat->data; 3194dfbe8321SBarry Smith PetscErrorCode ierr; 31952e8a6d31SBarry Smith 31962e8a6d31SBarry Smith PetscFunctionBegin; 31972e8a6d31SBarry Smith ierr = MatStoreValues(aij->A);CHKERRQ(ierr); 31982e8a6d31SBarry Smith ierr = MatStoreValues(aij->B);CHKERRQ(ierr); 31992e8a6d31SBarry Smith PetscFunctionReturn(0); 32002e8a6d31SBarry Smith } 3201fb2e594dSBarry Smith EXTERN_C_END 32022e8a6d31SBarry Smith 3203fb2e594dSBarry Smith EXTERN_C_BEGIN 32044a2ae208SSatish Balay #undef __FUNCT__ 32054a2ae208SSatish Balay #define __FUNCT__ "MatRetrieveValues_MPIAIJ" 32067087cfbeSBarry Smith PetscErrorCode MatRetrieveValues_MPIAIJ(Mat mat) 32072e8a6d31SBarry Smith { 32082e8a6d31SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ *)mat->data; 3209dfbe8321SBarry Smith PetscErrorCode ierr; 32102e8a6d31SBarry Smith 32112e8a6d31SBarry Smith PetscFunctionBegin; 32122e8a6d31SBarry Smith ierr = MatRetrieveValues(aij->A);CHKERRQ(ierr); 32132e8a6d31SBarry Smith ierr = MatRetrieveValues(aij->B);CHKERRQ(ierr); 32142e8a6d31SBarry Smith PetscFunctionReturn(0); 32152e8a6d31SBarry Smith } 3216fb2e594dSBarry Smith EXTERN_C_END 32178a729477SBarry Smith 321827508adbSBarry Smith EXTERN_C_BEGIN 32194a2ae208SSatish Balay #undef __FUNCT__ 3220a23d5eceSKris Buschelman #define __FUNCT__ "MatMPIAIJSetPreallocation_MPIAIJ" 32217087cfbeSBarry Smith PetscErrorCode MatMPIAIJSetPreallocation_MPIAIJ(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 3222a23d5eceSKris Buschelman { 3223a23d5eceSKris Buschelman Mat_MPIAIJ *b; 3224dfbe8321SBarry Smith PetscErrorCode ierr; 3225b1d57f15SBarry Smith PetscInt i; 32262576faa2SJed Brown PetscBool d_realalloc = PETSC_FALSE,o_realalloc = PETSC_FALSE; 3227a23d5eceSKris Buschelman 3228a23d5eceSKris Buschelman PetscFunctionBegin; 32292576faa2SJed Brown if (d_nz >= 0 || d_nnz) d_realalloc = PETSC_TRUE; 32302576faa2SJed Brown if (o_nz >= 0 || o_nnz) o_realalloc = PETSC_TRUE; 3231a23d5eceSKris Buschelman if (d_nz == PETSC_DEFAULT || d_nz == PETSC_DECIDE) d_nz = 5; 3232a23d5eceSKris Buschelman if (o_nz == PETSC_DEFAULT || o_nz == PETSC_DECIDE) o_nz = 2; 3233e32f2f54SBarry Smith if (d_nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"d_nz cannot be less than 0: value %D",d_nz); 3234e32f2f54SBarry Smith if (o_nz < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"o_nz cannot be less than 0: value %D",o_nz); 3235899cda47SBarry Smith 323626283091SBarry Smith ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 323726283091SBarry Smith ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 3238a23d5eceSKris Buschelman if (d_nnz) { 3239d0f46423SBarry Smith for (i=0; i<B->rmap->n; i++) { 3240e32f2f54SBarry Smith if (d_nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"d_nnz cannot be less than 0: local row %D value %D",i,d_nnz[i]); 3241a23d5eceSKris Buschelman } 3242a23d5eceSKris Buschelman } 3243a23d5eceSKris Buschelman if (o_nnz) { 3244d0f46423SBarry Smith for (i=0; i<B->rmap->n; i++) { 3245e32f2f54SBarry Smith if (o_nnz[i] < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"o_nnz cannot be less than 0: local row %D value %D",i,o_nnz[i]); 3246a23d5eceSKris Buschelman } 3247a23d5eceSKris Buschelman } 3248a23d5eceSKris Buschelman b = (Mat_MPIAIJ*)B->data; 3249899cda47SBarry Smith 3250526dfc15SBarry Smith if (!B->preallocated) { 3251899cda47SBarry Smith /* Explicitly create 2 MATSEQAIJ matrices. */ 3252899cda47SBarry Smith ierr = MatCreate(PETSC_COMM_SELF,&b->A);CHKERRQ(ierr); 3253d0f46423SBarry Smith ierr = MatSetSizes(b->A,B->rmap->n,B->cmap->n,B->rmap->n,B->cmap->n);CHKERRQ(ierr); 3254f9e9af59SJed Brown ierr = MatSetBlockSizes(b->A,B->rmap->bs,B->cmap->bs);CHKERRQ(ierr); 3255899cda47SBarry Smith ierr = MatSetType(b->A,MATSEQAIJ);CHKERRQ(ierr); 3256899cda47SBarry Smith ierr = PetscLogObjectParent(B,b->A);CHKERRQ(ierr); 3257899cda47SBarry Smith ierr = MatCreate(PETSC_COMM_SELF,&b->B);CHKERRQ(ierr); 3258d0f46423SBarry Smith ierr = MatSetSizes(b->B,B->rmap->n,B->cmap->N,B->rmap->n,B->cmap->N);CHKERRQ(ierr); 3259f9e9af59SJed Brown ierr = MatSetBlockSizes(b->B,B->rmap->bs,B->cmap->bs);CHKERRQ(ierr); 3260899cda47SBarry Smith ierr = MatSetType(b->B,MATSEQAIJ);CHKERRQ(ierr); 3261899cda47SBarry Smith ierr = PetscLogObjectParent(B,b->B);CHKERRQ(ierr); 3262526dfc15SBarry Smith } 3263899cda47SBarry Smith 3264c60e587dSKris Buschelman ierr = MatSeqAIJSetPreallocation(b->A,d_nz,d_nnz);CHKERRQ(ierr); 3265c60e587dSKris Buschelman ierr = MatSeqAIJSetPreallocation(b->B,o_nz,o_nnz);CHKERRQ(ierr); 32662576faa2SJed Brown /* Do not error if the user did not give real preallocation information. Ugly because this would overwrite a previous user call to MatSetOption(). */ 32672576faa2SJed Brown if (!d_realalloc) {ierr = MatSetOption(b->A,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);} 32682576faa2SJed Brown if (!o_realalloc) {ierr = MatSetOption(b->B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr);} 3269526dfc15SBarry Smith B->preallocated = PETSC_TRUE; 3270a23d5eceSKris Buschelman PetscFunctionReturn(0); 3271a23d5eceSKris Buschelman } 3272a23d5eceSKris Buschelman EXTERN_C_END 3273a23d5eceSKris Buschelman 32744a2ae208SSatish Balay #undef __FUNCT__ 32754a2ae208SSatish Balay #define __FUNCT__ "MatDuplicate_MPIAIJ" 3276dfbe8321SBarry Smith PetscErrorCode MatDuplicate_MPIAIJ(Mat matin,MatDuplicateOption cpvalues,Mat *newmat) 3277d6dfbf8fSBarry Smith { 3278d6dfbf8fSBarry Smith Mat mat; 3279416022c9SBarry Smith Mat_MPIAIJ *a,*oldmat = (Mat_MPIAIJ*)matin->data; 3280dfbe8321SBarry Smith PetscErrorCode ierr; 3281d6dfbf8fSBarry Smith 32823a40ed3dSBarry Smith PetscFunctionBegin; 3283416022c9SBarry Smith *newmat = 0; 32847adad957SLisandro Dalcin ierr = MatCreate(((PetscObject)matin)->comm,&mat);CHKERRQ(ierr); 3285d0f46423SBarry Smith ierr = MatSetSizes(mat,matin->rmap->n,matin->cmap->n,matin->rmap->N,matin->cmap->N);CHKERRQ(ierr); 3286a2f3521dSMark F. Adams ierr = MatSetBlockSizes(mat,matin->rmap->bs,matin->cmap->bs);CHKERRQ(ierr); 32877adad957SLisandro Dalcin ierr = MatSetType(mat,((PetscObject)matin)->type_name);CHKERRQ(ierr); 32881d5dac46SHong Zhang ierr = PetscMemcpy(mat->ops,matin->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 3289273d9f13SBarry Smith a = (Mat_MPIAIJ*)mat->data; 3290e1b6402fSHong Zhang 3291d5f3da31SBarry Smith mat->factortype = matin->factortype; 3292d0f46423SBarry Smith mat->rmap->bs = matin->rmap->bs; 3293a2f3521dSMark F. Adams mat->cmap->bs = matin->cmap->bs; 3294c456f294SBarry Smith mat->assembled = PETSC_TRUE; 3295e7641de0SSatish Balay mat->insertmode = NOT_SET_VALUES; 3296273d9f13SBarry Smith mat->preallocated = PETSC_TRUE; 3297d6dfbf8fSBarry Smith 329817699dbbSLois Curfman McInnes a->size = oldmat->size; 329917699dbbSLois Curfman McInnes a->rank = oldmat->rank; 3300e7641de0SSatish Balay a->donotstash = oldmat->donotstash; 3301e7641de0SSatish Balay a->roworiented = oldmat->roworiented; 3302e7641de0SSatish Balay a->rowindices = 0; 3303bcd2baecSBarry Smith a->rowvalues = 0; 3304bcd2baecSBarry Smith a->getrowactive = PETSC_FALSE; 3305d6dfbf8fSBarry Smith 33061e1e43feSBarry Smith ierr = PetscLayoutReference(matin->rmap,&mat->rmap);CHKERRQ(ierr); 33071e1e43feSBarry Smith ierr = PetscLayoutReference(matin->cmap,&mat->cmap);CHKERRQ(ierr); 3308899cda47SBarry Smith 33092ee70a88SLois Curfman McInnes if (oldmat->colmap) { 3310aa482453SBarry Smith #if defined (PETSC_USE_CTABLE) 33110f5bd95cSBarry Smith ierr = PetscTableCreateCopy(oldmat->colmap,&a->colmap);CHKERRQ(ierr); 3312b1fc9764SSatish Balay #else 3313d0f46423SBarry Smith ierr = PetscMalloc((mat->cmap->N)*sizeof(PetscInt),&a->colmap);CHKERRQ(ierr); 3314d0f46423SBarry Smith ierr = PetscLogObjectMemory(mat,(mat->cmap->N)*sizeof(PetscInt));CHKERRQ(ierr); 3315d0f46423SBarry Smith ierr = PetscMemcpy(a->colmap,oldmat->colmap,(mat->cmap->N)*sizeof(PetscInt));CHKERRQ(ierr); 3316b1fc9764SSatish Balay #endif 3317416022c9SBarry Smith } else a->colmap = 0; 33183f41c07dSBarry Smith if (oldmat->garray) { 3319b1d57f15SBarry Smith PetscInt len; 3320d0f46423SBarry Smith len = oldmat->B->cmap->n; 3321b1d57f15SBarry Smith ierr = PetscMalloc((len+1)*sizeof(PetscInt),&a->garray);CHKERRQ(ierr); 332252e6d16bSBarry Smith ierr = PetscLogObjectMemory(mat,len*sizeof(PetscInt));CHKERRQ(ierr); 3323b1d57f15SBarry Smith if (len) { ierr = PetscMemcpy(a->garray,oldmat->garray,len*sizeof(PetscInt));CHKERRQ(ierr); } 3324416022c9SBarry Smith } else a->garray = 0; 3325d6dfbf8fSBarry Smith 3326416022c9SBarry Smith ierr = VecDuplicate(oldmat->lvec,&a->lvec);CHKERRQ(ierr); 332752e6d16bSBarry Smith ierr = PetscLogObjectParent(mat,a->lvec);CHKERRQ(ierr); 3328a56f8943SBarry Smith ierr = VecScatterCopy(oldmat->Mvctx,&a->Mvctx);CHKERRQ(ierr); 332952e6d16bSBarry Smith ierr = PetscLogObjectParent(mat,a->Mvctx);CHKERRQ(ierr); 33302e8a6d31SBarry Smith ierr = MatDuplicate(oldmat->A,cpvalues,&a->A);CHKERRQ(ierr); 333152e6d16bSBarry Smith ierr = PetscLogObjectParent(mat,a->A);CHKERRQ(ierr); 33322e8a6d31SBarry Smith ierr = MatDuplicate(oldmat->B,cpvalues,&a->B);CHKERRQ(ierr); 333352e6d16bSBarry Smith ierr = PetscLogObjectParent(mat,a->B);CHKERRQ(ierr); 33347adad957SLisandro Dalcin ierr = PetscFListDuplicate(((PetscObject)matin)->qlist,&((PetscObject)mat)->qlist);CHKERRQ(ierr); 33358a729477SBarry Smith *newmat = mat; 33363a40ed3dSBarry Smith PetscFunctionReturn(0); 33378a729477SBarry Smith } 3338416022c9SBarry Smith 33391a4ee126SBarry Smith 33401a4ee126SBarry Smith 33414a2ae208SSatish Balay #undef __FUNCT__ 33425bba2384SShri Abhyankar #define __FUNCT__ "MatLoad_MPIAIJ" 3343112444f4SShri Abhyankar PetscErrorCode MatLoad_MPIAIJ(Mat newMat, PetscViewer viewer) 33448fb81238SShri Abhyankar { 33458fb81238SShri Abhyankar PetscScalar *vals,*svals; 33468fb81238SShri Abhyankar MPI_Comm comm = ((PetscObject)viewer)->comm; 33478fb81238SShri Abhyankar PetscErrorCode ierr; 33481a4ee126SBarry Smith PetscMPIInt rank,size,tag = ((PetscObject)viewer)->tag; 33498fb81238SShri Abhyankar PetscInt i,nz,j,rstart,rend,mmax,maxnz = 0,grows,gcols; 33508fb81238SShri Abhyankar PetscInt header[4],*rowlengths = 0,M,N,m,*cols; 33518fb81238SShri Abhyankar PetscInt *ourlens = PETSC_NULL,*procsnz = PETSC_NULL,*offlens = PETSC_NULL,jj,*mycols,*smycols; 33528fb81238SShri Abhyankar PetscInt cend,cstart,n,*rowners,sizesset=1; 33538fb81238SShri Abhyankar int fd; 335408ea439dSMark F. Adams PetscInt bs = 1; 33558fb81238SShri Abhyankar 33568fb81238SShri Abhyankar PetscFunctionBegin; 33578fb81238SShri Abhyankar ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 33588fb81238SShri Abhyankar ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 33598fb81238SShri Abhyankar if (!rank) { 33608fb81238SShri Abhyankar ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 33618fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,(char *)header,4,PETSC_INT);CHKERRQ(ierr); 33628fb81238SShri Abhyankar if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object"); 33638fb81238SShri Abhyankar } 33648fb81238SShri Abhyankar 336508ea439dSMark F. Adams ierr = PetscOptionsBegin(comm,PETSC_NULL,"Options for loading SEQAIJ matrix","Mat");CHKERRQ(ierr); 336608ea439dSMark F. Adams ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,PETSC_NULL);CHKERRQ(ierr); 336708ea439dSMark F. Adams ierr = PetscOptionsEnd();CHKERRQ(ierr); 336808ea439dSMark F. Adams 33698fb81238SShri Abhyankar if (newMat->rmap->n < 0 && newMat->rmap->N < 0 && newMat->cmap->n < 0 && newMat->cmap->N < 0) sizesset = 0; 33708fb81238SShri Abhyankar 33718fb81238SShri Abhyankar ierr = MPI_Bcast(header+1,3,MPIU_INT,0,comm);CHKERRQ(ierr); 33728fb81238SShri Abhyankar M = header[1]; N = header[2]; 33738fb81238SShri Abhyankar /* If global rows/cols are set to PETSC_DECIDE, set it to the sizes given in the file */ 33748fb81238SShri Abhyankar if (sizesset && newMat->rmap->N < 0) newMat->rmap->N = M; 33758fb81238SShri Abhyankar if (sizesset && newMat->cmap->N < 0) newMat->cmap->N = N; 33768fb81238SShri Abhyankar 33778fb81238SShri Abhyankar /* If global sizes are set, check if they are consistent with that given in the file */ 33788fb81238SShri Abhyankar if (sizesset) { 33798fb81238SShri Abhyankar ierr = MatGetSize(newMat,&grows,&gcols);CHKERRQ(ierr); 33808fb81238SShri Abhyankar } 3381abd38a8fSBarry Smith if (sizesset && newMat->rmap->N != grows) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Inconsistent # of rows:Matrix in file has (%d) and input matrix has (%d)",M,grows); 3382abd38a8fSBarry Smith if (sizesset && newMat->cmap->N != gcols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Inconsistent # of cols:Matrix in file has (%d) and input matrix has (%d)",N,gcols); 33838fb81238SShri Abhyankar 338408ea439dSMark F. Adams /* determine ownership of all (block) rows */ 338508ea439dSMark F. Adams if( M%bs ) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Inconsistent # of rows (%d) and block size (%d)",M,bs); 338608ea439dSMark F. Adams if (newMat->rmap->n < 0 ) m = bs*((M/bs)/size + (((M/bs) % size) > rank)); /* PETSC_DECIDE */ 33874683f7a4SShri Abhyankar else m = newMat->rmap->n; /* Set by user */ 33888fb81238SShri Abhyankar 33898fb81238SShri Abhyankar ierr = PetscMalloc((size+1)*sizeof(PetscInt),&rowners);CHKERRQ(ierr); 33908fb81238SShri Abhyankar ierr = MPI_Allgather(&m,1,MPIU_INT,rowners+1,1,MPIU_INT,comm);CHKERRQ(ierr); 33918fb81238SShri Abhyankar 33928fb81238SShri Abhyankar /* First process needs enough room for process with most rows */ 33938fb81238SShri Abhyankar if (!rank) { 33948fb81238SShri Abhyankar mmax = rowners[1]; 33958fb81238SShri Abhyankar for (i=2; i<size; i++) { 33968fb81238SShri Abhyankar mmax = PetscMax(mmax,rowners[i]); 33978fb81238SShri Abhyankar } 33988fb81238SShri Abhyankar } else mmax = m; 33998fb81238SShri Abhyankar 34008fb81238SShri Abhyankar rowners[0] = 0; 34018fb81238SShri Abhyankar for (i=2; i<=size; i++) { 34028fb81238SShri Abhyankar rowners[i] += rowners[i-1]; 34038fb81238SShri Abhyankar } 34048fb81238SShri Abhyankar rstart = rowners[rank]; 34058fb81238SShri Abhyankar rend = rowners[rank+1]; 34068fb81238SShri Abhyankar 34078fb81238SShri Abhyankar /* distribute row lengths to all processors */ 34088fb81238SShri Abhyankar ierr = PetscMalloc2(mmax,PetscInt,&ourlens,mmax,PetscInt,&offlens);CHKERRQ(ierr); 34098fb81238SShri Abhyankar if (!rank) { 34108fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,ourlens,m,PETSC_INT);CHKERRQ(ierr); 34118fb81238SShri Abhyankar ierr = PetscMalloc(m*sizeof(PetscInt),&rowlengths);CHKERRQ(ierr); 34128fb81238SShri Abhyankar ierr = PetscMalloc(size*sizeof(PetscInt),&procsnz);CHKERRQ(ierr); 34138fb81238SShri Abhyankar ierr = PetscMemzero(procsnz,size*sizeof(PetscInt));CHKERRQ(ierr); 34148fb81238SShri Abhyankar for (j=0; j<m; j++) { 34158fb81238SShri Abhyankar procsnz[0] += ourlens[j]; 34168fb81238SShri Abhyankar } 34178fb81238SShri Abhyankar for (i=1; i<size; i++) { 34188fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,rowlengths,rowners[i+1]-rowners[i],PETSC_INT);CHKERRQ(ierr); 34198fb81238SShri Abhyankar /* calculate the number of nonzeros on each processor */ 34208fb81238SShri Abhyankar for (j=0; j<rowners[i+1]-rowners[i]; j++) { 34218fb81238SShri Abhyankar procsnz[i] += rowlengths[j]; 34228fb81238SShri Abhyankar } 3423a25532f0SBarry Smith ierr = MPIULong_Send(rowlengths,rowners[i+1]-rowners[i],MPIU_INT,i,tag,comm);CHKERRQ(ierr); 34248fb81238SShri Abhyankar } 34258fb81238SShri Abhyankar ierr = PetscFree(rowlengths);CHKERRQ(ierr); 34268fb81238SShri Abhyankar } else { 3427a25532f0SBarry Smith ierr = MPIULong_Recv(ourlens,m,MPIU_INT,0,tag,comm);CHKERRQ(ierr); 34288fb81238SShri Abhyankar } 34298fb81238SShri Abhyankar 34308fb81238SShri Abhyankar if (!rank) { 34318fb81238SShri Abhyankar /* determine max buffer needed and allocate it */ 34328fb81238SShri Abhyankar maxnz = 0; 34338fb81238SShri Abhyankar for (i=0; i<size; i++) { 34348fb81238SShri Abhyankar maxnz = PetscMax(maxnz,procsnz[i]); 34358fb81238SShri Abhyankar } 34368fb81238SShri Abhyankar ierr = PetscMalloc(maxnz*sizeof(PetscInt),&cols);CHKERRQ(ierr); 34378fb81238SShri Abhyankar 34388fb81238SShri Abhyankar /* read in my part of the matrix column indices */ 34398fb81238SShri Abhyankar nz = procsnz[0]; 34408fb81238SShri Abhyankar ierr = PetscMalloc(nz*sizeof(PetscInt),&mycols);CHKERRQ(ierr); 34418fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,mycols,nz,PETSC_INT);CHKERRQ(ierr); 34428fb81238SShri Abhyankar 34438fb81238SShri Abhyankar /* read in every one elses and ship off */ 34448fb81238SShri Abhyankar for (i=1; i<size; i++) { 34458fb81238SShri Abhyankar nz = procsnz[i]; 34468fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT);CHKERRQ(ierr); 3447a25532f0SBarry Smith ierr = MPIULong_Send(cols,nz,MPIU_INT,i,tag,comm);CHKERRQ(ierr); 34488fb81238SShri Abhyankar } 34498fb81238SShri Abhyankar ierr = PetscFree(cols);CHKERRQ(ierr); 34508fb81238SShri Abhyankar } else { 34518fb81238SShri Abhyankar /* determine buffer space needed for message */ 34528fb81238SShri Abhyankar nz = 0; 34538fb81238SShri Abhyankar for (i=0; i<m; i++) { 34548fb81238SShri Abhyankar nz += ourlens[i]; 34558fb81238SShri Abhyankar } 34568fb81238SShri Abhyankar ierr = PetscMalloc(nz*sizeof(PetscInt),&mycols);CHKERRQ(ierr); 34578fb81238SShri Abhyankar 34588fb81238SShri Abhyankar /* receive message of column indices*/ 3459a25532f0SBarry Smith ierr = MPIULong_Recv(mycols,nz,MPIU_INT,0,tag,comm);CHKERRQ(ierr); 34608fb81238SShri Abhyankar } 34618fb81238SShri Abhyankar 34628fb81238SShri Abhyankar /* determine column ownership if matrix is not square */ 34638fb81238SShri Abhyankar if (N != M) { 34648fb81238SShri Abhyankar if (newMat->cmap->n < 0) n = N/size + ((N % size) > rank); 34658fb81238SShri Abhyankar else n = newMat->cmap->n; 34668fb81238SShri Abhyankar ierr = MPI_Scan(&n,&cend,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 34678fb81238SShri Abhyankar cstart = cend - n; 34688fb81238SShri Abhyankar } else { 34698fb81238SShri Abhyankar cstart = rstart; 34708fb81238SShri Abhyankar cend = rend; 34718fb81238SShri Abhyankar n = cend - cstart; 34728fb81238SShri Abhyankar } 34738fb81238SShri Abhyankar 34748fb81238SShri Abhyankar /* loop over local rows, determining number of off diagonal entries */ 34758fb81238SShri Abhyankar ierr = PetscMemzero(offlens,m*sizeof(PetscInt));CHKERRQ(ierr); 34768fb81238SShri Abhyankar jj = 0; 34778fb81238SShri Abhyankar for (i=0; i<m; i++) { 34788fb81238SShri Abhyankar for (j=0; j<ourlens[i]; j++) { 34798fb81238SShri Abhyankar if (mycols[jj] < cstart || mycols[jj] >= cend) offlens[i]++; 34808fb81238SShri Abhyankar jj++; 34818fb81238SShri Abhyankar } 34828fb81238SShri Abhyankar } 34838fb81238SShri Abhyankar 34848fb81238SShri Abhyankar for (i=0; i<m; i++) { 34858fb81238SShri Abhyankar ourlens[i] -= offlens[i]; 34868fb81238SShri Abhyankar } 34878fb81238SShri Abhyankar if (!sizesset) { 34888fb81238SShri Abhyankar ierr = MatSetSizes(newMat,m,n,M,N);CHKERRQ(ierr); 34898fb81238SShri Abhyankar } 349008ea439dSMark F. Adams 349108ea439dSMark F. Adams if (bs > 1) {ierr = MatSetBlockSize(newMat,bs);CHKERRQ(ierr);} 349208ea439dSMark F. Adams 34938fb81238SShri Abhyankar ierr = MatMPIAIJSetPreallocation(newMat,0,ourlens,0,offlens);CHKERRQ(ierr); 34948fb81238SShri Abhyankar 34958fb81238SShri Abhyankar for (i=0; i<m; i++) { 34968fb81238SShri Abhyankar ourlens[i] += offlens[i]; 34978fb81238SShri Abhyankar } 34988fb81238SShri Abhyankar 34998fb81238SShri Abhyankar if (!rank) { 35008fb81238SShri Abhyankar ierr = PetscMalloc((maxnz+1)*sizeof(PetscScalar),&vals);CHKERRQ(ierr); 35018fb81238SShri Abhyankar 35028fb81238SShri Abhyankar /* read in my part of the matrix numerical values */ 35038fb81238SShri Abhyankar nz = procsnz[0]; 35048fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr); 35058fb81238SShri Abhyankar 35068fb81238SShri Abhyankar /* insert into matrix */ 35078fb81238SShri Abhyankar jj = rstart; 35088fb81238SShri Abhyankar smycols = mycols; 35098fb81238SShri Abhyankar svals = vals; 35108fb81238SShri Abhyankar for (i=0; i<m; i++) { 35118fb81238SShri Abhyankar ierr = MatSetValues_MPIAIJ(newMat,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr); 35128fb81238SShri Abhyankar smycols += ourlens[i]; 35138fb81238SShri Abhyankar svals += ourlens[i]; 35148fb81238SShri Abhyankar jj++; 35158fb81238SShri Abhyankar } 35168fb81238SShri Abhyankar 35178fb81238SShri Abhyankar /* read in other processors and ship out */ 35188fb81238SShri Abhyankar for (i=1; i<size; i++) { 35198fb81238SShri Abhyankar nz = procsnz[i]; 35208fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr); 3521a25532f0SBarry Smith ierr = MPIULong_Send(vals,nz,MPIU_SCALAR,i,((PetscObject)newMat)->tag,comm);CHKERRQ(ierr); 35228fb81238SShri Abhyankar } 35238fb81238SShri Abhyankar ierr = PetscFree(procsnz);CHKERRQ(ierr); 35248fb81238SShri Abhyankar } else { 35258fb81238SShri Abhyankar /* receive numeric values */ 35268fb81238SShri Abhyankar ierr = PetscMalloc((nz+1)*sizeof(PetscScalar),&vals);CHKERRQ(ierr); 35278fb81238SShri Abhyankar 35288fb81238SShri Abhyankar /* receive message of values*/ 3529a25532f0SBarry Smith ierr = MPIULong_Recv(vals,nz,MPIU_SCALAR,0,((PetscObject)newMat)->tag,comm);CHKERRQ(ierr); 35308fb81238SShri Abhyankar 35318fb81238SShri Abhyankar /* insert into matrix */ 35328fb81238SShri Abhyankar jj = rstart; 35338fb81238SShri Abhyankar smycols = mycols; 35348fb81238SShri Abhyankar svals = vals; 35358fb81238SShri Abhyankar for (i=0; i<m; i++) { 35368fb81238SShri Abhyankar ierr = MatSetValues_MPIAIJ(newMat,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr); 35378fb81238SShri Abhyankar smycols += ourlens[i]; 35388fb81238SShri Abhyankar svals += ourlens[i]; 35398fb81238SShri Abhyankar jj++; 35408fb81238SShri Abhyankar } 35418fb81238SShri Abhyankar } 35428fb81238SShri Abhyankar ierr = PetscFree2(ourlens,offlens);CHKERRQ(ierr); 35438fb81238SShri Abhyankar ierr = PetscFree(vals);CHKERRQ(ierr); 35448fb81238SShri Abhyankar ierr = PetscFree(mycols);CHKERRQ(ierr); 35458fb81238SShri Abhyankar ierr = PetscFree(rowners);CHKERRQ(ierr); 35468fb81238SShri Abhyankar ierr = MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 35478fb81238SShri Abhyankar ierr = MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 354808ea439dSMark F. Adams 35498fb81238SShri Abhyankar PetscFunctionReturn(0); 35508fb81238SShri Abhyankar } 35518fb81238SShri Abhyankar 35528fb81238SShri Abhyankar #undef __FUNCT__ 35534a2ae208SSatish Balay #define __FUNCT__ "MatGetSubMatrix_MPIAIJ" 35544aa3045dSJed Brown PetscErrorCode MatGetSubMatrix_MPIAIJ(Mat mat,IS isrow,IS iscol,MatReuse call,Mat *newmat) 35554aa3045dSJed Brown { 35564aa3045dSJed Brown PetscErrorCode ierr; 35574aa3045dSJed Brown IS iscol_local; 35584aa3045dSJed Brown PetscInt csize; 35594aa3045dSJed Brown 35604aa3045dSJed Brown PetscFunctionBegin; 35614aa3045dSJed Brown ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr); 3562b79d0421SJed Brown if (call == MAT_REUSE_MATRIX) { 3563b79d0421SJed Brown ierr = PetscObjectQuery((PetscObject)*newmat,"ISAllGather",(PetscObject*)&iscol_local);CHKERRQ(ierr); 3564e32f2f54SBarry Smith if (!iscol_local) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Submatrix passed in was not used before, cannot reuse"); 3565b79d0421SJed Brown } else { 3566c5bfad50SMark F. Adams PetscInt cbs; 3567c5bfad50SMark F. Adams ierr = ISGetBlockSize(iscol,&cbs); CHKERRQ(ierr); 35684aa3045dSJed Brown ierr = ISAllGather(iscol,&iscol_local);CHKERRQ(ierr); 3569c5bfad50SMark F. Adams ierr = ISSetBlockSize(iscol_local,cbs); CHKERRQ(ierr); 3570b79d0421SJed Brown } 35714aa3045dSJed Brown ierr = MatGetSubMatrix_MPIAIJ_Private(mat,isrow,iscol_local,csize,call,newmat);CHKERRQ(ierr); 3572b79d0421SJed Brown if (call == MAT_INITIAL_MATRIX) { 3573b79d0421SJed Brown ierr = PetscObjectCompose((PetscObject)*newmat,"ISAllGather",(PetscObject)iscol_local);CHKERRQ(ierr); 35746bf464f9SBarry Smith ierr = ISDestroy(&iscol_local);CHKERRQ(ierr); 3575b79d0421SJed Brown } 35764aa3045dSJed Brown PetscFunctionReturn(0); 35774aa3045dSJed Brown } 35784aa3045dSJed Brown 357929dcf524SDmitry Karpeev extern PetscErrorCode MatGetSubMatrices_MPIAIJ_Local(Mat,PetscInt,const IS[],const IS[],MatReuse,PetscBool*,Mat*); 35804aa3045dSJed Brown #undef __FUNCT__ 35814aa3045dSJed Brown #define __FUNCT__ "MatGetSubMatrix_MPIAIJ_Private" 3582a0ff6018SBarry Smith /* 358329da9460SBarry Smith Not great since it makes two copies of the submatrix, first an SeqAIJ 358429da9460SBarry Smith in local and then by concatenating the local matrices the end result. 358529da9460SBarry Smith Writing it directly would be much like MatGetSubMatrices_MPIAIJ() 35864aa3045dSJed Brown 35874aa3045dSJed Brown Note: This requires a sequential iscol with all indices. 3588a0ff6018SBarry Smith */ 35894aa3045dSJed Brown PetscErrorCode MatGetSubMatrix_MPIAIJ_Private(Mat mat,IS isrow,IS iscol,PetscInt csize,MatReuse call,Mat *newmat) 3590a0ff6018SBarry Smith { 3591dfbe8321SBarry Smith PetscErrorCode ierr; 359232dcc486SBarry Smith PetscMPIInt rank,size; 3593a2f3521dSMark F. Adams PetscInt i,m,n,rstart,row,rend,nz,*cwork,j,bs,cbs; 359429dcf524SDmitry Karpeev PetscInt *ii,*jj,nlocal,*dlens,*olens,dlen,olen,jend,mglobal,ncol; 359529dcf524SDmitry Karpeev PetscBool allcolumns, colflag; 359629dcf524SDmitry Karpeev Mat M,Mreuse; 3597a77337e4SBarry Smith MatScalar *vwork,*aa; 35987adad957SLisandro Dalcin MPI_Comm comm = ((PetscObject)mat)->comm; 359900e6dbe6SBarry Smith Mat_SeqAIJ *aij; 36007e2c5f70SBarry Smith 3601a0ff6018SBarry Smith 3602a0ff6018SBarry Smith PetscFunctionBegin; 36031dab6e02SBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 36041dab6e02SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 360500e6dbe6SBarry Smith 360629dcf524SDmitry Karpeev ierr = ISIdentity(iscol,&colflag);CHKERRQ(ierr); 360729dcf524SDmitry Karpeev ierr = ISGetLocalSize(iscol,&ncol);CHKERRQ(ierr); 360829dcf524SDmitry Karpeev if (colflag && ncol == mat->cmap->N){ 360929dcf524SDmitry Karpeev allcolumns = PETSC_TRUE; 361029dcf524SDmitry Karpeev } else { 361129dcf524SDmitry Karpeev allcolumns = PETSC_FALSE; 361229dcf524SDmitry Karpeev } 3613fee21e36SBarry Smith if (call == MAT_REUSE_MATRIX) { 3614fee21e36SBarry Smith ierr = PetscObjectQuery((PetscObject)*newmat,"SubMatrix",(PetscObject *)&Mreuse);CHKERRQ(ierr); 3615e32f2f54SBarry Smith if (!Mreuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Submatrix passed in was not used before, cannot reuse"); 361629dcf524SDmitry Karpeev ierr = MatGetSubMatrices_MPIAIJ_Local(mat,1,&isrow,&iscol,MAT_REUSE_MATRIX,&allcolumns,&Mreuse);CHKERRQ(ierr); 3617fee21e36SBarry Smith } else { 361829dcf524SDmitry Karpeev ierr = MatGetSubMatrices_MPIAIJ_Local(mat,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&allcolumns,&Mreuse);CHKERRQ(ierr); 3619fee21e36SBarry Smith } 3620a0ff6018SBarry Smith 3621a0ff6018SBarry Smith /* 3622a0ff6018SBarry Smith m - number of local rows 3623a0ff6018SBarry Smith n - number of columns (same on all processors) 3624a0ff6018SBarry Smith rstart - first row in new global matrix generated 3625a0ff6018SBarry Smith */ 3626fee21e36SBarry Smith ierr = MatGetSize(Mreuse,&m,&n);CHKERRQ(ierr); 3627a2f3521dSMark F. Adams ierr = MatGetBlockSizes(Mreuse,&bs,&cbs);CHKERRQ(ierr); 3628a0ff6018SBarry Smith if (call == MAT_INITIAL_MATRIX) { 3629fee21e36SBarry Smith aij = (Mat_SeqAIJ*)(Mreuse)->data; 363000e6dbe6SBarry Smith ii = aij->i; 363100e6dbe6SBarry Smith jj = aij->j; 363200e6dbe6SBarry Smith 3633a0ff6018SBarry Smith /* 363400e6dbe6SBarry Smith Determine the number of non-zeros in the diagonal and off-diagonal 363500e6dbe6SBarry Smith portions of the matrix in order to do correct preallocation 3636a0ff6018SBarry Smith */ 363700e6dbe6SBarry Smith 363800e6dbe6SBarry Smith /* first get start and end of "diagonal" columns */ 36396a6a5d1dSBarry Smith if (csize == PETSC_DECIDE) { 3640ab50ec6bSBarry Smith ierr = ISGetSize(isrow,&mglobal);CHKERRQ(ierr); 3641ab50ec6bSBarry Smith if (mglobal == n) { /* square matrix */ 3642e2c4fddaSBarry Smith nlocal = m; 36436a6a5d1dSBarry Smith } else { 3644ab50ec6bSBarry Smith nlocal = n/size + ((n % size) > rank); 3645ab50ec6bSBarry Smith } 3646ab50ec6bSBarry Smith } else { 36476a6a5d1dSBarry Smith nlocal = csize; 36486a6a5d1dSBarry Smith } 3649b1d57f15SBarry Smith ierr = MPI_Scan(&nlocal,&rend,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 365000e6dbe6SBarry Smith rstart = rend - nlocal; 365165e19b50SBarry Smith if (rank == size - 1 && rend != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local column sizes %D do not add up to total number of columns %D",rend,n); 365200e6dbe6SBarry Smith 365300e6dbe6SBarry Smith /* next, compute all the lengths */ 3654b1d57f15SBarry Smith ierr = PetscMalloc((2*m+1)*sizeof(PetscInt),&dlens);CHKERRQ(ierr); 365500e6dbe6SBarry Smith olens = dlens + m; 365600e6dbe6SBarry Smith for (i=0; i<m; i++) { 365700e6dbe6SBarry Smith jend = ii[i+1] - ii[i]; 365800e6dbe6SBarry Smith olen = 0; 365900e6dbe6SBarry Smith dlen = 0; 366000e6dbe6SBarry Smith for (j=0; j<jend; j++) { 366100e6dbe6SBarry Smith if (*jj < rstart || *jj >= rend) olen++; 366200e6dbe6SBarry Smith else dlen++; 366300e6dbe6SBarry Smith jj++; 366400e6dbe6SBarry Smith } 366500e6dbe6SBarry Smith olens[i] = olen; 366600e6dbe6SBarry Smith dlens[i] = dlen; 366700e6dbe6SBarry Smith } 3668f69a0ea3SMatthew Knepley ierr = MatCreate(comm,&M);CHKERRQ(ierr); 3669f69a0ea3SMatthew Knepley ierr = MatSetSizes(M,m,nlocal,PETSC_DECIDE,n);CHKERRQ(ierr); 3670a2f3521dSMark F. Adams ierr = MatSetBlockSizes(M,bs,cbs); CHKERRQ(ierr); 36717adad957SLisandro Dalcin ierr = MatSetType(M,((PetscObject)mat)->type_name);CHKERRQ(ierr); 3672e2d9671bSKris Buschelman ierr = MatMPIAIJSetPreallocation(M,0,dlens,0,olens);CHKERRQ(ierr); 3673606d414cSSatish Balay ierr = PetscFree(dlens);CHKERRQ(ierr); 3674a0ff6018SBarry Smith } else { 3675b1d57f15SBarry Smith PetscInt ml,nl; 3676a0ff6018SBarry Smith 3677a0ff6018SBarry Smith M = *newmat; 3678a0ff6018SBarry Smith ierr = MatGetLocalSize(M,&ml,&nl);CHKERRQ(ierr); 3679e32f2f54SBarry Smith if (ml != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Previous matrix must be same size/layout as request"); 3680a0ff6018SBarry Smith ierr = MatZeroEntries(M);CHKERRQ(ierr); 3681c48de900SBarry Smith /* 3682c48de900SBarry Smith The next two lines are needed so we may call MatSetValues_MPIAIJ() below directly, 3683c48de900SBarry Smith rather than the slower MatSetValues(). 3684c48de900SBarry Smith */ 3685c48de900SBarry Smith M->was_assembled = PETSC_TRUE; 3686c48de900SBarry Smith M->assembled = PETSC_FALSE; 3687a0ff6018SBarry Smith } 3688a0ff6018SBarry Smith ierr = MatGetOwnershipRange(M,&rstart,&rend);CHKERRQ(ierr); 3689fee21e36SBarry Smith aij = (Mat_SeqAIJ*)(Mreuse)->data; 369000e6dbe6SBarry Smith ii = aij->i; 369100e6dbe6SBarry Smith jj = aij->j; 369200e6dbe6SBarry Smith aa = aij->a; 3693a0ff6018SBarry Smith for (i=0; i<m; i++) { 3694a0ff6018SBarry Smith row = rstart + i; 369500e6dbe6SBarry Smith nz = ii[i+1] - ii[i]; 369600e6dbe6SBarry Smith cwork = jj; jj += nz; 369700e6dbe6SBarry Smith vwork = aa; aa += nz; 36988c638d02SBarry Smith ierr = MatSetValues_MPIAIJ(M,1,&row,nz,cwork,vwork,INSERT_VALUES);CHKERRQ(ierr); 3699a0ff6018SBarry Smith } 3700a0ff6018SBarry Smith 3701a0ff6018SBarry Smith ierr = MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3702a0ff6018SBarry Smith ierr = MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3703a0ff6018SBarry Smith *newmat = M; 3704fee21e36SBarry Smith 3705fee21e36SBarry Smith /* save submatrix used in processor for next request */ 3706fee21e36SBarry Smith if (call == MAT_INITIAL_MATRIX) { 3707fee21e36SBarry Smith ierr = PetscObjectCompose((PetscObject)M,"SubMatrix",(PetscObject)Mreuse);CHKERRQ(ierr); 3708bf0cc555SLisandro Dalcin ierr = MatDestroy(&Mreuse);CHKERRQ(ierr); 3709fee21e36SBarry Smith } 3710fee21e36SBarry Smith 3711a0ff6018SBarry Smith PetscFunctionReturn(0); 3712a0ff6018SBarry Smith } 3713273d9f13SBarry Smith 3714e2e86b8fSSatish Balay EXTERN_C_BEGIN 37154a2ae208SSatish Balay #undef __FUNCT__ 3716ccd8e176SBarry Smith #define __FUNCT__ "MatMPIAIJSetPreallocationCSR_MPIAIJ" 37177087cfbeSBarry Smith PetscErrorCode MatMPIAIJSetPreallocationCSR_MPIAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[]) 3718ccd8e176SBarry Smith { 3719899cda47SBarry Smith PetscInt m,cstart, cend,j,nnz,i,d; 3720899cda47SBarry Smith PetscInt *d_nnz,*o_nnz,nnz_max = 0,rstart,ii; 3721ccd8e176SBarry Smith const PetscInt *JJ; 3722ccd8e176SBarry Smith PetscScalar *values; 3723ccd8e176SBarry Smith PetscErrorCode ierr; 3724ccd8e176SBarry Smith 3725ccd8e176SBarry Smith PetscFunctionBegin; 3726e32f2f54SBarry Smith if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Ii[0] must be 0 it is %D",Ii[0]); 3727899cda47SBarry Smith 372826283091SBarry Smith ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 372926283091SBarry Smith ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 3730d0f46423SBarry Smith m = B->rmap->n; 3731d0f46423SBarry Smith cstart = B->cmap->rstart; 3732d0f46423SBarry Smith cend = B->cmap->rend; 3733d0f46423SBarry Smith rstart = B->rmap->rstart; 3734899cda47SBarry Smith 37351d79065fSBarry Smith ierr = PetscMalloc2(m,PetscInt,&d_nnz,m,PetscInt,&o_nnz);CHKERRQ(ierr); 3736ccd8e176SBarry Smith 3737ecc77c7aSBarry Smith #if defined(PETSC_USE_DEBUGGING) 3738ecc77c7aSBarry Smith for (i=0; i<m; i++) { 3739ecc77c7aSBarry Smith nnz = Ii[i+1]- Ii[i]; 3740ecc77c7aSBarry Smith JJ = J + Ii[i]; 3741e32f2f54SBarry Smith if (nnz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local row %D has a negative %D number of columns",i,nnz); 3742ecc77c7aSBarry Smith if (nnz && (JJ[0] < 0)) SETERRRQ1(PETSC_ERR_ARG_WRONGSTATE,"Row %D starts with negative column index",i,j); 3743d0f46423SBarry Smith if (nnz && (JJ[nnz-1] >= B->cmap->N) SETERRRQ3(PETSC_ERR_ARG_WRONGSTATE,"Row %D ends with too large a column index %D (max allowed %D)",i,JJ[nnz-1],B->cmap->N); 3744ecc77c7aSBarry Smith } 3745ecc77c7aSBarry Smith #endif 3746ecc77c7aSBarry Smith 3747ccd8e176SBarry Smith for (i=0; i<m; i++) { 3748b7940d39SSatish Balay nnz = Ii[i+1]- Ii[i]; 3749b7940d39SSatish Balay JJ = J + Ii[i]; 3750ccd8e176SBarry Smith nnz_max = PetscMax(nnz_max,nnz); 3751ccd8e176SBarry Smith d = 0; 37520daa03b5SJed Brown for (j=0; j<nnz; j++) { 37530daa03b5SJed Brown if (cstart <= JJ[j] && JJ[j] < cend) d++; 3754ccd8e176SBarry Smith } 3755ccd8e176SBarry Smith d_nnz[i] = d; 3756ccd8e176SBarry Smith o_nnz[i] = nnz - d; 3757ccd8e176SBarry Smith } 3758ccd8e176SBarry Smith ierr = MatMPIAIJSetPreallocation(B,0,d_nnz,0,o_nnz);CHKERRQ(ierr); 37591d79065fSBarry Smith ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr); 3760ccd8e176SBarry Smith 3761ccd8e176SBarry Smith if (v) values = (PetscScalar*)v; 3762ccd8e176SBarry Smith else { 3763ccd8e176SBarry Smith ierr = PetscMalloc((nnz_max+1)*sizeof(PetscScalar),&values);CHKERRQ(ierr); 3764ccd8e176SBarry Smith ierr = PetscMemzero(values,nnz_max*sizeof(PetscScalar));CHKERRQ(ierr); 3765ccd8e176SBarry Smith } 3766ccd8e176SBarry Smith 3767ccd8e176SBarry Smith for (i=0; i<m; i++) { 3768ccd8e176SBarry Smith ii = i + rstart; 3769b7940d39SSatish Balay nnz = Ii[i+1]- Ii[i]; 3770b7940d39SSatish Balay ierr = MatSetValues_MPIAIJ(B,1,&ii,nnz,J+Ii[i],values+(v ? Ii[i] : 0),INSERT_VALUES);CHKERRQ(ierr); 3771ccd8e176SBarry Smith } 3772ccd8e176SBarry Smith ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3773ccd8e176SBarry Smith ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3774ccd8e176SBarry Smith 3775ccd8e176SBarry Smith if (!v) { 3776ccd8e176SBarry Smith ierr = PetscFree(values);CHKERRQ(ierr); 3777ccd8e176SBarry Smith } 37787827cd58SJed Brown ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 3779ccd8e176SBarry Smith PetscFunctionReturn(0); 3780ccd8e176SBarry Smith } 3781e2e86b8fSSatish Balay EXTERN_C_END 3782ccd8e176SBarry Smith 3783ccd8e176SBarry Smith #undef __FUNCT__ 3784ccd8e176SBarry Smith #define __FUNCT__ "MatMPIAIJSetPreallocationCSR" 37851eea217eSSatish Balay /*@ 3786ccd8e176SBarry Smith MatMPIAIJSetPreallocationCSR - Allocates memory for a sparse parallel matrix in AIJ format 3787ccd8e176SBarry Smith (the default parallel PETSc format). 3788ccd8e176SBarry Smith 3789ccd8e176SBarry Smith Collective on MPI_Comm 3790ccd8e176SBarry Smith 3791ccd8e176SBarry Smith Input Parameters: 3792a1661176SMatthew Knepley + B - the matrix 3793ccd8e176SBarry Smith . i - the indices into j for the start of each local row (starts with zero) 37940daa03b5SJed Brown . j - the column indices for each local row (starts with zero) 3795ccd8e176SBarry Smith - v - optional values in the matrix 3796ccd8e176SBarry Smith 3797ccd8e176SBarry Smith Level: developer 3798ccd8e176SBarry Smith 379912251496SSatish Balay Notes: 380012251496SSatish Balay The i, j, and a arrays ARE copied by this routine into the internal format used by PETSc; 380112251496SSatish Balay thus you CANNOT change the matrix entries by changing the values of a[] after you have 380212251496SSatish Balay called this routine. Use MatCreateMPIAIJWithSplitArrays() to avoid needing to copy the arrays. 380312251496SSatish Balay 380412251496SSatish Balay The i and j indices are 0 based, and i indices are indices corresponding to the local j array. 380512251496SSatish Balay 380612251496SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 380712251496SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 380812251496SSatish Balay as shown: 380912251496SSatish Balay 381012251496SSatish Balay 1 0 0 381112251496SSatish Balay 2 0 3 P0 381212251496SSatish Balay ------- 381312251496SSatish Balay 4 5 6 P1 381412251496SSatish Balay 381512251496SSatish Balay Process0 [P0]: rows_owned=[0,1] 381612251496SSatish Balay i = {0,1,3} [size = nrow+1 = 2+1] 381712251496SSatish Balay j = {0,0,2} [size = nz = 6] 381812251496SSatish Balay v = {1,2,3} [size = nz = 6] 381912251496SSatish Balay 382012251496SSatish Balay Process1 [P1]: rows_owned=[2] 382112251496SSatish Balay i = {0,3} [size = nrow+1 = 1+1] 382212251496SSatish Balay j = {0,1,2} [size = nz = 6] 382312251496SSatish Balay v = {4,5,6} [size = nz = 6] 382412251496SSatish Balay 3825ccd8e176SBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel 3826ccd8e176SBarry Smith 382769b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatCreateAIJ(), MPIAIJ, 38288d7a6e47SBarry Smith MatCreateSeqAIJWithArrays(), MatCreateMPIAIJWithSplitArrays() 3829ccd8e176SBarry Smith @*/ 38307087cfbeSBarry Smith PetscErrorCode MatMPIAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[], const PetscScalar v[]) 3831ccd8e176SBarry Smith { 38324ac538c5SBarry Smith PetscErrorCode ierr; 3833ccd8e176SBarry Smith 3834ccd8e176SBarry Smith PetscFunctionBegin; 38354ac538c5SBarry Smith ierr = PetscTryMethod(B,"MatMPIAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr); 3836ccd8e176SBarry Smith PetscFunctionReturn(0); 3837ccd8e176SBarry Smith } 3838ccd8e176SBarry Smith 3839ccd8e176SBarry Smith #undef __FUNCT__ 38404a2ae208SSatish Balay #define __FUNCT__ "MatMPIAIJSetPreallocation" 3841273d9f13SBarry Smith /*@C 3842ccd8e176SBarry Smith MatMPIAIJSetPreallocation - Preallocates memory for a sparse parallel matrix in AIJ format 3843273d9f13SBarry Smith (the default parallel PETSc format). For good matrix assembly performance 3844273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameters 3845273d9f13SBarry Smith d_nz (or d_nnz) and o_nz (or o_nnz). By setting these parameters accurately, 3846273d9f13SBarry Smith performance can be increased by more than a factor of 50. 3847273d9f13SBarry Smith 3848273d9f13SBarry Smith Collective on MPI_Comm 3849273d9f13SBarry Smith 3850273d9f13SBarry Smith Input Parameters: 3851273d9f13SBarry Smith + A - the matrix 3852273d9f13SBarry Smith . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 3853273d9f13SBarry Smith (same value is used for all local rows) 3854273d9f13SBarry Smith . d_nnz - array containing the number of nonzeros in the various rows of the 3855273d9f13SBarry Smith DIAGONAL portion of the local submatrix (possibly different for each row) 3856273d9f13SBarry Smith or PETSC_NULL, if d_nz is used to specify the nonzero structure. 3857273d9f13SBarry Smith The size of this array is equal to the number of local rows, i.e 'm'. 38583287b5eaSJed Brown For matrices that will be factored, you must leave room for (and set) 38593287b5eaSJed Brown the diagonal entry even if it is zero. 3860273d9f13SBarry Smith . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 3861273d9f13SBarry Smith submatrix (same value is used for all local rows). 3862273d9f13SBarry Smith - o_nnz - array containing the number of nonzeros in the various rows of the 3863273d9f13SBarry Smith OFF-DIAGONAL portion of the local submatrix (possibly different for 3864273d9f13SBarry Smith each row) or PETSC_NULL, if o_nz is used to specify the nonzero 3865273d9f13SBarry Smith structure. The size of this array is equal to the number 3866273d9f13SBarry Smith of local rows, i.e 'm'. 3867273d9f13SBarry Smith 386849a6f317SBarry Smith If the *_nnz parameter is given then the *_nz parameter is ignored 386949a6f317SBarry Smith 3870273d9f13SBarry Smith The AIJ format (also called the Yale sparse matrix format or 3871ccd8e176SBarry Smith compressed row storage (CSR)), is fully compatible with standard Fortran 77 38720598bfebSBarry Smith storage. The stored row and column indices begin with zero. 38730598bfebSBarry Smith See the <A href="../../docs/manual.pdf#nameddest=ch_mat">Mat chapter of the users manual</A> for details. 3874273d9f13SBarry Smith 3875273d9f13SBarry Smith The parallel matrix is partitioned such that the first m0 rows belong to 3876273d9f13SBarry Smith process 0, the next m1 rows belong to process 1, the next m2 rows belong 3877273d9f13SBarry Smith to process 2 etc.. where m0,m1,m2... are the input parameter 'm'. 3878273d9f13SBarry Smith 3879273d9f13SBarry Smith The DIAGONAL portion of the local submatrix of a processor can be defined 3880a05b864aSJed Brown as the submatrix which is obtained by extraction the part corresponding to 3881a05b864aSJed Brown the rows r1-r2 and columns c1-c2 of the global matrix, where r1 is the 3882a05b864aSJed Brown first row that belongs to the processor, r2 is the last row belonging to 3883a05b864aSJed Brown the this processor, and c1-c2 is range of indices of the local part of a 3884a05b864aSJed Brown vector suitable for applying the matrix to. This is an mxn matrix. In the 3885a05b864aSJed Brown common case of a square matrix, the row and column ranges are the same and 3886a05b864aSJed Brown the DIAGONAL part is also square. The remaining portion of the local 3887a05b864aSJed Brown submatrix (mxN) constitute the OFF-DIAGONAL portion. 3888273d9f13SBarry Smith 3889273d9f13SBarry Smith If o_nnz, d_nnz are specified, then o_nz, and d_nz are ignored. 3890273d9f13SBarry Smith 3891aa95bbe8SBarry Smith You can call MatGetInfo() to get information on how effective the preallocation was; 3892aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3893aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 3894aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 3895aa95bbe8SBarry Smith 3896273d9f13SBarry Smith Example usage: 3897273d9f13SBarry Smith 3898273d9f13SBarry Smith Consider the following 8x8 matrix with 34 non-zero values, that is 3899273d9f13SBarry Smith assembled across 3 processors. Lets assume that proc0 owns 3 rows, 3900273d9f13SBarry Smith proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 3901273d9f13SBarry Smith as follows: 3902273d9f13SBarry Smith 3903273d9f13SBarry Smith .vb 3904273d9f13SBarry Smith 1 2 0 | 0 3 0 | 0 4 3905273d9f13SBarry Smith Proc0 0 5 6 | 7 0 0 | 8 0 3906273d9f13SBarry Smith 9 0 10 | 11 0 0 | 12 0 3907273d9f13SBarry Smith ------------------------------------- 3908273d9f13SBarry Smith 13 0 14 | 15 16 17 | 0 0 3909273d9f13SBarry Smith Proc1 0 18 0 | 19 20 21 | 0 0 3910273d9f13SBarry Smith 0 0 0 | 22 23 0 | 24 0 3911273d9f13SBarry Smith ------------------------------------- 3912273d9f13SBarry Smith Proc2 25 26 27 | 0 0 28 | 29 0 3913273d9f13SBarry Smith 30 0 0 | 31 32 33 | 0 34 3914273d9f13SBarry Smith .ve 3915273d9f13SBarry Smith 3916273d9f13SBarry Smith This can be represented as a collection of submatrices as: 3917273d9f13SBarry Smith 3918273d9f13SBarry Smith .vb 3919273d9f13SBarry Smith A B C 3920273d9f13SBarry Smith D E F 3921273d9f13SBarry Smith G H I 3922273d9f13SBarry Smith .ve 3923273d9f13SBarry Smith 3924273d9f13SBarry Smith Where the submatrices A,B,C are owned by proc0, D,E,F are 3925273d9f13SBarry Smith owned by proc1, G,H,I are owned by proc2. 3926273d9f13SBarry Smith 3927273d9f13SBarry Smith The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 3928273d9f13SBarry Smith The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 3929273d9f13SBarry Smith The 'M','N' parameters are 8,8, and have the same values on all procs. 3930273d9f13SBarry Smith 3931273d9f13SBarry Smith The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are 3932273d9f13SBarry Smith submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices 3933273d9f13SBarry Smith corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively. 3934273d9f13SBarry Smith Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL 3935273d9f13SBarry Smith part as SeqAIJ matrices. for eg: proc1 will store [E] as a SeqAIJ 3936273d9f13SBarry Smith matrix, ans [DF] as another SeqAIJ matrix. 3937273d9f13SBarry Smith 3938273d9f13SBarry Smith When d_nz, o_nz parameters are specified, d_nz storage elements are 3939273d9f13SBarry Smith allocated for every row of the local diagonal submatrix, and o_nz 3940273d9f13SBarry Smith storage locations are allocated for every row of the OFF-DIAGONAL submat. 3941273d9f13SBarry Smith One way to choose d_nz and o_nz is to use the max nonzerors per local 3942273d9f13SBarry Smith rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices. 3943273d9f13SBarry Smith In this case, the values of d_nz,o_nz are: 3944273d9f13SBarry Smith .vb 3945273d9f13SBarry Smith proc0 : dnz = 2, o_nz = 2 3946273d9f13SBarry Smith proc1 : dnz = 3, o_nz = 2 3947273d9f13SBarry Smith proc2 : dnz = 1, o_nz = 4 3948273d9f13SBarry Smith .ve 3949273d9f13SBarry Smith We are allocating m*(d_nz+o_nz) storage locations for every proc. This 3950273d9f13SBarry Smith translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10 3951273d9f13SBarry Smith for proc3. i.e we are using 12+15+10=37 storage locations to store 3952273d9f13SBarry Smith 34 values. 3953273d9f13SBarry Smith 3954273d9f13SBarry Smith When d_nnz, o_nnz parameters are specified, the storage is specified 3955273d9f13SBarry Smith for every row, coresponding to both DIAGONAL and OFF-DIAGONAL submatrices. 3956273d9f13SBarry Smith In the above case the values for d_nnz,o_nnz are: 3957273d9f13SBarry Smith .vb 3958273d9f13SBarry Smith proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2] 3959273d9f13SBarry Smith proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1] 3960273d9f13SBarry Smith proc2: d_nnz = [1,1] and o_nnz = [4,4] 3961273d9f13SBarry Smith .ve 3962273d9f13SBarry Smith Here the space allocated is sum of all the above values i.e 34, and 3963273d9f13SBarry Smith hence pre-allocation is perfect. 3964273d9f13SBarry Smith 3965273d9f13SBarry Smith Level: intermediate 3966273d9f13SBarry Smith 3967273d9f13SBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel 3968273d9f13SBarry Smith 396969b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateAIJ(), MatMPIAIJSetPreallocationCSR(), 3970aa95bbe8SBarry Smith MPIAIJ, MatGetInfo() 3971273d9f13SBarry Smith @*/ 39727087cfbeSBarry Smith PetscErrorCode MatMPIAIJSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 3973273d9f13SBarry Smith { 39744ac538c5SBarry Smith PetscErrorCode ierr; 3975273d9f13SBarry Smith 3976273d9f13SBarry Smith PetscFunctionBegin; 39776ba663aaSJed Brown PetscValidHeaderSpecific(B,MAT_CLASSID,1); 39786ba663aaSJed Brown PetscValidType(B,1); 39794ac538c5SBarry Smith ierr = PetscTryMethod(B,"MatMPIAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr); 3980273d9f13SBarry Smith PetscFunctionReturn(0); 3981273d9f13SBarry Smith } 3982273d9f13SBarry Smith 39834a2ae208SSatish Balay #undef __FUNCT__ 39842fb0ec9aSBarry Smith #define __FUNCT__ "MatCreateMPIAIJWithArrays" 398558d36128SBarry Smith /*@ 39862fb0ec9aSBarry Smith MatCreateMPIAIJWithArrays - creates a MPI AIJ matrix using arrays that contain in standard 39872fb0ec9aSBarry Smith CSR format the local rows. 39882fb0ec9aSBarry Smith 39892fb0ec9aSBarry Smith Collective on MPI_Comm 39902fb0ec9aSBarry Smith 39912fb0ec9aSBarry Smith Input Parameters: 39922fb0ec9aSBarry Smith + comm - MPI communicator 39932fb0ec9aSBarry Smith . m - number of local rows (Cannot be PETSC_DECIDE) 39942fb0ec9aSBarry Smith . n - This value should be the same as the local size used in creating the 39952fb0ec9aSBarry Smith x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have 39962fb0ec9aSBarry Smith calculated if N is given) For square matrices n is almost always m. 39972fb0ec9aSBarry Smith . M - number of global rows (or PETSC_DETERMINE to have calculated if m is given) 39982fb0ec9aSBarry Smith . N - number of global columns (or PETSC_DETERMINE to have calculated if n is given) 39992fb0ec9aSBarry Smith . i - row indices 40002fb0ec9aSBarry Smith . j - column indices 40012fb0ec9aSBarry Smith - a - matrix values 40022fb0ec9aSBarry Smith 40032fb0ec9aSBarry Smith Output Parameter: 40042fb0ec9aSBarry Smith . mat - the matrix 400503bfb495SBarry Smith 40062fb0ec9aSBarry Smith Level: intermediate 40072fb0ec9aSBarry Smith 40082fb0ec9aSBarry Smith Notes: 40092fb0ec9aSBarry Smith The i, j, and a arrays ARE copied by this routine into the internal format used by PETSc; 40102fb0ec9aSBarry Smith thus you CANNOT change the matrix entries by changing the values of a[] after you have 40118d7a6e47SBarry Smith called this routine. Use MatCreateMPIAIJWithSplitArrays() to avoid needing to copy the arrays. 40122fb0ec9aSBarry Smith 401312251496SSatish Balay The i and j indices are 0 based, and i indices are indices corresponding to the local j array. 401412251496SSatish Balay 401512251496SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 401612251496SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 401712251496SSatish Balay as shown: 401812251496SSatish Balay 401912251496SSatish Balay 1 0 0 402012251496SSatish Balay 2 0 3 P0 402112251496SSatish Balay ------- 402212251496SSatish Balay 4 5 6 P1 402312251496SSatish Balay 402412251496SSatish Balay Process0 [P0]: rows_owned=[0,1] 402512251496SSatish Balay i = {0,1,3} [size = nrow+1 = 2+1] 402612251496SSatish Balay j = {0,0,2} [size = nz = 6] 402712251496SSatish Balay v = {1,2,3} [size = nz = 6] 402812251496SSatish Balay 402912251496SSatish Balay Process1 [P1]: rows_owned=[2] 403012251496SSatish Balay i = {0,3} [size = nrow+1 = 1+1] 403112251496SSatish Balay j = {0,1,2} [size = nz = 6] 403212251496SSatish Balay v = {4,5,6} [size = nz = 6] 40332fb0ec9aSBarry Smith 40342fb0ec9aSBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel 40352fb0ec9aSBarry Smith 40362fb0ec9aSBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(), 403769b1f4b7SBarry Smith MPIAIJ, MatCreateAIJ(), MatCreateMPIAIJWithSplitArrays() 40382fb0ec9aSBarry Smith @*/ 40397087cfbeSBarry Smith PetscErrorCode MatCreateMPIAIJWithArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,const PetscInt i[],const PetscInt j[],const PetscScalar a[],Mat *mat) 40402fb0ec9aSBarry Smith { 40412fb0ec9aSBarry Smith PetscErrorCode ierr; 40422fb0ec9aSBarry Smith 40432fb0ec9aSBarry Smith PetscFunctionBegin; 404469b1f4b7SBarry Smith if (i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 4045e32f2f54SBarry Smith if (m < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"local number of rows (m) cannot be PETSC_DECIDE, or negative"); 40462fb0ec9aSBarry Smith ierr = MatCreate(comm,mat);CHKERRQ(ierr); 4047d4146a68SBarry Smith ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr); 4048a2f3521dSMark F. Adams /* ierr = MatSetBlockSizes(M,bs,cbs); CHKERRQ(ierr); */ 40492fb0ec9aSBarry Smith ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr); 40502fb0ec9aSBarry Smith ierr = MatMPIAIJSetPreallocationCSR(*mat,i,j,a);CHKERRQ(ierr); 40512fb0ec9aSBarry Smith PetscFunctionReturn(0); 40522fb0ec9aSBarry Smith } 40532fb0ec9aSBarry Smith 40542fb0ec9aSBarry Smith #undef __FUNCT__ 405569b1f4b7SBarry Smith #define __FUNCT__ "MatCreateAIJ" 4056273d9f13SBarry Smith /*@C 405769b1f4b7SBarry Smith MatCreateAIJ - Creates a sparse parallel matrix in AIJ format 4058273d9f13SBarry Smith (the default parallel PETSc format). For good matrix assembly performance 4059273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameters 4060273d9f13SBarry Smith d_nz (or d_nnz) and o_nz (or o_nnz). By setting these parameters accurately, 4061273d9f13SBarry Smith performance can be increased by more than a factor of 50. 4062273d9f13SBarry Smith 4063273d9f13SBarry Smith Collective on MPI_Comm 4064273d9f13SBarry Smith 4065273d9f13SBarry Smith Input Parameters: 4066273d9f13SBarry Smith + comm - MPI communicator 4067273d9f13SBarry Smith . m - number of local rows (or PETSC_DECIDE to have calculated if M is given) 4068273d9f13SBarry Smith This value should be the same as the local size used in creating the 4069273d9f13SBarry Smith y vector for the matrix-vector product y = Ax. 4070273d9f13SBarry Smith . n - This value should be the same as the local size used in creating the 4071273d9f13SBarry Smith x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have 4072273d9f13SBarry Smith calculated if N is given) For square matrices n is almost always m. 4073273d9f13SBarry Smith . M - number of global rows (or PETSC_DETERMINE to have calculated if m is given) 4074273d9f13SBarry Smith . N - number of global columns (or PETSC_DETERMINE to have calculated if n is given) 4075273d9f13SBarry Smith . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 4076273d9f13SBarry Smith (same value is used for all local rows) 4077273d9f13SBarry Smith . d_nnz - array containing the number of nonzeros in the various rows of the 4078273d9f13SBarry Smith DIAGONAL portion of the local submatrix (possibly different for each row) 4079273d9f13SBarry Smith or PETSC_NULL, if d_nz is used to specify the nonzero structure. 4080273d9f13SBarry Smith The size of this array is equal to the number of local rows, i.e 'm'. 4081273d9f13SBarry Smith . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 4082273d9f13SBarry Smith submatrix (same value is used for all local rows). 4083273d9f13SBarry Smith - o_nnz - array containing the number of nonzeros in the various rows of the 4084273d9f13SBarry Smith OFF-DIAGONAL portion of the local submatrix (possibly different for 4085273d9f13SBarry Smith each row) or PETSC_NULL, if o_nz is used to specify the nonzero 4086273d9f13SBarry Smith structure. The size of this array is equal to the number 4087273d9f13SBarry Smith of local rows, i.e 'm'. 4088273d9f13SBarry Smith 4089273d9f13SBarry Smith Output Parameter: 4090273d9f13SBarry Smith . A - the matrix 4091273d9f13SBarry Smith 4092175b88e8SBarry Smith It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 4093ae1d86c5SBarry Smith MatXXXXSetPreallocation() paradgm instead of this routine directly. 4094175b88e8SBarry Smith [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 4095175b88e8SBarry Smith 4096273d9f13SBarry Smith Notes: 409749a6f317SBarry Smith If the *_nnz parameter is given then the *_nz parameter is ignored 409849a6f317SBarry Smith 4099273d9f13SBarry Smith m,n,M,N parameters specify the size of the matrix, and its partitioning across 4100273d9f13SBarry Smith processors, while d_nz,d_nnz,o_nz,o_nnz parameters specify the approximate 4101273d9f13SBarry Smith storage requirements for this matrix. 4102273d9f13SBarry Smith 4103273d9f13SBarry Smith If PETSC_DECIDE or PETSC_DETERMINE is used for a particular argument on one 4104273d9f13SBarry Smith processor than it must be used on all processors that share the object for 4105273d9f13SBarry Smith that argument. 4106273d9f13SBarry Smith 4107273d9f13SBarry Smith The user MUST specify either the local or global matrix dimensions 4108273d9f13SBarry Smith (possibly both). 4109273d9f13SBarry Smith 411033a7c187SSatish Balay The parallel matrix is partitioned across processors such that the 411133a7c187SSatish Balay first m0 rows belong to process 0, the next m1 rows belong to 411233a7c187SSatish Balay process 1, the next m2 rows belong to process 2 etc.. where 411333a7c187SSatish Balay m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores 411433a7c187SSatish Balay values corresponding to [m x N] submatrix. 4115273d9f13SBarry Smith 411633a7c187SSatish Balay The columns are logically partitioned with the n0 columns belonging 411733a7c187SSatish Balay to 0th partition, the next n1 columns belonging to the next 411833a7c187SSatish Balay partition etc.. where n0,n1,n2... are the the input parameter 'n'. 411933a7c187SSatish Balay 412033a7c187SSatish Balay The DIAGONAL portion of the local submatrix on any given processor 412133a7c187SSatish Balay is the submatrix corresponding to the rows and columns m,n 412233a7c187SSatish Balay corresponding to the given processor. i.e diagonal matrix on 412333a7c187SSatish Balay process 0 is [m0 x n0], diagonal matrix on process 1 is [m1 x n1] 412433a7c187SSatish Balay etc. The remaining portion of the local submatrix [m x (N-n)] 412533a7c187SSatish Balay constitute the OFF-DIAGONAL portion. The example below better 412633a7c187SSatish Balay illustrates this concept. 412733a7c187SSatish Balay 412833a7c187SSatish Balay For a square global matrix we define each processor's diagonal portion 412933a7c187SSatish Balay to be its local rows and the corresponding columns (a square submatrix); 413033a7c187SSatish Balay each processor's off-diagonal portion encompasses the remainder of the 413133a7c187SSatish Balay local matrix (a rectangular submatrix). 4132273d9f13SBarry Smith 4133273d9f13SBarry Smith If o_nnz, d_nnz are specified, then o_nz, and d_nz are ignored. 4134273d9f13SBarry Smith 413597d05335SKris Buschelman When calling this routine with a single process communicator, a matrix of 413697d05335SKris Buschelman type SEQAIJ is returned. If a matrix of type MPIAIJ is desired for this 413797d05335SKris Buschelman type of communicator, use the construction mechanism: 413878102f6cSMatthew Knepley MatCreate(...,&A); MatSetType(A,MATMPIAIJ); MatSetSizes(A, m,n,M,N); MatMPIAIJSetPreallocation(A,...); 413997d05335SKris Buschelman 4140273d9f13SBarry Smith By default, this format uses inodes (identical nodes) when possible. 4141273d9f13SBarry Smith We search for consecutive rows with the same nonzero structure, thereby 4142273d9f13SBarry Smith reusing matrix information to achieve increased efficiency. 4143273d9f13SBarry Smith 4144273d9f13SBarry Smith Options Database Keys: 4145923f20ffSKris Buschelman + -mat_no_inode - Do not use inodes 4146923f20ffSKris Buschelman . -mat_inode_limit <limit> - Sets inode limit (max limit=5) 4147273d9f13SBarry Smith - -mat_aij_oneindex - Internally use indexing starting at 1 4148273d9f13SBarry Smith rather than 0. Note that when calling MatSetValues(), 4149273d9f13SBarry Smith the user still MUST index entries starting at 0! 4150273d9f13SBarry Smith 4151273d9f13SBarry Smith 4152273d9f13SBarry Smith Example usage: 4153273d9f13SBarry Smith 4154273d9f13SBarry Smith Consider the following 8x8 matrix with 34 non-zero values, that is 4155273d9f13SBarry Smith assembled across 3 processors. Lets assume that proc0 owns 3 rows, 4156273d9f13SBarry Smith proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 4157273d9f13SBarry Smith as follows: 4158273d9f13SBarry Smith 4159273d9f13SBarry Smith .vb 4160273d9f13SBarry Smith 1 2 0 | 0 3 0 | 0 4 4161273d9f13SBarry Smith Proc0 0 5 6 | 7 0 0 | 8 0 4162273d9f13SBarry Smith 9 0 10 | 11 0 0 | 12 0 4163273d9f13SBarry Smith ------------------------------------- 4164273d9f13SBarry Smith 13 0 14 | 15 16 17 | 0 0 4165273d9f13SBarry Smith Proc1 0 18 0 | 19 20 21 | 0 0 4166273d9f13SBarry Smith 0 0 0 | 22 23 0 | 24 0 4167273d9f13SBarry Smith ------------------------------------- 4168273d9f13SBarry Smith Proc2 25 26 27 | 0 0 28 | 29 0 4169273d9f13SBarry Smith 30 0 0 | 31 32 33 | 0 34 4170273d9f13SBarry Smith .ve 4171273d9f13SBarry Smith 4172273d9f13SBarry Smith This can be represented as a collection of submatrices as: 4173273d9f13SBarry Smith 4174273d9f13SBarry Smith .vb 4175273d9f13SBarry Smith A B C 4176273d9f13SBarry Smith D E F 4177273d9f13SBarry Smith G H I 4178273d9f13SBarry Smith .ve 4179273d9f13SBarry Smith 4180273d9f13SBarry Smith Where the submatrices A,B,C are owned by proc0, D,E,F are 4181273d9f13SBarry Smith owned by proc1, G,H,I are owned by proc2. 4182273d9f13SBarry Smith 4183273d9f13SBarry Smith The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 4184273d9f13SBarry Smith The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 4185273d9f13SBarry Smith The 'M','N' parameters are 8,8, and have the same values on all procs. 4186273d9f13SBarry Smith 4187273d9f13SBarry Smith The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are 4188273d9f13SBarry Smith submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices 4189273d9f13SBarry Smith corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively. 4190273d9f13SBarry Smith Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL 4191273d9f13SBarry Smith part as SeqAIJ matrices. for eg: proc1 will store [E] as a SeqAIJ 4192273d9f13SBarry Smith matrix, ans [DF] as another SeqAIJ matrix. 4193273d9f13SBarry Smith 4194273d9f13SBarry Smith When d_nz, o_nz parameters are specified, d_nz storage elements are 4195273d9f13SBarry Smith allocated for every row of the local diagonal submatrix, and o_nz 4196273d9f13SBarry Smith storage locations are allocated for every row of the OFF-DIAGONAL submat. 4197273d9f13SBarry Smith One way to choose d_nz and o_nz is to use the max nonzerors per local 4198273d9f13SBarry Smith rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices. 4199273d9f13SBarry Smith In this case, the values of d_nz,o_nz are: 4200273d9f13SBarry Smith .vb 4201273d9f13SBarry Smith proc0 : dnz = 2, o_nz = 2 4202273d9f13SBarry Smith proc1 : dnz = 3, o_nz = 2 4203273d9f13SBarry Smith proc2 : dnz = 1, o_nz = 4 4204273d9f13SBarry Smith .ve 4205273d9f13SBarry Smith We are allocating m*(d_nz+o_nz) storage locations for every proc. This 4206273d9f13SBarry Smith translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10 4207273d9f13SBarry Smith for proc3. i.e we are using 12+15+10=37 storage locations to store 4208273d9f13SBarry Smith 34 values. 4209273d9f13SBarry Smith 4210273d9f13SBarry Smith When d_nnz, o_nnz parameters are specified, the storage is specified 4211273d9f13SBarry Smith for every row, coresponding to both DIAGONAL and OFF-DIAGONAL submatrices. 4212273d9f13SBarry Smith In the above case the values for d_nnz,o_nnz are: 4213273d9f13SBarry Smith .vb 4214273d9f13SBarry Smith proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2] 4215273d9f13SBarry Smith proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1] 4216273d9f13SBarry Smith proc2: d_nnz = [1,1] and o_nnz = [4,4] 4217273d9f13SBarry Smith .ve 4218273d9f13SBarry Smith Here the space allocated is sum of all the above values i.e 34, and 4219273d9f13SBarry Smith hence pre-allocation is perfect. 4220273d9f13SBarry Smith 4221273d9f13SBarry Smith Level: intermediate 4222273d9f13SBarry Smith 4223273d9f13SBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel 4224273d9f13SBarry Smith 4225ccd8e176SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(), 42262fb0ec9aSBarry Smith MPIAIJ, MatCreateMPIAIJWithArrays() 4227273d9f13SBarry Smith @*/ 422869b1f4b7SBarry Smith PetscErrorCode MatCreateAIJ(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[],Mat *A) 4229273d9f13SBarry Smith { 42306849ba73SBarry Smith PetscErrorCode ierr; 4231b1d57f15SBarry Smith PetscMPIInt size; 4232273d9f13SBarry Smith 4233273d9f13SBarry Smith PetscFunctionBegin; 4234f69a0ea3SMatthew Knepley ierr = MatCreate(comm,A);CHKERRQ(ierr); 4235f69a0ea3SMatthew Knepley ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); 4236273d9f13SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 4237273d9f13SBarry Smith if (size > 1) { 4238273d9f13SBarry Smith ierr = MatSetType(*A,MATMPIAIJ);CHKERRQ(ierr); 4239273d9f13SBarry Smith ierr = MatMPIAIJSetPreallocation(*A,d_nz,d_nnz,o_nz,o_nnz);CHKERRQ(ierr); 4240273d9f13SBarry Smith } else { 4241273d9f13SBarry Smith ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr); 4242273d9f13SBarry Smith ierr = MatSeqAIJSetPreallocation(*A,d_nz,d_nnz);CHKERRQ(ierr); 4243273d9f13SBarry Smith } 4244273d9f13SBarry Smith PetscFunctionReturn(0); 4245273d9f13SBarry Smith } 4246195d93cdSBarry Smith 42474a2ae208SSatish Balay #undef __FUNCT__ 42484a2ae208SSatish Balay #define __FUNCT__ "MatMPIAIJGetSeqAIJ" 42497087cfbeSBarry Smith PetscErrorCode MatMPIAIJGetSeqAIJ(Mat A,Mat *Ad,Mat *Ao,PetscInt *colmap[]) 4250195d93cdSBarry Smith { 4251195d93cdSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ *)A->data; 4252b1d57f15SBarry Smith 4253195d93cdSBarry Smith PetscFunctionBegin; 4254195d93cdSBarry Smith *Ad = a->A; 4255195d93cdSBarry Smith *Ao = a->B; 4256195d93cdSBarry Smith *colmap = a->garray; 4257195d93cdSBarry Smith PetscFunctionReturn(0); 4258195d93cdSBarry Smith } 4259a2243be0SBarry Smith 4260a2243be0SBarry Smith #undef __FUNCT__ 4261a2243be0SBarry Smith #define __FUNCT__ "MatSetColoring_MPIAIJ" 4262dfbe8321SBarry Smith PetscErrorCode MatSetColoring_MPIAIJ(Mat A,ISColoring coloring) 4263a2243be0SBarry Smith { 4264dfbe8321SBarry Smith PetscErrorCode ierr; 4265b1d57f15SBarry Smith PetscInt i; 4266a2243be0SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 4267a2243be0SBarry Smith 4268a2243be0SBarry Smith PetscFunctionBegin; 42698ee2e534SBarry Smith if (coloring->ctype == IS_COLORING_GLOBAL) { 427008b6dcc0SBarry Smith ISColoringValue *allcolors,*colors; 4271a2243be0SBarry Smith ISColoring ocoloring; 4272a2243be0SBarry Smith 4273a2243be0SBarry Smith /* set coloring for diagonal portion */ 4274a2243be0SBarry Smith ierr = MatSetColoring_SeqAIJ(a->A,coloring);CHKERRQ(ierr); 4275a2243be0SBarry Smith 4276a2243be0SBarry Smith /* set coloring for off-diagonal portion */ 42777adad957SLisandro Dalcin ierr = ISAllGatherColors(((PetscObject)A)->comm,coloring->n,coloring->colors,PETSC_NULL,&allcolors);CHKERRQ(ierr); 4278d0f46423SBarry Smith ierr = PetscMalloc((a->B->cmap->n+1)*sizeof(ISColoringValue),&colors);CHKERRQ(ierr); 4279d0f46423SBarry Smith for (i=0; i<a->B->cmap->n; i++) { 4280a2243be0SBarry Smith colors[i] = allcolors[a->garray[i]]; 4281a2243be0SBarry Smith } 4282a2243be0SBarry Smith ierr = PetscFree(allcolors);CHKERRQ(ierr); 4283d0f46423SBarry Smith ierr = ISColoringCreate(MPI_COMM_SELF,coloring->n,a->B->cmap->n,colors,&ocoloring);CHKERRQ(ierr); 4284a2243be0SBarry Smith ierr = MatSetColoring_SeqAIJ(a->B,ocoloring);CHKERRQ(ierr); 42856bf464f9SBarry Smith ierr = ISColoringDestroy(&ocoloring);CHKERRQ(ierr); 4286a2243be0SBarry Smith } else if (coloring->ctype == IS_COLORING_GHOSTED) { 428708b6dcc0SBarry Smith ISColoringValue *colors; 4288b1d57f15SBarry Smith PetscInt *larray; 4289a2243be0SBarry Smith ISColoring ocoloring; 4290a2243be0SBarry Smith 4291a2243be0SBarry Smith /* set coloring for diagonal portion */ 4292d0f46423SBarry Smith ierr = PetscMalloc((a->A->cmap->n+1)*sizeof(PetscInt),&larray);CHKERRQ(ierr); 4293d0f46423SBarry Smith for (i=0; i<a->A->cmap->n; i++) { 4294d0f46423SBarry Smith larray[i] = i + A->cmap->rstart; 4295a2243be0SBarry Smith } 4296992144d0SBarry Smith ierr = ISGlobalToLocalMappingApply(A->cmap->mapping,IS_GTOLM_MASK,a->A->cmap->n,larray,PETSC_NULL,larray);CHKERRQ(ierr); 4297d0f46423SBarry Smith ierr = PetscMalloc((a->A->cmap->n+1)*sizeof(ISColoringValue),&colors);CHKERRQ(ierr); 4298d0f46423SBarry Smith for (i=0; i<a->A->cmap->n; i++) { 4299a2243be0SBarry Smith colors[i] = coloring->colors[larray[i]]; 4300a2243be0SBarry Smith } 4301a2243be0SBarry Smith ierr = PetscFree(larray);CHKERRQ(ierr); 4302d0f46423SBarry Smith ierr = ISColoringCreate(PETSC_COMM_SELF,coloring->n,a->A->cmap->n,colors,&ocoloring);CHKERRQ(ierr); 4303a2243be0SBarry Smith ierr = MatSetColoring_SeqAIJ(a->A,ocoloring);CHKERRQ(ierr); 43046bf464f9SBarry Smith ierr = ISColoringDestroy(&ocoloring);CHKERRQ(ierr); 4305a2243be0SBarry Smith 4306a2243be0SBarry Smith /* set coloring for off-diagonal portion */ 4307d0f46423SBarry Smith ierr = PetscMalloc((a->B->cmap->n+1)*sizeof(PetscInt),&larray);CHKERRQ(ierr); 4308992144d0SBarry Smith ierr = ISGlobalToLocalMappingApply(A->cmap->mapping,IS_GTOLM_MASK,a->B->cmap->n,a->garray,PETSC_NULL,larray);CHKERRQ(ierr); 4309d0f46423SBarry Smith ierr = PetscMalloc((a->B->cmap->n+1)*sizeof(ISColoringValue),&colors);CHKERRQ(ierr); 4310d0f46423SBarry Smith for (i=0; i<a->B->cmap->n; i++) { 4311a2243be0SBarry Smith colors[i] = coloring->colors[larray[i]]; 4312a2243be0SBarry Smith } 4313a2243be0SBarry Smith ierr = PetscFree(larray);CHKERRQ(ierr); 4314d0f46423SBarry Smith ierr = ISColoringCreate(MPI_COMM_SELF,coloring->n,a->B->cmap->n,colors,&ocoloring);CHKERRQ(ierr); 4315a2243be0SBarry Smith ierr = MatSetColoring_SeqAIJ(a->B,ocoloring);CHKERRQ(ierr); 43166bf464f9SBarry Smith ierr = ISColoringDestroy(&ocoloring);CHKERRQ(ierr); 43176bf464f9SBarry Smith } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support ISColoringType %d",(int)coloring->ctype); 4318a2243be0SBarry Smith 4319a2243be0SBarry Smith PetscFunctionReturn(0); 4320a2243be0SBarry Smith } 4321a2243be0SBarry Smith 4322dcf5cc72SBarry Smith #if defined(PETSC_HAVE_ADIC) 4323a2243be0SBarry Smith #undef __FUNCT__ 4324779c1a83SBarry Smith #define __FUNCT__ "MatSetValuesAdic_MPIAIJ" 4325dfbe8321SBarry Smith PetscErrorCode MatSetValuesAdic_MPIAIJ(Mat A,void *advalues) 4326a2243be0SBarry Smith { 4327a2243be0SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 4328dfbe8321SBarry Smith PetscErrorCode ierr; 4329a2243be0SBarry Smith 4330a2243be0SBarry Smith PetscFunctionBegin; 4331779c1a83SBarry Smith ierr = MatSetValuesAdic_SeqAIJ(a->A,advalues);CHKERRQ(ierr); 4332779c1a83SBarry Smith ierr = MatSetValuesAdic_SeqAIJ(a->B,advalues);CHKERRQ(ierr); 4333779c1a83SBarry Smith PetscFunctionReturn(0); 4334779c1a83SBarry Smith } 4335dcf5cc72SBarry Smith #endif 4336779c1a83SBarry Smith 4337779c1a83SBarry Smith #undef __FUNCT__ 4338779c1a83SBarry Smith #define __FUNCT__ "MatSetValuesAdifor_MPIAIJ" 4339b1d57f15SBarry Smith PetscErrorCode MatSetValuesAdifor_MPIAIJ(Mat A,PetscInt nl,void *advalues) 4340779c1a83SBarry Smith { 4341779c1a83SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 4342dfbe8321SBarry Smith PetscErrorCode ierr; 4343779c1a83SBarry Smith 4344779c1a83SBarry Smith PetscFunctionBegin; 4345779c1a83SBarry Smith ierr = MatSetValuesAdifor_SeqAIJ(a->A,nl,advalues);CHKERRQ(ierr); 4346779c1a83SBarry Smith ierr = MatSetValuesAdifor_SeqAIJ(a->B,nl,advalues);CHKERRQ(ierr); 4347a2243be0SBarry Smith PetscFunctionReturn(0); 4348a2243be0SBarry Smith } 4349c5d6d63eSBarry Smith 4350c5d6d63eSBarry Smith #undef __FUNCT__ 435190431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJConcatenateSeqAIJSymbolic" 435290431a8fSHong Zhang PetscErrorCode MatCreateMPIAIJConcatenateSeqAIJSymbolic(MPI_Comm comm,Mat inmat,PetscInt n,Mat *outmat) 43539b8102ccSHong Zhang { 43549b8102ccSHong Zhang PetscErrorCode ierr; 4355a2f3521dSMark F. Adams PetscInt m,N,i,rstart,nnz,*dnz,*onz,sum,bs,cbs; 43569b8102ccSHong Zhang PetscInt *indx; 43579b8102ccSHong Zhang 43589b8102ccSHong Zhang PetscFunctionBegin; 43599b8102ccSHong Zhang /* This routine will ONLY return MPIAIJ type matrix */ 43609b8102ccSHong Zhang ierr = MatGetSize(inmat,&m,&N);CHKERRQ(ierr); 4361a2f3521dSMark F. Adams ierr = MatGetBlockSizes(inmat,&bs,&cbs);CHKERRQ(ierr); 43629b8102ccSHong Zhang if (n == PETSC_DECIDE){ 43639b8102ccSHong Zhang ierr = PetscSplitOwnership(comm,&n,&N);CHKERRQ(ierr); 43649b8102ccSHong Zhang } 4365a22543b6SHong Zhang /* Check sum(n) = N */ 4366a95133b1SBarry Smith ierr = MPI_Allreduce(&n,&sum,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 4367a22543b6SHong Zhang if (sum != N) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Sum of local columns != global columns %d",N); 4368a22543b6SHong Zhang 43699b8102ccSHong Zhang ierr = MPI_Scan(&m, &rstart,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 43709b8102ccSHong Zhang rstart -= m; 43719b8102ccSHong Zhang 43729b8102ccSHong Zhang ierr = MatPreallocateInitialize(comm,m,n,dnz,onz);CHKERRQ(ierr); 43739b8102ccSHong Zhang for (i=0;i<m;i++) { 43749b8102ccSHong Zhang ierr = MatGetRow_SeqAIJ(inmat,i,&nnz,&indx,PETSC_NULL);CHKERRQ(ierr); 43759b8102ccSHong Zhang ierr = MatPreallocateSet(i+rstart,nnz,indx,dnz,onz);CHKERRQ(ierr); 43769b8102ccSHong Zhang ierr = MatRestoreRow_SeqAIJ(inmat,i,&nnz,&indx,PETSC_NULL);CHKERRQ(ierr); 43779b8102ccSHong Zhang } 43789b8102ccSHong Zhang 43799b8102ccSHong Zhang ierr = MatCreate(comm,outmat);CHKERRQ(ierr); 43809b8102ccSHong Zhang ierr = MatSetSizes(*outmat,m,n,PETSC_DETERMINE,PETSC_DETERMINE); CHKERRQ(ierr); 4381a2f3521dSMark F. Adams ierr = MatSetBlockSizes(*outmat,bs,cbs); CHKERRQ(ierr); 43829b8102ccSHong Zhang ierr = MatSetType(*outmat,MATMPIAIJ); CHKERRQ(ierr); 43839b8102ccSHong Zhang ierr = MatMPIAIJSetPreallocation(*outmat,0,dnz,0,onz);CHKERRQ(ierr); 43849b8102ccSHong Zhang ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 43859b8102ccSHong Zhang PetscFunctionReturn(0); 43869b8102ccSHong Zhang } 43879b8102ccSHong Zhang 43889b8102ccSHong Zhang #undef __FUNCT__ 438990431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJConcatenateSeqAIJNumeric" 439090431a8fSHong Zhang PetscErrorCode MatCreateMPIAIJConcatenateSeqAIJNumeric(MPI_Comm comm,Mat inmat,PetscInt n,Mat outmat) 43919b8102ccSHong Zhang { 43929b8102ccSHong Zhang PetscErrorCode ierr; 43939b8102ccSHong Zhang PetscInt m,N,i,rstart,nnz,Ii; 43949b8102ccSHong Zhang PetscInt *indx; 43959b8102ccSHong Zhang PetscScalar *values; 43969b8102ccSHong Zhang 43979b8102ccSHong Zhang PetscFunctionBegin; 43989b8102ccSHong Zhang ierr = MatGetSize(inmat,&m,&N);CHKERRQ(ierr); 43999b8102ccSHong Zhang ierr = MatGetOwnershipRange(outmat,&rstart,PETSC_NULL);CHKERRQ(ierr); 44009b8102ccSHong Zhang for (i=0;i<m;i++) { 44019b8102ccSHong Zhang ierr = MatGetRow_SeqAIJ(inmat,i,&nnz,&indx,&values);CHKERRQ(ierr); 44029b8102ccSHong Zhang Ii = i + rstart; 4403a22543b6SHong Zhang ierr = MatSetValues_MPIAIJ(outmat,1,&Ii,nnz,indx,values,INSERT_VALUES);CHKERRQ(ierr); 44049b8102ccSHong Zhang ierr = MatRestoreRow_SeqAIJ(inmat,i,&nnz,&indx,&values);CHKERRQ(ierr); 44059b8102ccSHong Zhang } 44069b8102ccSHong Zhang ierr = MatAssemblyBegin(outmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 44079b8102ccSHong Zhang ierr = MatAssemblyEnd(outmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 44089b8102ccSHong Zhang PetscFunctionReturn(0); 44099b8102ccSHong Zhang } 44109b8102ccSHong Zhang 44119b8102ccSHong Zhang #undef __FUNCT__ 441290431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJConcatenateSeqAIJ" 4413bc08b0f1SBarry Smith /*@ 441490431a8fSHong Zhang MatCreateMPIAIJConcatenateSeqAIJ - Creates a single large PETSc matrix by concatenating sequential 441551dd7536SBarry Smith matrices from each processor 4416c5d6d63eSBarry Smith 4417c5d6d63eSBarry Smith Collective on MPI_Comm 4418c5d6d63eSBarry Smith 4419c5d6d63eSBarry Smith Input Parameters: 442051dd7536SBarry Smith + comm - the communicators the parallel matrix will live on 4421d6bb3c2dSHong Zhang . inmat - the input sequential matrices 44220e36024fSHong Zhang . n - number of local columns (or PETSC_DECIDE) 4423d6bb3c2dSHong Zhang - scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 442451dd7536SBarry Smith 442551dd7536SBarry Smith Output Parameter: 442651dd7536SBarry Smith . outmat - the parallel matrix generated 4427c5d6d63eSBarry Smith 44287e25d530SSatish Balay Level: advanced 44297e25d530SSatish Balay 4430f08fae4eSHong Zhang Notes: The number of columns of the matrix in EACH processor MUST be the same. 4431c5d6d63eSBarry Smith 4432c5d6d63eSBarry Smith @*/ 443390431a8fSHong Zhang PetscErrorCode MatCreateMPIAIJConcatenateSeqAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat) 4434c5d6d63eSBarry Smith { 4435dfbe8321SBarry Smith PetscErrorCode ierr; 4436c5d6d63eSBarry Smith 4437c5d6d63eSBarry Smith PetscFunctionBegin; 44389b8102ccSHong Zhang ierr = PetscLogEventBegin(MAT_Merge,inmat,0,0,0);CHKERRQ(ierr); 4439d6bb3c2dSHong Zhang if (scall == MAT_INITIAL_MATRIX){ 444090431a8fSHong Zhang ierr = MatCreateMPIAIJConcatenateSeqAIJSymbolic(comm,inmat,n,outmat);CHKERRQ(ierr); 44410e36024fSHong Zhang } 444290431a8fSHong Zhang ierr = MatCreateMPIAIJConcatenateSeqAIJNumeric(comm,inmat,n,*outmat);CHKERRQ(ierr); 44439b8102ccSHong Zhang ierr = PetscLogEventEnd(MAT_Merge,inmat,0,0,0);CHKERRQ(ierr); 4444c5d6d63eSBarry Smith PetscFunctionReturn(0); 4445c5d6d63eSBarry Smith } 4446c5d6d63eSBarry Smith 4447c5d6d63eSBarry Smith #undef __FUNCT__ 4448c5d6d63eSBarry Smith #define __FUNCT__ "MatFileSplit" 4449dfbe8321SBarry Smith PetscErrorCode MatFileSplit(Mat A,char *outfile) 4450c5d6d63eSBarry Smith { 4451dfbe8321SBarry Smith PetscErrorCode ierr; 445232dcc486SBarry Smith PetscMPIInt rank; 4453b1d57f15SBarry Smith PetscInt m,N,i,rstart,nnz; 4454de4209c5SBarry Smith size_t len; 4455b1d57f15SBarry Smith const PetscInt *indx; 4456c5d6d63eSBarry Smith PetscViewer out; 4457c5d6d63eSBarry Smith char *name; 4458c5d6d63eSBarry Smith Mat B; 4459b3cc6726SBarry Smith const PetscScalar *values; 4460c5d6d63eSBarry Smith 4461c5d6d63eSBarry Smith PetscFunctionBegin; 4462c5d6d63eSBarry Smith ierr = MatGetLocalSize(A,&m,0);CHKERRQ(ierr); 4463c5d6d63eSBarry Smith ierr = MatGetSize(A,0,&N);CHKERRQ(ierr); 4464f204ca49SKris Buschelman /* Should this be the type of the diagonal block of A? */ 4465f69a0ea3SMatthew Knepley ierr = MatCreate(PETSC_COMM_SELF,&B);CHKERRQ(ierr); 4466f69a0ea3SMatthew Knepley ierr = MatSetSizes(B,m,N,m,N);CHKERRQ(ierr); 4467a2f3521dSMark F. Adams ierr = MatSetBlockSizes(B,A->rmap->bs,A->cmap->bs);CHKERRQ(ierr); 4468f204ca49SKris Buschelman ierr = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr); 4469f204ca49SKris Buschelman ierr = MatSeqAIJSetPreallocation(B,0,PETSC_NULL);CHKERRQ(ierr); 4470c5d6d63eSBarry Smith ierr = MatGetOwnershipRange(A,&rstart,0);CHKERRQ(ierr); 4471c5d6d63eSBarry Smith for (i=0;i<m;i++) { 4472c5d6d63eSBarry Smith ierr = MatGetRow(A,i+rstart,&nnz,&indx,&values);CHKERRQ(ierr); 4473c5d6d63eSBarry Smith ierr = MatSetValues(B,1,&i,nnz,indx,values,INSERT_VALUES);CHKERRQ(ierr); 4474c5d6d63eSBarry Smith ierr = MatRestoreRow(A,i+rstart,&nnz,&indx,&values);CHKERRQ(ierr); 4475c5d6d63eSBarry Smith } 4476c5d6d63eSBarry Smith ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4477c5d6d63eSBarry Smith ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4478c5d6d63eSBarry Smith 44797adad957SLisandro Dalcin ierr = MPI_Comm_rank(((PetscObject)A)->comm,&rank);CHKERRQ(ierr); 4480c5d6d63eSBarry Smith ierr = PetscStrlen(outfile,&len);CHKERRQ(ierr); 4481c5d6d63eSBarry Smith ierr = PetscMalloc((len+5)*sizeof(char),&name);CHKERRQ(ierr); 4482c5d6d63eSBarry Smith sprintf(name,"%s.%d",outfile,rank); 4483852598b0SBarry Smith ierr = PetscViewerBinaryOpen(PETSC_COMM_SELF,name,FILE_MODE_APPEND,&out);CHKERRQ(ierr); 4484c5d6d63eSBarry Smith ierr = PetscFree(name); 4485c5d6d63eSBarry Smith ierr = MatView(B,out);CHKERRQ(ierr); 44866bf464f9SBarry Smith ierr = PetscViewerDestroy(&out);CHKERRQ(ierr); 44876bf464f9SBarry Smith ierr = MatDestroy(&B);CHKERRQ(ierr); 4488c5d6d63eSBarry Smith PetscFunctionReturn(0); 4489c5d6d63eSBarry Smith } 4490e5f2cdd8SHong Zhang 449109573ac7SBarry Smith extern PetscErrorCode MatDestroy_MPIAIJ(Mat); 449251a7d1a8SHong Zhang #undef __FUNCT__ 449351a7d1a8SHong Zhang #define __FUNCT__ "MatDestroy_MPIAIJ_SeqsToMPI" 44947087cfbeSBarry Smith PetscErrorCode MatDestroy_MPIAIJ_SeqsToMPI(Mat A) 449551a7d1a8SHong Zhang { 449651a7d1a8SHong Zhang PetscErrorCode ierr; 4497671beff6SHong Zhang Mat_Merge_SeqsToMPI *merge; 4498776b82aeSLisandro Dalcin PetscContainer container; 449951a7d1a8SHong Zhang 450051a7d1a8SHong Zhang PetscFunctionBegin; 4501671beff6SHong Zhang ierr = PetscObjectQuery((PetscObject)A,"MatMergeSeqsToMPI",(PetscObject *)&container);CHKERRQ(ierr); 4502671beff6SHong Zhang if (container) { 4503776b82aeSLisandro Dalcin ierr = PetscContainerGetPointer(container,(void **)&merge);CHKERRQ(ierr); 450451a7d1a8SHong Zhang ierr = PetscFree(merge->id_r);CHKERRQ(ierr); 45053e06a4e6SHong Zhang ierr = PetscFree(merge->len_s);CHKERRQ(ierr); 45063e06a4e6SHong Zhang ierr = PetscFree(merge->len_r);CHKERRQ(ierr); 450751a7d1a8SHong Zhang ierr = PetscFree(merge->bi);CHKERRQ(ierr); 450851a7d1a8SHong Zhang ierr = PetscFree(merge->bj);CHKERRQ(ierr); 4509533163c2SBarry Smith ierr = PetscFree(merge->buf_ri[0]);CHKERRQ(ierr); 451002c68681SHong Zhang ierr = PetscFree(merge->buf_ri);CHKERRQ(ierr); 4511533163c2SBarry Smith ierr = PetscFree(merge->buf_rj[0]);CHKERRQ(ierr); 451202c68681SHong Zhang ierr = PetscFree(merge->buf_rj);CHKERRQ(ierr); 451305b42c5fSBarry Smith ierr = PetscFree(merge->coi);CHKERRQ(ierr); 451405b42c5fSBarry Smith ierr = PetscFree(merge->coj);CHKERRQ(ierr); 451505b42c5fSBarry Smith ierr = PetscFree(merge->owners_co);CHKERRQ(ierr); 45166bf464f9SBarry Smith ierr = PetscLayoutDestroy(&merge->rowmap);CHKERRQ(ierr); 4517bf0cc555SLisandro Dalcin ierr = PetscFree(merge);CHKERRQ(ierr); 4518671beff6SHong Zhang ierr = PetscObjectCompose((PetscObject)A,"MatMergeSeqsToMPI",0);CHKERRQ(ierr); 4519671beff6SHong Zhang } 452051a7d1a8SHong Zhang ierr = MatDestroy_MPIAIJ(A);CHKERRQ(ierr); 452151a7d1a8SHong Zhang PetscFunctionReturn(0); 452251a7d1a8SHong Zhang } 452351a7d1a8SHong Zhang 4524c6db04a5SJed Brown #include <../src/mat/utils/freespace.h> 4525c6db04a5SJed Brown #include <petscbt.h> 45264ebed01fSBarry Smith 4527e5f2cdd8SHong Zhang #undef __FUNCT__ 452890431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJSumSeqAIJNumeric" 452990431a8fSHong Zhang PetscErrorCode MatCreateMPIAIJSumSeqAIJNumeric(Mat seqmat,Mat mpimat) 453055d1abb9SHong Zhang { 453155d1abb9SHong Zhang PetscErrorCode ierr; 45327adad957SLisandro Dalcin MPI_Comm comm=((PetscObject)mpimat)->comm; 453355d1abb9SHong Zhang Mat_SeqAIJ *a=(Mat_SeqAIJ*)seqmat->data; 4534b1d57f15SBarry Smith PetscMPIInt size,rank,taga,*len_s; 4535d0f46423SBarry Smith PetscInt N=mpimat->cmap->N,i,j,*owners,*ai=a->i,*aj=a->j; 4536b1d57f15SBarry Smith PetscInt proc,m; 4537b1d57f15SBarry Smith PetscInt **buf_ri,**buf_rj; 4538b1d57f15SBarry Smith PetscInt k,anzi,*bj_i,*bi,*bj,arow,bnzi,nextaj; 4539b1d57f15SBarry Smith PetscInt nrows,**buf_ri_k,**nextrow,**nextai; 454055d1abb9SHong Zhang MPI_Request *s_waits,*r_waits; 454155d1abb9SHong Zhang MPI_Status *status; 4542a77337e4SBarry Smith MatScalar *aa=a->a; 4543dd6ea824SBarry Smith MatScalar **abuf_r,*ba_i; 454455d1abb9SHong Zhang Mat_Merge_SeqsToMPI *merge; 4545776b82aeSLisandro Dalcin PetscContainer container; 454655d1abb9SHong Zhang 454755d1abb9SHong Zhang PetscFunctionBegin; 45484ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Seqstompinum,seqmat,0,0,0);CHKERRQ(ierr); 45493c2c1871SHong Zhang 455055d1abb9SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 455155d1abb9SHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 455255d1abb9SHong Zhang 455355d1abb9SHong Zhang ierr = PetscObjectQuery((PetscObject)mpimat,"MatMergeSeqsToMPI",(PetscObject *)&container);CHKERRQ(ierr); 4554776b82aeSLisandro Dalcin ierr = PetscContainerGetPointer(container,(void **)&merge);CHKERRQ(ierr); 4555bf0cc555SLisandro Dalcin 455655d1abb9SHong Zhang bi = merge->bi; 455755d1abb9SHong Zhang bj = merge->bj; 455855d1abb9SHong Zhang buf_ri = merge->buf_ri; 455955d1abb9SHong Zhang buf_rj = merge->buf_rj; 456055d1abb9SHong Zhang 456155d1abb9SHong Zhang ierr = PetscMalloc(size*sizeof(MPI_Status),&status);CHKERRQ(ierr); 45627a2fc3feSBarry Smith owners = merge->rowmap->range; 456355d1abb9SHong Zhang len_s = merge->len_s; 456455d1abb9SHong Zhang 456555d1abb9SHong Zhang /* send and recv matrix values */ 456655d1abb9SHong Zhang /*-----------------------------*/ 4567357abbc8SBarry Smith ierr = PetscObjectGetNewTag((PetscObject)mpimat,&taga);CHKERRQ(ierr); 456855d1abb9SHong Zhang ierr = PetscPostIrecvScalar(comm,taga,merge->nrecv,merge->id_r,merge->len_r,&abuf_r,&r_waits);CHKERRQ(ierr); 456955d1abb9SHong Zhang 457055d1abb9SHong Zhang ierr = PetscMalloc((merge->nsend+1)*sizeof(MPI_Request),&s_waits);CHKERRQ(ierr); 457155d1abb9SHong Zhang for (proc=0,k=0; proc<size; proc++){ 457255d1abb9SHong Zhang if (!len_s[proc]) continue; 457355d1abb9SHong Zhang i = owners[proc]; 457455d1abb9SHong Zhang ierr = MPI_Isend(aa+ai[i],len_s[proc],MPIU_MATSCALAR,proc,taga,comm,s_waits+k);CHKERRQ(ierr); 457555d1abb9SHong Zhang k++; 457655d1abb9SHong Zhang } 457755d1abb9SHong Zhang 45780c468ba9SBarry Smith if (merge->nrecv) {ierr = MPI_Waitall(merge->nrecv,r_waits,status);CHKERRQ(ierr);} 45790c468ba9SBarry Smith if (merge->nsend) {ierr = MPI_Waitall(merge->nsend,s_waits,status);CHKERRQ(ierr);} 458055d1abb9SHong Zhang ierr = PetscFree(status);CHKERRQ(ierr); 458155d1abb9SHong Zhang 458255d1abb9SHong Zhang ierr = PetscFree(s_waits);CHKERRQ(ierr); 458355d1abb9SHong Zhang ierr = PetscFree(r_waits);CHKERRQ(ierr); 458455d1abb9SHong Zhang 458555d1abb9SHong Zhang /* insert mat values of mpimat */ 458655d1abb9SHong Zhang /*----------------------------*/ 4587a77337e4SBarry Smith ierr = PetscMalloc(N*sizeof(PetscScalar),&ba_i);CHKERRQ(ierr); 45880572522cSBarry Smith ierr = PetscMalloc3(merge->nrecv,PetscInt*,&buf_ri_k,merge->nrecv,PetscInt*,&nextrow,merge->nrecv,PetscInt*,&nextai);CHKERRQ(ierr); 458955d1abb9SHong Zhang 459055d1abb9SHong Zhang for (k=0; k<merge->nrecv; k++){ 459155d1abb9SHong Zhang buf_ri_k[k] = buf_ri[k]; /* beginning of k-th recved i-structure */ 459255d1abb9SHong Zhang nrows = *(buf_ri_k[k]); 459355d1abb9SHong Zhang nextrow[k] = buf_ri_k[k]+1; /* next row number of k-th recved i-structure */ 459455d1abb9SHong Zhang nextai[k] = buf_ri_k[k] + (nrows + 1);/* poins to the next i-structure of k-th recved i-structure */ 459555d1abb9SHong Zhang } 459655d1abb9SHong Zhang 459755d1abb9SHong Zhang /* set values of ba */ 45987a2fc3feSBarry Smith m = merge->rowmap->n; 459955d1abb9SHong Zhang for (i=0; i<m; i++) { 460055d1abb9SHong Zhang arow = owners[rank] + i; 460155d1abb9SHong Zhang bj_i = bj+bi[i]; /* col indices of the i-th row of mpimat */ 460255d1abb9SHong Zhang bnzi = bi[i+1] - bi[i]; 4603a77337e4SBarry Smith ierr = PetscMemzero(ba_i,bnzi*sizeof(PetscScalar));CHKERRQ(ierr); 460455d1abb9SHong Zhang 460555d1abb9SHong Zhang /* add local non-zero vals of this proc's seqmat into ba */ 460655d1abb9SHong Zhang anzi = ai[arow+1] - ai[arow]; 460755d1abb9SHong Zhang aj = a->j + ai[arow]; 460855d1abb9SHong Zhang aa = a->a + ai[arow]; 460955d1abb9SHong Zhang nextaj = 0; 461055d1abb9SHong Zhang for (j=0; nextaj<anzi; j++){ 461155d1abb9SHong Zhang if (*(bj_i + j) == aj[nextaj]){ /* bcol == acol */ 461255d1abb9SHong Zhang ba_i[j] += aa[nextaj++]; 461355d1abb9SHong Zhang } 461455d1abb9SHong Zhang } 461555d1abb9SHong Zhang 461655d1abb9SHong Zhang /* add received vals into ba */ 461755d1abb9SHong Zhang for (k=0; k<merge->nrecv; k++){ /* k-th received message */ 461855d1abb9SHong Zhang /* i-th row */ 461955d1abb9SHong Zhang if (i == *nextrow[k]) { 462055d1abb9SHong Zhang anzi = *(nextai[k]+1) - *nextai[k]; 462155d1abb9SHong Zhang aj = buf_rj[k] + *(nextai[k]); 462255d1abb9SHong Zhang aa = abuf_r[k] + *(nextai[k]); 462355d1abb9SHong Zhang nextaj = 0; 462455d1abb9SHong Zhang for (j=0; nextaj<anzi; j++){ 462555d1abb9SHong Zhang if (*(bj_i + j) == aj[nextaj]){ /* bcol == acol */ 462655d1abb9SHong Zhang ba_i[j] += aa[nextaj++]; 462755d1abb9SHong Zhang } 462855d1abb9SHong Zhang } 462955d1abb9SHong Zhang nextrow[k]++; nextai[k]++; 463055d1abb9SHong Zhang } 463155d1abb9SHong Zhang } 463255d1abb9SHong Zhang ierr = MatSetValues(mpimat,1,&arow,bnzi,bj_i,ba_i,INSERT_VALUES);CHKERRQ(ierr); 463355d1abb9SHong Zhang } 463455d1abb9SHong Zhang ierr = MatAssemblyBegin(mpimat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 463555d1abb9SHong Zhang ierr = MatAssemblyEnd(mpimat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 463655d1abb9SHong Zhang 4637533163c2SBarry Smith ierr = PetscFree(abuf_r[0]);CHKERRQ(ierr); 463855d1abb9SHong Zhang ierr = PetscFree(abuf_r);CHKERRQ(ierr); 463955d1abb9SHong Zhang ierr = PetscFree(ba_i);CHKERRQ(ierr); 46401d79065fSBarry Smith ierr = PetscFree3(buf_ri_k,nextrow,nextai);CHKERRQ(ierr); 46414ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Seqstompinum,seqmat,0,0,0);CHKERRQ(ierr); 464255d1abb9SHong Zhang PetscFunctionReturn(0); 464355d1abb9SHong Zhang } 464438f152feSBarry Smith 46456bc0bbbfSBarry Smith extern PetscErrorCode MatDestroy_MPIAIJ_SeqsToMPI(Mat); 46466bc0bbbfSBarry Smith 464738f152feSBarry Smith #undef __FUNCT__ 464890431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJSumSeqAIJSymbolic" 464990431a8fSHong Zhang PetscErrorCode MatCreateMPIAIJSumSeqAIJSymbolic(MPI_Comm comm,Mat seqmat,PetscInt m,PetscInt n,Mat *mpimat) 4650e5f2cdd8SHong Zhang { 4651f08fae4eSHong Zhang PetscErrorCode ierr; 465255a3bba9SHong Zhang Mat B_mpi; 4653c2234fe3SHong Zhang Mat_SeqAIJ *a=(Mat_SeqAIJ*)seqmat->data; 4654b1d57f15SBarry Smith PetscMPIInt size,rank,tagi,tagj,*len_s,*len_si,*len_ri; 4655b1d57f15SBarry Smith PetscInt **buf_rj,**buf_ri,**buf_ri_k; 4656d0f46423SBarry Smith PetscInt M=seqmat->rmap->n,N=seqmat->cmap->n,i,*owners,*ai=a->i,*aj=a->j; 4657a2f3521dSMark F. Adams PetscInt len,proc,*dnz,*onz,bs,cbs; 4658b1d57f15SBarry Smith PetscInt k,anzi,*bi,*bj,*lnk,nlnk,arow,bnzi,nspacedouble=0; 4659b1d57f15SBarry Smith PetscInt nrows,*buf_s,*buf_si,*buf_si_i,**nextrow,**nextai; 466055d1abb9SHong Zhang MPI_Request *si_waits,*sj_waits,*ri_waits,*rj_waits; 466158cb9c82SHong Zhang MPI_Status *status; 4662a1a86e44SBarry Smith PetscFreeSpaceList free_space=PETSC_NULL,current_space=PETSC_NULL; 4663be0fcf8dSHong Zhang PetscBT lnkbt; 466451a7d1a8SHong Zhang Mat_Merge_SeqsToMPI *merge; 4665776b82aeSLisandro Dalcin PetscContainer container; 466602c68681SHong Zhang 4667e5f2cdd8SHong Zhang PetscFunctionBegin; 46684ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Seqstompisym,seqmat,0,0,0);CHKERRQ(ierr); 46693c2c1871SHong Zhang 467038f152feSBarry Smith /* make sure it is a PETSc comm */ 467138f152feSBarry Smith ierr = PetscCommDuplicate(comm,&comm,PETSC_NULL);CHKERRQ(ierr); 4672e5f2cdd8SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 4673e5f2cdd8SHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 467455d1abb9SHong Zhang 467551a7d1a8SHong Zhang ierr = PetscNew(Mat_Merge_SeqsToMPI,&merge);CHKERRQ(ierr); 4676c2234fe3SHong Zhang ierr = PetscMalloc(size*sizeof(MPI_Status),&status);CHKERRQ(ierr); 4677e5f2cdd8SHong Zhang 46786abd8857SHong Zhang /* determine row ownership */ 4679f08fae4eSHong Zhang /*---------------------------------------------------------*/ 468026283091SBarry Smith ierr = PetscLayoutCreate(comm,&merge->rowmap);CHKERRQ(ierr); 468126283091SBarry Smith ierr = PetscLayoutSetLocalSize(merge->rowmap,m);CHKERRQ(ierr); 468226283091SBarry Smith ierr = PetscLayoutSetSize(merge->rowmap,M);CHKERRQ(ierr); 468326283091SBarry Smith ierr = PetscLayoutSetBlockSize(merge->rowmap,1);CHKERRQ(ierr); 468426283091SBarry Smith ierr = PetscLayoutSetUp(merge->rowmap);CHKERRQ(ierr); 4685b1d57f15SBarry Smith ierr = PetscMalloc(size*sizeof(PetscMPIInt),&len_si);CHKERRQ(ierr); 4686b1d57f15SBarry Smith ierr = PetscMalloc(size*sizeof(PetscMPIInt),&merge->len_s);CHKERRQ(ierr); 468755d1abb9SHong Zhang 46887a2fc3feSBarry Smith m = merge->rowmap->n; 46897a2fc3feSBarry Smith M = merge->rowmap->N; 46907a2fc3feSBarry Smith owners = merge->rowmap->range; 46916abd8857SHong Zhang 46926abd8857SHong Zhang /* determine the number of messages to send, their lengths */ 46936abd8857SHong Zhang /*---------------------------------------------------------*/ 46943e06a4e6SHong Zhang len_s = merge->len_s; 469551a7d1a8SHong Zhang 46962257cef7SHong Zhang len = 0; /* length of buf_si[] */ 4697c2234fe3SHong Zhang merge->nsend = 0; 4698409913e3SHong Zhang for (proc=0; proc<size; proc++){ 46992257cef7SHong Zhang len_si[proc] = 0; 47003e06a4e6SHong Zhang if (proc == rank){ 47016abd8857SHong Zhang len_s[proc] = 0; 47023e06a4e6SHong Zhang } else { 470302c68681SHong Zhang len_si[proc] = owners[proc+1] - owners[proc] + 1; 47043e06a4e6SHong Zhang len_s[proc] = ai[owners[proc+1]] - ai[owners[proc]]; /* num of rows to be sent to [proc] */ 47053e06a4e6SHong Zhang } 47063e06a4e6SHong Zhang if (len_s[proc]) { 4707c2234fe3SHong Zhang merge->nsend++; 47082257cef7SHong Zhang nrows = 0; 47092257cef7SHong Zhang for (i=owners[proc]; i<owners[proc+1]; i++){ 47102257cef7SHong Zhang if (ai[i+1] > ai[i]) nrows++; 47112257cef7SHong Zhang } 47122257cef7SHong Zhang len_si[proc] = 2*(nrows+1); 47132257cef7SHong Zhang len += len_si[proc]; 4714409913e3SHong Zhang } 471558cb9c82SHong Zhang } 4716409913e3SHong Zhang 47172257cef7SHong Zhang /* determine the number and length of messages to receive for ij-structure */ 47182257cef7SHong Zhang /*-------------------------------------------------------------------------*/ 471951a7d1a8SHong Zhang ierr = PetscGatherNumberOfMessages(comm,PETSC_NULL,len_s,&merge->nrecv);CHKERRQ(ierr); 472055d1abb9SHong Zhang ierr = PetscGatherMessageLengths2(comm,merge->nsend,merge->nrecv,len_s,len_si,&merge->id_r,&merge->len_r,&len_ri);CHKERRQ(ierr); 4721671beff6SHong Zhang 47223e06a4e6SHong Zhang /* post the Irecv of j-structure */ 47233e06a4e6SHong Zhang /*-------------------------------*/ 47242c72b5baSSatish Balay ierr = PetscCommGetNewTag(comm,&tagj);CHKERRQ(ierr); 47253e06a4e6SHong Zhang ierr = PetscPostIrecvInt(comm,tagj,merge->nrecv,merge->id_r,merge->len_r,&buf_rj,&rj_waits);CHKERRQ(ierr); 472602c68681SHong Zhang 47273e06a4e6SHong Zhang /* post the Isend of j-structure */ 4728affca5deSHong Zhang /*--------------------------------*/ 47291d79065fSBarry Smith ierr = PetscMalloc2(merge->nsend,MPI_Request,&si_waits,merge->nsend,MPI_Request,&sj_waits);CHKERRQ(ierr); 47303e06a4e6SHong Zhang 47312257cef7SHong Zhang for (proc=0, k=0; proc<size; proc++){ 4732409913e3SHong Zhang if (!len_s[proc]) continue; 473302c68681SHong Zhang i = owners[proc]; 4734b1d57f15SBarry Smith ierr = MPI_Isend(aj+ai[i],len_s[proc],MPIU_INT,proc,tagj,comm,sj_waits+k);CHKERRQ(ierr); 473551a7d1a8SHong Zhang k++; 473651a7d1a8SHong Zhang } 473751a7d1a8SHong Zhang 47383e06a4e6SHong Zhang /* receives and sends of j-structure are complete */ 47393e06a4e6SHong Zhang /*------------------------------------------------*/ 47400c468ba9SBarry Smith if (merge->nrecv) {ierr = MPI_Waitall(merge->nrecv,rj_waits,status);CHKERRQ(ierr);} 47410c468ba9SBarry Smith if (merge->nsend) {ierr = MPI_Waitall(merge->nsend,sj_waits,status);CHKERRQ(ierr);} 474202c68681SHong Zhang 474302c68681SHong Zhang /* send and recv i-structure */ 474402c68681SHong Zhang /*---------------------------*/ 47452c72b5baSSatish Balay ierr = PetscCommGetNewTag(comm,&tagi);CHKERRQ(ierr); 474602c68681SHong Zhang ierr = PetscPostIrecvInt(comm,tagi,merge->nrecv,merge->id_r,len_ri,&buf_ri,&ri_waits);CHKERRQ(ierr); 474702c68681SHong Zhang 4748b1d57f15SBarry Smith ierr = PetscMalloc((len+1)*sizeof(PetscInt),&buf_s);CHKERRQ(ierr); 47493e06a4e6SHong Zhang buf_si = buf_s; /* points to the beginning of k-th msg to be sent */ 47502257cef7SHong Zhang for (proc=0,k=0; proc<size; proc++){ 475102c68681SHong Zhang if (!len_s[proc]) continue; 47523e06a4e6SHong Zhang /* form outgoing message for i-structure: 47533e06a4e6SHong Zhang buf_si[0]: nrows to be sent 47543e06a4e6SHong Zhang [1:nrows]: row index (global) 47553e06a4e6SHong Zhang [nrows+1:2*nrows+1]: i-structure index 47563e06a4e6SHong Zhang */ 47573e06a4e6SHong Zhang /*-------------------------------------------*/ 47582257cef7SHong Zhang nrows = len_si[proc]/2 - 1; 47593e06a4e6SHong Zhang buf_si_i = buf_si + nrows+1; 47603e06a4e6SHong Zhang buf_si[0] = nrows; 47613e06a4e6SHong Zhang buf_si_i[0] = 0; 47623e06a4e6SHong Zhang nrows = 0; 47633e06a4e6SHong Zhang for (i=owners[proc]; i<owners[proc+1]; i++){ 47643e06a4e6SHong Zhang anzi = ai[i+1] - ai[i]; 47653e06a4e6SHong Zhang if (anzi) { 47663e06a4e6SHong Zhang buf_si_i[nrows+1] = buf_si_i[nrows] + anzi; /* i-structure */ 47673e06a4e6SHong Zhang buf_si[nrows+1] = i-owners[proc]; /* local row index */ 47683e06a4e6SHong Zhang nrows++; 47693e06a4e6SHong Zhang } 47703e06a4e6SHong Zhang } 4771b1d57f15SBarry Smith ierr = MPI_Isend(buf_si,len_si[proc],MPIU_INT,proc,tagi,comm,si_waits+k);CHKERRQ(ierr); 477202c68681SHong Zhang k++; 47732257cef7SHong Zhang buf_si += len_si[proc]; 477402c68681SHong Zhang } 47752257cef7SHong Zhang 47760c468ba9SBarry Smith if (merge->nrecv) {ierr = MPI_Waitall(merge->nrecv,ri_waits,status);CHKERRQ(ierr);} 47770c468ba9SBarry Smith if (merge->nsend) {ierr = MPI_Waitall(merge->nsend,si_waits,status);CHKERRQ(ierr);} 477802c68681SHong Zhang 4779ae15b995SBarry Smith ierr = PetscInfo2(seqmat,"nsend: %D, nrecv: %D\n",merge->nsend,merge->nrecv);CHKERRQ(ierr); 47803e06a4e6SHong Zhang for (i=0; i<merge->nrecv; i++){ 4781ae15b995SBarry Smith ierr = PetscInfo3(seqmat,"recv len_ri=%D, len_rj=%D from [%D]\n",len_ri[i],merge->len_r[i],merge->id_r[i]);CHKERRQ(ierr); 47823e06a4e6SHong Zhang } 47833e06a4e6SHong Zhang 47843e06a4e6SHong Zhang ierr = PetscFree(len_si);CHKERRQ(ierr); 478502c68681SHong Zhang ierr = PetscFree(len_ri);CHKERRQ(ierr); 478602c68681SHong Zhang ierr = PetscFree(rj_waits);CHKERRQ(ierr); 47871d79065fSBarry Smith ierr = PetscFree2(si_waits,sj_waits);CHKERRQ(ierr); 47882257cef7SHong Zhang ierr = PetscFree(ri_waits);CHKERRQ(ierr); 47893e06a4e6SHong Zhang ierr = PetscFree(buf_s);CHKERRQ(ierr); 4790bcc1bcd5SHong Zhang ierr = PetscFree(status);CHKERRQ(ierr); 479158cb9c82SHong Zhang 4792bcc1bcd5SHong Zhang /* compute a local seq matrix in each processor */ 4793bcc1bcd5SHong Zhang /*----------------------------------------------*/ 479458cb9c82SHong Zhang /* allocate bi array and free space for accumulating nonzero column info */ 4795b1d57f15SBarry Smith ierr = PetscMalloc((m+1)*sizeof(PetscInt),&bi);CHKERRQ(ierr); 479658cb9c82SHong Zhang bi[0] = 0; 479758cb9c82SHong Zhang 4798be0fcf8dSHong Zhang /* create and initialize a linked list */ 4799be0fcf8dSHong Zhang nlnk = N+1; 4800be0fcf8dSHong Zhang ierr = PetscLLCreate(N,N,nlnk,lnk,lnkbt);CHKERRQ(ierr); 480158cb9c82SHong Zhang 4802bcc1bcd5SHong Zhang /* initial FreeSpace size is 2*(num of local nnz(seqmat)) */ 480358cb9c82SHong Zhang len = 0; 4804bcc1bcd5SHong Zhang len = ai[owners[rank+1]] - ai[owners[rank]]; 4805a1a86e44SBarry Smith ierr = PetscFreeSpaceGet((PetscInt)(2*len+1),&free_space);CHKERRQ(ierr); 480658cb9c82SHong Zhang current_space = free_space; 480758cb9c82SHong Zhang 4808bcc1bcd5SHong Zhang /* determine symbolic info for each local row */ 48090572522cSBarry Smith ierr = PetscMalloc3(merge->nrecv,PetscInt*,&buf_ri_k,merge->nrecv,PetscInt*,&nextrow,merge->nrecv,PetscInt*,&nextai);CHKERRQ(ierr); 48101d79065fSBarry Smith 48113e06a4e6SHong Zhang for (k=0; k<merge->nrecv; k++){ 48122257cef7SHong Zhang buf_ri_k[k] = buf_ri[k]; /* beginning of k-th recved i-structure */ 48133e06a4e6SHong Zhang nrows = *buf_ri_k[k]; 48143e06a4e6SHong Zhang nextrow[k] = buf_ri_k[k] + 1; /* next row number of k-th recved i-structure */ 48152257cef7SHong Zhang nextai[k] = buf_ri_k[k] + (nrows + 1);/* poins to the next i-structure of k-th recved i-structure */ 48163e06a4e6SHong Zhang } 48172257cef7SHong Zhang 4818bcc1bcd5SHong Zhang ierr = MatPreallocateInitialize(comm,m,n,dnz,onz);CHKERRQ(ierr); 4819bcc1bcd5SHong Zhang len = 0; 482058cb9c82SHong Zhang for (i=0;i<m;i++) { 482158cb9c82SHong Zhang bnzi = 0; 482258cb9c82SHong Zhang /* add local non-zero cols of this proc's seqmat into lnk */ 482358cb9c82SHong Zhang arow = owners[rank] + i; 482458cb9c82SHong Zhang anzi = ai[arow+1] - ai[arow]; 482558cb9c82SHong Zhang aj = a->j + ai[arow]; 4826dadf0e6bSHong Zhang ierr = PetscLLAddSorted(anzi,aj,N,nlnk,lnk,lnkbt);CHKERRQ(ierr); 482758cb9c82SHong Zhang bnzi += nlnk; 482858cb9c82SHong Zhang /* add received col data into lnk */ 482951a7d1a8SHong Zhang for (k=0; k<merge->nrecv; k++){ /* k-th received message */ 483055d1abb9SHong Zhang if (i == *nextrow[k]) { /* i-th row */ 48313e06a4e6SHong Zhang anzi = *(nextai[k]+1) - *nextai[k]; 48323e06a4e6SHong Zhang aj = buf_rj[k] + *nextai[k]; 4833dadf0e6bSHong Zhang ierr = PetscLLAddSorted(anzi,aj,N,nlnk,lnk,lnkbt);CHKERRQ(ierr); 48343e06a4e6SHong Zhang bnzi += nlnk; 48353e06a4e6SHong Zhang nextrow[k]++; nextai[k]++; 48363e06a4e6SHong Zhang } 483758cb9c82SHong Zhang } 4838bcc1bcd5SHong Zhang if (len < bnzi) len = bnzi; /* =max(bnzi) */ 483958cb9c82SHong Zhang 484058cb9c82SHong Zhang /* if free space is not available, make more free space */ 484158cb9c82SHong Zhang if (current_space->local_remaining<bnzi) { 48424238b7adSHong Zhang ierr = PetscFreeSpaceGet(bnzi+current_space->total_array_size,¤t_space);CHKERRQ(ierr); 484358cb9c82SHong Zhang nspacedouble++; 484458cb9c82SHong Zhang } 484558cb9c82SHong Zhang /* copy data into free space, then initialize lnk */ 4846be0fcf8dSHong Zhang ierr = PetscLLClean(N,N,bnzi,lnk,current_space->array,lnkbt);CHKERRQ(ierr); 4847bcc1bcd5SHong Zhang ierr = MatPreallocateSet(i+owners[rank],bnzi,current_space->array,dnz,onz);CHKERRQ(ierr); 4848bcc1bcd5SHong Zhang 484958cb9c82SHong Zhang current_space->array += bnzi; 485058cb9c82SHong Zhang current_space->local_used += bnzi; 485158cb9c82SHong Zhang current_space->local_remaining -= bnzi; 485258cb9c82SHong Zhang 485358cb9c82SHong Zhang bi[i+1] = bi[i] + bnzi; 485458cb9c82SHong Zhang } 4855bcc1bcd5SHong Zhang 48561d79065fSBarry Smith ierr = PetscFree3(buf_ri_k,nextrow,nextai);CHKERRQ(ierr); 4857bcc1bcd5SHong Zhang 4858b1d57f15SBarry Smith ierr = PetscMalloc((bi[m]+1)*sizeof(PetscInt),&bj);CHKERRQ(ierr); 4859a1a86e44SBarry Smith ierr = PetscFreeSpaceContiguous(&free_space,bj);CHKERRQ(ierr); 4860be0fcf8dSHong Zhang ierr = PetscLLDestroy(lnk,lnkbt);CHKERRQ(ierr); 4861409913e3SHong Zhang 4862bcc1bcd5SHong Zhang /* create symbolic parallel matrix B_mpi */ 4863bcc1bcd5SHong Zhang /*---------------------------------------*/ 4864a2f3521dSMark F. Adams ierr = MatGetBlockSizes(seqmat,&bs,&cbs);CHKERRQ(ierr); 4865f69a0ea3SMatthew Knepley ierr = MatCreate(comm,&B_mpi);CHKERRQ(ierr); 486654b84b50SHong Zhang if (n==PETSC_DECIDE) { 4867f69a0ea3SMatthew Knepley ierr = MatSetSizes(B_mpi,m,n,PETSC_DETERMINE,N);CHKERRQ(ierr); 486854b84b50SHong Zhang } else { 4869f69a0ea3SMatthew Knepley ierr = MatSetSizes(B_mpi,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 487054b84b50SHong Zhang } 4871a2f3521dSMark F. Adams ierr = MatSetBlockSizes(B_mpi,bs,cbs); CHKERRQ(ierr); 4872bcc1bcd5SHong Zhang ierr = MatSetType(B_mpi,MATMPIAIJ);CHKERRQ(ierr); 4873bcc1bcd5SHong Zhang ierr = MatMPIAIJSetPreallocation(B_mpi,0,dnz,0,onz);CHKERRQ(ierr); 4874bcc1bcd5SHong Zhang ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 48757e63b356SHong Zhang ierr = MatSetOption(B_mpi,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); 487658cb9c82SHong Zhang 487790431a8fSHong Zhang /* B_mpi is not ready for use - assembly will be done by MatCreateMPIAIJSumSeqAIJNumeric() */ 48786abd8857SHong Zhang B_mpi->assembled = PETSC_FALSE; 4879affca5deSHong Zhang B_mpi->ops->destroy = MatDestroy_MPIAIJ_SeqsToMPI; 4880affca5deSHong Zhang merge->bi = bi; 4881affca5deSHong Zhang merge->bj = bj; 488202c68681SHong Zhang merge->buf_ri = buf_ri; 488302c68681SHong Zhang merge->buf_rj = buf_rj; 4884de0260b3SHong Zhang merge->coi = PETSC_NULL; 4885de0260b3SHong Zhang merge->coj = PETSC_NULL; 4886de0260b3SHong Zhang merge->owners_co = PETSC_NULL; 4887affca5deSHong Zhang 4888bf0cc555SLisandro Dalcin ierr = PetscCommDestroy(&comm);CHKERRQ(ierr); 4889bf0cc555SLisandro Dalcin 4890affca5deSHong Zhang /* attach the supporting struct to B_mpi for reuse */ 4891776b82aeSLisandro Dalcin ierr = PetscContainerCreate(PETSC_COMM_SELF,&container);CHKERRQ(ierr); 4892776b82aeSLisandro Dalcin ierr = PetscContainerSetPointer(container,merge);CHKERRQ(ierr); 4893affca5deSHong Zhang ierr = PetscObjectCompose((PetscObject)B_mpi,"MatMergeSeqsToMPI",(PetscObject)container);CHKERRQ(ierr); 4894bf0cc555SLisandro Dalcin ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 4895affca5deSHong Zhang *mpimat = B_mpi; 489638f152feSBarry Smith 48974ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Seqstompisym,seqmat,0,0,0);CHKERRQ(ierr); 4898e5f2cdd8SHong Zhang PetscFunctionReturn(0); 4899e5f2cdd8SHong Zhang } 490025616d81SHong Zhang 490138f152feSBarry Smith #undef __FUNCT__ 490290431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJSumSeqAIJ" 4903d4036a1aSHong Zhang /*@C 490490431a8fSHong Zhang MatCreateMPIAIJSumSeqAIJ - Creates a MPIAIJ matrix by adding sequential 4905d4036a1aSHong Zhang matrices from each processor 4906d4036a1aSHong Zhang 4907d4036a1aSHong Zhang Collective on MPI_Comm 4908d4036a1aSHong Zhang 4909d4036a1aSHong Zhang Input Parameters: 4910d4036a1aSHong Zhang + comm - the communicators the parallel matrix will live on 4911d4036a1aSHong Zhang . seqmat - the input sequential matrices 4912d4036a1aSHong Zhang . m - number of local rows (or PETSC_DECIDE) 4913d4036a1aSHong Zhang . n - number of local columns (or PETSC_DECIDE) 4914d4036a1aSHong Zhang - scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 4915d4036a1aSHong Zhang 4916d4036a1aSHong Zhang Output Parameter: 4917d4036a1aSHong Zhang . mpimat - the parallel matrix generated 4918d4036a1aSHong Zhang 4919d4036a1aSHong Zhang Level: advanced 4920d4036a1aSHong Zhang 4921d4036a1aSHong Zhang Notes: 4922d4036a1aSHong Zhang The dimensions of the sequential matrix in each processor MUST be the same. 4923d4036a1aSHong Zhang The input seqmat is included into the container "Mat_Merge_SeqsToMPI", and will be 4924d4036a1aSHong Zhang destroyed when mpimat is destroyed. Call PetscObjectQuery() to access seqmat. 4925d4036a1aSHong Zhang @*/ 492690431a8fSHong Zhang PetscErrorCode MatCreateMPIAIJSumSeqAIJ(MPI_Comm comm,Mat seqmat,PetscInt m,PetscInt n,MatReuse scall,Mat *mpimat) 492755d1abb9SHong Zhang { 492855d1abb9SHong Zhang PetscErrorCode ierr; 49297e63b356SHong Zhang PetscMPIInt size; 493055d1abb9SHong Zhang 493155d1abb9SHong Zhang PetscFunctionBegin; 49327e63b356SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 49337e63b356SHong Zhang if (size == 1){ 49347e63b356SHong Zhang ierr = PetscLogEventBegin(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr); 49357e63b356SHong Zhang if (scall == MAT_INITIAL_MATRIX){ 49367e63b356SHong Zhang ierr = MatDuplicate(seqmat,MAT_COPY_VALUES,mpimat);CHKERRQ(ierr); 49377e63b356SHong Zhang } else { 49387e63b356SHong Zhang ierr = MatCopy(seqmat,*mpimat,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 49397e63b356SHong Zhang } 49407e63b356SHong Zhang ierr = PetscLogEventEnd(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr); 49417e63b356SHong Zhang PetscFunctionReturn(0); 49427e63b356SHong Zhang } 49434ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr); 494455d1abb9SHong Zhang if (scall == MAT_INITIAL_MATRIX){ 494590431a8fSHong Zhang ierr = MatCreateMPIAIJSumSeqAIJSymbolic(comm,seqmat,m,n,mpimat);CHKERRQ(ierr); 494655d1abb9SHong Zhang } 494790431a8fSHong Zhang ierr = MatCreateMPIAIJSumSeqAIJNumeric(seqmat,*mpimat);CHKERRQ(ierr); 49484ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr); 494955d1abb9SHong Zhang PetscFunctionReturn(0); 495055d1abb9SHong Zhang } 49514ebed01fSBarry Smith 495225616d81SHong Zhang #undef __FUNCT__ 49534a2b5492SBarry Smith #define __FUNCT__ "MatMPIAIJGetLocalMat" 4954bc08b0f1SBarry Smith /*@ 49554a2b5492SBarry Smith MatMPIAIJGetLocalMat - Creates a SeqAIJ from a MPIAIJ matrix by taking all its local rows and putting them into a sequential vector with 49568661ff28SBarry Smith mlocal rows and n columns. Where mlocal is the row count obtained with MatGetLocalSize() and n is the global column count obtained 49578661ff28SBarry Smith with MatGetSize() 495825616d81SHong Zhang 495932fba14fSHong Zhang Not Collective 496025616d81SHong Zhang 496125616d81SHong Zhang Input Parameters: 496225616d81SHong Zhang + A - the matrix 496325616d81SHong Zhang . scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 496425616d81SHong Zhang 496525616d81SHong Zhang Output Parameter: 496625616d81SHong Zhang . A_loc - the local sequential matrix generated 496725616d81SHong Zhang 496825616d81SHong Zhang Level: developer 496925616d81SHong Zhang 4970ba264940SBarry Smith .seealso: MatGetOwnerShipRange(), MatMPIAIJGetLocalMatCondensed() 49718661ff28SBarry Smith 497225616d81SHong Zhang @*/ 49734a2b5492SBarry Smith PetscErrorCode MatMPIAIJGetLocalMat(Mat A,MatReuse scall,Mat *A_loc) 497425616d81SHong Zhang { 497525616d81SHong Zhang PetscErrorCode ierr; 497601b7ae99SHong Zhang Mat_MPIAIJ *mpimat=(Mat_MPIAIJ*)A->data; 497701b7ae99SHong Zhang Mat_SeqAIJ *mat,*a=(Mat_SeqAIJ*)(mpimat->A)->data,*b=(Mat_SeqAIJ*)(mpimat->B)->data; 497801b7ae99SHong Zhang PetscInt *ai=a->i,*aj=a->j,*bi=b->i,*bj=b->j,*cmap=mpimat->garray; 4979a77337e4SBarry Smith MatScalar *aa=a->a,*ba=b->a,*cam; 4980a77337e4SBarry Smith PetscScalar *ca; 4981d0f46423SBarry Smith PetscInt am=A->rmap->n,i,j,k,cstart=A->cmap->rstart; 49825a7d977cSHong Zhang PetscInt *ci,*cj,col,ncols_d,ncols_o,jo; 49838661ff28SBarry Smith PetscBool match; 498425616d81SHong Zhang 498525616d81SHong Zhang PetscFunctionBegin; 4986251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&match);CHKERRQ(ierr); 49878661ff28SBarry Smith if (!match) SETERRQ(((PetscObject)A)->comm, PETSC_ERR_SUP,"Requires MPIAIJ matrix as input"); 49884ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Getlocalmat,A,0,0,0);CHKERRQ(ierr); 498901b7ae99SHong Zhang if (scall == MAT_INITIAL_MATRIX){ 4990dea91ad1SHong Zhang ierr = PetscMalloc((1+am)*sizeof(PetscInt),&ci);CHKERRQ(ierr); 4991dea91ad1SHong Zhang ci[0] = 0; 499201b7ae99SHong Zhang for (i=0; i<am; i++){ 4993dea91ad1SHong Zhang ci[i+1] = ci[i] + (ai[i+1] - ai[i]) + (bi[i+1] - bi[i]); 499401b7ae99SHong Zhang } 4995dea91ad1SHong Zhang ierr = PetscMalloc((1+ci[am])*sizeof(PetscInt),&cj);CHKERRQ(ierr); 4996dea91ad1SHong Zhang ierr = PetscMalloc((1+ci[am])*sizeof(PetscScalar),&ca);CHKERRQ(ierr); 4997dea91ad1SHong Zhang k = 0; 499801b7ae99SHong Zhang for (i=0; i<am; i++) { 49995a7d977cSHong Zhang ncols_o = bi[i+1] - bi[i]; 50005a7d977cSHong Zhang ncols_d = ai[i+1] - ai[i]; 500101b7ae99SHong Zhang /* off-diagonal portion of A */ 50025a7d977cSHong Zhang for (jo=0; jo<ncols_o; jo++) { 50035a7d977cSHong Zhang col = cmap[*bj]; 50045a7d977cSHong Zhang if (col >= cstart) break; 50055a7d977cSHong Zhang cj[k] = col; bj++; 50065a7d977cSHong Zhang ca[k++] = *ba++; 50075a7d977cSHong Zhang } 50085a7d977cSHong Zhang /* diagonal portion of A */ 50095a7d977cSHong Zhang for (j=0; j<ncols_d; j++) { 50105a7d977cSHong Zhang cj[k] = cstart + *aj++; 50115a7d977cSHong Zhang ca[k++] = *aa++; 50125a7d977cSHong Zhang } 50135a7d977cSHong Zhang /* off-diagonal portion of A */ 50145a7d977cSHong Zhang for (j=jo; j<ncols_o; j++) { 50155a7d977cSHong Zhang cj[k] = cmap[*bj++]; 50165a7d977cSHong Zhang ca[k++] = *ba++; 50175a7d977cSHong Zhang } 501825616d81SHong Zhang } 5019dea91ad1SHong Zhang /* put together the new matrix */ 5020d0f46423SBarry Smith ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,am,A->cmap->N,ci,cj,ca,A_loc);CHKERRQ(ierr); 5021dea91ad1SHong Zhang /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 5022dea91ad1SHong Zhang /* Since these are PETSc arrays, change flags to free them as necessary. */ 5023dea91ad1SHong Zhang mat = (Mat_SeqAIJ*)(*A_loc)->data; 5024e6b907acSBarry Smith mat->free_a = PETSC_TRUE; 5025e6b907acSBarry Smith mat->free_ij = PETSC_TRUE; 5026dea91ad1SHong Zhang mat->nonew = 0; 50275a7d977cSHong Zhang } else if (scall == MAT_REUSE_MATRIX){ 50285a7d977cSHong Zhang mat=(Mat_SeqAIJ*)(*A_loc)->data; 5029a77337e4SBarry Smith ci = mat->i; cj = mat->j; cam = mat->a; 50305a7d977cSHong Zhang for (i=0; i<am; i++) { 50315a7d977cSHong Zhang /* off-diagonal portion of A */ 50325a7d977cSHong Zhang ncols_o = bi[i+1] - bi[i]; 50335a7d977cSHong Zhang for (jo=0; jo<ncols_o; jo++) { 50345a7d977cSHong Zhang col = cmap[*bj]; 50355a7d977cSHong Zhang if (col >= cstart) break; 5036a77337e4SBarry Smith *cam++ = *ba++; bj++; 50375a7d977cSHong Zhang } 50385a7d977cSHong Zhang /* diagonal portion of A */ 5039ecc9b87dSHong Zhang ncols_d = ai[i+1] - ai[i]; 5040a77337e4SBarry Smith for (j=0; j<ncols_d; j++) *cam++ = *aa++; 50415a7d977cSHong Zhang /* off-diagonal portion of A */ 5042f33d1a9aSHong Zhang for (j=jo; j<ncols_o; j++) { 5043a77337e4SBarry Smith *cam++ = *ba++; bj++; 5044f33d1a9aSHong Zhang } 50455a7d977cSHong Zhang } 50468661ff28SBarry Smith } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid MatReuse %d",(int)scall); 50474ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Getlocalmat,A,0,0,0);CHKERRQ(ierr); 504825616d81SHong Zhang PetscFunctionReturn(0); 504925616d81SHong Zhang } 505025616d81SHong Zhang 505132fba14fSHong Zhang #undef __FUNCT__ 50524a2b5492SBarry Smith #define __FUNCT__ "MatMPIAIJGetLocalMatCondensed" 505332fba14fSHong Zhang /*@C 5054ba264940SBarry Smith MatMPIAIJGetLocalMatCondensed - Creates a SeqAIJ matrix from an MPIAIJ matrix by taking all its local rows and NON-ZERO columns 505532fba14fSHong Zhang 505632fba14fSHong Zhang Not Collective 505732fba14fSHong Zhang 505832fba14fSHong Zhang Input Parameters: 505932fba14fSHong Zhang + A - the matrix 506032fba14fSHong Zhang . scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 506132fba14fSHong Zhang - row, col - index sets of rows and columns to extract (or PETSC_NULL) 506232fba14fSHong Zhang 506332fba14fSHong Zhang Output Parameter: 506432fba14fSHong Zhang . A_loc - the local sequential matrix generated 506532fba14fSHong Zhang 506632fba14fSHong Zhang Level: developer 506732fba14fSHong Zhang 5068ba264940SBarry Smith .seealso: MatGetOwnershipRange(), MatMPIAIJGetLocalMat() 5069ba264940SBarry Smith 507032fba14fSHong Zhang @*/ 50714a2b5492SBarry Smith PetscErrorCode MatMPIAIJGetLocalMatCondensed(Mat A,MatReuse scall,IS *row,IS *col,Mat *A_loc) 507232fba14fSHong Zhang { 507332fba14fSHong Zhang Mat_MPIAIJ *a=(Mat_MPIAIJ*)A->data; 507432fba14fSHong Zhang PetscErrorCode ierr; 507532fba14fSHong Zhang PetscInt i,start,end,ncols,nzA,nzB,*cmap,imark,*idx; 507632fba14fSHong Zhang IS isrowa,iscola; 507732fba14fSHong Zhang Mat *aloc; 50784a2b5492SBarry Smith PetscBool match; 507932fba14fSHong Zhang 508032fba14fSHong Zhang PetscFunctionBegin; 5081251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&match);CHKERRQ(ierr); 50824a2b5492SBarry Smith if (!match) SETERRQ(((PetscObject)A)->comm, PETSC_ERR_SUP,"Requires MPIAIJ matrix as input"); 50834ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Getlocalmatcondensed,A,0,0,0);CHKERRQ(ierr); 508432fba14fSHong Zhang if (!row){ 5085d0f46423SBarry Smith start = A->rmap->rstart; end = A->rmap->rend; 508632fba14fSHong Zhang ierr = ISCreateStride(PETSC_COMM_SELF,end-start,start,1,&isrowa);CHKERRQ(ierr); 508732fba14fSHong Zhang } else { 508832fba14fSHong Zhang isrowa = *row; 508932fba14fSHong Zhang } 509032fba14fSHong Zhang if (!col){ 5091d0f46423SBarry Smith start = A->cmap->rstart; 509232fba14fSHong Zhang cmap = a->garray; 5093d0f46423SBarry Smith nzA = a->A->cmap->n; 5094d0f46423SBarry Smith nzB = a->B->cmap->n; 509532fba14fSHong Zhang ierr = PetscMalloc((nzA+nzB)*sizeof(PetscInt), &idx);CHKERRQ(ierr); 509632fba14fSHong Zhang ncols = 0; 509732fba14fSHong Zhang for (i=0; i<nzB; i++) { 509832fba14fSHong Zhang if (cmap[i] < start) idx[ncols++] = cmap[i]; 509932fba14fSHong Zhang else break; 510032fba14fSHong Zhang } 510132fba14fSHong Zhang imark = i; 510232fba14fSHong Zhang for (i=0; i<nzA; i++) idx[ncols++] = start + i; 510332fba14fSHong Zhang for (i=imark; i<nzB; i++) idx[ncols++] = cmap[i]; 5104d67e408aSBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,ncols,idx,PETSC_OWN_POINTER,&iscola);CHKERRQ(ierr); 510532fba14fSHong Zhang } else { 510632fba14fSHong Zhang iscola = *col; 510732fba14fSHong Zhang } 510832fba14fSHong Zhang if (scall != MAT_INITIAL_MATRIX){ 510932fba14fSHong Zhang ierr = PetscMalloc(sizeof(Mat),&aloc);CHKERRQ(ierr); 511032fba14fSHong Zhang aloc[0] = *A_loc; 511132fba14fSHong Zhang } 511232fba14fSHong Zhang ierr = MatGetSubMatrices(A,1,&isrowa,&iscola,scall,&aloc);CHKERRQ(ierr); 511332fba14fSHong Zhang *A_loc = aloc[0]; 511432fba14fSHong Zhang ierr = PetscFree(aloc);CHKERRQ(ierr); 511532fba14fSHong Zhang if (!row){ 51166bf464f9SBarry Smith ierr = ISDestroy(&isrowa);CHKERRQ(ierr); 511732fba14fSHong Zhang } 511832fba14fSHong Zhang if (!col){ 51196bf464f9SBarry Smith ierr = ISDestroy(&iscola);CHKERRQ(ierr); 512032fba14fSHong Zhang } 51214ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Getlocalmatcondensed,A,0,0,0);CHKERRQ(ierr); 512232fba14fSHong Zhang PetscFunctionReturn(0); 512332fba14fSHong Zhang } 512432fba14fSHong Zhang 512525616d81SHong Zhang #undef __FUNCT__ 512625616d81SHong Zhang #define __FUNCT__ "MatGetBrowsOfAcols" 512725616d81SHong Zhang /*@C 512832fba14fSHong Zhang MatGetBrowsOfAcols - Creates a SeqAIJ matrix by taking rows of B that equal to nonzero columns of local A 512925616d81SHong Zhang 513025616d81SHong Zhang Collective on Mat 513125616d81SHong Zhang 513225616d81SHong Zhang Input Parameters: 5133e240928fSHong Zhang + A,B - the matrices in mpiaij format 513425616d81SHong Zhang . scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 513525616d81SHong Zhang - rowb, colb - index sets of rows and columns of B to extract (or PETSC_NULL) 513625616d81SHong Zhang 513725616d81SHong Zhang Output Parameter: 513825616d81SHong Zhang + rowb, colb - index sets of rows and columns of B to extract 513925616d81SHong Zhang - B_seq - the sequential matrix generated 514025616d81SHong Zhang 514125616d81SHong Zhang Level: developer 514225616d81SHong Zhang 514325616d81SHong Zhang @*/ 514466bfb163SHong Zhang PetscErrorCode MatGetBrowsOfAcols(Mat A,Mat B,MatReuse scall,IS *rowb,IS *colb,Mat *B_seq) 514525616d81SHong Zhang { 5146899cda47SBarry Smith Mat_MPIAIJ *a=(Mat_MPIAIJ*)A->data; 514725616d81SHong Zhang PetscErrorCode ierr; 5148b1d57f15SBarry Smith PetscInt *idx,i,start,ncols,nzA,nzB,*cmap,imark; 514925616d81SHong Zhang IS isrowb,iscolb; 515066bfb163SHong Zhang Mat *bseq=PETSC_NULL; 515125616d81SHong Zhang 515225616d81SHong Zhang PetscFunctionBegin; 5153d0f46423SBarry Smith if (A->cmap->rstart != B->rmap->rstart || A->cmap->rend != B->rmap->rend){ 5154e32f2f54SBarry Smith SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Matrix local dimensions are incompatible, (%D, %D) != (%D,%D)",A->cmap->rstart,A->cmap->rend,B->rmap->rstart,B->rmap->rend); 515525616d81SHong Zhang } 51564ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_GetBrowsOfAcols,A,B,0,0);CHKERRQ(ierr); 515725616d81SHong Zhang 515825616d81SHong Zhang if (scall == MAT_INITIAL_MATRIX){ 5159d0f46423SBarry Smith start = A->cmap->rstart; 516025616d81SHong Zhang cmap = a->garray; 5161d0f46423SBarry Smith nzA = a->A->cmap->n; 5162d0f46423SBarry Smith nzB = a->B->cmap->n; 5163b1d57f15SBarry Smith ierr = PetscMalloc((nzA+nzB)*sizeof(PetscInt), &idx);CHKERRQ(ierr); 516425616d81SHong Zhang ncols = 0; 51650390132cSHong Zhang for (i=0; i<nzB; i++) { /* row < local row index */ 516625616d81SHong Zhang if (cmap[i] < start) idx[ncols++] = cmap[i]; 516725616d81SHong Zhang else break; 516825616d81SHong Zhang } 516925616d81SHong Zhang imark = i; 51700390132cSHong Zhang for (i=0; i<nzA; i++) idx[ncols++] = start + i; /* local rows */ 51710390132cSHong Zhang for (i=imark; i<nzB; i++) idx[ncols++] = cmap[i]; /* row > local row index */ 5172d67e408aSBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,ncols,idx,PETSC_OWN_POINTER,&isrowb);CHKERRQ(ierr); 5173d0f46423SBarry Smith ierr = ISCreateStride(PETSC_COMM_SELF,B->cmap->N,0,1,&iscolb);CHKERRQ(ierr); 517425616d81SHong Zhang } else { 5175e32f2f54SBarry Smith if (!rowb || !colb) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"IS rowb and colb must be provided for MAT_REUSE_MATRIX"); 517625616d81SHong Zhang isrowb = *rowb; iscolb = *colb; 517725616d81SHong Zhang ierr = PetscMalloc(sizeof(Mat),&bseq);CHKERRQ(ierr); 517825616d81SHong Zhang bseq[0] = *B_seq; 517925616d81SHong Zhang } 518025616d81SHong Zhang ierr = MatGetSubMatrices(B,1,&isrowb,&iscolb,scall,&bseq);CHKERRQ(ierr); 518125616d81SHong Zhang *B_seq = bseq[0]; 518225616d81SHong Zhang ierr = PetscFree(bseq);CHKERRQ(ierr); 518325616d81SHong Zhang if (!rowb){ 51846bf464f9SBarry Smith ierr = ISDestroy(&isrowb);CHKERRQ(ierr); 518525616d81SHong Zhang } else { 518625616d81SHong Zhang *rowb = isrowb; 518725616d81SHong Zhang } 518825616d81SHong Zhang if (!colb){ 51896bf464f9SBarry Smith ierr = ISDestroy(&iscolb);CHKERRQ(ierr); 519025616d81SHong Zhang } else { 519125616d81SHong Zhang *colb = iscolb; 519225616d81SHong Zhang } 51934ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_GetBrowsOfAcols,A,B,0,0);CHKERRQ(ierr); 519425616d81SHong Zhang PetscFunctionReturn(0); 519525616d81SHong Zhang } 5196429d309bSHong Zhang 5197a61c8c0fSHong Zhang #undef __FUNCT__ 5198f8487c73SHong Zhang #define __FUNCT__ "MatGetBrowsOfAoCols_MPIAIJ" 5199f8487c73SHong Zhang /* 5200f8487c73SHong Zhang MatGetBrowsOfAoCols_MPIAIJ - Creates a SeqAIJ matrix by taking rows of B that equal to nonzero columns 520101b7ae99SHong Zhang of the OFF-DIAGONAL portion of local A 5202429d309bSHong Zhang 5203429d309bSHong Zhang Collective on Mat 5204429d309bSHong Zhang 5205429d309bSHong Zhang Input Parameters: 5206429d309bSHong Zhang + A,B - the matrices in mpiaij format 5207598bc09dSHong Zhang - scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 5208429d309bSHong Zhang 5209429d309bSHong Zhang Output Parameter: 5210b7f45c76SHong Zhang + startsj_s - starting point in B's sending j-arrays, saved for MAT_REUSE (or PETSC_NULL) 5211b7f45c76SHong Zhang . startsj_r - starting point in B's receiving j-arrays, saved for MAT_REUSE (or PETSC_NULL) 5212598bc09dSHong Zhang . bufa_ptr - array for sending matrix values, saved for MAT_REUSE (or PETSC_NULL) 5213598bc09dSHong Zhang - B_oth - the sequential matrix generated with size aBn=a->B->cmap->n by B->cmap->N 5214429d309bSHong Zhang 5215429d309bSHong Zhang Level: developer 5216429d309bSHong Zhang 5217f8487c73SHong Zhang */ 5218b7f45c76SHong Zhang PetscErrorCode MatGetBrowsOfAoCols_MPIAIJ(Mat A,Mat B,MatReuse scall,PetscInt **startsj_s,PetscInt **startsj_r,MatScalar **bufa_ptr,Mat *B_oth) 5219429d309bSHong Zhang { 5220a6b2eed2SHong Zhang VecScatter_MPI_General *gen_to,*gen_from; 5221429d309bSHong Zhang PetscErrorCode ierr; 5222899cda47SBarry Smith Mat_MPIAIJ *a=(Mat_MPIAIJ*)A->data; 522387025532SHong Zhang Mat_SeqAIJ *b_oth; 5224a6b2eed2SHong Zhang VecScatter ctx=a->Mvctx; 52257adad957SLisandro Dalcin MPI_Comm comm=((PetscObject)ctx)->comm; 52267adad957SLisandro Dalcin PetscMPIInt *rprocs,*sprocs,tag=((PetscObject)ctx)->tag,rank; 5227d0f46423SBarry Smith PetscInt *rowlen,*bufj,*bufJ,ncols,aBn=a->B->cmap->n,row,*b_othi,*b_othj; 5228dd6ea824SBarry Smith PetscScalar *rvalues,*svalues; 5229dd6ea824SBarry Smith MatScalar *b_otha,*bufa,*bufA; 5230e42f35eeSHong Zhang PetscInt i,j,k,l,ll,nrecvs,nsends,nrows,*srow,*rstarts,*rstartsj = 0,*sstarts,*sstartsj,len; 5231910ba992SMatthew Knepley MPI_Request *rwaits = PETSC_NULL,*swaits = PETSC_NULL; 523287025532SHong Zhang MPI_Status *sstatus,rstatus; 5233aa5bb8c0SSatish Balay PetscMPIInt jj; 5234e42f35eeSHong Zhang PetscInt *cols,sbs,rbs; 5235ba8c8a56SBarry Smith PetscScalar *vals; 5236429d309bSHong Zhang 5237429d309bSHong Zhang PetscFunctionBegin; 5238d0f46423SBarry Smith if (A->cmap->rstart != B->rmap->rstart || A->cmap->rend != B->rmap->rend){ 5239e32f2f54SBarry Smith SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Matrix local dimensions are incompatible, (%d, %d) != (%d,%d)",A->cmap->rstart,A->cmap->rend,B->rmap->rstart,B->rmap->rend); 5240429d309bSHong Zhang } 52414ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_GetBrowsOfAocols,A,B,0,0);CHKERRQ(ierr); 5242a6b2eed2SHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 5243a6b2eed2SHong Zhang 5244a6b2eed2SHong Zhang gen_to = (VecScatter_MPI_General*)ctx->todata; 5245a6b2eed2SHong Zhang gen_from = (VecScatter_MPI_General*)ctx->fromdata; 5246e42f35eeSHong Zhang rvalues = gen_from->values; /* holds the length of receiving row */ 5247e42f35eeSHong Zhang svalues = gen_to->values; /* holds the length of sending row */ 5248a6b2eed2SHong Zhang nrecvs = gen_from->n; 5249a6b2eed2SHong Zhang nsends = gen_to->n; 5250d7ee0231SBarry Smith 5251d7ee0231SBarry Smith ierr = PetscMalloc2(nrecvs,MPI_Request,&rwaits,nsends,MPI_Request,&swaits);CHKERRQ(ierr); 5252a6b2eed2SHong Zhang srow = gen_to->indices; /* local row index to be sent */ 5253a6b2eed2SHong Zhang sstarts = gen_to->starts; 5254a6b2eed2SHong Zhang sprocs = gen_to->procs; 5255a6b2eed2SHong Zhang sstatus = gen_to->sstatus; 5256e42f35eeSHong Zhang sbs = gen_to->bs; 5257e42f35eeSHong Zhang rstarts = gen_from->starts; 5258e42f35eeSHong Zhang rprocs = gen_from->procs; 5259e42f35eeSHong Zhang rbs = gen_from->bs; 5260429d309bSHong Zhang 5261b7f45c76SHong Zhang if (!startsj_s || !bufa_ptr) scall = MAT_INITIAL_MATRIX; 5262429d309bSHong Zhang if (scall == MAT_INITIAL_MATRIX){ 5263a6b2eed2SHong Zhang /* i-array */ 5264a6b2eed2SHong Zhang /*---------*/ 5265a6b2eed2SHong Zhang /* post receives */ 5266a6b2eed2SHong Zhang for (i=0; i<nrecvs; i++){ 5267e42f35eeSHong Zhang rowlen = (PetscInt*)rvalues + rstarts[i]*rbs; 5268e42f35eeSHong Zhang nrows = (rstarts[i+1]-rstarts[i])*rbs; /* num of indices to be received */ 526987025532SHong Zhang ierr = MPI_Irecv(rowlen,nrows,MPIU_INT,rprocs[i],tag,comm,rwaits+i);CHKERRQ(ierr); 5270429d309bSHong Zhang } 5271a6b2eed2SHong Zhang 5272a6b2eed2SHong Zhang /* pack the outgoing message */ 52731d79065fSBarry Smith ierr = PetscMalloc2(nsends+1,PetscInt,&sstartsj,nrecvs+1,PetscInt,&rstartsj);CHKERRQ(ierr); 5274a6b2eed2SHong Zhang sstartsj[0] = 0; rstartsj[0] = 0; 5275a6b2eed2SHong Zhang len = 0; /* total length of j or a array to be sent */ 5276a6b2eed2SHong Zhang k = 0; 5277a6b2eed2SHong Zhang for (i=0; i<nsends; i++){ 5278e42f35eeSHong Zhang rowlen = (PetscInt*)svalues + sstarts[i]*sbs; 5279e42f35eeSHong Zhang nrows = sstarts[i+1]-sstarts[i]; /* num of block rows */ 528087025532SHong Zhang for (j=0; j<nrows; j++) { 5281d0f46423SBarry Smith row = srow[k] + B->rmap->range[rank]; /* global row idx */ 5282e42f35eeSHong Zhang for (l=0; l<sbs; l++){ 5283e42f35eeSHong Zhang ierr = MatGetRow_MPIAIJ(B,row+l,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); /* rowlength */ 5284e42f35eeSHong Zhang rowlen[j*sbs+l] = ncols; 5285e42f35eeSHong Zhang len += ncols; 5286e42f35eeSHong Zhang ierr = MatRestoreRow_MPIAIJ(B,row+l,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 5287e42f35eeSHong Zhang } 5288a6b2eed2SHong Zhang k++; 5289429d309bSHong Zhang } 5290e42f35eeSHong Zhang ierr = MPI_Isend(rowlen,nrows*sbs,MPIU_INT,sprocs[i],tag,comm,swaits+i);CHKERRQ(ierr); 5291dea91ad1SHong Zhang sstartsj[i+1] = len; /* starting point of (i+1)-th outgoing msg in bufj and bufa */ 5292429d309bSHong Zhang } 529387025532SHong Zhang /* recvs and sends of i-array are completed */ 529487025532SHong Zhang i = nrecvs; 529587025532SHong Zhang while (i--) { 5296aa5bb8c0SSatish Balay ierr = MPI_Waitany(nrecvs,rwaits,&jj,&rstatus);CHKERRQ(ierr); 529787025532SHong Zhang } 52980c468ba9SBarry Smith if (nsends) {ierr = MPI_Waitall(nsends,swaits,sstatus);CHKERRQ(ierr);} 5299e42f35eeSHong Zhang 5300a6b2eed2SHong Zhang /* allocate buffers for sending j and a arrays */ 5301a6b2eed2SHong Zhang ierr = PetscMalloc((len+1)*sizeof(PetscInt),&bufj);CHKERRQ(ierr); 5302a6b2eed2SHong Zhang ierr = PetscMalloc((len+1)*sizeof(PetscScalar),&bufa);CHKERRQ(ierr); 5303a6b2eed2SHong Zhang 530487025532SHong Zhang /* create i-array of B_oth */ 530587025532SHong Zhang ierr = PetscMalloc((aBn+2)*sizeof(PetscInt),&b_othi);CHKERRQ(ierr); 530687025532SHong Zhang b_othi[0] = 0; 5307a6b2eed2SHong Zhang len = 0; /* total length of j or a array to be received */ 5308a6b2eed2SHong Zhang k = 0; 5309a6b2eed2SHong Zhang for (i=0; i<nrecvs; i++){ 5310fd0ff01cSHong Zhang rowlen = (PetscInt*)rvalues + rstarts[i]*rbs; 5311e42f35eeSHong Zhang nrows = rbs*(rstarts[i+1]-rstarts[i]); /* num of rows to be recieved */ 531287025532SHong Zhang for (j=0; j<nrows; j++) { 531387025532SHong Zhang b_othi[k+1] = b_othi[k] + rowlen[j]; 5314a6b2eed2SHong Zhang len += rowlen[j]; k++; 5315a6b2eed2SHong Zhang } 5316dea91ad1SHong Zhang rstartsj[i+1] = len; /* starting point of (i+1)-th incoming msg in bufj and bufa */ 5317a6b2eed2SHong Zhang } 5318a6b2eed2SHong Zhang 531987025532SHong Zhang /* allocate space for j and a arrrays of B_oth */ 532087025532SHong Zhang ierr = PetscMalloc((b_othi[aBn]+1)*sizeof(PetscInt),&b_othj);CHKERRQ(ierr); 5321dd6ea824SBarry Smith ierr = PetscMalloc((b_othi[aBn]+1)*sizeof(MatScalar),&b_otha);CHKERRQ(ierr); 5322a6b2eed2SHong Zhang 532387025532SHong Zhang /* j-array */ 532487025532SHong Zhang /*---------*/ 5325a6b2eed2SHong Zhang /* post receives of j-array */ 5326a6b2eed2SHong Zhang for (i=0; i<nrecvs; i++){ 532787025532SHong Zhang nrows = rstartsj[i+1]-rstartsj[i]; /* length of the msg received */ 532887025532SHong Zhang ierr = MPI_Irecv(b_othj+rstartsj[i],nrows,MPIU_INT,rprocs[i],tag,comm,rwaits+i);CHKERRQ(ierr); 5329a6b2eed2SHong Zhang } 5330e42f35eeSHong Zhang 5331e42f35eeSHong Zhang /* pack the outgoing message j-array */ 5332a6b2eed2SHong Zhang k = 0; 5333a6b2eed2SHong Zhang for (i=0; i<nsends; i++){ 5334e42f35eeSHong Zhang nrows = sstarts[i+1]-sstarts[i]; /* num of block rows */ 5335a6b2eed2SHong Zhang bufJ = bufj+sstartsj[i]; 533687025532SHong Zhang for (j=0; j<nrows; j++) { 5337d0f46423SBarry Smith row = srow[k++] + B->rmap->range[rank]; /* global row idx */ 5338e42f35eeSHong Zhang for (ll=0; ll<sbs; ll++){ 5339e42f35eeSHong Zhang ierr = MatGetRow_MPIAIJ(B,row+ll,&ncols,&cols,PETSC_NULL);CHKERRQ(ierr); 5340a6b2eed2SHong Zhang for (l=0; l<ncols; l++){ 5341a6b2eed2SHong Zhang *bufJ++ = cols[l]; 534287025532SHong Zhang } 5343e42f35eeSHong Zhang ierr = MatRestoreRow_MPIAIJ(B,row+ll,&ncols,&cols,PETSC_NULL);CHKERRQ(ierr); 5344e42f35eeSHong Zhang } 534587025532SHong Zhang } 534687025532SHong Zhang ierr = MPI_Isend(bufj+sstartsj[i],sstartsj[i+1]-sstartsj[i],MPIU_INT,sprocs[i],tag,comm,swaits+i);CHKERRQ(ierr); 534787025532SHong Zhang } 534887025532SHong Zhang 534987025532SHong Zhang /* recvs and sends of j-array are completed */ 535087025532SHong Zhang i = nrecvs; 535187025532SHong Zhang while (i--) { 5352aa5bb8c0SSatish Balay ierr = MPI_Waitany(nrecvs,rwaits,&jj,&rstatus);CHKERRQ(ierr); 535387025532SHong Zhang } 53540c468ba9SBarry Smith if (nsends) {ierr = MPI_Waitall(nsends,swaits,sstatus);CHKERRQ(ierr);} 535587025532SHong Zhang } else if (scall == MAT_REUSE_MATRIX){ 5356b7f45c76SHong Zhang sstartsj = *startsj_s; 53571d79065fSBarry Smith rstartsj = *startsj_r; 535887025532SHong Zhang bufa = *bufa_ptr; 535987025532SHong Zhang b_oth = (Mat_SeqAIJ*)(*B_oth)->data; 536087025532SHong Zhang b_otha = b_oth->a; 536187025532SHong Zhang } else { 5362e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Matrix P does not posses an object container"); 536387025532SHong Zhang } 536487025532SHong Zhang 536587025532SHong Zhang /* a-array */ 536687025532SHong Zhang /*---------*/ 536787025532SHong Zhang /* post receives of a-array */ 536887025532SHong Zhang for (i=0; i<nrecvs; i++){ 536987025532SHong Zhang nrows = rstartsj[i+1]-rstartsj[i]; /* length of the msg received */ 537087025532SHong Zhang ierr = MPI_Irecv(b_otha+rstartsj[i],nrows,MPIU_SCALAR,rprocs[i],tag,comm,rwaits+i);CHKERRQ(ierr); 537187025532SHong Zhang } 5372e42f35eeSHong Zhang 5373e42f35eeSHong Zhang /* pack the outgoing message a-array */ 537487025532SHong Zhang k = 0; 537587025532SHong Zhang for (i=0; i<nsends; i++){ 5376e42f35eeSHong Zhang nrows = sstarts[i+1]-sstarts[i]; /* num of block rows */ 537787025532SHong Zhang bufA = bufa+sstartsj[i]; 537887025532SHong Zhang for (j=0; j<nrows; j++) { 5379d0f46423SBarry Smith row = srow[k++] + B->rmap->range[rank]; /* global row idx */ 5380e42f35eeSHong Zhang for (ll=0; ll<sbs; ll++){ 5381e42f35eeSHong Zhang ierr = MatGetRow_MPIAIJ(B,row+ll,&ncols,PETSC_NULL,&vals);CHKERRQ(ierr); 538287025532SHong Zhang for (l=0; l<ncols; l++){ 5383a6b2eed2SHong Zhang *bufA++ = vals[l]; 5384a6b2eed2SHong Zhang } 5385e42f35eeSHong Zhang ierr = MatRestoreRow_MPIAIJ(B,row+ll,&ncols,PETSC_NULL,&vals);CHKERRQ(ierr); 5386e42f35eeSHong Zhang } 5387a6b2eed2SHong Zhang } 538887025532SHong Zhang ierr = MPI_Isend(bufa+sstartsj[i],sstartsj[i+1]-sstartsj[i],MPIU_SCALAR,sprocs[i],tag,comm,swaits+i);CHKERRQ(ierr); 5389a6b2eed2SHong Zhang } 539087025532SHong Zhang /* recvs and sends of a-array are completed */ 539187025532SHong Zhang i = nrecvs; 539287025532SHong Zhang while (i--) { 5393aa5bb8c0SSatish Balay ierr = MPI_Waitany(nrecvs,rwaits,&jj,&rstatus);CHKERRQ(ierr); 539487025532SHong Zhang } 53950c468ba9SBarry Smith if (nsends) {ierr = MPI_Waitall(nsends,swaits,sstatus);CHKERRQ(ierr);} 5396d7ee0231SBarry Smith ierr = PetscFree2(rwaits,swaits);CHKERRQ(ierr); 5397a6b2eed2SHong Zhang 539887025532SHong Zhang if (scall == MAT_INITIAL_MATRIX){ 5399a6b2eed2SHong Zhang /* put together the new matrix */ 5400d0f46423SBarry Smith ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,aBn,B->cmap->N,b_othi,b_othj,b_otha,B_oth);CHKERRQ(ierr); 5401a6b2eed2SHong Zhang 5402a6b2eed2SHong Zhang /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 5403a6b2eed2SHong Zhang /* Since these are PETSc arrays, change flags to free them as necessary. */ 540487025532SHong Zhang b_oth = (Mat_SeqAIJ *)(*B_oth)->data; 5405e6b907acSBarry Smith b_oth->free_a = PETSC_TRUE; 5406e6b907acSBarry Smith b_oth->free_ij = PETSC_TRUE; 540787025532SHong Zhang b_oth->nonew = 0; 5408a6b2eed2SHong Zhang 5409a6b2eed2SHong Zhang ierr = PetscFree(bufj);CHKERRQ(ierr); 5410b7f45c76SHong Zhang if (!startsj_s || !bufa_ptr){ 54111d79065fSBarry Smith ierr = PetscFree2(sstartsj,rstartsj);CHKERRQ(ierr); 5412dea91ad1SHong Zhang ierr = PetscFree(bufa_ptr);CHKERRQ(ierr); 5413dea91ad1SHong Zhang } else { 5414b7f45c76SHong Zhang *startsj_s = sstartsj; 54151d79065fSBarry Smith *startsj_r = rstartsj; 541687025532SHong Zhang *bufa_ptr = bufa; 541787025532SHong Zhang } 5418dea91ad1SHong Zhang } 54194ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_GetBrowsOfAocols,A,B,0,0);CHKERRQ(ierr); 5420429d309bSHong Zhang PetscFunctionReturn(0); 5421429d309bSHong Zhang } 5422ccd8e176SBarry Smith 542343eb5e2fSMatthew Knepley #undef __FUNCT__ 542443eb5e2fSMatthew Knepley #define __FUNCT__ "MatGetCommunicationStructs" 542543eb5e2fSMatthew Knepley /*@C 542643eb5e2fSMatthew Knepley MatGetCommunicationStructs - Provides access to the communication structures used in matrix-vector multiplication. 542743eb5e2fSMatthew Knepley 542843eb5e2fSMatthew Knepley Not Collective 542943eb5e2fSMatthew Knepley 543043eb5e2fSMatthew Knepley Input Parameters: 543143eb5e2fSMatthew Knepley . A - The matrix in mpiaij format 543243eb5e2fSMatthew Knepley 543343eb5e2fSMatthew Knepley Output Parameter: 543443eb5e2fSMatthew Knepley + lvec - The local vector holding off-process values from the argument to a matrix-vector product 543543eb5e2fSMatthew Knepley . colmap - A map from global column index to local index into lvec 543643eb5e2fSMatthew Knepley - multScatter - A scatter from the argument of a matrix-vector product to lvec 543743eb5e2fSMatthew Knepley 543843eb5e2fSMatthew Knepley Level: developer 543943eb5e2fSMatthew Knepley 544043eb5e2fSMatthew Knepley @*/ 544143eb5e2fSMatthew Knepley #if defined (PETSC_USE_CTABLE) 54427087cfbeSBarry Smith PetscErrorCode MatGetCommunicationStructs(Mat A, Vec *lvec, PetscTable *colmap, VecScatter *multScatter) 544343eb5e2fSMatthew Knepley #else 54447087cfbeSBarry Smith PetscErrorCode MatGetCommunicationStructs(Mat A, Vec *lvec, PetscInt *colmap[], VecScatter *multScatter) 544543eb5e2fSMatthew Knepley #endif 544643eb5e2fSMatthew Knepley { 544743eb5e2fSMatthew Knepley Mat_MPIAIJ *a; 544843eb5e2fSMatthew Knepley 544943eb5e2fSMatthew Knepley PetscFunctionBegin; 54500700a824SBarry Smith PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5451e414b56bSJed Brown PetscValidPointer(lvec, 2); 5452e414b56bSJed Brown PetscValidPointer(colmap, 3); 5453e414b56bSJed Brown PetscValidPointer(multScatter, 4); 545443eb5e2fSMatthew Knepley a = (Mat_MPIAIJ *) A->data; 545543eb5e2fSMatthew Knepley if (lvec) *lvec = a->lvec; 545643eb5e2fSMatthew Knepley if (colmap) *colmap = a->colmap; 545743eb5e2fSMatthew Knepley if (multScatter) *multScatter = a->Mvctx; 545843eb5e2fSMatthew Knepley PetscFunctionReturn(0); 545943eb5e2fSMatthew Knepley } 546043eb5e2fSMatthew Knepley 546117667f90SBarry Smith EXTERN_C_BEGIN 54627087cfbeSBarry Smith extern PetscErrorCode MatConvert_MPIAIJ_MPIAIJCRL(Mat,const MatType,MatReuse,Mat*); 54637087cfbeSBarry Smith extern PetscErrorCode MatConvert_MPIAIJ_MPIAIJPERM(Mat,const MatType,MatReuse,Mat*); 54647087cfbeSBarry Smith extern PetscErrorCode MatConvert_MPIAIJ_MPISBAIJ(Mat,const MatType,MatReuse,Mat*); 546517667f90SBarry Smith EXTERN_C_END 546617667f90SBarry Smith 5467fc4dec0aSBarry Smith #undef __FUNCT__ 5468fc4dec0aSBarry Smith #define __FUNCT__ "MatMatMultNumeric_MPIDense_MPIAIJ" 5469fc4dec0aSBarry Smith /* 5470fc4dec0aSBarry Smith Computes (B'*A')' since computing B*A directly is untenable 5471fc4dec0aSBarry Smith 5472fc4dec0aSBarry Smith n p p 5473fc4dec0aSBarry Smith ( ) ( ) ( ) 5474fc4dec0aSBarry Smith m ( A ) * n ( B ) = m ( C ) 5475fc4dec0aSBarry Smith ( ) ( ) ( ) 5476fc4dec0aSBarry Smith 5477fc4dec0aSBarry Smith */ 5478fc4dec0aSBarry Smith PetscErrorCode MatMatMultNumeric_MPIDense_MPIAIJ(Mat A,Mat B,Mat C) 5479fc4dec0aSBarry Smith { 5480fc4dec0aSBarry Smith PetscErrorCode ierr; 5481fc4dec0aSBarry Smith Mat At,Bt,Ct; 5482fc4dec0aSBarry Smith 5483fc4dec0aSBarry Smith PetscFunctionBegin; 5484fc4dec0aSBarry Smith ierr = MatTranspose(A,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr); 5485fc4dec0aSBarry Smith ierr = MatTranspose(B,MAT_INITIAL_MATRIX,&Bt);CHKERRQ(ierr); 5486fc4dec0aSBarry Smith ierr = MatMatMult(Bt,At,MAT_INITIAL_MATRIX,1.0,&Ct);CHKERRQ(ierr); 54876bf464f9SBarry Smith ierr = MatDestroy(&At);CHKERRQ(ierr); 54886bf464f9SBarry Smith ierr = MatDestroy(&Bt);CHKERRQ(ierr); 5489fc4dec0aSBarry Smith ierr = MatTranspose(Ct,MAT_REUSE_MATRIX,&C);CHKERRQ(ierr); 54906bf464f9SBarry Smith ierr = MatDestroy(&Ct);CHKERRQ(ierr); 5491fc4dec0aSBarry Smith PetscFunctionReturn(0); 5492fc4dec0aSBarry Smith } 5493fc4dec0aSBarry Smith 5494fc4dec0aSBarry Smith #undef __FUNCT__ 5495fc4dec0aSBarry Smith #define __FUNCT__ "MatMatMultSymbolic_MPIDense_MPIAIJ" 5496fc4dec0aSBarry Smith PetscErrorCode MatMatMultSymbolic_MPIDense_MPIAIJ(Mat A,Mat B,PetscReal fill,Mat *C) 5497fc4dec0aSBarry Smith { 5498fc4dec0aSBarry Smith PetscErrorCode ierr; 5499d0f46423SBarry Smith PetscInt m=A->rmap->n,n=B->cmap->n; 5500fc4dec0aSBarry Smith Mat Cmat; 5501fc4dec0aSBarry Smith 5502fc4dec0aSBarry Smith PetscFunctionBegin; 5503e32f2f54SBarry Smith if (A->cmap->n != B->rmap->n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"A->cmap->n %d != B->rmap->n %d\n",A->cmap->n,B->rmap->n); 550439804f7cSBarry Smith ierr = MatCreate(((PetscObject)A)->comm,&Cmat);CHKERRQ(ierr); 5505fc4dec0aSBarry Smith ierr = MatSetSizes(Cmat,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 5506a2f3521dSMark F. Adams ierr = MatSetBlockSizes(Cmat,A->rmap->bs,B->cmap->bs);CHKERRQ(ierr); 5507fc4dec0aSBarry Smith ierr = MatSetType(Cmat,MATMPIDENSE);CHKERRQ(ierr); 5508fc4dec0aSBarry Smith ierr = MatMPIDenseSetPreallocation(Cmat,PETSC_NULL);CHKERRQ(ierr); 550938556019SBarry Smith ierr = MatAssemblyBegin(Cmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 551038556019SBarry Smith ierr = MatAssemblyEnd(Cmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 5511fc4dec0aSBarry Smith *C = Cmat; 55128cdbd757SHong Zhang (*C)->ops->matmult = MatMatMult_MPIDense_MPIAIJ; 5513fc4dec0aSBarry Smith PetscFunctionReturn(0); 5514fc4dec0aSBarry Smith } 5515fc4dec0aSBarry Smith 5516fc4dec0aSBarry Smith /* ----------------------------------------------------------------*/ 5517fc4dec0aSBarry Smith #undef __FUNCT__ 5518fc4dec0aSBarry Smith #define __FUNCT__ "MatMatMult_MPIDense_MPIAIJ" 5519fc4dec0aSBarry Smith PetscErrorCode MatMatMult_MPIDense_MPIAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 5520fc4dec0aSBarry Smith { 5521fc4dec0aSBarry Smith PetscErrorCode ierr; 5522fc4dec0aSBarry Smith 5523fc4dec0aSBarry Smith PetscFunctionBegin; 5524fc4dec0aSBarry Smith if (scall == MAT_INITIAL_MATRIX){ 5525fc4dec0aSBarry Smith ierr = MatMatMultSymbolic_MPIDense_MPIAIJ(A,B,fill,C);CHKERRQ(ierr); 5526fc4dec0aSBarry Smith } 5527fc4dec0aSBarry Smith ierr = MatMatMultNumeric_MPIDense_MPIAIJ(A,B,*C);CHKERRQ(ierr); 5528fc4dec0aSBarry Smith PetscFunctionReturn(0); 5529fc4dec0aSBarry Smith } 5530fc4dec0aSBarry Smith 55315c9eb25fSBarry Smith EXTERN_C_BEGIN 5532611f576cSBarry Smith #if defined(PETSC_HAVE_MUMPS) 5533bccb9932SShri Abhyankar extern PetscErrorCode MatGetFactor_aij_mumps(Mat,MatFactorType,Mat*); 5534611f576cSBarry Smith #endif 55353bf14a46SMatthew Knepley #if defined(PETSC_HAVE_PASTIX) 55363bf14a46SMatthew Knepley extern PetscErrorCode MatGetFactor_mpiaij_pastix(Mat,MatFactorType,Mat*); 55373bf14a46SMatthew Knepley #endif 5538611f576cSBarry Smith #if defined(PETSC_HAVE_SUPERLU_DIST) 55395c9eb25fSBarry Smith extern PetscErrorCode MatGetFactor_mpiaij_superlu_dist(Mat,MatFactorType,Mat*); 5540611f576cSBarry Smith #endif 5541611f576cSBarry Smith #if defined(PETSC_HAVE_SPOOLES) 55425c9eb25fSBarry Smith extern PetscErrorCode MatGetFactor_mpiaij_spooles(Mat,MatFactorType,Mat*); 5543611f576cSBarry Smith #endif 554417f1a0eaSHong Zhang #if defined(PETSC_HAVE_CLIQUE) 554517f1a0eaSHong Zhang extern PetscErrorCode MatGetFactor_aij_clique(Mat,MatFactorType,Mat*); 554617f1a0eaSHong Zhang #endif 55475c9eb25fSBarry Smith EXTERN_C_END 55485c9eb25fSBarry Smith 5549ccd8e176SBarry Smith /*MC 5550ccd8e176SBarry Smith MATMPIAIJ - MATMPIAIJ = "mpiaij" - A matrix type to be used for parallel sparse matrices. 5551ccd8e176SBarry Smith 5552ccd8e176SBarry Smith Options Database Keys: 5553ccd8e176SBarry Smith . -mat_type mpiaij - sets the matrix type to "mpiaij" during a call to MatSetFromOptions() 5554ccd8e176SBarry Smith 5555ccd8e176SBarry Smith Level: beginner 5556ccd8e176SBarry Smith 555769b1f4b7SBarry Smith .seealso: MatCreateAIJ() 5558ccd8e176SBarry Smith M*/ 5559ccd8e176SBarry Smith 5560ccd8e176SBarry Smith EXTERN_C_BEGIN 5561ccd8e176SBarry Smith #undef __FUNCT__ 5562ccd8e176SBarry Smith #define __FUNCT__ "MatCreate_MPIAIJ" 55637087cfbeSBarry Smith PetscErrorCode MatCreate_MPIAIJ(Mat B) 5564ccd8e176SBarry Smith { 5565ccd8e176SBarry Smith Mat_MPIAIJ *b; 5566ccd8e176SBarry Smith PetscErrorCode ierr; 5567ccd8e176SBarry Smith PetscMPIInt size; 5568ccd8e176SBarry Smith 5569ccd8e176SBarry Smith PetscFunctionBegin; 55707adad957SLisandro Dalcin ierr = MPI_Comm_size(((PetscObject)B)->comm,&size);CHKERRQ(ierr); 557138f2d2fdSLisandro Dalcin ierr = PetscNewLog(B,Mat_MPIAIJ,&b);CHKERRQ(ierr); 5572ccd8e176SBarry Smith B->data = (void*)b; 5573ccd8e176SBarry Smith ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 5574ccd8e176SBarry Smith B->assembled = PETSC_FALSE; 5575ccd8e176SBarry Smith B->insertmode = NOT_SET_VALUES; 5576ccd8e176SBarry Smith b->size = size; 55777adad957SLisandro Dalcin ierr = MPI_Comm_rank(((PetscObject)B)->comm,&b->rank);CHKERRQ(ierr); 5578ccd8e176SBarry Smith 5579ccd8e176SBarry Smith /* build cache for off array entries formed */ 55807adad957SLisandro Dalcin ierr = MatStashCreate_Private(((PetscObject)B)->comm,1,&B->stash);CHKERRQ(ierr); 5581ccd8e176SBarry Smith b->donotstash = PETSC_FALSE; 5582ccd8e176SBarry Smith b->colmap = 0; 5583ccd8e176SBarry Smith b->garray = 0; 5584ccd8e176SBarry Smith b->roworiented = PETSC_TRUE; 5585ccd8e176SBarry Smith 5586ccd8e176SBarry Smith /* stuff used for matrix vector multiply */ 5587ccd8e176SBarry Smith b->lvec = PETSC_NULL; 5588ccd8e176SBarry Smith b->Mvctx = PETSC_NULL; 5589ccd8e176SBarry Smith 5590ccd8e176SBarry Smith /* stuff for MatGetRow() */ 5591ccd8e176SBarry Smith b->rowindices = 0; 5592ccd8e176SBarry Smith b->rowvalues = 0; 5593ccd8e176SBarry Smith b->getrowactive = PETSC_FALSE; 5594ccd8e176SBarry Smith 5595bbf3fe20SPaul Mullowney /* flexible pointer used in CUSP/CUSPARSE classes */ 5596bbf3fe20SPaul Mullowney b->spptr = PETSC_NULL; 5597611f576cSBarry Smith #if defined(PETSC_HAVE_SPOOLES) 5598ec1065edSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_spooles_C", 55995c9eb25fSBarry Smith "MatGetFactor_mpiaij_spooles", 56005c9eb25fSBarry Smith MatGetFactor_mpiaij_spooles);CHKERRQ(ierr); 5601611f576cSBarry Smith #endif 5602611f576cSBarry Smith #if defined(PETSC_HAVE_MUMPS) 5603ec1065edSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_mumps_C", 5604bccb9932SShri Abhyankar "MatGetFactor_aij_mumps", 5605bccb9932SShri Abhyankar MatGetFactor_aij_mumps);CHKERRQ(ierr); 5606611f576cSBarry Smith #endif 56073bf14a46SMatthew Knepley #if defined(PETSC_HAVE_PASTIX) 5608ec1065edSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_pastix_C", 56093bf14a46SMatthew Knepley "MatGetFactor_mpiaij_pastix", 56103bf14a46SMatthew Knepley MatGetFactor_mpiaij_pastix);CHKERRQ(ierr); 56113bf14a46SMatthew Knepley #endif 5612611f576cSBarry Smith #if defined(PETSC_HAVE_SUPERLU_DIST) 5613ec1065edSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_superlu_dist_C", 56145c9eb25fSBarry Smith "MatGetFactor_mpiaij_superlu_dist", 56155c9eb25fSBarry Smith MatGetFactor_mpiaij_superlu_dist);CHKERRQ(ierr); 5616611f576cSBarry Smith #endif 561717f1a0eaSHong Zhang #if defined(PETSC_HAVE_CLIQUE) 561817f1a0eaSHong Zhang ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetFactor_clique_C", 561917f1a0eaSHong Zhang "MatGetFactor_aij_clique", 562017f1a0eaSHong Zhang MatGetFactor_aij_clique);CHKERRQ(ierr); 562117f1a0eaSHong Zhang #endif 5622ccd8e176SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatStoreValues_C", 5623ccd8e176SBarry Smith "MatStoreValues_MPIAIJ", 5624ccd8e176SBarry Smith MatStoreValues_MPIAIJ);CHKERRQ(ierr); 5625ccd8e176SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatRetrieveValues_C", 5626ccd8e176SBarry Smith "MatRetrieveValues_MPIAIJ", 5627ccd8e176SBarry Smith MatRetrieveValues_MPIAIJ);CHKERRQ(ierr); 5628ccd8e176SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatGetDiagonalBlock_C", 5629ccd8e176SBarry Smith "MatGetDiagonalBlock_MPIAIJ", 5630ccd8e176SBarry Smith MatGetDiagonalBlock_MPIAIJ);CHKERRQ(ierr); 5631ccd8e176SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatIsTranspose_C", 5632ccd8e176SBarry Smith "MatIsTranspose_MPIAIJ", 5633ccd8e176SBarry Smith MatIsTranspose_MPIAIJ);CHKERRQ(ierr); 5634ccd8e176SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMPIAIJSetPreallocation_C", 5635ccd8e176SBarry Smith "MatMPIAIJSetPreallocation_MPIAIJ", 5636ccd8e176SBarry Smith MatMPIAIJSetPreallocation_MPIAIJ);CHKERRQ(ierr); 5637ccd8e176SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMPIAIJSetPreallocationCSR_C", 5638ccd8e176SBarry Smith "MatMPIAIJSetPreallocationCSR_MPIAIJ", 5639ccd8e176SBarry Smith MatMPIAIJSetPreallocationCSR_MPIAIJ);CHKERRQ(ierr); 5640ccd8e176SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatDiagonalScaleLocal_C", 5641ccd8e176SBarry Smith "MatDiagonalScaleLocal_MPIAIJ", 5642ccd8e176SBarry Smith MatDiagonalScaleLocal_MPIAIJ);CHKERRQ(ierr); 56435a11e1b2SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_mpiaij_mpiaijperm_C", 56445a11e1b2SBarry Smith "MatConvert_MPIAIJ_MPIAIJPERM", 56455a11e1b2SBarry Smith MatConvert_MPIAIJ_MPIAIJPERM);CHKERRQ(ierr); 56465a11e1b2SBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_mpiaij_mpiaijcrl_C", 56475a11e1b2SBarry Smith "MatConvert_MPIAIJ_MPIAIJCRL", 56485a11e1b2SBarry Smith MatConvert_MPIAIJ_MPIAIJCRL);CHKERRQ(ierr); 5649471cc821SHong Zhang ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatConvert_mpiaij_mpisbaij_C", 5650471cc821SHong Zhang "MatConvert_MPIAIJ_MPISBAIJ", 5651471cc821SHong Zhang MatConvert_MPIAIJ_MPISBAIJ);CHKERRQ(ierr); 5652fc4dec0aSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMult_mpidense_mpiaij_C", 5653fc4dec0aSBarry Smith "MatMatMult_MPIDense_MPIAIJ", 5654fc4dec0aSBarry Smith MatMatMult_MPIDense_MPIAIJ);CHKERRQ(ierr); 5655fc4dec0aSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultSymbolic_mpidense_mpiaij_C", 5656fc4dec0aSBarry Smith "MatMatMultSymbolic_MPIDense_MPIAIJ", 5657fc4dec0aSBarry Smith MatMatMultSymbolic_MPIDense_MPIAIJ);CHKERRQ(ierr); 5658fc4dec0aSBarry Smith ierr = PetscObjectComposeFunctionDynamic((PetscObject)B,"MatMatMultNumeric_mpidense_mpiaij_C", 5659fc4dec0aSBarry Smith "MatMatMultNumeric_MPIDense_MPIAIJ", 5660fc4dec0aSBarry Smith MatMatMultNumeric_MPIDense_MPIAIJ);CHKERRQ(ierr); 566117667f90SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)B,MATMPIAIJ);CHKERRQ(ierr); 5662ccd8e176SBarry Smith PetscFunctionReturn(0); 5663ccd8e176SBarry Smith } 5664ccd8e176SBarry Smith EXTERN_C_END 566581824310SBarry Smith 566603bfb495SBarry Smith #undef __FUNCT__ 566703bfb495SBarry Smith #define __FUNCT__ "MatCreateMPIAIJWithSplitArrays" 566858d36128SBarry Smith /*@ 566903bfb495SBarry Smith MatCreateMPIAIJWithSplitArrays - creates a MPI AIJ matrix using arrays that contain the "diagonal" 567003bfb495SBarry Smith and "off-diagonal" part of the matrix in CSR format. 567103bfb495SBarry Smith 567203bfb495SBarry Smith Collective on MPI_Comm 567303bfb495SBarry Smith 567403bfb495SBarry Smith Input Parameters: 567503bfb495SBarry Smith + comm - MPI communicator 567603bfb495SBarry Smith . m - number of local rows (Cannot be PETSC_DECIDE) 567703bfb495SBarry Smith . n - This value should be the same as the local size used in creating the 567803bfb495SBarry Smith x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have 567903bfb495SBarry Smith calculated if N is given) For square matrices n is almost always m. 568003bfb495SBarry Smith . M - number of global rows (or PETSC_DETERMINE to have calculated if m is given) 568103bfb495SBarry Smith . N - number of global columns (or PETSC_DETERMINE to have calculated if n is given) 568203bfb495SBarry Smith . i - row indices for "diagonal" portion of matrix 568303bfb495SBarry Smith . j - column indices 568403bfb495SBarry Smith . a - matrix values 568503bfb495SBarry Smith . oi - row indices for "off-diagonal" portion of matrix 568603bfb495SBarry Smith . oj - column indices 568703bfb495SBarry Smith - oa - matrix values 568803bfb495SBarry Smith 568903bfb495SBarry Smith Output Parameter: 569003bfb495SBarry Smith . mat - the matrix 569103bfb495SBarry Smith 569203bfb495SBarry Smith Level: advanced 569303bfb495SBarry Smith 569403bfb495SBarry Smith Notes: 5695292fb18eSBarry Smith The i, j, and a arrays ARE NOT copied by this routine into the internal format used by PETSc. The user 5696292fb18eSBarry Smith must free the arrays once the matrix has been destroyed and not before. 569703bfb495SBarry Smith 569803bfb495SBarry Smith The i and j indices are 0 based 569903bfb495SBarry Smith 570069b1f4b7SBarry Smith See MatCreateAIJ() for the definition of "diagonal" and "off-diagonal" portion of the matrix 570103bfb495SBarry Smith 57027b55108eSBarry Smith This sets local rows and cannot be used to set off-processor values. 57037b55108eSBarry Smith 57047b55108eSBarry Smith You cannot later use MatSetValues() to change values in this matrix. 570503bfb495SBarry Smith 570603bfb495SBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel 570703bfb495SBarry Smith 570803bfb495SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(), 570969b1f4b7SBarry Smith MPIAIJ, MatCreateAIJ(), MatCreateMPIAIJWithArrays() 571003bfb495SBarry Smith @*/ 57117087cfbeSBarry Smith PetscErrorCode MatCreateMPIAIJWithSplitArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscInt i[],PetscInt j[],PetscScalar a[], 571203bfb495SBarry Smith PetscInt oi[], PetscInt oj[],PetscScalar oa[],Mat *mat) 571303bfb495SBarry Smith { 571403bfb495SBarry Smith PetscErrorCode ierr; 571503bfb495SBarry Smith Mat_MPIAIJ *maij; 571603bfb495SBarry Smith 571703bfb495SBarry Smith PetscFunctionBegin; 5718e32f2f54SBarry Smith if (m < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"local number of rows (m) cannot be PETSC_DECIDE, or negative"); 5719ea345e14SBarry Smith if (i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 5720ea345e14SBarry Smith if (oi[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"oi (row indices) must start with 0"); 572103bfb495SBarry Smith ierr = MatCreate(comm,mat);CHKERRQ(ierr); 572203bfb495SBarry Smith ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr); 572303bfb495SBarry Smith ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr); 572403bfb495SBarry Smith maij = (Mat_MPIAIJ*) (*mat)->data; 57258d7a6e47SBarry Smith maij->donotstash = PETSC_TRUE; 57268d7a6e47SBarry Smith (*mat)->preallocated = PETSC_TRUE; 572703bfb495SBarry Smith 572826283091SBarry Smith ierr = PetscLayoutSetUp((*mat)->rmap);CHKERRQ(ierr); 572926283091SBarry Smith ierr = PetscLayoutSetUp((*mat)->cmap);CHKERRQ(ierr); 573003bfb495SBarry Smith 573103bfb495SBarry Smith ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,m,n,i,j,a,&maij->A);CHKERRQ(ierr); 5732d0f46423SBarry Smith ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,m,(*mat)->cmap->N,oi,oj,oa,&maij->B);CHKERRQ(ierr); 573303bfb495SBarry Smith 57348d7a6e47SBarry Smith ierr = MatAssemblyBegin(maij->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 57358d7a6e47SBarry Smith ierr = MatAssemblyEnd(maij->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 57368d7a6e47SBarry Smith ierr = MatAssemblyBegin(maij->B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 57378d7a6e47SBarry Smith ierr = MatAssemblyEnd(maij->B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 57388d7a6e47SBarry Smith 573903bfb495SBarry Smith ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 574003bfb495SBarry Smith ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 574103bfb495SBarry Smith PetscFunctionReturn(0); 574203bfb495SBarry Smith } 574303bfb495SBarry Smith 574481824310SBarry Smith /* 574581824310SBarry Smith Special version for direct calls from Fortran 574681824310SBarry Smith */ 5747b45d2f2cSJed Brown #include <petsc-private/fortranimpl.h> 57487087cfbeSBarry Smith 574981824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS) 575081824310SBarry Smith #define matsetvaluesmpiaij_ MATSETVALUESMPIAIJ 575181824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 575281824310SBarry Smith #define matsetvaluesmpiaij_ matsetvaluesmpiaij 575381824310SBarry Smith #endif 575481824310SBarry Smith 575581824310SBarry Smith /* Change these macros so can be used in void function */ 575681824310SBarry Smith #undef CHKERRQ 5757e32f2f54SBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PETSC_COMM_WORLD,ierr) 575881824310SBarry Smith #undef SETERRQ2 5759e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr) 57604994cf47SJed Brown #undef SETERRQ3 57614994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr) 576281824310SBarry Smith #undef SETERRQ 5763e32f2f54SBarry Smith #define SETERRQ(c,ierr,b) CHKERRABORT(c,ierr) 576481824310SBarry Smith 576581824310SBarry Smith EXTERN_C_BEGIN 576681824310SBarry Smith #undef __FUNCT__ 576781824310SBarry Smith #define __FUNCT__ "matsetvaluesmpiaij_" 57681f6cc5b2SSatish Balay void PETSC_STDCALL matsetvaluesmpiaij_(Mat *mmat,PetscInt *mm,const PetscInt im[],PetscInt *mn,const PetscInt in[],const PetscScalar v[],InsertMode *maddv,PetscErrorCode *_ierr) 576981824310SBarry Smith { 577081824310SBarry Smith Mat mat = *mmat; 577181824310SBarry Smith PetscInt m = *mm, n = *mn; 577281824310SBarry Smith InsertMode addv = *maddv; 577381824310SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 577481824310SBarry Smith PetscScalar value; 577581824310SBarry Smith PetscErrorCode ierr; 5776899cda47SBarry Smith 57774994cf47SJed Brown MatCheckPreallocated(mat,1); 577881824310SBarry Smith if (mat->insertmode == NOT_SET_VALUES) { 577981824310SBarry Smith mat->insertmode = addv; 578081824310SBarry Smith } 578181824310SBarry Smith #if defined(PETSC_USE_DEBUG) 578281824310SBarry Smith else if (mat->insertmode != addv) { 5783e32f2f54SBarry Smith SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values"); 578481824310SBarry Smith } 578581824310SBarry Smith #endif 578681824310SBarry Smith { 5787d0f46423SBarry Smith PetscInt i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend; 5788d0f46423SBarry Smith PetscInt cstart = mat->cmap->rstart,cend = mat->cmap->rend,row,col; 5789ace3abfcSBarry Smith PetscBool roworiented = aij->roworiented; 579081824310SBarry Smith 579181824310SBarry Smith /* Some Variables required in the macro */ 579281824310SBarry Smith Mat A = aij->A; 579381824310SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 579481824310SBarry Smith PetscInt *aimax = a->imax,*ai = a->i,*ailen = a->ilen,*aj = a->j; 5795dd6ea824SBarry Smith MatScalar *aa = a->a; 5796ace3abfcSBarry Smith PetscBool ignorezeroentries = (((a->ignorezeroentries)&&(addv==ADD_VALUES))?PETSC_TRUE:PETSC_FALSE); 579781824310SBarry Smith Mat B = aij->B; 579881824310SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 5799d0f46423SBarry Smith PetscInt *bimax = b->imax,*bi = b->i,*bilen = b->ilen,*bj = b->j,bm = aij->B->rmap->n,am = aij->A->rmap->n; 5800dd6ea824SBarry Smith MatScalar *ba = b->a; 580181824310SBarry Smith 580281824310SBarry Smith PetscInt *rp1,*rp2,ii,nrow1,nrow2,_i,rmax1,rmax2,N,low1,high1,low2,high2,t,lastcol1,lastcol2; 580381824310SBarry Smith PetscInt nonew = a->nonew; 5804dd6ea824SBarry Smith MatScalar *ap1,*ap2; 580581824310SBarry Smith 580681824310SBarry Smith PetscFunctionBegin; 580781824310SBarry Smith for (i=0; i<m; i++) { 580881824310SBarry Smith if (im[i] < 0) continue; 580981824310SBarry Smith #if defined(PETSC_USE_DEBUG) 5810e32f2f54SBarry Smith if (im[i] >= mat->rmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row too large: row %D max %D",im[i],mat->rmap->N-1); 581181824310SBarry Smith #endif 581281824310SBarry Smith if (im[i] >= rstart && im[i] < rend) { 581381824310SBarry Smith row = im[i] - rstart; 581481824310SBarry Smith lastcol1 = -1; 581581824310SBarry Smith rp1 = aj + ai[row]; 581681824310SBarry Smith ap1 = aa + ai[row]; 581781824310SBarry Smith rmax1 = aimax[row]; 581881824310SBarry Smith nrow1 = ailen[row]; 581981824310SBarry Smith low1 = 0; 582081824310SBarry Smith high1 = nrow1; 582181824310SBarry Smith lastcol2 = -1; 582281824310SBarry Smith rp2 = bj + bi[row]; 582381824310SBarry Smith ap2 = ba + bi[row]; 582481824310SBarry Smith rmax2 = bimax[row]; 582581824310SBarry Smith nrow2 = bilen[row]; 582681824310SBarry Smith low2 = 0; 582781824310SBarry Smith high2 = nrow2; 582881824310SBarry Smith 582981824310SBarry Smith for (j=0; j<n; j++) { 583081824310SBarry Smith if (roworiented) value = v[i*n+j]; else value = v[i+j*m]; 583181824310SBarry Smith if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue; 583281824310SBarry Smith if (in[j] >= cstart && in[j] < cend){ 583381824310SBarry Smith col = in[j] - cstart; 583481824310SBarry Smith MatSetValues_SeqAIJ_A_Private(row,col,value,addv); 583581824310SBarry Smith } else if (in[j] < 0) continue; 583681824310SBarry Smith #if defined(PETSC_USE_DEBUG) 5837cb9801acSJed Brown else if (in[j] >= mat->cmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Column too large: col %D max %D",in[j],mat->cmap->N-1); 583881824310SBarry Smith #endif 583981824310SBarry Smith else { 584081824310SBarry Smith if (mat->was_assembled) { 584181824310SBarry Smith if (!aij->colmap) { 5842ab9863d7SBarry Smith ierr = MatCreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr); 584381824310SBarry Smith } 584481824310SBarry Smith #if defined (PETSC_USE_CTABLE) 584581824310SBarry Smith ierr = PetscTableFind(aij->colmap,in[j]+1,&col);CHKERRQ(ierr); 584681824310SBarry Smith col--; 584781824310SBarry Smith #else 584881824310SBarry Smith col = aij->colmap[in[j]] - 1; 584981824310SBarry Smith #endif 585081824310SBarry Smith if (col < 0 && !((Mat_SeqAIJ*)(aij->A->data))->nonew) { 5851ab9863d7SBarry Smith ierr = MatDisAssemble_MPIAIJ(mat);CHKERRQ(ierr); 585281824310SBarry Smith col = in[j]; 585381824310SBarry Smith /* Reinitialize the variables required by MatSetValues_SeqAIJ_B_Private() */ 585481824310SBarry Smith B = aij->B; 585581824310SBarry Smith b = (Mat_SeqAIJ*)B->data; 585681824310SBarry Smith bimax = b->imax; bi = b->i; bilen = b->ilen; bj = b->j; 585781824310SBarry Smith rp2 = bj + bi[row]; 585881824310SBarry Smith ap2 = ba + bi[row]; 585981824310SBarry Smith rmax2 = bimax[row]; 586081824310SBarry Smith nrow2 = bilen[row]; 586181824310SBarry Smith low2 = 0; 586281824310SBarry Smith high2 = nrow2; 5863d0f46423SBarry Smith bm = aij->B->rmap->n; 586481824310SBarry Smith ba = b->a; 586581824310SBarry Smith } 586681824310SBarry Smith } else col = in[j]; 586781824310SBarry Smith MatSetValues_SeqAIJ_B_Private(row,col,value,addv); 586881824310SBarry Smith } 586981824310SBarry Smith } 587081824310SBarry Smith } else { 587181824310SBarry Smith if (!aij->donotstash) { 587281824310SBarry Smith if (roworiented) { 5873ace3abfcSBarry Smith ierr = MatStashValuesRow_Private(&mat->stash,im[i],n,in,v+i*n,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr); 587481824310SBarry Smith } else { 5875ace3abfcSBarry Smith ierr = MatStashValuesCol_Private(&mat->stash,im[i],n,in,v+i,m,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr); 587681824310SBarry Smith } 587781824310SBarry Smith } 587881824310SBarry Smith } 587981824310SBarry Smith }} 588081824310SBarry Smith PetscFunctionReturnVoid(); 588181824310SBarry Smith } 588281824310SBarry Smith EXTERN_C_END 588303bfb495SBarry Smith 5884