18a729477SBarry Smith 274268593SBarry Smith 3c6db04a5SJed Brown #include <../src/mat/impls/aij/mpi/mpiaij.h> /*I "petscmat.h" I*/ 4af0996ceSBarry Smith #include <petsc/private/vecimpl.h> 53515ee7fSJunchao Zhang #include <petsc/private/vecscatterimpl.h> 6af0996ceSBarry Smith #include <petsc/private/isimpl.h> 7c6db04a5SJed Brown #include <petscblaslapack.h> 80c312b8eSJed Brown #include <petscsf.h> 98a729477SBarry Smith 1001bebe75SBarry Smith /*MC 1101bebe75SBarry Smith MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 1201bebe75SBarry Smith 1301bebe75SBarry Smith This matrix type is identical to MATSEQAIJ when constructed with a single process communicator, 1401bebe75SBarry Smith and MATMPIAIJ otherwise. As a result, for single process communicators, 15a323099bSStefano Zampini MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation() is supported 1601bebe75SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 1701bebe75SBarry Smith the above preallocation routines for simplicity. 1801bebe75SBarry Smith 1901bebe75SBarry Smith Options Database Keys: 2001bebe75SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions() 2101bebe75SBarry Smith 2295452b02SPatrick Sanan Developer Notes: 23ca9cdca7SRichard Tran Mills Subclasses include MATAIJCUSP, MATAIJCUSPARSE, MATAIJPERM, MATAIJSELL, MATAIJMKL, MATAIJCRL, and also automatically switches over to use inodes when 2401bebe75SBarry Smith enough exist. 2501bebe75SBarry Smith 2601bebe75SBarry Smith Level: beginner 2701bebe75SBarry Smith 2869b1f4b7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ, MATMPIAIJ 2901bebe75SBarry Smith M*/ 3001bebe75SBarry Smith 3101bebe75SBarry Smith /*MC 3201bebe75SBarry Smith MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 3301bebe75SBarry Smith 3401bebe75SBarry Smith This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator, 3501bebe75SBarry Smith and MATMPIAIJCRL otherwise. As a result, for single process communicators, 3601bebe75SBarry Smith MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 3701bebe75SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 3801bebe75SBarry Smith the above preallocation routines for simplicity. 3901bebe75SBarry Smith 4001bebe75SBarry Smith Options Database Keys: 4101bebe75SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions() 4201bebe75SBarry Smith 4301bebe75SBarry Smith Level: beginner 4401bebe75SBarry Smith 4501bebe75SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL 4601bebe75SBarry Smith M*/ 4701bebe75SBarry Smith 4846533700Sstefano_zampini PetscErrorCode MatSetBlockSizes_MPIAIJ(Mat M, PetscInt rbs, PetscInt cbs) 4926bda2c4Sstefano_zampini { 5026bda2c4Sstefano_zampini PetscErrorCode ierr; 5126bda2c4Sstefano_zampini Mat_MPIAIJ *mat = (Mat_MPIAIJ*)M->data; 5226bda2c4Sstefano_zampini 5326bda2c4Sstefano_zampini PetscFunctionBegin; 5446533700Sstefano_zampini if (mat->A) { 5526bda2c4Sstefano_zampini ierr = MatSetBlockSizes(mat->A,rbs,cbs);CHKERRQ(ierr); 5646533700Sstefano_zampini ierr = MatSetBlockSizes(mat->B,rbs,1);CHKERRQ(ierr); 5746533700Sstefano_zampini } 5826bda2c4Sstefano_zampini PetscFunctionReturn(0); 5926bda2c4Sstefano_zampini } 6026bda2c4Sstefano_zampini 61f2c98031SJed Brown PetscErrorCode MatFindNonzeroRows_MPIAIJ(Mat M,IS *keptrows) 6227d4218bSShri Abhyankar { 6327d4218bSShri Abhyankar PetscErrorCode ierr; 6427d4218bSShri Abhyankar Mat_MPIAIJ *mat = (Mat_MPIAIJ*)M->data; 6527d4218bSShri Abhyankar Mat_SeqAIJ *a = (Mat_SeqAIJ*)mat->A->data; 6627d4218bSShri Abhyankar Mat_SeqAIJ *b = (Mat_SeqAIJ*)mat->B->data; 6727d4218bSShri Abhyankar const PetscInt *ia,*ib; 6827d4218bSShri Abhyankar const MatScalar *aa,*bb; 6927d4218bSShri Abhyankar PetscInt na,nb,i,j,*rows,cnt=0,n0rows; 7027d4218bSShri Abhyankar PetscInt m = M->rmap->n,rstart = M->rmap->rstart; 7127d4218bSShri Abhyankar 7227d4218bSShri Abhyankar PetscFunctionBegin; 7327d4218bSShri Abhyankar *keptrows = 0; 7427d4218bSShri Abhyankar ia = a->i; 7527d4218bSShri Abhyankar ib = b->i; 7627d4218bSShri Abhyankar for (i=0; i<m; i++) { 7727d4218bSShri Abhyankar na = ia[i+1] - ia[i]; 7827d4218bSShri Abhyankar nb = ib[i+1] - ib[i]; 7927d4218bSShri Abhyankar if (!na && !nb) { 8027d4218bSShri Abhyankar cnt++; 8127d4218bSShri Abhyankar goto ok1; 8227d4218bSShri Abhyankar } 8327d4218bSShri Abhyankar aa = a->a + ia[i]; 8427d4218bSShri Abhyankar for (j=0; j<na; j++) { 8527d4218bSShri Abhyankar if (aa[j] != 0.0) goto ok1; 8627d4218bSShri Abhyankar } 8727d4218bSShri Abhyankar bb = b->a + ib[i]; 8827d4218bSShri Abhyankar for (j=0; j <nb; j++) { 8927d4218bSShri Abhyankar if (bb[j] != 0.0) goto ok1; 9027d4218bSShri Abhyankar } 9127d4218bSShri Abhyankar cnt++; 9227d4218bSShri Abhyankar ok1:; 9327d4218bSShri Abhyankar } 94b2566f29SBarry Smith ierr = MPIU_Allreduce(&cnt,&n0rows,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)M));CHKERRQ(ierr); 9527d4218bSShri Abhyankar if (!n0rows) PetscFunctionReturn(0); 96854ce69bSBarry Smith ierr = PetscMalloc1(M->rmap->n-cnt,&rows);CHKERRQ(ierr); 9727d4218bSShri Abhyankar cnt = 0; 9827d4218bSShri Abhyankar for (i=0; i<m; i++) { 9927d4218bSShri Abhyankar na = ia[i+1] - ia[i]; 10027d4218bSShri Abhyankar nb = ib[i+1] - ib[i]; 10127d4218bSShri Abhyankar if (!na && !nb) continue; 10227d4218bSShri Abhyankar aa = a->a + ia[i]; 10327d4218bSShri Abhyankar for (j=0; j<na;j++) { 10427d4218bSShri Abhyankar if (aa[j] != 0.0) { 10527d4218bSShri Abhyankar rows[cnt++] = rstart + i; 10627d4218bSShri Abhyankar goto ok2; 10727d4218bSShri Abhyankar } 10827d4218bSShri Abhyankar } 10927d4218bSShri Abhyankar bb = b->a + ib[i]; 11027d4218bSShri Abhyankar for (j=0; j<nb; j++) { 11127d4218bSShri Abhyankar if (bb[j] != 0.0) { 11227d4218bSShri Abhyankar rows[cnt++] = rstart + i; 11327d4218bSShri Abhyankar goto ok2; 11427d4218bSShri Abhyankar } 11527d4218bSShri Abhyankar } 11627d4218bSShri Abhyankar ok2:; 11727d4218bSShri Abhyankar } 118ce94432eSBarry Smith ierr = ISCreateGeneral(PetscObjectComm((PetscObject)M),cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr); 11927d4218bSShri Abhyankar PetscFunctionReturn(0); 12027d4218bSShri Abhyankar } 12127d4218bSShri Abhyankar 12299e65526SBarry Smith PetscErrorCode MatDiagonalSet_MPIAIJ(Mat Y,Vec D,InsertMode is) 12399e65526SBarry Smith { 12499e65526SBarry Smith PetscErrorCode ierr; 12599e65526SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*) Y->data; 12694342113SStefano Zampini PetscBool cong; 12799e65526SBarry Smith 12899e65526SBarry Smith PetscFunctionBegin; 12994342113SStefano Zampini ierr = MatHasCongruentLayouts(Y,&cong);CHKERRQ(ierr); 13094342113SStefano Zampini if (Y->assembled && cong) { 13199e65526SBarry Smith ierr = MatDiagonalSet(aij->A,D,is);CHKERRQ(ierr); 13299e65526SBarry Smith } else { 13399e65526SBarry Smith ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr); 13499e65526SBarry Smith } 13599e65526SBarry Smith PetscFunctionReturn(0); 13699e65526SBarry Smith } 13799e65526SBarry Smith 138f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_MPIAIJ(Mat M,IS *zrows) 139f1f41ecbSJed Brown { 140f1f41ecbSJed Brown Mat_MPIAIJ *aij = (Mat_MPIAIJ*)M->data; 141f1f41ecbSJed Brown PetscErrorCode ierr; 142f1f41ecbSJed Brown PetscInt i,rstart,nrows,*rows; 143f1f41ecbSJed Brown 144f1f41ecbSJed Brown PetscFunctionBegin; 1450298fd71SBarry Smith *zrows = NULL; 146f1f41ecbSJed Brown ierr = MatFindZeroDiagonals_SeqAIJ_Private(aij->A,&nrows,&rows);CHKERRQ(ierr); 1470298fd71SBarry Smith ierr = MatGetOwnershipRange(M,&rstart,NULL);CHKERRQ(ierr); 148f1f41ecbSJed Brown for (i=0; i<nrows; i++) rows[i] += rstart; 149ce94432eSBarry Smith ierr = ISCreateGeneral(PetscObjectComm((PetscObject)M),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr); 150f1f41ecbSJed Brown PetscFunctionReturn(0); 151f1f41ecbSJed Brown } 152f1f41ecbSJed Brown 1530716a85fSBarry Smith PetscErrorCode MatGetColumnNorms_MPIAIJ(Mat A,NormType type,PetscReal *norms) 1540716a85fSBarry Smith { 1550716a85fSBarry Smith PetscErrorCode ierr; 1560716a85fSBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)A->data; 1570716a85fSBarry Smith PetscInt i,n,*garray = aij->garray; 1580716a85fSBarry Smith Mat_SeqAIJ *a_aij = (Mat_SeqAIJ*) aij->A->data; 1590716a85fSBarry Smith Mat_SeqAIJ *b_aij = (Mat_SeqAIJ*) aij->B->data; 1600716a85fSBarry Smith PetscReal *work; 1610716a85fSBarry Smith 1620716a85fSBarry Smith PetscFunctionBegin; 1630298fd71SBarry Smith ierr = MatGetSize(A,NULL,&n);CHKERRQ(ierr); 1641795a4d1SJed Brown ierr = PetscCalloc1(n,&work);CHKERRQ(ierr); 1650716a85fSBarry Smith if (type == NORM_2) { 1660716a85fSBarry Smith for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) { 1670716a85fSBarry Smith work[A->cmap->rstart + a_aij->j[i]] += PetscAbsScalar(a_aij->a[i]*a_aij->a[i]); 1680716a85fSBarry Smith } 1690716a85fSBarry Smith for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) { 1700716a85fSBarry Smith work[garray[b_aij->j[i]]] += PetscAbsScalar(b_aij->a[i]*b_aij->a[i]); 1710716a85fSBarry Smith } 1720716a85fSBarry Smith } else if (type == NORM_1) { 1730716a85fSBarry Smith for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) { 1740716a85fSBarry Smith work[A->cmap->rstart + a_aij->j[i]] += PetscAbsScalar(a_aij->a[i]); 1750716a85fSBarry Smith } 1760716a85fSBarry Smith for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) { 1770716a85fSBarry Smith work[garray[b_aij->j[i]]] += PetscAbsScalar(b_aij->a[i]); 1780716a85fSBarry Smith } 1790716a85fSBarry Smith } else if (type == NORM_INFINITY) { 1800716a85fSBarry Smith for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) { 1810716a85fSBarry Smith work[A->cmap->rstart + a_aij->j[i]] = PetscMax(PetscAbsScalar(a_aij->a[i]), work[A->cmap->rstart + a_aij->j[i]]); 1820716a85fSBarry Smith } 1830716a85fSBarry Smith for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) { 1840716a85fSBarry Smith work[garray[b_aij->j[i]]] = PetscMax(PetscAbsScalar(b_aij->a[i]),work[garray[b_aij->j[i]]]); 1850716a85fSBarry Smith } 1860716a85fSBarry Smith 187ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Unknown NormType"); 1880716a85fSBarry Smith if (type == NORM_INFINITY) { 189b2566f29SBarry Smith ierr = MPIU_Allreduce(work,norms,n,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 1900716a85fSBarry Smith } else { 191b2566f29SBarry Smith ierr = MPIU_Allreduce(work,norms,n,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 1920716a85fSBarry Smith } 1930716a85fSBarry Smith ierr = PetscFree(work);CHKERRQ(ierr); 1940716a85fSBarry Smith if (type == NORM_2) { 1958f1a2a5eSBarry Smith for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]); 1960716a85fSBarry Smith } 1970716a85fSBarry Smith PetscFunctionReturn(0); 1980716a85fSBarry Smith } 1990716a85fSBarry Smith 200e52d2c62SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_MPIAIJ(Mat A,IS *is) 201e52d2c62SBarry Smith { 202e52d2c62SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 203e52d2c62SBarry Smith IS sis,gis; 204e52d2c62SBarry Smith PetscErrorCode ierr; 205e52d2c62SBarry Smith const PetscInt *isis,*igis; 206e52d2c62SBarry Smith PetscInt n,*iis,nsis,ngis,rstart,i; 207e52d2c62SBarry Smith 208e52d2c62SBarry Smith PetscFunctionBegin; 209e52d2c62SBarry Smith ierr = MatFindOffBlockDiagonalEntries(a->A,&sis);CHKERRQ(ierr); 210e52d2c62SBarry Smith ierr = MatFindNonzeroRows(a->B,&gis);CHKERRQ(ierr); 211e52d2c62SBarry Smith ierr = ISGetSize(gis,&ngis);CHKERRQ(ierr); 212e52d2c62SBarry Smith ierr = ISGetSize(sis,&nsis);CHKERRQ(ierr); 213e52d2c62SBarry Smith ierr = ISGetIndices(sis,&isis);CHKERRQ(ierr); 214e52d2c62SBarry Smith ierr = ISGetIndices(gis,&igis);CHKERRQ(ierr); 215e52d2c62SBarry Smith 216e52d2c62SBarry Smith ierr = PetscMalloc1(ngis+nsis,&iis);CHKERRQ(ierr); 217580bdb30SBarry Smith ierr = PetscArraycpy(iis,igis,ngis);CHKERRQ(ierr); 218580bdb30SBarry Smith ierr = PetscArraycpy(iis+ngis,isis,nsis);CHKERRQ(ierr); 219e52d2c62SBarry Smith n = ngis + nsis; 220e52d2c62SBarry Smith ierr = PetscSortRemoveDupsInt(&n,iis);CHKERRQ(ierr); 221e52d2c62SBarry Smith ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr); 222e52d2c62SBarry Smith for (i=0; i<n; i++) iis[i] += rstart; 223e52d2c62SBarry Smith ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),n,iis,PETSC_OWN_POINTER,is);CHKERRQ(ierr); 224e52d2c62SBarry Smith 225e52d2c62SBarry Smith ierr = ISRestoreIndices(sis,&isis);CHKERRQ(ierr); 226e52d2c62SBarry Smith ierr = ISRestoreIndices(gis,&igis);CHKERRQ(ierr); 227e52d2c62SBarry Smith ierr = ISDestroy(&sis);CHKERRQ(ierr); 228e52d2c62SBarry Smith ierr = ISDestroy(&gis);CHKERRQ(ierr); 229e52d2c62SBarry Smith PetscFunctionReturn(0); 230e52d2c62SBarry Smith } 231e52d2c62SBarry Smith 232dd6ea824SBarry Smith /* 233dd6ea824SBarry Smith Distributes a SeqAIJ matrix across a set of processes. Code stolen from 234dd6ea824SBarry Smith MatLoad_MPIAIJ(). Horrible lack of reuse. Should be a routine for each matrix type. 235dd6ea824SBarry Smith 236dd6ea824SBarry Smith Only for square matrices 237b30237c6SBarry Smith 238b30237c6SBarry Smith Used by a preconditioner, hence PETSC_EXTERN 239dd6ea824SBarry Smith */ 2405a576424SJed Brown PETSC_EXTERN PetscErrorCode MatDistribute_MPIAIJ(MPI_Comm comm,Mat gmat,PetscInt m,MatReuse reuse,Mat *inmat) 241dd6ea824SBarry Smith { 242dd6ea824SBarry Smith PetscMPIInt rank,size; 243d892089bSMatthew G. Knepley PetscInt *rowners,*dlens,*olens,i,rstart,rend,j,jj,nz = 0,*gmataj,cnt,row,*ld,bses[2]; 244dd6ea824SBarry Smith PetscErrorCode ierr; 245dd6ea824SBarry Smith Mat mat; 246dd6ea824SBarry Smith Mat_SeqAIJ *gmata; 247dd6ea824SBarry Smith PetscMPIInt tag; 248dd6ea824SBarry Smith MPI_Status status; 249ace3abfcSBarry Smith PetscBool aij; 250dd6ea824SBarry Smith MatScalar *gmataa,*ao,*ad,*gmataarestore=0; 251dd6ea824SBarry Smith 252dd6ea824SBarry Smith PetscFunctionBegin; 253dd6ea824SBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 254dd6ea824SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 255dd6ea824SBarry Smith if (!rank) { 256251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)gmat,MATSEQAIJ,&aij);CHKERRQ(ierr); 257ce94432eSBarry Smith if (!aij) SETERRQ1(PetscObjectComm((PetscObject)gmat),PETSC_ERR_SUP,"Currently no support for input matrix of type %s\n",((PetscObject)gmat)->type_name); 258dd6ea824SBarry Smith } 259dd6ea824SBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 260dd6ea824SBarry Smith ierr = MatCreate(comm,&mat);CHKERRQ(ierr); 261dd6ea824SBarry Smith ierr = MatSetSizes(mat,m,m,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 26233d57670SJed Brown ierr = MatGetBlockSizes(gmat,&bses[0],&bses[1]);CHKERRQ(ierr); 263efcf75d5SBarry Smith ierr = MPI_Bcast(bses,2,MPIU_INT,0,comm);CHKERRQ(ierr); 264efcf75d5SBarry Smith ierr = MatSetBlockSizes(mat,bses[0],bses[1]);CHKERRQ(ierr); 265dd6ea824SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 266854ce69bSBarry Smith ierr = PetscMalloc1(size+1,&rowners);CHKERRQ(ierr); 267dcca6d9dSJed Brown ierr = PetscMalloc2(m,&dlens,m,&olens);CHKERRQ(ierr); 268dd6ea824SBarry Smith ierr = MPI_Allgather(&m,1,MPIU_INT,rowners+1,1,MPIU_INT,comm);CHKERRQ(ierr); 2692205254eSKarl Rupp 270dd6ea824SBarry Smith rowners[0] = 0; 2712205254eSKarl Rupp for (i=2; i<=size; i++) rowners[i] += rowners[i-1]; 272dd6ea824SBarry Smith rstart = rowners[rank]; 273dd6ea824SBarry Smith rend = rowners[rank+1]; 274dd6ea824SBarry Smith ierr = PetscObjectGetNewTag((PetscObject)mat,&tag);CHKERRQ(ierr); 275dd6ea824SBarry Smith if (!rank) { 276dd6ea824SBarry Smith gmata = (Mat_SeqAIJ*) gmat->data; 277dd6ea824SBarry Smith /* send row lengths to all processors */ 278dd6ea824SBarry Smith for (i=0; i<m; i++) dlens[i] = gmata->ilen[i]; 279dd6ea824SBarry Smith for (i=1; i<size; i++) { 280dd6ea824SBarry Smith ierr = MPI_Send(gmata->ilen + rowners[i],rowners[i+1]-rowners[i],MPIU_INT,i,tag,comm);CHKERRQ(ierr); 281dd6ea824SBarry Smith } 282dd6ea824SBarry Smith /* determine number diagonal and off-diagonal counts */ 283580bdb30SBarry Smith ierr = PetscArrayzero(olens,m);CHKERRQ(ierr); 2841795a4d1SJed Brown ierr = PetscCalloc1(m,&ld);CHKERRQ(ierr); 285dd6ea824SBarry Smith jj = 0; 286dd6ea824SBarry Smith for (i=0; i<m; i++) { 287dd6ea824SBarry Smith for (j=0; j<dlens[i]; j++) { 288dd6ea824SBarry Smith if (gmata->j[jj] < rstart) ld[i]++; 289dd6ea824SBarry Smith if (gmata->j[jj] < rstart || gmata->j[jj] >= rend) olens[i]++; 290dd6ea824SBarry Smith jj++; 291dd6ea824SBarry Smith } 292dd6ea824SBarry Smith } 293dd6ea824SBarry Smith /* send column indices to other processes */ 294dd6ea824SBarry Smith for (i=1; i<size; i++) { 295dd6ea824SBarry Smith nz = gmata->i[rowners[i+1]]-gmata->i[rowners[i]]; 296dd6ea824SBarry Smith ierr = MPI_Send(&nz,1,MPIU_INT,i,tag,comm);CHKERRQ(ierr); 297dd6ea824SBarry Smith ierr = MPI_Send(gmata->j + gmata->i[rowners[i]],nz,MPIU_INT,i,tag,comm);CHKERRQ(ierr); 298dd6ea824SBarry Smith } 299dd6ea824SBarry Smith 300dd6ea824SBarry Smith /* send numerical values to other processes */ 301dd6ea824SBarry Smith for (i=1; i<size; i++) { 302dd6ea824SBarry Smith nz = gmata->i[rowners[i+1]]-gmata->i[rowners[i]]; 303dd6ea824SBarry Smith ierr = MPI_Send(gmata->a + gmata->i[rowners[i]],nz,MPIU_SCALAR,i,tag,comm);CHKERRQ(ierr); 304dd6ea824SBarry Smith } 305dd6ea824SBarry Smith gmataa = gmata->a; 306dd6ea824SBarry Smith gmataj = gmata->j; 307dd6ea824SBarry Smith 308dd6ea824SBarry Smith } else { 309dd6ea824SBarry Smith /* receive row lengths */ 310dd6ea824SBarry Smith ierr = MPI_Recv(dlens,m,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr); 311dd6ea824SBarry Smith /* receive column indices */ 312dd6ea824SBarry Smith ierr = MPI_Recv(&nz,1,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr); 313dcca6d9dSJed Brown ierr = PetscMalloc2(nz,&gmataa,nz,&gmataj);CHKERRQ(ierr); 314dd6ea824SBarry Smith ierr = MPI_Recv(gmataj,nz,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr); 315dd6ea824SBarry Smith /* determine number diagonal and off-diagonal counts */ 316580bdb30SBarry Smith ierr = PetscArrayzero(olens,m);CHKERRQ(ierr); 3171795a4d1SJed Brown ierr = PetscCalloc1(m,&ld);CHKERRQ(ierr); 318dd6ea824SBarry Smith jj = 0; 319dd6ea824SBarry Smith for (i=0; i<m; i++) { 320dd6ea824SBarry Smith for (j=0; j<dlens[i]; j++) { 321dd6ea824SBarry Smith if (gmataj[jj] < rstart) ld[i]++; 322dd6ea824SBarry Smith if (gmataj[jj] < rstart || gmataj[jj] >= rend) olens[i]++; 323dd6ea824SBarry Smith jj++; 324dd6ea824SBarry Smith } 325dd6ea824SBarry Smith } 326dd6ea824SBarry Smith /* receive numerical values */ 327580bdb30SBarry Smith ierr = PetscArrayzero(gmataa,nz);CHKERRQ(ierr); 328dd6ea824SBarry Smith ierr = MPI_Recv(gmataa,nz,MPIU_SCALAR,0,tag,comm,&status);CHKERRQ(ierr); 329dd6ea824SBarry Smith } 330dd6ea824SBarry Smith /* set preallocation */ 331dd6ea824SBarry Smith for (i=0; i<m; i++) { 332dd6ea824SBarry Smith dlens[i] -= olens[i]; 333dd6ea824SBarry Smith } 334dd6ea824SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dlens);CHKERRQ(ierr); 335dd6ea824SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dlens,0,olens);CHKERRQ(ierr); 336dd6ea824SBarry Smith 337dd6ea824SBarry Smith for (i=0; i<m; i++) { 338dd6ea824SBarry Smith dlens[i] += olens[i]; 339dd6ea824SBarry Smith } 340dd6ea824SBarry Smith cnt = 0; 341dd6ea824SBarry Smith for (i=0; i<m; i++) { 342dd6ea824SBarry Smith row = rstart + i; 343dd6ea824SBarry Smith ierr = MatSetValues(mat,1,&row,dlens[i],gmataj+cnt,gmataa+cnt,INSERT_VALUES);CHKERRQ(ierr); 344dd6ea824SBarry Smith cnt += dlens[i]; 345dd6ea824SBarry Smith } 346dd6ea824SBarry Smith if (rank) { 347dd6ea824SBarry Smith ierr = PetscFree2(gmataa,gmataj);CHKERRQ(ierr); 348dd6ea824SBarry Smith } 349dd6ea824SBarry Smith ierr = PetscFree2(dlens,olens);CHKERRQ(ierr); 350dd6ea824SBarry Smith ierr = PetscFree(rowners);CHKERRQ(ierr); 3512205254eSKarl Rupp 352dd6ea824SBarry Smith ((Mat_MPIAIJ*)(mat->data))->ld = ld; 3532205254eSKarl Rupp 354dd6ea824SBarry Smith *inmat = mat; 355dd6ea824SBarry Smith } else { /* column indices are already set; only need to move over numerical values from process 0 */ 356dd6ea824SBarry Smith Mat_SeqAIJ *Ad = (Mat_SeqAIJ*)((Mat_MPIAIJ*)((*inmat)->data))->A->data; 357dd6ea824SBarry Smith Mat_SeqAIJ *Ao = (Mat_SeqAIJ*)((Mat_MPIAIJ*)((*inmat)->data))->B->data; 358dd6ea824SBarry Smith mat = *inmat; 359dd6ea824SBarry Smith ierr = PetscObjectGetNewTag((PetscObject)mat,&tag);CHKERRQ(ierr); 360dd6ea824SBarry Smith if (!rank) { 361dd6ea824SBarry Smith /* send numerical values to other processes */ 362dd6ea824SBarry Smith gmata = (Mat_SeqAIJ*) gmat->data; 363dd6ea824SBarry Smith ierr = MatGetOwnershipRanges(mat,(const PetscInt**)&rowners);CHKERRQ(ierr); 364dd6ea824SBarry Smith gmataa = gmata->a; 365dd6ea824SBarry Smith for (i=1; i<size; i++) { 366dd6ea824SBarry Smith nz = gmata->i[rowners[i+1]]-gmata->i[rowners[i]]; 367dd6ea824SBarry Smith ierr = MPI_Send(gmataa + gmata->i[rowners[i]],nz,MPIU_SCALAR,i,tag,comm);CHKERRQ(ierr); 368dd6ea824SBarry Smith } 369dd6ea824SBarry Smith nz = gmata->i[rowners[1]]-gmata->i[rowners[0]]; 370dd6ea824SBarry Smith } else { 371dd6ea824SBarry Smith /* receive numerical values from process 0*/ 372dd6ea824SBarry Smith nz = Ad->nz + Ao->nz; 373785e854fSJed Brown ierr = PetscMalloc1(nz,&gmataa);CHKERRQ(ierr); gmataarestore = gmataa; 374dd6ea824SBarry Smith ierr = MPI_Recv(gmataa,nz,MPIU_SCALAR,0,tag,comm,&status);CHKERRQ(ierr); 375dd6ea824SBarry Smith } 376dd6ea824SBarry Smith /* transfer numerical values into the diagonal A and off diagonal B parts of mat */ 377dd6ea824SBarry Smith ld = ((Mat_MPIAIJ*)(mat->data))->ld; 378dd6ea824SBarry Smith ad = Ad->a; 379dd6ea824SBarry Smith ao = Ao->a; 380d0f46423SBarry Smith if (mat->rmap->n) { 381dd6ea824SBarry Smith i = 0; 382580bdb30SBarry Smith nz = ld[i]; ierr = PetscArraycpy(ao,gmataa,nz);CHKERRQ(ierr); ao += nz; gmataa += nz; 383580bdb30SBarry Smith nz = Ad->i[i+1] - Ad->i[i]; ierr = PetscArraycpy(ad,gmataa,nz);CHKERRQ(ierr); ad += nz; gmataa += nz; 384dd6ea824SBarry Smith } 385d0f46423SBarry Smith for (i=1; i<mat->rmap->n; i++) { 386580bdb30SBarry Smith nz = Ao->i[i] - Ao->i[i-1] - ld[i-1] + ld[i]; ierr = PetscArraycpy(ao,gmataa,nz);CHKERRQ(ierr); ao += nz; gmataa += nz; 387580bdb30SBarry Smith nz = Ad->i[i+1] - Ad->i[i]; ierr = PetscArraycpy(ad,gmataa,nz);CHKERRQ(ierr); ad += nz; gmataa += nz; 388dd6ea824SBarry Smith } 389dd6ea824SBarry Smith i--; 390d0f46423SBarry Smith if (mat->rmap->n) { 391580bdb30SBarry Smith nz = Ao->i[i+1] - Ao->i[i] - ld[i]; ierr = PetscArraycpy(ao,gmataa,nz);CHKERRQ(ierr); 392dd6ea824SBarry Smith } 393dd6ea824SBarry Smith if (rank) { 394dd6ea824SBarry Smith ierr = PetscFree(gmataarestore);CHKERRQ(ierr); 395dd6ea824SBarry Smith } 396dd6ea824SBarry Smith } 397dd6ea824SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 398dd6ea824SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 399dd6ea824SBarry Smith PetscFunctionReturn(0); 400dd6ea824SBarry Smith } 401dd6ea824SBarry Smith 4020f5bd95cSBarry Smith /* 4030f5bd95cSBarry Smith Local utility routine that creates a mapping from the global column 4049e25ed09SBarry Smith number to the local number in the off-diagonal part of the local 4050f5bd95cSBarry Smith storage of the matrix. When PETSC_USE_CTABLE is used this is scalable at 4060f5bd95cSBarry Smith a slightly higher hash table cost; without it it is not scalable (each processor 4070f5bd95cSBarry Smith has an order N integer array but is fast to acess. 4089e25ed09SBarry Smith */ 409ab9863d7SBarry Smith PetscErrorCode MatCreateColmap_MPIAIJ_Private(Mat mat) 4109e25ed09SBarry Smith { 41144a69424SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 4126849ba73SBarry Smith PetscErrorCode ierr; 413d0f46423SBarry Smith PetscInt n = aij->B->cmap->n,i; 414dbb450caSBarry Smith 4153a40ed3dSBarry Smith PetscFunctionBegin; 4165e1f6667SBarry Smith if (!aij->garray) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"MPIAIJ Matrix was assembled but is missing garray"); 417aa482453SBarry Smith #if defined(PETSC_USE_CTABLE) 418e23dfa41SBarry Smith ierr = PetscTableCreate(n,mat->cmap->N+1,&aij->colmap);CHKERRQ(ierr); 419b1fc9764SSatish Balay for (i=0; i<n; i++) { 4203861aac3SJed Brown ierr = PetscTableAdd(aij->colmap,aij->garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr); 421b1fc9764SSatish Balay } 422b1fc9764SSatish Balay #else 423854ce69bSBarry Smith ierr = PetscCalloc1(mat->cmap->N+1,&aij->colmap);CHKERRQ(ierr); 4241795a4d1SJed Brown ierr = PetscLogObjectMemory((PetscObject)mat,(mat->cmap->N+1)*sizeof(PetscInt));CHKERRQ(ierr); 425905e6a2fSBarry Smith for (i=0; i<n; i++) aij->colmap[aij->garray[i]] = i+1; 426b1fc9764SSatish Balay #endif 4273a40ed3dSBarry Smith PetscFunctionReturn(0); 4289e25ed09SBarry Smith } 4299e25ed09SBarry Smith 430d40312a9SBarry Smith #define MatSetValues_SeqAIJ_A_Private(row,col,value,addv,orow,ocol) \ 4310520107fSSatish Balay { \ 432db4deed7SKarl Rupp if (col <= lastcol1) low1 = 0; \ 433db4deed7SKarl Rupp else high1 = nrow1; \ 434fd3458f5SBarry Smith lastcol1 = col;\ 435fd3458f5SBarry Smith while (high1-low1 > 5) { \ 436fd3458f5SBarry Smith t = (low1+high1)/2; \ 437fd3458f5SBarry Smith if (rp1[t] > col) high1 = t; \ 438fd3458f5SBarry Smith else low1 = t; \ 439ba4e3ef2SSatish Balay } \ 440fd3458f5SBarry Smith for (_i=low1; _i<high1; _i++) { \ 441fd3458f5SBarry Smith if (rp1[_i] > col) break; \ 442fd3458f5SBarry Smith if (rp1[_i] == col) { \ 4430c0d7e18SFande Kong if (addv == ADD_VALUES) { \ 4440c0d7e18SFande Kong ap1[_i] += value; \ 4450c0d7e18SFande Kong /* Not sure LogFlops will slow dow the code or not */ \ 4460c0d7e18SFande Kong (void)PetscLogFlops(1.0); \ 4470c0d7e18SFande Kong } \ 448fd3458f5SBarry Smith else ap1[_i] = value; \ 44930770e4dSSatish Balay goto a_noinsert; \ 4500520107fSSatish Balay } \ 4510520107fSSatish Balay } \ 452dcd36c23SBarry Smith if (value == 0.0 && ignorezeroentries && row != col) {low1 = 0; high1 = nrow1;goto a_noinsert;} \ 453e44c0bd4SBarry Smith if (nonew == 1) {low1 = 0; high1 = nrow1; goto a_noinsert;} \ 454d40312a9SBarry Smith if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at global row/column (%D, %D) into matrix", orow, ocol); \ 455fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A,am,1,nrow1,row,col,rmax1,aa,ai,aj,rp1,ap1,aimax,nonew,MatScalar); \ 456669a8dbcSSatish Balay N = nrow1++ - 1; a->nz++; high1++; \ 4570520107fSSatish Balay /* shift up all the later entries in this row */ \ 458580bdb30SBarry Smith ierr = PetscArraymove(rp1+_i+1,rp1+_i,N-_i+1);CHKERRQ(ierr);\ 459580bdb30SBarry Smith ierr = PetscArraymove(ap1+_i+1,ap1+_i,N-_i+1);CHKERRQ(ierr);\ 460fd3458f5SBarry Smith rp1[_i] = col; \ 461fd3458f5SBarry Smith ap1[_i] = value; \ 462e56f5c9eSBarry Smith A->nonzerostate++;\ 46330770e4dSSatish Balay a_noinsert: ; \ 464fd3458f5SBarry Smith ailen[row] = nrow1; \ 4650520107fSSatish Balay } 4660a198c4cSBarry Smith 467d40312a9SBarry Smith #define MatSetValues_SeqAIJ_B_Private(row,col,value,addv,orow,ocol) \ 46830770e4dSSatish Balay { \ 469db4deed7SKarl Rupp if (col <= lastcol2) low2 = 0; \ 470db4deed7SKarl Rupp else high2 = nrow2; \ 471fd3458f5SBarry Smith lastcol2 = col; \ 472fd3458f5SBarry Smith while (high2-low2 > 5) { \ 473fd3458f5SBarry Smith t = (low2+high2)/2; \ 474fd3458f5SBarry Smith if (rp2[t] > col) high2 = t; \ 475fd3458f5SBarry Smith else low2 = t; \ 476ba4e3ef2SSatish Balay } \ 477fd3458f5SBarry Smith for (_i=low2; _i<high2; _i++) { \ 478fd3458f5SBarry Smith if (rp2[_i] > col) break; \ 479fd3458f5SBarry Smith if (rp2[_i] == col) { \ 4800c0d7e18SFande Kong if (addv == ADD_VALUES) { \ 4810c0d7e18SFande Kong ap2[_i] += value; \ 4820c0d7e18SFande Kong (void)PetscLogFlops(1.0); \ 4830c0d7e18SFande Kong } \ 484fd3458f5SBarry Smith else ap2[_i] = value; \ 48530770e4dSSatish Balay goto b_noinsert; \ 48630770e4dSSatish Balay } \ 48730770e4dSSatish Balay } \ 488e44c0bd4SBarry Smith if (value == 0.0 && ignorezeroentries) {low2 = 0; high2 = nrow2; goto b_noinsert;} \ 489e44c0bd4SBarry Smith if (nonew == 1) {low2 = 0; high2 = nrow2; goto b_noinsert;} \ 490d40312a9SBarry Smith if (nonew == -1) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at global row/column (%D, %D) into matrix", orow, ocol); \ 491fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(B,bm,1,nrow2,row,col,rmax2,ba,bi,bj,rp2,ap2,bimax,nonew,MatScalar); \ 492669a8dbcSSatish Balay N = nrow2++ - 1; b->nz++; high2++; \ 49330770e4dSSatish Balay /* shift up all the later entries in this row */ \ 494580bdb30SBarry Smith ierr = PetscArraymove(rp2+_i+1,rp2+_i,N-_i+1);CHKERRQ(ierr);\ 495580bdb30SBarry Smith ierr = PetscArraymove(ap2+_i+1,ap2+_i,N-_i+1);CHKERRQ(ierr);\ 496fd3458f5SBarry Smith rp2[_i] = col; \ 497fd3458f5SBarry Smith ap2[_i] = value; \ 498e56f5c9eSBarry Smith B->nonzerostate++; \ 49930770e4dSSatish Balay b_noinsert: ; \ 500fd3458f5SBarry Smith bilen[row] = nrow2; \ 50130770e4dSSatish Balay } 50230770e4dSSatish Balay 5032fd7e33dSBarry Smith PetscErrorCode MatSetValuesRow_MPIAIJ(Mat A,PetscInt row,const PetscScalar v[]) 5042fd7e33dSBarry Smith { 5052fd7e33dSBarry Smith Mat_MPIAIJ *mat = (Mat_MPIAIJ*)A->data; 5062fd7e33dSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)mat->A->data,*b = (Mat_SeqAIJ*)mat->B->data; 5072fd7e33dSBarry Smith PetscErrorCode ierr; 5082fd7e33dSBarry Smith PetscInt l,*garray = mat->garray,diag; 5092fd7e33dSBarry Smith 5102fd7e33dSBarry Smith PetscFunctionBegin; 5112fd7e33dSBarry Smith /* code only works for square matrices A */ 5122fd7e33dSBarry Smith 5132fd7e33dSBarry Smith /* find size of row to the left of the diagonal part */ 5142fd7e33dSBarry Smith ierr = MatGetOwnershipRange(A,&diag,0);CHKERRQ(ierr); 5152fd7e33dSBarry Smith row = row - diag; 5162fd7e33dSBarry Smith for (l=0; l<b->i[row+1]-b->i[row]; l++) { 5172fd7e33dSBarry Smith if (garray[b->j[b->i[row]+l]] > diag) break; 5182fd7e33dSBarry Smith } 519580bdb30SBarry Smith ierr = PetscArraycpy(b->a+b->i[row],v,l);CHKERRQ(ierr); 5202fd7e33dSBarry Smith 5212fd7e33dSBarry Smith /* diagonal part */ 522580bdb30SBarry Smith ierr = PetscArraycpy(a->a+a->i[row],v+l,(a->i[row+1]-a->i[row]));CHKERRQ(ierr); 5232fd7e33dSBarry Smith 5242fd7e33dSBarry Smith /* right of diagonal part */ 525580bdb30SBarry Smith ierr = PetscArraycpy(b->a+b->i[row]+l,v+l+a->i[row+1]-a->i[row],b->i[row+1]-b->i[row]-l);CHKERRQ(ierr); 5262fd7e33dSBarry Smith PetscFunctionReturn(0); 5272fd7e33dSBarry Smith } 5282fd7e33dSBarry Smith 529b1d57f15SBarry Smith PetscErrorCode MatSetValues_MPIAIJ(Mat mat,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode addv) 5308a729477SBarry Smith { 53144a69424SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 532*071fcb05SBarry Smith PetscScalar value = 0.0; 533dfbe8321SBarry Smith PetscErrorCode ierr; 534d0f46423SBarry Smith PetscInt i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend; 535d0f46423SBarry Smith PetscInt cstart = mat->cmap->rstart,cend = mat->cmap->rend,row,col; 536ace3abfcSBarry Smith PetscBool roworiented = aij->roworiented; 5378a729477SBarry Smith 5380520107fSSatish Balay /* Some Variables required in the macro */ 5394ee7247eSSatish Balay Mat A = aij->A; 5404ee7247eSSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 54157809a77SBarry Smith PetscInt *aimax = a->imax,*ai = a->i,*ailen = a->ilen,*aj = a->j; 542a77337e4SBarry Smith MatScalar *aa = a->a; 543ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 54430770e4dSSatish Balay Mat B = aij->B; 54530770e4dSSatish Balay Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 546d0f46423SBarry Smith PetscInt *bimax = b->imax,*bi = b->i,*bilen = b->ilen,*bj = b->j,bm = aij->B->rmap->n,am = aij->A->rmap->n; 547a77337e4SBarry Smith MatScalar *ba = b->a; 54830770e4dSSatish Balay 549fd3458f5SBarry Smith PetscInt *rp1,*rp2,ii,nrow1,nrow2,_i,rmax1,rmax2,N,low1,high1,low2,high2,t,lastcol1,lastcol2; 5508d76821aSHong Zhang PetscInt nonew; 551a77337e4SBarry Smith MatScalar *ap1,*ap2; 5524ee7247eSSatish Balay 5533a40ed3dSBarry Smith PetscFunctionBegin; 5548a729477SBarry Smith for (i=0; i<m; i++) { 5555ef9f2a5SBarry Smith if (im[i] < 0) continue; 5562515c552SBarry Smith #if defined(PETSC_USE_DEBUG) 557e32f2f54SBarry 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); 5580a198c4cSBarry Smith #endif 5594b0e389bSBarry Smith if (im[i] >= rstart && im[i] < rend) { 5604b0e389bSBarry Smith row = im[i] - rstart; 561fd3458f5SBarry Smith lastcol1 = -1; 562fd3458f5SBarry Smith rp1 = aj + ai[row]; 563fd3458f5SBarry Smith ap1 = aa + ai[row]; 564fd3458f5SBarry Smith rmax1 = aimax[row]; 565fd3458f5SBarry Smith nrow1 = ailen[row]; 566fd3458f5SBarry Smith low1 = 0; 567fd3458f5SBarry Smith high1 = nrow1; 568fd3458f5SBarry Smith lastcol2 = -1; 569fd3458f5SBarry Smith rp2 = bj + bi[row]; 570d498b1e9SBarry Smith ap2 = ba + bi[row]; 571fd3458f5SBarry Smith rmax2 = bimax[row]; 572d498b1e9SBarry Smith nrow2 = bilen[row]; 573fd3458f5SBarry Smith low2 = 0; 574fd3458f5SBarry Smith high2 = nrow2; 575fd3458f5SBarry Smith 5761eb62cbbSBarry Smith for (j=0; j<n; j++) { 577*071fcb05SBarry Smith if (v) value = roworiented ? v[i*n+j] : v[i+j*m]; 578fd3458f5SBarry Smith if (in[j] >= cstart && in[j] < cend) { 579fd3458f5SBarry Smith col = in[j] - cstart; 5808d76821aSHong Zhang nonew = a->nonew; 581dcd36c23SBarry Smith if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES) && row != col) continue; 582d40312a9SBarry Smith MatSetValues_SeqAIJ_A_Private(row,col,value,addv,im[i],in[j]); 583273d9f13SBarry Smith } else if (in[j] < 0) continue; 5842515c552SBarry Smith #if defined(PETSC_USE_DEBUG) 585cb9801acSJed 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); 5860a198c4cSBarry Smith #endif 5871eb62cbbSBarry Smith else { 588227d817aSBarry Smith if (mat->was_assembled) { 589905e6a2fSBarry Smith if (!aij->colmap) { 590ab9863d7SBarry Smith ierr = MatCreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr); 591905e6a2fSBarry Smith } 592aa482453SBarry Smith #if defined(PETSC_USE_CTABLE) 5930f5bd95cSBarry Smith ierr = PetscTableFind(aij->colmap,in[j]+1,&col);CHKERRQ(ierr); 594fa46199cSSatish Balay col--; 595b1fc9764SSatish Balay #else 596905e6a2fSBarry Smith col = aij->colmap[in[j]] - 1; 597b1fc9764SSatish Balay #endif 5980e9bae81SBarry Smith if (col < 0 && !((Mat_SeqAIJ*)(aij->B->data))->nonew) { 599ab9863d7SBarry Smith ierr = MatDisAssemble_MPIAIJ(mat);CHKERRQ(ierr); 6004b0e389bSBarry Smith col = in[j]; 6019bf004c3SSatish Balay /* Reinitialize the variables required by MatSetValues_SeqAIJ_B_Private() */ 602f9508a3cSSatish Balay B = aij->B; 603f9508a3cSSatish Balay b = (Mat_SeqAIJ*)B->data; 604e44c0bd4SBarry Smith bimax = b->imax; bi = b->i; bilen = b->ilen; bj = b->j; ba = b->a; 605d498b1e9SBarry Smith rp2 = bj + bi[row]; 606d498b1e9SBarry Smith ap2 = ba + bi[row]; 607d498b1e9SBarry Smith rmax2 = bimax[row]; 608d498b1e9SBarry Smith nrow2 = bilen[row]; 609d498b1e9SBarry Smith low2 = 0; 610d498b1e9SBarry Smith high2 = nrow2; 611d0f46423SBarry Smith bm = aij->B->rmap->n; 612f9508a3cSSatish Balay ba = b->a; 6130587a0fcSBarry Smith } else if (col < 0) { 6140587a0fcSBarry Smith if (1 == ((Mat_SeqAIJ*)(aij->B->data))->nonew) { 61521c5b617SBarry Smith ierr = PetscInfo3(mat,"Skipping of insertion of new nonzero location in off-diagonal portion of matrix %g(%D,%D)\n",(double)PetscRealPart(value),im[i],in[j]);CHKERRQ(ierr); 6160587a0fcSBarry Smith } else SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at global row/column (%D, %D) into matrix", im[i], in[j]); 6170587a0fcSBarry Smith } 618c48de900SBarry Smith } else col = in[j]; 6198d76821aSHong Zhang nonew = b->nonew; 620d40312a9SBarry Smith MatSetValues_SeqAIJ_B_Private(row,col,value,addv,im[i],in[j]); 6211eb62cbbSBarry Smith } 6221eb62cbbSBarry Smith } 6235ef9f2a5SBarry Smith } else { 6244cb17eb5SBarry 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]); 62590f02eecSBarry Smith if (!aij->donotstash) { 6265080c13bSMatthew G Knepley mat->assembled = PETSC_FALSE; 627d36fbae8SSatish Balay if (roworiented) { 628ace3abfcSBarry Smith ierr = MatStashValuesRow_Private(&mat->stash,im[i],n,in,v+i*n,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr); 629d36fbae8SSatish Balay } else { 630ace3abfcSBarry Smith ierr = MatStashValuesCol_Private(&mat->stash,im[i],n,in,v+i,m,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr); 6314b0e389bSBarry Smith } 6321eb62cbbSBarry Smith } 6338a729477SBarry Smith } 63490f02eecSBarry Smith } 6353a40ed3dSBarry Smith PetscFunctionReturn(0); 6368a729477SBarry Smith } 6378a729477SBarry Smith 6382b08fdbeSandi selinger /* 639904d1e70Sandi selinger This function sets the j and ilen arrays (of the diagonal and off-diagonal part) of an MPIAIJ-matrix. 6402b08fdbeSandi selinger The values in mat_i have to be sorted and the values in mat_j have to be sorted for each row (CSR-like). 641904d1e70Sandi selinger No off-processor parts off the matrix are allowed here and mat->was_assembled has to be PETSC_FALSE. 6422b08fdbeSandi selinger */ 643904d1e70Sandi selinger PetscErrorCode MatSetValues_MPIAIJ_CopyFromCSRFormat_Symbolic(Mat mat,const PetscInt mat_j[],const PetscInt mat_i[]) 644904d1e70Sandi selinger { 645904d1e70Sandi selinger Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 646904d1e70Sandi selinger Mat A = aij->A; /* diagonal part of the matrix */ 647904d1e70Sandi selinger Mat B = aij->B; /* offdiagonal part of the matrix */ 648904d1e70Sandi selinger Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 649904d1e70Sandi selinger Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 650904d1e70Sandi selinger PetscInt cstart = mat->cmap->rstart,cend = mat->cmap->rend,col; 651904d1e70Sandi selinger PetscInt *ailen = a->ilen,*aj = a->j; 652904d1e70Sandi selinger PetscInt *bilen = b->ilen,*bj = b->j; 6536dc1ffa3Sandi selinger PetscInt am = aij->A->rmap->n,j; 654904d1e70Sandi selinger PetscInt diag_so_far = 0,dnz; 655904d1e70Sandi selinger PetscInt offd_so_far = 0,onz; 656904d1e70Sandi selinger 657904d1e70Sandi selinger PetscFunctionBegin; 658904d1e70Sandi selinger /* Iterate over all rows of the matrix */ 659904d1e70Sandi selinger for (j=0; j<am; j++) { 660904d1e70Sandi selinger dnz = onz = 0; 661904d1e70Sandi selinger /* Iterate over all non-zero columns of the current row */ 6626dc1ffa3Sandi selinger for (col=mat_i[j]; col<mat_i[j+1]; col++) { 663904d1e70Sandi selinger /* If column is in the diagonal */ 664904d1e70Sandi selinger if (mat_j[col] >= cstart && mat_j[col] < cend) { 665904d1e70Sandi selinger aj[diag_so_far++] = mat_j[col] - cstart; 666904d1e70Sandi selinger dnz++; 667904d1e70Sandi selinger } else { /* off-diagonal entries */ 668904d1e70Sandi selinger bj[offd_so_far++] = mat_j[col]; 669904d1e70Sandi selinger onz++; 670904d1e70Sandi selinger } 671904d1e70Sandi selinger } 672904d1e70Sandi selinger ailen[j] = dnz; 673904d1e70Sandi selinger bilen[j] = onz; 674904d1e70Sandi selinger } 675904d1e70Sandi selinger PetscFunctionReturn(0); 676904d1e70Sandi selinger } 677904d1e70Sandi selinger 678904d1e70Sandi selinger /* 679904d1e70Sandi selinger This function sets the local j, a and ilen arrays (of the diagonal and off-diagonal part) of an MPIAIJ-matrix. 680904d1e70Sandi selinger The values in mat_i have to be sorted and the values in mat_j have to be sorted for each row (CSR-like). 6811de21080Sandi selinger No off-processor parts off the matrix are allowed here, they are set at a later point by MatSetValues_MPIAIJ. 6821de21080Sandi selinger Also, mat->was_assembled has to be false, otherwise the statement aj[rowstart_diag+dnz_row] = mat_j[col] - cstart; 6831de21080Sandi selinger would not be true and the more complex MatSetValues_MPIAIJ has to be used. 684904d1e70Sandi selinger */ 685e9ede7d0Sandi selinger PetscErrorCode MatSetValues_MPIAIJ_CopyFromCSRFormat(Mat mat,const PetscInt mat_j[],const PetscInt mat_i[],const PetscScalar mat_a[]) 6863a063d27Sandi selinger { 6873a063d27Sandi selinger Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 6883a063d27Sandi selinger Mat A = aij->A; /* diagonal part of the matrix */ 6893a063d27Sandi selinger Mat B = aij->B; /* offdiagonal part of the matrix */ 690e9ede7d0Sandi selinger Mat_SeqAIJ *aijd =(Mat_SeqAIJ*)(aij->A)->data,*aijo=(Mat_SeqAIJ*)(aij->B)->data; 6913a063d27Sandi selinger Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 6923a063d27Sandi selinger Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 6933a063d27Sandi selinger PetscInt cstart = mat->cmap->rstart,cend = mat->cmap->rend; 6943a063d27Sandi selinger PetscInt *ailen = a->ilen,*aj = a->j; 6953a063d27Sandi selinger PetscInt *bilen = b->ilen,*bj = b->j; 6966dc1ffa3Sandi selinger PetscInt am = aij->A->rmap->n,j; 6971de21080Sandi selinger PetscInt *full_diag_i=aijd->i,*full_offd_i=aijo->i; /* These variables can also include non-local elements, which are set at a later point. */ 698904d1e70Sandi selinger PetscInt col,dnz_row,onz_row,rowstart_diag,rowstart_offd; 699904d1e70Sandi selinger PetscScalar *aa = a->a,*ba = b->a; 7003a063d27Sandi selinger 7013a063d27Sandi selinger PetscFunctionBegin; 7023a063d27Sandi selinger /* Iterate over all rows of the matrix */ 7033a063d27Sandi selinger for (j=0; j<am; j++) { 704904d1e70Sandi selinger dnz_row = onz_row = 0; 705904d1e70Sandi selinger rowstart_offd = full_offd_i[j]; 706904d1e70Sandi selinger rowstart_diag = full_diag_i[j]; 707e9ede7d0Sandi selinger /* Iterate over all non-zero columns of the current row */ 708e9ede7d0Sandi selinger for (col=mat_i[j]; col<mat_i[j+1]; col++) { 709ae8e66a0Sandi selinger /* If column is in the diagonal */ 7103a063d27Sandi selinger if (mat_j[col] >= cstart && mat_j[col] < cend) { 711904d1e70Sandi selinger aj[rowstart_diag+dnz_row] = mat_j[col] - cstart; 712904d1e70Sandi selinger aa[rowstart_diag+dnz_row] = mat_a[col]; 713904d1e70Sandi selinger dnz_row++; 714ae8e66a0Sandi selinger } else { /* off-diagonal entries */ 715904d1e70Sandi selinger bj[rowstart_offd+onz_row] = mat_j[col]; 716904d1e70Sandi selinger ba[rowstart_offd+onz_row] = mat_a[col]; 717904d1e70Sandi selinger onz_row++; 7183a063d27Sandi selinger } 7193a063d27Sandi selinger } 720904d1e70Sandi selinger ailen[j] = dnz_row; 721904d1e70Sandi selinger bilen[j] = onz_row; 7223a063d27Sandi selinger } 7233a063d27Sandi selinger PetscFunctionReturn(0); 7243a063d27Sandi selinger } 7253a063d27Sandi selinger 726b1d57f15SBarry Smith PetscErrorCode MatGetValues_MPIAIJ(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[]) 727b49de8d1SLois Curfman McInnes { 728b49de8d1SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 729dfbe8321SBarry Smith PetscErrorCode ierr; 730d0f46423SBarry Smith PetscInt i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend; 731d0f46423SBarry Smith PetscInt cstart = mat->cmap->rstart,cend = mat->cmap->rend,row,col; 732b49de8d1SLois Curfman McInnes 7333a40ed3dSBarry Smith PetscFunctionBegin; 734b49de8d1SLois Curfman McInnes for (i=0; i<m; i++) { 735e32f2f54SBarry Smith if (idxm[i] < 0) continue; /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",idxm[i]);*/ 736e32f2f54SBarry 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); 737b49de8d1SLois Curfman McInnes if (idxm[i] >= rstart && idxm[i] < rend) { 738b49de8d1SLois Curfman McInnes row = idxm[i] - rstart; 739b49de8d1SLois Curfman McInnes for (j=0; j<n; j++) { 740e32f2f54SBarry Smith if (idxn[j] < 0) continue; /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",idxn[j]); */ 741e32f2f54SBarry 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); 742b49de8d1SLois Curfman McInnes if (idxn[j] >= cstart && idxn[j] < cend) { 743b49de8d1SLois Curfman McInnes col = idxn[j] - cstart; 744b49de8d1SLois Curfman McInnes ierr = MatGetValues(aij->A,1,&row,1,&col,v+i*n+j);CHKERRQ(ierr); 745fa852ad4SSatish Balay } else { 746905e6a2fSBarry Smith if (!aij->colmap) { 747ab9863d7SBarry Smith ierr = MatCreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr); 748905e6a2fSBarry Smith } 749aa482453SBarry Smith #if defined(PETSC_USE_CTABLE) 7500f5bd95cSBarry Smith ierr = PetscTableFind(aij->colmap,idxn[j]+1,&col);CHKERRQ(ierr); 751fa46199cSSatish Balay col--; 752b1fc9764SSatish Balay #else 753905e6a2fSBarry Smith col = aij->colmap[idxn[j]] - 1; 754b1fc9764SSatish Balay #endif 755e60e1c95SSatish Balay if ((col < 0) || (aij->garray[col] != idxn[j])) *(v+i*n+j) = 0.0; 756d9d09a02SSatish Balay else { 757b49de8d1SLois Curfman McInnes ierr = MatGetValues(aij->B,1,&row,1,&col,v+i*n+j);CHKERRQ(ierr); 758b49de8d1SLois Curfman McInnes } 759b49de8d1SLois Curfman McInnes } 760b49de8d1SLois Curfman McInnes } 761f23aa3ddSBarry Smith } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only local values currently supported"); 762b49de8d1SLois Curfman McInnes } 7633a40ed3dSBarry Smith PetscFunctionReturn(0); 764b49de8d1SLois Curfman McInnes } 765bc5ccf88SSatish Balay 766bd0c2dcbSBarry Smith extern PetscErrorCode MatMultDiagonalBlock_MPIAIJ(Mat,Vec,Vec); 767bd0c2dcbSBarry Smith 768dfbe8321SBarry Smith PetscErrorCode MatAssemblyBegin_MPIAIJ(Mat mat,MatAssemblyType mode) 769bc5ccf88SSatish Balay { 770bc5ccf88SSatish Balay Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 771dfbe8321SBarry Smith PetscErrorCode ierr; 772b1d57f15SBarry Smith PetscInt nstash,reallocs; 773bc5ccf88SSatish Balay 774bc5ccf88SSatish Balay PetscFunctionBegin; 7752205254eSKarl Rupp if (aij->donotstash || mat->nooffprocentries) PetscFunctionReturn(0); 776bc5ccf88SSatish Balay 777d0f46423SBarry Smith ierr = MatStashScatterBegin_Private(mat,&mat->stash,mat->rmap->range);CHKERRQ(ierr); 7788798bf22SSatish Balay ierr = MatStashGetInfo_Private(&mat->stash,&nstash,&reallocs);CHKERRQ(ierr); 779ae15b995SBarry Smith ierr = PetscInfo2(aij->A,"Stash has %D entries, uses %D mallocs.\n",nstash,reallocs);CHKERRQ(ierr); 780bc5ccf88SSatish Balay PetscFunctionReturn(0); 781bc5ccf88SSatish Balay } 782bc5ccf88SSatish Balay 783dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_MPIAIJ(Mat mat,MatAssemblyType mode) 784bc5ccf88SSatish Balay { 785bc5ccf88SSatish Balay Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 78691c97fd4SSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ*)aij->A->data; 7876849ba73SBarry Smith PetscErrorCode ierr; 788b1d57f15SBarry Smith PetscMPIInt n; 789b1d57f15SBarry Smith PetscInt i,j,rstart,ncols,flg; 790e44c0bd4SBarry Smith PetscInt *row,*col; 791ace3abfcSBarry Smith PetscBool other_disassembled; 79287828ca2SBarry Smith PetscScalar *val; 793bc5ccf88SSatish Balay 79491c97fd4SSatish Balay /* do not use 'b = (Mat_SeqAIJ*)aij->B->data' as B can be reset in disassembly */ 7956e111a19SKarl Rupp 796bc5ccf88SSatish Balay PetscFunctionBegin; 7974cb17eb5SBarry Smith if (!aij->donotstash && !mat->nooffprocentries) { 798a2d1c673SSatish Balay while (1) { 7998798bf22SSatish Balay ierr = MatStashScatterGetMesg_Private(&mat->stash,&n,&row,&col,&val,&flg);CHKERRQ(ierr); 800a2d1c673SSatish Balay if (!flg) break; 801a2d1c673SSatish Balay 802bc5ccf88SSatish Balay for (i=0; i<n; ) { 803bc5ccf88SSatish Balay /* Now identify the consecutive vals belonging to the same row */ 8042205254eSKarl Rupp for (j=i,rstart=row[j]; j<n; j++) { 8052205254eSKarl Rupp if (row[j] != rstart) break; 8062205254eSKarl Rupp } 807bc5ccf88SSatish Balay if (j < n) ncols = j-i; 808bc5ccf88SSatish Balay else ncols = n-i; 809bc5ccf88SSatish Balay /* Now assemble all these values with a single function call */ 8104b4eb8d3SJed Brown ierr = MatSetValues_MPIAIJ(mat,1,row+i,ncols,col+i,val+i,mat->insertmode);CHKERRQ(ierr); 8112205254eSKarl Rupp 812bc5ccf88SSatish Balay i = j; 813bc5ccf88SSatish Balay } 814bc5ccf88SSatish Balay } 8158798bf22SSatish Balay ierr = MatStashScatterEnd_Private(&mat->stash);CHKERRQ(ierr); 816bc5ccf88SSatish Balay } 817bc5ccf88SSatish Balay ierr = MatAssemblyBegin(aij->A,mode);CHKERRQ(ierr); 818bc5ccf88SSatish Balay ierr = MatAssemblyEnd(aij->A,mode);CHKERRQ(ierr); 819bc5ccf88SSatish Balay 820bc5ccf88SSatish Balay /* determine if any processor has disassembled, if so we must 821*071fcb05SBarry Smith also disassemble ourself, in order that we may reassemble. */ 822bc5ccf88SSatish Balay /* 823bc5ccf88SSatish Balay if nonzero structure of submatrix B cannot change then we know that 824bc5ccf88SSatish Balay no processor disassembled thus we can skip this stuff 825bc5ccf88SSatish Balay */ 826bc5ccf88SSatish Balay if (!((Mat_SeqAIJ*)aij->B->data)->nonew) { 827b2566f29SBarry Smith ierr = MPIU_Allreduce(&mat->was_assembled,&other_disassembled,1,MPIU_BOOL,MPI_PROD,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 828bc5ccf88SSatish Balay if (mat->was_assembled && !other_disassembled) { 829ab9863d7SBarry Smith ierr = MatDisAssemble_MPIAIJ(mat);CHKERRQ(ierr); 830ad59fb31SSatish Balay } 831ad59fb31SSatish Balay } 832bc5ccf88SSatish Balay if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) { 833bc5ccf88SSatish Balay ierr = MatSetUpMultiply_MPIAIJ(mat);CHKERRQ(ierr); 834bc5ccf88SSatish Balay } 8354e0d8c25SBarry Smith ierr = MatSetOption(aij->B,MAT_USE_INODES,PETSC_FALSE);CHKERRQ(ierr); 836bc5ccf88SSatish Balay ierr = MatAssemblyBegin(aij->B,mode);CHKERRQ(ierr); 837bc5ccf88SSatish Balay ierr = MatAssemblyEnd(aij->B,mode);CHKERRQ(ierr); 838bc5ccf88SSatish Balay 8391d79065fSBarry Smith ierr = PetscFree2(aij->rowvalues,aij->rowindices);CHKERRQ(ierr); 8402205254eSKarl Rupp 841606d414cSSatish Balay aij->rowvalues = 0; 842a30b2313SHong Zhang 8436bf464f9SBarry Smith ierr = VecDestroy(&aij->diag);CHKERRQ(ierr); 844bd0c2dcbSBarry Smith if (a->inode.size) mat->ops->multdiagonalblock = MatMultDiagonalBlock_MPIAIJ; 845e56f5c9eSBarry Smith 8464f9cfa9eSBarry Smith /* if no new nonzero locations are allowed in matrix then only set the matrix state the first time through */ 8474f9cfa9eSBarry Smith if ((!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) || !((Mat_SeqAIJ*)(aij->A->data))->nonew) { 848e56f5c9eSBarry Smith PetscObjectState state = aij->A->nonzerostate + aij->B->nonzerostate; 849b2566f29SBarry Smith ierr = MPIU_Allreduce(&state,&mat->nonzerostate,1,MPIU_INT64,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 850e56f5c9eSBarry Smith } 851bc5ccf88SSatish Balay PetscFunctionReturn(0); 852bc5ccf88SSatish Balay } 853bc5ccf88SSatish Balay 854dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_MPIAIJ(Mat A) 8551eb62cbbSBarry Smith { 85644a69424SLois Curfman McInnes Mat_MPIAIJ *l = (Mat_MPIAIJ*)A->data; 857dfbe8321SBarry Smith PetscErrorCode ierr; 8583a40ed3dSBarry Smith 8593a40ed3dSBarry Smith PetscFunctionBegin; 86078b31e54SBarry Smith ierr = MatZeroEntries(l->A);CHKERRQ(ierr); 86178b31e54SBarry Smith ierr = MatZeroEntries(l->B);CHKERRQ(ierr); 8623a40ed3dSBarry Smith PetscFunctionReturn(0); 8631eb62cbbSBarry Smith } 8641eb62cbbSBarry Smith 8652b40b63fSBarry Smith PetscErrorCode MatZeroRows_MPIAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 8661eb62cbbSBarry Smith { 8671b1dd7adSMatthew G. Knepley Mat_MPIAIJ *mat = (Mat_MPIAIJ *) A->data; 868a92ad425SStefano Zampini PetscObjectState sA, sB; 8691b1dd7adSMatthew G. Knepley PetscInt *lrows; 8706e520ac8SStefano Zampini PetscInt r, len; 871a92ad425SStefano Zampini PetscBool cong, lch, gch; 8726849ba73SBarry Smith PetscErrorCode ierr; 8731eb62cbbSBarry Smith 8743a40ed3dSBarry Smith PetscFunctionBegin; 8756e520ac8SStefano Zampini /* get locally owned rows */ 8766e520ac8SStefano Zampini ierr = MatZeroRowsMapLocal_Private(A,N,rows,&len,&lrows);CHKERRQ(ierr); 877a92ad425SStefano Zampini ierr = MatHasCongruentLayouts(A,&cong);CHKERRQ(ierr); 87897b48c8fSBarry Smith /* fix right hand side if needed */ 87997b48c8fSBarry Smith if (x && b) { 8801b1dd7adSMatthew G. Knepley const PetscScalar *xx; 8811b1dd7adSMatthew G. Knepley PetscScalar *bb; 8821b1dd7adSMatthew G. Knepley 883a92ad425SStefano Zampini if (!cong) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Need matching row/col layout"); 88497b48c8fSBarry Smith ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr); 88597b48c8fSBarry Smith ierr = VecGetArray(b, &bb);CHKERRQ(ierr); 8861b1dd7adSMatthew G. Knepley for (r = 0; r < len; ++r) bb[lrows[r]] = diag*xx[lrows[r]]; 88797b48c8fSBarry Smith ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr); 88897b48c8fSBarry Smith ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr); 88997b48c8fSBarry Smith } 890a92ad425SStefano Zampini 891a92ad425SStefano Zampini sA = mat->A->nonzerostate; 892a92ad425SStefano Zampini sB = mat->B->nonzerostate; 893a92ad425SStefano Zampini 894a92ad425SStefano Zampini if (diag != 0.0 && cong) { 8951b1dd7adSMatthew G. Knepley ierr = MatZeroRows(mat->A, len, lrows, diag, NULL, NULL);CHKERRQ(ierr); 896a92ad425SStefano Zampini ierr = MatZeroRows(mat->B, len, lrows, 0.0, NULL, NULL);CHKERRQ(ierr); 897a92ad425SStefano Zampini } else if (diag != 0.0) { /* non-square or non congruent layouts -> if keepnonzeropattern is false, we allow for new insertion */ 898a92ad425SStefano Zampini Mat_SeqAIJ *aijA = (Mat_SeqAIJ*)mat->A->data; 899a92ad425SStefano Zampini Mat_SeqAIJ *aijB = (Mat_SeqAIJ*)mat->B->data; 900a92ad425SStefano Zampini PetscInt nnwA, nnwB; 901a92ad425SStefano Zampini PetscBool nnzA, nnzB; 902a92ad425SStefano Zampini 903a92ad425SStefano Zampini nnwA = aijA->nonew; 904a92ad425SStefano Zampini nnwB = aijB->nonew; 905a92ad425SStefano Zampini nnzA = aijA->keepnonzeropattern; 906a92ad425SStefano Zampini nnzB = aijB->keepnonzeropattern; 907a92ad425SStefano Zampini if (!nnzA) { 908a92ad425SStefano Zampini ierr = PetscInfo(mat->A,"Requested to not keep the pattern and add a nonzero diagonal; may encounter reallocations on diagonal block.\n");CHKERRQ(ierr); 909a92ad425SStefano Zampini aijA->nonew = 0; 910a92ad425SStefano Zampini } 911a92ad425SStefano Zampini if (!nnzB) { 912a92ad425SStefano Zampini ierr = PetscInfo(mat->B,"Requested to not keep the pattern and add a nonzero diagonal; may encounter reallocations on off-diagonal block.\n");CHKERRQ(ierr); 913a92ad425SStefano Zampini aijB->nonew = 0; 914a92ad425SStefano Zampini } 915a92ad425SStefano Zampini /* Must zero here before the next loop */ 9161b1dd7adSMatthew G. Knepley ierr = MatZeroRows(mat->A, len, lrows, 0.0, NULL, NULL);CHKERRQ(ierr); 917a92ad425SStefano Zampini ierr = MatZeroRows(mat->B, len, lrows, 0.0, NULL, NULL);CHKERRQ(ierr); 9181b1dd7adSMatthew G. Knepley for (r = 0; r < len; ++r) { 9191b1dd7adSMatthew G. Knepley const PetscInt row = lrows[r] + A->rmap->rstart; 920a92ad425SStefano Zampini if (row >= A->cmap->N) continue; 921f4df32b1SMatthew Knepley ierr = MatSetValues(A, 1, &row, 1, &row, &diag, INSERT_VALUES);CHKERRQ(ierr); 922e2d53e46SBarry Smith } 923a92ad425SStefano Zampini aijA->nonew = nnwA; 924a92ad425SStefano Zampini aijB->nonew = nnwB; 9256eb55b6aSBarry Smith } else { 9261b1dd7adSMatthew G. Knepley ierr = MatZeroRows(mat->A, len, lrows, 0.0, NULL, NULL);CHKERRQ(ierr); 927a92ad425SStefano Zampini ierr = MatZeroRows(mat->B, len, lrows, 0.0, NULL, NULL);CHKERRQ(ierr); 9286eb55b6aSBarry Smith } 929606d414cSSatish Balay ierr = PetscFree(lrows);CHKERRQ(ierr); 930a92ad425SStefano Zampini ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 931a92ad425SStefano Zampini ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 9324f9cfa9eSBarry Smith 933a92ad425SStefano Zampini /* reduce nonzerostate */ 934a92ad425SStefano Zampini lch = (PetscBool)(sA != mat->A->nonzerostate || sB != mat->B->nonzerostate); 935a92ad425SStefano Zampini ierr = MPIU_Allreduce(&lch,&gch,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 936a92ad425SStefano Zampini if (gch) A->nonzerostate++; 9373a40ed3dSBarry Smith PetscFunctionReturn(0); 9381eb62cbbSBarry Smith } 9391eb62cbbSBarry Smith 9409c7c4993SBarry Smith PetscErrorCode MatZeroRowsColumns_MPIAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 9419c7c4993SBarry Smith { 9429c7c4993SBarry Smith Mat_MPIAIJ *l = (Mat_MPIAIJ*)A->data; 9439c7c4993SBarry Smith PetscErrorCode ierr; 9445ba17502SJed Brown PetscMPIInt n = A->rmap->n; 94578fab17bSMatthew G. Knepley PetscInt i,j,r,m,p = 0,len = 0; 94654bd4135SMatthew G. Knepley PetscInt *lrows,*owners = A->rmap->range; 94754bd4135SMatthew G. Knepley PetscSFNode *rrows; 94854bd4135SMatthew G. Knepley PetscSF sf; 9499c7c4993SBarry Smith const PetscScalar *xx; 950564f14d6SBarry Smith PetscScalar *bb,*mask; 951564f14d6SBarry Smith Vec xmask,lmask; 952564f14d6SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)l->B->data; 953564f14d6SBarry Smith const PetscInt *aj, *ii,*ridx; 954564f14d6SBarry Smith PetscScalar *aa; 9559c7c4993SBarry Smith 9569c7c4993SBarry Smith PetscFunctionBegin; 95754bd4135SMatthew G. Knepley /* Create SF where leaves are input rows and roots are owned rows */ 95854bd4135SMatthew G. Knepley ierr = PetscMalloc1(n, &lrows);CHKERRQ(ierr); 95954bd4135SMatthew G. Knepley for (r = 0; r < n; ++r) lrows[r] = -1; 96054bd4135SMatthew G. Knepley ierr = PetscMalloc1(N, &rrows);CHKERRQ(ierr); 96154bd4135SMatthew G. Knepley for (r = 0; r < N; ++r) { 96254bd4135SMatthew G. Knepley const PetscInt idx = rows[r]; 9635ba17502SJed Brown if (idx < 0 || A->rmap->N <= idx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Row %D out of range [0,%D)",idx,A->rmap->N); 9645ba17502SJed Brown if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this row too */ 9655ba17502SJed Brown ierr = PetscLayoutFindOwner(A->rmap,idx,&p);CHKERRQ(ierr); 9665ba17502SJed Brown } 96754bd4135SMatthew G. Knepley rrows[r].rank = p; 96854bd4135SMatthew G. Knepley rrows[r].index = rows[r] - owners[p]; 9699c7c4993SBarry Smith } 97054bd4135SMatthew G. Knepley ierr = PetscSFCreate(PetscObjectComm((PetscObject) A), &sf);CHKERRQ(ierr); 97154bd4135SMatthew G. Knepley ierr = PetscSFSetGraph(sf, n, N, NULL, PETSC_OWN_POINTER, rrows, PETSC_OWN_POINTER);CHKERRQ(ierr); 97254bd4135SMatthew G. Knepley /* Collect flags for rows to be zeroed */ 97354bd4135SMatthew G. Knepley ierr = PetscSFReduceBegin(sf, MPIU_INT, (PetscInt *) rows, lrows, MPI_LOR);CHKERRQ(ierr); 97454bd4135SMatthew G. Knepley ierr = PetscSFReduceEnd(sf, MPIU_INT, (PetscInt *) rows, lrows, MPI_LOR);CHKERRQ(ierr); 97554bd4135SMatthew G. Knepley ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 97654bd4135SMatthew G. Knepley /* Compress and put in row numbers */ 97754bd4135SMatthew G. Knepley for (r = 0; r < n; ++r) if (lrows[r] >= 0) lrows[len++] = r; 978564f14d6SBarry Smith /* zero diagonal part of matrix */ 97954bd4135SMatthew G. Knepley ierr = MatZeroRowsColumns(l->A,len,lrows,diag,x,b);CHKERRQ(ierr); 980564f14d6SBarry Smith /* handle off diagonal part of matrix */ 9812a7a6963SBarry Smith ierr = MatCreateVecs(A,&xmask,NULL);CHKERRQ(ierr); 982564f14d6SBarry Smith ierr = VecDuplicate(l->lvec,&lmask);CHKERRQ(ierr); 983564f14d6SBarry Smith ierr = VecGetArray(xmask,&bb);CHKERRQ(ierr); 98454bd4135SMatthew G. Knepley for (i=0; i<len; i++) bb[lrows[i]] = 1; 985564f14d6SBarry Smith ierr = VecRestoreArray(xmask,&bb);CHKERRQ(ierr); 986564f14d6SBarry Smith ierr = VecScatterBegin(l->Mvctx,xmask,lmask,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 987564f14d6SBarry Smith ierr = VecScatterEnd(l->Mvctx,xmask,lmask,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 9886bf464f9SBarry Smith ierr = VecDestroy(&xmask);CHKERRQ(ierr); 989a92ad425SStefano Zampini if (x && b) { /* this code is buggy when the row and column layout don't match */ 990a92ad425SStefano Zampini PetscBool cong; 991a92ad425SStefano Zampini 992a92ad425SStefano Zampini ierr = MatHasCongruentLayouts(A,&cong);CHKERRQ(ierr); 993a92ad425SStefano Zampini if (!cong) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Need matching row/col layout"); 99467caceb0SMatthew G. Knepley ierr = VecScatterBegin(l->Mvctx,x,l->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 99567caceb0SMatthew G. Knepley ierr = VecScatterEnd(l->Mvctx,x,l->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 996564f14d6SBarry Smith ierr = VecGetArrayRead(l->lvec,&xx);CHKERRQ(ierr); 997564f14d6SBarry Smith ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 998377aa5a1SBarry Smith } 999377aa5a1SBarry Smith ierr = VecGetArray(lmask,&mask);CHKERRQ(ierr); 1000564f14d6SBarry Smith /* remove zeroed rows of off diagonal matrix */ 1001564f14d6SBarry Smith ii = aij->i; 100254bd4135SMatthew G. Knepley for (i=0; i<len; i++) { 1003580bdb30SBarry Smith ierr = PetscArrayzero(aij->a + ii[lrows[i]],ii[lrows[i]+1] - ii[lrows[i]]);CHKERRQ(ierr); 10049c7c4993SBarry Smith } 1005564f14d6SBarry Smith /* loop over all elements of off process part of matrix zeroing removed columns*/ 1006564f14d6SBarry Smith if (aij->compressedrow.use) { 1007564f14d6SBarry Smith m = aij->compressedrow.nrows; 1008564f14d6SBarry Smith ii = aij->compressedrow.i; 1009564f14d6SBarry Smith ridx = aij->compressedrow.rindex; 1010564f14d6SBarry Smith for (i=0; i<m; i++) { 1011564f14d6SBarry Smith n = ii[i+1] - ii[i]; 1012564f14d6SBarry Smith aj = aij->j + ii[i]; 1013564f14d6SBarry Smith aa = aij->a + ii[i]; 1014564f14d6SBarry Smith 1015564f14d6SBarry Smith for (j=0; j<n; j++) { 101625266a92SSatish Balay if (PetscAbsScalar(mask[*aj])) { 1017377aa5a1SBarry Smith if (b) bb[*ridx] -= *aa*xx[*aj]; 1018564f14d6SBarry Smith *aa = 0.0; 1019564f14d6SBarry Smith } 1020564f14d6SBarry Smith aa++; 1021564f14d6SBarry Smith aj++; 1022564f14d6SBarry Smith } 1023564f14d6SBarry Smith ridx++; 1024564f14d6SBarry Smith } 1025564f14d6SBarry Smith } else { /* do not use compressed row format */ 1026564f14d6SBarry Smith m = l->B->rmap->n; 1027564f14d6SBarry Smith for (i=0; i<m; i++) { 1028564f14d6SBarry Smith n = ii[i+1] - ii[i]; 1029564f14d6SBarry Smith aj = aij->j + ii[i]; 1030564f14d6SBarry Smith aa = aij->a + ii[i]; 1031564f14d6SBarry Smith for (j=0; j<n; j++) { 103225266a92SSatish Balay if (PetscAbsScalar(mask[*aj])) { 1033377aa5a1SBarry Smith if (b) bb[i] -= *aa*xx[*aj]; 1034564f14d6SBarry Smith *aa = 0.0; 1035564f14d6SBarry Smith } 1036564f14d6SBarry Smith aa++; 1037564f14d6SBarry Smith aj++; 1038564f14d6SBarry Smith } 1039564f14d6SBarry Smith } 1040564f14d6SBarry Smith } 1041a92ad425SStefano Zampini if (x && b) { 1042564f14d6SBarry Smith ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 1043564f14d6SBarry Smith ierr = VecRestoreArrayRead(l->lvec,&xx);CHKERRQ(ierr); 1044377aa5a1SBarry Smith } 1045377aa5a1SBarry Smith ierr = VecRestoreArray(lmask,&mask);CHKERRQ(ierr); 10466bf464f9SBarry Smith ierr = VecDestroy(&lmask);CHKERRQ(ierr); 10479c7c4993SBarry Smith ierr = PetscFree(lrows);CHKERRQ(ierr); 10484f9cfa9eSBarry Smith 10494f9cfa9eSBarry Smith /* only change matrix nonzero state if pattern was allowed to be changed */ 10504f9cfa9eSBarry Smith if (!((Mat_SeqAIJ*)(l->A->data))->keepnonzeropattern) { 10514f9cfa9eSBarry Smith PetscObjectState state = l->A->nonzerostate + l->B->nonzerostate; 1052b2566f29SBarry Smith ierr = MPIU_Allreduce(&state,&A->nonzerostate,1,MPIU_INT64,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 10534f9cfa9eSBarry Smith } 10549c7c4993SBarry Smith PetscFunctionReturn(0); 10559c7c4993SBarry Smith } 10569c7c4993SBarry Smith 1057dfbe8321SBarry Smith PetscErrorCode MatMult_MPIAIJ(Mat A,Vec xx,Vec yy) 10581eb62cbbSBarry Smith { 1059416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1060dfbe8321SBarry Smith PetscErrorCode ierr; 1061b1d57f15SBarry Smith PetscInt nt; 106219b3b6edSHong Zhang VecScatter Mvctx = a->Mvctx; 1063416022c9SBarry Smith 10643a40ed3dSBarry Smith PetscFunctionBegin; 1065a2ce50c7SBarry Smith ierr = VecGetLocalSize(xx,&nt);CHKERRQ(ierr); 106665e19b50SBarry 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); 10677eb85803SHong Zhang 106819b3b6edSHong Zhang ierr = VecScatterBegin(Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1069f830108cSBarry Smith ierr = (*a->A->ops->mult)(a->A,xx,yy);CHKERRQ(ierr); 107019b3b6edSHong Zhang ierr = VecScatterEnd(Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1071f830108cSBarry Smith ierr = (*a->B->ops->multadd)(a->B,a->lvec,yy,yy);CHKERRQ(ierr); 10723a40ed3dSBarry Smith PetscFunctionReturn(0); 10731eb62cbbSBarry Smith } 10741eb62cbbSBarry Smith 1075bd0c2dcbSBarry Smith PetscErrorCode MatMultDiagonalBlock_MPIAIJ(Mat A,Vec bb,Vec xx) 1076bd0c2dcbSBarry Smith { 1077bd0c2dcbSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1078bd0c2dcbSBarry Smith PetscErrorCode ierr; 1079bd0c2dcbSBarry Smith 1080bd0c2dcbSBarry Smith PetscFunctionBegin; 1081bd0c2dcbSBarry Smith ierr = MatMultDiagonalBlock(a->A,bb,xx);CHKERRQ(ierr); 1082bd0c2dcbSBarry Smith PetscFunctionReturn(0); 1083bd0c2dcbSBarry Smith } 1084bd0c2dcbSBarry Smith 1085dfbe8321SBarry Smith PetscErrorCode MatMultAdd_MPIAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1086da3a660dSBarry Smith { 1087416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1088dfbe8321SBarry Smith PetscErrorCode ierr; 108901ad2aeeSHong Zhang VecScatter Mvctx = a->Mvctx; 10903a40ed3dSBarry Smith 10913a40ed3dSBarry Smith PetscFunctionBegin; 1092a78d8160SHong Zhang if (a->Mvctx_mpi1_flg) Mvctx = a->Mvctx_mpi1; 109301ad2aeeSHong Zhang ierr = VecScatterBegin(Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1094f830108cSBarry Smith ierr = (*a->A->ops->multadd)(a->A,xx,yy,zz);CHKERRQ(ierr); 109501ad2aeeSHong Zhang ierr = VecScatterEnd(Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1096f830108cSBarry Smith ierr = (*a->B->ops->multadd)(a->B,a->lvec,zz,zz);CHKERRQ(ierr); 10973a40ed3dSBarry Smith PetscFunctionReturn(0); 1098da3a660dSBarry Smith } 1099da3a660dSBarry Smith 1100dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_MPIAIJ(Mat A,Vec xx,Vec yy) 1101da3a660dSBarry Smith { 1102416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1103dfbe8321SBarry Smith PetscErrorCode ierr; 1104da3a660dSBarry Smith 11053a40ed3dSBarry Smith PetscFunctionBegin; 1106da3a660dSBarry Smith /* do nondiagonal part */ 11077c922b88SBarry Smith ierr = (*a->B->ops->multtranspose)(a->B,xx,a->lvec);CHKERRQ(ierr); 1108da3a660dSBarry Smith /* do local part */ 11097c922b88SBarry Smith ierr = (*a->A->ops->multtranspose)(a->A,xx,yy);CHKERRQ(ierr); 11109613dc34SJunchao Zhang /* add partial results together */ 1111ca9f406cSSatish Balay ierr = VecScatterBegin(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1112ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 11133a40ed3dSBarry Smith PetscFunctionReturn(0); 1114da3a660dSBarry Smith } 1115da3a660dSBarry Smith 11167087cfbeSBarry Smith PetscErrorCode MatIsTranspose_MPIAIJ(Mat Amat,Mat Bmat,PetscReal tol,PetscBool *f) 1117cd0d46ebSvictorle { 11184f423910Svictorle MPI_Comm comm; 1119cd0d46ebSvictorle Mat_MPIAIJ *Aij = (Mat_MPIAIJ*) Amat->data, *Bij; 112066501d38Svictorle Mat Adia = Aij->A, Bdia, Aoff,Boff,*Aoffs,*Boffs; 1121cd0d46ebSvictorle IS Me,Notme; 11226849ba73SBarry Smith PetscErrorCode ierr; 1123b1d57f15SBarry Smith PetscInt M,N,first,last,*notme,i; 112454d735aeSStefano Zampini PetscBool lf; 1125b1d57f15SBarry Smith PetscMPIInt size; 1126cd0d46ebSvictorle 1127cd0d46ebSvictorle PetscFunctionBegin; 112842e5f5b4Svictorle /* Easy test: symmetric diagonal block */ 112966501d38Svictorle Bij = (Mat_MPIAIJ*) Bmat->data; Bdia = Bij->A; 113054d735aeSStefano Zampini ierr = MatIsTranspose(Adia,Bdia,tol,&lf);CHKERRQ(ierr); 113154d735aeSStefano Zampini ierr = MPIU_Allreduce(&lf,f,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)Amat));CHKERRQ(ierr); 1132cd0d46ebSvictorle if (!*f) PetscFunctionReturn(0); 11334f423910Svictorle ierr = PetscObjectGetComm((PetscObject)Amat,&comm);CHKERRQ(ierr); 1134b1d57f15SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1135b1d57f15SBarry Smith if (size == 1) PetscFunctionReturn(0); 113642e5f5b4Svictorle 11377dae84e0SHong Zhang /* Hard test: off-diagonal block. This takes a MatCreateSubMatrix. */ 1138cd0d46ebSvictorle ierr = MatGetSize(Amat,&M,&N);CHKERRQ(ierr); 1139cd0d46ebSvictorle ierr = MatGetOwnershipRange(Amat,&first,&last);CHKERRQ(ierr); 1140854ce69bSBarry Smith ierr = PetscMalloc1(N-last+first,¬me);CHKERRQ(ierr); 1141cd0d46ebSvictorle for (i=0; i<first; i++) notme[i] = i; 1142cd0d46ebSvictorle for (i=last; i<M; i++) notme[i-last+first] = i; 114370b3c8c7SBarry Smith ierr = ISCreateGeneral(MPI_COMM_SELF,N-last+first,notme,PETSC_COPY_VALUES,&Notme);CHKERRQ(ierr); 1144268466fbSBarry Smith ierr = ISCreateStride(MPI_COMM_SELF,last-first,first,1,&Me);CHKERRQ(ierr); 11457dae84e0SHong Zhang ierr = MatCreateSubMatrices(Amat,1,&Me,&Notme,MAT_INITIAL_MATRIX,&Aoffs);CHKERRQ(ierr); 114666501d38Svictorle Aoff = Aoffs[0]; 11477dae84e0SHong Zhang ierr = MatCreateSubMatrices(Bmat,1,&Notme,&Me,MAT_INITIAL_MATRIX,&Boffs);CHKERRQ(ierr); 114866501d38Svictorle Boff = Boffs[0]; 11495485867bSBarry Smith ierr = MatIsTranspose(Aoff,Boff,tol,f);CHKERRQ(ierr); 115066501d38Svictorle ierr = MatDestroyMatrices(1,&Aoffs);CHKERRQ(ierr); 115166501d38Svictorle ierr = MatDestroyMatrices(1,&Boffs);CHKERRQ(ierr); 11526bf464f9SBarry Smith ierr = ISDestroy(&Me);CHKERRQ(ierr); 11536bf464f9SBarry Smith ierr = ISDestroy(&Notme);CHKERRQ(ierr); 11543e0d0d19SHong Zhang ierr = PetscFree(notme);CHKERRQ(ierr); 1155cd0d46ebSvictorle PetscFunctionReturn(0); 1156cd0d46ebSvictorle } 1157cd0d46ebSvictorle 1158a3bbdb47SHong Zhang PetscErrorCode MatIsSymmetric_MPIAIJ(Mat A,PetscReal tol,PetscBool *f) 1159a3bbdb47SHong Zhang { 1160a3bbdb47SHong Zhang PetscErrorCode ierr; 1161a3bbdb47SHong Zhang 1162a3bbdb47SHong Zhang PetscFunctionBegin; 1163a3bbdb47SHong Zhang ierr = MatIsTranspose_MPIAIJ(A,A,tol,f);CHKERRQ(ierr); 1164a3bbdb47SHong Zhang PetscFunctionReturn(0); 1165a3bbdb47SHong Zhang } 1166a3bbdb47SHong Zhang 1167dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_MPIAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1168da3a660dSBarry Smith { 1169416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1170dfbe8321SBarry Smith PetscErrorCode ierr; 1171da3a660dSBarry Smith 11723a40ed3dSBarry Smith PetscFunctionBegin; 1173da3a660dSBarry Smith /* do nondiagonal part */ 11747c922b88SBarry Smith ierr = (*a->B->ops->multtranspose)(a->B,xx,a->lvec);CHKERRQ(ierr); 1175da3a660dSBarry Smith /* do local part */ 11767c922b88SBarry Smith ierr = (*a->A->ops->multtransposeadd)(a->A,xx,yy,zz);CHKERRQ(ierr); 11779613dc34SJunchao Zhang /* add partial results together */ 11789613dc34SJunchao Zhang ierr = VecScatterBegin(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1179ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 11803a40ed3dSBarry Smith PetscFunctionReturn(0); 1181da3a660dSBarry Smith } 1182da3a660dSBarry Smith 11831eb62cbbSBarry Smith /* 11841eb62cbbSBarry Smith This only works correctly for square matrices where the subblock A->A is the 11851eb62cbbSBarry Smith diagonal block 11861eb62cbbSBarry Smith */ 1187dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_MPIAIJ(Mat A,Vec v) 11881eb62cbbSBarry Smith { 1189dfbe8321SBarry Smith PetscErrorCode ierr; 1190416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 11913a40ed3dSBarry Smith 11923a40ed3dSBarry Smith PetscFunctionBegin; 1193ce94432eSBarry Smith if (A->rmap->N != A->cmap->N) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Supports only square matrix where A->A is diag block"); 1194e7e72b3dSBarry 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"); 11953a40ed3dSBarry Smith ierr = MatGetDiagonal(a->A,v);CHKERRQ(ierr); 11963a40ed3dSBarry Smith PetscFunctionReturn(0); 11971eb62cbbSBarry Smith } 11981eb62cbbSBarry Smith 1199f4df32b1SMatthew Knepley PetscErrorCode MatScale_MPIAIJ(Mat A,PetscScalar aa) 1200052efed2SBarry Smith { 1201052efed2SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1202dfbe8321SBarry Smith PetscErrorCode ierr; 12033a40ed3dSBarry Smith 12043a40ed3dSBarry Smith PetscFunctionBegin; 1205f4df32b1SMatthew Knepley ierr = MatScale(a->A,aa);CHKERRQ(ierr); 1206f4df32b1SMatthew Knepley ierr = MatScale(a->B,aa);CHKERRQ(ierr); 12073a40ed3dSBarry Smith PetscFunctionReturn(0); 1208052efed2SBarry Smith } 1209052efed2SBarry Smith 1210dfbe8321SBarry Smith PetscErrorCode MatDestroy_MPIAIJ(Mat mat) 12111eb62cbbSBarry Smith { 121244a69424SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 1213dfbe8321SBarry Smith PetscErrorCode ierr; 121483e2fdc7SBarry Smith 12153a40ed3dSBarry Smith PetscFunctionBegin; 1216aa482453SBarry Smith #if defined(PETSC_USE_LOG) 1217d0f46423SBarry Smith PetscLogObjectState((PetscObject)mat,"Rows=%D, Cols=%D",mat->rmap->N,mat->cmap->N); 1218a5a9c739SBarry Smith #endif 12198798bf22SSatish Balay ierr = MatStashDestroy_Private(&mat->stash);CHKERRQ(ierr); 12206bf464f9SBarry Smith ierr = VecDestroy(&aij->diag);CHKERRQ(ierr); 12216bf464f9SBarry Smith ierr = MatDestroy(&aij->A);CHKERRQ(ierr); 12226bf464f9SBarry Smith ierr = MatDestroy(&aij->B);CHKERRQ(ierr); 1223aa482453SBarry Smith #if defined(PETSC_USE_CTABLE) 12246bc0bbbfSBarry Smith ierr = PetscTableDestroy(&aij->colmap);CHKERRQ(ierr); 1225b1fc9764SSatish Balay #else 122605b42c5fSBarry Smith ierr = PetscFree(aij->colmap);CHKERRQ(ierr); 1227b1fc9764SSatish Balay #endif 122805b42c5fSBarry Smith ierr = PetscFree(aij->garray);CHKERRQ(ierr); 12296bf464f9SBarry Smith ierr = VecDestroy(&aij->lvec);CHKERRQ(ierr); 12306bf464f9SBarry Smith ierr = VecScatterDestroy(&aij->Mvctx);CHKERRQ(ierr); 12314b8d542aSHong Zhang if (aij->Mvctx_mpi1) {ierr = VecScatterDestroy(&aij->Mvctx_mpi1);CHKERRQ(ierr);} 123203095fedSBarry Smith ierr = PetscFree2(aij->rowvalues,aij->rowindices);CHKERRQ(ierr); 12338aa348c1SBarry Smith ierr = PetscFree(aij->ld);CHKERRQ(ierr); 1234bf0cc555SLisandro Dalcin ierr = PetscFree(mat->data);CHKERRQ(ierr); 1235901853e0SKris Buschelman 1236dbd8c25aSHong Zhang ierr = PetscObjectChangeTypeName((PetscObject)mat,0);CHKERRQ(ierr); 1237bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatStoreValues_C",NULL);CHKERRQ(ierr); 1238bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatRetrieveValues_C",NULL);CHKERRQ(ierr); 1239bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatIsTranspose_C",NULL);CHKERRQ(ierr); 1240bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPIAIJSetPreallocation_C",NULL);CHKERRQ(ierr); 1241846b4da1SFande Kong ierr = PetscObjectComposeFunction((PetscObject)mat,"MatResetPreallocation_C",NULL);CHKERRQ(ierr); 1242bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPIAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr); 1243bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDiagonalScaleLocal_C",NULL);CHKERRQ(ierr); 1244bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_mpiaij_mpisbaij_C",NULL);CHKERRQ(ierr); 12455d7652ecSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 12465d7652ecSHong Zhang ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_mpiaij_elemental_C",NULL);CHKERRQ(ierr); 12475d7652ecSHong Zhang #endif 124863c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 124963c07aadSStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_mpiaij_hypre_C",NULL);CHKERRQ(ierr); 12503dad0653Sstefano_zampini ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMatMatMult_transpose_mpiaij_mpiaij_C",NULL);CHKERRQ(ierr); 125163c07aadSStefano Zampini #endif 125275d48cdbSStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_mpiaij_is_C",NULL);CHKERRQ(ierr); 125375d48cdbSStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)mat,"MatPtAP_is_mpiaij_C",NULL);CHKERRQ(ierr); 12543a40ed3dSBarry Smith PetscFunctionReturn(0); 12551eb62cbbSBarry Smith } 1256ee50ffe9SBarry Smith 1257dfbe8321SBarry Smith PetscErrorCode MatView_MPIAIJ_Binary(Mat mat,PetscViewer viewer) 12588e2fed03SBarry Smith { 12598e2fed03SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 12608e2fed03SBarry Smith Mat_SeqAIJ *A = (Mat_SeqAIJ*)aij->A->data; 12618e2fed03SBarry Smith Mat_SeqAIJ *B = (Mat_SeqAIJ*)aij->B->data; 12626849ba73SBarry Smith PetscErrorCode ierr; 126332dcc486SBarry Smith PetscMPIInt rank,size,tag = ((PetscObject)viewer)->tag; 12646f69ff64SBarry Smith int fd; 1265a788621eSSatish Balay PetscInt nz,header[4],*row_lengths,*range=0,rlen,i; 1266d892089bSMatthew G. Knepley PetscInt nzmax,*column_indices,j,k,col,*garray = aij->garray,cnt,cstart = mat->cmap->rstart,rnz = 0; 12678e2fed03SBarry Smith PetscScalar *column_values; 126885ebf7a4SBarry Smith PetscInt message_count,flowcontrolcount; 1269b37d52dbSMark F. Adams FILE *file; 12708e2fed03SBarry Smith 12718e2fed03SBarry Smith PetscFunctionBegin; 1272ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr); 1273ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr); 12748e2fed03SBarry Smith nz = A->nz + B->nz; 12755872f025SBarry Smith ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 1276958c9bccSBarry Smith if (!rank) { 12770700a824SBarry Smith header[0] = MAT_FILE_CLASSID; 1278d0f46423SBarry Smith header[1] = mat->rmap->N; 1279d0f46423SBarry Smith header[2] = mat->cmap->N; 12802205254eSKarl Rupp 1281ce94432eSBarry Smith ierr = MPI_Reduce(&nz,&header[3],1,MPIU_INT,MPI_SUM,0,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 12826f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,header,4,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 12838e2fed03SBarry Smith /* get largest number of rows any processor has */ 1284d0f46423SBarry Smith rlen = mat->rmap->n; 1285d0f46423SBarry Smith range = mat->rmap->range; 12862205254eSKarl Rupp for (i=1; i<size; i++) rlen = PetscMax(rlen,range[i+1] - range[i]); 12878e2fed03SBarry Smith } else { 1288ce94432eSBarry Smith ierr = MPI_Reduce(&nz,0,1,MPIU_INT,MPI_SUM,0,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1289d0f46423SBarry Smith rlen = mat->rmap->n; 12908e2fed03SBarry Smith } 12918e2fed03SBarry Smith 12928e2fed03SBarry Smith /* load up the local row counts */ 1293854ce69bSBarry Smith ierr = PetscMalloc1(rlen+1,&row_lengths);CHKERRQ(ierr); 12942205254eSKarl Rupp for (i=0; i<mat->rmap->n; i++) row_lengths[i] = A->i[i+1] - A->i[i] + B->i[i+1] - B->i[i]; 12958e2fed03SBarry Smith 12968e2fed03SBarry Smith /* store the row lengths to the file */ 129785ebf7a4SBarry Smith ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr); 1298958c9bccSBarry Smith if (!rank) { 1299d0f46423SBarry Smith ierr = PetscBinaryWrite(fd,row_lengths,mat->rmap->n,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 13008e2fed03SBarry Smith for (i=1; i<size; i++) { 1301639ff905SBarry Smith ierr = PetscViewerFlowControlStepMaster(viewer,i,&message_count,flowcontrolcount);CHKERRQ(ierr); 13028e2fed03SBarry Smith rlen = range[i+1] - range[i]; 1303ce94432eSBarry Smith ierr = MPIULong_Recv(row_lengths,rlen,MPIU_INT,i,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 13046f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,row_lengths,rlen,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 13058e2fed03SBarry Smith } 1306639ff905SBarry Smith ierr = PetscViewerFlowControlEndMaster(viewer,&message_count);CHKERRQ(ierr); 13078e2fed03SBarry Smith } else { 1308639ff905SBarry Smith ierr = PetscViewerFlowControlStepWorker(viewer,rank,&message_count);CHKERRQ(ierr); 1309ce94432eSBarry Smith ierr = MPIULong_Send(row_lengths,mat->rmap->n,MPIU_INT,0,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1310639ff905SBarry Smith ierr = PetscViewerFlowControlEndWorker(viewer,&message_count);CHKERRQ(ierr); 13118e2fed03SBarry Smith } 13128e2fed03SBarry Smith ierr = PetscFree(row_lengths);CHKERRQ(ierr); 13138e2fed03SBarry Smith 13148e2fed03SBarry Smith /* load up the local column indices */ 13151147fc2aSKarl Rupp nzmax = nz; /* th processor needs space a largest processor needs */ 1316ce94432eSBarry Smith ierr = MPI_Reduce(&nz,&nzmax,1,MPIU_INT,MPI_MAX,0,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1317854ce69bSBarry Smith ierr = PetscMalloc1(nzmax+1,&column_indices);CHKERRQ(ierr); 13188e2fed03SBarry Smith cnt = 0; 1319d0f46423SBarry Smith for (i=0; i<mat->rmap->n; i++) { 13208e2fed03SBarry Smith for (j=B->i[i]; j<B->i[i+1]; j++) { 13218e2fed03SBarry Smith if ((col = garray[B->j[j]]) > cstart) break; 13228e2fed03SBarry Smith column_indices[cnt++] = col; 13238e2fed03SBarry Smith } 13242205254eSKarl Rupp for (k=A->i[i]; k<A->i[i+1]; k++) column_indices[cnt++] = A->j[k] + cstart; 13252205254eSKarl Rupp for (; j<B->i[i+1]; j++) column_indices[cnt++] = garray[B->j[j]]; 13268e2fed03SBarry Smith } 1327e32f2f54SBarry 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); 13288e2fed03SBarry Smith 13298e2fed03SBarry Smith /* store the column indices to the file */ 133085ebf7a4SBarry Smith ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr); 1331958c9bccSBarry Smith if (!rank) { 13328e2fed03SBarry Smith MPI_Status status; 13336f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,column_indices,nz,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 13348e2fed03SBarry Smith for (i=1; i<size; i++) { 1335639ff905SBarry Smith ierr = PetscViewerFlowControlStepMaster(viewer,i,&message_count,flowcontrolcount);CHKERRQ(ierr); 1336ce94432eSBarry Smith ierr = MPI_Recv(&rnz,1,MPIU_INT,i,tag,PetscObjectComm((PetscObject)mat),&status);CHKERRQ(ierr); 1337e32f2f54SBarry Smith if (rnz > nzmax) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Internal PETSc error: nz = %D nzmax = %D",nz,nzmax); 1338ce94432eSBarry Smith ierr = MPIULong_Recv(column_indices,rnz,MPIU_INT,i,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 13396f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,column_indices,rnz,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 13408e2fed03SBarry Smith } 1341639ff905SBarry Smith ierr = PetscViewerFlowControlEndMaster(viewer,&message_count);CHKERRQ(ierr); 13428e2fed03SBarry Smith } else { 1343639ff905SBarry Smith ierr = PetscViewerFlowControlStepWorker(viewer,rank,&message_count);CHKERRQ(ierr); 1344ce94432eSBarry Smith ierr = MPI_Send(&nz,1,MPIU_INT,0,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1345ce94432eSBarry Smith ierr = MPIULong_Send(column_indices,nz,MPIU_INT,0,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1346639ff905SBarry Smith ierr = PetscViewerFlowControlEndWorker(viewer,&message_count);CHKERRQ(ierr); 13478e2fed03SBarry Smith } 13488e2fed03SBarry Smith ierr = PetscFree(column_indices);CHKERRQ(ierr); 13498e2fed03SBarry Smith 13508e2fed03SBarry Smith /* load up the local column values */ 1351854ce69bSBarry Smith ierr = PetscMalloc1(nzmax+1,&column_values);CHKERRQ(ierr); 13528e2fed03SBarry Smith cnt = 0; 1353d0f46423SBarry Smith for (i=0; i<mat->rmap->n; i++) { 13548e2fed03SBarry Smith for (j=B->i[i]; j<B->i[i+1]; j++) { 13558e2fed03SBarry Smith if (garray[B->j[j]] > cstart) break; 13568e2fed03SBarry Smith column_values[cnt++] = B->a[j]; 13578e2fed03SBarry Smith } 13582205254eSKarl Rupp for (k=A->i[i]; k<A->i[i+1]; k++) column_values[cnt++] = A->a[k]; 13592205254eSKarl Rupp for (; j<B->i[i+1]; j++) column_values[cnt++] = B->a[j]; 13608e2fed03SBarry Smith } 1361e32f2f54SBarry 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); 13628e2fed03SBarry Smith 13638e2fed03SBarry Smith /* store the column values to the file */ 136485ebf7a4SBarry Smith ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr); 1365958c9bccSBarry Smith if (!rank) { 13668e2fed03SBarry Smith MPI_Status status; 13676f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,column_values,nz,PETSC_SCALAR,PETSC_TRUE);CHKERRQ(ierr); 13688e2fed03SBarry Smith for (i=1; i<size; i++) { 1369639ff905SBarry Smith ierr = PetscViewerFlowControlStepMaster(viewer,i,&message_count,flowcontrolcount);CHKERRQ(ierr); 1370ce94432eSBarry Smith ierr = MPI_Recv(&rnz,1,MPIU_INT,i,tag,PetscObjectComm((PetscObject)mat),&status);CHKERRQ(ierr); 1371e32f2f54SBarry Smith if (rnz > nzmax) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Internal PETSc error: nz = %D nzmax = %D",nz,nzmax); 1372ce94432eSBarry Smith ierr = MPIULong_Recv(column_values,rnz,MPIU_SCALAR,i,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 13736f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,column_values,rnz,PETSC_SCALAR,PETSC_TRUE);CHKERRQ(ierr); 13748e2fed03SBarry Smith } 1375639ff905SBarry Smith ierr = PetscViewerFlowControlEndMaster(viewer,&message_count);CHKERRQ(ierr); 13768e2fed03SBarry Smith } else { 1377639ff905SBarry Smith ierr = PetscViewerFlowControlStepWorker(viewer,rank,&message_count);CHKERRQ(ierr); 1378ce94432eSBarry Smith ierr = MPI_Send(&nz,1,MPIU_INT,0,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1379ce94432eSBarry Smith ierr = MPIULong_Send(column_values,nz,MPIU_SCALAR,0,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1380639ff905SBarry Smith ierr = PetscViewerFlowControlEndWorker(viewer,&message_count);CHKERRQ(ierr); 13818e2fed03SBarry Smith } 13828e2fed03SBarry Smith ierr = PetscFree(column_values);CHKERRQ(ierr); 1383b37d52dbSMark F. Adams 1384b37d52dbSMark F. Adams ierr = PetscViewerBinaryGetInfoPointer(viewer,&file);CHKERRQ(ierr); 138533d57670SJed Brown if (file) fprintf(file,"-matload_block_size %d\n",(int)PetscAbs(mat->rmap->bs)); 13868e2fed03SBarry Smith PetscFunctionReturn(0); 13878e2fed03SBarry Smith } 13888e2fed03SBarry Smith 13899804daf3SBarry Smith #include <petscdraw.h> 1390dfbe8321SBarry Smith PetscErrorCode MatView_MPIAIJ_ASCIIorDraworSocket(Mat mat,PetscViewer viewer) 1391416022c9SBarry Smith { 139244a69424SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 1393dfbe8321SBarry Smith PetscErrorCode ierr; 139432dcc486SBarry Smith PetscMPIInt rank = aij->rank,size = aij->size; 1395ace3abfcSBarry Smith PetscBool isdraw,iascii,isbinary; 1396b0a32e0cSBarry Smith PetscViewer sviewer; 1397f3ef73ceSBarry Smith PetscViewerFormat format; 1398416022c9SBarry Smith 13993a40ed3dSBarry Smith PetscFunctionBegin; 1400251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 1401251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1402251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 140332077d6dSBarry Smith if (iascii) { 1404b0a32e0cSBarry Smith ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 1405ef5fdb51SBarry Smith if (format == PETSC_VIEWER_LOAD_BALANCE) { 1406ef5fdb51SBarry Smith PetscInt i,nmax = 0,nmin = PETSC_MAX_INT,navg = 0,*nz,nzlocal = ((Mat_SeqAIJ*) (aij->A->data))->nz + ((Mat_SeqAIJ*) (aij->B->data))->nz; 1407ef5fdb51SBarry Smith ierr = PetscMalloc1(size,&nz);CHKERRQ(ierr); 1408ef5fdb51SBarry Smith ierr = MPI_Allgather(&nzlocal,1,MPIU_INT,nz,1,MPIU_INT,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1409ef5fdb51SBarry Smith for (i=0; i<(PetscInt)size; i++) { 1410ef5fdb51SBarry Smith nmax = PetscMax(nmax,nz[i]); 1411ef5fdb51SBarry Smith nmin = PetscMin(nmin,nz[i]); 1412ef5fdb51SBarry Smith navg += nz[i]; 1413ef5fdb51SBarry Smith } 1414ef5fdb51SBarry Smith ierr = PetscFree(nz);CHKERRQ(ierr); 1415ef5fdb51SBarry Smith navg = navg/size; 141676a8abe0SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Load Balance - Nonzeros: Min %D avg %D max %D\n",nmin,navg,nmax);CHKERRQ(ierr); 1417ef5fdb51SBarry Smith PetscFunctionReturn(0); 1418ef5fdb51SBarry Smith } 1419ef5fdb51SBarry Smith ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 1420456192e2SBarry Smith if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 14214e220ebcSLois Curfman McInnes MatInfo info; 1422ace3abfcSBarry Smith PetscBool inodes; 1423923f20ffSKris Buschelman 1424ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr); 1425888f2ed8SSatish Balay ierr = MatGetInfo(mat,MAT_LOCAL,&info);CHKERRQ(ierr); 14260298fd71SBarry Smith ierr = MatInodeGetInodeSizes(aij->A,NULL,(PetscInt**)&inodes,NULL);CHKERRQ(ierr); 1427c5e4d11fSDmitry Karpeev ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 1428923f20ffSKris Buschelman if (!inodes) { 1429b1e9c6f1SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local rows %D nz %D nz alloced %D mem %g, not using I-node routines\n", 1430b1e9c6f1SBarry Smith rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(double)info.memory);CHKERRQ(ierr); 14316831982aSBarry Smith } else { 1432b1e9c6f1SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local rows %D nz %D nz alloced %D mem %g, using I-node routines\n", 1433b1e9c6f1SBarry Smith rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(double)info.memory);CHKERRQ(ierr); 14346831982aSBarry Smith } 1435888f2ed8SSatish Balay ierr = MatGetInfo(aij->A,MAT_LOCAL,&info);CHKERRQ(ierr); 143677431f27SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] on-diagonal part: nz %D \n",rank,(PetscInt)info.nz_used);CHKERRQ(ierr); 1437888f2ed8SSatish Balay ierr = MatGetInfo(aij->B,MAT_LOCAL,&info);CHKERRQ(ierr); 143877431f27SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] off-diagonal part: nz %D \n",rank,(PetscInt)info.nz_used);CHKERRQ(ierr); 1439b0a32e0cSBarry Smith ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1440c5e4d11fSDmitry Karpeev ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 144107d81ca4SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Information on VecScatter used in matrix-vector product: \n");CHKERRQ(ierr); 1442a40aa06bSLois Curfman McInnes ierr = VecScatterView(aij->Mvctx,viewer);CHKERRQ(ierr); 14433a40ed3dSBarry Smith PetscFunctionReturn(0); 1444fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_INFO) { 1445923f20ffSKris Buschelman PetscInt inodecount,inodelimit,*inodes; 1446923f20ffSKris Buschelman ierr = MatInodeGetInodeSizes(aij->A,&inodecount,&inodes,&inodelimit);CHKERRQ(ierr); 1447923f20ffSKris Buschelman if (inodes) { 1448923f20ffSKris Buschelman ierr = PetscViewerASCIIPrintf(viewer,"using I-node (on process 0) routines: found %D nodes, limit used is %D\n",inodecount,inodelimit);CHKERRQ(ierr); 1449d38fa0fbSBarry Smith } else { 1450d38fa0fbSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"not using I-node (on process 0) routines\n");CHKERRQ(ierr); 1451d38fa0fbSBarry Smith } 14523a40ed3dSBarry Smith PetscFunctionReturn(0); 14534aedb280SBarry Smith } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 14544aedb280SBarry Smith PetscFunctionReturn(0); 145508480c60SBarry Smith } 14568e2fed03SBarry Smith } else if (isbinary) { 14578e2fed03SBarry Smith if (size == 1) { 14587adad957SLisandro Dalcin ierr = PetscObjectSetName((PetscObject)aij->A,((PetscObject)mat)->name);CHKERRQ(ierr); 14598e2fed03SBarry Smith ierr = MatView(aij->A,viewer);CHKERRQ(ierr); 14608e2fed03SBarry Smith } else { 14618e2fed03SBarry Smith ierr = MatView_MPIAIJ_Binary(mat,viewer);CHKERRQ(ierr); 14628e2fed03SBarry Smith } 14638e2fed03SBarry Smith PetscFunctionReturn(0); 146471e56450SStefano Zampini } else if (iascii && size == 1) { 146571e56450SStefano Zampini ierr = PetscObjectSetName((PetscObject)aij->A,((PetscObject)mat)->name);CHKERRQ(ierr); 146671e56450SStefano Zampini ierr = MatView(aij->A,viewer);CHKERRQ(ierr); 146771e56450SStefano Zampini PetscFunctionReturn(0); 14680f5bd95cSBarry Smith } else if (isdraw) { 1469b0a32e0cSBarry Smith PetscDraw draw; 1470ace3abfcSBarry Smith PetscBool isnull; 1471b0a32e0cSBarry Smith ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 1472383922c3SLisandro Dalcin ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); 1473383922c3SLisandro Dalcin if (isnull) PetscFunctionReturn(0); 147419bcc07fSBarry Smith } 147519bcc07fSBarry Smith 147671e56450SStefano Zampini { /* assemble the entire matrix onto first processor */ 147771e56450SStefano Zampini Mat A = NULL, Av; 147871e56450SStefano Zampini IS isrow,iscol; 14792ee70a88SLois Curfman McInnes 148071e56450SStefano Zampini ierr = ISCreateStride(PetscObjectComm((PetscObject)mat),!rank ? mat->rmap->N : 0,0,1,&isrow);CHKERRQ(ierr); 148171e56450SStefano Zampini ierr = ISCreateStride(PetscObjectComm((PetscObject)mat),!rank ? mat->cmap->N : 0,0,1,&iscol);CHKERRQ(ierr); 148271e56450SStefano Zampini ierr = MatCreateSubMatrix(mat,isrow,iscol,MAT_INITIAL_MATRIX,&A);CHKERRQ(ierr); 148371e56450SStefano Zampini ierr = MatMPIAIJGetSeqAIJ(A,&Av,NULL,NULL);CHKERRQ(ierr); 148471e56450SStefano Zampini /* The commented code uses MatCreateSubMatrices instead */ 148571e56450SStefano Zampini /* 148671e56450SStefano Zampini Mat *AA, A = NULL, Av; 148771e56450SStefano Zampini IS isrow,iscol; 148871e56450SStefano Zampini 148971e56450SStefano Zampini ierr = ISCreateStride(PetscObjectComm((PetscObject)mat),!rank ? mat->rmap->N : 0,0,1,&isrow);CHKERRQ(ierr); 149071e56450SStefano Zampini ierr = ISCreateStride(PetscObjectComm((PetscObject)mat),!rank ? mat->cmap->N : 0,0,1,&iscol);CHKERRQ(ierr); 149171e56450SStefano Zampini ierr = MatCreateSubMatrices(mat,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&AA);CHKERRQ(ierr); 149217699dbbSLois Curfman McInnes if (!rank) { 149371e56450SStefano Zampini ierr = PetscObjectReference((PetscObject)AA[0]);CHKERRQ(ierr); 149471e56450SStefano Zampini A = AA[0]; 149571e56450SStefano Zampini Av = AA[0]; 149695373324SBarry Smith } 149771e56450SStefano Zampini ierr = MatDestroySubMatrices(1,&AA);CHKERRQ(ierr); 149871e56450SStefano Zampini */ 149971e56450SStefano Zampini ierr = ISDestroy(&iscol);CHKERRQ(ierr); 150071e56450SStefano Zampini ierr = ISDestroy(&isrow);CHKERRQ(ierr); 150155843e3eSBarry Smith /* 150255843e3eSBarry Smith Everyone has to call to draw the matrix since the graphics waits are 1503b0a32e0cSBarry Smith synchronized across all processors that share the PetscDraw object 150455843e3eSBarry Smith */ 1505c5e4d11fSDmitry Karpeev ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 15063e219373SBarry Smith if (!rank) { 150771e56450SStefano Zampini if (((PetscObject)mat)->name) { 150871e56450SStefano Zampini ierr = PetscObjectSetName((PetscObject)Av,((PetscObject)mat)->name);CHKERRQ(ierr); 150971e56450SStefano Zampini } 151071e56450SStefano Zampini ierr = MatView_SeqAIJ(Av,sviewer);CHKERRQ(ierr); 151195373324SBarry Smith } 1512c5e4d11fSDmitry Karpeev ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 1513c5e4d11fSDmitry Karpeev ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 15146bf464f9SBarry Smith ierr = MatDestroy(&A);CHKERRQ(ierr); 151595373324SBarry Smith } 15163a40ed3dSBarry Smith PetscFunctionReturn(0); 15171eb62cbbSBarry Smith } 15181eb62cbbSBarry Smith 1519dfbe8321SBarry Smith PetscErrorCode MatView_MPIAIJ(Mat mat,PetscViewer viewer) 1520416022c9SBarry Smith { 1521dfbe8321SBarry Smith PetscErrorCode ierr; 1522ace3abfcSBarry Smith PetscBool iascii,isdraw,issocket,isbinary; 1523416022c9SBarry Smith 15243a40ed3dSBarry Smith PetscFunctionBegin; 1525251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1526251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 1527251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 1528251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSOCKET,&issocket);CHKERRQ(ierr); 152932077d6dSBarry Smith if (iascii || isdraw || isbinary || issocket) { 15307b2a1423SBarry Smith ierr = MatView_MPIAIJ_ASCIIorDraworSocket(mat,viewer);CHKERRQ(ierr); 1531416022c9SBarry Smith } 15323a40ed3dSBarry Smith PetscFunctionReturn(0); 1533416022c9SBarry Smith } 1534416022c9SBarry Smith 153541f059aeSBarry Smith PetscErrorCode MatSOR_MPIAIJ(Mat matin,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 15368a729477SBarry Smith { 153744a69424SLois Curfman McInnes Mat_MPIAIJ *mat = (Mat_MPIAIJ*)matin->data; 1538dfbe8321SBarry Smith PetscErrorCode ierr; 15396987fefcSBarry Smith Vec bb1 = 0; 1540ace3abfcSBarry Smith PetscBool hasop; 15418a729477SBarry Smith 15423a40ed3dSBarry Smith PetscFunctionBegin; 1543a2b30743SBarry Smith if (flag == SOR_APPLY_UPPER) { 154441f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr); 1545a2b30743SBarry Smith PetscFunctionReturn(0); 1546a2b30743SBarry Smith } 1547a2b30743SBarry Smith 15484e980039SJed Brown if (its > 1 || ~flag & SOR_ZERO_INITIAL_GUESS || flag & SOR_EISENSTAT) { 15494e980039SJed Brown ierr = VecDuplicate(bb,&bb1);CHKERRQ(ierr); 15504e980039SJed Brown } 15514e980039SJed Brown 1552c16cb8f2SBarry Smith if ((flag & SOR_LOCAL_SYMMETRIC_SWEEP) == SOR_LOCAL_SYMMETRIC_SWEEP) { 1553da3a660dSBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 155441f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr); 15552798e883SHong Zhang its--; 1556da3a660dSBarry Smith } 15572798e883SHong Zhang 15582798e883SHong Zhang while (its--) { 1559ca9f406cSSatish Balay ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1560ca9f406cSSatish Balay ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 15612798e883SHong Zhang 1562c14dc6b6SHong Zhang /* update rhs: bb1 = bb - B*x */ 1563efb30889SBarry Smith ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr); 1564c14dc6b6SHong Zhang ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr); 15652798e883SHong Zhang 1566c14dc6b6SHong Zhang /* local sweep */ 156741f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_SYMMETRIC_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr); 15682798e883SHong Zhang } 15693a40ed3dSBarry Smith } else if (flag & SOR_LOCAL_FORWARD_SWEEP) { 1570da3a660dSBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 157141f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr); 15722798e883SHong Zhang its--; 1573da3a660dSBarry Smith } 15742798e883SHong Zhang while (its--) { 1575ca9f406cSSatish Balay ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1576ca9f406cSSatish Balay ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 15772798e883SHong Zhang 1578c14dc6b6SHong Zhang /* update rhs: bb1 = bb - B*x */ 1579efb30889SBarry Smith ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr); 1580c14dc6b6SHong Zhang ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr); 1581c14dc6b6SHong Zhang 1582c14dc6b6SHong Zhang /* local sweep */ 158341f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_FORWARD_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr); 15842798e883SHong Zhang } 15853a40ed3dSBarry Smith } else if (flag & SOR_LOCAL_BACKWARD_SWEEP) { 1586da3a660dSBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 158741f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr); 15882798e883SHong Zhang its--; 1589da3a660dSBarry Smith } 15902798e883SHong Zhang while (its--) { 1591ca9f406cSSatish Balay ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1592ca9f406cSSatish Balay ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 15932798e883SHong Zhang 1594c14dc6b6SHong Zhang /* update rhs: bb1 = bb - B*x */ 1595efb30889SBarry Smith ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr); 1596c14dc6b6SHong Zhang ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr); 15972798e883SHong Zhang 1598c14dc6b6SHong Zhang /* local sweep */ 159941f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_BACKWARD_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr); 16002798e883SHong Zhang } 1601a7420bb7SBarry Smith } else if (flag & SOR_EISENSTAT) { 1602a7420bb7SBarry Smith Vec xx1; 1603a7420bb7SBarry Smith 1604a7420bb7SBarry Smith ierr = VecDuplicate(bb,&xx1);CHKERRQ(ierr); 160541f059aeSBarry 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); 1606a7420bb7SBarry Smith 1607a7420bb7SBarry Smith ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1608a7420bb7SBarry Smith ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1609a7420bb7SBarry Smith if (!mat->diag) { 16102a7a6963SBarry Smith ierr = MatCreateVecs(matin,&mat->diag,NULL);CHKERRQ(ierr); 1611a7420bb7SBarry Smith ierr = MatGetDiagonal(matin,mat->diag);CHKERRQ(ierr); 1612a7420bb7SBarry Smith } 1613bd0c2dcbSBarry Smith ierr = MatHasOperation(matin,MATOP_MULT_DIAGONAL_BLOCK,&hasop);CHKERRQ(ierr); 1614bd0c2dcbSBarry Smith if (hasop) { 1615bd0c2dcbSBarry Smith ierr = MatMultDiagonalBlock(matin,xx,bb1);CHKERRQ(ierr); 1616bd0c2dcbSBarry Smith } else { 1617a7420bb7SBarry Smith ierr = VecPointwiseMult(bb1,mat->diag,xx);CHKERRQ(ierr); 1618bd0c2dcbSBarry Smith } 1619887ee2caSBarry Smith ierr = VecAYPX(bb1,(omega-2.0)/omega,bb);CHKERRQ(ierr); 1620887ee2caSBarry Smith 1621a7420bb7SBarry Smith ierr = MatMultAdd(mat->B,mat->lvec,bb1,bb1);CHKERRQ(ierr); 1622a7420bb7SBarry Smith 1623a7420bb7SBarry Smith /* local sweep */ 162441f059aeSBarry 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); 1625a7420bb7SBarry Smith ierr = VecAXPY(xx,1.0,xx1);CHKERRQ(ierr); 16266bf464f9SBarry Smith ierr = VecDestroy(&xx1);CHKERRQ(ierr); 1627ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)matin),PETSC_ERR_SUP,"Parallel SOR not supported"); 1628c14dc6b6SHong Zhang 16296bf464f9SBarry Smith ierr = VecDestroy(&bb1);CHKERRQ(ierr); 1630a0808db4SHong Zhang 16317b6c816cSBarry Smith matin->factorerrortype = mat->A->factorerrortype; 16323a40ed3dSBarry Smith PetscFunctionReturn(0); 16338a729477SBarry Smith } 1634a66be287SLois Curfman McInnes 163542e855d1Svictor PetscErrorCode MatPermute_MPIAIJ(Mat A,IS rowp,IS colp,Mat *B) 163642e855d1Svictor { 163772e6a0cfSJed Brown Mat aA,aB,Aperm; 163872e6a0cfSJed Brown const PetscInt *rwant,*cwant,*gcols,*ai,*bi,*aj,*bj; 163972e6a0cfSJed Brown PetscScalar *aa,*ba; 164072e6a0cfSJed Brown PetscInt i,j,m,n,ng,anz,bnz,*dnnz,*onnz,*tdnnz,*tonnz,*rdest,*cdest,*work,*gcdest; 164172e6a0cfSJed Brown PetscSF rowsf,sf; 16420298fd71SBarry Smith IS parcolp = NULL; 164372e6a0cfSJed Brown PetscBool done; 164442e855d1Svictor PetscErrorCode ierr; 164542e855d1Svictor 164642e855d1Svictor PetscFunctionBegin; 164772e6a0cfSJed Brown ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); 164872e6a0cfSJed Brown ierr = ISGetIndices(rowp,&rwant);CHKERRQ(ierr); 164972e6a0cfSJed Brown ierr = ISGetIndices(colp,&cwant);CHKERRQ(ierr); 1650dcca6d9dSJed Brown ierr = PetscMalloc3(PetscMax(m,n),&work,m,&rdest,n,&cdest);CHKERRQ(ierr); 165172e6a0cfSJed Brown 165272e6a0cfSJed Brown /* Invert row permutation to find out where my rows should go */ 1653ce94432eSBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)A),&rowsf);CHKERRQ(ierr); 16540298fd71SBarry Smith ierr = PetscSFSetGraphLayout(rowsf,A->rmap,A->rmap->n,NULL,PETSC_OWN_POINTER,rwant);CHKERRQ(ierr); 1655e9e74f11SJed Brown ierr = PetscSFSetFromOptions(rowsf);CHKERRQ(ierr); 165672e6a0cfSJed Brown for (i=0; i<m; i++) work[i] = A->rmap->rstart + i; 16578bfbc91cSJed Brown ierr = PetscSFReduceBegin(rowsf,MPIU_INT,work,rdest,MPIU_REPLACE);CHKERRQ(ierr); 16588bfbc91cSJed Brown ierr = PetscSFReduceEnd(rowsf,MPIU_INT,work,rdest,MPIU_REPLACE);CHKERRQ(ierr); 165972e6a0cfSJed Brown 166072e6a0cfSJed Brown /* Invert column permutation to find out where my columns should go */ 1661ce94432eSBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)A),&sf);CHKERRQ(ierr); 16620298fd71SBarry Smith ierr = PetscSFSetGraphLayout(sf,A->cmap,A->cmap->n,NULL,PETSC_OWN_POINTER,cwant);CHKERRQ(ierr); 1663e9e74f11SJed Brown ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); 166472e6a0cfSJed Brown for (i=0; i<n; i++) work[i] = A->cmap->rstart + i; 16658bfbc91cSJed Brown ierr = PetscSFReduceBegin(sf,MPIU_INT,work,cdest,MPIU_REPLACE);CHKERRQ(ierr); 16668bfbc91cSJed Brown ierr = PetscSFReduceEnd(sf,MPIU_INT,work,cdest,MPIU_REPLACE);CHKERRQ(ierr); 166772e6a0cfSJed Brown ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 166872e6a0cfSJed Brown 166972e6a0cfSJed Brown ierr = ISRestoreIndices(rowp,&rwant);CHKERRQ(ierr); 167072e6a0cfSJed Brown ierr = ISRestoreIndices(colp,&cwant);CHKERRQ(ierr); 167172e6a0cfSJed Brown ierr = MatMPIAIJGetSeqAIJ(A,&aA,&aB,&gcols);CHKERRQ(ierr); 167272e6a0cfSJed Brown 167372e6a0cfSJed Brown /* Find out where my gcols should go */ 16740298fd71SBarry Smith ierr = MatGetSize(aB,NULL,&ng);CHKERRQ(ierr); 1675785e854fSJed Brown ierr = PetscMalloc1(ng,&gcdest);CHKERRQ(ierr); 1676ce94432eSBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)A),&sf);CHKERRQ(ierr); 16770298fd71SBarry Smith ierr = PetscSFSetGraphLayout(sf,A->cmap,ng,NULL,PETSC_OWN_POINTER,gcols);CHKERRQ(ierr); 1678e9e74f11SJed Brown ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); 167972e6a0cfSJed Brown ierr = PetscSFBcastBegin(sf,MPIU_INT,cdest,gcdest);CHKERRQ(ierr); 168072e6a0cfSJed Brown ierr = PetscSFBcastEnd(sf,MPIU_INT,cdest,gcdest);CHKERRQ(ierr); 168172e6a0cfSJed Brown ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 168272e6a0cfSJed Brown 16831795a4d1SJed Brown ierr = PetscCalloc4(m,&dnnz,m,&onnz,m,&tdnnz,m,&tonnz);CHKERRQ(ierr); 168472e6a0cfSJed Brown ierr = MatGetRowIJ(aA,0,PETSC_FALSE,PETSC_FALSE,&anz,&ai,&aj,&done);CHKERRQ(ierr); 168572e6a0cfSJed Brown ierr = MatGetRowIJ(aB,0,PETSC_FALSE,PETSC_FALSE,&bnz,&bi,&bj,&done);CHKERRQ(ierr); 168672e6a0cfSJed Brown for (i=0; i<m; i++) { 168772e6a0cfSJed Brown PetscInt row = rdest[i],rowner; 168872e6a0cfSJed Brown ierr = PetscLayoutFindOwner(A->rmap,row,&rowner);CHKERRQ(ierr); 168972e6a0cfSJed Brown for (j=ai[i]; j<ai[i+1]; j++) { 169072e6a0cfSJed Brown PetscInt cowner,col = cdest[aj[j]]; 169172e6a0cfSJed Brown ierr = PetscLayoutFindOwner(A->cmap,col,&cowner);CHKERRQ(ierr); /* Could build an index for the columns to eliminate this search */ 169272e6a0cfSJed Brown if (rowner == cowner) dnnz[i]++; 169372e6a0cfSJed Brown else onnz[i]++; 169472e6a0cfSJed Brown } 169572e6a0cfSJed Brown for (j=bi[i]; j<bi[i+1]; j++) { 169672e6a0cfSJed Brown PetscInt cowner,col = gcdest[bj[j]]; 169772e6a0cfSJed Brown ierr = PetscLayoutFindOwner(A->cmap,col,&cowner);CHKERRQ(ierr); 169872e6a0cfSJed Brown if (rowner == cowner) dnnz[i]++; 169972e6a0cfSJed Brown else onnz[i]++; 170072e6a0cfSJed Brown } 170172e6a0cfSJed Brown } 170272e6a0cfSJed Brown ierr = PetscSFBcastBegin(rowsf,MPIU_INT,dnnz,tdnnz);CHKERRQ(ierr); 170372e6a0cfSJed Brown ierr = PetscSFBcastEnd(rowsf,MPIU_INT,dnnz,tdnnz);CHKERRQ(ierr); 170472e6a0cfSJed Brown ierr = PetscSFBcastBegin(rowsf,MPIU_INT,onnz,tonnz);CHKERRQ(ierr); 170572e6a0cfSJed Brown ierr = PetscSFBcastEnd(rowsf,MPIU_INT,onnz,tonnz);CHKERRQ(ierr); 170672e6a0cfSJed Brown ierr = PetscSFDestroy(&rowsf);CHKERRQ(ierr); 170772e6a0cfSJed Brown 1708ce94432eSBarry Smith ierr = MatCreateAIJ(PetscObjectComm((PetscObject)A),A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,0,tdnnz,0,tonnz,&Aperm);CHKERRQ(ierr); 170972e6a0cfSJed Brown ierr = MatSeqAIJGetArray(aA,&aa);CHKERRQ(ierr); 171072e6a0cfSJed Brown ierr = MatSeqAIJGetArray(aB,&ba);CHKERRQ(ierr); 171172e6a0cfSJed Brown for (i=0; i<m; i++) { 171272e6a0cfSJed Brown PetscInt *acols = dnnz,*bcols = onnz; /* Repurpose now-unneeded arrays */ 1713970468b0SJed Brown PetscInt j0,rowlen; 171472e6a0cfSJed Brown rowlen = ai[i+1] - ai[i]; 1715970468b0SJed Brown for (j0=j=0; j<rowlen; j0=j) { /* rowlen could be larger than number of rows m, so sum in batches */ 1716970468b0SJed Brown for ( ; j<PetscMin(rowlen,j0+m); j++) acols[j-j0] = cdest[aj[ai[i]+j]]; 1717970468b0SJed Brown ierr = MatSetValues(Aperm,1,&rdest[i],j-j0,acols,aa+ai[i]+j0,INSERT_VALUES);CHKERRQ(ierr); 1718970468b0SJed Brown } 171972e6a0cfSJed Brown rowlen = bi[i+1] - bi[i]; 1720970468b0SJed Brown for (j0=j=0; j<rowlen; j0=j) { 1721970468b0SJed Brown for ( ; j<PetscMin(rowlen,j0+m); j++) bcols[j-j0] = gcdest[bj[bi[i]+j]]; 1722970468b0SJed Brown ierr = MatSetValues(Aperm,1,&rdest[i],j-j0,bcols,ba+bi[i]+j0,INSERT_VALUES);CHKERRQ(ierr); 1723970468b0SJed Brown } 172472e6a0cfSJed Brown } 172572e6a0cfSJed Brown ierr = MatAssemblyBegin(Aperm,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 172672e6a0cfSJed Brown ierr = MatAssemblyEnd(Aperm,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 172772e6a0cfSJed Brown ierr = MatRestoreRowIJ(aA,0,PETSC_FALSE,PETSC_FALSE,&anz,&ai,&aj,&done);CHKERRQ(ierr); 172872e6a0cfSJed Brown ierr = MatRestoreRowIJ(aB,0,PETSC_FALSE,PETSC_FALSE,&bnz,&bi,&bj,&done);CHKERRQ(ierr); 172972e6a0cfSJed Brown ierr = MatSeqAIJRestoreArray(aA,&aa);CHKERRQ(ierr); 173072e6a0cfSJed Brown ierr = MatSeqAIJRestoreArray(aB,&ba);CHKERRQ(ierr); 173172e6a0cfSJed Brown ierr = PetscFree4(dnnz,onnz,tdnnz,tonnz);CHKERRQ(ierr); 173272e6a0cfSJed Brown ierr = PetscFree3(work,rdest,cdest);CHKERRQ(ierr); 173372e6a0cfSJed Brown ierr = PetscFree(gcdest);CHKERRQ(ierr); 173472e6a0cfSJed Brown if (parcolp) {ierr = ISDestroy(&colp);CHKERRQ(ierr);} 173572e6a0cfSJed Brown *B = Aperm; 173642e855d1Svictor PetscFunctionReturn(0); 173742e855d1Svictor } 173842e855d1Svictor 1739c5e4d11fSDmitry Karpeev PetscErrorCode MatGetGhosts_MPIAIJ(Mat mat,PetscInt *nghosts,const PetscInt *ghosts[]) 1740c5e4d11fSDmitry Karpeev { 1741c5e4d11fSDmitry Karpeev Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 1742c5e4d11fSDmitry Karpeev PetscErrorCode ierr; 1743c5e4d11fSDmitry Karpeev 1744c5e4d11fSDmitry Karpeev PetscFunctionBegin; 1745c5e4d11fSDmitry Karpeev ierr = MatGetSize(aij->B,NULL,nghosts);CHKERRQ(ierr); 1746c5e4d11fSDmitry Karpeev if (ghosts) *ghosts = aij->garray; 1747c5e4d11fSDmitry Karpeev PetscFunctionReturn(0); 1748c5e4d11fSDmitry Karpeev } 1749c5e4d11fSDmitry Karpeev 1750dfbe8321SBarry Smith PetscErrorCode MatGetInfo_MPIAIJ(Mat matin,MatInfoType flag,MatInfo *info) 1751a66be287SLois Curfman McInnes { 1752a66be287SLois Curfman McInnes Mat_MPIAIJ *mat = (Mat_MPIAIJ*)matin->data; 1753a66be287SLois Curfman McInnes Mat A = mat->A,B = mat->B; 1754dfbe8321SBarry Smith PetscErrorCode ierr; 1755329f5518SBarry Smith PetscReal isend[5],irecv[5]; 1756a66be287SLois Curfman McInnes 17573a40ed3dSBarry Smith PetscFunctionBegin; 17584e220ebcSLois Curfman McInnes info->block_size = 1.0; 17594e220ebcSLois Curfman McInnes ierr = MatGetInfo(A,MAT_LOCAL,info);CHKERRQ(ierr); 17602205254eSKarl Rupp 17614e220ebcSLois Curfman McInnes isend[0] = info->nz_used; isend[1] = info->nz_allocated; isend[2] = info->nz_unneeded; 17624e220ebcSLois Curfman McInnes isend[3] = info->memory; isend[4] = info->mallocs; 17632205254eSKarl Rupp 17644e220ebcSLois Curfman McInnes ierr = MatGetInfo(B,MAT_LOCAL,info);CHKERRQ(ierr); 17652205254eSKarl Rupp 17664e220ebcSLois Curfman McInnes isend[0] += info->nz_used; isend[1] += info->nz_allocated; isend[2] += info->nz_unneeded; 17674e220ebcSLois Curfman McInnes isend[3] += info->memory; isend[4] += info->mallocs; 1768a66be287SLois Curfman McInnes if (flag == MAT_LOCAL) { 17694e220ebcSLois Curfman McInnes info->nz_used = isend[0]; 17704e220ebcSLois Curfman McInnes info->nz_allocated = isend[1]; 17714e220ebcSLois Curfman McInnes info->nz_unneeded = isend[2]; 17724e220ebcSLois Curfman McInnes info->memory = isend[3]; 17734e220ebcSLois Curfman McInnes info->mallocs = isend[4]; 1774a66be287SLois Curfman McInnes } else if (flag == MAT_GLOBAL_MAX) { 1775b2566f29SBarry Smith ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)matin));CHKERRQ(ierr); 17762205254eSKarl Rupp 17774e220ebcSLois Curfman McInnes info->nz_used = irecv[0]; 17784e220ebcSLois Curfman McInnes info->nz_allocated = irecv[1]; 17794e220ebcSLois Curfman McInnes info->nz_unneeded = irecv[2]; 17804e220ebcSLois Curfman McInnes info->memory = irecv[3]; 17814e220ebcSLois Curfman McInnes info->mallocs = irecv[4]; 1782a66be287SLois Curfman McInnes } else if (flag == MAT_GLOBAL_SUM) { 1783b2566f29SBarry Smith ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)matin));CHKERRQ(ierr); 17842205254eSKarl Rupp 17854e220ebcSLois Curfman McInnes info->nz_used = irecv[0]; 17864e220ebcSLois Curfman McInnes info->nz_allocated = irecv[1]; 17874e220ebcSLois Curfman McInnes info->nz_unneeded = irecv[2]; 17884e220ebcSLois Curfman McInnes info->memory = irecv[3]; 17894e220ebcSLois Curfman McInnes info->mallocs = irecv[4]; 1790a66be287SLois Curfman McInnes } 17914e220ebcSLois Curfman McInnes info->fill_ratio_given = 0; /* no parallel LU/ILU/Cholesky */ 17924e220ebcSLois Curfman McInnes info->fill_ratio_needed = 0; 17934e220ebcSLois Curfman McInnes info->factor_mallocs = 0; 17943a40ed3dSBarry Smith PetscFunctionReturn(0); 1795a66be287SLois Curfman McInnes } 1796a66be287SLois Curfman McInnes 1797ace3abfcSBarry Smith PetscErrorCode MatSetOption_MPIAIJ(Mat A,MatOption op,PetscBool flg) 1798c74985f6SBarry Smith { 1799c0bbcb79SLois Curfman McInnes Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1800dfbe8321SBarry Smith PetscErrorCode ierr; 1801c74985f6SBarry Smith 18023a40ed3dSBarry Smith PetscFunctionBegin; 180312c028f9SKris Buschelman switch (op) { 1804512a5fc5SBarry Smith case MAT_NEW_NONZERO_LOCATIONS: 180512c028f9SKris Buschelman case MAT_NEW_NONZERO_ALLOCATION_ERR: 180628b2fa4aSMatthew Knepley case MAT_UNUSED_NONZERO_LOCATION_ERR: 1807a9817697SBarry Smith case MAT_KEEP_NONZERO_PATTERN: 180812c028f9SKris Buschelman case MAT_NEW_NONZERO_LOCATION_ERR: 180912c028f9SKris Buschelman case MAT_USE_INODES: 181012c028f9SKris Buschelman case MAT_IGNORE_ZERO_ENTRIES: 1811fa1f0d2cSMatthew G Knepley MatCheckPreallocated(A,1); 18124e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 18134e0d8c25SBarry Smith ierr = MatSetOption(a->B,op,flg);CHKERRQ(ierr); 181412c028f9SKris Buschelman break; 181512c028f9SKris Buschelman case MAT_ROW_ORIENTED: 181643674050SBarry Smith MatCheckPreallocated(A,1); 18174e0d8c25SBarry Smith a->roworiented = flg; 18182205254eSKarl Rupp 18194e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 18204e0d8c25SBarry Smith ierr = MatSetOption(a->B,op,flg);CHKERRQ(ierr); 182112c028f9SKris Buschelman break; 18224e0d8c25SBarry Smith case MAT_NEW_DIAGONALS: 1823*071fcb05SBarry Smith case MAT_SORTED_FULL: 1824290bbb0aSBarry Smith ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr); 182512c028f9SKris Buschelman break; 182612c028f9SKris Buschelman case MAT_IGNORE_OFF_PROC_ENTRIES: 18275c0f0b64SBarry Smith a->donotstash = flg; 182812c028f9SKris Buschelman break; 1829c8ca1fbcSVaclav Hapla /* Symmetry flags are handled directly by MatSetOption() and they don't affect preallocation */ 1830ffa07934SHong Zhang case MAT_SPD: 183177e54ba9SKris Buschelman case MAT_SYMMETRIC: 183277e54ba9SKris Buschelman case MAT_STRUCTURALLY_SYMMETRIC: 1833bf108f30SBarry Smith case MAT_HERMITIAN: 1834bf108f30SBarry Smith case MAT_SYMMETRY_ETERNAL: 183577e54ba9SKris Buschelman break; 1836c10200c1SHong Zhang case MAT_SUBMAT_SINGLEIS: 1837c10200c1SHong Zhang A->submat_singleis = flg; 1838c10200c1SHong Zhang break; 1839957cac9fSHong Zhang case MAT_STRUCTURE_ONLY: 1840957cac9fSHong Zhang /* The option is handled directly by MatSetOption() */ 1841957cac9fSHong Zhang break; 184212c028f9SKris Buschelman default: 1843e32f2f54SBarry Smith SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op); 18443a40ed3dSBarry Smith } 18453a40ed3dSBarry Smith PetscFunctionReturn(0); 1846c74985f6SBarry Smith } 1847c74985f6SBarry Smith 1848b1d57f15SBarry Smith PetscErrorCode MatGetRow_MPIAIJ(Mat matin,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 184939e00950SLois Curfman McInnes { 1850154123eaSLois Curfman McInnes Mat_MPIAIJ *mat = (Mat_MPIAIJ*)matin->data; 185187828ca2SBarry Smith PetscScalar *vworkA,*vworkB,**pvA,**pvB,*v_p; 18526849ba73SBarry Smith PetscErrorCode ierr; 1853d0f46423SBarry Smith PetscInt i,*cworkA,*cworkB,**pcA,**pcB,cstart = matin->cmap->rstart; 1854d0f46423SBarry Smith PetscInt nztot,nzA,nzB,lrow,rstart = matin->rmap->rstart,rend = matin->rmap->rend; 1855b1d57f15SBarry Smith PetscInt *cmap,*idx_p; 185639e00950SLois Curfman McInnes 18573a40ed3dSBarry Smith PetscFunctionBegin; 1858e32f2f54SBarry Smith if (mat->getrowactive) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Already active"); 18597a0afa10SBarry Smith mat->getrowactive = PETSC_TRUE; 18607a0afa10SBarry Smith 186170f0671dSBarry Smith if (!mat->rowvalues && (idx || v)) { 18627a0afa10SBarry Smith /* 18637a0afa10SBarry Smith allocate enough space to hold information from the longest row. 18647a0afa10SBarry Smith */ 18657a0afa10SBarry Smith Mat_SeqAIJ *Aa = (Mat_SeqAIJ*)mat->A->data,*Ba = (Mat_SeqAIJ*)mat->B->data; 1866b1d57f15SBarry Smith PetscInt max = 1,tmp; 1867d0f46423SBarry Smith for (i=0; i<matin->rmap->n; i++) { 18687a0afa10SBarry Smith tmp = Aa->i[i+1] - Aa->i[i] + Ba->i[i+1] - Ba->i[i]; 18692205254eSKarl Rupp if (max < tmp) max = tmp; 18707a0afa10SBarry Smith } 1871dcca6d9dSJed Brown ierr = PetscMalloc2(max,&mat->rowvalues,max,&mat->rowindices);CHKERRQ(ierr); 18727a0afa10SBarry Smith } 18737a0afa10SBarry Smith 1874e7e72b3dSBarry Smith if (row < rstart || row >= rend) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only local rows"); 1875abc0e9e4SLois Curfman McInnes lrow = row - rstart; 187639e00950SLois Curfman McInnes 1877154123eaSLois Curfman McInnes pvA = &vworkA; pcA = &cworkA; pvB = &vworkB; pcB = &cworkB; 1878154123eaSLois Curfman McInnes if (!v) {pvA = 0; pvB = 0;} 1879154123eaSLois Curfman McInnes if (!idx) {pcA = 0; if (!v) pcB = 0;} 1880f830108cSBarry Smith ierr = (*mat->A->ops->getrow)(mat->A,lrow,&nzA,pcA,pvA);CHKERRQ(ierr); 1881f830108cSBarry Smith ierr = (*mat->B->ops->getrow)(mat->B,lrow,&nzB,pcB,pvB);CHKERRQ(ierr); 1882154123eaSLois Curfman McInnes nztot = nzA + nzB; 1883154123eaSLois Curfman McInnes 188470f0671dSBarry Smith cmap = mat->garray; 1885154123eaSLois Curfman McInnes if (v || idx) { 1886154123eaSLois Curfman McInnes if (nztot) { 1887154123eaSLois Curfman McInnes /* Sort by increasing column numbers, assuming A and B already sorted */ 1888b1d57f15SBarry Smith PetscInt imark = -1; 1889154123eaSLois Curfman McInnes if (v) { 189070f0671dSBarry Smith *v = v_p = mat->rowvalues; 189139e00950SLois Curfman McInnes for (i=0; i<nzB; i++) { 189270f0671dSBarry Smith if (cmap[cworkB[i]] < cstart) v_p[i] = vworkB[i]; 1893154123eaSLois Curfman McInnes else break; 1894154123eaSLois Curfman McInnes } 1895154123eaSLois Curfman McInnes imark = i; 189670f0671dSBarry Smith for (i=0; i<nzA; i++) v_p[imark+i] = vworkA[i]; 189770f0671dSBarry Smith for (i=imark; i<nzB; i++) v_p[nzA+i] = vworkB[i]; 1898154123eaSLois Curfman McInnes } 1899154123eaSLois Curfman McInnes if (idx) { 190070f0671dSBarry Smith *idx = idx_p = mat->rowindices; 190170f0671dSBarry Smith if (imark > -1) { 190270f0671dSBarry Smith for (i=0; i<imark; i++) { 190370f0671dSBarry Smith idx_p[i] = cmap[cworkB[i]]; 190470f0671dSBarry Smith } 190570f0671dSBarry Smith } else { 1906154123eaSLois Curfman McInnes for (i=0; i<nzB; i++) { 190770f0671dSBarry Smith if (cmap[cworkB[i]] < cstart) idx_p[i] = cmap[cworkB[i]]; 1908154123eaSLois Curfman McInnes else break; 1909154123eaSLois Curfman McInnes } 1910154123eaSLois Curfman McInnes imark = i; 191170f0671dSBarry Smith } 191270f0671dSBarry Smith for (i=0; i<nzA; i++) idx_p[imark+i] = cstart + cworkA[i]; 191370f0671dSBarry Smith for (i=imark; i<nzB; i++) idx_p[nzA+i] = cmap[cworkB[i]]; 191439e00950SLois Curfman McInnes } 19153f97c4b0SBarry Smith } else { 19161ca473b0SSatish Balay if (idx) *idx = 0; 19171ca473b0SSatish Balay if (v) *v = 0; 19181ca473b0SSatish Balay } 1919154123eaSLois Curfman McInnes } 192039e00950SLois Curfman McInnes *nz = nztot; 1921f830108cSBarry Smith ierr = (*mat->A->ops->restorerow)(mat->A,lrow,&nzA,pcA,pvA);CHKERRQ(ierr); 1922f830108cSBarry Smith ierr = (*mat->B->ops->restorerow)(mat->B,lrow,&nzB,pcB,pvB);CHKERRQ(ierr); 19233a40ed3dSBarry Smith PetscFunctionReturn(0); 192439e00950SLois Curfman McInnes } 192539e00950SLois Curfman McInnes 1926b1d57f15SBarry Smith PetscErrorCode MatRestoreRow_MPIAIJ(Mat mat,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 192739e00950SLois Curfman McInnes { 19287a0afa10SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 19293a40ed3dSBarry Smith 19303a40ed3dSBarry Smith PetscFunctionBegin; 1931e7e72b3dSBarry Smith if (!aij->getrowactive) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"MatGetRow() must be called first"); 19327a0afa10SBarry Smith aij->getrowactive = PETSC_FALSE; 19333a40ed3dSBarry Smith PetscFunctionReturn(0); 193439e00950SLois Curfman McInnes } 193539e00950SLois Curfman McInnes 1936dfbe8321SBarry Smith PetscErrorCode MatNorm_MPIAIJ(Mat mat,NormType type,PetscReal *norm) 1937855ac2c5SLois Curfman McInnes { 1938855ac2c5SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 1939ec8511deSBarry Smith Mat_SeqAIJ *amat = (Mat_SeqAIJ*)aij->A->data,*bmat = (Mat_SeqAIJ*)aij->B->data; 1940dfbe8321SBarry Smith PetscErrorCode ierr; 1941d0f46423SBarry Smith PetscInt i,j,cstart = mat->cmap->rstart; 1942329f5518SBarry Smith PetscReal sum = 0.0; 1943a77337e4SBarry Smith MatScalar *v; 194404ca555eSLois Curfman McInnes 19453a40ed3dSBarry Smith PetscFunctionBegin; 194617699dbbSLois Curfman McInnes if (aij->size == 1) { 194714183eadSLois Curfman McInnes ierr = MatNorm(aij->A,type,norm);CHKERRQ(ierr); 194837fa93a5SLois Curfman McInnes } else { 194904ca555eSLois Curfman McInnes if (type == NORM_FROBENIUS) { 195004ca555eSLois Curfman McInnes v = amat->a; 195104ca555eSLois Curfman McInnes for (i=0; i<amat->nz; i++) { 1952329f5518SBarry Smith sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 195304ca555eSLois Curfman McInnes } 195404ca555eSLois Curfman McInnes v = bmat->a; 195504ca555eSLois Curfman McInnes for (i=0; i<bmat->nz; i++) { 1956329f5518SBarry Smith sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 195704ca555eSLois Curfman McInnes } 1958b2566f29SBarry Smith ierr = MPIU_Allreduce(&sum,norm,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 19598f1a2a5eSBarry Smith *norm = PetscSqrtReal(*norm); 196051f70360SJed Brown ierr = PetscLogFlops(2*amat->nz+2*bmat->nz);CHKERRQ(ierr); 19613a40ed3dSBarry Smith } else if (type == NORM_1) { /* max column norm */ 1962329f5518SBarry Smith PetscReal *tmp,*tmp2; 1963b1d57f15SBarry Smith PetscInt *jj,*garray = aij->garray; 1964854ce69bSBarry Smith ierr = PetscCalloc1(mat->cmap->N+1,&tmp);CHKERRQ(ierr); 1965854ce69bSBarry Smith ierr = PetscMalloc1(mat->cmap->N+1,&tmp2);CHKERRQ(ierr); 196604ca555eSLois Curfman McInnes *norm = 0.0; 196704ca555eSLois Curfman McInnes v = amat->a; jj = amat->j; 196804ca555eSLois Curfman McInnes for (j=0; j<amat->nz; j++) { 1969bfec09a0SHong Zhang tmp[cstart + *jj++] += PetscAbsScalar(*v); v++; 197004ca555eSLois Curfman McInnes } 197104ca555eSLois Curfman McInnes v = bmat->a; jj = bmat->j; 197204ca555eSLois Curfman McInnes for (j=0; j<bmat->nz; j++) { 1973bfec09a0SHong Zhang tmp[garray[*jj++]] += PetscAbsScalar(*v); v++; 197404ca555eSLois Curfman McInnes } 1975b2566f29SBarry Smith ierr = MPIU_Allreduce(tmp,tmp2,mat->cmap->N,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1976d0f46423SBarry Smith for (j=0; j<mat->cmap->N; j++) { 197704ca555eSLois Curfman McInnes if (tmp2[j] > *norm) *norm = tmp2[j]; 197804ca555eSLois Curfman McInnes } 1979606d414cSSatish Balay ierr = PetscFree(tmp);CHKERRQ(ierr); 1980606d414cSSatish Balay ierr = PetscFree(tmp2);CHKERRQ(ierr); 198151f70360SJed Brown ierr = PetscLogFlops(PetscMax(amat->nz+bmat->nz-1,0));CHKERRQ(ierr); 19823a40ed3dSBarry Smith } else if (type == NORM_INFINITY) { /* max row norm */ 1983329f5518SBarry Smith PetscReal ntemp = 0.0; 1984d0f46423SBarry Smith for (j=0; j<aij->A->rmap->n; j++) { 1985bfec09a0SHong Zhang v = amat->a + amat->i[j]; 198604ca555eSLois Curfman McInnes sum = 0.0; 198704ca555eSLois Curfman McInnes for (i=0; i<amat->i[j+1]-amat->i[j]; i++) { 1988cddf8d76SBarry Smith sum += PetscAbsScalar(*v); v++; 198904ca555eSLois Curfman McInnes } 1990bfec09a0SHong Zhang v = bmat->a + bmat->i[j]; 199104ca555eSLois Curfman McInnes for (i=0; i<bmat->i[j+1]-bmat->i[j]; i++) { 1992cddf8d76SBarry Smith sum += PetscAbsScalar(*v); v++; 199304ca555eSLois Curfman McInnes } 1994515d9167SLois Curfman McInnes if (sum > ntemp) ntemp = sum; 199504ca555eSLois Curfman McInnes } 1996b2566f29SBarry Smith ierr = MPIU_Allreduce(&ntemp,norm,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 199751f70360SJed Brown ierr = PetscLogFlops(PetscMax(amat->nz+bmat->nz-1,0));CHKERRQ(ierr); 1998ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support for two norm"); 199937fa93a5SLois Curfman McInnes } 20003a40ed3dSBarry Smith PetscFunctionReturn(0); 2001855ac2c5SLois Curfman McInnes } 2002855ac2c5SLois Curfman McInnes 2003fc4dec0aSBarry Smith PetscErrorCode MatTranspose_MPIAIJ(Mat A,MatReuse reuse,Mat *matout) 2004b7c46309SBarry Smith { 2005a8661f62Sandi selinger Mat_MPIAIJ *a =(Mat_MPIAIJ*)A->data,*b; 2006a8661f62Sandi selinger Mat_SeqAIJ *Aloc =(Mat_SeqAIJ*)a->A->data,*Bloc=(Mat_SeqAIJ*)a->B->data,*sub_B_diag; 2007*071fcb05SBarry Smith PetscInt M = A->rmap->N,N=A->cmap->N,ma,na,mb,nb,row,*cols,*cols_tmp,*B_diag_ilen,i,ncol,A_diag_ncol; 2008*071fcb05SBarry Smith const PetscInt *ai,*aj,*bi,*bj,*B_diag_i; 2009dfbe8321SBarry Smith PetscErrorCode ierr; 2010a8661f62Sandi selinger Mat B,A_diag,*B_diag; 2011*071fcb05SBarry Smith const MatScalar *array; 2012b7c46309SBarry Smith 20133a40ed3dSBarry Smith PetscFunctionBegin; 201480bcc5a1SJed Brown ma = A->rmap->n; na = A->cmap->n; mb = a->B->rmap->n; nb = a->B->cmap->n; 2015da668accSHong Zhang ai = Aloc->i; aj = Aloc->j; 2016da668accSHong Zhang bi = Bloc->i; bj = Bloc->j; 2017fc73b1b3SBarry Smith if (reuse == MAT_INITIAL_MATRIX || *matout == A) { 201880bcc5a1SJed Brown PetscInt *d_nnz,*g_nnz,*o_nnz; 201980bcc5a1SJed Brown PetscSFNode *oloc; 2020713c93b4SJed Brown PETSC_UNUSED PetscSF sf; 202180bcc5a1SJed Brown 2022dcca6d9dSJed Brown ierr = PetscMalloc4(na,&d_nnz,na,&o_nnz,nb,&g_nnz,nb,&oloc);CHKERRQ(ierr); 202380bcc5a1SJed Brown /* compute d_nnz for preallocation */ 2024580bdb30SBarry Smith ierr = PetscArrayzero(d_nnz,na);CHKERRQ(ierr); 2025da668accSHong Zhang for (i=0; i<ai[ma]; i++) { 2026da668accSHong Zhang d_nnz[aj[i]]++; 2027d4bb536fSBarry Smith } 202880bcc5a1SJed Brown /* compute local off-diagonal contributions */ 2029580bdb30SBarry Smith ierr = PetscArrayzero(g_nnz,nb);CHKERRQ(ierr); 203080bcc5a1SJed Brown for (i=0; i<bi[ma]; i++) g_nnz[bj[i]]++; 203180bcc5a1SJed Brown /* map those to global */ 2032ce94432eSBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)A),&sf);CHKERRQ(ierr); 20330298fd71SBarry Smith ierr = PetscSFSetGraphLayout(sf,A->cmap,nb,NULL,PETSC_USE_POINTER,a->garray);CHKERRQ(ierr); 2034e9e74f11SJed Brown ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); 2035580bdb30SBarry Smith ierr = PetscArrayzero(o_nnz,na);CHKERRQ(ierr); 203680bcc5a1SJed Brown ierr = PetscSFReduceBegin(sf,MPIU_INT,g_nnz,o_nnz,MPIU_SUM);CHKERRQ(ierr); 203780bcc5a1SJed Brown ierr = PetscSFReduceEnd(sf,MPIU_INT,g_nnz,o_nnz,MPIU_SUM);CHKERRQ(ierr); 203880bcc5a1SJed Brown ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 2039d4bb536fSBarry Smith 2040ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 2041d0f46423SBarry Smith ierr = MatSetSizes(B,A->cmap->n,A->rmap->n,N,M);CHKERRQ(ierr); 204233d57670SJed Brown ierr = MatSetBlockSizes(B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr); 20437adad957SLisandro Dalcin ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); 204480bcc5a1SJed Brown ierr = MatMPIAIJSetPreallocation(B,0,d_nnz,0,o_nnz);CHKERRQ(ierr); 204580bcc5a1SJed Brown ierr = PetscFree4(d_nnz,o_nnz,g_nnz,oloc);CHKERRQ(ierr); 2046fc4dec0aSBarry Smith } else { 2047fc4dec0aSBarry Smith B = *matout; 20486ffab4bbSHong Zhang ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 2049fc4dec0aSBarry Smith } 2050b7c46309SBarry Smith 2051f79cb1a0Sandi selinger b = (Mat_MPIAIJ*)B->data; 2052a8661f62Sandi selinger A_diag = a->A; 2053a8661f62Sandi selinger B_diag = &b->A; 2054a8661f62Sandi selinger sub_B_diag = (Mat_SeqAIJ*)(*B_diag)->data; 2055a8661f62Sandi selinger A_diag_ncol = A_diag->cmap->N; 2056a8661f62Sandi selinger B_diag_ilen = sub_B_diag->ilen; 2057a8661f62Sandi selinger B_diag_i = sub_B_diag->i; 2058f79cb1a0Sandi selinger 2059f79cb1a0Sandi selinger /* Set ilen for diagonal of B */ 2060a8661f62Sandi selinger for (i=0; i<A_diag_ncol; i++) { 2061a8661f62Sandi selinger B_diag_ilen[i] = B_diag_i[i+1] - B_diag_i[i]; 2062b7c46309SBarry Smith } 2063f79cb1a0Sandi selinger 2064a8661f62Sandi selinger /* Transpose the diagonal part of the matrix. In contrast to the offdiagonal part, this can be done 2065a8661f62Sandi selinger very quickly (=without using MatSetValues), because all writes are local. */ 2066a8661f62Sandi selinger ierr = MatTranspose(A_diag,MAT_REUSE_MATRIX,B_diag);CHKERRQ(ierr); 2067f79cb1a0Sandi selinger 2068b7c46309SBarry Smith /* copy over the B part */ 2069*071fcb05SBarry Smith ierr = PetscMalloc1(bi[mb],&cols);CHKERRQ(ierr); 2070da668accSHong Zhang array = Bloc->a; 2071d0f46423SBarry Smith row = A->rmap->rstart; 20722205254eSKarl Rupp for (i=0; i<bi[mb]; i++) cols[i] = a->garray[bj[i]]; 207361a2fbbaSHong Zhang cols_tmp = cols; 2074da668accSHong Zhang for (i=0; i<mb; i++) { 2075da668accSHong Zhang ncol = bi[i+1]-bi[i]; 207661a2fbbaSHong Zhang ierr = MatSetValues(B,ncol,cols_tmp,1,&row,array,INSERT_VALUES);CHKERRQ(ierr); 20772205254eSKarl Rupp row++; 20782205254eSKarl Rupp array += ncol; cols_tmp += ncol; 2079b7c46309SBarry Smith } 2080fc73b1b3SBarry Smith ierr = PetscFree(cols);CHKERRQ(ierr); 2081fc73b1b3SBarry Smith 20826d4a8577SBarry Smith ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 20836d4a8577SBarry Smith ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2084cf37664fSBarry Smith if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) { 20850de55854SLois Curfman McInnes *matout = B; 20860de55854SLois Curfman McInnes } else { 208728be2f97SBarry Smith ierr = MatHeaderMerge(A,&B);CHKERRQ(ierr); 20880de55854SLois Curfman McInnes } 20893a40ed3dSBarry Smith PetscFunctionReturn(0); 2090b7c46309SBarry Smith } 2091b7c46309SBarry Smith 2092dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_MPIAIJ(Mat mat,Vec ll,Vec rr) 2093a008b906SSatish Balay { 20944b967eb1SSatish Balay Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 20954b967eb1SSatish Balay Mat a = aij->A,b = aij->B; 2096dfbe8321SBarry Smith PetscErrorCode ierr; 2097b1d57f15SBarry Smith PetscInt s1,s2,s3; 2098a008b906SSatish Balay 20993a40ed3dSBarry Smith PetscFunctionBegin; 21004b967eb1SSatish Balay ierr = MatGetLocalSize(mat,&s2,&s3);CHKERRQ(ierr); 21014b967eb1SSatish Balay if (rr) { 2102e1311b90SBarry Smith ierr = VecGetLocalSize(rr,&s1);CHKERRQ(ierr); 2103e32f2f54SBarry Smith if (s1!=s3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"right vector non-conforming local size"); 21044b967eb1SSatish Balay /* Overlap communication with computation. */ 2105ca9f406cSSatish Balay ierr = VecScatterBegin(aij->Mvctx,rr,aij->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2106a008b906SSatish Balay } 21074b967eb1SSatish Balay if (ll) { 2108e1311b90SBarry Smith ierr = VecGetLocalSize(ll,&s1);CHKERRQ(ierr); 2109e32f2f54SBarry Smith if (s1!=s2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"left vector non-conforming local size"); 2110f830108cSBarry Smith ierr = (*b->ops->diagonalscale)(b,ll,0);CHKERRQ(ierr); 21114b967eb1SSatish Balay } 21124b967eb1SSatish Balay /* scale the diagonal block */ 2113f830108cSBarry Smith ierr = (*a->ops->diagonalscale)(a,ll,rr);CHKERRQ(ierr); 21144b967eb1SSatish Balay 21154b967eb1SSatish Balay if (rr) { 21164b967eb1SSatish Balay /* Do a scatter end and then right scale the off-diagonal block */ 2117ca9f406cSSatish Balay ierr = VecScatterEnd(aij->Mvctx,rr,aij->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2118f830108cSBarry Smith ierr = (*b->ops->diagonalscale)(b,0,aij->lvec);CHKERRQ(ierr); 21194b967eb1SSatish Balay } 21203a40ed3dSBarry Smith PetscFunctionReturn(0); 2121a008b906SSatish Balay } 2122a008b906SSatish Balay 2123dfbe8321SBarry Smith PetscErrorCode MatSetUnfactored_MPIAIJ(Mat A) 2124bb5a7306SBarry Smith { 2125bb5a7306SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2126dfbe8321SBarry Smith PetscErrorCode ierr; 21273a40ed3dSBarry Smith 21283a40ed3dSBarry Smith PetscFunctionBegin; 2129bb5a7306SBarry Smith ierr = MatSetUnfactored(a->A);CHKERRQ(ierr); 21303a40ed3dSBarry Smith PetscFunctionReturn(0); 2131bb5a7306SBarry Smith } 2132bb5a7306SBarry Smith 2133ace3abfcSBarry Smith PetscErrorCode MatEqual_MPIAIJ(Mat A,Mat B,PetscBool *flag) 2134d4bb536fSBarry Smith { 2135d4bb536fSBarry Smith Mat_MPIAIJ *matB = (Mat_MPIAIJ*)B->data,*matA = (Mat_MPIAIJ*)A->data; 2136d4bb536fSBarry Smith Mat a,b,c,d; 2137ace3abfcSBarry Smith PetscBool flg; 2138dfbe8321SBarry Smith PetscErrorCode ierr; 2139d4bb536fSBarry Smith 21403a40ed3dSBarry Smith PetscFunctionBegin; 2141d4bb536fSBarry Smith a = matA->A; b = matA->B; 2142d4bb536fSBarry Smith c = matB->A; d = matB->B; 2143d4bb536fSBarry Smith 2144d4bb536fSBarry Smith ierr = MatEqual(a,c,&flg);CHKERRQ(ierr); 2145abc0a331SBarry Smith if (flg) { 2146d4bb536fSBarry Smith ierr = MatEqual(b,d,&flg);CHKERRQ(ierr); 2147d4bb536fSBarry Smith } 2148b2566f29SBarry Smith ierr = MPIU_Allreduce(&flg,flag,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 21493a40ed3dSBarry Smith PetscFunctionReturn(0); 2150d4bb536fSBarry Smith } 2151d4bb536fSBarry Smith 2152dfbe8321SBarry Smith PetscErrorCode MatCopy_MPIAIJ(Mat A,Mat B,MatStructure str) 2153cb5b572fSBarry Smith { 2154dfbe8321SBarry Smith PetscErrorCode ierr; 2155cb5b572fSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2156cb5b572fSBarry Smith Mat_MPIAIJ *b = (Mat_MPIAIJ*)B->data; 2157cb5b572fSBarry Smith 2158cb5b572fSBarry Smith PetscFunctionBegin; 215933f4a19fSKris Buschelman /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */ 216033f4a19fSKris Buschelman if ((str != SAME_NONZERO_PATTERN) || (A->ops->copy != B->ops->copy)) { 2161cb5b572fSBarry Smith /* because of the column compression in the off-processor part of the matrix a->B, 2162cb5b572fSBarry Smith the number of columns in a->B and b->B may be different, hence we cannot call 2163cb5b572fSBarry Smith the MatCopy() directly on the two parts. If need be, we can provide a more 2164cb5b572fSBarry Smith efficient copy than the MatCopy_Basic() by first uncompressing the a->B matrices 2165cb5b572fSBarry Smith then copying the submatrices */ 2166cb5b572fSBarry Smith ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr); 2167cb5b572fSBarry Smith } else { 2168cb5b572fSBarry Smith ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr); 2169cb5b572fSBarry Smith ierr = MatCopy(a->B,b->B,str);CHKERRQ(ierr); 2170cb5b572fSBarry Smith } 2171cdc753b6SBarry Smith ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr); 2172cb5b572fSBarry Smith PetscFunctionReturn(0); 2173cb5b572fSBarry Smith } 2174cb5b572fSBarry Smith 21754994cf47SJed Brown PetscErrorCode MatSetUp_MPIAIJ(Mat A) 2176273d9f13SBarry Smith { 2177dfbe8321SBarry Smith PetscErrorCode ierr; 2178273d9f13SBarry Smith 2179273d9f13SBarry Smith PetscFunctionBegin; 2180273d9f13SBarry Smith ierr = MatMPIAIJSetPreallocation(A,PETSC_DEFAULT,0,PETSC_DEFAULT,0);CHKERRQ(ierr); 2181273d9f13SBarry Smith PetscFunctionReturn(0); 2182273d9f13SBarry Smith } 2183273d9f13SBarry Smith 2184001ddc4fSHong Zhang /* 2185001ddc4fSHong Zhang Computes the number of nonzeros per row needed for preallocation when X and Y 2186001ddc4fSHong Zhang have different nonzero structure. 2187001ddc4fSHong Zhang */ 2188001ddc4fSHong Zhang PetscErrorCode MatAXPYGetPreallocation_MPIX_private(PetscInt m,const PetscInt *xi,const PetscInt *xj,const PetscInt *xltog,const PetscInt *yi,const PetscInt *yj,const PetscInt *yltog,PetscInt *nnz) 218995b7e79eSJed Brown { 2190001ddc4fSHong Zhang PetscInt i,j,k,nzx,nzy; 219195b7e79eSJed Brown 219295b7e79eSJed Brown PetscFunctionBegin; 219395b7e79eSJed Brown /* Set the number of nonzeros in the new matrix */ 219495b7e79eSJed Brown for (i=0; i<m; i++) { 2195001ddc4fSHong Zhang const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i]; 2196001ddc4fSHong Zhang nzx = xi[i+1] - xi[i]; 2197001ddc4fSHong Zhang nzy = yi[i+1] - yi[i]; 219895b7e79eSJed Brown nnz[i] = 0; 219995b7e79eSJed Brown for (j=0,k=0; j<nzx; j++) { /* Point in X */ 2200001ddc4fSHong Zhang for (; k<nzy && yltog[yjj[k]]<xltog[xjj[j]]; k++) nnz[i]++; /* Catch up to X */ 2201001ddc4fSHong Zhang if (k<nzy && yltog[yjj[k]]==xltog[xjj[j]]) k++; /* Skip duplicate */ 220295b7e79eSJed Brown nnz[i]++; 220395b7e79eSJed Brown } 220495b7e79eSJed Brown for (; k<nzy; k++) nnz[i]++; 220595b7e79eSJed Brown } 220695b7e79eSJed Brown PetscFunctionReturn(0); 220795b7e79eSJed Brown } 220895b7e79eSJed Brown 2209001ddc4fSHong Zhang /* This is the same as MatAXPYGetPreallocation_SeqAIJ, except that the local-to-global map is provided */ 2210001ddc4fSHong Zhang static PetscErrorCode MatAXPYGetPreallocation_MPIAIJ(Mat Y,const PetscInt *yltog,Mat X,const PetscInt *xltog,PetscInt *nnz) 2211001ddc4fSHong Zhang { 2212001ddc4fSHong Zhang PetscErrorCode ierr; 2213001ddc4fSHong Zhang PetscInt m = Y->rmap->N; 2214001ddc4fSHong Zhang Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data; 2215001ddc4fSHong Zhang Mat_SeqAIJ *y = (Mat_SeqAIJ*)Y->data; 2216001ddc4fSHong Zhang 2217001ddc4fSHong Zhang PetscFunctionBegin; 2218001ddc4fSHong Zhang ierr = MatAXPYGetPreallocation_MPIX_private(m,x->i,x->j,xltog,y->i,y->j,yltog,nnz);CHKERRQ(ierr); 2219001ddc4fSHong Zhang PetscFunctionReturn(0); 2220001ddc4fSHong Zhang } 2221001ddc4fSHong Zhang 2222f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_MPIAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str) 2223ac90fabeSBarry Smith { 2224dfbe8321SBarry Smith PetscErrorCode ierr; 2225ac90fabeSBarry Smith Mat_MPIAIJ *xx = (Mat_MPIAIJ*)X->data,*yy = (Mat_MPIAIJ*)Y->data; 22264ce68768SBarry Smith PetscBLASInt bnz,one=1; 2227ac90fabeSBarry Smith Mat_SeqAIJ *x,*y; 2228ac90fabeSBarry Smith 2229ac90fabeSBarry Smith PetscFunctionBegin; 2230ac90fabeSBarry Smith if (str == SAME_NONZERO_PATTERN) { 2231f4df32b1SMatthew Knepley PetscScalar alpha = a; 2232ac90fabeSBarry Smith x = (Mat_SeqAIJ*)xx->A->data; 2233c5df96a5SBarry Smith ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr); 2234ac90fabeSBarry Smith y = (Mat_SeqAIJ*)yy->A->data; 22358b83055fSJed Brown PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one)); 2236ac90fabeSBarry Smith x = (Mat_SeqAIJ*)xx->B->data; 2237ac90fabeSBarry Smith y = (Mat_SeqAIJ*)yy->B->data; 2238c5df96a5SBarry Smith ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr); 22398b83055fSJed Brown PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one)); 2240a3fa217bSJose E. Roman ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr); 2241ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 2242ab784542SHong Zhang ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr); 2243ac90fabeSBarry Smith } else { 22449f5f6813SShri Abhyankar Mat B; 22459f5f6813SShri Abhyankar PetscInt *nnz_d,*nnz_o; 2246785e854fSJed Brown ierr = PetscMalloc1(yy->A->rmap->N,&nnz_d);CHKERRQ(ierr); 2247785e854fSJed Brown ierr = PetscMalloc1(yy->B->rmap->N,&nnz_o);CHKERRQ(ierr); 2248ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr); 2249bc5a2726SShri Abhyankar ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr); 22509f5f6813SShri Abhyankar ierr = MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);CHKERRQ(ierr); 225133d57670SJed Brown ierr = MatSetBlockSizesFromMats(B,Y,Y);CHKERRQ(ierr); 22529f5f6813SShri Abhyankar ierr = MatSetType(B,MATMPIAIJ);CHKERRQ(ierr); 22539f5f6813SShri Abhyankar ierr = MatAXPYGetPreallocation_SeqAIJ(yy->A,xx->A,nnz_d);CHKERRQ(ierr); 225495b7e79eSJed Brown ierr = MatAXPYGetPreallocation_MPIAIJ(yy->B,yy->garray,xx->B,xx->garray,nnz_o);CHKERRQ(ierr); 2255ecd8bba6SJed Brown ierr = MatMPIAIJSetPreallocation(B,0,nnz_d,0,nnz_o);CHKERRQ(ierr); 22569f5f6813SShri Abhyankar ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr); 225728be2f97SBarry Smith ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr); 22589f5f6813SShri Abhyankar ierr = PetscFree(nnz_d);CHKERRQ(ierr); 22599f5f6813SShri Abhyankar ierr = PetscFree(nnz_o);CHKERRQ(ierr); 2260ac90fabeSBarry Smith } 2261ac90fabeSBarry Smith PetscFunctionReturn(0); 2262ac90fabeSBarry Smith } 2263ac90fabeSBarry Smith 22647087cfbeSBarry Smith extern PetscErrorCode MatConjugate_SeqAIJ(Mat); 2265354c94deSBarry Smith 22667087cfbeSBarry Smith PetscErrorCode MatConjugate_MPIAIJ(Mat mat) 2267354c94deSBarry Smith { 2268354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX) 2269354c94deSBarry Smith PetscErrorCode ierr; 2270354c94deSBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 2271354c94deSBarry Smith 2272354c94deSBarry Smith PetscFunctionBegin; 2273354c94deSBarry Smith ierr = MatConjugate_SeqAIJ(aij->A);CHKERRQ(ierr); 2274354c94deSBarry Smith ierr = MatConjugate_SeqAIJ(aij->B);CHKERRQ(ierr); 2275354c94deSBarry Smith #else 2276354c94deSBarry Smith PetscFunctionBegin; 2277354c94deSBarry Smith #endif 2278354c94deSBarry Smith PetscFunctionReturn(0); 2279354c94deSBarry Smith } 2280354c94deSBarry Smith 228199cafbc1SBarry Smith PetscErrorCode MatRealPart_MPIAIJ(Mat A) 228299cafbc1SBarry Smith { 228399cafbc1SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 228499cafbc1SBarry Smith PetscErrorCode ierr; 228599cafbc1SBarry Smith 228699cafbc1SBarry Smith PetscFunctionBegin; 228799cafbc1SBarry Smith ierr = MatRealPart(a->A);CHKERRQ(ierr); 228899cafbc1SBarry Smith ierr = MatRealPart(a->B);CHKERRQ(ierr); 228999cafbc1SBarry Smith PetscFunctionReturn(0); 229099cafbc1SBarry Smith } 229199cafbc1SBarry Smith 229299cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_MPIAIJ(Mat A) 229399cafbc1SBarry Smith { 229499cafbc1SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 229599cafbc1SBarry Smith PetscErrorCode ierr; 229699cafbc1SBarry Smith 229799cafbc1SBarry Smith PetscFunctionBegin; 229899cafbc1SBarry Smith ierr = MatImaginaryPart(a->A);CHKERRQ(ierr); 229999cafbc1SBarry Smith ierr = MatImaginaryPart(a->B);CHKERRQ(ierr); 230099cafbc1SBarry Smith PetscFunctionReturn(0); 230199cafbc1SBarry Smith } 230299cafbc1SBarry Smith 2303c91732d9SHong Zhang PetscErrorCode MatGetRowMaxAbs_MPIAIJ(Mat A, Vec v, PetscInt idx[]) 2304c91732d9SHong Zhang { 2305c91732d9SHong Zhang Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2306c91732d9SHong Zhang PetscErrorCode ierr; 2307c91732d9SHong Zhang PetscInt i,*idxb = 0; 2308c91732d9SHong Zhang PetscScalar *va,*vb; 2309c91732d9SHong Zhang Vec vtmp; 2310c91732d9SHong Zhang 2311c91732d9SHong Zhang PetscFunctionBegin; 2312c91732d9SHong Zhang ierr = MatGetRowMaxAbs(a->A,v,idx);CHKERRQ(ierr); 2313c91732d9SHong Zhang ierr = VecGetArray(v,&va);CHKERRQ(ierr); 2314c91732d9SHong Zhang if (idx) { 2315192daf7cSBarry Smith for (i=0; i<A->rmap->n; i++) { 2316d0f46423SBarry Smith if (PetscAbsScalar(va[i])) idx[i] += A->cmap->rstart; 2317c91732d9SHong Zhang } 2318c91732d9SHong Zhang } 2319c91732d9SHong Zhang 2320d0f46423SBarry Smith ierr = VecCreateSeq(PETSC_COMM_SELF,A->rmap->n,&vtmp);CHKERRQ(ierr); 2321c91732d9SHong Zhang if (idx) { 2322785e854fSJed Brown ierr = PetscMalloc1(A->rmap->n,&idxb);CHKERRQ(ierr); 2323c91732d9SHong Zhang } 2324c91732d9SHong Zhang ierr = MatGetRowMaxAbs(a->B,vtmp,idxb);CHKERRQ(ierr); 2325c91732d9SHong Zhang ierr = VecGetArray(vtmp,&vb);CHKERRQ(ierr); 2326c91732d9SHong Zhang 2327d0f46423SBarry Smith for (i=0; i<A->rmap->n; i++) { 2328c91732d9SHong Zhang if (PetscAbsScalar(va[i]) < PetscAbsScalar(vb[i])) { 2329c91732d9SHong Zhang va[i] = vb[i]; 2330c91732d9SHong Zhang if (idx) idx[i] = a->garray[idxb[i]]; 2331c91732d9SHong Zhang } 2332c91732d9SHong Zhang } 2333c91732d9SHong Zhang 2334c91732d9SHong Zhang ierr = VecRestoreArray(v,&va);CHKERRQ(ierr); 2335c91732d9SHong Zhang ierr = VecRestoreArray(vtmp,&vb);CHKERRQ(ierr); 2336c91732d9SHong Zhang ierr = PetscFree(idxb);CHKERRQ(ierr); 23376bf464f9SBarry Smith ierr = VecDestroy(&vtmp);CHKERRQ(ierr); 2338c91732d9SHong Zhang PetscFunctionReturn(0); 2339c91732d9SHong Zhang } 2340c91732d9SHong Zhang 2341c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_MPIAIJ(Mat A, Vec v, PetscInt idx[]) 2342c87e5d42SMatthew Knepley { 2343c87e5d42SMatthew Knepley Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2344c87e5d42SMatthew Knepley PetscErrorCode ierr; 2345c87e5d42SMatthew Knepley PetscInt i,*idxb = 0; 2346c87e5d42SMatthew Knepley PetscScalar *va,*vb; 2347c87e5d42SMatthew Knepley Vec vtmp; 2348c87e5d42SMatthew Knepley 2349c87e5d42SMatthew Knepley PetscFunctionBegin; 2350c87e5d42SMatthew Knepley ierr = MatGetRowMinAbs(a->A,v,idx);CHKERRQ(ierr); 2351c87e5d42SMatthew Knepley ierr = VecGetArray(v,&va);CHKERRQ(ierr); 2352c87e5d42SMatthew Knepley if (idx) { 2353c87e5d42SMatthew Knepley for (i=0; i<A->cmap->n; i++) { 2354c87e5d42SMatthew Knepley if (PetscAbsScalar(va[i])) idx[i] += A->cmap->rstart; 2355c87e5d42SMatthew Knepley } 2356c87e5d42SMatthew Knepley } 2357c87e5d42SMatthew Knepley 2358c87e5d42SMatthew Knepley ierr = VecCreateSeq(PETSC_COMM_SELF,A->rmap->n,&vtmp);CHKERRQ(ierr); 2359c87e5d42SMatthew Knepley if (idx) { 2360785e854fSJed Brown ierr = PetscMalloc1(A->rmap->n,&idxb);CHKERRQ(ierr); 2361c87e5d42SMatthew Knepley } 2362c87e5d42SMatthew Knepley ierr = MatGetRowMinAbs(a->B,vtmp,idxb);CHKERRQ(ierr); 2363c87e5d42SMatthew Knepley ierr = VecGetArray(vtmp,&vb);CHKERRQ(ierr); 2364c87e5d42SMatthew Knepley 2365c87e5d42SMatthew Knepley for (i=0; i<A->rmap->n; i++) { 2366c87e5d42SMatthew Knepley if (PetscAbsScalar(va[i]) > PetscAbsScalar(vb[i])) { 2367c87e5d42SMatthew Knepley va[i] = vb[i]; 2368c87e5d42SMatthew Knepley if (idx) idx[i] = a->garray[idxb[i]]; 2369c87e5d42SMatthew Knepley } 2370c87e5d42SMatthew Knepley } 2371c87e5d42SMatthew Knepley 2372c87e5d42SMatthew Knepley ierr = VecRestoreArray(v,&va);CHKERRQ(ierr); 2373c87e5d42SMatthew Knepley ierr = VecRestoreArray(vtmp,&vb);CHKERRQ(ierr); 2374c87e5d42SMatthew Knepley ierr = PetscFree(idxb);CHKERRQ(ierr); 23756bf464f9SBarry Smith ierr = VecDestroy(&vtmp);CHKERRQ(ierr); 2376c87e5d42SMatthew Knepley PetscFunctionReturn(0); 2377c87e5d42SMatthew Knepley } 2378c87e5d42SMatthew Knepley 237903bc72f1SMatthew Knepley PetscErrorCode MatGetRowMin_MPIAIJ(Mat A, Vec v, PetscInt idx[]) 238003bc72f1SMatthew Knepley { 238103bc72f1SMatthew Knepley Mat_MPIAIJ *mat = (Mat_MPIAIJ*) A->data; 2382d0f46423SBarry Smith PetscInt n = A->rmap->n; 2383d0f46423SBarry Smith PetscInt cstart = A->cmap->rstart; 238403bc72f1SMatthew Knepley PetscInt *cmap = mat->garray; 238503bc72f1SMatthew Knepley PetscInt *diagIdx, *offdiagIdx; 238603bc72f1SMatthew Knepley Vec diagV, offdiagV; 238703bc72f1SMatthew Knepley PetscScalar *a, *diagA, *offdiagA; 238803bc72f1SMatthew Knepley PetscInt r; 238903bc72f1SMatthew Knepley PetscErrorCode ierr; 239003bc72f1SMatthew Knepley 239103bc72f1SMatthew Knepley PetscFunctionBegin; 2392dcca6d9dSJed Brown ierr = PetscMalloc2(n,&diagIdx,n,&offdiagIdx);CHKERRQ(ierr); 2393ce94432eSBarry Smith ierr = VecCreateSeq(PetscObjectComm((PetscObject)A), n, &diagV);CHKERRQ(ierr); 2394ce94432eSBarry Smith ierr = VecCreateSeq(PetscObjectComm((PetscObject)A), n, &offdiagV);CHKERRQ(ierr); 239503bc72f1SMatthew Knepley ierr = MatGetRowMin(mat->A, diagV, diagIdx);CHKERRQ(ierr); 239603bc72f1SMatthew Knepley ierr = MatGetRowMin(mat->B, offdiagV, offdiagIdx);CHKERRQ(ierr); 239703bc72f1SMatthew Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 239803bc72f1SMatthew Knepley ierr = VecGetArray(diagV, &diagA);CHKERRQ(ierr); 239903bc72f1SMatthew Knepley ierr = VecGetArray(offdiagV, &offdiagA);CHKERRQ(ierr); 240003bc72f1SMatthew Knepley for (r = 0; r < n; ++r) { 2401028cd4eaSSatish Balay if (PetscAbsScalar(diagA[r]) <= PetscAbsScalar(offdiagA[r])) { 240203bc72f1SMatthew Knepley a[r] = diagA[r]; 240303bc72f1SMatthew Knepley idx[r] = cstart + diagIdx[r]; 240403bc72f1SMatthew Knepley } else { 240503bc72f1SMatthew Knepley a[r] = offdiagA[r]; 240603bc72f1SMatthew Knepley idx[r] = cmap[offdiagIdx[r]]; 240703bc72f1SMatthew Knepley } 240803bc72f1SMatthew Knepley } 240903bc72f1SMatthew Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 241003bc72f1SMatthew Knepley ierr = VecRestoreArray(diagV, &diagA);CHKERRQ(ierr); 241103bc72f1SMatthew Knepley ierr = VecRestoreArray(offdiagV, &offdiagA);CHKERRQ(ierr); 24126bf464f9SBarry Smith ierr = VecDestroy(&diagV);CHKERRQ(ierr); 24136bf464f9SBarry Smith ierr = VecDestroy(&offdiagV);CHKERRQ(ierr); 241403bc72f1SMatthew Knepley ierr = PetscFree2(diagIdx, offdiagIdx);CHKERRQ(ierr); 241503bc72f1SMatthew Knepley PetscFunctionReturn(0); 241603bc72f1SMatthew Knepley } 241703bc72f1SMatthew Knepley 2418c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMax_MPIAIJ(Mat A, Vec v, PetscInt idx[]) 2419c87e5d42SMatthew Knepley { 2420c87e5d42SMatthew Knepley Mat_MPIAIJ *mat = (Mat_MPIAIJ*) A->data; 2421c87e5d42SMatthew Knepley PetscInt n = A->rmap->n; 2422c87e5d42SMatthew Knepley PetscInt cstart = A->cmap->rstart; 2423c87e5d42SMatthew Knepley PetscInt *cmap = mat->garray; 2424c87e5d42SMatthew Knepley PetscInt *diagIdx, *offdiagIdx; 2425c87e5d42SMatthew Knepley Vec diagV, offdiagV; 2426c87e5d42SMatthew Knepley PetscScalar *a, *diagA, *offdiagA; 2427c87e5d42SMatthew Knepley PetscInt r; 2428c87e5d42SMatthew Knepley PetscErrorCode ierr; 2429c87e5d42SMatthew Knepley 2430c87e5d42SMatthew Knepley PetscFunctionBegin; 2431dcca6d9dSJed Brown ierr = PetscMalloc2(n,&diagIdx,n,&offdiagIdx);CHKERRQ(ierr); 2432d11e49fbSSatish Balay ierr = VecCreateSeq(PETSC_COMM_SELF, n, &diagV);CHKERRQ(ierr); 2433d11e49fbSSatish Balay ierr = VecCreateSeq(PETSC_COMM_SELF, n, &offdiagV);CHKERRQ(ierr); 2434c87e5d42SMatthew Knepley ierr = MatGetRowMax(mat->A, diagV, diagIdx);CHKERRQ(ierr); 2435c87e5d42SMatthew Knepley ierr = MatGetRowMax(mat->B, offdiagV, offdiagIdx);CHKERRQ(ierr); 2436c87e5d42SMatthew Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 2437c87e5d42SMatthew Knepley ierr = VecGetArray(diagV, &diagA);CHKERRQ(ierr); 2438c87e5d42SMatthew Knepley ierr = VecGetArray(offdiagV, &offdiagA);CHKERRQ(ierr); 2439c87e5d42SMatthew Knepley for (r = 0; r < n; ++r) { 2440c87e5d42SMatthew Knepley if (PetscAbsScalar(diagA[r]) >= PetscAbsScalar(offdiagA[r])) { 2441c87e5d42SMatthew Knepley a[r] = diagA[r]; 2442c87e5d42SMatthew Knepley idx[r] = cstart + diagIdx[r]; 2443c87e5d42SMatthew Knepley } else { 2444c87e5d42SMatthew Knepley a[r] = offdiagA[r]; 2445c87e5d42SMatthew Knepley idx[r] = cmap[offdiagIdx[r]]; 2446c87e5d42SMatthew Knepley } 2447c87e5d42SMatthew Knepley } 2448c87e5d42SMatthew Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 2449c87e5d42SMatthew Knepley ierr = VecRestoreArray(diagV, &diagA);CHKERRQ(ierr); 2450c87e5d42SMatthew Knepley ierr = VecRestoreArray(offdiagV, &offdiagA);CHKERRQ(ierr); 24516bf464f9SBarry Smith ierr = VecDestroy(&diagV);CHKERRQ(ierr); 24526bf464f9SBarry Smith ierr = VecDestroy(&offdiagV);CHKERRQ(ierr); 2453c87e5d42SMatthew Knepley ierr = PetscFree2(diagIdx, offdiagIdx);CHKERRQ(ierr); 2454c87e5d42SMatthew Knepley PetscFunctionReturn(0); 2455c87e5d42SMatthew Knepley } 2456c87e5d42SMatthew Knepley 2457d1adec66SJed Brown PetscErrorCode MatGetSeqNonzeroStructure_MPIAIJ(Mat mat,Mat *newmat) 24585494a064SHong Zhang { 24595494a064SHong Zhang PetscErrorCode ierr; 2460f6d58c54SBarry Smith Mat *dummy; 24615494a064SHong Zhang 24625494a064SHong Zhang PetscFunctionBegin; 24637dae84e0SHong Zhang ierr = MatCreateSubMatrix_MPIAIJ_All(mat,MAT_DO_NOT_GET_VALUES,MAT_INITIAL_MATRIX,&dummy);CHKERRQ(ierr); 2464f6d58c54SBarry Smith *newmat = *dummy; 2465f6d58c54SBarry Smith ierr = PetscFree(dummy);CHKERRQ(ierr); 24665494a064SHong Zhang PetscFunctionReturn(0); 24675494a064SHong Zhang } 24685494a064SHong Zhang 2469713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_MPIAIJ(Mat A,const PetscScalar **values) 2470bbead8a2SBarry Smith { 2471bbead8a2SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*) A->data; 2472bbead8a2SBarry Smith PetscErrorCode ierr; 2473bbead8a2SBarry Smith 2474bbead8a2SBarry Smith PetscFunctionBegin; 2475bbead8a2SBarry Smith ierr = MatInvertBlockDiagonal(a->A,values);CHKERRQ(ierr); 24767b6c816cSBarry Smith A->factorerrortype = a->A->factorerrortype; 2477bbead8a2SBarry Smith PetscFunctionReturn(0); 2478bbead8a2SBarry Smith } 2479bbead8a2SBarry Smith 248073a71a0fSBarry Smith static PetscErrorCode MatSetRandom_MPIAIJ(Mat x,PetscRandom rctx) 248173a71a0fSBarry Smith { 248273a71a0fSBarry Smith PetscErrorCode ierr; 248373a71a0fSBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)x->data; 248473a71a0fSBarry Smith 248573a71a0fSBarry Smith PetscFunctionBegin; 2486679944adSJunchao Zhang if (!x->assembled && !x->preallocated) SETERRQ(PetscObjectComm((PetscObject)x), PETSC_ERR_ARG_WRONGSTATE, "MatSetRandom on an unassembled and unpreallocated MATMPIAIJ is not allowed"); 248773a71a0fSBarry Smith ierr = MatSetRandom(aij->A,rctx);CHKERRQ(ierr); 2488679944adSJunchao Zhang if (x->assembled) { 248973a71a0fSBarry Smith ierr = MatSetRandom(aij->B,rctx);CHKERRQ(ierr); 2490679944adSJunchao Zhang } else { 2491679944adSJunchao Zhang ierr = MatSetRandomSkipColumnRange_SeqAIJ_Private(aij->B,x->cmap->rstart,x->cmap->rend,rctx);CHKERRQ(ierr); 2492679944adSJunchao Zhang } 249373a71a0fSBarry Smith ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 249473a71a0fSBarry Smith ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 249573a71a0fSBarry Smith PetscFunctionReturn(0); 249673a71a0fSBarry Smith } 2497bbead8a2SBarry Smith 2498b1b1104fSBarry Smith PetscErrorCode MatMPIAIJSetUseScalableIncreaseOverlap_MPIAIJ(Mat A,PetscBool sc) 2499b1b1104fSBarry Smith { 2500b1b1104fSBarry Smith PetscFunctionBegin; 2501b1b1104fSBarry Smith if (sc) A->ops->increaseoverlap = MatIncreaseOverlap_MPIAIJ_Scalable; 2502b1b1104fSBarry Smith else A->ops->increaseoverlap = MatIncreaseOverlap_MPIAIJ; 2503b1b1104fSBarry Smith PetscFunctionReturn(0); 2504b1b1104fSBarry Smith } 2505b1b1104fSBarry Smith 2506b1b1104fSBarry Smith /*@ 2507b1b1104fSBarry Smith MatMPIAIJSetUseScalableIncreaseOverlap - Determine if the matrix uses a scalable algorithm to compute the overlap 2508b1b1104fSBarry Smith 2509b1b1104fSBarry Smith Collective on Mat 2510b1b1104fSBarry Smith 2511b1b1104fSBarry Smith Input Parameters: 2512b1b1104fSBarry Smith + A - the matrix 2513b1b1104fSBarry Smith - sc - PETSC_TRUE indicates use the scalable algorithm (default is not to use the scalable algorithm) 2514b1b1104fSBarry Smith 251596a0c994SBarry Smith Level: advanced 251696a0c994SBarry Smith 2517b1b1104fSBarry Smith @*/ 2518b1b1104fSBarry Smith PetscErrorCode MatMPIAIJSetUseScalableIncreaseOverlap(Mat A,PetscBool sc) 2519b1b1104fSBarry Smith { 2520b1b1104fSBarry Smith PetscErrorCode ierr; 2521b1b1104fSBarry Smith 2522b1b1104fSBarry Smith PetscFunctionBegin; 2523b1b1104fSBarry Smith ierr = PetscTryMethod(A,"MatMPIAIJSetUseScalableIncreaseOverlap_C",(Mat,PetscBool),(A,sc));CHKERRQ(ierr); 2524b1b1104fSBarry Smith PetscFunctionReturn(0); 2525b1b1104fSBarry Smith } 2526b1b1104fSBarry Smith 25274416b707SBarry Smith PetscErrorCode MatSetFromOptions_MPIAIJ(PetscOptionItems *PetscOptionsObject,Mat A) 2528b1b1104fSBarry Smith { 2529b1b1104fSBarry Smith PetscErrorCode ierr; 2530b1b1104fSBarry Smith PetscBool sc = PETSC_FALSE,flg; 2531b1b1104fSBarry Smith 2532b1b1104fSBarry Smith PetscFunctionBegin; 2533b1b1104fSBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"MPIAIJ options");CHKERRQ(ierr); 2534b1b1104fSBarry Smith if (A->ops->increaseoverlap == MatIncreaseOverlap_MPIAIJ_Scalable) sc = PETSC_TRUE; 2535b1b1104fSBarry Smith ierr = PetscOptionsBool("-mat_increase_overlap_scalable","Use a scalable algorithm to compute the overlap","MatIncreaseOverlap",sc,&sc,&flg);CHKERRQ(ierr); 2536b1b1104fSBarry Smith if (flg) { 2537b1b1104fSBarry Smith ierr = MatMPIAIJSetUseScalableIncreaseOverlap(A,sc);CHKERRQ(ierr); 2538b1b1104fSBarry Smith } 25390af67c1bSStefano Zampini ierr = PetscOptionsTail();CHKERRQ(ierr); 2540b1b1104fSBarry Smith PetscFunctionReturn(0); 2541b1b1104fSBarry Smith } 2542b1b1104fSBarry Smith 25437d68702bSBarry Smith PetscErrorCode MatShift_MPIAIJ(Mat Y,PetscScalar a) 25447d68702bSBarry Smith { 25457d68702bSBarry Smith PetscErrorCode ierr; 25467d68702bSBarry Smith Mat_MPIAIJ *maij = (Mat_MPIAIJ*)Y->data; 2547c5e4d11fSDmitry Karpeev Mat_SeqAIJ *aij = (Mat_SeqAIJ*)maij->A->data; 25487d68702bSBarry Smith 25497d68702bSBarry Smith PetscFunctionBegin; 2550c5e4d11fSDmitry Karpeev if (!Y->preallocated) { 25517d68702bSBarry Smith ierr = MatMPIAIJSetPreallocation(Y,1,NULL,0,NULL);CHKERRQ(ierr); 2552c5e4d11fSDmitry Karpeev } else if (!aij->nz) { 2553b83222d8SBarry Smith PetscInt nonew = aij->nonew; 2554c5e4d11fSDmitry Karpeev ierr = MatSeqAIJSetPreallocation(maij->A,1,NULL);CHKERRQ(ierr); 2555b83222d8SBarry Smith aij->nonew = nonew; 25567d68702bSBarry Smith } 25577d68702bSBarry Smith ierr = MatShift_Basic(Y,a);CHKERRQ(ierr); 25587d68702bSBarry Smith PetscFunctionReturn(0); 25597d68702bSBarry Smith } 25607d68702bSBarry Smith 25613b49f96aSBarry Smith PetscErrorCode MatMissingDiagonal_MPIAIJ(Mat A,PetscBool *missing,PetscInt *d) 25623b49f96aSBarry Smith { 25633b49f96aSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 25643b49f96aSBarry Smith PetscErrorCode ierr; 25653b49f96aSBarry Smith 25663b49f96aSBarry Smith PetscFunctionBegin; 25673b49f96aSBarry Smith if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only works for square matrices"); 25683b49f96aSBarry Smith ierr = MatMissingDiagonal(a->A,missing,d);CHKERRQ(ierr); 25693b49f96aSBarry Smith if (d) { 25703b49f96aSBarry Smith PetscInt rstart; 25713b49f96aSBarry Smith ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr); 25723b49f96aSBarry Smith *d += rstart; 25733b49f96aSBarry Smith 25743b49f96aSBarry Smith } 25753b49f96aSBarry Smith PetscFunctionReturn(0); 25763b49f96aSBarry Smith } 25773b49f96aSBarry Smith 2578a8ee9fb5SBarry Smith PetscErrorCode MatInvertVariableBlockDiagonal_MPIAIJ(Mat A,PetscInt nblocks,const PetscInt *bsizes,PetscScalar *diag) 2579a8ee9fb5SBarry Smith { 2580a8ee9fb5SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2581a8ee9fb5SBarry Smith PetscErrorCode ierr; 2582a8ee9fb5SBarry Smith 2583a8ee9fb5SBarry Smith PetscFunctionBegin; 2584a8ee9fb5SBarry Smith ierr = MatInvertVariableBlockDiagonal(a->A,nblocks,bsizes,diag);CHKERRQ(ierr); 2585a8ee9fb5SBarry Smith PetscFunctionReturn(0); 2586a8ee9fb5SBarry Smith } 25873b49f96aSBarry Smith 25888a729477SBarry Smith /* -------------------------------------------------------------------*/ 2589cda55fadSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_MPIAIJ, 2590cda55fadSBarry Smith MatGetRow_MPIAIJ, 2591cda55fadSBarry Smith MatRestoreRow_MPIAIJ, 2592cda55fadSBarry Smith MatMult_MPIAIJ, 259397304618SKris Buschelman /* 4*/ MatMultAdd_MPIAIJ, 25947c922b88SBarry Smith MatMultTranspose_MPIAIJ, 25957c922b88SBarry Smith MatMultTransposeAdd_MPIAIJ, 2596cda55fadSBarry Smith 0, 2597cda55fadSBarry Smith 0, 2598cda55fadSBarry Smith 0, 259997304618SKris Buschelman /*10*/ 0, 2600cda55fadSBarry Smith 0, 2601cda55fadSBarry Smith 0, 260241f059aeSBarry Smith MatSOR_MPIAIJ, 2603b7c46309SBarry Smith MatTranspose_MPIAIJ, 260497304618SKris Buschelman /*15*/ MatGetInfo_MPIAIJ, 2605cda55fadSBarry Smith MatEqual_MPIAIJ, 2606cda55fadSBarry Smith MatGetDiagonal_MPIAIJ, 2607cda55fadSBarry Smith MatDiagonalScale_MPIAIJ, 2608cda55fadSBarry Smith MatNorm_MPIAIJ, 260997304618SKris Buschelman /*20*/ MatAssemblyBegin_MPIAIJ, 2610cda55fadSBarry Smith MatAssemblyEnd_MPIAIJ, 2611cda55fadSBarry Smith MatSetOption_MPIAIJ, 2612cda55fadSBarry Smith MatZeroEntries_MPIAIJ, 2613d519adbfSMatthew Knepley /*24*/ MatZeroRows_MPIAIJ, 2614cda55fadSBarry Smith 0, 2615719d5645SBarry Smith 0, 2616cda55fadSBarry Smith 0, 2617cda55fadSBarry Smith 0, 26184994cf47SJed Brown /*29*/ MatSetUp_MPIAIJ, 2619719d5645SBarry Smith 0, 2620cda55fadSBarry Smith 0, 2621a5b7ff6bSBarry Smith MatGetDiagonalBlock_MPIAIJ, 2622cda55fadSBarry Smith 0, 2623d519adbfSMatthew Knepley /*34*/ MatDuplicate_MPIAIJ, 2624cda55fadSBarry Smith 0, 2625cda55fadSBarry Smith 0, 2626cda55fadSBarry Smith 0, 2627cda55fadSBarry Smith 0, 2628d519adbfSMatthew Knepley /*39*/ MatAXPY_MPIAIJ, 26297dae84e0SHong Zhang MatCreateSubMatrices_MPIAIJ, 2630cda55fadSBarry Smith MatIncreaseOverlap_MPIAIJ, 2631cda55fadSBarry Smith MatGetValues_MPIAIJ, 2632cb5b572fSBarry Smith MatCopy_MPIAIJ, 2633d519adbfSMatthew Knepley /*44*/ MatGetRowMax_MPIAIJ, 2634cda55fadSBarry Smith MatScale_MPIAIJ, 26357d68702bSBarry Smith MatShift_MPIAIJ, 263699e65526SBarry Smith MatDiagonalSet_MPIAIJ, 2637564f14d6SBarry Smith MatZeroRowsColumns_MPIAIJ, 263873a71a0fSBarry Smith /*49*/ MatSetRandom_MPIAIJ, 2639cda55fadSBarry Smith 0, 2640cda55fadSBarry Smith 0, 2641cda55fadSBarry Smith 0, 2642cda55fadSBarry Smith 0, 264393dfae19SHong Zhang /*54*/ MatFDColoringCreate_MPIXAIJ, 2644cda55fadSBarry Smith 0, 2645cda55fadSBarry Smith MatSetUnfactored_MPIAIJ, 264672e6a0cfSJed Brown MatPermute_MPIAIJ, 2647cda55fadSBarry Smith 0, 26487dae84e0SHong Zhang /*59*/ MatCreateSubMatrix_MPIAIJ, 2649e03a110bSBarry Smith MatDestroy_MPIAIJ, 2650e03a110bSBarry Smith MatView_MPIAIJ, 2651357abbc8SBarry Smith 0, 2652f996eeb8SHong Zhang MatMatMatMult_MPIAIJ_MPIAIJ_MPIAIJ, 2653f996eeb8SHong Zhang /*64*/ MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ, 2654f996eeb8SHong Zhang MatMatMatMultNumeric_MPIAIJ_MPIAIJ_MPIAIJ, 2655a2243be0SBarry Smith 0, 2656a2243be0SBarry Smith 0, 2657a2243be0SBarry Smith 0, 2658d519adbfSMatthew Knepley /*69*/ MatGetRowMaxAbs_MPIAIJ, 2659c87e5d42SMatthew Knepley MatGetRowMinAbs_MPIAIJ, 2660a2243be0SBarry Smith 0, 2661dcf5cc72SBarry Smith 0, 26622c93a97aSBarry Smith 0, 26632c93a97aSBarry Smith 0, 26643acb8795SBarry Smith /*75*/ MatFDColoringApply_AIJ, 2665b1b1104fSBarry Smith MatSetFromOptions_MPIAIJ, 266697304618SKris Buschelman 0, 266797304618SKris Buschelman 0, 2668f1f41ecbSJed Brown MatFindZeroDiagonals_MPIAIJ, 266997304618SKris Buschelman /*80*/ 0, 267097304618SKris Buschelman 0, 267197304618SKris Buschelman 0, 26725bba2384SShri Abhyankar /*83*/ MatLoad_MPIAIJ, 2673a3bbdb47SHong Zhang MatIsSymmetric_MPIAIJ, 26746284ec50SHong Zhang 0, 26756284ec50SHong Zhang 0, 26766284ec50SHong Zhang 0, 2677865e5f61SKris Buschelman 0, 2678d519adbfSMatthew Knepley /*89*/ MatMatMult_MPIAIJ_MPIAIJ, 267926be0446SHong Zhang MatMatMultSymbolic_MPIAIJ_MPIAIJ, 268026be0446SHong Zhang MatMatMultNumeric_MPIAIJ_MPIAIJ, 2681cf3ca8ceSHong Zhang MatPtAP_MPIAIJ_MPIAIJ, 2682cf3ca8ceSHong Zhang MatPtAPSymbolic_MPIAIJ_MPIAIJ, 2683cf3ca8ceSHong Zhang /*94*/ MatPtAPNumeric_MPIAIJ_MPIAIJ, 26847a7894deSKris Buschelman 0, 26857a7894deSKris Buschelman 0, 26867a7894deSKris Buschelman 0, 26877a7894deSKris Buschelman 0, 2688d519adbfSMatthew Knepley /*99*/ 0, 2689d2b207f1SPeter Brune 0, 2690d2b207f1SPeter Brune 0, 26912fd7e33dSBarry Smith MatConjugate_MPIAIJ, 26922fd7e33dSBarry Smith 0, 2693d519adbfSMatthew Knepley /*104*/MatSetValuesRow_MPIAIJ, 269499cafbc1SBarry Smith MatRealPart_MPIAIJ, 269569db28dcSHong Zhang MatImaginaryPart_MPIAIJ, 269669db28dcSHong Zhang 0, 269769db28dcSHong Zhang 0, 2698d519adbfSMatthew Knepley /*109*/0, 2699aae456dbSHong Zhang 0, 27005494a064SHong Zhang MatGetRowMin_MPIAIJ, 27015494a064SHong Zhang 0, 27023b49f96aSBarry Smith MatMissingDiagonal_MPIAIJ, 2703d1adec66SJed Brown /*114*/MatGetSeqNonzeroStructure_MPIAIJ, 2704bd0c2dcbSBarry Smith 0, 2705c5e4d11fSDmitry Karpeev MatGetGhosts_MPIAIJ, 2706bd0c2dcbSBarry Smith 0, 2707bd0c2dcbSBarry Smith 0, 27088fb81238SShri Abhyankar /*119*/0, 27098fb81238SShri Abhyankar 0, 27108fb81238SShri Abhyankar 0, 2711d6037b41SHong Zhang 0, 2712b9614d88SDmitry Karpeev MatGetMultiProcBlock_MPIAIJ, 2713f2c98031SJed Brown /*124*/MatFindNonzeroRows_MPIAIJ, 27140716a85fSBarry Smith MatGetColumnNorms_MPIAIJ, 2715bbead8a2SBarry Smith MatInvertBlockDiagonal_MPIAIJ, 2716a8ee9fb5SBarry Smith MatInvertVariableBlockDiagonal_MPIAIJ, 27177dae84e0SHong Zhang MatCreateSubMatricesMPI_MPIAIJ, 2718187b3c17SHong Zhang /*129*/0, 2719187b3c17SHong Zhang MatTransposeMatMult_MPIAIJ_MPIAIJ, 2720187b3c17SHong Zhang MatTransposeMatMultSymbolic_MPIAIJ_MPIAIJ, 2721187b3c17SHong Zhang MatTransposeMatMultNumeric_MPIAIJ_MPIAIJ, 2722187b3c17SHong Zhang 0, 2723187b3c17SHong Zhang /*134*/0, 2724187b3c17SHong Zhang 0, 27258d45306eSHong Zhang MatRARt_MPIAIJ_MPIAIJ, 2726187b3c17SHong Zhang 0, 27273964eb88SJed Brown 0, 272846533700Sstefano_zampini /*139*/MatSetBlockSizes_MPIAIJ, 2729f9426fe0SMark Adams 0, 2730f86b9fbaSHong Zhang 0, 27319c8f2541SHong Zhang MatFDColoringSetUp_MPIXAIJ, 2732a0b6529bSBarry Smith MatFindOffBlockDiagonalEntries_MPIAIJ, 27339c8f2541SHong Zhang /*144*/MatCreateMPIMatConcatenateSeqMat_MPIAIJ 2734bd0c2dcbSBarry Smith }; 273536ce4990SBarry Smith 27362e8a6d31SBarry Smith /* ----------------------------------------------------------------------------------------*/ 27372e8a6d31SBarry Smith 27387087cfbeSBarry Smith PetscErrorCode MatStoreValues_MPIAIJ(Mat mat) 27392e8a6d31SBarry Smith { 27402e8a6d31SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 2741dfbe8321SBarry Smith PetscErrorCode ierr; 27422e8a6d31SBarry Smith 27432e8a6d31SBarry Smith PetscFunctionBegin; 27442e8a6d31SBarry Smith ierr = MatStoreValues(aij->A);CHKERRQ(ierr); 27452e8a6d31SBarry Smith ierr = MatStoreValues(aij->B);CHKERRQ(ierr); 27462e8a6d31SBarry Smith PetscFunctionReturn(0); 27472e8a6d31SBarry Smith } 27482e8a6d31SBarry Smith 27497087cfbeSBarry Smith PetscErrorCode MatRetrieveValues_MPIAIJ(Mat mat) 27502e8a6d31SBarry Smith { 27512e8a6d31SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 2752dfbe8321SBarry Smith PetscErrorCode ierr; 27532e8a6d31SBarry Smith 27542e8a6d31SBarry Smith PetscFunctionBegin; 27552e8a6d31SBarry Smith ierr = MatRetrieveValues(aij->A);CHKERRQ(ierr); 27562e8a6d31SBarry Smith ierr = MatRetrieveValues(aij->B);CHKERRQ(ierr); 27572e8a6d31SBarry Smith PetscFunctionReturn(0); 27582e8a6d31SBarry Smith } 27598a729477SBarry Smith 27607087cfbeSBarry Smith PetscErrorCode MatMPIAIJSetPreallocation_MPIAIJ(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 2761a23d5eceSKris Buschelman { 2762a23d5eceSKris Buschelman Mat_MPIAIJ *b; 2763dfbe8321SBarry Smith PetscErrorCode ierr; 27645d2a9ed1SStefano Zampini PetscMPIInt size; 2765a23d5eceSKris Buschelman 2766a23d5eceSKris Buschelman PetscFunctionBegin; 276726283091SBarry Smith ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 276826283091SBarry Smith ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 2769a23d5eceSKris Buschelman b = (Mat_MPIAIJ*)B->data; 2770899cda47SBarry Smith 2771cb7b82ddSBarry Smith #if defined(PETSC_USE_CTABLE) 2772cb7b82ddSBarry Smith ierr = PetscTableDestroy(&b->colmap);CHKERRQ(ierr); 2773cb7b82ddSBarry Smith #else 2774cb7b82ddSBarry Smith ierr = PetscFree(b->colmap);CHKERRQ(ierr); 2775cb7b82ddSBarry Smith #endif 2776cb7b82ddSBarry Smith ierr = PetscFree(b->garray);CHKERRQ(ierr); 2777cb7b82ddSBarry Smith ierr = VecDestroy(&b->lvec);CHKERRQ(ierr); 2778cb7b82ddSBarry Smith ierr = VecScatterDestroy(&b->Mvctx);CHKERRQ(ierr); 2779cb7b82ddSBarry Smith 2780cb7b82ddSBarry Smith /* Because the B will have been resized we simply destroy it and create a new one each time */ 27815d2a9ed1SStefano Zampini ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr); 2782cb7b82ddSBarry Smith ierr = MatDestroy(&b->B);CHKERRQ(ierr); 2783899cda47SBarry Smith ierr = MatCreate(PETSC_COMM_SELF,&b->B);CHKERRQ(ierr); 27845d2a9ed1SStefano Zampini ierr = MatSetSizes(b->B,B->rmap->n,size > 1 ? B->cmap->N : 0,B->rmap->n,size > 1 ? B->cmap->N : 0);CHKERRQ(ierr); 278533d57670SJed Brown ierr = MatSetBlockSizesFromMats(b->B,B,B);CHKERRQ(ierr); 2786899cda47SBarry Smith ierr = MatSetType(b->B,MATSEQAIJ);CHKERRQ(ierr); 27873bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)B,(PetscObject)b->B);CHKERRQ(ierr); 2788cb7b82ddSBarry Smith 2789cb7b82ddSBarry Smith if (!B->preallocated) { 2790cb7b82ddSBarry Smith ierr = MatCreate(PETSC_COMM_SELF,&b->A);CHKERRQ(ierr); 2791cb7b82ddSBarry Smith ierr = MatSetSizes(b->A,B->rmap->n,B->cmap->n,B->rmap->n,B->cmap->n);CHKERRQ(ierr); 2792cb7b82ddSBarry Smith ierr = MatSetBlockSizesFromMats(b->A,B,B);CHKERRQ(ierr); 2793cb7b82ddSBarry Smith ierr = MatSetType(b->A,MATSEQAIJ);CHKERRQ(ierr); 2794cb7b82ddSBarry Smith ierr = PetscLogObjectParent((PetscObject)B,(PetscObject)b->A);CHKERRQ(ierr); 2795526dfc15SBarry Smith } 2796899cda47SBarry Smith 2797c60e587dSKris Buschelman ierr = MatSeqAIJSetPreallocation(b->A,d_nz,d_nnz);CHKERRQ(ierr); 2798c60e587dSKris Buschelman ierr = MatSeqAIJSetPreallocation(b->B,o_nz,o_nnz);CHKERRQ(ierr); 2799526dfc15SBarry Smith B->preallocated = PETSC_TRUE; 2800cb7b82ddSBarry Smith B->was_assembled = PETSC_FALSE; 280115001458SStefano Zampini B->assembled = PETSC_FALSE; 2802a23d5eceSKris Buschelman PetscFunctionReturn(0); 2803a23d5eceSKris Buschelman } 2804a23d5eceSKris Buschelman 2805846b4da1SFande Kong PetscErrorCode MatResetPreallocation_MPIAIJ(Mat B) 2806846b4da1SFande Kong { 2807846b4da1SFande Kong Mat_MPIAIJ *b; 2808846b4da1SFande Kong PetscErrorCode ierr; 2809846b4da1SFande Kong 2810846b4da1SFande Kong PetscFunctionBegin; 2811846b4da1SFande Kong PetscValidHeaderSpecific(B,MAT_CLASSID,1); 2812846b4da1SFande Kong ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 2813846b4da1SFande Kong ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 2814846b4da1SFande Kong b = (Mat_MPIAIJ*)B->data; 2815846b4da1SFande Kong 2816846b4da1SFande Kong #if defined(PETSC_USE_CTABLE) 2817846b4da1SFande Kong ierr = PetscTableDestroy(&b->colmap);CHKERRQ(ierr); 2818846b4da1SFande Kong #else 2819846b4da1SFande Kong ierr = PetscFree(b->colmap);CHKERRQ(ierr); 2820846b4da1SFande Kong #endif 2821846b4da1SFande Kong ierr = PetscFree(b->garray);CHKERRQ(ierr); 2822846b4da1SFande Kong ierr = VecDestroy(&b->lvec);CHKERRQ(ierr); 2823846b4da1SFande Kong ierr = VecScatterDestroy(&b->Mvctx);CHKERRQ(ierr); 2824846b4da1SFande Kong 2825846b4da1SFande Kong ierr = MatResetPreallocation(b->A);CHKERRQ(ierr); 2826846b4da1SFande Kong ierr = MatResetPreallocation(b->B);CHKERRQ(ierr); 2827846b4da1SFande Kong B->preallocated = PETSC_TRUE; 2828846b4da1SFande Kong B->was_assembled = PETSC_FALSE; 2829846b4da1SFande Kong B->assembled = PETSC_FALSE; 2830846b4da1SFande Kong PetscFunctionReturn(0); 2831846b4da1SFande Kong } 2832846b4da1SFande Kong 2833dfbe8321SBarry Smith PetscErrorCode MatDuplicate_MPIAIJ(Mat matin,MatDuplicateOption cpvalues,Mat *newmat) 2834d6dfbf8fSBarry Smith { 2835d6dfbf8fSBarry Smith Mat mat; 2836416022c9SBarry Smith Mat_MPIAIJ *a,*oldmat = (Mat_MPIAIJ*)matin->data; 2837dfbe8321SBarry Smith PetscErrorCode ierr; 2838d6dfbf8fSBarry Smith 28393a40ed3dSBarry Smith PetscFunctionBegin; 2840416022c9SBarry Smith *newmat = 0; 2841ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)matin),&mat);CHKERRQ(ierr); 2842d0f46423SBarry Smith ierr = MatSetSizes(mat,matin->rmap->n,matin->cmap->n,matin->rmap->N,matin->cmap->N);CHKERRQ(ierr); 284333d57670SJed Brown ierr = MatSetBlockSizesFromMats(mat,matin,matin);CHKERRQ(ierr); 28447adad957SLisandro Dalcin ierr = MatSetType(mat,((PetscObject)matin)->type_name);CHKERRQ(ierr); 2845273d9f13SBarry Smith a = (Mat_MPIAIJ*)mat->data; 2846e1b6402fSHong Zhang 2847d5f3da31SBarry Smith mat->factortype = matin->factortype; 2848c456f294SBarry Smith mat->assembled = PETSC_TRUE; 2849e7641de0SSatish Balay mat->insertmode = NOT_SET_VALUES; 2850273d9f13SBarry Smith mat->preallocated = PETSC_TRUE; 2851d6dfbf8fSBarry Smith 285217699dbbSLois Curfman McInnes a->size = oldmat->size; 285317699dbbSLois Curfman McInnes a->rank = oldmat->rank; 2854e7641de0SSatish Balay a->donotstash = oldmat->donotstash; 2855e7641de0SSatish Balay a->roworiented = oldmat->roworiented; 2856e7641de0SSatish Balay a->rowindices = 0; 2857bcd2baecSBarry Smith a->rowvalues = 0; 2858bcd2baecSBarry Smith a->getrowactive = PETSC_FALSE; 2859d6dfbf8fSBarry Smith 28601e1e43feSBarry Smith ierr = PetscLayoutReference(matin->rmap,&mat->rmap);CHKERRQ(ierr); 28611e1e43feSBarry Smith ierr = PetscLayoutReference(matin->cmap,&mat->cmap);CHKERRQ(ierr); 2862899cda47SBarry Smith 28632ee70a88SLois Curfman McInnes if (oldmat->colmap) { 2864aa482453SBarry Smith #if defined(PETSC_USE_CTABLE) 28650f5bd95cSBarry Smith ierr = PetscTableCreateCopy(oldmat->colmap,&a->colmap);CHKERRQ(ierr); 2866b1fc9764SSatish Balay #else 2867854ce69bSBarry Smith ierr = PetscMalloc1(mat->cmap->N,&a->colmap);CHKERRQ(ierr); 28683bb1ff40SBarry Smith ierr = PetscLogObjectMemory((PetscObject)mat,(mat->cmap->N)*sizeof(PetscInt));CHKERRQ(ierr); 2869580bdb30SBarry Smith ierr = PetscArraycpy(a->colmap,oldmat->colmap,mat->cmap->N);CHKERRQ(ierr); 2870b1fc9764SSatish Balay #endif 2871416022c9SBarry Smith } else a->colmap = 0; 28723f41c07dSBarry Smith if (oldmat->garray) { 2873b1d57f15SBarry Smith PetscInt len; 2874d0f46423SBarry Smith len = oldmat->B->cmap->n; 2875854ce69bSBarry Smith ierr = PetscMalloc1(len+1,&a->garray);CHKERRQ(ierr); 28763bb1ff40SBarry Smith ierr = PetscLogObjectMemory((PetscObject)mat,len*sizeof(PetscInt));CHKERRQ(ierr); 2877580bdb30SBarry Smith if (len) { ierr = PetscArraycpy(a->garray,oldmat->garray,len);CHKERRQ(ierr); } 2878416022c9SBarry Smith } else a->garray = 0; 2879d6dfbf8fSBarry Smith 2880416022c9SBarry Smith ierr = VecDuplicate(oldmat->lvec,&a->lvec);CHKERRQ(ierr); 28813bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->lvec);CHKERRQ(ierr); 2882a56f8943SBarry Smith ierr = VecScatterCopy(oldmat->Mvctx,&a->Mvctx);CHKERRQ(ierr); 28833bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->Mvctx);CHKERRQ(ierr); 2884fa83eaafSHong Zhang 2885fa83eaafSHong Zhang if (oldmat->Mvctx_mpi1) { 2886fa83eaafSHong Zhang ierr = VecScatterCopy(oldmat->Mvctx_mpi1,&a->Mvctx_mpi1);CHKERRQ(ierr); 2887fa83eaafSHong Zhang ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->Mvctx_mpi1);CHKERRQ(ierr); 2888fa110396SHong Zhang } 2889fa83eaafSHong Zhang 28902e8a6d31SBarry Smith ierr = MatDuplicate(oldmat->A,cpvalues,&a->A);CHKERRQ(ierr); 28913bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->A);CHKERRQ(ierr); 28922e8a6d31SBarry Smith ierr = MatDuplicate(oldmat->B,cpvalues,&a->B);CHKERRQ(ierr); 28933bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->B);CHKERRQ(ierr); 2894140e18c1SBarry Smith ierr = PetscFunctionListDuplicate(((PetscObject)matin)->qlist,&((PetscObject)mat)->qlist);CHKERRQ(ierr); 28958a729477SBarry Smith *newmat = mat; 28963a40ed3dSBarry Smith PetscFunctionReturn(0); 28978a729477SBarry Smith } 2898416022c9SBarry Smith 2899112444f4SShri Abhyankar PetscErrorCode MatLoad_MPIAIJ(Mat newMat, PetscViewer viewer) 29008fb81238SShri Abhyankar { 290152f91c60SVaclav Hapla PetscBool isbinary, ishdf5; 290252f91c60SVaclav Hapla PetscErrorCode ierr; 290352f91c60SVaclav Hapla 290452f91c60SVaclav Hapla PetscFunctionBegin; 290552f91c60SVaclav Hapla PetscValidHeaderSpecific(newMat,MAT_CLASSID,1); 290652f91c60SVaclav Hapla PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 2907c27b3999SVaclav Hapla /* force binary viewer to load .info file if it has not yet done so */ 2908c27b3999SVaclav Hapla ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr); 290952f91c60SVaclav Hapla ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 291052f91c60SVaclav Hapla ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 291152f91c60SVaclav Hapla if (isbinary) { 291252f91c60SVaclav Hapla ierr = MatLoad_MPIAIJ_Binary(newMat,viewer);CHKERRQ(ierr); 291352f91c60SVaclav Hapla } else if (ishdf5) { 291452f91c60SVaclav Hapla #if defined(PETSC_HAVE_HDF5) 291552f91c60SVaclav Hapla ierr = MatLoad_AIJ_HDF5(newMat,viewer);CHKERRQ(ierr); 291652f91c60SVaclav Hapla #else 291752f91c60SVaclav Hapla SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 291852f91c60SVaclav Hapla #endif 291952f91c60SVaclav Hapla } else { 292052f91c60SVaclav Hapla SETERRQ2(PetscObjectComm((PetscObject)newMat),PETSC_ERR_SUP,"Viewer type %s not yet supported for reading %s matrices",((PetscObject)viewer)->type_name,((PetscObject)newMat)->type_name); 292152f91c60SVaclav Hapla } 292252f91c60SVaclav Hapla PetscFunctionReturn(0); 292352f91c60SVaclav Hapla } 292452f91c60SVaclav Hapla 292552f91c60SVaclav Hapla PetscErrorCode MatLoad_MPIAIJ_Binary(Mat newMat, PetscViewer viewer) 292652f91c60SVaclav Hapla { 29278fb81238SShri Abhyankar PetscScalar *vals,*svals; 2928ce94432eSBarry Smith MPI_Comm comm; 29298fb81238SShri Abhyankar PetscErrorCode ierr; 29301a4ee126SBarry Smith PetscMPIInt rank,size,tag = ((PetscObject)viewer)->tag; 2931461878b2SBarry Smith PetscInt i,nz,j,rstart,rend,mmax,maxnz = 0; 29328fb81238SShri Abhyankar PetscInt header[4],*rowlengths = 0,M,N,m,*cols; 29330298fd71SBarry Smith PetscInt *ourlens = NULL,*procsnz = NULL,*offlens = NULL,jj,*mycols,*smycols; 2934461878b2SBarry Smith PetscInt cend,cstart,n,*rowners; 29358fb81238SShri Abhyankar int fd; 29363059b6faSBarry Smith PetscInt bs = newMat->rmap->bs; 29378fb81238SShri Abhyankar 29388fb81238SShri Abhyankar PetscFunctionBegin; 2939ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 29408fb81238SShri Abhyankar ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 29418fb81238SShri Abhyankar ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 29428fb81238SShri Abhyankar ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 29435872f025SBarry Smith if (!rank) { 29449860990eSLisandro Dalcin ierr = PetscBinaryRead(fd,(char*)header,4,NULL,PETSC_INT);CHKERRQ(ierr); 29458fb81238SShri Abhyankar if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object"); 29465f4d30c4SBarry Smith if (header[3] < 0) SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as MATMPIAIJ"); 29478fb81238SShri Abhyankar } 29488fb81238SShri Abhyankar 29495f4d30c4SBarry Smith ierr = PetscOptionsBegin(comm,NULL,"Options for loading MATMPIAIJ matrix","Mat");CHKERRQ(ierr); 29500298fd71SBarry Smith ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,NULL);CHKERRQ(ierr); 295108ea439dSMark F. Adams ierr = PetscOptionsEnd();CHKERRQ(ierr); 29523059b6faSBarry Smith if (bs < 0) bs = 1; 295308ea439dSMark F. Adams 29548fb81238SShri Abhyankar ierr = MPI_Bcast(header+1,3,MPIU_INT,0,comm);CHKERRQ(ierr); 29558fb81238SShri Abhyankar M = header[1]; N = header[2]; 29568fb81238SShri Abhyankar 29578fb81238SShri Abhyankar /* If global sizes are set, check if they are consistent with that given in the file */ 2958461878b2SBarry Smith if (newMat->rmap->N >= 0 && newMat->rmap->N != M) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Inconsistent # of rows:Matrix in file has (%D) and input matrix has (%D)",newMat->rmap->N,M); 2959461878b2SBarry Smith if (newMat->cmap->N >=0 && newMat->cmap->N != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"Inconsistent # of cols:Matrix in file has (%D) and input matrix has (%D)",newMat->cmap->N,N); 29608fb81238SShri Abhyankar 296108ea439dSMark F. Adams /* determine ownership of all (block) rows */ 296208ea439dSMark F. Adams if (M%bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Inconsistent # of rows (%d) and block size (%d)",M,bs); 296308ea439dSMark F. Adams if (newMat->rmap->n < 0) m = bs*((M/bs)/size + (((M/bs) % size) > rank)); /* PETSC_DECIDE */ 29644683f7a4SShri Abhyankar else m = newMat->rmap->n; /* Set by user */ 29658fb81238SShri Abhyankar 2966854ce69bSBarry Smith ierr = PetscMalloc1(size+1,&rowners);CHKERRQ(ierr); 29678fb81238SShri Abhyankar ierr = MPI_Allgather(&m,1,MPIU_INT,rowners+1,1,MPIU_INT,comm);CHKERRQ(ierr); 29688fb81238SShri Abhyankar 29698fb81238SShri Abhyankar /* First process needs enough room for process with most rows */ 29708fb81238SShri Abhyankar if (!rank) { 29718fb81238SShri Abhyankar mmax = rowners[1]; 29725c4ea359SMatthew G Knepley for (i=2; i<=size; i++) { 29738fb81238SShri Abhyankar mmax = PetscMax(mmax, rowners[i]); 29748fb81238SShri Abhyankar } 29753964eb88SJed Brown } else mmax = -1; /* unused, but compilers complain */ 29768fb81238SShri Abhyankar 29778fb81238SShri Abhyankar rowners[0] = 0; 29788fb81238SShri Abhyankar for (i=2; i<=size; i++) { 29798fb81238SShri Abhyankar rowners[i] += rowners[i-1]; 29808fb81238SShri Abhyankar } 29818fb81238SShri Abhyankar rstart = rowners[rank]; 29828fb81238SShri Abhyankar rend = rowners[rank+1]; 29838fb81238SShri Abhyankar 29848fb81238SShri Abhyankar /* distribute row lengths to all processors */ 2985dcca6d9dSJed Brown ierr = PetscMalloc2(m,&ourlens,m,&offlens);CHKERRQ(ierr); 29868fb81238SShri Abhyankar if (!rank) { 29879860990eSLisandro Dalcin ierr = PetscBinaryRead(fd,ourlens,m,NULL,PETSC_INT);CHKERRQ(ierr); 2988785e854fSJed Brown ierr = PetscMalloc1(mmax,&rowlengths);CHKERRQ(ierr); 29891795a4d1SJed Brown ierr = PetscCalloc1(size,&procsnz);CHKERRQ(ierr); 29908fb81238SShri Abhyankar for (j=0; j<m; j++) { 29918fb81238SShri Abhyankar procsnz[0] += ourlens[j]; 29928fb81238SShri Abhyankar } 29938fb81238SShri Abhyankar for (i=1; i<size; i++) { 29949860990eSLisandro Dalcin ierr = PetscBinaryRead(fd,rowlengths,rowners[i+1]-rowners[i],NULL,PETSC_INT);CHKERRQ(ierr); 29958fb81238SShri Abhyankar /* calculate the number of nonzeros on each processor */ 29968fb81238SShri Abhyankar for (j=0; j<rowners[i+1]-rowners[i]; j++) { 29978fb81238SShri Abhyankar procsnz[i] += rowlengths[j]; 29988fb81238SShri Abhyankar } 2999a25532f0SBarry Smith ierr = MPIULong_Send(rowlengths,rowners[i+1]-rowners[i],MPIU_INT,i,tag,comm);CHKERRQ(ierr); 30008fb81238SShri Abhyankar } 30018fb81238SShri Abhyankar ierr = PetscFree(rowlengths);CHKERRQ(ierr); 30028fb81238SShri Abhyankar } else { 3003a25532f0SBarry Smith ierr = MPIULong_Recv(ourlens,m,MPIU_INT,0,tag,comm);CHKERRQ(ierr); 30048fb81238SShri Abhyankar } 30058fb81238SShri Abhyankar 30068fb81238SShri Abhyankar if (!rank) { 30078fb81238SShri Abhyankar /* determine max buffer needed and allocate it */ 30088fb81238SShri Abhyankar maxnz = 0; 30098fb81238SShri Abhyankar for (i=0; i<size; i++) { 30108fb81238SShri Abhyankar maxnz = PetscMax(maxnz,procsnz[i]); 30118fb81238SShri Abhyankar } 3012785e854fSJed Brown ierr = PetscMalloc1(maxnz,&cols);CHKERRQ(ierr); 30138fb81238SShri Abhyankar 30148fb81238SShri Abhyankar /* read in my part of the matrix column indices */ 30158fb81238SShri Abhyankar nz = procsnz[0]; 3016785e854fSJed Brown ierr = PetscMalloc1(nz,&mycols);CHKERRQ(ierr); 30179860990eSLisandro Dalcin ierr = PetscBinaryRead(fd,mycols,nz,NULL,PETSC_INT);CHKERRQ(ierr); 30188fb81238SShri Abhyankar 30198fb81238SShri Abhyankar /* read in every one elses and ship off */ 30208fb81238SShri Abhyankar for (i=1; i<size; i++) { 30218fb81238SShri Abhyankar nz = procsnz[i]; 30229860990eSLisandro Dalcin ierr = PetscBinaryRead(fd,cols,nz,NULL,PETSC_INT);CHKERRQ(ierr); 3023a25532f0SBarry Smith ierr = MPIULong_Send(cols,nz,MPIU_INT,i,tag,comm);CHKERRQ(ierr); 30248fb81238SShri Abhyankar } 30258fb81238SShri Abhyankar ierr = PetscFree(cols);CHKERRQ(ierr); 30268fb81238SShri Abhyankar } else { 30278fb81238SShri Abhyankar /* determine buffer space needed for message */ 30288fb81238SShri Abhyankar nz = 0; 30298fb81238SShri Abhyankar for (i=0; i<m; i++) { 30308fb81238SShri Abhyankar nz += ourlens[i]; 30318fb81238SShri Abhyankar } 3032785e854fSJed Brown ierr = PetscMalloc1(nz,&mycols);CHKERRQ(ierr); 30338fb81238SShri Abhyankar 30348fb81238SShri Abhyankar /* receive message of column indices*/ 3035a25532f0SBarry Smith ierr = MPIULong_Recv(mycols,nz,MPIU_INT,0,tag,comm);CHKERRQ(ierr); 30368fb81238SShri Abhyankar } 30378fb81238SShri Abhyankar 30388fb81238SShri Abhyankar /* determine column ownership if matrix is not square */ 30398fb81238SShri Abhyankar if (N != M) { 30408fb81238SShri Abhyankar if (newMat->cmap->n < 0) n = N/size + ((N % size) > rank); 30418fb81238SShri Abhyankar else n = newMat->cmap->n; 30428fb81238SShri Abhyankar ierr = MPI_Scan(&n,&cend,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 30438fb81238SShri Abhyankar cstart = cend - n; 30448fb81238SShri Abhyankar } else { 30458fb81238SShri Abhyankar cstart = rstart; 30468fb81238SShri Abhyankar cend = rend; 30478fb81238SShri Abhyankar n = cend - cstart; 30488fb81238SShri Abhyankar } 30498fb81238SShri Abhyankar 30508fb81238SShri Abhyankar /* loop over local rows, determining number of off diagonal entries */ 3051580bdb30SBarry Smith ierr = PetscArrayzero(offlens,m);CHKERRQ(ierr); 30528fb81238SShri Abhyankar jj = 0; 30538fb81238SShri Abhyankar for (i=0; i<m; i++) { 30548fb81238SShri Abhyankar for (j=0; j<ourlens[i]; j++) { 30558fb81238SShri Abhyankar if (mycols[jj] < cstart || mycols[jj] >= cend) offlens[i]++; 30568fb81238SShri Abhyankar jj++; 30578fb81238SShri Abhyankar } 30588fb81238SShri Abhyankar } 30598fb81238SShri Abhyankar 30608fb81238SShri Abhyankar for (i=0; i<m; i++) { 30618fb81238SShri Abhyankar ourlens[i] -= offlens[i]; 30628fb81238SShri Abhyankar } 30638fb81238SShri Abhyankar ierr = MatSetSizes(newMat,m,n,M,N);CHKERRQ(ierr); 306408ea439dSMark F. Adams 306508ea439dSMark F. Adams if (bs > 1) {ierr = MatSetBlockSize(newMat,bs);CHKERRQ(ierr);} 306608ea439dSMark F. Adams 30678fb81238SShri Abhyankar ierr = MatMPIAIJSetPreallocation(newMat,0,ourlens,0,offlens);CHKERRQ(ierr); 30688fb81238SShri Abhyankar 30698fb81238SShri Abhyankar for (i=0; i<m; i++) { 30708fb81238SShri Abhyankar ourlens[i] += offlens[i]; 30718fb81238SShri Abhyankar } 30728fb81238SShri Abhyankar 30738fb81238SShri Abhyankar if (!rank) { 3074854ce69bSBarry Smith ierr = PetscMalloc1(maxnz+1,&vals);CHKERRQ(ierr); 30758fb81238SShri Abhyankar 30768fb81238SShri Abhyankar /* read in my part of the matrix numerical values */ 30778fb81238SShri Abhyankar nz = procsnz[0]; 30789860990eSLisandro Dalcin ierr = PetscBinaryRead(fd,vals,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr); 30798fb81238SShri Abhyankar 30808fb81238SShri Abhyankar /* insert into matrix */ 30818fb81238SShri Abhyankar jj = rstart; 30828fb81238SShri Abhyankar smycols = mycols; 30838fb81238SShri Abhyankar svals = vals; 30848fb81238SShri Abhyankar for (i=0; i<m; i++) { 30858fb81238SShri Abhyankar ierr = MatSetValues_MPIAIJ(newMat,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr); 30868fb81238SShri Abhyankar smycols += ourlens[i]; 30878fb81238SShri Abhyankar svals += ourlens[i]; 30888fb81238SShri Abhyankar jj++; 30898fb81238SShri Abhyankar } 30908fb81238SShri Abhyankar 30918fb81238SShri Abhyankar /* read in other processors and ship out */ 30928fb81238SShri Abhyankar for (i=1; i<size; i++) { 30938fb81238SShri Abhyankar nz = procsnz[i]; 30949860990eSLisandro Dalcin ierr = PetscBinaryRead(fd,vals,nz,NULL,PETSC_SCALAR);CHKERRQ(ierr); 3095a25532f0SBarry Smith ierr = MPIULong_Send(vals,nz,MPIU_SCALAR,i,((PetscObject)newMat)->tag,comm);CHKERRQ(ierr); 30968fb81238SShri Abhyankar } 30978fb81238SShri Abhyankar ierr = PetscFree(procsnz);CHKERRQ(ierr); 30988fb81238SShri Abhyankar } else { 30998fb81238SShri Abhyankar /* receive numeric values */ 3100854ce69bSBarry Smith ierr = PetscMalloc1(nz+1,&vals);CHKERRQ(ierr); 31018fb81238SShri Abhyankar 31028fb81238SShri Abhyankar /* receive message of values*/ 3103a25532f0SBarry Smith ierr = MPIULong_Recv(vals,nz,MPIU_SCALAR,0,((PetscObject)newMat)->tag,comm);CHKERRQ(ierr); 31048fb81238SShri Abhyankar 31058fb81238SShri Abhyankar /* insert into matrix */ 31068fb81238SShri Abhyankar jj = rstart; 31078fb81238SShri Abhyankar smycols = mycols; 31088fb81238SShri Abhyankar svals = vals; 31098fb81238SShri Abhyankar for (i=0; i<m; i++) { 31108fb81238SShri Abhyankar ierr = MatSetValues_MPIAIJ(newMat,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr); 31118fb81238SShri Abhyankar smycols += ourlens[i]; 31128fb81238SShri Abhyankar svals += ourlens[i]; 31138fb81238SShri Abhyankar jj++; 31148fb81238SShri Abhyankar } 31158fb81238SShri Abhyankar } 31168fb81238SShri Abhyankar ierr = PetscFree2(ourlens,offlens);CHKERRQ(ierr); 31178fb81238SShri Abhyankar ierr = PetscFree(vals);CHKERRQ(ierr); 31188fb81238SShri Abhyankar ierr = PetscFree(mycols);CHKERRQ(ierr); 31198fb81238SShri Abhyankar ierr = PetscFree(rowners);CHKERRQ(ierr); 31208fb81238SShri Abhyankar ierr = MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 31218fb81238SShri Abhyankar ierr = MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 31228fb81238SShri Abhyankar PetscFunctionReturn(0); 31238fb81238SShri Abhyankar } 31248fb81238SShri Abhyankar 31253782ecc7SHong Zhang /* Not scalable because of ISAllGather() unless getting all columns. */ 31268b3fa1f7SHong Zhang PetscErrorCode ISGetSeqIS_Private(Mat mat,IS iscol,IS *isseq) 31274aa3045dSJed Brown { 31284aa3045dSJed Brown PetscErrorCode ierr; 31294aa3045dSJed Brown IS iscol_local; 3130c5e4d11fSDmitry Karpeev PetscBool isstride; 3131c5e4d11fSDmitry Karpeev PetscMPIInt lisstride=0,gisstride; 31323782ecc7SHong Zhang 31333782ecc7SHong Zhang PetscFunctionBegin; 31343782ecc7SHong Zhang /* check if we are grabbing all columns*/ 3135c5e4d11fSDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&isstride);CHKERRQ(ierr); 31363782ecc7SHong Zhang 3137c5e4d11fSDmitry Karpeev if (isstride) { 3138c5e4d11fSDmitry Karpeev PetscInt start,len,mstart,mlen; 3139c5e4d11fSDmitry Karpeev ierr = ISStrideGetInfo(iscol,&start,NULL);CHKERRQ(ierr); 3140c5e4d11fSDmitry Karpeev ierr = ISGetLocalSize(iscol,&len);CHKERRQ(ierr); 3141c5e4d11fSDmitry Karpeev ierr = MatGetOwnershipRangeColumn(mat,&mstart,&mlen);CHKERRQ(ierr); 3142c5e4d11fSDmitry Karpeev if (mstart == start && mlen-mstart == len) lisstride = 1; 3143c5e4d11fSDmitry Karpeev } 31443782ecc7SHong Zhang 3145b2566f29SBarry Smith ierr = MPIU_Allreduce(&lisstride,&gisstride,1,MPI_INT,MPI_MIN,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 3146c5e4d11fSDmitry Karpeev if (gisstride) { 3147c5e4d11fSDmitry Karpeev PetscInt N; 3148c5e4d11fSDmitry Karpeev ierr = MatGetSize(mat,NULL,&N);CHKERRQ(ierr); 3149c5e4d11fSDmitry Karpeev ierr = ISCreateStride(PetscObjectComm((PetscObject)mat),N,0,1,&iscol_local);CHKERRQ(ierr); 3150c5e4d11fSDmitry Karpeev ierr = ISSetIdentity(iscol_local);CHKERRQ(ierr); 3151c5e4d11fSDmitry Karpeev ierr = PetscInfo(mat,"Optimizing for obtaining all columns of the matrix; skipping ISAllGather()\n");CHKERRQ(ierr); 3152c5e4d11fSDmitry Karpeev } else { 3153c5bfad50SMark F. Adams PetscInt cbs; 3154c5bfad50SMark F. Adams ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 31554aa3045dSJed Brown ierr = ISAllGather(iscol,&iscol_local);CHKERRQ(ierr); 3156c5bfad50SMark F. Adams ierr = ISSetBlockSize(iscol_local,cbs);CHKERRQ(ierr); 3157b79d0421SJed Brown } 31583782ecc7SHong Zhang 31593782ecc7SHong Zhang *isseq = iscol_local; 31603782ecc7SHong Zhang PetscFunctionReturn(0); 3161c5e4d11fSDmitry Karpeev } 31628d2139bdSHong Zhang 3163ddfdf956SHong Zhang /* 31649c988bcaSHong Zhang Used by MatCreateSubMatrix_MPIAIJ_SameRowColDist() to avoid ISAllGather() and global size of iscol_local 31659c988bcaSHong Zhang (see MatCreateSubMatrix_MPIAIJ_nonscalable) 3166ddfdf956SHong Zhang 3167ddfdf956SHong Zhang Input Parameters: 3168ddfdf956SHong Zhang mat - matrix 31699c988bcaSHong Zhang isrow - parallel row index set; its local indices are a subset of local columns of mat, 31709c988bcaSHong Zhang i.e., mat->rstart <= isrow[i] < mat->rend 3171ddfdf956SHong Zhang iscol - parallel column index set; its local indices are a subset of local columns of mat, 3172ddfdf956SHong Zhang i.e., mat->cstart <= iscol[i] < mat->cend 3173ddfdf956SHong Zhang Output Parameter: 31749c988bcaSHong Zhang isrow_d,iscol_d - sequential row and column index sets for retrieving mat->A 31759c988bcaSHong Zhang iscol_o - sequential column index set for retrieving mat->B 31769c988bcaSHong Zhang garray - column map; garray[i] indicates global location of iscol_o[i] in iscol 3177ddfdf956SHong Zhang */ 31789c988bcaSHong Zhang PetscErrorCode ISGetSeqIS_SameColDist_Private(Mat mat,IS isrow,IS iscol,IS *isrow_d,IS *iscol_d,IS *iscol_o,const PetscInt *garray[]) 31793782ecc7SHong Zhang { 31803782ecc7SHong Zhang PetscErrorCode ierr; 3181040216a4SHong Zhang Vec x,cmap; 3182040216a4SHong Zhang const PetscInt *is_idx; 3183040216a4SHong Zhang PetscScalar *xarray,*cmaparray; 31849c988bcaSHong Zhang PetscInt ncols,isstart,*idx,m,rstart,*cmap1,count; 3185040216a4SHong Zhang Mat_MPIAIJ *a=(Mat_MPIAIJ*)mat->data; 3186040216a4SHong Zhang Mat B=a->B; 3187040216a4SHong Zhang Vec lvec=a->lvec,lcmap; 3188a31a438cSHong Zhang PetscInt i,cstart,cend,Bn=B->cmap->N; 31898b3fa1f7SHong Zhang MPI_Comm comm; 31903a8d973cSHong Zhang VecScatter Mvctx=a->Mvctx; 31913782ecc7SHong Zhang 31923782ecc7SHong Zhang PetscFunctionBegin; 31938b3fa1f7SHong Zhang ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 3194ddfdf956SHong Zhang ierr = ISGetLocalSize(iscol,&ncols);CHKERRQ(ierr); 31958b3fa1f7SHong Zhang 3196ddfdf956SHong Zhang /* (1) iscol is a sub-column vector of mat, pad it with '-1.' to form a full vector x */ 31978b3fa1f7SHong Zhang ierr = MatCreateVecs(mat,&x,NULL);CHKERRQ(ierr); 31988b3fa1f7SHong Zhang ierr = VecSet(x,-1.0);CHKERRQ(ierr); 31990a351717SHong Zhang ierr = VecDuplicate(x,&cmap);CHKERRQ(ierr); 32000a351717SHong Zhang ierr = VecSet(cmap,-1.0);CHKERRQ(ierr); 32010a351717SHong Zhang 32029c988bcaSHong Zhang /* Get start indices */ 3203ddfdf956SHong Zhang ierr = MPI_Scan(&ncols,&isstart,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 3204ddfdf956SHong Zhang isstart -= ncols; 3205040216a4SHong Zhang ierr = MatGetOwnershipRangeColumn(mat,&cstart,&cend);CHKERRQ(ierr); 3206040216a4SHong Zhang 32078b3fa1f7SHong Zhang ierr = ISGetIndices(iscol,&is_idx);CHKERRQ(ierr); 32088b3fa1f7SHong Zhang ierr = VecGetArray(x,&xarray);CHKERRQ(ierr); 320964efcef9SHong Zhang ierr = VecGetArray(cmap,&cmaparray);CHKERRQ(ierr); 3210feb78a15SHong Zhang ierr = PetscMalloc1(ncols,&idx);CHKERRQ(ierr); 3211ddfdf956SHong Zhang for (i=0; i<ncols; i++) { 32128b3fa1f7SHong Zhang xarray[is_idx[i]-cstart] = (PetscScalar)is_idx[i]; 3213ddfdf956SHong Zhang cmaparray[is_idx[i]-cstart] = i + isstart; /* global index of iscol[i] */ 32149c988bcaSHong Zhang idx[i] = is_idx[i]-cstart; /* local index of iscol[i] */ 32158b3fa1f7SHong Zhang } 32168b3fa1f7SHong Zhang ierr = VecRestoreArray(x,&xarray);CHKERRQ(ierr); 321764efcef9SHong Zhang ierr = VecRestoreArray(cmap,&cmaparray);CHKERRQ(ierr); 32188b3fa1f7SHong Zhang ierr = ISRestoreIndices(iscol,&is_idx);CHKERRQ(ierr); 32198b3fa1f7SHong Zhang 32209c988bcaSHong Zhang /* Get iscol_d */ 32219c988bcaSHong Zhang ierr = ISCreateGeneral(PETSC_COMM_SELF,ncols,idx,PETSC_OWN_POINTER,iscol_d);CHKERRQ(ierr); 3222b6d9b4e0SHong Zhang ierr = ISGetBlockSize(iscol,&i);CHKERRQ(ierr); 3223b6d9b4e0SHong Zhang ierr = ISSetBlockSize(*iscol_d,i);CHKERRQ(ierr); 3224feb78a15SHong Zhang 32259c988bcaSHong Zhang /* Get isrow_d */ 3226feb78a15SHong Zhang ierr = ISGetLocalSize(isrow,&m);CHKERRQ(ierr); 3227feb78a15SHong Zhang rstart = mat->rmap->rstart; 3228feb78a15SHong Zhang ierr = PetscMalloc1(m,&idx);CHKERRQ(ierr); 3229feb78a15SHong Zhang ierr = ISGetIndices(isrow,&is_idx);CHKERRQ(ierr); 32309c988bcaSHong Zhang for (i=0; i<m; i++) idx[i] = is_idx[i]-rstart; 3231feb78a15SHong Zhang ierr = ISRestoreIndices(isrow,&is_idx);CHKERRQ(ierr); 3232feb78a15SHong Zhang 32339c988bcaSHong Zhang ierr = ISCreateGeneral(PETSC_COMM_SELF,m,idx,PETSC_OWN_POINTER,isrow_d);CHKERRQ(ierr); 3234feb78a15SHong Zhang ierr = ISGetBlockSize(isrow,&i);CHKERRQ(ierr); 3235feb78a15SHong Zhang ierr = ISSetBlockSize(*isrow_d,i);CHKERRQ(ierr); 3236feb78a15SHong Zhang 32379c988bcaSHong Zhang /* (2) Scatter x and cmap using aij->Mvctx to get their off-process portions (see MatMult_MPIAIJ) */ 32384b8d542aSHong Zhang ierr = VecScatterBegin(Mvctx,x,lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 32391c645242SHong Zhang ierr = VecScatterEnd(Mvctx,x,lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 3240ddfdf956SHong Zhang 324107250d77SHong Zhang ierr = VecDuplicate(lvec,&lcmap);CHKERRQ(ierr); 324207250d77SHong Zhang 32434b8d542aSHong Zhang ierr = VecScatterBegin(Mvctx,cmap,lcmap,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 32444b8d542aSHong Zhang ierr = VecScatterEnd(Mvctx,cmap,lcmap,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 324564efcef9SHong Zhang 32469c988bcaSHong Zhang /* (3) create sequential iscol_o (a subset of iscol) and isgarray */ 3247ddfdf956SHong Zhang /* off-process column indices */ 32489c988bcaSHong Zhang count = 0; 32499c988bcaSHong Zhang ierr = PetscMalloc1(Bn,&idx);CHKERRQ(ierr); 32509c988bcaSHong Zhang ierr = PetscMalloc1(Bn,&cmap1);CHKERRQ(ierr); 3251feb78a15SHong Zhang 32528b3fa1f7SHong Zhang ierr = VecGetArray(lvec,&xarray);CHKERRQ(ierr); 325364efcef9SHong Zhang ierr = VecGetArray(lcmap,&cmaparray);CHKERRQ(ierr); 32548b3fa1f7SHong Zhang for (i=0; i<Bn; i++) { 3255f73421bfSHong Zhang if (PetscRealPart(xarray[i]) > -1.0) { 32569c988bcaSHong Zhang idx[count] = i; /* local column index in off-diagonal part B */ 32571c645242SHong Zhang cmap1[count] = (PetscInt)PetscRealPart(cmaparray[i]); /* column index in submat */ 32581c645242SHong Zhang count++; 32598b3fa1f7SHong Zhang } 32608b3fa1f7SHong Zhang } 32618b3fa1f7SHong Zhang ierr = VecRestoreArray(lvec,&xarray);CHKERRQ(ierr); 326264efcef9SHong Zhang ierr = VecRestoreArray(lcmap,&cmaparray);CHKERRQ(ierr); 326307250d77SHong Zhang 32649c988bcaSHong Zhang ierr = ISCreateGeneral(PETSC_COMM_SELF,count,idx,PETSC_COPY_VALUES,iscol_o);CHKERRQ(ierr); 3265b6d9b4e0SHong Zhang /* cannot ensure iscol_o has same blocksize as iscol! */ 3266b6d9b4e0SHong Zhang 32679c988bcaSHong Zhang ierr = PetscFree(idx);CHKERRQ(ierr); 32689c988bcaSHong Zhang *garray = cmap1; 32699c988bcaSHong Zhang 32708b3fa1f7SHong Zhang ierr = VecDestroy(&x);CHKERRQ(ierr); 327164efcef9SHong Zhang ierr = VecDestroy(&cmap);CHKERRQ(ierr); 327264efcef9SHong Zhang ierr = VecDestroy(&lcmap);CHKERRQ(ierr); 3273040216a4SHong Zhang PetscFunctionReturn(0); 3274040216a4SHong Zhang } 3275040216a4SHong Zhang 3276b20e2604SHong Zhang /* isrow and iscol have same processor distribution as mat, output *submat is a submatrix of local mat */ 32773b00a383SHong Zhang PetscErrorCode MatCreateSubMatrix_MPIAIJ_SameRowColDist(Mat mat,IS isrow,IS iscol,MatReuse call,Mat *submat) 32783b00a383SHong Zhang { 32793b00a383SHong Zhang PetscErrorCode ierr; 3280b20e2604SHong Zhang Mat_MPIAIJ *a = (Mat_MPIAIJ*)mat->data,*asub; 32811fd43edeSHong Zhang Mat M = NULL; 32823b00a383SHong Zhang MPI_Comm comm; 3283b20e2604SHong Zhang IS iscol_d,isrow_d,iscol_o; 32843b00a383SHong Zhang Mat Asub = NULL,Bsub = NULL; 3285b20e2604SHong Zhang PetscInt n; 32863b00a383SHong Zhang 32873b00a383SHong Zhang PetscFunctionBegin; 32883b00a383SHong Zhang ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 32893b00a383SHong Zhang 32903b00a383SHong Zhang if (call == MAT_REUSE_MATRIX) { 3291b20e2604SHong Zhang /* Retrieve isrow_d, iscol_d and iscol_o from submat */ 32923b00a383SHong Zhang ierr = PetscObjectQuery((PetscObject)*submat,"isrow_d",(PetscObject*)&isrow_d);CHKERRQ(ierr); 32933b00a383SHong Zhang if (!isrow_d) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"isrow_d passed in was not used before, cannot reuse"); 32943b00a383SHong Zhang 32953b00a383SHong Zhang ierr = PetscObjectQuery((PetscObject)*submat,"iscol_d",(PetscObject*)&iscol_d);CHKERRQ(ierr); 32963b00a383SHong Zhang if (!iscol_d) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"iscol_d passed in was not used before, cannot reuse"); 32973b00a383SHong Zhang 32983b00a383SHong Zhang ierr = PetscObjectQuery((PetscObject)*submat,"iscol_o",(PetscObject*)&iscol_o);CHKERRQ(ierr); 32993b00a383SHong Zhang if (!iscol_o) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"iscol_o passed in was not used before, cannot reuse"); 33003b00a383SHong Zhang 3301b20e2604SHong Zhang /* Update diagonal and off-diagonal portions of submat */ 3302b20e2604SHong Zhang asub = (Mat_MPIAIJ*)(*submat)->data; 3303b20e2604SHong Zhang ierr = MatCreateSubMatrix_SeqAIJ(a->A,isrow_d,iscol_d,PETSC_DECIDE,MAT_REUSE_MATRIX,&asub->A);CHKERRQ(ierr); 33047cfce09cSHong Zhang ierr = ISGetLocalSize(iscol_o,&n);CHKERRQ(ierr); 33057cfce09cSHong Zhang if (n) { 3306b20e2604SHong Zhang ierr = MatCreateSubMatrix_SeqAIJ(a->B,isrow_d,iscol_o,PETSC_DECIDE,MAT_REUSE_MATRIX,&asub->B);CHKERRQ(ierr); 33077cfce09cSHong Zhang } 33083b00a383SHong Zhang ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 33093b00a383SHong Zhang ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 33103b00a383SHong Zhang 33113b00a383SHong Zhang } else { /* call == MAT_INITIAL_MATRIX) */ 33129c988bcaSHong Zhang const PetscInt *garray; 3313b20e2604SHong Zhang PetscInt BsubN; 33143b00a383SHong Zhang 3315b20e2604SHong Zhang /* Create isrow_d, iscol_d, iscol_o and isgarray (replace isgarray with array?) */ 33169c988bcaSHong Zhang ierr = ISGetSeqIS_SameColDist_Private(mat,isrow,iscol,&isrow_d,&iscol_d,&iscol_o,&garray);CHKERRQ(ierr); 33173b00a383SHong Zhang 3318b20e2604SHong Zhang /* Create local submatrices Asub and Bsub */ 33197cfce09cSHong Zhang ierr = MatCreateSubMatrix_SeqAIJ(a->A,isrow_d,iscol_d,PETSC_DECIDE,MAT_INITIAL_MATRIX,&Asub);CHKERRQ(ierr); 33207cfce09cSHong Zhang ierr = MatCreateSubMatrix_SeqAIJ(a->B,isrow_d,iscol_o,PETSC_DECIDE,MAT_INITIAL_MATRIX,&Bsub);CHKERRQ(ierr); 33213b00a383SHong Zhang 33229c988bcaSHong Zhang /* Create submatrix M */ 33239c988bcaSHong Zhang ierr = MatCreateMPIAIJWithSeqAIJ(comm,Asub,Bsub,garray,&M);CHKERRQ(ierr); 33243b00a383SHong Zhang 3325b20e2604SHong Zhang /* If Bsub has empty columns, compress iscol_o such that it will retrieve condensed Bsub from a->B during reuse */ 3326b20e2604SHong Zhang asub = (Mat_MPIAIJ*)M->data; 33277cfce09cSHong Zhang 33289c988bcaSHong Zhang ierr = ISGetLocalSize(iscol_o,&BsubN);CHKERRQ(ierr); 3329b20e2604SHong Zhang n = asub->B->cmap->N; 3330b20e2604SHong Zhang if (BsubN > n) { 33317cfce09cSHong Zhang /* This case can be tested using ~petsc/src/tao/bound/examples/tutorials/runplate2_3 */ 33327cfce09cSHong Zhang const PetscInt *idx; 33339c988bcaSHong Zhang PetscInt i,j,*idx_new,*subgarray = asub->garray; 33349c988bcaSHong Zhang ierr = PetscInfo2(M,"submatrix Bn %D != BsubN %D, update iscol_o\n",n,BsubN);CHKERRQ(ierr); 33357cfce09cSHong Zhang 3336b20e2604SHong Zhang ierr = PetscMalloc1(n,&idx_new);CHKERRQ(ierr); 33377cfce09cSHong Zhang j = 0; 3338b20e2604SHong Zhang ierr = ISGetIndices(iscol_o,&idx);CHKERRQ(ierr); 3339b20e2604SHong Zhang for (i=0; i<n; i++) { 33407cfce09cSHong Zhang if (j >= BsubN) break; 33419c988bcaSHong Zhang while (subgarray[i] > garray[j]) j++; 33427cfce09cSHong Zhang 33439c988bcaSHong Zhang if (subgarray[i] == garray[j]) { 33447cfce09cSHong Zhang idx_new[i] = idx[j++]; 33459c988bcaSHong Zhang } else SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"subgarray[%D]=%D cannot < garray[%D]=%D",i,subgarray[i],j,garray[j]); 33467cfce09cSHong Zhang } 33477cfce09cSHong Zhang ierr = ISRestoreIndices(iscol_o,&idx);CHKERRQ(ierr); 33487cfce09cSHong Zhang 33497cfce09cSHong Zhang ierr = ISDestroy(&iscol_o);CHKERRQ(ierr); 3350b20e2604SHong Zhang ierr = ISCreateGeneral(PETSC_COMM_SELF,n,idx_new,PETSC_OWN_POINTER,&iscol_o);CHKERRQ(ierr); 33517cfce09cSHong Zhang 3352b20e2604SHong Zhang } else if (BsubN < n) { 3353b20e2604SHong Zhang SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Columns of Bsub cannot be smaller than B's",BsubN,asub->B->cmap->N); 3354b20e2604SHong Zhang } 33557cfce09cSHong Zhang 33569c988bcaSHong Zhang ierr = PetscFree(garray);CHKERRQ(ierr); 3357b20e2604SHong Zhang *submat = M; 33583b00a383SHong Zhang 3359e489de8fSHong Zhang /* Save isrow_d, iscol_d and iscol_o used in processor for next request */ 33603b00a383SHong Zhang ierr = PetscObjectCompose((PetscObject)M,"isrow_d",(PetscObject)isrow_d);CHKERRQ(ierr); 33613b00a383SHong Zhang ierr = ISDestroy(&isrow_d);CHKERRQ(ierr); 33623b00a383SHong Zhang 33633b00a383SHong Zhang ierr = PetscObjectCompose((PetscObject)M,"iscol_d",(PetscObject)iscol_d);CHKERRQ(ierr); 33643b00a383SHong Zhang ierr = ISDestroy(&iscol_d);CHKERRQ(ierr); 33653b00a383SHong Zhang 33663b00a383SHong Zhang ierr = PetscObjectCompose((PetscObject)M,"iscol_o",(PetscObject)iscol_o);CHKERRQ(ierr); 33673b00a383SHong Zhang ierr = ISDestroy(&iscol_o);CHKERRQ(ierr); 33683b00a383SHong Zhang } 33693b00a383SHong Zhang PetscFunctionReturn(0); 33703b00a383SHong Zhang } 33713b00a383SHong Zhang 33723782ecc7SHong Zhang PetscErrorCode MatCreateSubMatrix_MPIAIJ(Mat mat,IS isrow,IS iscol,MatReuse call,Mat *newmat) 33733782ecc7SHong Zhang { 33743782ecc7SHong Zhang PetscErrorCode ierr; 33751358a193SHong Zhang IS iscol_local=NULL,isrow_d; 33763782ecc7SHong Zhang PetscInt csize; 337718e627e3SHong Zhang PetscInt n,i,j,start,end; 33784a3daf6eSHong Zhang PetscBool sameRowDist=PETSC_FALSE,sameDist[2],tsameDist[2]; 33793782ecc7SHong Zhang MPI_Comm comm; 33803782ecc7SHong Zhang 33813782ecc7SHong Zhang PetscFunctionBegin; 3382bcae8d28SHong Zhang /* If isrow has same processor distribution as mat, 3383a31a438cSHong Zhang call MatCreateSubMatrix_MPIAIJ_SameRowDist() to avoid using a hash table with global size of iscol */ 33848f69fa7bSHong Zhang if (call == MAT_REUSE_MATRIX) { 3385d5761cdaSHong Zhang ierr = PetscObjectQuery((PetscObject)*newmat,"isrow_d",(PetscObject*)&isrow_d);CHKERRQ(ierr); 3386d5761cdaSHong Zhang if (isrow_d) { 3387d5761cdaSHong Zhang sameRowDist = PETSC_TRUE; 3388d5761cdaSHong Zhang tsameDist[1] = PETSC_TRUE; /* sameColDist */ 3389d5761cdaSHong Zhang } else { 33908f69fa7bSHong Zhang ierr = PetscObjectQuery((PetscObject)*newmat,"SubIScol",(PetscObject*)&iscol_local);CHKERRQ(ierr); 3391d5761cdaSHong Zhang if (iscol_local) { 3392d5761cdaSHong Zhang sameRowDist = PETSC_TRUE; 3393d5761cdaSHong Zhang tsameDist[1] = PETSC_FALSE; /* !sameColDist */ 3394d5761cdaSHong Zhang } 3395d5761cdaSHong Zhang } 33968f69fa7bSHong Zhang } else { 3397e489de8fSHong Zhang /* Check if isrow has same processor distribution as mat */ 339818e627e3SHong Zhang sameDist[0] = PETSC_FALSE; 33993782ecc7SHong Zhang ierr = ISGetLocalSize(isrow,&n);CHKERRQ(ierr); 34003782ecc7SHong Zhang if (!n) { 340118e627e3SHong Zhang sameDist[0] = PETSC_TRUE; 34023782ecc7SHong Zhang } else { 34033782ecc7SHong Zhang ierr = ISGetMinMax(isrow,&i,&j);CHKERRQ(ierr); 340418e627e3SHong Zhang ierr = MatGetOwnershipRange(mat,&start,&end);CHKERRQ(ierr); 340518e627e3SHong Zhang if (i >= start && j < end) { 340618e627e3SHong Zhang sameDist[0] = PETSC_TRUE; 34073782ecc7SHong Zhang } 34088f69fa7bSHong Zhang } 34093782ecc7SHong Zhang 3410e489de8fSHong Zhang /* Check if iscol has same processor distribution as mat */ 341118e627e3SHong Zhang sameDist[1] = PETSC_FALSE; 341218e627e3SHong Zhang ierr = ISGetLocalSize(iscol,&n);CHKERRQ(ierr); 341318e627e3SHong Zhang if (!n) { 341418e627e3SHong Zhang sameDist[1] = PETSC_TRUE; 341518e627e3SHong Zhang } else { 341618e627e3SHong Zhang ierr = ISGetMinMax(iscol,&i,&j);CHKERRQ(ierr); 341718e627e3SHong Zhang ierr = MatGetOwnershipRangeColumn(mat,&start,&end);CHKERRQ(ierr); 341818e627e3SHong Zhang if (i >= start && j < end) sameDist[1] = PETSC_TRUE; 341918e627e3SHong Zhang } 342018e627e3SHong Zhang 342118e627e3SHong Zhang ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 342218e627e3SHong Zhang ierr = MPIU_Allreduce(&sameDist,&tsameDist,2,MPIU_BOOL,MPI_LAND,comm);CHKERRQ(ierr); 342318e627e3SHong Zhang sameRowDist = tsameDist[0]; 342418e627e3SHong Zhang } 342518e627e3SHong Zhang 342618e627e3SHong Zhang if (sameRowDist) { 3427b20e2604SHong Zhang if (tsameDist[1]) { /* sameRowDist & sameColDist */ 34283b00a383SHong Zhang /* isrow and iscol have same processor distribution as mat */ 34293b00a383SHong Zhang ierr = MatCreateSubMatrix_MPIAIJ_SameRowColDist(mat,isrow,iscol,call,newmat);CHKERRQ(ierr); 34301358a193SHong Zhang PetscFunctionReturn(0); 3431b20e2604SHong Zhang } else { /* sameRowDist */ 34323b00a383SHong Zhang /* isrow has same processor distribution as mat */ 34331358a193SHong Zhang if (call == MAT_INITIAL_MATRIX) { 34341358a193SHong Zhang PetscBool sorted; 34351358a193SHong Zhang ierr = ISGetSeqIS_Private(mat,iscol,&iscol_local);CHKERRQ(ierr); 34361358a193SHong Zhang ierr = ISGetLocalSize(iscol_local,&n);CHKERRQ(ierr); /* local size of iscol_local = global columns of newmat */ 34371358a193SHong Zhang ierr = ISGetSize(iscol,&i);CHKERRQ(ierr); 34381358a193SHong Zhang if (n != i) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"n %d != size of iscol %d",n,i); 34391358a193SHong Zhang 34401358a193SHong Zhang ierr = ISSorted(iscol_local,&sorted);CHKERRQ(ierr); 34411358a193SHong Zhang if (sorted) { 34421358a193SHong Zhang /* MatCreateSubMatrix_MPIAIJ_SameRowDist() requires iscol_local be sorted; it can have duplicate indices */ 34431358a193SHong Zhang ierr = MatCreateSubMatrix_MPIAIJ_SameRowDist(mat,isrow,iscol,iscol_local,MAT_INITIAL_MATRIX,newmat);CHKERRQ(ierr); 34443782ecc7SHong Zhang PetscFunctionReturn(0); 34453782ecc7SHong Zhang } 34461358a193SHong Zhang } else { /* call == MAT_REUSE_MATRIX */ 344748c0d076SHong Zhang IS iscol_sub; 344848c0d076SHong Zhang ierr = PetscObjectQuery((PetscObject)*newmat,"SubIScol",(PetscObject*)&iscol_sub);CHKERRQ(ierr); 344948c0d076SHong Zhang if (iscol_sub) { 345048c0d076SHong Zhang ierr = MatCreateSubMatrix_MPIAIJ_SameRowDist(mat,isrow,iscol,NULL,call,newmat);CHKERRQ(ierr); 345148c0d076SHong Zhang PetscFunctionReturn(0); 345248c0d076SHong Zhang } 34531358a193SHong Zhang } 34541358a193SHong Zhang } 34551358a193SHong Zhang } 34563782ecc7SHong Zhang 3457bcae8d28SHong Zhang /* General case: iscol -> iscol_local which has global size of iscol */ 34583782ecc7SHong Zhang if (call == MAT_REUSE_MATRIX) { 34593782ecc7SHong Zhang ierr = PetscObjectQuery((PetscObject)*newmat,"ISAllGather",(PetscObject*)&iscol_local);CHKERRQ(ierr); 34603782ecc7SHong Zhang if (!iscol_local) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Submatrix passed in was not used before, cannot reuse"); 34613782ecc7SHong Zhang } else { 34621358a193SHong Zhang if (!iscol_local) { 34638b3fa1f7SHong Zhang ierr = ISGetSeqIS_Private(mat,iscol,&iscol_local);CHKERRQ(ierr); 34643782ecc7SHong Zhang } 34651358a193SHong Zhang } 34663782ecc7SHong Zhang 34673782ecc7SHong Zhang ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr); 3468618cbb4aSHong Zhang ierr = MatCreateSubMatrix_MPIAIJ_nonscalable(mat,isrow,iscol_local,csize,call,newmat);CHKERRQ(ierr); 34698f69fa7bSHong Zhang 3470b79d0421SJed Brown if (call == MAT_INITIAL_MATRIX) { 3471b79d0421SJed Brown ierr = PetscObjectCompose((PetscObject)*newmat,"ISAllGather",(PetscObject)iscol_local);CHKERRQ(ierr); 34726bf464f9SBarry Smith ierr = ISDestroy(&iscol_local);CHKERRQ(ierr); 3473b79d0421SJed Brown } 34744aa3045dSJed Brown PetscFunctionReturn(0); 34754aa3045dSJed Brown } 34764aa3045dSJed Brown 3477feb78a15SHong Zhang /*@C 3478feb78a15SHong Zhang MatCreateMPIAIJWithSeqAIJ - creates a MPIAIJ matrix using SeqAIJ matrices that contain the "diagonal" 3479feb78a15SHong Zhang and "off-diagonal" part of the matrix in CSR format. 3480feb78a15SHong Zhang 3481d083f849SBarry Smith Collective 3482feb78a15SHong Zhang 3483feb78a15SHong Zhang Input Parameters: 3484feb78a15SHong Zhang + comm - MPI communicator 3485feb78a15SHong Zhang . A - "diagonal" portion of matrix 3486b20e2604SHong Zhang . B - "off-diagonal" portion of matrix, may have empty columns, will be destroyed by this routine 3487feb78a15SHong Zhang - garray - global index of B columns 3488feb78a15SHong Zhang 3489feb78a15SHong Zhang Output Parameter: 3490d5761cdaSHong Zhang . mat - the matrix, with input A as its local diagonal matrix 3491feb78a15SHong Zhang Level: advanced 3492feb78a15SHong Zhang 3493feb78a15SHong Zhang Notes: 3494d5761cdaSHong Zhang See MatCreateAIJ() for the definition of "diagonal" and "off-diagonal" portion of the matrix. 3495d5761cdaSHong Zhang A becomes part of output mat, B is destroyed by this routine. The user cannot use A and B anymore. 3496feb78a15SHong Zhang 3497feb78a15SHong Zhang .seealso: MatCreateMPIAIJWithSplitArrays() 3498feb78a15SHong Zhang @*/ 3499feb78a15SHong Zhang PetscErrorCode MatCreateMPIAIJWithSeqAIJ(MPI_Comm comm,Mat A,Mat B,const PetscInt garray[],Mat *mat) 3500feb78a15SHong Zhang { 3501feb78a15SHong Zhang PetscErrorCode ierr; 3502feb78a15SHong Zhang Mat_MPIAIJ *maij; 3503e489de8fSHong Zhang Mat_SeqAIJ *b=(Mat_SeqAIJ*)B->data,*bnew; 3504a5348796SHong Zhang PetscInt *oi=b->i,*oj=b->j,i,nz,col; 3505feb78a15SHong Zhang PetscScalar *oa=b->a; 3506e489de8fSHong Zhang Mat Bnew; 3507feb78a15SHong Zhang PetscInt m,n,N; 3508feb78a15SHong Zhang 3509feb78a15SHong Zhang PetscFunctionBegin; 3510feb78a15SHong Zhang ierr = MatCreate(comm,mat);CHKERRQ(ierr); 3511feb78a15SHong Zhang ierr = MatGetSize(A,&m,&n);CHKERRQ(ierr); 3512e489de8fSHong Zhang if (m != B->rmap->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Am %D != Bm %D",m,B->rmap->N); 3513e489de8fSHong Zhang if (A->rmap->bs != B->rmap->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"A row bs %D != B row bs %D",A->rmap->bs,B->rmap->bs); 3514b6d9b4e0SHong Zhang /* remove check below; When B is created using iscol_o from ISGetSeqIS_SameColDist_Private(), its bs may not be same as A */ 3515b6d9b4e0SHong Zhang /* if (A->cmap->bs != B->cmap->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"A column bs %D != B column bs %D",A->cmap->bs,B->cmap->bs); */ 3516feb78a15SHong Zhang 3517e489de8fSHong Zhang /* Get global columns of mat */ 3518451f1979SBarry Smith ierr = MPIU_Allreduce(&n,&N,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 3519feb78a15SHong Zhang 3520feb78a15SHong Zhang ierr = MatSetSizes(*mat,m,n,PETSC_DECIDE,N);CHKERRQ(ierr); 3521feb78a15SHong Zhang ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr); 3522e489de8fSHong Zhang ierr = MatSetBlockSizes(*mat,A->rmap->bs,A->cmap->bs);CHKERRQ(ierr); 3523feb78a15SHong Zhang maij = (Mat_MPIAIJ*)(*mat)->data; 3524feb78a15SHong Zhang 3525feb78a15SHong Zhang (*mat)->preallocated = PETSC_TRUE; 3526feb78a15SHong Zhang 3527feb78a15SHong Zhang ierr = PetscLayoutSetUp((*mat)->rmap);CHKERRQ(ierr); 3528feb78a15SHong Zhang ierr = PetscLayoutSetUp((*mat)->cmap);CHKERRQ(ierr); 3529feb78a15SHong Zhang 3530e489de8fSHong Zhang /* Set A as diagonal portion of *mat */ 3531feb78a15SHong Zhang maij->A = A; 3532feb78a15SHong Zhang 3533a5348796SHong Zhang nz = oi[m]; 3534a5348796SHong Zhang for (i=0; i<nz; i++) { 3535a5348796SHong Zhang col = oj[i]; 3536a5348796SHong Zhang oj[i] = garray[col]; 3537feb78a15SHong Zhang } 3538feb78a15SHong Zhang 3539e489de8fSHong Zhang /* Set Bnew as off-diagonal portion of *mat */ 3540e489de8fSHong Zhang ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,m,N,oi,oj,oa,&Bnew);CHKERRQ(ierr); 3541e489de8fSHong Zhang bnew = (Mat_SeqAIJ*)Bnew->data; 3542e489de8fSHong Zhang bnew->maxnz = b->maxnz; /* allocated nonzeros of B */ 3543e489de8fSHong Zhang maij->B = Bnew; 3544d5761cdaSHong Zhang 3545e489de8fSHong Zhang if (B->rmap->N != Bnew->rmap->N) SETERRQ2(PETSC_COMM_SELF,0,"BN %d != BnewN %d",B->rmap->N,Bnew->rmap->N); 3546d5761cdaSHong Zhang 3547e489de8fSHong Zhang b->singlemalloc = PETSC_FALSE; /* B arrays are shared by Bnew */ 3548d5761cdaSHong Zhang b->free_a = PETSC_FALSE; 3549d5761cdaSHong Zhang b->free_ij = PETSC_FALSE; 3550d5761cdaSHong Zhang ierr = MatDestroy(&B);CHKERRQ(ierr); 3551d5761cdaSHong Zhang 3552e489de8fSHong Zhang bnew->singlemalloc = PETSC_TRUE; /* arrays will be freed by MatDestroy(&Bnew) */ 3553e489de8fSHong Zhang bnew->free_a = PETSC_TRUE; 3554e489de8fSHong Zhang bnew->free_ij = PETSC_TRUE; 3555feb78a15SHong Zhang 3556a5348796SHong Zhang /* condense columns of maij->B */ 3557feb78a15SHong Zhang ierr = MatSetOption(*mat,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr); 3558feb78a15SHong Zhang ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3559feb78a15SHong Zhang ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3560feb78a15SHong Zhang ierr = MatSetOption(*mat,MAT_NO_OFF_PROC_ENTRIES,PETSC_FALSE);CHKERRQ(ierr); 3561feb78a15SHong Zhang ierr = MatSetOption(*mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 3562feb78a15SHong Zhang PetscFunctionReturn(0); 3563feb78a15SHong Zhang } 3564feb78a15SHong Zhang 3565ef514586SHong Zhang extern PetscErrorCode MatCreateSubMatrices_MPIAIJ_SingleIS_Local(Mat,PetscInt,const IS[],const IS[],MatReuse,PetscBool,Mat*); 35664aa3045dSJed Brown 35671358a193SHong Zhang PetscErrorCode MatCreateSubMatrix_MPIAIJ_SameRowDist(Mat mat,IS isrow,IS iscol,IS iscol_local,MatReuse call,Mat *newmat) 3568a0ff6018SBarry Smith { 3569dfbe8321SBarry Smith PetscErrorCode ierr; 357098b658c4SHong Zhang PetscInt i,m,n,rstart,row,rend,nz,j,bs,cbs; 357185f27616SHong Zhang PetscInt *ii,*jj,nlocal,*dlens,*olens,dlen,olen,jend,mglobal; 357298b658c4SHong Zhang Mat_MPIAIJ *a=(Mat_MPIAIJ*)mat->data; 35731fd43edeSHong Zhang Mat M,Msub,B=a->B; 357498b658c4SHong Zhang MatScalar *aa; 357500e6dbe6SBarry Smith Mat_SeqAIJ *aij; 3576a31a438cSHong Zhang PetscInt *garray = a->garray,*colsub,Ncols; 357798b658c4SHong Zhang PetscInt count,Bn=B->cmap->N,cstart=mat->cmap->rstart,cend=mat->cmap->rend; 357898b658c4SHong Zhang IS iscol_sub,iscmap; 357998b658c4SHong Zhang const PetscInt *is_idx,*cmap; 358018e627e3SHong Zhang PetscBool allcolumns=PETSC_FALSE; 3581a31a438cSHong Zhang MPI_Comm comm; 35827e2c5f70SBarry Smith 3583a0ff6018SBarry Smith PetscFunctionBegin; 35848b3fa1f7SHong Zhang ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 358585f27616SHong Zhang 3586d5761cdaSHong Zhang if (call == MAT_REUSE_MATRIX) { 3587d5761cdaSHong Zhang ierr = PetscObjectQuery((PetscObject)*newmat,"SubIScol",(PetscObject*)&iscol_sub);CHKERRQ(ierr); 3588d5761cdaSHong Zhang if (!iscol_sub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"SubIScol passed in was not used before, cannot reuse"); 3589d5761cdaSHong Zhang ierr = ISGetLocalSize(iscol_sub,&count);CHKERRQ(ierr); 3590d5761cdaSHong Zhang 3591d5761cdaSHong Zhang ierr = PetscObjectQuery((PetscObject)*newmat,"Subcmap",(PetscObject*)&iscmap);CHKERRQ(ierr); 3592d5761cdaSHong Zhang if (!iscmap) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Subcmap passed in was not used before, cannot reuse"); 3593d5761cdaSHong Zhang 3594d5761cdaSHong Zhang ierr = PetscObjectQuery((PetscObject)*newmat,"SubMatrix",(PetscObject*)&Msub);CHKERRQ(ierr); 3595d5761cdaSHong Zhang if (!Msub) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Submatrix passed in was not used before, cannot reuse"); 3596d5761cdaSHong Zhang 3597d5761cdaSHong Zhang ierr = MatCreateSubMatrices_MPIAIJ_SingleIS_Local(mat,1,&isrow,&iscol_sub,MAT_REUSE_MATRIX,PETSC_FALSE,&Msub);CHKERRQ(ierr); 3598d5761cdaSHong Zhang 3599d5761cdaSHong Zhang } else { /* call == MAT_INITIAL_MATRIX) */ 36003b00a383SHong Zhang PetscBool flg; 36013b00a383SHong Zhang 3602bcae8d28SHong Zhang ierr = ISGetLocalSize(iscol,&n);CHKERRQ(ierr); 3603a31a438cSHong Zhang ierr = ISGetSize(iscol,&Ncols);CHKERRQ(ierr); 3604bcae8d28SHong Zhang 36053b00a383SHong Zhang /* (1) iscol -> nonscalable iscol_local */ 3606366a327dSHong Zhang /* Check for special case: each processor gets entire matrix columns */ 3607366a327dSHong Zhang ierr = ISIdentity(iscol_local,&flg);CHKERRQ(ierr); 3608366a327dSHong Zhang if (flg && n == mat->cmap->N) allcolumns = PETSC_TRUE; 3609366a327dSHong Zhang if (allcolumns) { 3610366a327dSHong Zhang iscol_sub = iscol_local; 3611366a327dSHong Zhang ierr = PetscObjectReference((PetscObject)iscol_local);CHKERRQ(ierr); 3612366a327dSHong Zhang ierr = ISCreateStride(PETSC_COMM_SELF,n,0,1,&iscmap);CHKERRQ(ierr); 3613366a327dSHong Zhang 36143b00a383SHong Zhang } else { 36151358a193SHong Zhang /* (2) iscol_local -> iscol_sub and iscmap. Implementation below requires iscol_local be sorted, it can have duplicate indices */ 3616244c7f15SHong Zhang PetscInt *idx,*cmap1,k; 3617b20e2604SHong Zhang ierr = PetscMalloc1(Ncols,&idx);CHKERRQ(ierr); 3618b20e2604SHong Zhang ierr = PetscMalloc1(Ncols,&cmap1);CHKERRQ(ierr); 3619bcae8d28SHong Zhang ierr = ISGetIndices(iscol_local,&is_idx);CHKERRQ(ierr); 36208d2139bdSHong Zhang count = 0; 3621a31a438cSHong Zhang k = 0; 3622a31a438cSHong Zhang for (i=0; i<Ncols; i++) { 3623a31a438cSHong Zhang j = is_idx[i]; 3624a31a438cSHong Zhang if (j >= cstart && j < cend) { 3625a31a438cSHong Zhang /* diagonal part of mat */ 36268d2139bdSHong Zhang idx[count] = j; 3627366a327dSHong Zhang cmap1[count++] = i; /* column index in submat */ 36284a3daf6eSHong Zhang } else if (Bn) { 3629a31a438cSHong Zhang /* off-diagonal part of mat */ 3630a31a438cSHong Zhang if (j == garray[k]) { 36318d2139bdSHong Zhang idx[count] = j; 3632a31a438cSHong Zhang cmap1[count++] = i; /* column index in submat */ 3633a31a438cSHong Zhang } else if (j > garray[k]) { 3634a31a438cSHong Zhang while (j > garray[k] && k < Bn-1) k++; 3635a31a438cSHong Zhang if (j == garray[k]) { 3636a31a438cSHong Zhang idx[count] = j; 3637a31a438cSHong Zhang cmap1[count++] = i; /* column index in submat */ 36388d2139bdSHong Zhang } 36398d2139bdSHong Zhang } 36408d2139bdSHong Zhang } 36418d2139bdSHong Zhang } 3642bcae8d28SHong Zhang ierr = ISRestoreIndices(iscol_local,&is_idx);CHKERRQ(ierr); 36438d2139bdSHong Zhang 3644b20e2604SHong Zhang ierr = ISCreateGeneral(PETSC_COMM_SELF,count,idx,PETSC_OWN_POINTER,&iscol_sub);CHKERRQ(ierr); 3645b6d9b4e0SHong Zhang ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 3646b6d9b4e0SHong Zhang ierr = ISSetBlockSize(iscol_sub,cbs);CHKERRQ(ierr); 3647b6d9b4e0SHong Zhang 3648b20e2604SHong Zhang ierr = ISCreateGeneral(PetscObjectComm((PetscObject)iscol_local),count,cmap1,PETSC_OWN_POINTER,&iscmap);CHKERRQ(ierr); 3649a31a438cSHong Zhang } 36508b3fa1f7SHong Zhang 36513b00a383SHong Zhang /* (3) Create sequential Msub */ 3652366a327dSHong Zhang ierr = MatCreateSubMatrices_MPIAIJ_SingleIS_Local(mat,1,&isrow,&iscol_sub,MAT_INITIAL_MATRIX,allcolumns,&Msub);CHKERRQ(ierr); 3653d5761cdaSHong Zhang } 36548d2139bdSHong Zhang 3655bcae8d28SHong Zhang ierr = ISGetLocalSize(iscol_sub,&count);CHKERRQ(ierr); 365698b658c4SHong Zhang aij = (Mat_SeqAIJ*)(Msub)->data; 365798b658c4SHong Zhang ii = aij->i; 365898b658c4SHong Zhang ierr = ISGetIndices(iscmap,&cmap);CHKERRQ(ierr); 3659a0ff6018SBarry Smith 3660a0ff6018SBarry Smith /* 3661a0ff6018SBarry Smith m - number of local rows 3662a31a438cSHong Zhang Ncols - number of columns (same on all processors) 3663a0ff6018SBarry Smith rstart - first row in new global matrix generated 3664a0ff6018SBarry Smith */ 366515b2185cSHong Zhang ierr = MatGetSize(Msub,&m,NULL);CHKERRQ(ierr); 366698b658c4SHong Zhang 36673b00a383SHong Zhang if (call == MAT_INITIAL_MATRIX) { 36683b00a383SHong Zhang /* (4) Create parallel newmat */ 366998b658c4SHong Zhang PetscMPIInt rank,size; 3670bcae8d28SHong Zhang PetscInt csize; 367198b658c4SHong Zhang 367298b658c4SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 367398b658c4SHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 367400e6dbe6SBarry Smith 3675a0ff6018SBarry Smith /* 367600e6dbe6SBarry Smith Determine the number of non-zeros in the diagonal and off-diagonal 367700e6dbe6SBarry Smith portions of the matrix in order to do correct preallocation 3678a0ff6018SBarry Smith */ 367900e6dbe6SBarry Smith 368000e6dbe6SBarry Smith /* first get start and end of "diagonal" columns */ 3681bcae8d28SHong Zhang ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr); 36826a6a5d1dSBarry Smith if (csize == PETSC_DECIDE) { 3683ab50ec6bSBarry Smith ierr = ISGetSize(isrow,&mglobal);CHKERRQ(ierr); 3684a31a438cSHong Zhang if (mglobal == Ncols) { /* square matrix */ 3685e2c4fddaSBarry Smith nlocal = m; 36866a6a5d1dSBarry Smith } else { 3687a31a438cSHong Zhang nlocal = Ncols/size + ((Ncols % size) > rank); 3688ab50ec6bSBarry Smith } 3689ab50ec6bSBarry Smith } else { 36906a6a5d1dSBarry Smith nlocal = csize; 36916a6a5d1dSBarry Smith } 3692b1d57f15SBarry Smith ierr = MPI_Scan(&nlocal,&rend,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 369300e6dbe6SBarry Smith rstart = rend - nlocal; 3694a31a438cSHong Zhang if (rank == size - 1 && rend != Ncols) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local column sizes %D do not add up to total number of columns %D",rend,Ncols); 369500e6dbe6SBarry Smith 369600e6dbe6SBarry Smith /* next, compute all the lengths */ 369798b658c4SHong Zhang jj = aij->j; 3698854ce69bSBarry Smith ierr = PetscMalloc1(2*m+1,&dlens);CHKERRQ(ierr); 369900e6dbe6SBarry Smith olens = dlens + m; 370000e6dbe6SBarry Smith for (i=0; i<m; i++) { 370100e6dbe6SBarry Smith jend = ii[i+1] - ii[i]; 370200e6dbe6SBarry Smith olen = 0; 370300e6dbe6SBarry Smith dlen = 0; 370400e6dbe6SBarry Smith for (j=0; j<jend; j++) { 370515b2185cSHong Zhang if (cmap[*jj] < rstart || cmap[*jj] >= rend) olen++; 370600e6dbe6SBarry Smith else dlen++; 370700e6dbe6SBarry Smith jj++; 370800e6dbe6SBarry Smith } 370900e6dbe6SBarry Smith olens[i] = olen; 371000e6dbe6SBarry Smith dlens[i] = dlen; 371100e6dbe6SBarry Smith } 3712b6d9b4e0SHong Zhang 3713b6d9b4e0SHong Zhang ierr = ISGetBlockSize(isrow,&bs);CHKERRQ(ierr); 3714b6d9b4e0SHong Zhang ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 371598b658c4SHong Zhang 3716f69a0ea3SMatthew Knepley ierr = MatCreate(comm,&M);CHKERRQ(ierr); 3717a31a438cSHong Zhang ierr = MatSetSizes(M,m,nlocal,PETSC_DECIDE,Ncols);CHKERRQ(ierr); 3718a2f3521dSMark F. Adams ierr = MatSetBlockSizes(M,bs,cbs);CHKERRQ(ierr); 37197adad957SLisandro Dalcin ierr = MatSetType(M,((PetscObject)mat)->type_name);CHKERRQ(ierr); 3720e2d9671bSKris Buschelman ierr = MatMPIAIJSetPreallocation(M,0,dlens,0,olens);CHKERRQ(ierr); 3721606d414cSSatish Balay ierr = PetscFree(dlens);CHKERRQ(ierr); 3722d5761cdaSHong Zhang 3723d5761cdaSHong Zhang } else { /* call == MAT_REUSE_MATRIX */ 3724a0ff6018SBarry Smith M = *newmat; 372598b658c4SHong Zhang ierr = MatGetLocalSize(M,&i,NULL);CHKERRQ(ierr); 372698b658c4SHong Zhang if (i != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Previous matrix must be same size/layout as request"); 3727a0ff6018SBarry Smith ierr = MatZeroEntries(M);CHKERRQ(ierr); 3728c48de900SBarry Smith /* 3729c48de900SBarry Smith The next two lines are needed so we may call MatSetValues_MPIAIJ() below directly, 3730c48de900SBarry Smith rather than the slower MatSetValues(). 3731c48de900SBarry Smith */ 3732c48de900SBarry Smith M->was_assembled = PETSC_TRUE; 3733c48de900SBarry Smith M->assembled = PETSC_FALSE; 3734a0ff6018SBarry Smith } 3735548ecf4dSHong Zhang 37363b00a383SHong Zhang /* (5) Set values of Msub to *newmat */ 373798b658c4SHong Zhang ierr = PetscMalloc1(count,&colsub);CHKERRQ(ierr); 373898b658c4SHong Zhang ierr = MatGetOwnershipRange(M,&rstart,NULL);CHKERRQ(ierr); 373998b658c4SHong Zhang 374098b658c4SHong Zhang jj = aij->j; 374198b658c4SHong Zhang aa = aij->a; 3742a0ff6018SBarry Smith for (i=0; i<m; i++) { 3743a0ff6018SBarry Smith row = rstart + i; 374400e6dbe6SBarry Smith nz = ii[i+1] - ii[i]; 374515b2185cSHong Zhang for (j=0; j<nz; j++) colsub[j] = cmap[jj[j]]; 374615b2185cSHong Zhang ierr = MatSetValues_MPIAIJ(M,1,&row,nz,colsub,aa,INSERT_VALUES);CHKERRQ(ierr); 374715b2185cSHong Zhang jj += nz; aa += nz; 3748a0ff6018SBarry Smith } 374998b658c4SHong Zhang ierr = ISRestoreIndices(iscmap,&cmap);CHKERRQ(ierr); 3750a0ff6018SBarry Smith 3751a0ff6018SBarry Smith ierr = MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3752a0ff6018SBarry Smith ierr = MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3753fee21e36SBarry Smith 375498b658c4SHong Zhang ierr = PetscFree(colsub);CHKERRQ(ierr); 375598b658c4SHong Zhang 375698b658c4SHong Zhang /* save Msub, iscol_sub and iscmap used in processor for next request */ 3757fee21e36SBarry Smith if (call == MAT_INITIAL_MATRIX) { 37583b00a383SHong Zhang *newmat = M; 3759d5761cdaSHong Zhang ierr = PetscObjectCompose((PetscObject)(*newmat),"SubMatrix",(PetscObject)Msub);CHKERRQ(ierr); 3760548ecf4dSHong Zhang ierr = MatDestroy(&Msub);CHKERRQ(ierr); 376198b658c4SHong Zhang 3762d5761cdaSHong Zhang ierr = PetscObjectCompose((PetscObject)(*newmat),"SubIScol",(PetscObject)iscol_sub);CHKERRQ(ierr); 376398b658c4SHong Zhang ierr = ISDestroy(&iscol_sub);CHKERRQ(ierr); 376498b658c4SHong Zhang 3765d5761cdaSHong Zhang ierr = PetscObjectCompose((PetscObject)(*newmat),"Subcmap",(PetscObject)iscmap);CHKERRQ(ierr); 376698b658c4SHong Zhang ierr = ISDestroy(&iscmap);CHKERRQ(ierr); 3767bcae8d28SHong Zhang 3768bcae8d28SHong Zhang if (iscol_local) { 3769d5761cdaSHong Zhang ierr = PetscObjectCompose((PetscObject)(*newmat),"ISAllGather",(PetscObject)iscol_local);CHKERRQ(ierr); 3770bcae8d28SHong Zhang ierr = ISDestroy(&iscol_local);CHKERRQ(ierr); 3771bcae8d28SHong Zhang } 377298b658c4SHong Zhang } 3773a0ff6018SBarry Smith PetscFunctionReturn(0); 3774a0ff6018SBarry Smith } 3775273d9f13SBarry Smith 3776df40acb1SHong Zhang /* 3777df40acb1SHong Zhang Not great since it makes two copies of the submatrix, first an SeqAIJ 3778df40acb1SHong Zhang in local and then by concatenating the local matrices the end result. 3779df40acb1SHong Zhang Writing it directly would be much like MatCreateSubMatrices_MPIAIJ() 3780df40acb1SHong Zhang 3781df40acb1SHong Zhang Note: This requires a sequential iscol with all indices. 3782df40acb1SHong Zhang */ 3783618cbb4aSHong Zhang PetscErrorCode MatCreateSubMatrix_MPIAIJ_nonscalable(Mat mat,IS isrow,IS iscol,PetscInt csize,MatReuse call,Mat *newmat) 3784df40acb1SHong Zhang { 3785df40acb1SHong Zhang PetscErrorCode ierr; 3786df40acb1SHong Zhang PetscMPIInt rank,size; 3787df40acb1SHong Zhang PetscInt i,m,n,rstart,row,rend,nz,*cwork,j,bs,cbs; 3788df40acb1SHong Zhang PetscInt *ii,*jj,nlocal,*dlens,*olens,dlen,olen,jend,mglobal; 3789df40acb1SHong Zhang Mat M,Mreuse; 379098b658c4SHong Zhang MatScalar *aa,*vwork; 3791df40acb1SHong Zhang MPI_Comm comm; 3792df40acb1SHong Zhang Mat_SeqAIJ *aij; 37930b27a90eSHong Zhang PetscBool colflag,allcolumns=PETSC_FALSE; 3794df40acb1SHong Zhang 3795df40acb1SHong Zhang PetscFunctionBegin; 3796df40acb1SHong Zhang ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 3797df40acb1SHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 3798df40acb1SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 3799df40acb1SHong Zhang 38000b27a90eSHong Zhang /* Check for special case: each processor gets entire matrix columns */ 38010b27a90eSHong Zhang ierr = ISIdentity(iscol,&colflag);CHKERRQ(ierr); 38020b27a90eSHong Zhang ierr = ISGetLocalSize(iscol,&n);CHKERRQ(ierr); 38030b27a90eSHong Zhang if (colflag && n == mat->cmap->N) allcolumns = PETSC_TRUE; 38040b27a90eSHong Zhang 3805df40acb1SHong Zhang if (call == MAT_REUSE_MATRIX) { 3806df40acb1SHong Zhang ierr = PetscObjectQuery((PetscObject)*newmat,"SubMatrix",(PetscObject*)&Mreuse);CHKERRQ(ierr); 3807df40acb1SHong Zhang if (!Mreuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Submatrix passed in was not used before, cannot reuse"); 38080b27a90eSHong Zhang ierr = MatCreateSubMatrices_MPIAIJ_SingleIS_Local(mat,1,&isrow,&iscol,MAT_REUSE_MATRIX,allcolumns,&Mreuse);CHKERRQ(ierr); 3809df40acb1SHong Zhang } else { 38100b27a90eSHong Zhang ierr = MatCreateSubMatrices_MPIAIJ_SingleIS_Local(mat,1,&isrow,&iscol,MAT_INITIAL_MATRIX,allcolumns,&Mreuse);CHKERRQ(ierr); 3811df40acb1SHong Zhang } 3812df40acb1SHong Zhang 3813df40acb1SHong Zhang /* 3814df40acb1SHong Zhang m - number of local rows 3815df40acb1SHong Zhang n - number of columns (same on all processors) 3816df40acb1SHong Zhang rstart - first row in new global matrix generated 3817df40acb1SHong Zhang */ 3818df40acb1SHong Zhang ierr = MatGetSize(Mreuse,&m,&n);CHKERRQ(ierr); 3819df40acb1SHong Zhang ierr = MatGetBlockSizes(Mreuse,&bs,&cbs);CHKERRQ(ierr); 3820df40acb1SHong Zhang if (call == MAT_INITIAL_MATRIX) { 3821df40acb1SHong Zhang aij = (Mat_SeqAIJ*)(Mreuse)->data; 3822df40acb1SHong Zhang ii = aij->i; 3823df40acb1SHong Zhang jj = aij->j; 3824df40acb1SHong Zhang 3825df40acb1SHong Zhang /* 3826df40acb1SHong Zhang Determine the number of non-zeros in the diagonal and off-diagonal 3827df40acb1SHong Zhang portions of the matrix in order to do correct preallocation 3828df40acb1SHong Zhang */ 3829df40acb1SHong Zhang 3830df40acb1SHong Zhang /* first get start and end of "diagonal" columns */ 3831df40acb1SHong Zhang if (csize == PETSC_DECIDE) { 3832df40acb1SHong Zhang ierr = ISGetSize(isrow,&mglobal);CHKERRQ(ierr); 3833df40acb1SHong Zhang if (mglobal == n) { /* square matrix */ 3834df40acb1SHong Zhang nlocal = m; 3835df40acb1SHong Zhang } else { 3836df40acb1SHong Zhang nlocal = n/size + ((n % size) > rank); 3837df40acb1SHong Zhang } 3838df40acb1SHong Zhang } else { 3839df40acb1SHong Zhang nlocal = csize; 3840df40acb1SHong Zhang } 3841df40acb1SHong Zhang ierr = MPI_Scan(&nlocal,&rend,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 3842df40acb1SHong Zhang rstart = rend - nlocal; 3843df40acb1SHong Zhang 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); 3844df40acb1SHong Zhang 3845df40acb1SHong Zhang /* next, compute all the lengths */ 3846df40acb1SHong Zhang ierr = PetscMalloc1(2*m+1,&dlens);CHKERRQ(ierr); 3847df40acb1SHong Zhang olens = dlens + m; 3848df40acb1SHong Zhang for (i=0; i<m; i++) { 3849df40acb1SHong Zhang jend = ii[i+1] - ii[i]; 3850df40acb1SHong Zhang olen = 0; 3851df40acb1SHong Zhang dlen = 0; 3852df40acb1SHong Zhang for (j=0; j<jend; j++) { 3853df40acb1SHong Zhang if (*jj < rstart || *jj >= rend) olen++; 3854df40acb1SHong Zhang else dlen++; 3855df40acb1SHong Zhang jj++; 3856df40acb1SHong Zhang } 3857df40acb1SHong Zhang olens[i] = olen; 3858df40acb1SHong Zhang dlens[i] = dlen; 3859df40acb1SHong Zhang } 3860df40acb1SHong Zhang ierr = MatCreate(comm,&M);CHKERRQ(ierr); 3861df40acb1SHong Zhang ierr = MatSetSizes(M,m,nlocal,PETSC_DECIDE,n);CHKERRQ(ierr); 3862df40acb1SHong Zhang ierr = MatSetBlockSizes(M,bs,cbs);CHKERRQ(ierr); 3863df40acb1SHong Zhang ierr = MatSetType(M,((PetscObject)mat)->type_name);CHKERRQ(ierr); 3864df40acb1SHong Zhang ierr = MatMPIAIJSetPreallocation(M,0,dlens,0,olens);CHKERRQ(ierr); 3865df40acb1SHong Zhang ierr = PetscFree(dlens);CHKERRQ(ierr); 3866df40acb1SHong Zhang } else { 3867df40acb1SHong Zhang PetscInt ml,nl; 3868df40acb1SHong Zhang 3869df40acb1SHong Zhang M = *newmat; 3870df40acb1SHong Zhang ierr = MatGetLocalSize(M,&ml,&nl);CHKERRQ(ierr); 3871df40acb1SHong Zhang if (ml != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Previous matrix must be same size/layout as request"); 3872df40acb1SHong Zhang ierr = MatZeroEntries(M);CHKERRQ(ierr); 3873df40acb1SHong Zhang /* 3874df40acb1SHong Zhang The next two lines are needed so we may call MatSetValues_MPIAIJ() below directly, 3875df40acb1SHong Zhang rather than the slower MatSetValues(). 3876df40acb1SHong Zhang */ 3877df40acb1SHong Zhang M->was_assembled = PETSC_TRUE; 3878df40acb1SHong Zhang M->assembled = PETSC_FALSE; 3879df40acb1SHong Zhang } 3880df40acb1SHong Zhang ierr = MatGetOwnershipRange(M,&rstart,&rend);CHKERRQ(ierr); 3881df40acb1SHong Zhang aij = (Mat_SeqAIJ*)(Mreuse)->data; 3882df40acb1SHong Zhang ii = aij->i; 3883df40acb1SHong Zhang jj = aij->j; 3884df40acb1SHong Zhang aa = aij->a; 3885df40acb1SHong Zhang for (i=0; i<m; i++) { 3886df40acb1SHong Zhang row = rstart + i; 3887df40acb1SHong Zhang nz = ii[i+1] - ii[i]; 3888df40acb1SHong Zhang cwork = jj; jj += nz; 3889df40acb1SHong Zhang vwork = aa; aa += nz; 3890df40acb1SHong Zhang ierr = MatSetValues_MPIAIJ(M,1,&row,nz,cwork,vwork,INSERT_VALUES);CHKERRQ(ierr); 3891df40acb1SHong Zhang } 3892df40acb1SHong Zhang 3893df40acb1SHong Zhang ierr = MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3894df40acb1SHong Zhang ierr = MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3895df40acb1SHong Zhang *newmat = M; 3896df40acb1SHong Zhang 3897df40acb1SHong Zhang /* save submatrix used in processor for next request */ 3898df40acb1SHong Zhang if (call == MAT_INITIAL_MATRIX) { 3899df40acb1SHong Zhang ierr = PetscObjectCompose((PetscObject)M,"SubMatrix",(PetscObject)Mreuse);CHKERRQ(ierr); 3900df40acb1SHong Zhang ierr = MatDestroy(&Mreuse);CHKERRQ(ierr); 3901df40acb1SHong Zhang } 3902df40acb1SHong Zhang PetscFunctionReturn(0); 3903df40acb1SHong Zhang } 3904df40acb1SHong Zhang 39057087cfbeSBarry Smith PetscErrorCode MatMPIAIJSetPreallocationCSR_MPIAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[]) 3906ccd8e176SBarry Smith { 3907899cda47SBarry Smith PetscInt m,cstart, cend,j,nnz,i,d; 3908899cda47SBarry Smith PetscInt *d_nnz,*o_nnz,nnz_max = 0,rstart,ii; 3909ccd8e176SBarry Smith const PetscInt *JJ; 3910ccd8e176SBarry Smith PetscErrorCode ierr; 3911eeb24464SBarry Smith PetscBool nooffprocentries; 3912ccd8e176SBarry Smith 3913ccd8e176SBarry Smith PetscFunctionBegin; 39148f8f2f0dSBarry Smith if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Ii[0] must be 0 it is %D",Ii[0]); 3915899cda47SBarry Smith 391626283091SBarry Smith ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 391726283091SBarry Smith ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 3918d0f46423SBarry Smith m = B->rmap->n; 3919d0f46423SBarry Smith cstart = B->cmap->rstart; 3920d0f46423SBarry Smith cend = B->cmap->rend; 3921d0f46423SBarry Smith rstart = B->rmap->rstart; 3922899cda47SBarry Smith 3923435bcee1SStefano Zampini ierr = PetscCalloc2(m,&d_nnz,m,&o_nnz);CHKERRQ(ierr); 3924ccd8e176SBarry Smith 3925b60407b9SStefano Zampini #if defined(PETSC_USE_DEBUG) 39268f8f2f0dSBarry Smith for (i=0; i<m; i++) { 3927ecc77c7aSBarry Smith nnz = Ii[i+1]- Ii[i]; 3928ecc77c7aSBarry Smith JJ = J + Ii[i]; 3929e32f2f54SBarry Smith if (nnz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local row %D has a negative %D number of columns",i,nnz); 3930b60407b9SStefano Zampini if (nnz && (JJ[0] < 0)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Row %D starts with negative column index",i,JJ[0]); 3931b60407b9SStefano Zampini if (nnz && (JJ[nnz-1] >= B->cmap->N)) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Row %D ends with too large a column index %D (max allowed %D)",i,JJ[nnz-1],B->cmap->N); 3932ecc77c7aSBarry Smith } 3933ecc77c7aSBarry Smith #endif 3934ecc77c7aSBarry Smith 39358f8f2f0dSBarry Smith for (i=0; i<m; i++) { 3936b7940d39SSatish Balay nnz = Ii[i+1]- Ii[i]; 3937b7940d39SSatish Balay JJ = J + Ii[i]; 3938ccd8e176SBarry Smith nnz_max = PetscMax(nnz_max,nnz); 3939ccd8e176SBarry Smith d = 0; 39400daa03b5SJed Brown for (j=0; j<nnz; j++) { 39410daa03b5SJed Brown if (cstart <= JJ[j] && JJ[j] < cend) d++; 3942ccd8e176SBarry Smith } 3943ccd8e176SBarry Smith d_nnz[i] = d; 3944ccd8e176SBarry Smith o_nnz[i] = nnz - d; 3945ccd8e176SBarry Smith } 3946ccd8e176SBarry Smith ierr = MatMPIAIJSetPreallocation(B,0,d_nnz,0,o_nnz);CHKERRQ(ierr); 39471d79065fSBarry Smith ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr); 3948ccd8e176SBarry Smith 39498f8f2f0dSBarry Smith for (i=0; i<m; i++) { 3950ccd8e176SBarry Smith ii = i + rstart; 3951*071fcb05SBarry Smith ierr = MatSetValues_MPIAIJ(B,1,&ii,Ii[i+1] - Ii[i],J+Ii[i], v ? v + Ii[i] : NULL,INSERT_VALUES);CHKERRQ(ierr); 3952ccd8e176SBarry Smith } 3953eeb24464SBarry Smith nooffprocentries = B->nooffprocentries; 3954eeb24464SBarry Smith B->nooffprocentries = PETSC_TRUE; 3955ccd8e176SBarry Smith ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3956ccd8e176SBarry Smith ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3957eeb24464SBarry Smith B->nooffprocentries = nooffprocentries; 3958ccd8e176SBarry Smith 39597827cd58SJed Brown ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 3960ccd8e176SBarry Smith PetscFunctionReturn(0); 3961ccd8e176SBarry Smith } 3962ccd8e176SBarry Smith 39631eea217eSSatish Balay /*@ 3964ccd8e176SBarry Smith MatMPIAIJSetPreallocationCSR - Allocates memory for a sparse parallel matrix in AIJ format 3965ccd8e176SBarry Smith (the default parallel PETSc format). 3966ccd8e176SBarry Smith 3967d083f849SBarry Smith Collective 3968ccd8e176SBarry Smith 3969ccd8e176SBarry Smith Input Parameters: 3970a1661176SMatthew Knepley + B - the matrix 3971ccd8e176SBarry Smith . i - the indices into j for the start of each local row (starts with zero) 39720daa03b5SJed Brown . j - the column indices for each local row (starts with zero) 3973ccd8e176SBarry Smith - v - optional values in the matrix 3974ccd8e176SBarry Smith 3975ccd8e176SBarry Smith Level: developer 3976ccd8e176SBarry Smith 397712251496SSatish Balay Notes: 3978c1c1d628SHong Zhang The i, j, and v arrays ARE copied by this routine into the internal format used by PETSc; 3979c1c1d628SHong Zhang thus you CANNOT change the matrix entries by changing the values of v[] after you have 398012251496SSatish Balay called this routine. Use MatCreateMPIAIJWithSplitArrays() to avoid needing to copy the arrays. 398112251496SSatish Balay 398212251496SSatish Balay The i and j indices are 0 based, and i indices are indices corresponding to the local j array. 398312251496SSatish Balay 398412251496SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 398512251496SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 3986c5e4d11fSDmitry Karpeev as shown 398712251496SSatish Balay 3988c5e4d11fSDmitry Karpeev $ 1 0 0 3989c5e4d11fSDmitry Karpeev $ 2 0 3 P0 3990c5e4d11fSDmitry Karpeev $ ------- 3991c5e4d11fSDmitry Karpeev $ 4 5 6 P1 3992c5e4d11fSDmitry Karpeev $ 3993c5e4d11fSDmitry Karpeev $ Process0 [P0]: rows_owned=[0,1] 3994c5e4d11fSDmitry Karpeev $ i = {0,1,3} [size = nrow+1 = 2+1] 3995c5e4d11fSDmitry Karpeev $ j = {0,0,2} [size = 3] 3996c5e4d11fSDmitry Karpeev $ v = {1,2,3} [size = 3] 3997c5e4d11fSDmitry Karpeev $ 3998c5e4d11fSDmitry Karpeev $ Process1 [P1]: rows_owned=[2] 3999c5e4d11fSDmitry Karpeev $ i = {0,3} [size = nrow+1 = 1+1] 4000c5e4d11fSDmitry Karpeev $ j = {0,1,2} [size = 3] 4001c5e4d11fSDmitry Karpeev $ v = {4,5,6} [size = 3] 400212251496SSatish Balay 40035f4d30c4SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatCreateAIJ(), MATMPIAIJ, 40048d7a6e47SBarry Smith MatCreateSeqAIJWithArrays(), MatCreateMPIAIJWithSplitArrays() 4005ccd8e176SBarry Smith @*/ 40067087cfbeSBarry Smith PetscErrorCode MatMPIAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[], const PetscScalar v[]) 4007ccd8e176SBarry Smith { 40084ac538c5SBarry Smith PetscErrorCode ierr; 4009ccd8e176SBarry Smith 4010ccd8e176SBarry Smith PetscFunctionBegin; 40114ac538c5SBarry Smith ierr = PetscTryMethod(B,"MatMPIAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr); 4012ccd8e176SBarry Smith PetscFunctionReturn(0); 4013ccd8e176SBarry Smith } 4014ccd8e176SBarry Smith 4015273d9f13SBarry Smith /*@C 4016ccd8e176SBarry Smith MatMPIAIJSetPreallocation - Preallocates memory for a sparse parallel matrix in AIJ format 4017273d9f13SBarry Smith (the default parallel PETSc format). For good matrix assembly performance 4018273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameters 4019273d9f13SBarry Smith d_nz (or d_nnz) and o_nz (or o_nnz). By setting these parameters accurately, 4020273d9f13SBarry Smith performance can be increased by more than a factor of 50. 4021273d9f13SBarry Smith 4022d083f849SBarry Smith Collective 4023273d9f13SBarry Smith 4024273d9f13SBarry Smith Input Parameters: 40251c4f3114SJed Brown + B - the matrix 4026273d9f13SBarry Smith . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 4027273d9f13SBarry Smith (same value is used for all local rows) 4028273d9f13SBarry Smith . d_nnz - array containing the number of nonzeros in the various rows of the 4029273d9f13SBarry Smith DIAGONAL portion of the local submatrix (possibly different for each row) 403020fa73abSMatthew G. Knepley or NULL (PETSC_NULL_INTEGER in Fortran), if d_nz is used to specify the nonzero structure. 4031273d9f13SBarry Smith The size of this array is equal to the number of local rows, i.e 'm'. 40323287b5eaSJed Brown For matrices that will be factored, you must leave room for (and set) 40333287b5eaSJed Brown the diagonal entry even if it is zero. 4034273d9f13SBarry Smith . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 4035273d9f13SBarry Smith submatrix (same value is used for all local rows). 4036273d9f13SBarry Smith - o_nnz - array containing the number of nonzeros in the various rows of the 4037273d9f13SBarry Smith OFF-DIAGONAL portion of the local submatrix (possibly different for 403820fa73abSMatthew G. Knepley each row) or NULL (PETSC_NULL_INTEGER in Fortran), if o_nz is used to specify the nonzero 4039273d9f13SBarry Smith structure. The size of this array is equal to the number 4040273d9f13SBarry Smith of local rows, i.e 'm'. 4041273d9f13SBarry Smith 404249a6f317SBarry Smith If the *_nnz parameter is given then the *_nz parameter is ignored 404349a6f317SBarry Smith 4044273d9f13SBarry Smith The AIJ format (also called the Yale sparse matrix format or 4045ccd8e176SBarry Smith compressed row storage (CSR)), is fully compatible with standard Fortran 77 40460598bfebSBarry Smith storage. The stored row and column indices begin with zero. 4047a7f22e61SSatish Balay See Users-Manual: ch_mat for details. 4048273d9f13SBarry Smith 4049273d9f13SBarry Smith The parallel matrix is partitioned such that the first m0 rows belong to 4050273d9f13SBarry Smith process 0, the next m1 rows belong to process 1, the next m2 rows belong 4051273d9f13SBarry Smith to process 2 etc.. where m0,m1,m2... are the input parameter 'm'. 4052273d9f13SBarry Smith 4053273d9f13SBarry Smith The DIAGONAL portion of the local submatrix of a processor can be defined 4054a05b864aSJed Brown as the submatrix which is obtained by extraction the part corresponding to 4055a05b864aSJed Brown the rows r1-r2 and columns c1-c2 of the global matrix, where r1 is the 4056a05b864aSJed Brown first row that belongs to the processor, r2 is the last row belonging to 4057a05b864aSJed Brown the this processor, and c1-c2 is range of indices of the local part of a 4058a05b864aSJed Brown vector suitable for applying the matrix to. This is an mxn matrix. In the 4059a05b864aSJed Brown common case of a square matrix, the row and column ranges are the same and 4060a05b864aSJed Brown the DIAGONAL part is also square. The remaining portion of the local 4061a05b864aSJed Brown submatrix (mxN) constitute the OFF-DIAGONAL portion. 4062273d9f13SBarry Smith 4063273d9f13SBarry Smith If o_nnz, d_nnz are specified, then o_nz, and d_nz are ignored. 4064273d9f13SBarry Smith 4065aa95bbe8SBarry Smith You can call MatGetInfo() to get information on how effective the preallocation was; 4066aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 4067aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 4068aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 4069aa95bbe8SBarry Smith 4070273d9f13SBarry Smith Example usage: 4071273d9f13SBarry Smith 4072273d9f13SBarry Smith Consider the following 8x8 matrix with 34 non-zero values, that is 4073273d9f13SBarry Smith assembled across 3 processors. Lets assume that proc0 owns 3 rows, 4074273d9f13SBarry Smith proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 4075273d9f13SBarry Smith as follows: 4076273d9f13SBarry Smith 4077273d9f13SBarry Smith .vb 4078273d9f13SBarry Smith 1 2 0 | 0 3 0 | 0 4 4079273d9f13SBarry Smith Proc0 0 5 6 | 7 0 0 | 8 0 4080273d9f13SBarry Smith 9 0 10 | 11 0 0 | 12 0 4081273d9f13SBarry Smith ------------------------------------- 4082273d9f13SBarry Smith 13 0 14 | 15 16 17 | 0 0 4083273d9f13SBarry Smith Proc1 0 18 0 | 19 20 21 | 0 0 4084273d9f13SBarry Smith 0 0 0 | 22 23 0 | 24 0 4085273d9f13SBarry Smith ------------------------------------- 4086273d9f13SBarry Smith Proc2 25 26 27 | 0 0 28 | 29 0 4087273d9f13SBarry Smith 30 0 0 | 31 32 33 | 0 34 4088273d9f13SBarry Smith .ve 4089273d9f13SBarry Smith 4090273d9f13SBarry Smith This can be represented as a collection of submatrices as: 4091273d9f13SBarry Smith 4092273d9f13SBarry Smith .vb 4093273d9f13SBarry Smith A B C 4094273d9f13SBarry Smith D E F 4095273d9f13SBarry Smith G H I 4096273d9f13SBarry Smith .ve 4097273d9f13SBarry Smith 4098273d9f13SBarry Smith Where the submatrices A,B,C are owned by proc0, D,E,F are 4099273d9f13SBarry Smith owned by proc1, G,H,I are owned by proc2. 4100273d9f13SBarry Smith 4101273d9f13SBarry Smith The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 4102273d9f13SBarry Smith The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 4103273d9f13SBarry Smith The 'M','N' parameters are 8,8, and have the same values on all procs. 4104273d9f13SBarry Smith 4105273d9f13SBarry Smith The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are 4106273d9f13SBarry Smith submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices 4107273d9f13SBarry Smith corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively. 4108273d9f13SBarry Smith Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL 4109273d9f13SBarry Smith part as SeqAIJ matrices. for eg: proc1 will store [E] as a SeqAIJ 4110273d9f13SBarry Smith matrix, ans [DF] as another SeqAIJ matrix. 4111273d9f13SBarry Smith 4112273d9f13SBarry Smith When d_nz, o_nz parameters are specified, d_nz storage elements are 4113273d9f13SBarry Smith allocated for every row of the local diagonal submatrix, and o_nz 4114273d9f13SBarry Smith storage locations are allocated for every row of the OFF-DIAGONAL submat. 4115273d9f13SBarry Smith One way to choose d_nz and o_nz is to use the max nonzerors per local 4116273d9f13SBarry Smith rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices. 4117273d9f13SBarry Smith In this case, the values of d_nz,o_nz are: 4118273d9f13SBarry Smith .vb 4119273d9f13SBarry Smith proc0 : dnz = 2, o_nz = 2 4120273d9f13SBarry Smith proc1 : dnz = 3, o_nz = 2 4121273d9f13SBarry Smith proc2 : dnz = 1, o_nz = 4 4122273d9f13SBarry Smith .ve 4123273d9f13SBarry Smith We are allocating m*(d_nz+o_nz) storage locations for every proc. This 4124273d9f13SBarry Smith translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10 4125273d9f13SBarry Smith for proc3. i.e we are using 12+15+10=37 storage locations to store 4126273d9f13SBarry Smith 34 values. 4127273d9f13SBarry Smith 4128273d9f13SBarry Smith When d_nnz, o_nnz parameters are specified, the storage is specified 4129273d9f13SBarry Smith for every row, coresponding to both DIAGONAL and OFF-DIAGONAL submatrices. 4130273d9f13SBarry Smith In the above case the values for d_nnz,o_nnz are: 4131273d9f13SBarry Smith .vb 4132273d9f13SBarry Smith proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2] 4133273d9f13SBarry Smith proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1] 4134273d9f13SBarry Smith proc2: d_nnz = [1,1] and o_nnz = [4,4] 4135273d9f13SBarry Smith .ve 4136273d9f13SBarry Smith Here the space allocated is sum of all the above values i.e 34, and 4137273d9f13SBarry Smith hence pre-allocation is perfect. 4138273d9f13SBarry Smith 4139273d9f13SBarry Smith Level: intermediate 4140273d9f13SBarry Smith 414169b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateAIJ(), MatMPIAIJSetPreallocationCSR(), 41425f4d30c4SBarry Smith MATMPIAIJ, MatGetInfo(), PetscSplitOwnership() 4143273d9f13SBarry Smith @*/ 41447087cfbeSBarry Smith PetscErrorCode MatMPIAIJSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 4145273d9f13SBarry Smith { 41464ac538c5SBarry Smith PetscErrorCode ierr; 4147273d9f13SBarry Smith 4148273d9f13SBarry Smith PetscFunctionBegin; 41496ba663aaSJed Brown PetscValidHeaderSpecific(B,MAT_CLASSID,1); 41506ba663aaSJed Brown PetscValidType(B,1); 41514ac538c5SBarry Smith ierr = PetscTryMethod(B,"MatMPIAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr); 4152273d9f13SBarry Smith PetscFunctionReturn(0); 4153273d9f13SBarry Smith } 4154273d9f13SBarry Smith 415558d36128SBarry Smith /*@ 41562fb0ec9aSBarry Smith MatCreateMPIAIJWithArrays - creates a MPI AIJ matrix using arrays that contain in standard 41578f8f2f0dSBarry Smith CSR format for the local rows. 41582fb0ec9aSBarry Smith 4159d083f849SBarry Smith Collective 41602fb0ec9aSBarry Smith 41612fb0ec9aSBarry Smith Input Parameters: 41622fb0ec9aSBarry Smith + comm - MPI communicator 41632fb0ec9aSBarry Smith . m - number of local rows (Cannot be PETSC_DECIDE) 41642fb0ec9aSBarry Smith . n - This value should be the same as the local size used in creating the 41652fb0ec9aSBarry Smith x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have 41662fb0ec9aSBarry Smith calculated if N is given) For square matrices n is almost always m. 41672fb0ec9aSBarry Smith . M - number of global rows (or PETSC_DETERMINE to have calculated if m is given) 41682fb0ec9aSBarry Smith . N - number of global columns (or PETSC_DETERMINE to have calculated if n is given) 4169483a2f95SBarry Smith . i - row indices; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 41702fb0ec9aSBarry Smith . j - column indices 41712fb0ec9aSBarry Smith - a - matrix values 41722fb0ec9aSBarry Smith 41732fb0ec9aSBarry Smith Output Parameter: 41742fb0ec9aSBarry Smith . mat - the matrix 417503bfb495SBarry Smith 41762fb0ec9aSBarry Smith Level: intermediate 41772fb0ec9aSBarry Smith 41782fb0ec9aSBarry Smith Notes: 41792fb0ec9aSBarry Smith The i, j, and a arrays ARE copied by this routine into the internal format used by PETSc; 41802fb0ec9aSBarry Smith thus you CANNOT change the matrix entries by changing the values of a[] after you have 41818d7a6e47SBarry Smith called this routine. Use MatCreateMPIAIJWithSplitArrays() to avoid needing to copy the arrays. 41822fb0ec9aSBarry Smith 418312251496SSatish Balay The i and j indices are 0 based, and i indices are indices corresponding to the local j array. 418412251496SSatish Balay 418512251496SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 418612251496SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 4187c5e4d11fSDmitry Karpeev as shown 418812251496SSatish Balay 41898f8f2f0dSBarry Smith Once you have created the matrix you can update it with new numerical values using MatUpdateMPIAIJWithArrays 41908f8f2f0dSBarry Smith 4191c5e4d11fSDmitry Karpeev $ 1 0 0 4192c5e4d11fSDmitry Karpeev $ 2 0 3 P0 4193c5e4d11fSDmitry Karpeev $ ------- 4194c5e4d11fSDmitry Karpeev $ 4 5 6 P1 4195c5e4d11fSDmitry Karpeev $ 4196c5e4d11fSDmitry Karpeev $ Process0 [P0]: rows_owned=[0,1] 4197c5e4d11fSDmitry Karpeev $ i = {0,1,3} [size = nrow+1 = 2+1] 4198c5e4d11fSDmitry Karpeev $ j = {0,0,2} [size = 3] 4199c5e4d11fSDmitry Karpeev $ v = {1,2,3} [size = 3] 4200c5e4d11fSDmitry Karpeev $ 4201c5e4d11fSDmitry Karpeev $ Process1 [P1]: rows_owned=[2] 4202c5e4d11fSDmitry Karpeev $ i = {0,3} [size = nrow+1 = 1+1] 4203c5e4d11fSDmitry Karpeev $ j = {0,1,2} [size = 3] 4204c5e4d11fSDmitry Karpeev $ v = {4,5,6} [size = 3] 42052fb0ec9aSBarry Smith 42062fb0ec9aSBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(), 42078f8f2f0dSBarry Smith MATMPIAIJ, MatCreateAIJ(), MatCreateMPIAIJWithSplitArrays(), MatUpdateMPIAIJWithArrays() 42082fb0ec9aSBarry Smith @*/ 42097087cfbeSBarry 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) 42102fb0ec9aSBarry Smith { 42112fb0ec9aSBarry Smith PetscErrorCode ierr; 42122fb0ec9aSBarry Smith 42132fb0ec9aSBarry Smith PetscFunctionBegin; 4214b60407b9SStefano Zampini if (i && i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 4215e32f2f54SBarry Smith if (m < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"local number of rows (m) cannot be PETSC_DECIDE, or negative"); 42162fb0ec9aSBarry Smith ierr = MatCreate(comm,mat);CHKERRQ(ierr); 4217d4146a68SBarry Smith ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr); 4218a2f3521dSMark F. Adams /* ierr = MatSetBlockSizes(M,bs,cbs);CHKERRQ(ierr); */ 42192fb0ec9aSBarry Smith ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr); 42202fb0ec9aSBarry Smith ierr = MatMPIAIJSetPreallocationCSR(*mat,i,j,a);CHKERRQ(ierr); 42212fb0ec9aSBarry Smith PetscFunctionReturn(0); 42222fb0ec9aSBarry Smith } 42232fb0ec9aSBarry Smith 42248f8f2f0dSBarry Smith /*@ 42258f8f2f0dSBarry Smith MatUpdateMPIAIJWithArrays - updates a MPI AIJ matrix using arrays that contain in standard 42268f8f2f0dSBarry Smith CSR format for the local rows. Only the numerical values are updated the other arrays must be identical 42278f8f2f0dSBarry Smith 42288f8f2f0dSBarry Smith Collective 42298f8f2f0dSBarry Smith 42308f8f2f0dSBarry Smith Input Parameters: 42318f8f2f0dSBarry Smith + mat - the matrix 42328f8f2f0dSBarry Smith . m - number of local rows (Cannot be PETSC_DECIDE) 42338f8f2f0dSBarry Smith . n - This value should be the same as the local size used in creating the 42348f8f2f0dSBarry Smith x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have 42358f8f2f0dSBarry Smith calculated if N is given) For square matrices n is almost always m. 42368f8f2f0dSBarry Smith . M - number of global rows (or PETSC_DETERMINE to have calculated if m is given) 42378f8f2f0dSBarry Smith . N - number of global columns (or PETSC_DETERMINE to have calculated if n is given) 42388f8f2f0dSBarry Smith . Ii - row indices; that is Ii[0] = 0, Ii[row] = Ii[row-1] + number of elements in that row of the matrix 42398f8f2f0dSBarry Smith . J - column indices 42408f8f2f0dSBarry Smith - v - matrix values 42418f8f2f0dSBarry Smith 42428f8f2f0dSBarry Smith Level: intermediate 42438f8f2f0dSBarry Smith 42448f8f2f0dSBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(), 42458f8f2f0dSBarry Smith MATMPIAIJ, MatCreateAIJ(), MatCreateMPIAIJWithSplitArrays(), MatUpdateMPIAIJWithArrays() 42468f8f2f0dSBarry Smith @*/ 42478f8f2f0dSBarry Smith PetscErrorCode MatUpdateMPIAIJWithArrays(Mat mat,PetscInt m,PetscInt n,PetscInt M,PetscInt N,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[]) 42488f8f2f0dSBarry Smith { 42498f8f2f0dSBarry Smith PetscErrorCode ierr; 425070990e77SSatish Balay PetscInt cstart,nnz,i,j; 42518f8f2f0dSBarry Smith PetscInt *ld; 42528f8f2f0dSBarry Smith PetscBool nooffprocentries; 42538f8f2f0dSBarry Smith Mat_MPIAIJ *Aij = (Mat_MPIAIJ*)mat->data; 42548f8f2f0dSBarry Smith Mat_SeqAIJ *Ad = (Mat_SeqAIJ*)Aij->A->data, *Ao = (Mat_SeqAIJ*)Aij->B->data; 42558f8f2f0dSBarry Smith PetscScalar *ad = Ad->a, *ao = Ao->a; 42568f8f2f0dSBarry Smith const PetscInt *Adi = Ad->i; 42578f8f2f0dSBarry Smith PetscInt ldi,Iii,md; 42588f8f2f0dSBarry Smith 42598f8f2f0dSBarry Smith PetscFunctionBegin; 42608f8f2f0dSBarry Smith if (Ii[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 42618f8f2f0dSBarry Smith if (m < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"local number of rows (m) cannot be PETSC_DECIDE, or negative"); 42628f8f2f0dSBarry Smith if (m != mat->rmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local number of rows cannot change from call to MatUpdateMPIAIJWithArrays()"); 42638f8f2f0dSBarry Smith if (n != mat->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local number of columns cannot change from call to MatUpdateMPIAIJWithArrays()"); 42648f8f2f0dSBarry Smith 42658f8f2f0dSBarry Smith cstart = mat->cmap->rstart; 42668f8f2f0dSBarry Smith if (!Aij->ld) { 42678f8f2f0dSBarry Smith /* count number of entries below block diagonal */ 42688f8f2f0dSBarry Smith ierr = PetscCalloc1(m,&ld);CHKERRQ(ierr); 42698f8f2f0dSBarry Smith Aij->ld = ld; 42708f8f2f0dSBarry Smith for (i=0; i<m; i++) { 42718f8f2f0dSBarry Smith nnz = Ii[i+1]- Ii[i]; 42728f8f2f0dSBarry Smith j = 0; 42738f8f2f0dSBarry Smith while (J[j] < cstart && j < nnz) {j++;} 42748f8f2f0dSBarry Smith J += nnz; 42758f8f2f0dSBarry Smith ld[i] = j; 42768f8f2f0dSBarry Smith } 42778f8f2f0dSBarry Smith } else { 42788f8f2f0dSBarry Smith ld = Aij->ld; 42798f8f2f0dSBarry Smith } 42808f8f2f0dSBarry Smith 42818f8f2f0dSBarry Smith for (i=0; i<m; i++) { 42828f8f2f0dSBarry Smith nnz = Ii[i+1]- Ii[i]; 42838f8f2f0dSBarry Smith Iii = Ii[i]; 42848f8f2f0dSBarry Smith ldi = ld[i]; 42858f8f2f0dSBarry Smith md = Adi[i+1]-Adi[i]; 42868f8f2f0dSBarry Smith ierr = PetscArraycpy(ao,v + Iii,ldi);CHKERRQ(ierr); 42878f8f2f0dSBarry Smith ierr = PetscArraycpy(ad,v + Iii + ldi,md);CHKERRQ(ierr); 42888f8f2f0dSBarry Smith ierr = PetscArraycpy(ao + ldi,v + Iii + ldi + md,nnz - ldi - md);CHKERRQ(ierr); 42898f8f2f0dSBarry Smith ad += md; 42908f8f2f0dSBarry Smith ao += nnz - md; 42918f8f2f0dSBarry Smith } 42928f8f2f0dSBarry Smith nooffprocentries = mat->nooffprocentries; 42938f8f2f0dSBarry Smith mat->nooffprocentries = PETSC_TRUE; 42948f8f2f0dSBarry Smith ierr = PetscObjectStateIncrease((PetscObject)Aij->A);CHKERRQ(ierr); 42958f8f2f0dSBarry Smith ierr = PetscObjectStateIncrease((PetscObject)Aij->B);CHKERRQ(ierr); 42968f8f2f0dSBarry Smith ierr = PetscObjectStateIncrease((PetscObject)mat);CHKERRQ(ierr); 42978f8f2f0dSBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 42988f8f2f0dSBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 42998f8f2f0dSBarry Smith mat->nooffprocentries = nooffprocentries; 43008f8f2f0dSBarry Smith PetscFunctionReturn(0); 43018f8f2f0dSBarry Smith } 43028f8f2f0dSBarry Smith 4303273d9f13SBarry Smith /*@C 430469b1f4b7SBarry Smith MatCreateAIJ - Creates a sparse parallel matrix in AIJ format 4305273d9f13SBarry Smith (the default parallel PETSc format). For good matrix assembly performance 4306273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameters 4307273d9f13SBarry Smith d_nz (or d_nnz) and o_nz (or o_nnz). By setting these parameters accurately, 4308273d9f13SBarry Smith performance can be increased by more than a factor of 50. 4309273d9f13SBarry Smith 4310d083f849SBarry Smith Collective 4311273d9f13SBarry Smith 4312273d9f13SBarry Smith Input Parameters: 4313273d9f13SBarry Smith + comm - MPI communicator 4314273d9f13SBarry Smith . m - number of local rows (or PETSC_DECIDE to have calculated if M is given) 4315273d9f13SBarry Smith This value should be the same as the local size used in creating the 4316273d9f13SBarry Smith y vector for the matrix-vector product y = Ax. 4317273d9f13SBarry Smith . n - This value should be the same as the local size used in creating the 4318273d9f13SBarry Smith x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have 4319273d9f13SBarry Smith calculated if N is given) For square matrices n is almost always m. 4320273d9f13SBarry Smith . M - number of global rows (or PETSC_DETERMINE to have calculated if m is given) 4321273d9f13SBarry Smith . N - number of global columns (or PETSC_DETERMINE to have calculated if n is given) 4322273d9f13SBarry Smith . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 4323273d9f13SBarry Smith (same value is used for all local rows) 4324273d9f13SBarry Smith . d_nnz - array containing the number of nonzeros in the various rows of the 4325273d9f13SBarry Smith DIAGONAL portion of the local submatrix (possibly different for each row) 43260298fd71SBarry Smith or NULL, if d_nz is used to specify the nonzero structure. 4327273d9f13SBarry Smith The size of this array is equal to the number of local rows, i.e 'm'. 4328273d9f13SBarry Smith . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 4329273d9f13SBarry Smith submatrix (same value is used for all local rows). 4330273d9f13SBarry Smith - o_nnz - array containing the number of nonzeros in the various rows of the 4331273d9f13SBarry Smith OFF-DIAGONAL portion of the local submatrix (possibly different for 43320298fd71SBarry Smith each row) or NULL, if o_nz is used to specify the nonzero 4333273d9f13SBarry Smith structure. The size of this array is equal to the number 4334273d9f13SBarry Smith of local rows, i.e 'm'. 4335273d9f13SBarry Smith 4336273d9f13SBarry Smith Output Parameter: 4337273d9f13SBarry Smith . A - the matrix 4338273d9f13SBarry Smith 4339175b88e8SBarry Smith It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 4340f6f02116SRichard Tran Mills MatXXXXSetPreallocation() paradigm instead of this routine directly. 4341175b88e8SBarry Smith [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 4342175b88e8SBarry Smith 4343273d9f13SBarry Smith Notes: 434449a6f317SBarry Smith If the *_nnz parameter is given then the *_nz parameter is ignored 434549a6f317SBarry Smith 4346273d9f13SBarry Smith m,n,M,N parameters specify the size of the matrix, and its partitioning across 4347273d9f13SBarry Smith processors, while d_nz,d_nnz,o_nz,o_nnz parameters specify the approximate 4348273d9f13SBarry Smith storage requirements for this matrix. 4349273d9f13SBarry Smith 4350273d9f13SBarry Smith If PETSC_DECIDE or PETSC_DETERMINE is used for a particular argument on one 4351273d9f13SBarry Smith processor than it must be used on all processors that share the object for 4352273d9f13SBarry Smith that argument. 4353273d9f13SBarry Smith 4354273d9f13SBarry Smith The user MUST specify either the local or global matrix dimensions 4355273d9f13SBarry Smith (possibly both). 4356273d9f13SBarry Smith 435733a7c187SSatish Balay The parallel matrix is partitioned across processors such that the 435833a7c187SSatish Balay first m0 rows belong to process 0, the next m1 rows belong to 435933a7c187SSatish Balay process 1, the next m2 rows belong to process 2 etc.. where 436033a7c187SSatish Balay m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores 436133a7c187SSatish Balay values corresponding to [m x N] submatrix. 4362273d9f13SBarry Smith 436333a7c187SSatish Balay The columns are logically partitioned with the n0 columns belonging 436433a7c187SSatish Balay to 0th partition, the next n1 columns belonging to the next 4365df3898eeSBarry Smith partition etc.. where n0,n1,n2... are the input parameter 'n'. 436633a7c187SSatish Balay 436733a7c187SSatish Balay The DIAGONAL portion of the local submatrix on any given processor 436833a7c187SSatish Balay is the submatrix corresponding to the rows and columns m,n 436933a7c187SSatish Balay corresponding to the given processor. i.e diagonal matrix on 437033a7c187SSatish Balay process 0 is [m0 x n0], diagonal matrix on process 1 is [m1 x n1] 437133a7c187SSatish Balay etc. The remaining portion of the local submatrix [m x (N-n)] 437233a7c187SSatish Balay constitute the OFF-DIAGONAL portion. The example below better 437333a7c187SSatish Balay illustrates this concept. 437433a7c187SSatish Balay 437533a7c187SSatish Balay For a square global matrix we define each processor's diagonal portion 437633a7c187SSatish Balay to be its local rows and the corresponding columns (a square submatrix); 437733a7c187SSatish Balay each processor's off-diagonal portion encompasses the remainder of the 437833a7c187SSatish Balay local matrix (a rectangular submatrix). 4379273d9f13SBarry Smith 4380273d9f13SBarry Smith If o_nnz, d_nnz are specified, then o_nz, and d_nz are ignored. 4381273d9f13SBarry Smith 438297d05335SKris Buschelman When calling this routine with a single process communicator, a matrix of 438397d05335SKris Buschelman type SEQAIJ is returned. If a matrix of type MPIAIJ is desired for this 4384da57b5cdSKarl Rupp type of communicator, use the construction mechanism 4385da57b5cdSKarl Rupp .vb 438678102f6cSMatthew Knepley MatCreate(...,&A); MatSetType(A,MATMPIAIJ); MatSetSizes(A, m,n,M,N); MatMPIAIJSetPreallocation(A,...); 4387da57b5cdSKarl Rupp .ve 438897d05335SKris Buschelman 4389f1058c0fSBarry Smith $ MatCreate(...,&A); 4390f1058c0fSBarry Smith $ MatSetType(A,MATMPIAIJ); 4391f1058c0fSBarry Smith $ MatSetSizes(A, m,n,M,N); 4392f1058c0fSBarry Smith $ MatMPIAIJSetPreallocation(A,...); 4393f1058c0fSBarry Smith 4394273d9f13SBarry Smith By default, this format uses inodes (identical nodes) when possible. 4395273d9f13SBarry Smith We search for consecutive rows with the same nonzero structure, thereby 4396273d9f13SBarry Smith reusing matrix information to achieve increased efficiency. 4397273d9f13SBarry Smith 4398273d9f13SBarry Smith Options Database Keys: 4399923f20ffSKris Buschelman + -mat_no_inode - Do not use inodes 440047b2e64bSBarry Smith - -mat_inode_limit <limit> - Sets inode limit (max limit=5) 440147b2e64bSBarry Smith 4402273d9f13SBarry Smith 4403273d9f13SBarry Smith 4404273d9f13SBarry Smith Example usage: 4405273d9f13SBarry Smith 4406273d9f13SBarry Smith Consider the following 8x8 matrix with 34 non-zero values, that is 4407273d9f13SBarry Smith assembled across 3 processors. Lets assume that proc0 owns 3 rows, 4408273d9f13SBarry Smith proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 4409efc377ccSKarl Rupp as follows 4410273d9f13SBarry Smith 4411273d9f13SBarry Smith .vb 4412273d9f13SBarry Smith 1 2 0 | 0 3 0 | 0 4 4413273d9f13SBarry Smith Proc0 0 5 6 | 7 0 0 | 8 0 4414273d9f13SBarry Smith 9 0 10 | 11 0 0 | 12 0 4415273d9f13SBarry Smith ------------------------------------- 4416273d9f13SBarry Smith 13 0 14 | 15 16 17 | 0 0 4417273d9f13SBarry Smith Proc1 0 18 0 | 19 20 21 | 0 0 4418273d9f13SBarry Smith 0 0 0 | 22 23 0 | 24 0 4419273d9f13SBarry Smith ------------------------------------- 4420273d9f13SBarry Smith Proc2 25 26 27 | 0 0 28 | 29 0 4421273d9f13SBarry Smith 30 0 0 | 31 32 33 | 0 34 4422273d9f13SBarry Smith .ve 4423273d9f13SBarry Smith 4424da57b5cdSKarl Rupp This can be represented as a collection of submatrices as 4425273d9f13SBarry Smith 4426273d9f13SBarry Smith .vb 4427273d9f13SBarry Smith A B C 4428273d9f13SBarry Smith D E F 4429273d9f13SBarry Smith G H I 4430273d9f13SBarry Smith .ve 4431273d9f13SBarry Smith 4432273d9f13SBarry Smith Where the submatrices A,B,C are owned by proc0, D,E,F are 4433273d9f13SBarry Smith owned by proc1, G,H,I are owned by proc2. 4434273d9f13SBarry Smith 4435273d9f13SBarry Smith The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 4436273d9f13SBarry Smith The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 4437273d9f13SBarry Smith The 'M','N' parameters are 8,8, and have the same values on all procs. 4438273d9f13SBarry Smith 4439273d9f13SBarry Smith The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are 4440273d9f13SBarry Smith submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices 4441273d9f13SBarry Smith corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively. 4442273d9f13SBarry Smith Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL 4443273d9f13SBarry Smith part as SeqAIJ matrices. for eg: proc1 will store [E] as a SeqAIJ 4444273d9f13SBarry Smith matrix, ans [DF] as another SeqAIJ matrix. 4445273d9f13SBarry Smith 4446273d9f13SBarry Smith When d_nz, o_nz parameters are specified, d_nz storage elements are 4447273d9f13SBarry Smith allocated for every row of the local diagonal submatrix, and o_nz 4448273d9f13SBarry Smith storage locations are allocated for every row of the OFF-DIAGONAL submat. 4449273d9f13SBarry Smith One way to choose d_nz and o_nz is to use the max nonzerors per local 4450273d9f13SBarry Smith rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices. 4451da57b5cdSKarl Rupp In this case, the values of d_nz,o_nz are 4452273d9f13SBarry Smith .vb 4453273d9f13SBarry Smith proc0 : dnz = 2, o_nz = 2 4454273d9f13SBarry Smith proc1 : dnz = 3, o_nz = 2 4455273d9f13SBarry Smith proc2 : dnz = 1, o_nz = 4 4456273d9f13SBarry Smith .ve 4457273d9f13SBarry Smith We are allocating m*(d_nz+o_nz) storage locations for every proc. This 4458273d9f13SBarry Smith translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10 4459273d9f13SBarry Smith for proc3. i.e we are using 12+15+10=37 storage locations to store 4460273d9f13SBarry Smith 34 values. 4461273d9f13SBarry Smith 4462273d9f13SBarry Smith When d_nnz, o_nnz parameters are specified, the storage is specified 4463273d9f13SBarry Smith for every row, coresponding to both DIAGONAL and OFF-DIAGONAL submatrices. 4464da57b5cdSKarl Rupp In the above case the values for d_nnz,o_nnz are 4465273d9f13SBarry Smith .vb 4466273d9f13SBarry Smith proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2] 4467273d9f13SBarry Smith proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1] 4468273d9f13SBarry Smith proc2: d_nnz = [1,1] and o_nnz = [4,4] 4469273d9f13SBarry Smith .ve 4470273d9f13SBarry Smith Here the space allocated is sum of all the above values i.e 34, and 4471273d9f13SBarry Smith hence pre-allocation is perfect. 4472273d9f13SBarry Smith 4473273d9f13SBarry Smith Level: intermediate 4474273d9f13SBarry Smith 4475ccd8e176SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(), 44765f4d30c4SBarry Smith MATMPIAIJ, MatCreateMPIAIJWithArrays() 4477273d9f13SBarry Smith @*/ 447869b1f4b7SBarry 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) 4479273d9f13SBarry Smith { 44806849ba73SBarry Smith PetscErrorCode ierr; 4481b1d57f15SBarry Smith PetscMPIInt size; 4482273d9f13SBarry Smith 4483273d9f13SBarry Smith PetscFunctionBegin; 4484f69a0ea3SMatthew Knepley ierr = MatCreate(comm,A);CHKERRQ(ierr); 4485f69a0ea3SMatthew Knepley ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); 4486273d9f13SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 4487273d9f13SBarry Smith if (size > 1) { 4488273d9f13SBarry Smith ierr = MatSetType(*A,MATMPIAIJ);CHKERRQ(ierr); 4489273d9f13SBarry Smith ierr = MatMPIAIJSetPreallocation(*A,d_nz,d_nnz,o_nz,o_nnz);CHKERRQ(ierr); 4490273d9f13SBarry Smith } else { 4491273d9f13SBarry Smith ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr); 4492273d9f13SBarry Smith ierr = MatSeqAIJSetPreallocation(*A,d_nz,d_nnz);CHKERRQ(ierr); 4493273d9f13SBarry Smith } 4494273d9f13SBarry Smith PetscFunctionReturn(0); 4495273d9f13SBarry Smith } 4496195d93cdSBarry Smith 44979230625dSJed Brown PetscErrorCode MatMPIAIJGetSeqAIJ(Mat A,Mat *Ad,Mat *Ao,const PetscInt *colmap[]) 4498195d93cdSBarry Smith { 4499195d93cdSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 450004cf37c7SBarry Smith PetscBool flg; 450104cf37c7SBarry Smith PetscErrorCode ierr; 4502b1d57f15SBarry Smith 4503195d93cdSBarry Smith PetscFunctionBegin; 4504b92f168fSBarry Smith ierr = PetscStrbeginswith(((PetscObject)A)->type_name,MATMPIAIJ,&flg);CHKERRQ(ierr); 45055f4d30c4SBarry Smith if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"This function requires a MATMPIAIJ matrix as input"); 450621e72a00SBarry Smith if (Ad) *Ad = a->A; 450721e72a00SBarry Smith if (Ao) *Ao = a->B; 450821e72a00SBarry Smith if (colmap) *colmap = a->garray; 4509195d93cdSBarry Smith PetscFunctionReturn(0); 4510195d93cdSBarry Smith } 4511a2243be0SBarry Smith 4512110bb6e1SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_MPIAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat) 45139b8102ccSHong Zhang { 45149b8102ccSHong Zhang PetscErrorCode ierr; 4515110bb6e1SHong Zhang PetscInt m,N,i,rstart,nnz,Ii; 45169b8102ccSHong Zhang PetscInt *indx; 4517110bb6e1SHong Zhang PetscScalar *values; 45189b8102ccSHong Zhang 45199b8102ccSHong Zhang PetscFunctionBegin; 45209b8102ccSHong Zhang ierr = MatGetSize(inmat,&m,&N);CHKERRQ(ierr); 4521110bb6e1SHong Zhang if (scall == MAT_INITIAL_MATRIX) { /* symbolic phase */ 4522110bb6e1SHong Zhang PetscInt *dnz,*onz,sum,bs,cbs; 4523110bb6e1SHong Zhang 45249b8102ccSHong Zhang if (n == PETSC_DECIDE) { 45259b8102ccSHong Zhang ierr = PetscSplitOwnership(comm,&n,&N);CHKERRQ(ierr); 45269b8102ccSHong Zhang } 4527a22543b6SHong Zhang /* Check sum(n) = N */ 4528b2566f29SBarry Smith ierr = MPIU_Allreduce(&n,&sum,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 45297bbdc51dSHong Zhang if (sum != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Sum of local columns %D != global columns %D",sum,N); 4530a22543b6SHong Zhang 45319b8102ccSHong Zhang ierr = MPI_Scan(&m, &rstart,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 45329b8102ccSHong Zhang rstart -= m; 45339b8102ccSHong Zhang 45349b8102ccSHong Zhang ierr = MatPreallocateInitialize(comm,m,n,dnz,onz);CHKERRQ(ierr); 45359b8102ccSHong Zhang for (i=0; i<m; i++) { 45360298fd71SBarry Smith ierr = MatGetRow_SeqAIJ(inmat,i,&nnz,&indx,NULL);CHKERRQ(ierr); 45379b8102ccSHong Zhang ierr = MatPreallocateSet(i+rstart,nnz,indx,dnz,onz);CHKERRQ(ierr); 45380298fd71SBarry Smith ierr = MatRestoreRow_SeqAIJ(inmat,i,&nnz,&indx,NULL);CHKERRQ(ierr); 45399b8102ccSHong Zhang } 45409b8102ccSHong Zhang 45419b8102ccSHong Zhang ierr = MatCreate(comm,outmat);CHKERRQ(ierr); 45429b8102ccSHong Zhang ierr = MatSetSizes(*outmat,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 4543110bb6e1SHong Zhang ierr = MatGetBlockSizes(inmat,&bs,&cbs);CHKERRQ(ierr); 4544a2f3521dSMark F. Adams ierr = MatSetBlockSizes(*outmat,bs,cbs);CHKERRQ(ierr); 45458761c3d6SHong Zhang ierr = MatSetType(*outmat,MATAIJ);CHKERRQ(ierr); 45468761c3d6SHong Zhang ierr = MatSeqAIJSetPreallocation(*outmat,0,dnz);CHKERRQ(ierr); 45479b8102ccSHong Zhang ierr = MatMPIAIJSetPreallocation(*outmat,0,dnz,0,onz);CHKERRQ(ierr); 45489b8102ccSHong Zhang ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 45499b8102ccSHong Zhang } 45509b8102ccSHong Zhang 4551110bb6e1SHong Zhang /* numeric phase */ 4552110bb6e1SHong Zhang ierr = MatGetOwnershipRange(*outmat,&rstart,NULL);CHKERRQ(ierr); 45539b8102ccSHong Zhang for (i=0; i<m; i++) { 45549b8102ccSHong Zhang ierr = MatGetRow_SeqAIJ(inmat,i,&nnz,&indx,&values);CHKERRQ(ierr); 45559b8102ccSHong Zhang Ii = i + rstart; 4556110bb6e1SHong Zhang ierr = MatSetValues(*outmat,1,&Ii,nnz,indx,values,INSERT_VALUES);CHKERRQ(ierr); 45579b8102ccSHong Zhang ierr = MatRestoreRow_SeqAIJ(inmat,i,&nnz,&indx,&values);CHKERRQ(ierr); 45589b8102ccSHong Zhang } 4559110bb6e1SHong Zhang ierr = MatAssemblyBegin(*outmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4560110bb6e1SHong Zhang ierr = MatAssemblyEnd(*outmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4561c5d6d63eSBarry Smith PetscFunctionReturn(0); 4562c5d6d63eSBarry Smith } 4563c5d6d63eSBarry Smith 4564dfbe8321SBarry Smith PetscErrorCode MatFileSplit(Mat A,char *outfile) 4565c5d6d63eSBarry Smith { 4566dfbe8321SBarry Smith PetscErrorCode ierr; 456732dcc486SBarry Smith PetscMPIInt rank; 4568b1d57f15SBarry Smith PetscInt m,N,i,rstart,nnz; 4569de4209c5SBarry Smith size_t len; 4570b1d57f15SBarry Smith const PetscInt *indx; 4571c5d6d63eSBarry Smith PetscViewer out; 4572c5d6d63eSBarry Smith char *name; 4573c5d6d63eSBarry Smith Mat B; 4574b3cc6726SBarry Smith const PetscScalar *values; 4575c5d6d63eSBarry Smith 4576c5d6d63eSBarry Smith PetscFunctionBegin; 4577c5d6d63eSBarry Smith ierr = MatGetLocalSize(A,&m,0);CHKERRQ(ierr); 4578c5d6d63eSBarry Smith ierr = MatGetSize(A,0,&N);CHKERRQ(ierr); 4579f204ca49SKris Buschelman /* Should this be the type of the diagonal block of A? */ 4580f69a0ea3SMatthew Knepley ierr = MatCreate(PETSC_COMM_SELF,&B);CHKERRQ(ierr); 4581f69a0ea3SMatthew Knepley ierr = MatSetSizes(B,m,N,m,N);CHKERRQ(ierr); 458233d57670SJed Brown ierr = MatSetBlockSizesFromMats(B,A,A);CHKERRQ(ierr); 4583f204ca49SKris Buschelman ierr = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr); 45840298fd71SBarry Smith ierr = MatSeqAIJSetPreallocation(B,0,NULL);CHKERRQ(ierr); 4585c5d6d63eSBarry Smith ierr = MatGetOwnershipRange(A,&rstart,0);CHKERRQ(ierr); 4586c5d6d63eSBarry Smith for (i=0; i<m; i++) { 4587c5d6d63eSBarry Smith ierr = MatGetRow(A,i+rstart,&nnz,&indx,&values);CHKERRQ(ierr); 4588c5d6d63eSBarry Smith ierr = MatSetValues(B,1,&i,nnz,indx,values,INSERT_VALUES);CHKERRQ(ierr); 4589c5d6d63eSBarry Smith ierr = MatRestoreRow(A,i+rstart,&nnz,&indx,&values);CHKERRQ(ierr); 4590c5d6d63eSBarry Smith } 4591c5d6d63eSBarry Smith ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4592c5d6d63eSBarry Smith ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4593c5d6d63eSBarry Smith 4594ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr); 4595c5d6d63eSBarry Smith ierr = PetscStrlen(outfile,&len);CHKERRQ(ierr); 4596854ce69bSBarry Smith ierr = PetscMalloc1(len+5,&name);CHKERRQ(ierr); 4597c5d6d63eSBarry Smith sprintf(name,"%s.%d",outfile,rank); 4598852598b0SBarry Smith ierr = PetscViewerBinaryOpen(PETSC_COMM_SELF,name,FILE_MODE_APPEND,&out);CHKERRQ(ierr); 4599a2ea699eSBarry Smith ierr = PetscFree(name);CHKERRQ(ierr); 4600c5d6d63eSBarry Smith ierr = MatView(B,out);CHKERRQ(ierr); 46016bf464f9SBarry Smith ierr = PetscViewerDestroy(&out);CHKERRQ(ierr); 46026bf464f9SBarry Smith ierr = MatDestroy(&B);CHKERRQ(ierr); 4603c5d6d63eSBarry Smith PetscFunctionReturn(0); 4604c5d6d63eSBarry Smith } 4605e5f2cdd8SHong Zhang 46067087cfbeSBarry Smith PetscErrorCode MatDestroy_MPIAIJ_SeqsToMPI(Mat A) 460751a7d1a8SHong Zhang { 460851a7d1a8SHong Zhang PetscErrorCode ierr; 4609671beff6SHong Zhang Mat_Merge_SeqsToMPI *merge; 4610776b82aeSLisandro Dalcin PetscContainer container; 461151a7d1a8SHong Zhang 461251a7d1a8SHong Zhang PetscFunctionBegin; 4613671beff6SHong Zhang ierr = PetscObjectQuery((PetscObject)A,"MatMergeSeqsToMPI",(PetscObject*)&container);CHKERRQ(ierr); 4614671beff6SHong Zhang if (container) { 4615776b82aeSLisandro Dalcin ierr = PetscContainerGetPointer(container,(void**)&merge);CHKERRQ(ierr); 461651a7d1a8SHong Zhang ierr = PetscFree(merge->id_r);CHKERRQ(ierr); 46173e06a4e6SHong Zhang ierr = PetscFree(merge->len_s);CHKERRQ(ierr); 46183e06a4e6SHong Zhang ierr = PetscFree(merge->len_r);CHKERRQ(ierr); 461951a7d1a8SHong Zhang ierr = PetscFree(merge->bi);CHKERRQ(ierr); 462051a7d1a8SHong Zhang ierr = PetscFree(merge->bj);CHKERRQ(ierr); 4621533163c2SBarry Smith ierr = PetscFree(merge->buf_ri[0]);CHKERRQ(ierr); 462202c68681SHong Zhang ierr = PetscFree(merge->buf_ri);CHKERRQ(ierr); 4623533163c2SBarry Smith ierr = PetscFree(merge->buf_rj[0]);CHKERRQ(ierr); 462402c68681SHong Zhang ierr = PetscFree(merge->buf_rj);CHKERRQ(ierr); 462505b42c5fSBarry Smith ierr = PetscFree(merge->coi);CHKERRQ(ierr); 462605b42c5fSBarry Smith ierr = PetscFree(merge->coj);CHKERRQ(ierr); 462705b42c5fSBarry Smith ierr = PetscFree(merge->owners_co);CHKERRQ(ierr); 46286bf464f9SBarry Smith ierr = PetscLayoutDestroy(&merge->rowmap);CHKERRQ(ierr); 4629bf0cc555SLisandro Dalcin ierr = PetscFree(merge);CHKERRQ(ierr); 4630671beff6SHong Zhang ierr = PetscObjectCompose((PetscObject)A,"MatMergeSeqsToMPI",0);CHKERRQ(ierr); 4631671beff6SHong Zhang } 463251a7d1a8SHong Zhang ierr = MatDestroy_MPIAIJ(A);CHKERRQ(ierr); 463351a7d1a8SHong Zhang PetscFunctionReturn(0); 463451a7d1a8SHong Zhang } 463551a7d1a8SHong Zhang 4636c6db04a5SJed Brown #include <../src/mat/utils/freespace.h> 4637c6db04a5SJed Brown #include <petscbt.h> 46384ebed01fSBarry Smith 463990431a8fSHong Zhang PetscErrorCode MatCreateMPIAIJSumSeqAIJNumeric(Mat seqmat,Mat mpimat) 464055d1abb9SHong Zhang { 464155d1abb9SHong Zhang PetscErrorCode ierr; 4642ce94432eSBarry Smith MPI_Comm comm; 464355d1abb9SHong Zhang Mat_SeqAIJ *a =(Mat_SeqAIJ*)seqmat->data; 4644b1d57f15SBarry Smith PetscMPIInt size,rank,taga,*len_s; 4645a2ea699eSBarry Smith PetscInt N=mpimat->cmap->N,i,j,*owners,*ai=a->i,*aj; 4646b1d57f15SBarry Smith PetscInt proc,m; 4647b1d57f15SBarry Smith PetscInt **buf_ri,**buf_rj; 4648b1d57f15SBarry Smith PetscInt k,anzi,*bj_i,*bi,*bj,arow,bnzi,nextaj; 4649b1d57f15SBarry Smith PetscInt nrows,**buf_ri_k,**nextrow,**nextai; 465055d1abb9SHong Zhang MPI_Request *s_waits,*r_waits; 465155d1abb9SHong Zhang MPI_Status *status; 4652a77337e4SBarry Smith MatScalar *aa=a->a; 4653dd6ea824SBarry Smith MatScalar **abuf_r,*ba_i; 465455d1abb9SHong Zhang Mat_Merge_SeqsToMPI *merge; 4655776b82aeSLisandro Dalcin PetscContainer container; 465655d1abb9SHong Zhang 465755d1abb9SHong Zhang PetscFunctionBegin; 4658bedda5b1SHong Zhang ierr = PetscObjectGetComm((PetscObject)mpimat,&comm);CHKERRQ(ierr); 46594ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Seqstompinum,seqmat,0,0,0);CHKERRQ(ierr); 46603c2c1871SHong Zhang 466155d1abb9SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 466255d1abb9SHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 466355d1abb9SHong Zhang 466455d1abb9SHong Zhang ierr = PetscObjectQuery((PetscObject)mpimat,"MatMergeSeqsToMPI",(PetscObject*)&container);CHKERRQ(ierr); 4665776b82aeSLisandro Dalcin ierr = PetscContainerGetPointer(container,(void**)&merge);CHKERRQ(ierr); 4666bf0cc555SLisandro Dalcin 466755d1abb9SHong Zhang bi = merge->bi; 466855d1abb9SHong Zhang bj = merge->bj; 466955d1abb9SHong Zhang buf_ri = merge->buf_ri; 467055d1abb9SHong Zhang buf_rj = merge->buf_rj; 467155d1abb9SHong Zhang 4672785e854fSJed Brown ierr = PetscMalloc1(size,&status);CHKERRQ(ierr); 46737a2fc3feSBarry Smith owners = merge->rowmap->range; 467455d1abb9SHong Zhang len_s = merge->len_s; 467555d1abb9SHong Zhang 467655d1abb9SHong Zhang /* send and recv matrix values */ 467755d1abb9SHong Zhang /*-----------------------------*/ 4678357abbc8SBarry Smith ierr = PetscObjectGetNewTag((PetscObject)mpimat,&taga);CHKERRQ(ierr); 467955d1abb9SHong Zhang ierr = PetscPostIrecvScalar(comm,taga,merge->nrecv,merge->id_r,merge->len_r,&abuf_r,&r_waits);CHKERRQ(ierr); 468055d1abb9SHong Zhang 4681854ce69bSBarry Smith ierr = PetscMalloc1(merge->nsend+1,&s_waits);CHKERRQ(ierr); 468255d1abb9SHong Zhang for (proc=0,k=0; proc<size; proc++) { 468355d1abb9SHong Zhang if (!len_s[proc]) continue; 468455d1abb9SHong Zhang i = owners[proc]; 468555d1abb9SHong Zhang ierr = MPI_Isend(aa+ai[i],len_s[proc],MPIU_MATSCALAR,proc,taga,comm,s_waits+k);CHKERRQ(ierr); 468655d1abb9SHong Zhang k++; 468755d1abb9SHong Zhang } 468855d1abb9SHong Zhang 46890c468ba9SBarry Smith if (merge->nrecv) {ierr = MPI_Waitall(merge->nrecv,r_waits,status);CHKERRQ(ierr);} 46900c468ba9SBarry Smith if (merge->nsend) {ierr = MPI_Waitall(merge->nsend,s_waits,status);CHKERRQ(ierr);} 469155d1abb9SHong Zhang ierr = PetscFree(status);CHKERRQ(ierr); 469255d1abb9SHong Zhang 469355d1abb9SHong Zhang ierr = PetscFree(s_waits);CHKERRQ(ierr); 469455d1abb9SHong Zhang ierr = PetscFree(r_waits);CHKERRQ(ierr); 469555d1abb9SHong Zhang 469655d1abb9SHong Zhang /* insert mat values of mpimat */ 469755d1abb9SHong Zhang /*----------------------------*/ 4698785e854fSJed Brown ierr = PetscMalloc1(N,&ba_i);CHKERRQ(ierr); 4699dcca6d9dSJed Brown ierr = PetscMalloc3(merge->nrecv,&buf_ri_k,merge->nrecv,&nextrow,merge->nrecv,&nextai);CHKERRQ(ierr); 470055d1abb9SHong Zhang 470155d1abb9SHong Zhang for (k=0; k<merge->nrecv; k++) { 470255d1abb9SHong Zhang buf_ri_k[k] = buf_ri[k]; /* beginning of k-th recved i-structure */ 470355d1abb9SHong Zhang nrows = *(buf_ri_k[k]); 470455d1abb9SHong Zhang nextrow[k] = buf_ri_k[k]+1; /* next row number of k-th recved i-structure */ 470555d1abb9SHong Zhang nextai[k] = buf_ri_k[k] + (nrows + 1); /* poins to the next i-structure of k-th recved i-structure */ 470655d1abb9SHong Zhang } 470755d1abb9SHong Zhang 470855d1abb9SHong Zhang /* set values of ba */ 47097a2fc3feSBarry Smith m = merge->rowmap->n; 471055d1abb9SHong Zhang for (i=0; i<m; i++) { 471155d1abb9SHong Zhang arow = owners[rank] + i; 471255d1abb9SHong Zhang bj_i = bj+bi[i]; /* col indices of the i-th row of mpimat */ 471355d1abb9SHong Zhang bnzi = bi[i+1] - bi[i]; 4714580bdb30SBarry Smith ierr = PetscArrayzero(ba_i,bnzi);CHKERRQ(ierr); 471555d1abb9SHong Zhang 471655d1abb9SHong Zhang /* add local non-zero vals of this proc's seqmat into ba */ 471755d1abb9SHong Zhang anzi = ai[arow+1] - ai[arow]; 471855d1abb9SHong Zhang aj = a->j + ai[arow]; 471955d1abb9SHong Zhang aa = a->a + ai[arow]; 472055d1abb9SHong Zhang nextaj = 0; 472155d1abb9SHong Zhang for (j=0; nextaj<anzi; j++) { 472255d1abb9SHong Zhang if (*(bj_i + j) == aj[nextaj]) { /* bcol == acol */ 472355d1abb9SHong Zhang ba_i[j] += aa[nextaj++]; 472455d1abb9SHong Zhang } 472555d1abb9SHong Zhang } 472655d1abb9SHong Zhang 472755d1abb9SHong Zhang /* add received vals into ba */ 472855d1abb9SHong Zhang for (k=0; k<merge->nrecv; k++) { /* k-th received message */ 472955d1abb9SHong Zhang /* i-th row */ 473055d1abb9SHong Zhang if (i == *nextrow[k]) { 473155d1abb9SHong Zhang anzi = *(nextai[k]+1) - *nextai[k]; 473255d1abb9SHong Zhang aj = buf_rj[k] + *(nextai[k]); 473355d1abb9SHong Zhang aa = abuf_r[k] + *(nextai[k]); 473455d1abb9SHong Zhang nextaj = 0; 473555d1abb9SHong Zhang for (j=0; nextaj<anzi; j++) { 473655d1abb9SHong Zhang if (*(bj_i + j) == aj[nextaj]) { /* bcol == acol */ 473755d1abb9SHong Zhang ba_i[j] += aa[nextaj++]; 473855d1abb9SHong Zhang } 473955d1abb9SHong Zhang } 474055d1abb9SHong Zhang nextrow[k]++; nextai[k]++; 474155d1abb9SHong Zhang } 474255d1abb9SHong Zhang } 474355d1abb9SHong Zhang ierr = MatSetValues(mpimat,1,&arow,bnzi,bj_i,ba_i,INSERT_VALUES);CHKERRQ(ierr); 474455d1abb9SHong Zhang } 474555d1abb9SHong Zhang ierr = MatAssemblyBegin(mpimat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 474655d1abb9SHong Zhang ierr = MatAssemblyEnd(mpimat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 474755d1abb9SHong Zhang 4748533163c2SBarry Smith ierr = PetscFree(abuf_r[0]);CHKERRQ(ierr); 474955d1abb9SHong Zhang ierr = PetscFree(abuf_r);CHKERRQ(ierr); 475055d1abb9SHong Zhang ierr = PetscFree(ba_i);CHKERRQ(ierr); 47511d79065fSBarry Smith ierr = PetscFree3(buf_ri_k,nextrow,nextai);CHKERRQ(ierr); 47524ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Seqstompinum,seqmat,0,0,0);CHKERRQ(ierr); 475355d1abb9SHong Zhang PetscFunctionReturn(0); 475455d1abb9SHong Zhang } 475538f152feSBarry Smith 475690431a8fSHong Zhang PetscErrorCode MatCreateMPIAIJSumSeqAIJSymbolic(MPI_Comm comm,Mat seqmat,PetscInt m,PetscInt n,Mat *mpimat) 4757e5f2cdd8SHong Zhang { 4758f08fae4eSHong Zhang PetscErrorCode ierr; 475955a3bba9SHong Zhang Mat B_mpi; 4760c2234fe3SHong Zhang Mat_SeqAIJ *a=(Mat_SeqAIJ*)seqmat->data; 4761b1d57f15SBarry Smith PetscMPIInt size,rank,tagi,tagj,*len_s,*len_si,*len_ri; 4762b1d57f15SBarry Smith PetscInt **buf_rj,**buf_ri,**buf_ri_k; 4763d0f46423SBarry Smith PetscInt M=seqmat->rmap->n,N=seqmat->cmap->n,i,*owners,*ai=a->i,*aj=a->j; 4764a2f3521dSMark F. Adams PetscInt len,proc,*dnz,*onz,bs,cbs; 4765b1d57f15SBarry Smith PetscInt k,anzi,*bi,*bj,*lnk,nlnk,arow,bnzi,nspacedouble=0; 4766b1d57f15SBarry Smith PetscInt nrows,*buf_s,*buf_si,*buf_si_i,**nextrow,**nextai; 476755d1abb9SHong Zhang MPI_Request *si_waits,*sj_waits,*ri_waits,*rj_waits; 476858cb9c82SHong Zhang MPI_Status *status; 47690298fd71SBarry Smith PetscFreeSpaceList free_space=NULL,current_space=NULL; 4770be0fcf8dSHong Zhang PetscBT lnkbt; 477151a7d1a8SHong Zhang Mat_Merge_SeqsToMPI *merge; 4772776b82aeSLisandro Dalcin PetscContainer container; 477302c68681SHong Zhang 4774e5f2cdd8SHong Zhang PetscFunctionBegin; 47754ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Seqstompisym,seqmat,0,0,0);CHKERRQ(ierr); 47763c2c1871SHong Zhang 477738f152feSBarry Smith /* make sure it is a PETSc comm */ 47780298fd71SBarry Smith ierr = PetscCommDuplicate(comm,&comm,NULL);CHKERRQ(ierr); 4779e5f2cdd8SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 4780e5f2cdd8SHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 478155d1abb9SHong Zhang 4782b00a9115SJed Brown ierr = PetscNew(&merge);CHKERRQ(ierr); 4783785e854fSJed Brown ierr = PetscMalloc1(size,&status);CHKERRQ(ierr); 4784e5f2cdd8SHong Zhang 47856abd8857SHong Zhang /* determine row ownership */ 4786f08fae4eSHong Zhang /*---------------------------------------------------------*/ 478726283091SBarry Smith ierr = PetscLayoutCreate(comm,&merge->rowmap);CHKERRQ(ierr); 478826283091SBarry Smith ierr = PetscLayoutSetLocalSize(merge->rowmap,m);CHKERRQ(ierr); 478926283091SBarry Smith ierr = PetscLayoutSetSize(merge->rowmap,M);CHKERRQ(ierr); 479026283091SBarry Smith ierr = PetscLayoutSetBlockSize(merge->rowmap,1);CHKERRQ(ierr); 479126283091SBarry Smith ierr = PetscLayoutSetUp(merge->rowmap);CHKERRQ(ierr); 4792785e854fSJed Brown ierr = PetscMalloc1(size,&len_si);CHKERRQ(ierr); 4793785e854fSJed Brown ierr = PetscMalloc1(size,&merge->len_s);CHKERRQ(ierr); 479455d1abb9SHong Zhang 47957a2fc3feSBarry Smith m = merge->rowmap->n; 47967a2fc3feSBarry Smith owners = merge->rowmap->range; 47976abd8857SHong Zhang 47986abd8857SHong Zhang /* determine the number of messages to send, their lengths */ 47996abd8857SHong Zhang /*---------------------------------------------------------*/ 48003e06a4e6SHong Zhang len_s = merge->len_s; 480151a7d1a8SHong Zhang 48022257cef7SHong Zhang len = 0; /* length of buf_si[] */ 4803c2234fe3SHong Zhang merge->nsend = 0; 4804409913e3SHong Zhang for (proc=0; proc<size; proc++) { 48052257cef7SHong Zhang len_si[proc] = 0; 48063e06a4e6SHong Zhang if (proc == rank) { 48076abd8857SHong Zhang len_s[proc] = 0; 48083e06a4e6SHong Zhang } else { 480902c68681SHong Zhang len_si[proc] = owners[proc+1] - owners[proc] + 1; 48103e06a4e6SHong Zhang len_s[proc] = ai[owners[proc+1]] - ai[owners[proc]]; /* num of rows to be sent to [proc] */ 48113e06a4e6SHong Zhang } 48123e06a4e6SHong Zhang if (len_s[proc]) { 4813c2234fe3SHong Zhang merge->nsend++; 48142257cef7SHong Zhang nrows = 0; 48152257cef7SHong Zhang for (i=owners[proc]; i<owners[proc+1]; i++) { 48162257cef7SHong Zhang if (ai[i+1] > ai[i]) nrows++; 48172257cef7SHong Zhang } 48182257cef7SHong Zhang len_si[proc] = 2*(nrows+1); 48192257cef7SHong Zhang len += len_si[proc]; 4820409913e3SHong Zhang } 482158cb9c82SHong Zhang } 4822409913e3SHong Zhang 48232257cef7SHong Zhang /* determine the number and length of messages to receive for ij-structure */ 48242257cef7SHong Zhang /*-------------------------------------------------------------------------*/ 48250298fd71SBarry Smith ierr = PetscGatherNumberOfMessages(comm,NULL,len_s,&merge->nrecv);CHKERRQ(ierr); 482655d1abb9SHong Zhang ierr = PetscGatherMessageLengths2(comm,merge->nsend,merge->nrecv,len_s,len_si,&merge->id_r,&merge->len_r,&len_ri);CHKERRQ(ierr); 4827671beff6SHong Zhang 48283e06a4e6SHong Zhang /* post the Irecv of j-structure */ 48293e06a4e6SHong Zhang /*-------------------------------*/ 48302c72b5baSSatish Balay ierr = PetscCommGetNewTag(comm,&tagj);CHKERRQ(ierr); 48313e06a4e6SHong Zhang ierr = PetscPostIrecvInt(comm,tagj,merge->nrecv,merge->id_r,merge->len_r,&buf_rj,&rj_waits);CHKERRQ(ierr); 483202c68681SHong Zhang 48333e06a4e6SHong Zhang /* post the Isend of j-structure */ 4834affca5deSHong Zhang /*--------------------------------*/ 4835dcca6d9dSJed Brown ierr = PetscMalloc2(merge->nsend,&si_waits,merge->nsend,&sj_waits);CHKERRQ(ierr); 48363e06a4e6SHong Zhang 48372257cef7SHong Zhang for (proc=0, k=0; proc<size; proc++) { 4838409913e3SHong Zhang if (!len_s[proc]) continue; 483902c68681SHong Zhang i = owners[proc]; 4840b1d57f15SBarry Smith ierr = MPI_Isend(aj+ai[i],len_s[proc],MPIU_INT,proc,tagj,comm,sj_waits+k);CHKERRQ(ierr); 484151a7d1a8SHong Zhang k++; 484251a7d1a8SHong Zhang } 484351a7d1a8SHong Zhang 48443e06a4e6SHong Zhang /* receives and sends of j-structure are complete */ 48453e06a4e6SHong Zhang /*------------------------------------------------*/ 48460c468ba9SBarry Smith if (merge->nrecv) {ierr = MPI_Waitall(merge->nrecv,rj_waits,status);CHKERRQ(ierr);} 48470c468ba9SBarry Smith if (merge->nsend) {ierr = MPI_Waitall(merge->nsend,sj_waits,status);CHKERRQ(ierr);} 484802c68681SHong Zhang 484902c68681SHong Zhang /* send and recv i-structure */ 485002c68681SHong Zhang /*---------------------------*/ 48512c72b5baSSatish Balay ierr = PetscCommGetNewTag(comm,&tagi);CHKERRQ(ierr); 485202c68681SHong Zhang ierr = PetscPostIrecvInt(comm,tagi,merge->nrecv,merge->id_r,len_ri,&buf_ri,&ri_waits);CHKERRQ(ierr); 485302c68681SHong Zhang 4854854ce69bSBarry Smith ierr = PetscMalloc1(len+1,&buf_s);CHKERRQ(ierr); 48553e06a4e6SHong Zhang buf_si = buf_s; /* points to the beginning of k-th msg to be sent */ 48562257cef7SHong Zhang for (proc=0,k=0; proc<size; proc++) { 485702c68681SHong Zhang if (!len_s[proc]) continue; 48583e06a4e6SHong Zhang /* form outgoing message for i-structure: 48593e06a4e6SHong Zhang buf_si[0]: nrows to be sent 48603e06a4e6SHong Zhang [1:nrows]: row index (global) 48613e06a4e6SHong Zhang [nrows+1:2*nrows+1]: i-structure index 48623e06a4e6SHong Zhang */ 48633e06a4e6SHong Zhang /*-------------------------------------------*/ 48642257cef7SHong Zhang nrows = len_si[proc]/2 - 1; 48653e06a4e6SHong Zhang buf_si_i = buf_si + nrows+1; 48663e06a4e6SHong Zhang buf_si[0] = nrows; 48673e06a4e6SHong Zhang buf_si_i[0] = 0; 48683e06a4e6SHong Zhang nrows = 0; 48693e06a4e6SHong Zhang for (i=owners[proc]; i<owners[proc+1]; i++) { 48703e06a4e6SHong Zhang anzi = ai[i+1] - ai[i]; 48713e06a4e6SHong Zhang if (anzi) { 48723e06a4e6SHong Zhang buf_si_i[nrows+1] = buf_si_i[nrows] + anzi; /* i-structure */ 48733e06a4e6SHong Zhang buf_si[nrows+1] = i-owners[proc]; /* local row index */ 48743e06a4e6SHong Zhang nrows++; 48753e06a4e6SHong Zhang } 48763e06a4e6SHong Zhang } 4877b1d57f15SBarry Smith ierr = MPI_Isend(buf_si,len_si[proc],MPIU_INT,proc,tagi,comm,si_waits+k);CHKERRQ(ierr); 487802c68681SHong Zhang k++; 48792257cef7SHong Zhang buf_si += len_si[proc]; 488002c68681SHong Zhang } 48812257cef7SHong Zhang 48820c468ba9SBarry Smith if (merge->nrecv) {ierr = MPI_Waitall(merge->nrecv,ri_waits,status);CHKERRQ(ierr);} 48830c468ba9SBarry Smith if (merge->nsend) {ierr = MPI_Waitall(merge->nsend,si_waits,status);CHKERRQ(ierr);} 488402c68681SHong Zhang 4885ae15b995SBarry Smith ierr = PetscInfo2(seqmat,"nsend: %D, nrecv: %D\n",merge->nsend,merge->nrecv);CHKERRQ(ierr); 48863e06a4e6SHong Zhang for (i=0; i<merge->nrecv; i++) { 4887ae15b995SBarry 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); 48883e06a4e6SHong Zhang } 48893e06a4e6SHong Zhang 48903e06a4e6SHong Zhang ierr = PetscFree(len_si);CHKERRQ(ierr); 489102c68681SHong Zhang ierr = PetscFree(len_ri);CHKERRQ(ierr); 489202c68681SHong Zhang ierr = PetscFree(rj_waits);CHKERRQ(ierr); 48931d79065fSBarry Smith ierr = PetscFree2(si_waits,sj_waits);CHKERRQ(ierr); 48942257cef7SHong Zhang ierr = PetscFree(ri_waits);CHKERRQ(ierr); 48953e06a4e6SHong Zhang ierr = PetscFree(buf_s);CHKERRQ(ierr); 4896bcc1bcd5SHong Zhang ierr = PetscFree(status);CHKERRQ(ierr); 489758cb9c82SHong Zhang 4898bcc1bcd5SHong Zhang /* compute a local seq matrix in each processor */ 4899bcc1bcd5SHong Zhang /*----------------------------------------------*/ 490058cb9c82SHong Zhang /* allocate bi array and free space for accumulating nonzero column info */ 4901854ce69bSBarry Smith ierr = PetscMalloc1(m+1,&bi);CHKERRQ(ierr); 490258cb9c82SHong Zhang bi[0] = 0; 490358cb9c82SHong Zhang 4904be0fcf8dSHong Zhang /* create and initialize a linked list */ 4905be0fcf8dSHong Zhang nlnk = N+1; 4906be0fcf8dSHong Zhang ierr = PetscLLCreate(N,N,nlnk,lnk,lnkbt);CHKERRQ(ierr); 490758cb9c82SHong Zhang 4908bcc1bcd5SHong Zhang /* initial FreeSpace size is 2*(num of local nnz(seqmat)) */ 4909bcc1bcd5SHong Zhang len = ai[owners[rank+1]] - ai[owners[rank]]; 4910f91af8c7SBarry Smith ierr = PetscFreeSpaceGet(PetscIntMultTruncate(2,len)+1,&free_space);CHKERRQ(ierr); 49112205254eSKarl Rupp 491258cb9c82SHong Zhang current_space = free_space; 491358cb9c82SHong Zhang 4914bcc1bcd5SHong Zhang /* determine symbolic info for each local row */ 4915dcca6d9dSJed Brown ierr = PetscMalloc3(merge->nrecv,&buf_ri_k,merge->nrecv,&nextrow,merge->nrecv,&nextai);CHKERRQ(ierr); 49161d79065fSBarry Smith 49173e06a4e6SHong Zhang for (k=0; k<merge->nrecv; k++) { 49182257cef7SHong Zhang buf_ri_k[k] = buf_ri[k]; /* beginning of k-th recved i-structure */ 49193e06a4e6SHong Zhang nrows = *buf_ri_k[k]; 49203e06a4e6SHong Zhang nextrow[k] = buf_ri_k[k] + 1; /* next row number of k-th recved i-structure */ 49212257cef7SHong Zhang nextai[k] = buf_ri_k[k] + (nrows + 1); /* poins to the next i-structure of k-th recved i-structure */ 49223e06a4e6SHong Zhang } 49232257cef7SHong Zhang 4924bcc1bcd5SHong Zhang ierr = MatPreallocateInitialize(comm,m,n,dnz,onz);CHKERRQ(ierr); 4925bcc1bcd5SHong Zhang len = 0; 492658cb9c82SHong Zhang for (i=0; i<m; i++) { 492758cb9c82SHong Zhang bnzi = 0; 492858cb9c82SHong Zhang /* add local non-zero cols of this proc's seqmat into lnk */ 492958cb9c82SHong Zhang arow = owners[rank] + i; 493058cb9c82SHong Zhang anzi = ai[arow+1] - ai[arow]; 493158cb9c82SHong Zhang aj = a->j + ai[arow]; 4932dadf0e6bSHong Zhang ierr = PetscLLAddSorted(anzi,aj,N,nlnk,lnk,lnkbt);CHKERRQ(ierr); 493358cb9c82SHong Zhang bnzi += nlnk; 493458cb9c82SHong Zhang /* add received col data into lnk */ 493551a7d1a8SHong Zhang for (k=0; k<merge->nrecv; k++) { /* k-th received message */ 493655d1abb9SHong Zhang if (i == *nextrow[k]) { /* i-th row */ 49373e06a4e6SHong Zhang anzi = *(nextai[k]+1) - *nextai[k]; 49383e06a4e6SHong Zhang aj = buf_rj[k] + *nextai[k]; 4939dadf0e6bSHong Zhang ierr = PetscLLAddSorted(anzi,aj,N,nlnk,lnk,lnkbt);CHKERRQ(ierr); 49403e06a4e6SHong Zhang bnzi += nlnk; 49413e06a4e6SHong Zhang nextrow[k]++; nextai[k]++; 49423e06a4e6SHong Zhang } 494358cb9c82SHong Zhang } 4944bcc1bcd5SHong Zhang if (len < bnzi) len = bnzi; /* =max(bnzi) */ 494558cb9c82SHong Zhang 494658cb9c82SHong Zhang /* if free space is not available, make more free space */ 494758cb9c82SHong Zhang if (current_space->local_remaining<bnzi) { 4948f91af8c7SBarry Smith ierr = PetscFreeSpaceGet(PetscIntSumTruncate(bnzi,current_space->total_array_size),¤t_space);CHKERRQ(ierr); 494958cb9c82SHong Zhang nspacedouble++; 495058cb9c82SHong Zhang } 495158cb9c82SHong Zhang /* copy data into free space, then initialize lnk */ 4952be0fcf8dSHong Zhang ierr = PetscLLClean(N,N,bnzi,lnk,current_space->array,lnkbt);CHKERRQ(ierr); 4953bcc1bcd5SHong Zhang ierr = MatPreallocateSet(i+owners[rank],bnzi,current_space->array,dnz,onz);CHKERRQ(ierr); 4954bcc1bcd5SHong Zhang 495558cb9c82SHong Zhang current_space->array += bnzi; 495658cb9c82SHong Zhang current_space->local_used += bnzi; 495758cb9c82SHong Zhang current_space->local_remaining -= bnzi; 495858cb9c82SHong Zhang 495958cb9c82SHong Zhang bi[i+1] = bi[i] + bnzi; 496058cb9c82SHong Zhang } 4961bcc1bcd5SHong Zhang 49621d79065fSBarry Smith ierr = PetscFree3(buf_ri_k,nextrow,nextai);CHKERRQ(ierr); 4963bcc1bcd5SHong Zhang 4964854ce69bSBarry Smith ierr = PetscMalloc1(bi[m]+1,&bj);CHKERRQ(ierr); 4965a1a86e44SBarry Smith ierr = PetscFreeSpaceContiguous(&free_space,bj);CHKERRQ(ierr); 4966be0fcf8dSHong Zhang ierr = PetscLLDestroy(lnk,lnkbt);CHKERRQ(ierr); 4967409913e3SHong Zhang 4968bcc1bcd5SHong Zhang /* create symbolic parallel matrix B_mpi */ 4969bcc1bcd5SHong Zhang /*---------------------------------------*/ 4970a2f3521dSMark F. Adams ierr = MatGetBlockSizes(seqmat,&bs,&cbs);CHKERRQ(ierr); 4971f69a0ea3SMatthew Knepley ierr = MatCreate(comm,&B_mpi);CHKERRQ(ierr); 497254b84b50SHong Zhang if (n==PETSC_DECIDE) { 4973f69a0ea3SMatthew Knepley ierr = MatSetSizes(B_mpi,m,n,PETSC_DETERMINE,N);CHKERRQ(ierr); 497454b84b50SHong Zhang } else { 4975f69a0ea3SMatthew Knepley ierr = MatSetSizes(B_mpi,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 497654b84b50SHong Zhang } 4977a2f3521dSMark F. Adams ierr = MatSetBlockSizes(B_mpi,bs,cbs);CHKERRQ(ierr); 4978bcc1bcd5SHong Zhang ierr = MatSetType(B_mpi,MATMPIAIJ);CHKERRQ(ierr); 4979bcc1bcd5SHong Zhang ierr = MatMPIAIJSetPreallocation(B_mpi,0,dnz,0,onz);CHKERRQ(ierr); 4980bcc1bcd5SHong Zhang ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 49817e63b356SHong Zhang ierr = MatSetOption(B_mpi,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); 498258cb9c82SHong Zhang 498390431a8fSHong Zhang /* B_mpi is not ready for use - assembly will be done by MatCreateMPIAIJSumSeqAIJNumeric() */ 49846abd8857SHong Zhang B_mpi->assembled = PETSC_FALSE; 4985affca5deSHong Zhang B_mpi->ops->destroy = MatDestroy_MPIAIJ_SeqsToMPI; 4986affca5deSHong Zhang merge->bi = bi; 4987affca5deSHong Zhang merge->bj = bj; 498802c68681SHong Zhang merge->buf_ri = buf_ri; 498902c68681SHong Zhang merge->buf_rj = buf_rj; 49900298fd71SBarry Smith merge->coi = NULL; 49910298fd71SBarry Smith merge->coj = NULL; 49920298fd71SBarry Smith merge->owners_co = NULL; 4993affca5deSHong Zhang 4994bf0cc555SLisandro Dalcin ierr = PetscCommDestroy(&comm);CHKERRQ(ierr); 4995bf0cc555SLisandro Dalcin 4996affca5deSHong Zhang /* attach the supporting struct to B_mpi for reuse */ 4997776b82aeSLisandro Dalcin ierr = PetscContainerCreate(PETSC_COMM_SELF,&container);CHKERRQ(ierr); 4998776b82aeSLisandro Dalcin ierr = PetscContainerSetPointer(container,merge);CHKERRQ(ierr); 4999affca5deSHong Zhang ierr = PetscObjectCompose((PetscObject)B_mpi,"MatMergeSeqsToMPI",(PetscObject)container);CHKERRQ(ierr); 5000bf0cc555SLisandro Dalcin ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 5001affca5deSHong Zhang *mpimat = B_mpi; 500238f152feSBarry Smith 50034ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Seqstompisym,seqmat,0,0,0);CHKERRQ(ierr); 5004e5f2cdd8SHong Zhang PetscFunctionReturn(0); 5005e5f2cdd8SHong Zhang } 500625616d81SHong Zhang 5007d4036a1aSHong Zhang /*@C 50085f4d30c4SBarry Smith MatCreateMPIAIJSumSeqAIJ - Creates a MATMPIAIJ matrix by adding sequential 5009d4036a1aSHong Zhang matrices from each processor 5010d4036a1aSHong Zhang 5011d083f849SBarry Smith Collective 5012d4036a1aSHong Zhang 5013d4036a1aSHong Zhang Input Parameters: 5014d4036a1aSHong Zhang + comm - the communicators the parallel matrix will live on 5015d4036a1aSHong Zhang . seqmat - the input sequential matrices 5016d4036a1aSHong Zhang . m - number of local rows (or PETSC_DECIDE) 5017d4036a1aSHong Zhang . n - number of local columns (or PETSC_DECIDE) 5018d4036a1aSHong Zhang - scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 5019d4036a1aSHong Zhang 5020d4036a1aSHong Zhang Output Parameter: 5021d4036a1aSHong Zhang . mpimat - the parallel matrix generated 5022d4036a1aSHong Zhang 5023d4036a1aSHong Zhang Level: advanced 5024d4036a1aSHong Zhang 5025d4036a1aSHong Zhang Notes: 5026d4036a1aSHong Zhang The dimensions of the sequential matrix in each processor MUST be the same. 5027d4036a1aSHong Zhang The input seqmat is included into the container "Mat_Merge_SeqsToMPI", and will be 5028d4036a1aSHong Zhang destroyed when mpimat is destroyed. Call PetscObjectQuery() to access seqmat. 5029d4036a1aSHong Zhang @*/ 503090431a8fSHong Zhang PetscErrorCode MatCreateMPIAIJSumSeqAIJ(MPI_Comm comm,Mat seqmat,PetscInt m,PetscInt n,MatReuse scall,Mat *mpimat) 503155d1abb9SHong Zhang { 503255d1abb9SHong Zhang PetscErrorCode ierr; 50337e63b356SHong Zhang PetscMPIInt size; 503455d1abb9SHong Zhang 503555d1abb9SHong Zhang PetscFunctionBegin; 50367e63b356SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 50377e63b356SHong Zhang if (size == 1) { 50387e63b356SHong Zhang ierr = PetscLogEventBegin(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr); 50397e63b356SHong Zhang if (scall == MAT_INITIAL_MATRIX) { 50407e63b356SHong Zhang ierr = MatDuplicate(seqmat,MAT_COPY_VALUES,mpimat);CHKERRQ(ierr); 50417e63b356SHong Zhang } else { 50427e63b356SHong Zhang ierr = MatCopy(seqmat,*mpimat,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 50437e63b356SHong Zhang } 50447e63b356SHong Zhang ierr = PetscLogEventEnd(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr); 50457e63b356SHong Zhang PetscFunctionReturn(0); 50467e63b356SHong Zhang } 50474ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr); 504855d1abb9SHong Zhang if (scall == MAT_INITIAL_MATRIX) { 504990431a8fSHong Zhang ierr = MatCreateMPIAIJSumSeqAIJSymbolic(comm,seqmat,m,n,mpimat);CHKERRQ(ierr); 505055d1abb9SHong Zhang } 505190431a8fSHong Zhang ierr = MatCreateMPIAIJSumSeqAIJNumeric(seqmat,*mpimat);CHKERRQ(ierr); 50524ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr); 505355d1abb9SHong Zhang PetscFunctionReturn(0); 505455d1abb9SHong Zhang } 50554ebed01fSBarry Smith 5056bc08b0f1SBarry Smith /*@ 5057ef76dfe8SJed Brown MatMPIAIJGetLocalMat - Creates a SeqAIJ from a MATMPIAIJ matrix by taking all its local rows and putting them into a sequential matrix with 50588661ff28SBarry Smith mlocal rows and n columns. Where mlocal is the row count obtained with MatGetLocalSize() and n is the global column count obtained 50598661ff28SBarry Smith with MatGetSize() 506025616d81SHong Zhang 506132fba14fSHong Zhang Not Collective 506225616d81SHong Zhang 506325616d81SHong Zhang Input Parameters: 506425616d81SHong Zhang + A - the matrix 506525616d81SHong Zhang . scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 506625616d81SHong Zhang 506725616d81SHong Zhang Output Parameter: 506825616d81SHong Zhang . A_loc - the local sequential matrix generated 506925616d81SHong Zhang 507025616d81SHong Zhang Level: developer 507125616d81SHong Zhang 50728694ddc4SPierre Jolivet .seealso: MatGetOwnershipRange(), MatMPIAIJGetLocalMatCondensed() 50738661ff28SBarry Smith 507425616d81SHong Zhang @*/ 50754a2b5492SBarry Smith PetscErrorCode MatMPIAIJGetLocalMat(Mat A,MatReuse scall,Mat *A_loc) 507625616d81SHong Zhang { 507725616d81SHong Zhang PetscErrorCode ierr; 507801b7ae99SHong Zhang Mat_MPIAIJ *mpimat=(Mat_MPIAIJ*)A->data; 5079b78526a6SJose E. Roman Mat_SeqAIJ *mat,*a,*b; 5080b78526a6SJose E. Roman PetscInt *ai,*aj,*bi,*bj,*cmap=mpimat->garray; 5081b78526a6SJose E. Roman MatScalar *aa,*ba,*cam; 5082a77337e4SBarry Smith PetscScalar *ca; 5083d0f46423SBarry Smith PetscInt am=A->rmap->n,i,j,k,cstart=A->cmap->rstart; 50845a7d977cSHong Zhang PetscInt *ci,*cj,col,ncols_d,ncols_o,jo; 50858661ff28SBarry Smith PetscBool match; 508670a9ba44SHong Zhang MPI_Comm comm; 508770a9ba44SHong Zhang PetscMPIInt size; 508825616d81SHong Zhang 508925616d81SHong Zhang PetscFunctionBegin; 5090b92f168fSBarry Smith ierr = PetscStrbeginswith(((PetscObject)A)->type_name,MATMPIAIJ,&match);CHKERRQ(ierr); 50915f4d30c4SBarry Smith if (!match) SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_SUP,"Requires MATMPIAIJ matrix as input"); 509270a9ba44SHong Zhang ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 509370a9ba44SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 509470a9ba44SHong Zhang if (size == 1 && scall == MAT_REUSE_MATRIX) PetscFunctionReturn(0); 509570a9ba44SHong Zhang 50964ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Getlocalmat,A,0,0,0);CHKERRQ(ierr); 5097b78526a6SJose E. Roman a = (Mat_SeqAIJ*)(mpimat->A)->data; 5098b78526a6SJose E. Roman b = (Mat_SeqAIJ*)(mpimat->B)->data; 5099b78526a6SJose E. Roman ai = a->i; aj = a->j; bi = b->i; bj = b->j; 5100b78526a6SJose E. Roman aa = a->a; ba = b->a; 510101b7ae99SHong Zhang if (scall == MAT_INITIAL_MATRIX) { 510270a9ba44SHong Zhang if (size == 1) { 510370a9ba44SHong Zhang ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,am,A->cmap->N,ai,aj,aa,A_loc);CHKERRQ(ierr); 510470a9ba44SHong Zhang PetscFunctionReturn(0); 510570a9ba44SHong Zhang } 510670a9ba44SHong Zhang 5107854ce69bSBarry Smith ierr = PetscMalloc1(1+am,&ci);CHKERRQ(ierr); 5108dea91ad1SHong Zhang ci[0] = 0; 510901b7ae99SHong Zhang for (i=0; i<am; i++) { 5110dea91ad1SHong Zhang ci[i+1] = ci[i] + (ai[i+1] - ai[i]) + (bi[i+1] - bi[i]); 511101b7ae99SHong Zhang } 5112854ce69bSBarry Smith ierr = PetscMalloc1(1+ci[am],&cj);CHKERRQ(ierr); 5113854ce69bSBarry Smith ierr = PetscMalloc1(1+ci[am],&ca);CHKERRQ(ierr); 5114dea91ad1SHong Zhang k = 0; 511501b7ae99SHong Zhang for (i=0; i<am; i++) { 51165a7d977cSHong Zhang ncols_o = bi[i+1] - bi[i]; 51175a7d977cSHong Zhang ncols_d = ai[i+1] - ai[i]; 511801b7ae99SHong Zhang /* off-diagonal portion of A */ 51195a7d977cSHong Zhang for (jo=0; jo<ncols_o; jo++) { 51205a7d977cSHong Zhang col = cmap[*bj]; 51215a7d977cSHong Zhang if (col >= cstart) break; 51225a7d977cSHong Zhang cj[k] = col; bj++; 51235a7d977cSHong Zhang ca[k++] = *ba++; 51245a7d977cSHong Zhang } 51255a7d977cSHong Zhang /* diagonal portion of A */ 51265a7d977cSHong Zhang for (j=0; j<ncols_d; j++) { 51275a7d977cSHong Zhang cj[k] = cstart + *aj++; 51285a7d977cSHong Zhang ca[k++] = *aa++; 51295a7d977cSHong Zhang } 51305a7d977cSHong Zhang /* off-diagonal portion of A */ 51315a7d977cSHong Zhang for (j=jo; j<ncols_o; j++) { 51325a7d977cSHong Zhang cj[k] = cmap[*bj++]; 51335a7d977cSHong Zhang ca[k++] = *ba++; 51345a7d977cSHong Zhang } 513525616d81SHong Zhang } 5136dea91ad1SHong Zhang /* put together the new matrix */ 5137d0f46423SBarry Smith ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,am,A->cmap->N,ci,cj,ca,A_loc);CHKERRQ(ierr); 5138dea91ad1SHong Zhang /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 5139dea91ad1SHong Zhang /* Since these are PETSc arrays, change flags to free them as necessary. */ 5140dea91ad1SHong Zhang mat = (Mat_SeqAIJ*)(*A_loc)->data; 5141e6b907acSBarry Smith mat->free_a = PETSC_TRUE; 5142e6b907acSBarry Smith mat->free_ij = PETSC_TRUE; 5143dea91ad1SHong Zhang mat->nonew = 0; 51445a7d977cSHong Zhang } else if (scall == MAT_REUSE_MATRIX) { 51455a7d977cSHong Zhang mat=(Mat_SeqAIJ*)(*A_loc)->data; 5146a77337e4SBarry Smith ci = mat->i; cj = mat->j; cam = mat->a; 51475a7d977cSHong Zhang for (i=0; i<am; i++) { 51485a7d977cSHong Zhang /* off-diagonal portion of A */ 51495a7d977cSHong Zhang ncols_o = bi[i+1] - bi[i]; 51505a7d977cSHong Zhang for (jo=0; jo<ncols_o; jo++) { 51515a7d977cSHong Zhang col = cmap[*bj]; 51525a7d977cSHong Zhang if (col >= cstart) break; 5153a77337e4SBarry Smith *cam++ = *ba++; bj++; 51545a7d977cSHong Zhang } 51555a7d977cSHong Zhang /* diagonal portion of A */ 5156ecc9b87dSHong Zhang ncols_d = ai[i+1] - ai[i]; 5157a77337e4SBarry Smith for (j=0; j<ncols_d; j++) *cam++ = *aa++; 51585a7d977cSHong Zhang /* off-diagonal portion of A */ 5159f33d1a9aSHong Zhang for (j=jo; j<ncols_o; j++) { 5160a77337e4SBarry Smith *cam++ = *ba++; bj++; 5161f33d1a9aSHong Zhang } 51625a7d977cSHong Zhang } 51638661ff28SBarry Smith } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid MatReuse %d",(int)scall); 51644ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Getlocalmat,A,0,0,0);CHKERRQ(ierr); 516525616d81SHong Zhang PetscFunctionReturn(0); 516625616d81SHong Zhang } 516725616d81SHong Zhang 516832fba14fSHong Zhang /*@C 51695f4d30c4SBarry Smith MatMPIAIJGetLocalMatCondensed - Creates a SeqAIJ matrix from an MATMPIAIJ matrix by taking all its local rows and NON-ZERO columns 517032fba14fSHong Zhang 517132fba14fSHong Zhang Not Collective 517232fba14fSHong Zhang 517332fba14fSHong Zhang Input Parameters: 517432fba14fSHong Zhang + A - the matrix 517532fba14fSHong Zhang . scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 51760298fd71SBarry Smith - row, col - index sets of rows and columns to extract (or NULL) 517732fba14fSHong Zhang 517832fba14fSHong Zhang Output Parameter: 517932fba14fSHong Zhang . A_loc - the local sequential matrix generated 518032fba14fSHong Zhang 518132fba14fSHong Zhang Level: developer 518232fba14fSHong Zhang 5183ba264940SBarry Smith .seealso: MatGetOwnershipRange(), MatMPIAIJGetLocalMat() 5184ba264940SBarry Smith 518532fba14fSHong Zhang @*/ 51864a2b5492SBarry Smith PetscErrorCode MatMPIAIJGetLocalMatCondensed(Mat A,MatReuse scall,IS *row,IS *col,Mat *A_loc) 518732fba14fSHong Zhang { 518832fba14fSHong Zhang Mat_MPIAIJ *a=(Mat_MPIAIJ*)A->data; 518932fba14fSHong Zhang PetscErrorCode ierr; 519032fba14fSHong Zhang PetscInt i,start,end,ncols,nzA,nzB,*cmap,imark,*idx; 519132fba14fSHong Zhang IS isrowa,iscola; 519232fba14fSHong Zhang Mat *aloc; 51934a2b5492SBarry Smith PetscBool match; 519432fba14fSHong Zhang 519532fba14fSHong Zhang PetscFunctionBegin; 5196251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&match);CHKERRQ(ierr); 51975f4d30c4SBarry Smith if (!match) SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_SUP,"Requires MATMPIAIJ matrix as input"); 51984ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Getlocalmatcondensed,A,0,0,0);CHKERRQ(ierr); 519932fba14fSHong Zhang if (!row) { 5200d0f46423SBarry Smith start = A->rmap->rstart; end = A->rmap->rend; 520132fba14fSHong Zhang ierr = ISCreateStride(PETSC_COMM_SELF,end-start,start,1,&isrowa);CHKERRQ(ierr); 520232fba14fSHong Zhang } else { 520332fba14fSHong Zhang isrowa = *row; 520432fba14fSHong Zhang } 520532fba14fSHong Zhang if (!col) { 5206d0f46423SBarry Smith start = A->cmap->rstart; 520732fba14fSHong Zhang cmap = a->garray; 5208d0f46423SBarry Smith nzA = a->A->cmap->n; 5209d0f46423SBarry Smith nzB = a->B->cmap->n; 5210854ce69bSBarry Smith ierr = PetscMalloc1(nzA+nzB, &idx);CHKERRQ(ierr); 521132fba14fSHong Zhang ncols = 0; 521232fba14fSHong Zhang for (i=0; i<nzB; i++) { 521332fba14fSHong Zhang if (cmap[i] < start) idx[ncols++] = cmap[i]; 521432fba14fSHong Zhang else break; 521532fba14fSHong Zhang } 521632fba14fSHong Zhang imark = i; 521732fba14fSHong Zhang for (i=0; i<nzA; i++) idx[ncols++] = start + i; 521832fba14fSHong Zhang for (i=imark; i<nzB; i++) idx[ncols++] = cmap[i]; 5219d67e408aSBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,ncols,idx,PETSC_OWN_POINTER,&iscola);CHKERRQ(ierr); 522032fba14fSHong Zhang } else { 522132fba14fSHong Zhang iscola = *col; 522232fba14fSHong Zhang } 522332fba14fSHong Zhang if (scall != MAT_INITIAL_MATRIX) { 5224854ce69bSBarry Smith ierr = PetscMalloc1(1,&aloc);CHKERRQ(ierr); 522532fba14fSHong Zhang aloc[0] = *A_loc; 522632fba14fSHong Zhang } 52277dae84e0SHong Zhang ierr = MatCreateSubMatrices(A,1,&isrowa,&iscola,scall,&aloc);CHKERRQ(ierr); 5228109e0772SStefano Zampini if (!col) { /* attach global id of condensed columns */ 5229109e0772SStefano Zampini ierr = PetscObjectCompose((PetscObject)aloc[0],"_petsc_GetLocalMatCondensed_iscol",(PetscObject)iscola);CHKERRQ(ierr); 5230109e0772SStefano Zampini } 523132fba14fSHong Zhang *A_loc = aloc[0]; 523232fba14fSHong Zhang ierr = PetscFree(aloc);CHKERRQ(ierr); 523332fba14fSHong Zhang if (!row) { 52346bf464f9SBarry Smith ierr = ISDestroy(&isrowa);CHKERRQ(ierr); 523532fba14fSHong Zhang } 523632fba14fSHong Zhang if (!col) { 52376bf464f9SBarry Smith ierr = ISDestroy(&iscola);CHKERRQ(ierr); 523832fba14fSHong Zhang } 52394ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Getlocalmatcondensed,A,0,0,0);CHKERRQ(ierr); 524032fba14fSHong Zhang PetscFunctionReturn(0); 524132fba14fSHong Zhang } 524232fba14fSHong Zhang 524325616d81SHong Zhang /*@C 524432fba14fSHong Zhang MatGetBrowsOfAcols - Creates a SeqAIJ matrix by taking rows of B that equal to nonzero columns of local A 524525616d81SHong Zhang 524625616d81SHong Zhang Collective on Mat 524725616d81SHong Zhang 524825616d81SHong Zhang Input Parameters: 5249e240928fSHong Zhang + A,B - the matrices in mpiaij format 525025616d81SHong Zhang . scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 52510298fd71SBarry Smith - rowb, colb - index sets of rows and columns of B to extract (or NULL) 525225616d81SHong Zhang 525325616d81SHong Zhang Output Parameter: 525425616d81SHong Zhang + rowb, colb - index sets of rows and columns of B to extract 525525616d81SHong Zhang - B_seq - the sequential matrix generated 525625616d81SHong Zhang 525725616d81SHong Zhang Level: developer 525825616d81SHong Zhang 525925616d81SHong Zhang @*/ 526066bfb163SHong Zhang PetscErrorCode MatGetBrowsOfAcols(Mat A,Mat B,MatReuse scall,IS *rowb,IS *colb,Mat *B_seq) 526125616d81SHong Zhang { 5262899cda47SBarry Smith Mat_MPIAIJ *a=(Mat_MPIAIJ*)A->data; 526325616d81SHong Zhang PetscErrorCode ierr; 5264b1d57f15SBarry Smith PetscInt *idx,i,start,ncols,nzA,nzB,*cmap,imark; 526525616d81SHong Zhang IS isrowb,iscolb; 52660298fd71SBarry Smith Mat *bseq=NULL; 526725616d81SHong Zhang 526825616d81SHong Zhang PetscFunctionBegin; 5269d0f46423SBarry Smith if (A->cmap->rstart != B->rmap->rstart || A->cmap->rend != B->rmap->rend) { 5270e32f2f54SBarry 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); 527125616d81SHong Zhang } 52724ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_GetBrowsOfAcols,A,B,0,0);CHKERRQ(ierr); 527325616d81SHong Zhang 527425616d81SHong Zhang if (scall == MAT_INITIAL_MATRIX) { 5275d0f46423SBarry Smith start = A->cmap->rstart; 527625616d81SHong Zhang cmap = a->garray; 5277d0f46423SBarry Smith nzA = a->A->cmap->n; 5278d0f46423SBarry Smith nzB = a->B->cmap->n; 5279854ce69bSBarry Smith ierr = PetscMalloc1(nzA+nzB, &idx);CHKERRQ(ierr); 528025616d81SHong Zhang ncols = 0; 52810390132cSHong Zhang for (i=0; i<nzB; i++) { /* row < local row index */ 528225616d81SHong Zhang if (cmap[i] < start) idx[ncols++] = cmap[i]; 528325616d81SHong Zhang else break; 528425616d81SHong Zhang } 528525616d81SHong Zhang imark = i; 52860390132cSHong Zhang for (i=0; i<nzA; i++) idx[ncols++] = start + i; /* local rows */ 52870390132cSHong Zhang for (i=imark; i<nzB; i++) idx[ncols++] = cmap[i]; /* row > local row index */ 5288d67e408aSBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,ncols,idx,PETSC_OWN_POINTER,&isrowb);CHKERRQ(ierr); 5289d0f46423SBarry Smith ierr = ISCreateStride(PETSC_COMM_SELF,B->cmap->N,0,1,&iscolb);CHKERRQ(ierr); 529025616d81SHong Zhang } else { 5291e32f2f54SBarry Smith if (!rowb || !colb) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"IS rowb and colb must be provided for MAT_REUSE_MATRIX"); 529225616d81SHong Zhang isrowb = *rowb; iscolb = *colb; 5293854ce69bSBarry Smith ierr = PetscMalloc1(1,&bseq);CHKERRQ(ierr); 529425616d81SHong Zhang bseq[0] = *B_seq; 529525616d81SHong Zhang } 52967dae84e0SHong Zhang ierr = MatCreateSubMatrices(B,1,&isrowb,&iscolb,scall,&bseq);CHKERRQ(ierr); 529725616d81SHong Zhang *B_seq = bseq[0]; 529825616d81SHong Zhang ierr = PetscFree(bseq);CHKERRQ(ierr); 529925616d81SHong Zhang if (!rowb) { 53006bf464f9SBarry Smith ierr = ISDestroy(&isrowb);CHKERRQ(ierr); 530125616d81SHong Zhang } else { 530225616d81SHong Zhang *rowb = isrowb; 530325616d81SHong Zhang } 530425616d81SHong Zhang if (!colb) { 53056bf464f9SBarry Smith ierr = ISDestroy(&iscolb);CHKERRQ(ierr); 530625616d81SHong Zhang } else { 530725616d81SHong Zhang *colb = iscolb; 530825616d81SHong Zhang } 53094ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_GetBrowsOfAcols,A,B,0,0);CHKERRQ(ierr); 531025616d81SHong Zhang PetscFunctionReturn(0); 531125616d81SHong Zhang } 5312429d309bSHong Zhang 5313f8487c73SHong Zhang /* 5314f8487c73SHong Zhang MatGetBrowsOfAoCols_MPIAIJ - Creates a SeqAIJ matrix by taking rows of B that equal to nonzero columns 531501b7ae99SHong Zhang of the OFF-DIAGONAL portion of local A 5316429d309bSHong Zhang 5317429d309bSHong Zhang Collective on Mat 5318429d309bSHong Zhang 5319429d309bSHong Zhang Input Parameters: 5320429d309bSHong Zhang + A,B - the matrices in mpiaij format 5321598bc09dSHong Zhang - scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 5322429d309bSHong Zhang 5323429d309bSHong Zhang Output Parameter: 53240298fd71SBarry Smith + startsj_s - starting point in B's sending j-arrays, saved for MAT_REUSE (or NULL) 53250298fd71SBarry Smith . startsj_r - starting point in B's receiving j-arrays, saved for MAT_REUSE (or NULL) 53260298fd71SBarry Smith . bufa_ptr - array for sending matrix values, saved for MAT_REUSE (or NULL) 5327598bc09dSHong Zhang - B_oth - the sequential matrix generated with size aBn=a->B->cmap->n by B->cmap->N 5328429d309bSHong Zhang 53296eb45d04SBarry Smith Developer Notes: This directly accesses information inside the VecScatter associated with the matrix-vector product 53306eb45d04SBarry Smith for this matrix. This is not desirable.. 53316eb45d04SBarry Smith 5332429d309bSHong Zhang Level: developer 5333429d309bSHong Zhang 5334f8487c73SHong Zhang */ 5335b7f45c76SHong Zhang PetscErrorCode MatGetBrowsOfAoCols_MPIAIJ(Mat A,Mat B,MatReuse scall,PetscInt **startsj_s,PetscInt **startsj_r,MatScalar **bufa_ptr,Mat *B_oth) 5336429d309bSHong Zhang { 5337429d309bSHong Zhang PetscErrorCode ierr; 5338899cda47SBarry Smith Mat_MPIAIJ *a=(Mat_MPIAIJ*)A->data; 533987025532SHong Zhang Mat_SeqAIJ *b_oth; 53404b8d542aSHong Zhang VecScatter ctx; 5341ce94432eSBarry Smith MPI_Comm comm; 53423515ee7fSJunchao Zhang const PetscMPIInt *rprocs,*sprocs; 53433515ee7fSJunchao Zhang const PetscInt *srow,*rstarts,*sstarts; 53443515ee7fSJunchao Zhang PetscInt *rowlen,*bufj,*bufJ,ncols,aBn=a->B->cmap->n,row,*b_othi,*b_othj,*rvalues=NULL,*svalues=NULL,*cols,sbs,rbs; 53453515ee7fSJunchao Zhang PetscInt i,j,k=0,l,ll,nrecvs,nsends,nrows,*rstartsj = 0,*sstartsj,len; 5346803a1b88SHong Zhang PetscScalar *b_otha,*bufa,*bufA,*vals; 53470298fd71SBarry Smith MPI_Request *rwaits = NULL,*swaits = NULL; 53483515ee7fSJunchao Zhang MPI_Status rstatus; 53493515ee7fSJunchao Zhang PetscMPIInt jj,size,tag,rank,nsends_mpi,nrecvs_mpi; 5350429d309bSHong Zhang 5351429d309bSHong Zhang PetscFunctionBegin; 5352ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 5353a7c7454dSHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 5354a7c7454dSHong Zhang 5355d0f46423SBarry Smith if (A->cmap->rstart != B->rmap->rstart || A->cmap->rend != B->rmap->rend) { 5356e32f2f54SBarry 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); 5357429d309bSHong Zhang } 53584ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_GetBrowsOfAocols,A,B,0,0);CHKERRQ(ierr); 5359a6b2eed2SHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 5360a6b2eed2SHong Zhang 5361ec07b8f8SHong Zhang if (size == 1) { 5362ec07b8f8SHong Zhang startsj_s = NULL; 5363ec07b8f8SHong Zhang bufa_ptr = NULL; 536452f7967eSHong Zhang *B_oth = NULL; 5365ec07b8f8SHong Zhang PetscFunctionReturn(0); 5366ec07b8f8SHong Zhang } 5367ec07b8f8SHong Zhang 5368fa83eaafSHong Zhang ctx = a->Mvctx; 53694b8d542aSHong Zhang tag = ((PetscObject)ctx)->tag; 53704b8d542aSHong Zhang 53713515ee7fSJunchao Zhang if (ctx->inuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE," Scatter ctx already in use"); 53723515ee7fSJunchao Zhang ierr = VecScatterGetRemote_Private(ctx,PETSC_TRUE/*send*/,&nsends,&sstarts,&srow,&sprocs,&sbs);CHKERRQ(ierr); 53733515ee7fSJunchao Zhang /* rprocs[] must be ordered so that indices received from them are ordered in rvalues[], which is key to algorithms used in this subroutine */ 53743515ee7fSJunchao Zhang ierr = VecScatterGetRemoteOrdered_Private(ctx,PETSC_FALSE/*recv*/,&nrecvs,&rstarts,NULL/*indices not needed*/,&rprocs,&rbs);CHKERRQ(ierr); 53753515ee7fSJunchao Zhang ierr = PetscMPIIntCast(nsends,&nsends_mpi);CHKERRQ(ierr); 53763515ee7fSJunchao Zhang ierr = PetscMPIIntCast(nrecvs,&nrecvs_mpi);CHKERRQ(ierr); 5377dcca6d9dSJed Brown ierr = PetscMalloc2(nrecvs,&rwaits,nsends,&swaits);CHKERRQ(ierr); 5378429d309bSHong Zhang 5379b7f45c76SHong Zhang if (!startsj_s || !bufa_ptr) scall = MAT_INITIAL_MATRIX; 5380429d309bSHong Zhang if (scall == MAT_INITIAL_MATRIX) { 5381a6b2eed2SHong Zhang /* i-array */ 5382a6b2eed2SHong Zhang /*---------*/ 5383a6b2eed2SHong Zhang /* post receives */ 53843515ee7fSJunchao Zhang if (nrecvs) {ierr = PetscMalloc1(rbs*(rstarts[nrecvs] - rstarts[0]),&rvalues);CHKERRQ(ierr);} /* rstarts can be NULL when nrecvs=0 */ 5385a6b2eed2SHong Zhang for (i=0; i<nrecvs; i++) { 538674268593SBarry Smith rowlen = rvalues + rstarts[i]*rbs; 5387e42f35eeSHong Zhang nrows = (rstarts[i+1]-rstarts[i])*rbs; /* num of indices to be received */ 538887025532SHong Zhang ierr = MPI_Irecv(rowlen,nrows,MPIU_INT,rprocs[i],tag,comm,rwaits+i);CHKERRQ(ierr); 5389429d309bSHong Zhang } 5390a6b2eed2SHong Zhang 5391a6b2eed2SHong Zhang /* pack the outgoing message */ 5392dcca6d9dSJed Brown ierr = PetscMalloc2(nsends+1,&sstartsj,nrecvs+1,&rstartsj);CHKERRQ(ierr); 53932205254eSKarl Rupp 53942205254eSKarl Rupp sstartsj[0] = 0; 53952205254eSKarl Rupp rstartsj[0] = 0; 5396a6b2eed2SHong Zhang len = 0; /* total length of j or a array to be sent */ 53973515ee7fSJunchao Zhang if (nsends) { 53983515ee7fSJunchao Zhang k = sstarts[0]; /* ATTENTION: sstarts[0] and rstarts[0] are not necessarily zero */ 539974268593SBarry Smith ierr = PetscMalloc1(sbs*(sstarts[nsends]-sstarts[0]),&svalues);CHKERRQ(ierr); 54003515ee7fSJunchao Zhang } 5401a6b2eed2SHong Zhang for (i=0; i<nsends; i++) { 54023515ee7fSJunchao Zhang rowlen = svalues + (sstarts[i]-sstarts[0])*sbs; 5403e42f35eeSHong Zhang nrows = sstarts[i+1]-sstarts[i]; /* num of block rows */ 540487025532SHong Zhang for (j=0; j<nrows; j++) { 5405d0f46423SBarry Smith row = srow[k] + B->rmap->range[rank]; /* global row idx */ 5406e42f35eeSHong Zhang for (l=0; l<sbs; l++) { 54070298fd71SBarry Smith ierr = MatGetRow_MPIAIJ(B,row+l,&ncols,NULL,NULL);CHKERRQ(ierr); /* rowlength */ 54082205254eSKarl Rupp 5409e42f35eeSHong Zhang rowlen[j*sbs+l] = ncols; 54102205254eSKarl Rupp 5411e42f35eeSHong Zhang len += ncols; 54120298fd71SBarry Smith ierr = MatRestoreRow_MPIAIJ(B,row+l,&ncols,NULL,NULL);CHKERRQ(ierr); 5413e42f35eeSHong Zhang } 5414a6b2eed2SHong Zhang k++; 5415429d309bSHong Zhang } 5416e42f35eeSHong Zhang ierr = MPI_Isend(rowlen,nrows*sbs,MPIU_INT,sprocs[i],tag,comm,swaits+i);CHKERRQ(ierr); 54172205254eSKarl Rupp 5418dea91ad1SHong Zhang sstartsj[i+1] = len; /* starting point of (i+1)-th outgoing msg in bufj and bufa */ 5419429d309bSHong Zhang } 542087025532SHong Zhang /* recvs and sends of i-array are completed */ 542187025532SHong Zhang i = nrecvs; 542287025532SHong Zhang while (i--) { 54233515ee7fSJunchao Zhang ierr = MPI_Waitany(nrecvs_mpi,rwaits,&jj,&rstatus);CHKERRQ(ierr); 542487025532SHong Zhang } 54253515ee7fSJunchao Zhang if (nsends) {ierr = MPI_Waitall(nsends_mpi,swaits,MPI_STATUSES_IGNORE);CHKERRQ(ierr);} 542674268593SBarry Smith ierr = PetscFree(svalues);CHKERRQ(ierr); 5427e42f35eeSHong Zhang 5428a6b2eed2SHong Zhang /* allocate buffers for sending j and a arrays */ 5429854ce69bSBarry Smith ierr = PetscMalloc1(len+1,&bufj);CHKERRQ(ierr); 5430854ce69bSBarry Smith ierr = PetscMalloc1(len+1,&bufa);CHKERRQ(ierr); 5431a6b2eed2SHong Zhang 543287025532SHong Zhang /* create i-array of B_oth */ 5433854ce69bSBarry Smith ierr = PetscMalloc1(aBn+2,&b_othi);CHKERRQ(ierr); 54342205254eSKarl Rupp 543587025532SHong Zhang b_othi[0] = 0; 5436a6b2eed2SHong Zhang len = 0; /* total length of j or a array to be received */ 5437a6b2eed2SHong Zhang k = 0; 5438a6b2eed2SHong Zhang for (i=0; i<nrecvs; i++) { 54393515ee7fSJunchao Zhang rowlen = rvalues + (rstarts[i]-rstarts[0])*rbs; 54403515ee7fSJunchao Zhang nrows = (rstarts[i+1]-rstarts[i])*rbs; /* num of rows to be received */ 544187025532SHong Zhang for (j=0; j<nrows; j++) { 544287025532SHong Zhang b_othi[k+1] = b_othi[k] + rowlen[j]; 5443f416af30SBarry Smith ierr = PetscIntSumError(rowlen[j],len,&len);CHKERRQ(ierr); 5444f91af8c7SBarry Smith k++; 5445a6b2eed2SHong Zhang } 5446dea91ad1SHong Zhang rstartsj[i+1] = len; /* starting point of (i+1)-th incoming msg in bufj and bufa */ 5447a6b2eed2SHong Zhang } 544874268593SBarry Smith ierr = PetscFree(rvalues);CHKERRQ(ierr); 5449a6b2eed2SHong Zhang 545087025532SHong Zhang /* allocate space for j and a arrrays of B_oth */ 5451854ce69bSBarry Smith ierr = PetscMalloc1(b_othi[aBn]+1,&b_othj);CHKERRQ(ierr); 5452854ce69bSBarry Smith ierr = PetscMalloc1(b_othi[aBn]+1,&b_otha);CHKERRQ(ierr); 5453a6b2eed2SHong Zhang 545487025532SHong Zhang /* j-array */ 545587025532SHong Zhang /*---------*/ 5456a6b2eed2SHong Zhang /* post receives of j-array */ 5457a6b2eed2SHong Zhang for (i=0; i<nrecvs; i++) { 545887025532SHong Zhang nrows = rstartsj[i+1]-rstartsj[i]; /* length of the msg received */ 545987025532SHong Zhang ierr = MPI_Irecv(b_othj+rstartsj[i],nrows,MPIU_INT,rprocs[i],tag,comm,rwaits+i);CHKERRQ(ierr); 5460a6b2eed2SHong Zhang } 5461e42f35eeSHong Zhang 5462e42f35eeSHong Zhang /* pack the outgoing message j-array */ 54633515ee7fSJunchao Zhang if (nsends) k = sstarts[0]; 5464a6b2eed2SHong Zhang for (i=0; i<nsends; i++) { 5465e42f35eeSHong Zhang nrows = sstarts[i+1]-sstarts[i]; /* num of block rows */ 5466a6b2eed2SHong Zhang bufJ = bufj+sstartsj[i]; 546787025532SHong Zhang for (j=0; j<nrows; j++) { 5468d0f46423SBarry Smith row = srow[k++] + B->rmap->range[rank]; /* global row idx */ 5469e42f35eeSHong Zhang for (ll=0; ll<sbs; ll++) { 54700298fd71SBarry Smith ierr = MatGetRow_MPIAIJ(B,row+ll,&ncols,&cols,NULL);CHKERRQ(ierr); 5471a6b2eed2SHong Zhang for (l=0; l<ncols; l++) { 5472a6b2eed2SHong Zhang *bufJ++ = cols[l]; 547387025532SHong Zhang } 54740298fd71SBarry Smith ierr = MatRestoreRow_MPIAIJ(B,row+ll,&ncols,&cols,NULL);CHKERRQ(ierr); 5475e42f35eeSHong Zhang } 547687025532SHong Zhang } 547787025532SHong Zhang ierr = MPI_Isend(bufj+sstartsj[i],sstartsj[i+1]-sstartsj[i],MPIU_INT,sprocs[i],tag,comm,swaits+i);CHKERRQ(ierr); 547887025532SHong Zhang } 547987025532SHong Zhang 548087025532SHong Zhang /* recvs and sends of j-array are completed */ 548187025532SHong Zhang i = nrecvs; 548287025532SHong Zhang while (i--) { 54833515ee7fSJunchao Zhang ierr = MPI_Waitany(nrecvs_mpi,rwaits,&jj,&rstatus);CHKERRQ(ierr); 548487025532SHong Zhang } 54853515ee7fSJunchao Zhang if (nsends) {ierr = MPI_Waitall(nsends_mpi,swaits,MPI_STATUSES_IGNORE);CHKERRQ(ierr);} 548687025532SHong Zhang } else if (scall == MAT_REUSE_MATRIX) { 5487b7f45c76SHong Zhang sstartsj = *startsj_s; 54881d79065fSBarry Smith rstartsj = *startsj_r; 548987025532SHong Zhang bufa = *bufa_ptr; 549087025532SHong Zhang b_oth = (Mat_SeqAIJ*)(*B_oth)->data; 549187025532SHong Zhang b_otha = b_oth->a; 5492f23aa3ddSBarry Smith } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Matrix P does not posses an object container"); 549387025532SHong Zhang 549487025532SHong Zhang /* a-array */ 549587025532SHong Zhang /*---------*/ 549687025532SHong Zhang /* post receives of a-array */ 549787025532SHong Zhang for (i=0; i<nrecvs; i++) { 549887025532SHong Zhang nrows = rstartsj[i+1]-rstartsj[i]; /* length of the msg received */ 549987025532SHong Zhang ierr = MPI_Irecv(b_otha+rstartsj[i],nrows,MPIU_SCALAR,rprocs[i],tag,comm,rwaits+i);CHKERRQ(ierr); 550087025532SHong Zhang } 5501e42f35eeSHong Zhang 5502e42f35eeSHong Zhang /* pack the outgoing message a-array */ 55033515ee7fSJunchao Zhang if (nsends) k = sstarts[0]; 550487025532SHong Zhang for (i=0; i<nsends; i++) { 5505e42f35eeSHong Zhang nrows = sstarts[i+1]-sstarts[i]; /* num of block rows */ 550687025532SHong Zhang bufA = bufa+sstartsj[i]; 550787025532SHong Zhang for (j=0; j<nrows; j++) { 5508d0f46423SBarry Smith row = srow[k++] + B->rmap->range[rank]; /* global row idx */ 5509e42f35eeSHong Zhang for (ll=0; ll<sbs; ll++) { 55100298fd71SBarry Smith ierr = MatGetRow_MPIAIJ(B,row+ll,&ncols,NULL,&vals);CHKERRQ(ierr); 551187025532SHong Zhang for (l=0; l<ncols; l++) { 5512a6b2eed2SHong Zhang *bufA++ = vals[l]; 5513a6b2eed2SHong Zhang } 55140298fd71SBarry Smith ierr = MatRestoreRow_MPIAIJ(B,row+ll,&ncols,NULL,&vals);CHKERRQ(ierr); 5515e42f35eeSHong Zhang } 5516a6b2eed2SHong Zhang } 551787025532SHong Zhang ierr = MPI_Isend(bufa+sstartsj[i],sstartsj[i+1]-sstartsj[i],MPIU_SCALAR,sprocs[i],tag,comm,swaits+i);CHKERRQ(ierr); 5518a6b2eed2SHong Zhang } 551987025532SHong Zhang /* recvs and sends of a-array are completed */ 552087025532SHong Zhang i = nrecvs; 552187025532SHong Zhang while (i--) { 55223515ee7fSJunchao Zhang ierr = MPI_Waitany(nrecvs_mpi,rwaits,&jj,&rstatus);CHKERRQ(ierr); 552387025532SHong Zhang } 55243515ee7fSJunchao Zhang if (nsends) {ierr = MPI_Waitall(nsends_mpi,swaits,MPI_STATUSES_IGNORE);CHKERRQ(ierr);} 5525d7ee0231SBarry Smith ierr = PetscFree2(rwaits,swaits);CHKERRQ(ierr); 5526a6b2eed2SHong Zhang 552787025532SHong Zhang if (scall == MAT_INITIAL_MATRIX) { 5528a6b2eed2SHong Zhang /* put together the new matrix */ 5529d0f46423SBarry Smith ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,aBn,B->cmap->N,b_othi,b_othj,b_otha,B_oth);CHKERRQ(ierr); 5530a6b2eed2SHong Zhang 5531a6b2eed2SHong Zhang /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 5532a6b2eed2SHong Zhang /* Since these are PETSc arrays, change flags to free them as necessary. */ 553387025532SHong Zhang b_oth = (Mat_SeqAIJ*)(*B_oth)->data; 5534e6b907acSBarry Smith b_oth->free_a = PETSC_TRUE; 5535e6b907acSBarry Smith b_oth->free_ij = PETSC_TRUE; 553687025532SHong Zhang b_oth->nonew = 0; 5537a6b2eed2SHong Zhang 5538a6b2eed2SHong Zhang ierr = PetscFree(bufj);CHKERRQ(ierr); 5539b7f45c76SHong Zhang if (!startsj_s || !bufa_ptr) { 55401d79065fSBarry Smith ierr = PetscFree2(sstartsj,rstartsj);CHKERRQ(ierr); 5541dea91ad1SHong Zhang ierr = PetscFree(bufa_ptr);CHKERRQ(ierr); 5542dea91ad1SHong Zhang } else { 5543b7f45c76SHong Zhang *startsj_s = sstartsj; 55441d79065fSBarry Smith *startsj_r = rstartsj; 554587025532SHong Zhang *bufa_ptr = bufa; 554687025532SHong Zhang } 5547dea91ad1SHong Zhang } 55483515ee7fSJunchao Zhang 55493515ee7fSJunchao Zhang ierr = VecScatterRestoreRemote_Private(ctx,PETSC_TRUE,&nsends,&sstarts,&srow,&sprocs,&sbs);CHKERRQ(ierr); 55503515ee7fSJunchao Zhang ierr = VecScatterRestoreRemoteOrdered_Private(ctx,PETSC_FALSE,&nrecvs,&rstarts,NULL,&rprocs,&rbs);CHKERRQ(ierr); 55514ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_GetBrowsOfAocols,A,B,0,0);CHKERRQ(ierr); 5552429d309bSHong Zhang PetscFunctionReturn(0); 5553429d309bSHong Zhang } 5554ccd8e176SBarry Smith 555543eb5e2fSMatthew Knepley /*@C 555643eb5e2fSMatthew Knepley MatGetCommunicationStructs - Provides access to the communication structures used in matrix-vector multiplication. 555743eb5e2fSMatthew Knepley 555843eb5e2fSMatthew Knepley Not Collective 555943eb5e2fSMatthew Knepley 556043eb5e2fSMatthew Knepley Input Parameters: 556143eb5e2fSMatthew Knepley . A - The matrix in mpiaij format 556243eb5e2fSMatthew Knepley 556343eb5e2fSMatthew Knepley Output Parameter: 556443eb5e2fSMatthew Knepley + lvec - The local vector holding off-process values from the argument to a matrix-vector product 556543eb5e2fSMatthew Knepley . colmap - A map from global column index to local index into lvec 556643eb5e2fSMatthew Knepley - multScatter - A scatter from the argument of a matrix-vector product to lvec 556743eb5e2fSMatthew Knepley 556843eb5e2fSMatthew Knepley Level: developer 556943eb5e2fSMatthew Knepley 557043eb5e2fSMatthew Knepley @*/ 557143eb5e2fSMatthew Knepley #if defined(PETSC_USE_CTABLE) 55727087cfbeSBarry Smith PetscErrorCode MatGetCommunicationStructs(Mat A, Vec *lvec, PetscTable *colmap, VecScatter *multScatter) 557343eb5e2fSMatthew Knepley #else 55747087cfbeSBarry Smith PetscErrorCode MatGetCommunicationStructs(Mat A, Vec *lvec, PetscInt *colmap[], VecScatter *multScatter) 557543eb5e2fSMatthew Knepley #endif 557643eb5e2fSMatthew Knepley { 557743eb5e2fSMatthew Knepley Mat_MPIAIJ *a; 557843eb5e2fSMatthew Knepley 557943eb5e2fSMatthew Knepley PetscFunctionBegin; 55800700a824SBarry Smith PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 5581e414b56bSJed Brown PetscValidPointer(lvec, 2); 5582e414b56bSJed Brown PetscValidPointer(colmap, 3); 5583e414b56bSJed Brown PetscValidPointer(multScatter, 4); 558443eb5e2fSMatthew Knepley a = (Mat_MPIAIJ*) A->data; 558543eb5e2fSMatthew Knepley if (lvec) *lvec = a->lvec; 558643eb5e2fSMatthew Knepley if (colmap) *colmap = a->colmap; 558743eb5e2fSMatthew Knepley if (multScatter) *multScatter = a->Mvctx; 558843eb5e2fSMatthew Knepley PetscFunctionReturn(0); 558943eb5e2fSMatthew Knepley } 559043eb5e2fSMatthew Knepley 5591cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPIAIJCRL(Mat,MatType,MatReuse,Mat*); 5592cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPIAIJPERM(Mat,MatType,MatReuse,Mat*); 5593ca9cdca7SRichard Tran Mills PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPIAIJSELL(Mat,MatType,MatReuse,Mat*); 55949779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 5595a84739b8SRichard Tran Mills PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPIAIJMKL(Mat,MatType,MatReuse,Mat*); 5596191b95cbSRichard Tran Mills #endif 5597cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPISBAIJ(Mat,MatType,MatReuse,Mat*); 55985d7652ecSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 5599cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_Elemental(Mat,MatType,MatReuse,Mat*); 56005d7652ecSHong Zhang #endif 560163c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 560263c07aadSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_AIJ_HYPRE(Mat,MatType,MatReuse,Mat*); 56033dad0653Sstefano_zampini PETSC_INTERN PetscErrorCode MatMatMatMult_Transpose_AIJ_AIJ(Mat,Mat,Mat,MatReuse,PetscReal,Mat*); 560463c07aadSStefano Zampini #endif 5605c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat,MatType,MatReuse,Mat*); 5606d4002b98SHong Zhang PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPISELL(Mat,MatType,MatReuse,Mat*); 560775d48cdbSStefano Zampini PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat,Mat,MatReuse,PetscReal,Mat*); 560817667f90SBarry Smith 5609fc4dec0aSBarry Smith /* 5610fc4dec0aSBarry Smith Computes (B'*A')' since computing B*A directly is untenable 5611fc4dec0aSBarry Smith 5612fc4dec0aSBarry Smith n p p 5613fc4dec0aSBarry Smith ( ) ( ) ( ) 5614fc4dec0aSBarry Smith m ( A ) * n ( B ) = m ( C ) 5615fc4dec0aSBarry Smith ( ) ( ) ( ) 5616fc4dec0aSBarry Smith 5617fc4dec0aSBarry Smith */ 5618fc4dec0aSBarry Smith PetscErrorCode MatMatMultNumeric_MPIDense_MPIAIJ(Mat A,Mat B,Mat C) 5619fc4dec0aSBarry Smith { 5620fc4dec0aSBarry Smith PetscErrorCode ierr; 5621fc4dec0aSBarry Smith Mat At,Bt,Ct; 5622fc4dec0aSBarry Smith 5623fc4dec0aSBarry Smith PetscFunctionBegin; 5624fc4dec0aSBarry Smith ierr = MatTranspose(A,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr); 5625fc4dec0aSBarry Smith ierr = MatTranspose(B,MAT_INITIAL_MATRIX,&Bt);CHKERRQ(ierr); 5626fc4dec0aSBarry Smith ierr = MatMatMult(Bt,At,MAT_INITIAL_MATRIX,1.0,&Ct);CHKERRQ(ierr); 56276bf464f9SBarry Smith ierr = MatDestroy(&At);CHKERRQ(ierr); 56286bf464f9SBarry Smith ierr = MatDestroy(&Bt);CHKERRQ(ierr); 5629fc4dec0aSBarry Smith ierr = MatTranspose(Ct,MAT_REUSE_MATRIX,&C);CHKERRQ(ierr); 56306bf464f9SBarry Smith ierr = MatDestroy(&Ct);CHKERRQ(ierr); 5631fc4dec0aSBarry Smith PetscFunctionReturn(0); 5632fc4dec0aSBarry Smith } 5633fc4dec0aSBarry Smith 5634fc4dec0aSBarry Smith PetscErrorCode MatMatMultSymbolic_MPIDense_MPIAIJ(Mat A,Mat B,PetscReal fill,Mat *C) 5635fc4dec0aSBarry Smith { 5636fc4dec0aSBarry Smith PetscErrorCode ierr; 5637d0f46423SBarry Smith PetscInt m=A->rmap->n,n=B->cmap->n; 5638fc4dec0aSBarry Smith Mat Cmat; 5639fc4dec0aSBarry Smith 5640fc4dec0aSBarry Smith PetscFunctionBegin; 5641e32f2f54SBarry 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); 5642ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)A),&Cmat);CHKERRQ(ierr); 5643fc4dec0aSBarry Smith ierr = MatSetSizes(Cmat,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 564433d57670SJed Brown ierr = MatSetBlockSizesFromMats(Cmat,A,B);CHKERRQ(ierr); 5645fc4dec0aSBarry Smith ierr = MatSetType(Cmat,MATMPIDENSE);CHKERRQ(ierr); 56460298fd71SBarry Smith ierr = MatMPIDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr); 564738556019SBarry Smith ierr = MatAssemblyBegin(Cmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 564838556019SBarry Smith ierr = MatAssemblyEnd(Cmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 5649f75ecaa4SHong Zhang 5650f75ecaa4SHong Zhang Cmat->ops->matmultnumeric = MatMatMultNumeric_MPIDense_MPIAIJ; 56512205254eSKarl Rupp 5652fc4dec0aSBarry Smith *C = Cmat; 5653fc4dec0aSBarry Smith PetscFunctionReturn(0); 5654fc4dec0aSBarry Smith } 5655fc4dec0aSBarry Smith 5656fc4dec0aSBarry Smith /* ----------------------------------------------------------------*/ 5657150d2497SBarry Smith PETSC_INTERN PetscErrorCode MatMatMult_MPIDense_MPIAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 5658fc4dec0aSBarry Smith { 5659fc4dec0aSBarry Smith PetscErrorCode ierr; 5660fc4dec0aSBarry Smith 5661fc4dec0aSBarry Smith PetscFunctionBegin; 5662fc4dec0aSBarry Smith if (scall == MAT_INITIAL_MATRIX) { 56633ff4c91cSHong Zhang ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 5664fc4dec0aSBarry Smith ierr = MatMatMultSymbolic_MPIDense_MPIAIJ(A,B,fill,C);CHKERRQ(ierr); 56653ff4c91cSHong Zhang ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 5666fc4dec0aSBarry Smith } 56673ff4c91cSHong Zhang ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 5668fc4dec0aSBarry Smith ierr = MatMatMultNumeric_MPIDense_MPIAIJ(A,B,*C);CHKERRQ(ierr); 56693ff4c91cSHong Zhang ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 5670fc4dec0aSBarry Smith PetscFunctionReturn(0); 5671fc4dec0aSBarry Smith } 5672fc4dec0aSBarry Smith 5673ccd8e176SBarry Smith /*MC 5674ccd8e176SBarry Smith MATMPIAIJ - MATMPIAIJ = "mpiaij" - A matrix type to be used for parallel sparse matrices. 5675ccd8e176SBarry Smith 5676ccd8e176SBarry Smith Options Database Keys: 5677ccd8e176SBarry Smith . -mat_type mpiaij - sets the matrix type to "mpiaij" during a call to MatSetFromOptions() 5678ccd8e176SBarry Smith 5679ccd8e176SBarry Smith Level: beginner 5680ccd8e176SBarry Smith 568169b1f4b7SBarry Smith .seealso: MatCreateAIJ() 5682ccd8e176SBarry Smith M*/ 5683ccd8e176SBarry Smith 56848cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_MPIAIJ(Mat B) 5685ccd8e176SBarry Smith { 5686ccd8e176SBarry Smith Mat_MPIAIJ *b; 5687ccd8e176SBarry Smith PetscErrorCode ierr; 5688ccd8e176SBarry Smith PetscMPIInt size; 5689ccd8e176SBarry Smith 5690ccd8e176SBarry Smith PetscFunctionBegin; 5691ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr); 56922205254eSKarl Rupp 5693b00a9115SJed Brown ierr = PetscNewLog(B,&b);CHKERRQ(ierr); 5694ccd8e176SBarry Smith B->data = (void*)b; 5695ccd8e176SBarry Smith ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 5696ccd8e176SBarry Smith B->assembled = PETSC_FALSE; 5697ccd8e176SBarry Smith B->insertmode = NOT_SET_VALUES; 5698ccd8e176SBarry Smith b->size = size; 56992205254eSKarl Rupp 5700ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)B),&b->rank);CHKERRQ(ierr); 5701ccd8e176SBarry Smith 5702ccd8e176SBarry Smith /* build cache for off array entries formed */ 5703ce94432eSBarry Smith ierr = MatStashCreate_Private(PetscObjectComm((PetscObject)B),1,&B->stash);CHKERRQ(ierr); 57042205254eSKarl Rupp 5705ccd8e176SBarry Smith b->donotstash = PETSC_FALSE; 5706ccd8e176SBarry Smith b->colmap = 0; 5707ccd8e176SBarry Smith b->garray = 0; 5708ccd8e176SBarry Smith b->roworiented = PETSC_TRUE; 5709ccd8e176SBarry Smith 5710ccd8e176SBarry Smith /* stuff used for matrix vector multiply */ 57110298fd71SBarry Smith b->lvec = NULL; 57120298fd71SBarry Smith b->Mvctx = NULL; 5713ccd8e176SBarry Smith 5714ccd8e176SBarry Smith /* stuff for MatGetRow() */ 5715ccd8e176SBarry Smith b->rowindices = 0; 5716ccd8e176SBarry Smith b->rowvalues = 0; 5717ccd8e176SBarry Smith b->getrowactive = PETSC_FALSE; 5718ccd8e176SBarry Smith 5719bbf3fe20SPaul Mullowney /* flexible pointer used in CUSP/CUSPARSE classes */ 57200298fd71SBarry Smith b->spptr = NULL; 5721f60c3dc2SHong Zhang 5722b1b1104fSBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMPIAIJSetUseScalableIncreaseOverlap_C",MatMPIAIJSetUseScalableIncreaseOverlap_MPIAIJ);CHKERRQ(ierr); 5723bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_MPIAIJ);CHKERRQ(ierr); 5724bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_MPIAIJ);CHKERRQ(ierr); 5725bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_MPIAIJ);CHKERRQ(ierr); 5726bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMPIAIJSetPreallocation_C",MatMPIAIJSetPreallocation_MPIAIJ);CHKERRQ(ierr); 5727846b4da1SFande Kong ierr = PetscObjectComposeFunction((PetscObject)B,"MatResetPreallocation_C",MatResetPreallocation_MPIAIJ);CHKERRQ(ierr); 5728bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMPIAIJSetPreallocationCSR_C",MatMPIAIJSetPreallocationCSR_MPIAIJ);CHKERRQ(ierr); 5729bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatDiagonalScaleLocal_C",MatDiagonalScaleLocal_MPIAIJ);CHKERRQ(ierr); 5730bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_mpiaijperm_C",MatConvert_MPIAIJ_MPIAIJPERM);CHKERRQ(ierr); 5731ca9cdca7SRichard Tran Mills ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_mpiaijsell_C",MatConvert_MPIAIJ_MPIAIJSELL);CHKERRQ(ierr); 57329779e05dSSatish Balay #if defined(PETSC_HAVE_MKL_SPARSE) 5733a84739b8SRichard Tran Mills ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_mpiaijmkl_C",MatConvert_MPIAIJ_MPIAIJMKL);CHKERRQ(ierr); 5734191b95cbSRichard Tran Mills #endif 5735bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_mpiaijcrl_C",MatConvert_MPIAIJ_MPIAIJCRL);CHKERRQ(ierr); 5736bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_mpisbaij_C",MatConvert_MPIAIJ_MPISBAIJ);CHKERRQ(ierr); 57375d7652ecSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 57385d7652ecSHong Zhang ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_elemental_C",MatConvert_MPIAIJ_Elemental);CHKERRQ(ierr); 57395d7652ecSHong Zhang #endif 574063c07aadSStefano Zampini #if defined(PETSC_HAVE_HYPRE) 574163c07aadSStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_hypre_C",MatConvert_AIJ_HYPRE);CHKERRQ(ierr); 574263c07aadSStefano Zampini #endif 5743c9225affSStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_is_C",MatConvert_XAIJ_IS);CHKERRQ(ierr); 5744d4002b98SHong Zhang ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_mpisell_C",MatConvert_MPIAIJ_MPISELL);CHKERRQ(ierr); 5745bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_mpidense_mpiaij_C",MatMatMult_MPIDense_MPIAIJ);CHKERRQ(ierr); 5746bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_mpidense_mpiaij_C",MatMatMultSymbolic_MPIDense_MPIAIJ);CHKERRQ(ierr); 5747bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_mpidense_mpiaij_C",MatMatMultNumeric_MPIDense_MPIAIJ);CHKERRQ(ierr); 57483dad0653Sstefano_zampini #if defined(PETSC_HAVE_HYPRE) 57493dad0653Sstefano_zampini ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMatMult_transpose_mpiaij_mpiaij_C",MatMatMatMult_Transpose_AIJ_AIJ);CHKERRQ(ierr); 57503dad0653Sstefano_zampini #endif 575175d48cdbSStefano Zampini ierr = PetscObjectComposeFunction((PetscObject)B,"MatPtAP_is_mpiaij_C",MatPtAP_IS_XAIJ);CHKERRQ(ierr); 575217667f90SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)B,MATMPIAIJ);CHKERRQ(ierr); 5753ccd8e176SBarry Smith PetscFunctionReturn(0); 5754ccd8e176SBarry Smith } 575581824310SBarry Smith 5756cce60c4dSBarry Smith /*@C 575703bfb495SBarry Smith MatCreateMPIAIJWithSplitArrays - creates a MPI AIJ matrix using arrays that contain the "diagonal" 575803bfb495SBarry Smith and "off-diagonal" part of the matrix in CSR format. 575903bfb495SBarry Smith 5760d083f849SBarry Smith Collective 576103bfb495SBarry Smith 576203bfb495SBarry Smith Input Parameters: 576303bfb495SBarry Smith + comm - MPI communicator 576403bfb495SBarry Smith . m - number of local rows (Cannot be PETSC_DECIDE) 576503bfb495SBarry Smith . n - This value should be the same as the local size used in creating the 576603bfb495SBarry Smith x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have 576703bfb495SBarry Smith calculated if N is given) For square matrices n is almost always m. 576803bfb495SBarry Smith . M - number of global rows (or PETSC_DETERMINE to have calculated if m is given) 576903bfb495SBarry Smith . N - number of global columns (or PETSC_DETERMINE to have calculated if n is given) 5770483a2f95SBarry Smith . i - row indices for "diagonal" portion of matrix; that is i[0] = 0, i[row] = i[row-1] + number of elements in that row of the matrix 577103bfb495SBarry Smith . j - column indices 577203bfb495SBarry Smith . a - matrix values 5773483a2f95SBarry Smith . oi - row indices for "off-diagonal" portion of matrix; that is oi[0] = 0, oi[row] = oi[row-1] + number of elements in that row of the matrix 577403bfb495SBarry Smith . oj - column indices 577503bfb495SBarry Smith - oa - matrix values 577603bfb495SBarry Smith 577703bfb495SBarry Smith Output Parameter: 577803bfb495SBarry Smith . mat - the matrix 577903bfb495SBarry Smith 578003bfb495SBarry Smith Level: advanced 578103bfb495SBarry Smith 578203bfb495SBarry Smith Notes: 5783292fb18eSBarry Smith The i, j, and a arrays ARE NOT copied by this routine into the internal format used by PETSc. The user 5784292fb18eSBarry Smith must free the arrays once the matrix has been destroyed and not before. 578503bfb495SBarry Smith 578603bfb495SBarry Smith The i and j indices are 0 based 578703bfb495SBarry Smith 578869b1f4b7SBarry Smith See MatCreateAIJ() for the definition of "diagonal" and "off-diagonal" portion of the matrix 578903bfb495SBarry Smith 57907b55108eSBarry Smith This sets local rows and cannot be used to set off-processor values. 57917b55108eSBarry Smith 5792dca341c0SJed Brown Use of this routine is discouraged because it is inflexible and cumbersome to use. It is extremely rare that a 5793dca341c0SJed Brown legacy application natively assembles into exactly this split format. The code to do so is nontrivial and does 5794dca341c0SJed Brown not easily support in-place reassembly. It is recommended to use MatSetValues() (or a variant thereof) because 5795dca341c0SJed Brown the resulting assembly is easier to implement, will work with any matrix format, and the user does not have to 5796eeb24464SBarry Smith keep track of the underlying array. Use MatSetOption(A,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE) to disable all 5797dca341c0SJed Brown communication if it is known that only local entries will be set. 579803bfb495SBarry Smith 579903bfb495SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(), 58005f4d30c4SBarry Smith MATMPIAIJ, MatCreateAIJ(), MatCreateMPIAIJWithArrays() 58012b26979fSBarry Smith @*/ 58022205254eSKarl Rupp PetscErrorCode MatCreateMPIAIJWithSplitArrays(MPI_Comm comm,PetscInt m,PetscInt n,PetscInt M,PetscInt N,PetscInt i[],PetscInt j[],PetscScalar a[],PetscInt oi[], PetscInt oj[],PetscScalar oa[],Mat *mat) 580303bfb495SBarry Smith { 580403bfb495SBarry Smith PetscErrorCode ierr; 580503bfb495SBarry Smith Mat_MPIAIJ *maij; 580603bfb495SBarry Smith 580703bfb495SBarry Smith PetscFunctionBegin; 5808e32f2f54SBarry Smith if (m < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"local number of rows (m) cannot be PETSC_DECIDE, or negative"); 5809ea345e14SBarry Smith if (i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 5810ea345e14SBarry Smith if (oi[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"oi (row indices) must start with 0"); 581103bfb495SBarry Smith ierr = MatCreate(comm,mat);CHKERRQ(ierr); 581203bfb495SBarry Smith ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr); 581303bfb495SBarry Smith ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr); 581403bfb495SBarry Smith maij = (Mat_MPIAIJ*) (*mat)->data; 58152205254eSKarl Rupp 58168d7a6e47SBarry Smith (*mat)->preallocated = PETSC_TRUE; 581703bfb495SBarry Smith 581826283091SBarry Smith ierr = PetscLayoutSetUp((*mat)->rmap);CHKERRQ(ierr); 581926283091SBarry Smith ierr = PetscLayoutSetUp((*mat)->cmap);CHKERRQ(ierr); 582003bfb495SBarry Smith 582103bfb495SBarry Smith ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,m,n,i,j,a,&maij->A);CHKERRQ(ierr); 5822d0f46423SBarry Smith ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,m,(*mat)->cmap->N,oi,oj,oa,&maij->B);CHKERRQ(ierr); 582303bfb495SBarry Smith 58248d7a6e47SBarry Smith ierr = MatAssemblyBegin(maij->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 58258d7a6e47SBarry Smith ierr = MatAssemblyEnd(maij->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 58268d7a6e47SBarry Smith ierr = MatAssemblyBegin(maij->B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 58278d7a6e47SBarry Smith ierr = MatAssemblyEnd(maij->B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 58288d7a6e47SBarry Smith 5829eeb24464SBarry Smith ierr = MatSetOption(*mat,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr); 583003bfb495SBarry Smith ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 583103bfb495SBarry Smith ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 5832eeb24464SBarry Smith ierr = MatSetOption(*mat,MAT_NO_OFF_PROC_ENTRIES,PETSC_FALSE);CHKERRQ(ierr); 5833dca341c0SJed Brown ierr = MatSetOption(*mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 583403bfb495SBarry Smith PetscFunctionReturn(0); 583503bfb495SBarry Smith } 583603bfb495SBarry Smith 583781824310SBarry Smith /* 583881824310SBarry Smith Special version for direct calls from Fortran 583981824310SBarry Smith */ 5840af0996ceSBarry Smith #include <petsc/private/fortranimpl.h> 58417087cfbeSBarry Smith 584281824310SBarry Smith /* Change these macros so can be used in void function */ 584381824310SBarry Smith #undef CHKERRQ 5844e32f2f54SBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PETSC_COMM_WORLD,ierr) 584581824310SBarry Smith #undef SETERRQ2 5846e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr) 58474994cf47SJed Brown #undef SETERRQ3 58484994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr) 584981824310SBarry Smith #undef SETERRQ 5850e32f2f54SBarry Smith #define SETERRQ(c,ierr,b) CHKERRABORT(c,ierr) 585181824310SBarry Smith 58522c2ad335SSatish Balay #if defined(PETSC_HAVE_FORTRAN_CAPS) 58532c2ad335SSatish Balay #define matsetvaluesmpiaij_ MATSETVALUESMPIAIJ 58542c2ad335SSatish Balay #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 58552c2ad335SSatish Balay #define matsetvaluesmpiaij_ matsetvaluesmpiaij 58562c2ad335SSatish Balay #else 58572c2ad335SSatish Balay #endif 58588cc058d9SJed Brown PETSC_EXTERN void PETSC_STDCALL matsetvaluesmpiaij_(Mat *mmat,PetscInt *mm,const PetscInt im[],PetscInt *mn,const PetscInt in[],const PetscScalar v[],InsertMode *maddv,PetscErrorCode *_ierr) 585981824310SBarry Smith { 586081824310SBarry Smith Mat mat = *mmat; 586181824310SBarry Smith PetscInt m = *mm, n = *mn; 586281824310SBarry Smith InsertMode addv = *maddv; 586381824310SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 586481824310SBarry Smith PetscScalar value; 586581824310SBarry Smith PetscErrorCode ierr; 5866899cda47SBarry Smith 58674994cf47SJed Brown MatCheckPreallocated(mat,1); 58682205254eSKarl Rupp if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 58692205254eSKarl Rupp 587081824310SBarry Smith #if defined(PETSC_USE_DEBUG) 5871f23aa3ddSBarry Smith else if (mat->insertmode != addv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values"); 587281824310SBarry Smith #endif 587381824310SBarry Smith { 5874d0f46423SBarry Smith PetscInt i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend; 5875d0f46423SBarry Smith PetscInt cstart = mat->cmap->rstart,cend = mat->cmap->rend,row,col; 5876ace3abfcSBarry Smith PetscBool roworiented = aij->roworiented; 587781824310SBarry Smith 587881824310SBarry Smith /* Some Variables required in the macro */ 587981824310SBarry Smith Mat A = aij->A; 588081824310SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 588181824310SBarry Smith PetscInt *aimax = a->imax,*ai = a->i,*ailen = a->ilen,*aj = a->j; 5882dd6ea824SBarry Smith MatScalar *aa = a->a; 5883ace3abfcSBarry Smith PetscBool ignorezeroentries = (((a->ignorezeroentries)&&(addv==ADD_VALUES)) ? PETSC_TRUE : PETSC_FALSE); 588481824310SBarry Smith Mat B = aij->B; 588581824310SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 5886d0f46423SBarry Smith PetscInt *bimax = b->imax,*bi = b->i,*bilen = b->ilen,*bj = b->j,bm = aij->B->rmap->n,am = aij->A->rmap->n; 5887dd6ea824SBarry Smith MatScalar *ba = b->a; 588881824310SBarry Smith 588981824310SBarry Smith PetscInt *rp1,*rp2,ii,nrow1,nrow2,_i,rmax1,rmax2,N,low1,high1,low2,high2,t,lastcol1,lastcol2; 589081824310SBarry Smith PetscInt nonew = a->nonew; 5891dd6ea824SBarry Smith MatScalar *ap1,*ap2; 589281824310SBarry Smith 589381824310SBarry Smith PetscFunctionBegin; 589481824310SBarry Smith for (i=0; i<m; i++) { 589581824310SBarry Smith if (im[i] < 0) continue; 589681824310SBarry Smith #if defined(PETSC_USE_DEBUG) 5897e32f2f54SBarry 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); 589881824310SBarry Smith #endif 589981824310SBarry Smith if (im[i] >= rstart && im[i] < rend) { 590081824310SBarry Smith row = im[i] - rstart; 590181824310SBarry Smith lastcol1 = -1; 590281824310SBarry Smith rp1 = aj + ai[row]; 590381824310SBarry Smith ap1 = aa + ai[row]; 590481824310SBarry Smith rmax1 = aimax[row]; 590581824310SBarry Smith nrow1 = ailen[row]; 590681824310SBarry Smith low1 = 0; 590781824310SBarry Smith high1 = nrow1; 590881824310SBarry Smith lastcol2 = -1; 590981824310SBarry Smith rp2 = bj + bi[row]; 591081824310SBarry Smith ap2 = ba + bi[row]; 591181824310SBarry Smith rmax2 = bimax[row]; 591281824310SBarry Smith nrow2 = bilen[row]; 591381824310SBarry Smith low2 = 0; 591481824310SBarry Smith high2 = nrow2; 591581824310SBarry Smith 591681824310SBarry Smith for (j=0; j<n; j++) { 59172205254eSKarl Rupp if (roworiented) value = v[i*n+j]; 59182205254eSKarl Rupp else value = v[i+j*m]; 591981824310SBarry Smith if (in[j] >= cstart && in[j] < cend) { 592081824310SBarry Smith col = in[j] - cstart; 5921dcd36c23SBarry Smith if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES) && row != col) continue; 5922d40312a9SBarry Smith MatSetValues_SeqAIJ_A_Private(row,col,value,addv,im[i],in[j]); 592381824310SBarry Smith } else if (in[j] < 0) continue; 592481824310SBarry Smith #if defined(PETSC_USE_DEBUG) 5925671f4814SSatish Balay /* extra brace on SETERRQ2() is required for --with-errorchecking=0 - due to the next 'else' clause */ 5926671f4814SSatish Balay 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);} 592781824310SBarry Smith #endif 592881824310SBarry Smith else { 592981824310SBarry Smith if (mat->was_assembled) { 593081824310SBarry Smith if (!aij->colmap) { 5931ab9863d7SBarry Smith ierr = MatCreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr); 593281824310SBarry Smith } 593381824310SBarry Smith #if defined(PETSC_USE_CTABLE) 593481824310SBarry Smith ierr = PetscTableFind(aij->colmap,in[j]+1,&col);CHKERRQ(ierr); 593581824310SBarry Smith col--; 593681824310SBarry Smith #else 593781824310SBarry Smith col = aij->colmap[in[j]] - 1; 593881824310SBarry Smith #endif 5939dcd36c23SBarry Smith if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES) && row != col) continue; 594081824310SBarry Smith if (col < 0 && !((Mat_SeqAIJ*)(aij->A->data))->nonew) { 5941ab9863d7SBarry Smith ierr = MatDisAssemble_MPIAIJ(mat);CHKERRQ(ierr); 594281824310SBarry Smith col = in[j]; 594381824310SBarry Smith /* Reinitialize the variables required by MatSetValues_SeqAIJ_B_Private() */ 594481824310SBarry Smith B = aij->B; 594581824310SBarry Smith b = (Mat_SeqAIJ*)B->data; 594681824310SBarry Smith bimax = b->imax; bi = b->i; bilen = b->ilen; bj = b->j; 594781824310SBarry Smith rp2 = bj + bi[row]; 594881824310SBarry Smith ap2 = ba + bi[row]; 594981824310SBarry Smith rmax2 = bimax[row]; 595081824310SBarry Smith nrow2 = bilen[row]; 595181824310SBarry Smith low2 = 0; 595281824310SBarry Smith high2 = nrow2; 5953d0f46423SBarry Smith bm = aij->B->rmap->n; 595481824310SBarry Smith ba = b->a; 595581824310SBarry Smith } 595681824310SBarry Smith } else col = in[j]; 5957d40312a9SBarry Smith MatSetValues_SeqAIJ_B_Private(row,col,value,addv,im[i],in[j]); 595881824310SBarry Smith } 595981824310SBarry Smith } 59602205254eSKarl Rupp } else if (!aij->donotstash) { 596181824310SBarry Smith if (roworiented) { 5962ace3abfcSBarry Smith ierr = MatStashValuesRow_Private(&mat->stash,im[i],n,in,v+i*n,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr); 596381824310SBarry Smith } else { 5964ace3abfcSBarry Smith ierr = MatStashValuesCol_Private(&mat->stash,im[i],n,in,v+i,m,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr); 596581824310SBarry Smith } 596681824310SBarry Smith } 596781824310SBarry Smith } 59682205254eSKarl Rupp } 596981824310SBarry Smith PetscFunctionReturnVoid(); 597081824310SBarry Smith } 5971