18a729477SBarry Smith 2c6db04a5SJed Brown #include <../src/mat/impls/aij/mpi/mpiaij.h> /*I "petscmat.h" I*/ 3af0996ceSBarry Smith #include <petsc/private/vecimpl.h> 4af0996ceSBarry Smith #include <petsc/private/isimpl.h> 5c6db04a5SJed Brown #include <petscblaslapack.h> 60c312b8eSJed Brown #include <petscsf.h> 78a729477SBarry Smith 801bebe75SBarry Smith /*MC 901bebe75SBarry Smith MATAIJ - MATAIJ = "aij" - A matrix type to be used for sparse matrices. 1001bebe75SBarry Smith 1101bebe75SBarry Smith This matrix type is identical to MATSEQAIJ when constructed with a single process communicator, 1201bebe75SBarry Smith and MATMPIAIJ otherwise. As a result, for single process communicators, 1301bebe75SBarry Smith MatSeqAIJSetPreallocation is supported, and similarly MatMPIAIJSetPreallocation is supported 1401bebe75SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 1501bebe75SBarry Smith the above preallocation routines for simplicity. 1601bebe75SBarry Smith 1701bebe75SBarry Smith Options Database Keys: 1801bebe75SBarry Smith . -mat_type aij - sets the matrix type to "aij" during a call to MatSetFromOptions() 1901bebe75SBarry Smith 209ae82921SPaul Mullowney Developer Notes: Subclasses include MATAIJCUSP, MATAIJCUSPARSE, MATAIJPERM, MATAIJCRL, and also automatically switches over to use inodes when 2101bebe75SBarry Smith enough exist. 2201bebe75SBarry Smith 2301bebe75SBarry Smith Level: beginner 2401bebe75SBarry Smith 2569b1f4b7SBarry Smith .seealso: MatCreateAIJ(), MatCreateSeqAIJ(), MATSEQAIJ, MATMPIAIJ 2601bebe75SBarry Smith M*/ 2701bebe75SBarry Smith 2801bebe75SBarry Smith /*MC 2901bebe75SBarry Smith MATAIJCRL - MATAIJCRL = "aijcrl" - A matrix type to be used for sparse matrices. 3001bebe75SBarry Smith 3101bebe75SBarry Smith This matrix type is identical to MATSEQAIJCRL when constructed with a single process communicator, 3201bebe75SBarry Smith and MATMPIAIJCRL otherwise. As a result, for single process communicators, 3301bebe75SBarry Smith MatSeqAIJSetPreallocation() is supported, and similarly MatMPIAIJSetPreallocation() is supported 3401bebe75SBarry Smith for communicators controlling multiple processes. It is recommended that you call both of 3501bebe75SBarry Smith the above preallocation routines for simplicity. 3601bebe75SBarry Smith 3701bebe75SBarry Smith Options Database Keys: 3801bebe75SBarry Smith . -mat_type aijcrl - sets the matrix type to "aijcrl" during a call to MatSetFromOptions() 3901bebe75SBarry Smith 4001bebe75SBarry Smith Level: beginner 4101bebe75SBarry Smith 4201bebe75SBarry Smith .seealso: MatCreateMPIAIJCRL,MATSEQAIJCRL,MATMPIAIJCRL, MATSEQAIJCRL, MATMPIAIJCRL 4301bebe75SBarry Smith M*/ 4401bebe75SBarry Smith 45dd6ea824SBarry Smith #undef __FUNCT__ 46*26bda2c4Sstefano_zampini #define __FUNCT__ "MatSetLateBlockSizes_MPIAIJ" 47*26bda2c4Sstefano_zampini PetscErrorCode MatSetLateBlockSizes_MPIAIJ(Mat M, PetscInt rbs, PetscInt cbs) 48*26bda2c4Sstefano_zampini { 49*26bda2c4Sstefano_zampini PetscErrorCode ierr; 50*26bda2c4Sstefano_zampini Mat_MPIAIJ *mat = (Mat_MPIAIJ*)M->data; 51*26bda2c4Sstefano_zampini 52*26bda2c4Sstefano_zampini PetscFunctionBegin; 53*26bda2c4Sstefano_zampini if (rbs && !cbs) { 54*26bda2c4Sstefano_zampini ierr = MatSetBlockSize(mat->A,rbs);CHKERRQ(ierr); 55*26bda2c4Sstefano_zampini ierr = MatSetBlockSize(mat->B,rbs);CHKERRQ(ierr); 56*26bda2c4Sstefano_zampini } else if (rbs && cbs) { 57*26bda2c4Sstefano_zampini ierr = MatSetBlockSizes(mat->A,rbs,cbs);CHKERRQ(ierr); 58*26bda2c4Sstefano_zampini ierr = MatSetBlockSize(mat->B,rbs);CHKERRQ(ierr); 59*26bda2c4Sstefano_zampini } else SETERRQ2(PetscObjectComm((PetscObject)M),PETSC_ERR_ARG_WRONG,"Cannot set late block sizes %D %D",rbs,cbs); 60*26bda2c4Sstefano_zampini PetscFunctionReturn(0); 61*26bda2c4Sstefano_zampini } 62*26bda2c4Sstefano_zampini 63*26bda2c4Sstefano_zampini #undef __FUNCT__ 64f2c98031SJed Brown #define __FUNCT__ "MatFindNonzeroRows_MPIAIJ" 65f2c98031SJed Brown PetscErrorCode MatFindNonzeroRows_MPIAIJ(Mat M,IS *keptrows) 6627d4218bSShri Abhyankar { 6727d4218bSShri Abhyankar PetscErrorCode ierr; 6827d4218bSShri Abhyankar Mat_MPIAIJ *mat = (Mat_MPIAIJ*)M->data; 6927d4218bSShri Abhyankar Mat_SeqAIJ *a = (Mat_SeqAIJ*)mat->A->data; 7027d4218bSShri Abhyankar Mat_SeqAIJ *b = (Mat_SeqAIJ*)mat->B->data; 7127d4218bSShri Abhyankar const PetscInt *ia,*ib; 7227d4218bSShri Abhyankar const MatScalar *aa,*bb; 7327d4218bSShri Abhyankar PetscInt na,nb,i,j,*rows,cnt=0,n0rows; 7427d4218bSShri Abhyankar PetscInt m = M->rmap->n,rstart = M->rmap->rstart; 7527d4218bSShri Abhyankar 7627d4218bSShri Abhyankar PetscFunctionBegin; 7727d4218bSShri Abhyankar *keptrows = 0; 7827d4218bSShri Abhyankar ia = a->i; 7927d4218bSShri Abhyankar ib = b->i; 8027d4218bSShri Abhyankar for (i=0; i<m; i++) { 8127d4218bSShri Abhyankar na = ia[i+1] - ia[i]; 8227d4218bSShri Abhyankar nb = ib[i+1] - ib[i]; 8327d4218bSShri Abhyankar if (!na && !nb) { 8427d4218bSShri Abhyankar cnt++; 8527d4218bSShri Abhyankar goto ok1; 8627d4218bSShri Abhyankar } 8727d4218bSShri Abhyankar aa = a->a + ia[i]; 8827d4218bSShri Abhyankar for (j=0; j<na; j++) { 8927d4218bSShri Abhyankar if (aa[j] != 0.0) goto ok1; 9027d4218bSShri Abhyankar } 9127d4218bSShri Abhyankar bb = b->a + ib[i]; 9227d4218bSShri Abhyankar for (j=0; j <nb; j++) { 9327d4218bSShri Abhyankar if (bb[j] != 0.0) goto ok1; 9427d4218bSShri Abhyankar } 9527d4218bSShri Abhyankar cnt++; 9627d4218bSShri Abhyankar ok1:; 9727d4218bSShri Abhyankar } 98b2566f29SBarry Smith ierr = MPIU_Allreduce(&cnt,&n0rows,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)M));CHKERRQ(ierr); 9927d4218bSShri Abhyankar if (!n0rows) PetscFunctionReturn(0); 100854ce69bSBarry Smith ierr = PetscMalloc1(M->rmap->n-cnt,&rows);CHKERRQ(ierr); 10127d4218bSShri Abhyankar cnt = 0; 10227d4218bSShri Abhyankar for (i=0; i<m; i++) { 10327d4218bSShri Abhyankar na = ia[i+1] - ia[i]; 10427d4218bSShri Abhyankar nb = ib[i+1] - ib[i]; 10527d4218bSShri Abhyankar if (!na && !nb) continue; 10627d4218bSShri Abhyankar aa = a->a + ia[i]; 10727d4218bSShri Abhyankar for (j=0; j<na;j++) { 10827d4218bSShri Abhyankar if (aa[j] != 0.0) { 10927d4218bSShri Abhyankar rows[cnt++] = rstart + i; 11027d4218bSShri Abhyankar goto ok2; 11127d4218bSShri Abhyankar } 11227d4218bSShri Abhyankar } 11327d4218bSShri Abhyankar bb = b->a + ib[i]; 11427d4218bSShri Abhyankar for (j=0; j<nb; j++) { 11527d4218bSShri Abhyankar if (bb[j] != 0.0) { 11627d4218bSShri Abhyankar rows[cnt++] = rstart + i; 11727d4218bSShri Abhyankar goto ok2; 11827d4218bSShri Abhyankar } 11927d4218bSShri Abhyankar } 12027d4218bSShri Abhyankar ok2:; 12127d4218bSShri Abhyankar } 122ce94432eSBarry Smith ierr = ISCreateGeneral(PetscObjectComm((PetscObject)M),cnt,rows,PETSC_OWN_POINTER,keptrows);CHKERRQ(ierr); 12327d4218bSShri Abhyankar PetscFunctionReturn(0); 12427d4218bSShri Abhyankar } 12527d4218bSShri Abhyankar 12627d4218bSShri Abhyankar #undef __FUNCT__ 12799e65526SBarry Smith #define __FUNCT__ "MatDiagonalSet_MPIAIJ" 12899e65526SBarry Smith PetscErrorCode MatDiagonalSet_MPIAIJ(Mat Y,Vec D,InsertMode is) 12999e65526SBarry Smith { 13099e65526SBarry Smith PetscErrorCode ierr; 13199e65526SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*) Y->data; 13299e65526SBarry Smith 13399e65526SBarry Smith PetscFunctionBegin; 13499e65526SBarry Smith if (Y->assembled && Y->rmap->rstart == Y->cmap->rstart && Y->rmap->rend == Y->cmap->rend) { 13599e65526SBarry Smith ierr = MatDiagonalSet(aij->A,D,is);CHKERRQ(ierr); 13699e65526SBarry Smith } else { 13799e65526SBarry Smith ierr = MatDiagonalSet_Default(Y,D,is);CHKERRQ(ierr); 13899e65526SBarry Smith } 13999e65526SBarry Smith PetscFunctionReturn(0); 14099e65526SBarry Smith } 14199e65526SBarry Smith 14299e65526SBarry Smith 14399e65526SBarry Smith #undef __FUNCT__ 144f1f41ecbSJed Brown #define __FUNCT__ "MatFindZeroDiagonals_MPIAIJ" 145f1f41ecbSJed Brown PetscErrorCode MatFindZeroDiagonals_MPIAIJ(Mat M,IS *zrows) 146f1f41ecbSJed Brown { 147f1f41ecbSJed Brown Mat_MPIAIJ *aij = (Mat_MPIAIJ*)M->data; 148f1f41ecbSJed Brown PetscErrorCode ierr; 149f1f41ecbSJed Brown PetscInt i,rstart,nrows,*rows; 150f1f41ecbSJed Brown 151f1f41ecbSJed Brown PetscFunctionBegin; 1520298fd71SBarry Smith *zrows = NULL; 153f1f41ecbSJed Brown ierr = MatFindZeroDiagonals_SeqAIJ_Private(aij->A,&nrows,&rows);CHKERRQ(ierr); 1540298fd71SBarry Smith ierr = MatGetOwnershipRange(M,&rstart,NULL);CHKERRQ(ierr); 155f1f41ecbSJed Brown for (i=0; i<nrows; i++) rows[i] += rstart; 156ce94432eSBarry Smith ierr = ISCreateGeneral(PetscObjectComm((PetscObject)M),nrows,rows,PETSC_OWN_POINTER,zrows);CHKERRQ(ierr); 157f1f41ecbSJed Brown PetscFunctionReturn(0); 158f1f41ecbSJed Brown } 159f1f41ecbSJed Brown 160f1f41ecbSJed Brown #undef __FUNCT__ 1610716a85fSBarry Smith #define __FUNCT__ "MatGetColumnNorms_MPIAIJ" 1620716a85fSBarry Smith PetscErrorCode MatGetColumnNorms_MPIAIJ(Mat A,NormType type,PetscReal *norms) 1630716a85fSBarry Smith { 1640716a85fSBarry Smith PetscErrorCode ierr; 1650716a85fSBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)A->data; 1660716a85fSBarry Smith PetscInt i,n,*garray = aij->garray; 1670716a85fSBarry Smith Mat_SeqAIJ *a_aij = (Mat_SeqAIJ*) aij->A->data; 1680716a85fSBarry Smith Mat_SeqAIJ *b_aij = (Mat_SeqAIJ*) aij->B->data; 1690716a85fSBarry Smith PetscReal *work; 1700716a85fSBarry Smith 1710716a85fSBarry Smith PetscFunctionBegin; 1720298fd71SBarry Smith ierr = MatGetSize(A,NULL,&n);CHKERRQ(ierr); 1731795a4d1SJed Brown ierr = PetscCalloc1(n,&work);CHKERRQ(ierr); 1740716a85fSBarry Smith if (type == NORM_2) { 1750716a85fSBarry Smith for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) { 1760716a85fSBarry Smith work[A->cmap->rstart + a_aij->j[i]] += PetscAbsScalar(a_aij->a[i]*a_aij->a[i]); 1770716a85fSBarry Smith } 1780716a85fSBarry Smith for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) { 1790716a85fSBarry Smith work[garray[b_aij->j[i]]] += PetscAbsScalar(b_aij->a[i]*b_aij->a[i]); 1800716a85fSBarry Smith } 1810716a85fSBarry Smith } else if (type == NORM_1) { 1820716a85fSBarry Smith for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) { 1830716a85fSBarry Smith work[A->cmap->rstart + a_aij->j[i]] += PetscAbsScalar(a_aij->a[i]); 1840716a85fSBarry Smith } 1850716a85fSBarry Smith for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) { 1860716a85fSBarry Smith work[garray[b_aij->j[i]]] += PetscAbsScalar(b_aij->a[i]); 1870716a85fSBarry Smith } 1880716a85fSBarry Smith } else if (type == NORM_INFINITY) { 1890716a85fSBarry Smith for (i=0; i<a_aij->i[aij->A->rmap->n]; i++) { 1900716a85fSBarry Smith work[A->cmap->rstart + a_aij->j[i]] = PetscMax(PetscAbsScalar(a_aij->a[i]), work[A->cmap->rstart + a_aij->j[i]]); 1910716a85fSBarry Smith } 1920716a85fSBarry Smith for (i=0; i<b_aij->i[aij->B->rmap->n]; i++) { 1930716a85fSBarry Smith work[garray[b_aij->j[i]]] = PetscMax(PetscAbsScalar(b_aij->a[i]),work[garray[b_aij->j[i]]]); 1940716a85fSBarry Smith } 1950716a85fSBarry Smith 196ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_WRONG,"Unknown NormType"); 1970716a85fSBarry Smith if (type == NORM_INFINITY) { 198b2566f29SBarry Smith ierr = MPIU_Allreduce(work,norms,n,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 1990716a85fSBarry Smith } else { 200b2566f29SBarry Smith ierr = MPIU_Allreduce(work,norms,n,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 2010716a85fSBarry Smith } 2020716a85fSBarry Smith ierr = PetscFree(work);CHKERRQ(ierr); 2030716a85fSBarry Smith if (type == NORM_2) { 2048f1a2a5eSBarry Smith for (i=0; i<n; i++) norms[i] = PetscSqrtReal(norms[i]); 2050716a85fSBarry Smith } 2060716a85fSBarry Smith PetscFunctionReturn(0); 2070716a85fSBarry Smith } 2080716a85fSBarry Smith 2090716a85fSBarry Smith #undef __FUNCT__ 210e52d2c62SBarry Smith #define __FUNCT__ "MatFindOffBlockDiagonalEntries_MPIAIJ" 211e52d2c62SBarry Smith PetscErrorCode MatFindOffBlockDiagonalEntries_MPIAIJ(Mat A,IS *is) 212e52d2c62SBarry Smith { 213e52d2c62SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 214e52d2c62SBarry Smith IS sis,gis; 215e52d2c62SBarry Smith PetscErrorCode ierr; 216e52d2c62SBarry Smith const PetscInt *isis,*igis; 217e52d2c62SBarry Smith PetscInt n,*iis,nsis,ngis,rstart,i; 218e52d2c62SBarry Smith 219e52d2c62SBarry Smith PetscFunctionBegin; 220e52d2c62SBarry Smith ierr = MatFindOffBlockDiagonalEntries(a->A,&sis);CHKERRQ(ierr); 221e52d2c62SBarry Smith ierr = MatFindNonzeroRows(a->B,&gis);CHKERRQ(ierr); 222e52d2c62SBarry Smith ierr = ISGetSize(gis,&ngis);CHKERRQ(ierr); 223e52d2c62SBarry Smith ierr = ISGetSize(sis,&nsis);CHKERRQ(ierr); 224e52d2c62SBarry Smith ierr = ISGetIndices(sis,&isis);CHKERRQ(ierr); 225e52d2c62SBarry Smith ierr = ISGetIndices(gis,&igis);CHKERRQ(ierr); 226e52d2c62SBarry Smith 227e52d2c62SBarry Smith ierr = PetscMalloc1(ngis+nsis,&iis);CHKERRQ(ierr); 228e52d2c62SBarry Smith ierr = PetscMemcpy(iis,igis,ngis*sizeof(PetscInt));CHKERRQ(ierr); 229e52d2c62SBarry Smith ierr = PetscMemcpy(iis+ngis,isis,nsis*sizeof(PetscInt));CHKERRQ(ierr); 230e52d2c62SBarry Smith n = ngis + nsis; 231e52d2c62SBarry Smith ierr = PetscSortRemoveDupsInt(&n,iis);CHKERRQ(ierr); 232e52d2c62SBarry Smith ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr); 233e52d2c62SBarry Smith for (i=0; i<n; i++) iis[i] += rstart; 234e52d2c62SBarry Smith ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),n,iis,PETSC_OWN_POINTER,is);CHKERRQ(ierr); 235e52d2c62SBarry Smith 236e52d2c62SBarry Smith ierr = ISRestoreIndices(sis,&isis);CHKERRQ(ierr); 237e52d2c62SBarry Smith ierr = ISRestoreIndices(gis,&igis);CHKERRQ(ierr); 238e52d2c62SBarry Smith ierr = ISDestroy(&sis);CHKERRQ(ierr); 239e52d2c62SBarry Smith ierr = ISDestroy(&gis);CHKERRQ(ierr); 240e52d2c62SBarry Smith PetscFunctionReturn(0); 241e52d2c62SBarry Smith } 242e52d2c62SBarry Smith 243e52d2c62SBarry Smith #undef __FUNCT__ 244dd6ea824SBarry Smith #define __FUNCT__ "MatDistribute_MPIAIJ" 245dd6ea824SBarry Smith /* 246dd6ea824SBarry Smith Distributes a SeqAIJ matrix across a set of processes. Code stolen from 247dd6ea824SBarry Smith MatLoad_MPIAIJ(). Horrible lack of reuse. Should be a routine for each matrix type. 248dd6ea824SBarry Smith 249dd6ea824SBarry Smith Only for square matrices 250b30237c6SBarry Smith 251b30237c6SBarry Smith Used by a preconditioner, hence PETSC_EXTERN 252dd6ea824SBarry Smith */ 2535a576424SJed Brown PETSC_EXTERN PetscErrorCode MatDistribute_MPIAIJ(MPI_Comm comm,Mat gmat,PetscInt m,MatReuse reuse,Mat *inmat) 254dd6ea824SBarry Smith { 255dd6ea824SBarry Smith PetscMPIInt rank,size; 256d892089bSMatthew G. Knepley PetscInt *rowners,*dlens,*olens,i,rstart,rend,j,jj,nz = 0,*gmataj,cnt,row,*ld,bses[2]; 257dd6ea824SBarry Smith PetscErrorCode ierr; 258dd6ea824SBarry Smith Mat mat; 259dd6ea824SBarry Smith Mat_SeqAIJ *gmata; 260dd6ea824SBarry Smith PetscMPIInt tag; 261dd6ea824SBarry Smith MPI_Status status; 262ace3abfcSBarry Smith PetscBool aij; 263dd6ea824SBarry Smith MatScalar *gmataa,*ao,*ad,*gmataarestore=0; 264dd6ea824SBarry Smith 265dd6ea824SBarry Smith PetscFunctionBegin; 266dd6ea824SBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 267dd6ea824SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 268dd6ea824SBarry Smith if (!rank) { 269251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)gmat,MATSEQAIJ,&aij);CHKERRQ(ierr); 270ce94432eSBarry Smith if (!aij) SETERRQ1(PetscObjectComm((PetscObject)gmat),PETSC_ERR_SUP,"Currently no support for input matrix of type %s\n",((PetscObject)gmat)->type_name); 271dd6ea824SBarry Smith } 272dd6ea824SBarry Smith if (reuse == MAT_INITIAL_MATRIX) { 273dd6ea824SBarry Smith ierr = MatCreate(comm,&mat);CHKERRQ(ierr); 274dd6ea824SBarry Smith ierr = MatSetSizes(mat,m,m,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 27533d57670SJed Brown ierr = MatGetBlockSizes(gmat,&bses[0],&bses[1]);CHKERRQ(ierr); 276efcf75d5SBarry Smith ierr = MPI_Bcast(bses,2,MPIU_INT,0,comm);CHKERRQ(ierr); 277efcf75d5SBarry Smith ierr = MatSetBlockSizes(mat,bses[0],bses[1]);CHKERRQ(ierr); 278dd6ea824SBarry Smith ierr = MatSetType(mat,MATAIJ);CHKERRQ(ierr); 279854ce69bSBarry Smith ierr = PetscMalloc1(size+1,&rowners);CHKERRQ(ierr); 280dcca6d9dSJed Brown ierr = PetscMalloc2(m,&dlens,m,&olens);CHKERRQ(ierr); 281dd6ea824SBarry Smith ierr = MPI_Allgather(&m,1,MPIU_INT,rowners+1,1,MPIU_INT,comm);CHKERRQ(ierr); 2822205254eSKarl Rupp 283dd6ea824SBarry Smith rowners[0] = 0; 2842205254eSKarl Rupp for (i=2; i<=size; i++) rowners[i] += rowners[i-1]; 285dd6ea824SBarry Smith rstart = rowners[rank]; 286dd6ea824SBarry Smith rend = rowners[rank+1]; 287dd6ea824SBarry Smith ierr = PetscObjectGetNewTag((PetscObject)mat,&tag);CHKERRQ(ierr); 288dd6ea824SBarry Smith if (!rank) { 289dd6ea824SBarry Smith gmata = (Mat_SeqAIJ*) gmat->data; 290dd6ea824SBarry Smith /* send row lengths to all processors */ 291dd6ea824SBarry Smith for (i=0; i<m; i++) dlens[i] = gmata->ilen[i]; 292dd6ea824SBarry Smith for (i=1; i<size; i++) { 293dd6ea824SBarry Smith ierr = MPI_Send(gmata->ilen + rowners[i],rowners[i+1]-rowners[i],MPIU_INT,i,tag,comm);CHKERRQ(ierr); 294dd6ea824SBarry Smith } 295dd6ea824SBarry Smith /* determine number diagonal and off-diagonal counts */ 296dd6ea824SBarry Smith ierr = PetscMemzero(olens,m*sizeof(PetscInt));CHKERRQ(ierr); 2971795a4d1SJed Brown ierr = PetscCalloc1(m,&ld);CHKERRQ(ierr); 298dd6ea824SBarry Smith jj = 0; 299dd6ea824SBarry Smith for (i=0; i<m; i++) { 300dd6ea824SBarry Smith for (j=0; j<dlens[i]; j++) { 301dd6ea824SBarry Smith if (gmata->j[jj] < rstart) ld[i]++; 302dd6ea824SBarry Smith if (gmata->j[jj] < rstart || gmata->j[jj] >= rend) olens[i]++; 303dd6ea824SBarry Smith jj++; 304dd6ea824SBarry Smith } 305dd6ea824SBarry Smith } 306dd6ea824SBarry Smith /* send column indices to other processes */ 307dd6ea824SBarry Smith for (i=1; i<size; i++) { 308dd6ea824SBarry Smith nz = gmata->i[rowners[i+1]]-gmata->i[rowners[i]]; 309dd6ea824SBarry Smith ierr = MPI_Send(&nz,1,MPIU_INT,i,tag,comm);CHKERRQ(ierr); 310dd6ea824SBarry Smith ierr = MPI_Send(gmata->j + gmata->i[rowners[i]],nz,MPIU_INT,i,tag,comm);CHKERRQ(ierr); 311dd6ea824SBarry Smith } 312dd6ea824SBarry Smith 313dd6ea824SBarry Smith /* send numerical values to other processes */ 314dd6ea824SBarry Smith for (i=1; i<size; i++) { 315dd6ea824SBarry Smith nz = gmata->i[rowners[i+1]]-gmata->i[rowners[i]]; 316dd6ea824SBarry Smith ierr = MPI_Send(gmata->a + gmata->i[rowners[i]],nz,MPIU_SCALAR,i,tag,comm);CHKERRQ(ierr); 317dd6ea824SBarry Smith } 318dd6ea824SBarry Smith gmataa = gmata->a; 319dd6ea824SBarry Smith gmataj = gmata->j; 320dd6ea824SBarry Smith 321dd6ea824SBarry Smith } else { 322dd6ea824SBarry Smith /* receive row lengths */ 323dd6ea824SBarry Smith ierr = MPI_Recv(dlens,m,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr); 324dd6ea824SBarry Smith /* receive column indices */ 325dd6ea824SBarry Smith ierr = MPI_Recv(&nz,1,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr); 326dcca6d9dSJed Brown ierr = PetscMalloc2(nz,&gmataa,nz,&gmataj);CHKERRQ(ierr); 327dd6ea824SBarry Smith ierr = MPI_Recv(gmataj,nz,MPIU_INT,0,tag,comm,&status);CHKERRQ(ierr); 328dd6ea824SBarry Smith /* determine number diagonal and off-diagonal counts */ 329dd6ea824SBarry Smith ierr = PetscMemzero(olens,m*sizeof(PetscInt));CHKERRQ(ierr); 3301795a4d1SJed Brown ierr = PetscCalloc1(m,&ld);CHKERRQ(ierr); 331dd6ea824SBarry Smith jj = 0; 332dd6ea824SBarry Smith for (i=0; i<m; i++) { 333dd6ea824SBarry Smith for (j=0; j<dlens[i]; j++) { 334dd6ea824SBarry Smith if (gmataj[jj] < rstart) ld[i]++; 335dd6ea824SBarry Smith if (gmataj[jj] < rstart || gmataj[jj] >= rend) olens[i]++; 336dd6ea824SBarry Smith jj++; 337dd6ea824SBarry Smith } 338dd6ea824SBarry Smith } 339dd6ea824SBarry Smith /* receive numerical values */ 340dd6ea824SBarry Smith ierr = PetscMemzero(gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); 341dd6ea824SBarry Smith ierr = MPI_Recv(gmataa,nz,MPIU_SCALAR,0,tag,comm,&status);CHKERRQ(ierr); 342dd6ea824SBarry Smith } 343dd6ea824SBarry Smith /* set preallocation */ 344dd6ea824SBarry Smith for (i=0; i<m; i++) { 345dd6ea824SBarry Smith dlens[i] -= olens[i]; 346dd6ea824SBarry Smith } 347dd6ea824SBarry Smith ierr = MatSeqAIJSetPreallocation(mat,0,dlens);CHKERRQ(ierr); 348dd6ea824SBarry Smith ierr = MatMPIAIJSetPreallocation(mat,0,dlens,0,olens);CHKERRQ(ierr); 349dd6ea824SBarry Smith 350dd6ea824SBarry Smith for (i=0; i<m; i++) { 351dd6ea824SBarry Smith dlens[i] += olens[i]; 352dd6ea824SBarry Smith } 353dd6ea824SBarry Smith cnt = 0; 354dd6ea824SBarry Smith for (i=0; i<m; i++) { 355dd6ea824SBarry Smith row = rstart + i; 356dd6ea824SBarry Smith ierr = MatSetValues(mat,1,&row,dlens[i],gmataj+cnt,gmataa+cnt,INSERT_VALUES);CHKERRQ(ierr); 357dd6ea824SBarry Smith cnt += dlens[i]; 358dd6ea824SBarry Smith } 359dd6ea824SBarry Smith if (rank) { 360dd6ea824SBarry Smith ierr = PetscFree2(gmataa,gmataj);CHKERRQ(ierr); 361dd6ea824SBarry Smith } 362dd6ea824SBarry Smith ierr = PetscFree2(dlens,olens);CHKERRQ(ierr); 363dd6ea824SBarry Smith ierr = PetscFree(rowners);CHKERRQ(ierr); 3642205254eSKarl Rupp 365dd6ea824SBarry Smith ((Mat_MPIAIJ*)(mat->data))->ld = ld; 3662205254eSKarl Rupp 367dd6ea824SBarry Smith *inmat = mat; 368dd6ea824SBarry Smith } else { /* column indices are already set; only need to move over numerical values from process 0 */ 369dd6ea824SBarry Smith Mat_SeqAIJ *Ad = (Mat_SeqAIJ*)((Mat_MPIAIJ*)((*inmat)->data))->A->data; 370dd6ea824SBarry Smith Mat_SeqAIJ *Ao = (Mat_SeqAIJ*)((Mat_MPIAIJ*)((*inmat)->data))->B->data; 371dd6ea824SBarry Smith mat = *inmat; 372dd6ea824SBarry Smith ierr = PetscObjectGetNewTag((PetscObject)mat,&tag);CHKERRQ(ierr); 373dd6ea824SBarry Smith if (!rank) { 374dd6ea824SBarry Smith /* send numerical values to other processes */ 375dd6ea824SBarry Smith gmata = (Mat_SeqAIJ*) gmat->data; 376dd6ea824SBarry Smith ierr = MatGetOwnershipRanges(mat,(const PetscInt**)&rowners);CHKERRQ(ierr); 377dd6ea824SBarry Smith gmataa = gmata->a; 378dd6ea824SBarry Smith for (i=1; i<size; i++) { 379dd6ea824SBarry Smith nz = gmata->i[rowners[i+1]]-gmata->i[rowners[i]]; 380dd6ea824SBarry Smith ierr = MPI_Send(gmataa + gmata->i[rowners[i]],nz,MPIU_SCALAR,i,tag,comm);CHKERRQ(ierr); 381dd6ea824SBarry Smith } 382dd6ea824SBarry Smith nz = gmata->i[rowners[1]]-gmata->i[rowners[0]]; 383dd6ea824SBarry Smith } else { 384dd6ea824SBarry Smith /* receive numerical values from process 0*/ 385dd6ea824SBarry Smith nz = Ad->nz + Ao->nz; 386785e854fSJed Brown ierr = PetscMalloc1(nz,&gmataa);CHKERRQ(ierr); gmataarestore = gmataa; 387dd6ea824SBarry Smith ierr = MPI_Recv(gmataa,nz,MPIU_SCALAR,0,tag,comm,&status);CHKERRQ(ierr); 388dd6ea824SBarry Smith } 389dd6ea824SBarry Smith /* transfer numerical values into the diagonal A and off diagonal B parts of mat */ 390dd6ea824SBarry Smith ld = ((Mat_MPIAIJ*)(mat->data))->ld; 391dd6ea824SBarry Smith ad = Ad->a; 392dd6ea824SBarry Smith ao = Ao->a; 393d0f46423SBarry Smith if (mat->rmap->n) { 394dd6ea824SBarry Smith i = 0; 395dd6ea824SBarry Smith nz = ld[i]; ierr = PetscMemcpy(ao,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ao += nz; gmataa += nz; 396dd6ea824SBarry Smith nz = Ad->i[i+1] - Ad->i[i]; ierr = PetscMemcpy(ad,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ad += nz; gmataa += nz; 397dd6ea824SBarry Smith } 398d0f46423SBarry Smith for (i=1; i<mat->rmap->n; i++) { 399dd6ea824SBarry Smith nz = Ao->i[i] - Ao->i[i-1] - ld[i-1] + ld[i]; ierr = PetscMemcpy(ao,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ao += nz; gmataa += nz; 400dd6ea824SBarry Smith nz = Ad->i[i+1] - Ad->i[i]; ierr = PetscMemcpy(ad,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); ad += nz; gmataa += nz; 401dd6ea824SBarry Smith } 402dd6ea824SBarry Smith i--; 403d0f46423SBarry Smith if (mat->rmap->n) { 40422d28d08SBarry Smith nz = Ao->i[i+1] - Ao->i[i] - ld[i]; ierr = PetscMemcpy(ao,gmataa,nz*sizeof(PetscScalar));CHKERRQ(ierr); 405dd6ea824SBarry Smith } 406dd6ea824SBarry Smith if (rank) { 407dd6ea824SBarry Smith ierr = PetscFree(gmataarestore);CHKERRQ(ierr); 408dd6ea824SBarry Smith } 409dd6ea824SBarry Smith } 410dd6ea824SBarry Smith ierr = MatAssemblyBegin(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 411dd6ea824SBarry Smith ierr = MatAssemblyEnd(mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 412dd6ea824SBarry Smith PetscFunctionReturn(0); 413dd6ea824SBarry Smith } 414dd6ea824SBarry Smith 4150f5bd95cSBarry Smith /* 4160f5bd95cSBarry Smith Local utility routine that creates a mapping from the global column 4179e25ed09SBarry Smith number to the local number in the off-diagonal part of the local 4180f5bd95cSBarry Smith storage of the matrix. When PETSC_USE_CTABLE is used this is scalable at 4190f5bd95cSBarry Smith a slightly higher hash table cost; without it it is not scalable (each processor 4200f5bd95cSBarry Smith has an order N integer array but is fast to acess. 4219e25ed09SBarry Smith */ 4224a2ae208SSatish Balay #undef __FUNCT__ 423ab9863d7SBarry Smith #define __FUNCT__ "MatCreateColmap_MPIAIJ_Private" 424ab9863d7SBarry Smith PetscErrorCode MatCreateColmap_MPIAIJ_Private(Mat mat) 4259e25ed09SBarry Smith { 42644a69424SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 4276849ba73SBarry Smith PetscErrorCode ierr; 428d0f46423SBarry Smith PetscInt n = aij->B->cmap->n,i; 429dbb450caSBarry Smith 4303a40ed3dSBarry Smith PetscFunctionBegin; 4315e1f6667SBarry Smith if (!aij->garray) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"MPIAIJ Matrix was assembled but is missing garray"); 432aa482453SBarry Smith #if defined(PETSC_USE_CTABLE) 433e23dfa41SBarry Smith ierr = PetscTableCreate(n,mat->cmap->N+1,&aij->colmap);CHKERRQ(ierr); 434b1fc9764SSatish Balay for (i=0; i<n; i++) { 4353861aac3SJed Brown ierr = PetscTableAdd(aij->colmap,aij->garray[i]+1,i+1,INSERT_VALUES);CHKERRQ(ierr); 436b1fc9764SSatish Balay } 437b1fc9764SSatish Balay #else 438854ce69bSBarry Smith ierr = PetscCalloc1(mat->cmap->N+1,&aij->colmap);CHKERRQ(ierr); 4391795a4d1SJed Brown ierr = PetscLogObjectMemory((PetscObject)mat,(mat->cmap->N+1)*sizeof(PetscInt));CHKERRQ(ierr); 440905e6a2fSBarry Smith for (i=0; i<n; i++) aij->colmap[aij->garray[i]] = i+1; 441b1fc9764SSatish Balay #endif 4423a40ed3dSBarry Smith PetscFunctionReturn(0); 4439e25ed09SBarry Smith } 4449e25ed09SBarry Smith 445d40312a9SBarry Smith #define MatSetValues_SeqAIJ_A_Private(row,col,value,addv,orow,ocol) \ 4460520107fSSatish Balay { \ 447db4deed7SKarl Rupp if (col <= lastcol1) low1 = 0; \ 448db4deed7SKarl Rupp else high1 = nrow1; \ 449fd3458f5SBarry Smith lastcol1 = col;\ 450fd3458f5SBarry Smith while (high1-low1 > 5) { \ 451fd3458f5SBarry Smith t = (low1+high1)/2; \ 452fd3458f5SBarry Smith if (rp1[t] > col) high1 = t; \ 453fd3458f5SBarry Smith else low1 = t; \ 454ba4e3ef2SSatish Balay } \ 455fd3458f5SBarry Smith for (_i=low1; _i<high1; _i++) { \ 456fd3458f5SBarry Smith if (rp1[_i] > col) break; \ 457fd3458f5SBarry Smith if (rp1[_i] == col) { \ 458fd3458f5SBarry Smith if (addv == ADD_VALUES) ap1[_i] += value; \ 459fd3458f5SBarry Smith else ap1[_i] = value; \ 46030770e4dSSatish Balay goto a_noinsert; \ 4610520107fSSatish Balay } \ 4620520107fSSatish Balay } \ 463e44c0bd4SBarry Smith if (value == 0.0 && ignorezeroentries) {low1 = 0; high1 = nrow1;goto a_noinsert;} \ 464e44c0bd4SBarry Smith if (nonew == 1) {low1 = 0; high1 = nrow1; goto a_noinsert;} \ 465d40312a9SBarry 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); \ 466fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(A,am,1,nrow1,row,col,rmax1,aa,ai,aj,rp1,ap1,aimax,nonew,MatScalar); \ 467669a8dbcSSatish Balay N = nrow1++ - 1; a->nz++; high1++; \ 4680520107fSSatish Balay /* shift up all the later entries in this row */ \ 4690520107fSSatish Balay for (ii=N; ii>=_i; ii--) { \ 470fd3458f5SBarry Smith rp1[ii+1] = rp1[ii]; \ 471fd3458f5SBarry Smith ap1[ii+1] = ap1[ii]; \ 4720520107fSSatish Balay } \ 473fd3458f5SBarry Smith rp1[_i] = col; \ 474fd3458f5SBarry Smith ap1[_i] = value; \ 475e56f5c9eSBarry Smith A->nonzerostate++;\ 47630770e4dSSatish Balay a_noinsert: ; \ 477fd3458f5SBarry Smith ailen[row] = nrow1; \ 4780520107fSSatish Balay } 4790a198c4cSBarry Smith 480085a36d4SBarry Smith 481d40312a9SBarry Smith #define MatSetValues_SeqAIJ_B_Private(row,col,value,addv,orow,ocol) \ 48230770e4dSSatish Balay { \ 483db4deed7SKarl Rupp if (col <= lastcol2) low2 = 0; \ 484db4deed7SKarl Rupp else high2 = nrow2; \ 485fd3458f5SBarry Smith lastcol2 = col; \ 486fd3458f5SBarry Smith while (high2-low2 > 5) { \ 487fd3458f5SBarry Smith t = (low2+high2)/2; \ 488fd3458f5SBarry Smith if (rp2[t] > col) high2 = t; \ 489fd3458f5SBarry Smith else low2 = t; \ 490ba4e3ef2SSatish Balay } \ 491fd3458f5SBarry Smith for (_i=low2; _i<high2; _i++) { \ 492fd3458f5SBarry Smith if (rp2[_i] > col) break; \ 493fd3458f5SBarry Smith if (rp2[_i] == col) { \ 494fd3458f5SBarry Smith if (addv == ADD_VALUES) ap2[_i] += value; \ 495fd3458f5SBarry Smith else ap2[_i] = value; \ 49630770e4dSSatish Balay goto b_noinsert; \ 49730770e4dSSatish Balay } \ 49830770e4dSSatish Balay } \ 499e44c0bd4SBarry Smith if (value == 0.0 && ignorezeroentries) {low2 = 0; high2 = nrow2; goto b_noinsert;} \ 500e44c0bd4SBarry Smith if (nonew == 1) {low2 = 0; high2 = nrow2; goto b_noinsert;} \ 501d40312a9SBarry 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); \ 502fef13f97SBarry Smith MatSeqXAIJReallocateAIJ(B,bm,1,nrow2,row,col,rmax2,ba,bi,bj,rp2,ap2,bimax,nonew,MatScalar); \ 503669a8dbcSSatish Balay N = nrow2++ - 1; b->nz++; high2++; \ 50430770e4dSSatish Balay /* shift up all the later entries in this row */ \ 50530770e4dSSatish Balay for (ii=N; ii>=_i; ii--) { \ 506fd3458f5SBarry Smith rp2[ii+1] = rp2[ii]; \ 507fd3458f5SBarry Smith ap2[ii+1] = ap2[ii]; \ 50830770e4dSSatish Balay } \ 509fd3458f5SBarry Smith rp2[_i] = col; \ 510fd3458f5SBarry Smith ap2[_i] = value; \ 511e56f5c9eSBarry Smith B->nonzerostate++; \ 51230770e4dSSatish Balay b_noinsert: ; \ 513fd3458f5SBarry Smith bilen[row] = nrow2; \ 51430770e4dSSatish Balay } 51530770e4dSSatish Balay 5164a2ae208SSatish Balay #undef __FUNCT__ 5172fd7e33dSBarry Smith #define __FUNCT__ "MatSetValuesRow_MPIAIJ" 5182fd7e33dSBarry Smith PetscErrorCode MatSetValuesRow_MPIAIJ(Mat A,PetscInt row,const PetscScalar v[]) 5192fd7e33dSBarry Smith { 5202fd7e33dSBarry Smith Mat_MPIAIJ *mat = (Mat_MPIAIJ*)A->data; 5212fd7e33dSBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)mat->A->data,*b = (Mat_SeqAIJ*)mat->B->data; 5222fd7e33dSBarry Smith PetscErrorCode ierr; 5232fd7e33dSBarry Smith PetscInt l,*garray = mat->garray,diag; 5242fd7e33dSBarry Smith 5252fd7e33dSBarry Smith PetscFunctionBegin; 5262fd7e33dSBarry Smith /* code only works for square matrices A */ 5272fd7e33dSBarry Smith 5282fd7e33dSBarry Smith /* find size of row to the left of the diagonal part */ 5292fd7e33dSBarry Smith ierr = MatGetOwnershipRange(A,&diag,0);CHKERRQ(ierr); 5302fd7e33dSBarry Smith row = row - diag; 5312fd7e33dSBarry Smith for (l=0; l<b->i[row+1]-b->i[row]; l++) { 5322fd7e33dSBarry Smith if (garray[b->j[b->i[row]+l]] > diag) break; 5332fd7e33dSBarry Smith } 5342fd7e33dSBarry Smith ierr = PetscMemcpy(b->a+b->i[row],v,l*sizeof(PetscScalar));CHKERRQ(ierr); 5352fd7e33dSBarry Smith 5362fd7e33dSBarry Smith /* diagonal part */ 5372fd7e33dSBarry Smith ierr = PetscMemcpy(a->a+a->i[row],v+l,(a->i[row+1]-a->i[row])*sizeof(PetscScalar));CHKERRQ(ierr); 5382fd7e33dSBarry Smith 5392fd7e33dSBarry Smith /* right of diagonal part */ 5402fd7e33dSBarry Smith ierr = PetscMemcpy(b->a+b->i[row]+l,v+l+a->i[row+1]-a->i[row],(b->i[row+1]-b->i[row]-l)*sizeof(PetscScalar));CHKERRQ(ierr); 5412fd7e33dSBarry Smith PetscFunctionReturn(0); 5422fd7e33dSBarry Smith } 5432fd7e33dSBarry Smith 5442fd7e33dSBarry Smith #undef __FUNCT__ 5454a2ae208SSatish Balay #define __FUNCT__ "MatSetValues_MPIAIJ" 546b1d57f15SBarry Smith PetscErrorCode MatSetValues_MPIAIJ(Mat mat,PetscInt m,const PetscInt im[],PetscInt n,const PetscInt in[],const PetscScalar v[],InsertMode addv) 5478a729477SBarry Smith { 54844a69424SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 54987828ca2SBarry Smith PetscScalar value; 550dfbe8321SBarry Smith PetscErrorCode ierr; 551d0f46423SBarry Smith PetscInt i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend; 552d0f46423SBarry Smith PetscInt cstart = mat->cmap->rstart,cend = mat->cmap->rend,row,col; 553ace3abfcSBarry Smith PetscBool roworiented = aij->roworiented; 5548a729477SBarry Smith 5550520107fSSatish Balay /* Some Variables required in the macro */ 5564ee7247eSSatish Balay Mat A = aij->A; 5574ee7247eSSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 55857809a77SBarry Smith PetscInt *aimax = a->imax,*ai = a->i,*ailen = a->ilen,*aj = a->j; 559a77337e4SBarry Smith MatScalar *aa = a->a; 560ace3abfcSBarry Smith PetscBool ignorezeroentries = a->ignorezeroentries; 56130770e4dSSatish Balay Mat B = aij->B; 56230770e4dSSatish Balay Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 563d0f46423SBarry Smith PetscInt *bimax = b->imax,*bi = b->i,*bilen = b->ilen,*bj = b->j,bm = aij->B->rmap->n,am = aij->A->rmap->n; 564a77337e4SBarry Smith MatScalar *ba = b->a; 56530770e4dSSatish Balay 566fd3458f5SBarry Smith PetscInt *rp1,*rp2,ii,nrow1,nrow2,_i,rmax1,rmax2,N,low1,high1,low2,high2,t,lastcol1,lastcol2; 5678d76821aSHong Zhang PetscInt nonew; 568a77337e4SBarry Smith MatScalar *ap1,*ap2; 5694ee7247eSSatish Balay 5703a40ed3dSBarry Smith PetscFunctionBegin; 5718a729477SBarry Smith for (i=0; i<m; i++) { 5725ef9f2a5SBarry Smith if (im[i] < 0) continue; 5732515c552SBarry Smith #if defined(PETSC_USE_DEBUG) 574e32f2f54SBarry 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); 5750a198c4cSBarry Smith #endif 5764b0e389bSBarry Smith if (im[i] >= rstart && im[i] < rend) { 5774b0e389bSBarry Smith row = im[i] - rstart; 578fd3458f5SBarry Smith lastcol1 = -1; 579fd3458f5SBarry Smith rp1 = aj + ai[row]; 580fd3458f5SBarry Smith ap1 = aa + ai[row]; 581fd3458f5SBarry Smith rmax1 = aimax[row]; 582fd3458f5SBarry Smith nrow1 = ailen[row]; 583fd3458f5SBarry Smith low1 = 0; 584fd3458f5SBarry Smith high1 = nrow1; 585fd3458f5SBarry Smith lastcol2 = -1; 586fd3458f5SBarry Smith rp2 = bj + bi[row]; 587d498b1e9SBarry Smith ap2 = ba + bi[row]; 588fd3458f5SBarry Smith rmax2 = bimax[row]; 589d498b1e9SBarry Smith nrow2 = bilen[row]; 590fd3458f5SBarry Smith low2 = 0; 591fd3458f5SBarry Smith high2 = nrow2; 592fd3458f5SBarry Smith 5931eb62cbbSBarry Smith for (j=0; j<n; j++) { 594db4deed7SKarl Rupp if (roworiented) value = v[i*n+j]; 595db4deed7SKarl Rupp else value = v[i+j*m]; 596abc0a331SBarry Smith if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue; 597fd3458f5SBarry Smith if (in[j] >= cstart && in[j] < cend) { 598fd3458f5SBarry Smith col = in[j] - cstart; 5998d76821aSHong Zhang nonew = a->nonew; 600d40312a9SBarry Smith MatSetValues_SeqAIJ_A_Private(row,col,value,addv,im[i],in[j]); 601273d9f13SBarry Smith } else if (in[j] < 0) continue; 6022515c552SBarry Smith #if defined(PETSC_USE_DEBUG) 603cb9801acSJed 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); 6040a198c4cSBarry Smith #endif 6051eb62cbbSBarry Smith else { 606227d817aSBarry Smith if (mat->was_assembled) { 607905e6a2fSBarry Smith if (!aij->colmap) { 608ab9863d7SBarry Smith ierr = MatCreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr); 609905e6a2fSBarry Smith } 610aa482453SBarry Smith #if defined(PETSC_USE_CTABLE) 6110f5bd95cSBarry Smith ierr = PetscTableFind(aij->colmap,in[j]+1,&col);CHKERRQ(ierr); 612fa46199cSSatish Balay col--; 613b1fc9764SSatish Balay #else 614905e6a2fSBarry Smith col = aij->colmap[in[j]] - 1; 615b1fc9764SSatish Balay #endif 6160e9bae81SBarry Smith if (col < 0 && !((Mat_SeqAIJ*)(aij->B->data))->nonew) { 617ab9863d7SBarry Smith ierr = MatDisAssemble_MPIAIJ(mat);CHKERRQ(ierr); 6184b0e389bSBarry Smith col = in[j]; 6199bf004c3SSatish Balay /* Reinitialize the variables required by MatSetValues_SeqAIJ_B_Private() */ 620f9508a3cSSatish Balay B = aij->B; 621f9508a3cSSatish Balay b = (Mat_SeqAIJ*)B->data; 622e44c0bd4SBarry Smith bimax = b->imax; bi = b->i; bilen = b->ilen; bj = b->j; ba = b->a; 623d498b1e9SBarry Smith rp2 = bj + bi[row]; 624d498b1e9SBarry Smith ap2 = ba + bi[row]; 625d498b1e9SBarry Smith rmax2 = bimax[row]; 626d498b1e9SBarry Smith nrow2 = bilen[row]; 627d498b1e9SBarry Smith low2 = 0; 628d498b1e9SBarry Smith high2 = nrow2; 629d0f46423SBarry Smith bm = aij->B->rmap->n; 630f9508a3cSSatish Balay ba = b->a; 631d40312a9SBarry Smith } else if (col < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Inserting a new nonzero at global row/column (%D, %D) into matrix", im[i], in[j]); 632c48de900SBarry Smith } else col = in[j]; 6338d76821aSHong Zhang nonew = b->nonew; 634d40312a9SBarry Smith MatSetValues_SeqAIJ_B_Private(row,col,value,addv,im[i],in[j]); 6351eb62cbbSBarry Smith } 6361eb62cbbSBarry Smith } 6375ef9f2a5SBarry Smith } else { 6384cb17eb5SBarry 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]); 63990f02eecSBarry Smith if (!aij->donotstash) { 6405080c13bSMatthew G Knepley mat->assembled = PETSC_FALSE; 641d36fbae8SSatish Balay if (roworiented) { 642ace3abfcSBarry Smith ierr = MatStashValuesRow_Private(&mat->stash,im[i],n,in,v+i*n,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr); 643d36fbae8SSatish Balay } else { 644ace3abfcSBarry Smith ierr = MatStashValuesCol_Private(&mat->stash,im[i],n,in,v+i,m,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr); 6454b0e389bSBarry Smith } 6461eb62cbbSBarry Smith } 6478a729477SBarry Smith } 64890f02eecSBarry Smith } 6493a40ed3dSBarry Smith PetscFunctionReturn(0); 6508a729477SBarry Smith } 6518a729477SBarry Smith 6524a2ae208SSatish Balay #undef __FUNCT__ 6534a2ae208SSatish Balay #define __FUNCT__ "MatGetValues_MPIAIJ" 654b1d57f15SBarry Smith PetscErrorCode MatGetValues_MPIAIJ(Mat mat,PetscInt m,const PetscInt idxm[],PetscInt n,const PetscInt idxn[],PetscScalar v[]) 655b49de8d1SLois Curfman McInnes { 656b49de8d1SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 657dfbe8321SBarry Smith PetscErrorCode ierr; 658d0f46423SBarry Smith PetscInt i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend; 659d0f46423SBarry Smith PetscInt cstart = mat->cmap->rstart,cend = mat->cmap->rend,row,col; 660b49de8d1SLois Curfman McInnes 6613a40ed3dSBarry Smith PetscFunctionBegin; 662b49de8d1SLois Curfman McInnes for (i=0; i<m; i++) { 663e32f2f54SBarry Smith if (idxm[i] < 0) continue; /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative row: %D",idxm[i]);*/ 664e32f2f54SBarry 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); 665b49de8d1SLois Curfman McInnes if (idxm[i] >= rstart && idxm[i] < rend) { 666b49de8d1SLois Curfman McInnes row = idxm[i] - rstart; 667b49de8d1SLois Curfman McInnes for (j=0; j<n; j++) { 668e32f2f54SBarry Smith if (idxn[j] < 0) continue; /* SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative column: %D",idxn[j]); */ 669e32f2f54SBarry 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); 670b49de8d1SLois Curfman McInnes if (idxn[j] >= cstart && idxn[j] < cend) { 671b49de8d1SLois Curfman McInnes col = idxn[j] - cstart; 672b49de8d1SLois Curfman McInnes ierr = MatGetValues(aij->A,1,&row,1,&col,v+i*n+j);CHKERRQ(ierr); 673fa852ad4SSatish Balay } else { 674905e6a2fSBarry Smith if (!aij->colmap) { 675ab9863d7SBarry Smith ierr = MatCreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr); 676905e6a2fSBarry Smith } 677aa482453SBarry Smith #if defined(PETSC_USE_CTABLE) 6780f5bd95cSBarry Smith ierr = PetscTableFind(aij->colmap,idxn[j]+1,&col);CHKERRQ(ierr); 679fa46199cSSatish Balay col--; 680b1fc9764SSatish Balay #else 681905e6a2fSBarry Smith col = aij->colmap[idxn[j]] - 1; 682b1fc9764SSatish Balay #endif 683e60e1c95SSatish Balay if ((col < 0) || (aij->garray[col] != idxn[j])) *(v+i*n+j) = 0.0; 684d9d09a02SSatish Balay else { 685b49de8d1SLois Curfman McInnes ierr = MatGetValues(aij->B,1,&row,1,&col,v+i*n+j);CHKERRQ(ierr); 686b49de8d1SLois Curfman McInnes } 687b49de8d1SLois Curfman McInnes } 688b49de8d1SLois Curfman McInnes } 689f23aa3ddSBarry Smith } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only local values currently supported"); 690b49de8d1SLois Curfman McInnes } 6913a40ed3dSBarry Smith PetscFunctionReturn(0); 692b49de8d1SLois Curfman McInnes } 693bc5ccf88SSatish Balay 694bd0c2dcbSBarry Smith extern PetscErrorCode MatMultDiagonalBlock_MPIAIJ(Mat,Vec,Vec); 695bd0c2dcbSBarry Smith 6964a2ae208SSatish Balay #undef __FUNCT__ 6974a2ae208SSatish Balay #define __FUNCT__ "MatAssemblyBegin_MPIAIJ" 698dfbe8321SBarry Smith PetscErrorCode MatAssemblyBegin_MPIAIJ(Mat mat,MatAssemblyType mode) 699bc5ccf88SSatish Balay { 700bc5ccf88SSatish Balay Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 701dfbe8321SBarry Smith PetscErrorCode ierr; 702b1d57f15SBarry Smith PetscInt nstash,reallocs; 703bc5ccf88SSatish Balay 704bc5ccf88SSatish Balay PetscFunctionBegin; 7052205254eSKarl Rupp if (aij->donotstash || mat->nooffprocentries) PetscFunctionReturn(0); 706bc5ccf88SSatish Balay 707d0f46423SBarry Smith ierr = MatStashScatterBegin_Private(mat,&mat->stash,mat->rmap->range);CHKERRQ(ierr); 7088798bf22SSatish Balay ierr = MatStashGetInfo_Private(&mat->stash,&nstash,&reallocs);CHKERRQ(ierr); 709ae15b995SBarry Smith ierr = PetscInfo2(aij->A,"Stash has %D entries, uses %D mallocs.\n",nstash,reallocs);CHKERRQ(ierr); 710bc5ccf88SSatish Balay PetscFunctionReturn(0); 711bc5ccf88SSatish Balay } 712bc5ccf88SSatish Balay 7134a2ae208SSatish Balay #undef __FUNCT__ 7144a2ae208SSatish Balay #define __FUNCT__ "MatAssemblyEnd_MPIAIJ" 715dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_MPIAIJ(Mat mat,MatAssemblyType mode) 716bc5ccf88SSatish Balay { 717bc5ccf88SSatish Balay Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 71891c97fd4SSatish Balay Mat_SeqAIJ *a = (Mat_SeqAIJ*)aij->A->data; 7196849ba73SBarry Smith PetscErrorCode ierr; 720b1d57f15SBarry Smith PetscMPIInt n; 721b1d57f15SBarry Smith PetscInt i,j,rstart,ncols,flg; 722e44c0bd4SBarry Smith PetscInt *row,*col; 723ace3abfcSBarry Smith PetscBool other_disassembled; 72487828ca2SBarry Smith PetscScalar *val; 725bc5ccf88SSatish Balay 72691c97fd4SSatish Balay /* do not use 'b = (Mat_SeqAIJ*)aij->B->data' as B can be reset in disassembly */ 7276e111a19SKarl Rupp 728bc5ccf88SSatish Balay PetscFunctionBegin; 7294cb17eb5SBarry Smith if (!aij->donotstash && !mat->nooffprocentries) { 730a2d1c673SSatish Balay while (1) { 7318798bf22SSatish Balay ierr = MatStashScatterGetMesg_Private(&mat->stash,&n,&row,&col,&val,&flg);CHKERRQ(ierr); 732a2d1c673SSatish Balay if (!flg) break; 733a2d1c673SSatish Balay 734bc5ccf88SSatish Balay for (i=0; i<n; ) { 735bc5ccf88SSatish Balay /* Now identify the consecutive vals belonging to the same row */ 7362205254eSKarl Rupp for (j=i,rstart=row[j]; j<n; j++) { 7372205254eSKarl Rupp if (row[j] != rstart) break; 7382205254eSKarl Rupp } 739bc5ccf88SSatish Balay if (j < n) ncols = j-i; 740bc5ccf88SSatish Balay else ncols = n-i; 741bc5ccf88SSatish Balay /* Now assemble all these values with a single function call */ 7424b4eb8d3SJed Brown ierr = MatSetValues_MPIAIJ(mat,1,row+i,ncols,col+i,val+i,mat->insertmode);CHKERRQ(ierr); 7432205254eSKarl Rupp 744bc5ccf88SSatish Balay i = j; 745bc5ccf88SSatish Balay } 746bc5ccf88SSatish Balay } 7478798bf22SSatish Balay ierr = MatStashScatterEnd_Private(&mat->stash);CHKERRQ(ierr); 748bc5ccf88SSatish Balay } 749bc5ccf88SSatish Balay ierr = MatAssemblyBegin(aij->A,mode);CHKERRQ(ierr); 750bc5ccf88SSatish Balay ierr = MatAssemblyEnd(aij->A,mode);CHKERRQ(ierr); 751bc5ccf88SSatish Balay 752bc5ccf88SSatish Balay /* determine if any processor has disassembled, if so we must 753bc5ccf88SSatish Balay also disassemble ourselfs, in order that we may reassemble. */ 754bc5ccf88SSatish Balay /* 755bc5ccf88SSatish Balay if nonzero structure of submatrix B cannot change then we know that 756bc5ccf88SSatish Balay no processor disassembled thus we can skip this stuff 757bc5ccf88SSatish Balay */ 758bc5ccf88SSatish Balay if (!((Mat_SeqAIJ*)aij->B->data)->nonew) { 759b2566f29SBarry Smith ierr = MPIU_Allreduce(&mat->was_assembled,&other_disassembled,1,MPIU_BOOL,MPI_PROD,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 760bc5ccf88SSatish Balay if (mat->was_assembled && !other_disassembled) { 761ab9863d7SBarry Smith ierr = MatDisAssemble_MPIAIJ(mat);CHKERRQ(ierr); 762ad59fb31SSatish Balay } 763ad59fb31SSatish Balay } 764bc5ccf88SSatish Balay if (!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) { 765bc5ccf88SSatish Balay ierr = MatSetUpMultiply_MPIAIJ(mat);CHKERRQ(ierr); 766bc5ccf88SSatish Balay } 7674e0d8c25SBarry Smith ierr = MatSetOption(aij->B,MAT_USE_INODES,PETSC_FALSE);CHKERRQ(ierr); 768bc5ccf88SSatish Balay ierr = MatAssemblyBegin(aij->B,mode);CHKERRQ(ierr); 769bc5ccf88SSatish Balay ierr = MatAssemblyEnd(aij->B,mode);CHKERRQ(ierr); 770bc5ccf88SSatish Balay 7711d79065fSBarry Smith ierr = PetscFree2(aij->rowvalues,aij->rowindices);CHKERRQ(ierr); 7722205254eSKarl Rupp 773606d414cSSatish Balay aij->rowvalues = 0; 774a30b2313SHong Zhang 7756bf464f9SBarry Smith ierr = VecDestroy(&aij->diag);CHKERRQ(ierr); 776bd0c2dcbSBarry Smith if (a->inode.size) mat->ops->multdiagonalblock = MatMultDiagonalBlock_MPIAIJ; 777e56f5c9eSBarry Smith 7784f9cfa9eSBarry Smith /* if no new nonzero locations are allowed in matrix then only set the matrix state the first time through */ 7794f9cfa9eSBarry Smith if ((!mat->was_assembled && mode == MAT_FINAL_ASSEMBLY) || !((Mat_SeqAIJ*)(aij->A->data))->nonew) { 780e56f5c9eSBarry Smith PetscObjectState state = aij->A->nonzerostate + aij->B->nonzerostate; 781b2566f29SBarry Smith ierr = MPIU_Allreduce(&state,&mat->nonzerostate,1,MPIU_INT64,MPI_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 782e56f5c9eSBarry Smith } 783bc5ccf88SSatish Balay PetscFunctionReturn(0); 784bc5ccf88SSatish Balay } 785bc5ccf88SSatish Balay 7864a2ae208SSatish Balay #undef __FUNCT__ 7874a2ae208SSatish Balay #define __FUNCT__ "MatZeroEntries_MPIAIJ" 788dfbe8321SBarry Smith PetscErrorCode MatZeroEntries_MPIAIJ(Mat A) 7891eb62cbbSBarry Smith { 79044a69424SLois Curfman McInnes Mat_MPIAIJ *l = (Mat_MPIAIJ*)A->data; 791dfbe8321SBarry Smith PetscErrorCode ierr; 7923a40ed3dSBarry Smith 7933a40ed3dSBarry Smith PetscFunctionBegin; 79478b31e54SBarry Smith ierr = MatZeroEntries(l->A);CHKERRQ(ierr); 79578b31e54SBarry Smith ierr = MatZeroEntries(l->B);CHKERRQ(ierr); 7963a40ed3dSBarry Smith PetscFunctionReturn(0); 7971eb62cbbSBarry Smith } 7981eb62cbbSBarry Smith 7994a2ae208SSatish Balay #undef __FUNCT__ 8004a2ae208SSatish Balay #define __FUNCT__ "MatZeroRows_MPIAIJ" 8012b40b63fSBarry Smith PetscErrorCode MatZeroRows_MPIAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 8021eb62cbbSBarry Smith { 8031b1dd7adSMatthew G. Knepley Mat_MPIAIJ *mat = (Mat_MPIAIJ *) A->data; 8041b1dd7adSMatthew G. Knepley PetscInt *lrows; 8056e520ac8SStefano Zampini PetscInt r, len; 8066849ba73SBarry Smith PetscErrorCode ierr; 8071eb62cbbSBarry Smith 8083a40ed3dSBarry Smith PetscFunctionBegin; 8096e520ac8SStefano Zampini /* get locally owned rows */ 8106e520ac8SStefano Zampini ierr = MatZeroRowsMapLocal_Private(A,N,rows,&len,&lrows);CHKERRQ(ierr); 81197b48c8fSBarry Smith /* fix right hand side if needed */ 81297b48c8fSBarry Smith if (x && b) { 8131b1dd7adSMatthew G. Knepley const PetscScalar *xx; 8141b1dd7adSMatthew G. Knepley PetscScalar *bb; 8151b1dd7adSMatthew G. Knepley 81697b48c8fSBarry Smith ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr); 81797b48c8fSBarry Smith ierr = VecGetArray(b, &bb);CHKERRQ(ierr); 8181b1dd7adSMatthew G. Knepley for (r = 0; r < len; ++r) bb[lrows[r]] = diag*xx[lrows[r]]; 81997b48c8fSBarry Smith ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr); 82097b48c8fSBarry Smith ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr); 82197b48c8fSBarry Smith } 8221b1dd7adSMatthew G. Knepley /* Must zero l->B before l->A because the (diag) case below may put values into l->B*/ 823a34163a4SJed Brown ierr = MatZeroRows(mat->B, len, lrows, 0.0, NULL, NULL);CHKERRQ(ierr); 8249ae29715SStefano Zampini if (A->congruentlayouts == -1) { /* first time we compare rows and cols layouts */ 8259ae29715SStefano Zampini PetscBool cong; 8269ae29715SStefano Zampini ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr); 8279ae29715SStefano Zampini if (cong) A->congruentlayouts = 1; 8289ae29715SStefano Zampini else A->congruentlayouts = 0; 8299ae29715SStefano Zampini } 8309ae29715SStefano Zampini if ((diag != 0.0) && A->congruentlayouts) { 8311b1dd7adSMatthew G. Knepley ierr = MatZeroRows(mat->A, len, lrows, diag, NULL, NULL);CHKERRQ(ierr); 832f4df32b1SMatthew Knepley } else if (diag != 0.0) { 8331b1dd7adSMatthew G. Knepley ierr = MatZeroRows(mat->A, len, lrows, 0.0, NULL, NULL);CHKERRQ(ierr); 8341b1dd7adSMatthew G. Knepley if (((Mat_SeqAIJ *) mat->A->data)->nonew) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "MatZeroRows() on rectangular matrices cannot be used with the Mat options\nMAT_NEW_NONZERO_LOCATIONS,MAT_NEW_NONZERO_LOCATION_ERR,MAT_NEW_NONZERO_ALLOCATION_ERR"); 8351b1dd7adSMatthew G. Knepley for (r = 0; r < len; ++r) { 8361b1dd7adSMatthew G. Knepley const PetscInt row = lrows[r] + A->rmap->rstart; 837f4df32b1SMatthew Knepley ierr = MatSetValues(A, 1, &row, 1, &row, &diag, INSERT_VALUES);CHKERRQ(ierr); 838e2d53e46SBarry Smith } 839e2d53e46SBarry Smith ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 840e2d53e46SBarry Smith ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 8416eb55b6aSBarry Smith } else { 8421b1dd7adSMatthew G. Knepley ierr = MatZeroRows(mat->A, len, lrows, 0.0, NULL, NULL);CHKERRQ(ierr); 8436eb55b6aSBarry Smith } 844606d414cSSatish Balay ierr = PetscFree(lrows);CHKERRQ(ierr); 8454f9cfa9eSBarry Smith 8464f9cfa9eSBarry Smith /* only change matrix nonzero state if pattern was allowed to be changed */ 8474f9cfa9eSBarry Smith if (!((Mat_SeqAIJ*)(mat->A->data))->keepnonzeropattern) { 848e56f5c9eSBarry Smith PetscObjectState state = mat->A->nonzerostate + mat->B->nonzerostate; 849b2566f29SBarry Smith ierr = MPIU_Allreduce(&state,&A->nonzerostate,1,MPIU_INT64,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 850e56f5c9eSBarry Smith } 8513a40ed3dSBarry Smith PetscFunctionReturn(0); 8521eb62cbbSBarry Smith } 8531eb62cbbSBarry Smith 8544a2ae208SSatish Balay #undef __FUNCT__ 8559c7c4993SBarry Smith #define __FUNCT__ "MatZeroRowsColumns_MPIAIJ" 8569c7c4993SBarry Smith PetscErrorCode MatZeroRowsColumns_MPIAIJ(Mat A,PetscInt N,const PetscInt rows[],PetscScalar diag,Vec x,Vec b) 8579c7c4993SBarry Smith { 8589c7c4993SBarry Smith Mat_MPIAIJ *l = (Mat_MPIAIJ*)A->data; 8599c7c4993SBarry Smith PetscErrorCode ierr; 8605ba17502SJed Brown PetscMPIInt n = A->rmap->n; 86178fab17bSMatthew G. Knepley PetscInt i,j,r,m,p = 0,len = 0; 86254bd4135SMatthew G. Knepley PetscInt *lrows,*owners = A->rmap->range; 86354bd4135SMatthew G. Knepley PetscSFNode *rrows; 86454bd4135SMatthew G. Knepley PetscSF sf; 8659c7c4993SBarry Smith const PetscScalar *xx; 866564f14d6SBarry Smith PetscScalar *bb,*mask; 867564f14d6SBarry Smith Vec xmask,lmask; 868564f14d6SBarry Smith Mat_SeqAIJ *aij = (Mat_SeqAIJ*)l->B->data; 869564f14d6SBarry Smith const PetscInt *aj, *ii,*ridx; 870564f14d6SBarry Smith PetscScalar *aa; 8719c7c4993SBarry Smith 8729c7c4993SBarry Smith PetscFunctionBegin; 87354bd4135SMatthew G. Knepley /* Create SF where leaves are input rows and roots are owned rows */ 87454bd4135SMatthew G. Knepley ierr = PetscMalloc1(n, &lrows);CHKERRQ(ierr); 87554bd4135SMatthew G. Knepley for (r = 0; r < n; ++r) lrows[r] = -1; 87654bd4135SMatthew G. Knepley ierr = PetscMalloc1(N, &rrows);CHKERRQ(ierr); 87754bd4135SMatthew G. Knepley for (r = 0; r < N; ++r) { 87854bd4135SMatthew G. Knepley const PetscInt idx = rows[r]; 8795ba17502SJed 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); 8805ba17502SJed Brown if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this row too */ 8815ba17502SJed Brown ierr = PetscLayoutFindOwner(A->rmap,idx,&p);CHKERRQ(ierr); 8825ba17502SJed Brown } 88354bd4135SMatthew G. Knepley rrows[r].rank = p; 88454bd4135SMatthew G. Knepley rrows[r].index = rows[r] - owners[p]; 8859c7c4993SBarry Smith } 88654bd4135SMatthew G. Knepley ierr = PetscSFCreate(PetscObjectComm((PetscObject) A), &sf);CHKERRQ(ierr); 88754bd4135SMatthew G. Knepley ierr = PetscSFSetGraph(sf, n, N, NULL, PETSC_OWN_POINTER, rrows, PETSC_OWN_POINTER);CHKERRQ(ierr); 88854bd4135SMatthew G. Knepley /* Collect flags for rows to be zeroed */ 88954bd4135SMatthew G. Knepley ierr = PetscSFReduceBegin(sf, MPIU_INT, (PetscInt *) rows, lrows, MPI_LOR);CHKERRQ(ierr); 89054bd4135SMatthew G. Knepley ierr = PetscSFReduceEnd(sf, MPIU_INT, (PetscInt *) rows, lrows, MPI_LOR);CHKERRQ(ierr); 89154bd4135SMatthew G. Knepley ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 89254bd4135SMatthew G. Knepley /* Compress and put in row numbers */ 89354bd4135SMatthew G. Knepley for (r = 0; r < n; ++r) if (lrows[r] >= 0) lrows[len++] = r; 894564f14d6SBarry Smith /* zero diagonal part of matrix */ 89554bd4135SMatthew G. Knepley ierr = MatZeroRowsColumns(l->A,len,lrows,diag,x,b);CHKERRQ(ierr); 896564f14d6SBarry Smith /* handle off diagonal part of matrix */ 8972a7a6963SBarry Smith ierr = MatCreateVecs(A,&xmask,NULL);CHKERRQ(ierr); 898564f14d6SBarry Smith ierr = VecDuplicate(l->lvec,&lmask);CHKERRQ(ierr); 899564f14d6SBarry Smith ierr = VecGetArray(xmask,&bb);CHKERRQ(ierr); 90054bd4135SMatthew G. Knepley for (i=0; i<len; i++) bb[lrows[i]] = 1; 901564f14d6SBarry Smith ierr = VecRestoreArray(xmask,&bb);CHKERRQ(ierr); 902564f14d6SBarry Smith ierr = VecScatterBegin(l->Mvctx,xmask,lmask,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 903564f14d6SBarry Smith ierr = VecScatterEnd(l->Mvctx,xmask,lmask,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 9046bf464f9SBarry Smith ierr = VecDestroy(&xmask);CHKERRQ(ierr); 905377aa5a1SBarry Smith if (x) { 90667caceb0SMatthew G. Knepley ierr = VecScatterBegin(l->Mvctx,x,l->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 90767caceb0SMatthew G. Knepley ierr = VecScatterEnd(l->Mvctx,x,l->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 908564f14d6SBarry Smith ierr = VecGetArrayRead(l->lvec,&xx);CHKERRQ(ierr); 909564f14d6SBarry Smith ierr = VecGetArray(b,&bb);CHKERRQ(ierr); 910377aa5a1SBarry Smith } 911377aa5a1SBarry Smith ierr = VecGetArray(lmask,&mask);CHKERRQ(ierr); 912564f14d6SBarry Smith /* remove zeroed rows of off diagonal matrix */ 913564f14d6SBarry Smith ii = aij->i; 91454bd4135SMatthew G. Knepley for (i=0; i<len; i++) { 915564f14d6SBarry Smith ierr = PetscMemzero(aij->a + ii[lrows[i]],(ii[lrows[i]+1] - ii[lrows[i]])*sizeof(PetscScalar));CHKERRQ(ierr); 9169c7c4993SBarry Smith } 917564f14d6SBarry Smith /* loop over all elements of off process part of matrix zeroing removed columns*/ 918564f14d6SBarry Smith if (aij->compressedrow.use) { 919564f14d6SBarry Smith m = aij->compressedrow.nrows; 920564f14d6SBarry Smith ii = aij->compressedrow.i; 921564f14d6SBarry Smith ridx = aij->compressedrow.rindex; 922564f14d6SBarry Smith for (i=0; i<m; i++) { 923564f14d6SBarry Smith n = ii[i+1] - ii[i]; 924564f14d6SBarry Smith aj = aij->j + ii[i]; 925564f14d6SBarry Smith aa = aij->a + ii[i]; 926564f14d6SBarry Smith 927564f14d6SBarry Smith for (j=0; j<n; j++) { 92825266a92SSatish Balay if (PetscAbsScalar(mask[*aj])) { 929377aa5a1SBarry Smith if (b) bb[*ridx] -= *aa*xx[*aj]; 930564f14d6SBarry Smith *aa = 0.0; 931564f14d6SBarry Smith } 932564f14d6SBarry Smith aa++; 933564f14d6SBarry Smith aj++; 934564f14d6SBarry Smith } 935564f14d6SBarry Smith ridx++; 936564f14d6SBarry Smith } 937564f14d6SBarry Smith } else { /* do not use compressed row format */ 938564f14d6SBarry Smith m = l->B->rmap->n; 939564f14d6SBarry Smith for (i=0; i<m; i++) { 940564f14d6SBarry Smith n = ii[i+1] - ii[i]; 941564f14d6SBarry Smith aj = aij->j + ii[i]; 942564f14d6SBarry Smith aa = aij->a + ii[i]; 943564f14d6SBarry Smith for (j=0; j<n; j++) { 94425266a92SSatish Balay if (PetscAbsScalar(mask[*aj])) { 945377aa5a1SBarry Smith if (b) bb[i] -= *aa*xx[*aj]; 946564f14d6SBarry Smith *aa = 0.0; 947564f14d6SBarry Smith } 948564f14d6SBarry Smith aa++; 949564f14d6SBarry Smith aj++; 950564f14d6SBarry Smith } 951564f14d6SBarry Smith } 952564f14d6SBarry Smith } 953377aa5a1SBarry Smith if (x) { 954564f14d6SBarry Smith ierr = VecRestoreArray(b,&bb);CHKERRQ(ierr); 955564f14d6SBarry Smith ierr = VecRestoreArrayRead(l->lvec,&xx);CHKERRQ(ierr); 956377aa5a1SBarry Smith } 957377aa5a1SBarry Smith ierr = VecRestoreArray(lmask,&mask);CHKERRQ(ierr); 9586bf464f9SBarry Smith ierr = VecDestroy(&lmask);CHKERRQ(ierr); 9599c7c4993SBarry Smith ierr = PetscFree(lrows);CHKERRQ(ierr); 9604f9cfa9eSBarry Smith 9614f9cfa9eSBarry Smith /* only change matrix nonzero state if pattern was allowed to be changed */ 9624f9cfa9eSBarry Smith if (!((Mat_SeqAIJ*)(l->A->data))->keepnonzeropattern) { 9634f9cfa9eSBarry Smith PetscObjectState state = l->A->nonzerostate + l->B->nonzerostate; 964b2566f29SBarry Smith ierr = MPIU_Allreduce(&state,&A->nonzerostate,1,MPIU_INT64,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 9654f9cfa9eSBarry Smith } 9669c7c4993SBarry Smith PetscFunctionReturn(0); 9679c7c4993SBarry Smith } 9689c7c4993SBarry Smith 9699c7c4993SBarry Smith #undef __FUNCT__ 9704a2ae208SSatish Balay #define __FUNCT__ "MatMult_MPIAIJ" 971dfbe8321SBarry Smith PetscErrorCode MatMult_MPIAIJ(Mat A,Vec xx,Vec yy) 9721eb62cbbSBarry Smith { 973416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 974dfbe8321SBarry Smith PetscErrorCode ierr; 975b1d57f15SBarry Smith PetscInt nt; 976416022c9SBarry Smith 9773a40ed3dSBarry Smith PetscFunctionBegin; 978a2ce50c7SBarry Smith ierr = VecGetLocalSize(xx,&nt);CHKERRQ(ierr); 97965e19b50SBarry 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); 980ca9f406cSSatish Balay ierr = VecScatterBegin(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 981f830108cSBarry Smith ierr = (*a->A->ops->mult)(a->A,xx,yy);CHKERRQ(ierr); 982ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 983f830108cSBarry Smith ierr = (*a->B->ops->multadd)(a->B,a->lvec,yy,yy);CHKERRQ(ierr); 9843a40ed3dSBarry Smith PetscFunctionReturn(0); 9851eb62cbbSBarry Smith } 9861eb62cbbSBarry Smith 9874a2ae208SSatish Balay #undef __FUNCT__ 988bd0c2dcbSBarry Smith #define __FUNCT__ "MatMultDiagonalBlock_MPIAIJ" 989bd0c2dcbSBarry Smith PetscErrorCode MatMultDiagonalBlock_MPIAIJ(Mat A,Vec bb,Vec xx) 990bd0c2dcbSBarry Smith { 991bd0c2dcbSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 992bd0c2dcbSBarry Smith PetscErrorCode ierr; 993bd0c2dcbSBarry Smith 994bd0c2dcbSBarry Smith PetscFunctionBegin; 995bd0c2dcbSBarry Smith ierr = MatMultDiagonalBlock(a->A,bb,xx);CHKERRQ(ierr); 996bd0c2dcbSBarry Smith PetscFunctionReturn(0); 997bd0c2dcbSBarry Smith } 998bd0c2dcbSBarry Smith 999bd0c2dcbSBarry Smith #undef __FUNCT__ 10004a2ae208SSatish Balay #define __FUNCT__ "MatMultAdd_MPIAIJ" 1001dfbe8321SBarry Smith PetscErrorCode MatMultAdd_MPIAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1002da3a660dSBarry Smith { 1003416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1004dfbe8321SBarry Smith PetscErrorCode ierr; 10053a40ed3dSBarry Smith 10063a40ed3dSBarry Smith PetscFunctionBegin; 1007ca9f406cSSatish Balay ierr = VecScatterBegin(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1008f830108cSBarry Smith ierr = (*a->A->ops->multadd)(a->A,xx,yy,zz);CHKERRQ(ierr); 1009ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,xx,a->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1010f830108cSBarry Smith ierr = (*a->B->ops->multadd)(a->B,a->lvec,zz,zz);CHKERRQ(ierr); 10113a40ed3dSBarry Smith PetscFunctionReturn(0); 1012da3a660dSBarry Smith } 1013da3a660dSBarry Smith 10144a2ae208SSatish Balay #undef __FUNCT__ 10154a2ae208SSatish Balay #define __FUNCT__ "MatMultTranspose_MPIAIJ" 1016dfbe8321SBarry Smith PetscErrorCode MatMultTranspose_MPIAIJ(Mat A,Vec xx,Vec yy) 1017da3a660dSBarry Smith { 1018416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1019dfbe8321SBarry Smith PetscErrorCode ierr; 1020ace3abfcSBarry Smith PetscBool merged; 1021da3a660dSBarry Smith 10223a40ed3dSBarry Smith PetscFunctionBegin; 1023a5ff213dSBarry Smith ierr = VecScatterGetMerged(a->Mvctx,&merged);CHKERRQ(ierr); 1024da3a660dSBarry Smith /* do nondiagonal part */ 10257c922b88SBarry Smith ierr = (*a->B->ops->multtranspose)(a->B,xx,a->lvec);CHKERRQ(ierr); 1026a5ff213dSBarry Smith if (!merged) { 1027da3a660dSBarry Smith /* send it on its way */ 1028ca9f406cSSatish Balay ierr = VecScatterBegin(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1029da3a660dSBarry Smith /* do local part */ 10307c922b88SBarry Smith ierr = (*a->A->ops->multtranspose)(a->A,xx,yy);CHKERRQ(ierr); 1031da3a660dSBarry Smith /* receive remote parts: note this assumes the values are not actually */ 1032a5ff213dSBarry Smith /* added in yy until the next line, */ 1033ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1034a5ff213dSBarry Smith } else { 1035a5ff213dSBarry Smith /* do local part */ 1036a5ff213dSBarry Smith ierr = (*a->A->ops->multtranspose)(a->A,xx,yy);CHKERRQ(ierr); 1037a5ff213dSBarry Smith /* send it on its way */ 1038ca9f406cSSatish Balay ierr = VecScatterBegin(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1039a5ff213dSBarry Smith /* values actually were received in the Begin() but we need to call this nop */ 1040ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,a->lvec,yy,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1041a5ff213dSBarry Smith } 10423a40ed3dSBarry Smith PetscFunctionReturn(0); 1043da3a660dSBarry Smith } 1044da3a660dSBarry Smith 1045cd0d46ebSvictorle #undef __FUNCT__ 10465fbd3699SBarry Smith #define __FUNCT__ "MatIsTranspose_MPIAIJ" 10477087cfbeSBarry Smith PetscErrorCode MatIsTranspose_MPIAIJ(Mat Amat,Mat Bmat,PetscReal tol,PetscBool *f) 1048cd0d46ebSvictorle { 10494f423910Svictorle MPI_Comm comm; 1050cd0d46ebSvictorle Mat_MPIAIJ *Aij = (Mat_MPIAIJ*) Amat->data, *Bij; 105166501d38Svictorle Mat Adia = Aij->A, Bdia, Aoff,Boff,*Aoffs,*Boffs; 1052cd0d46ebSvictorle IS Me,Notme; 10536849ba73SBarry Smith PetscErrorCode ierr; 1054b1d57f15SBarry Smith PetscInt M,N,first,last,*notme,i; 1055b1d57f15SBarry Smith PetscMPIInt size; 1056cd0d46ebSvictorle 1057cd0d46ebSvictorle PetscFunctionBegin; 105842e5f5b4Svictorle /* Easy test: symmetric diagonal block */ 105966501d38Svictorle Bij = (Mat_MPIAIJ*) Bmat->data; Bdia = Bij->A; 10605485867bSBarry Smith ierr = MatIsTranspose(Adia,Bdia,tol,f);CHKERRQ(ierr); 1061cd0d46ebSvictorle if (!*f) PetscFunctionReturn(0); 10624f423910Svictorle ierr = PetscObjectGetComm((PetscObject)Amat,&comm);CHKERRQ(ierr); 1063b1d57f15SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 1064b1d57f15SBarry Smith if (size == 1) PetscFunctionReturn(0); 106542e5f5b4Svictorle 106642e5f5b4Svictorle /* Hard test: off-diagonal block. This takes a MatGetSubMatrix. */ 1067cd0d46ebSvictorle ierr = MatGetSize(Amat,&M,&N);CHKERRQ(ierr); 1068cd0d46ebSvictorle ierr = MatGetOwnershipRange(Amat,&first,&last);CHKERRQ(ierr); 1069854ce69bSBarry Smith ierr = PetscMalloc1(N-last+first,¬me);CHKERRQ(ierr); 1070cd0d46ebSvictorle for (i=0; i<first; i++) notme[i] = i; 1071cd0d46ebSvictorle for (i=last; i<M; i++) notme[i-last+first] = i; 107270b3c8c7SBarry Smith ierr = ISCreateGeneral(MPI_COMM_SELF,N-last+first,notme,PETSC_COPY_VALUES,&Notme);CHKERRQ(ierr); 1073268466fbSBarry Smith ierr = ISCreateStride(MPI_COMM_SELF,last-first,first,1,&Me);CHKERRQ(ierr); 1074268466fbSBarry Smith ierr = MatGetSubMatrices(Amat,1,&Me,&Notme,MAT_INITIAL_MATRIX,&Aoffs);CHKERRQ(ierr); 107566501d38Svictorle Aoff = Aoffs[0]; 1076268466fbSBarry Smith ierr = MatGetSubMatrices(Bmat,1,&Notme,&Me,MAT_INITIAL_MATRIX,&Boffs);CHKERRQ(ierr); 107766501d38Svictorle Boff = Boffs[0]; 10785485867bSBarry Smith ierr = MatIsTranspose(Aoff,Boff,tol,f);CHKERRQ(ierr); 107966501d38Svictorle ierr = MatDestroyMatrices(1,&Aoffs);CHKERRQ(ierr); 108066501d38Svictorle ierr = MatDestroyMatrices(1,&Boffs);CHKERRQ(ierr); 10816bf464f9SBarry Smith ierr = ISDestroy(&Me);CHKERRQ(ierr); 10826bf464f9SBarry Smith ierr = ISDestroy(&Notme);CHKERRQ(ierr); 10833e0d0d19SHong Zhang ierr = PetscFree(notme);CHKERRQ(ierr); 1084cd0d46ebSvictorle PetscFunctionReturn(0); 1085cd0d46ebSvictorle } 1086cd0d46ebSvictorle 10874a2ae208SSatish Balay #undef __FUNCT__ 10884a2ae208SSatish Balay #define __FUNCT__ "MatMultTransposeAdd_MPIAIJ" 1089dfbe8321SBarry Smith PetscErrorCode MatMultTransposeAdd_MPIAIJ(Mat A,Vec xx,Vec yy,Vec zz) 1090da3a660dSBarry Smith { 1091416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1092dfbe8321SBarry Smith PetscErrorCode ierr; 1093da3a660dSBarry Smith 10943a40ed3dSBarry Smith PetscFunctionBegin; 1095da3a660dSBarry Smith /* do nondiagonal part */ 10967c922b88SBarry Smith ierr = (*a->B->ops->multtranspose)(a->B,xx,a->lvec);CHKERRQ(ierr); 1097da3a660dSBarry Smith /* send it on its way */ 1098ca9f406cSSatish Balay ierr = VecScatterBegin(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 1099da3a660dSBarry Smith /* do local part */ 11007c922b88SBarry Smith ierr = (*a->A->ops->multtransposeadd)(a->A,xx,yy,zz);CHKERRQ(ierr); 1101a5ff213dSBarry Smith /* receive remote parts */ 1102ca9f406cSSatish Balay ierr = VecScatterEnd(a->Mvctx,a->lvec,zz,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); 11033a40ed3dSBarry Smith PetscFunctionReturn(0); 1104da3a660dSBarry Smith } 1105da3a660dSBarry Smith 11061eb62cbbSBarry Smith /* 11071eb62cbbSBarry Smith This only works correctly for square matrices where the subblock A->A is the 11081eb62cbbSBarry Smith diagonal block 11091eb62cbbSBarry Smith */ 11104a2ae208SSatish Balay #undef __FUNCT__ 11114a2ae208SSatish Balay #define __FUNCT__ "MatGetDiagonal_MPIAIJ" 1112dfbe8321SBarry Smith PetscErrorCode MatGetDiagonal_MPIAIJ(Mat A,Vec v) 11131eb62cbbSBarry Smith { 1114dfbe8321SBarry Smith PetscErrorCode ierr; 1115416022c9SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 11163a40ed3dSBarry Smith 11173a40ed3dSBarry Smith PetscFunctionBegin; 1118ce94432eSBarry 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"); 1119e7e72b3dSBarry 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"); 11203a40ed3dSBarry Smith ierr = MatGetDiagonal(a->A,v);CHKERRQ(ierr); 11213a40ed3dSBarry Smith PetscFunctionReturn(0); 11221eb62cbbSBarry Smith } 11231eb62cbbSBarry Smith 11244a2ae208SSatish Balay #undef __FUNCT__ 11254a2ae208SSatish Balay #define __FUNCT__ "MatScale_MPIAIJ" 1126f4df32b1SMatthew Knepley PetscErrorCode MatScale_MPIAIJ(Mat A,PetscScalar aa) 1127052efed2SBarry Smith { 1128052efed2SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1129dfbe8321SBarry Smith PetscErrorCode ierr; 11303a40ed3dSBarry Smith 11313a40ed3dSBarry Smith PetscFunctionBegin; 1132f4df32b1SMatthew Knepley ierr = MatScale(a->A,aa);CHKERRQ(ierr); 1133f4df32b1SMatthew Knepley ierr = MatScale(a->B,aa);CHKERRQ(ierr); 11343a40ed3dSBarry Smith PetscFunctionReturn(0); 1135052efed2SBarry Smith } 1136052efed2SBarry Smith 11374a2ae208SSatish Balay #undef __FUNCT__ 11384a2ae208SSatish Balay #define __FUNCT__ "MatDestroy_MPIAIJ" 1139dfbe8321SBarry Smith PetscErrorCode MatDestroy_MPIAIJ(Mat mat) 11401eb62cbbSBarry Smith { 114144a69424SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 1142dfbe8321SBarry Smith PetscErrorCode ierr; 114383e2fdc7SBarry Smith 11443a40ed3dSBarry Smith PetscFunctionBegin; 1145aa482453SBarry Smith #if defined(PETSC_USE_LOG) 1146d0f46423SBarry Smith PetscLogObjectState((PetscObject)mat,"Rows=%D, Cols=%D",mat->rmap->N,mat->cmap->N); 1147a5a9c739SBarry Smith #endif 11488798bf22SSatish Balay ierr = MatStashDestroy_Private(&mat->stash);CHKERRQ(ierr); 11496bf464f9SBarry Smith ierr = VecDestroy(&aij->diag);CHKERRQ(ierr); 11506bf464f9SBarry Smith ierr = MatDestroy(&aij->A);CHKERRQ(ierr); 11516bf464f9SBarry Smith ierr = MatDestroy(&aij->B);CHKERRQ(ierr); 1152aa482453SBarry Smith #if defined(PETSC_USE_CTABLE) 11536bc0bbbfSBarry Smith ierr = PetscTableDestroy(&aij->colmap);CHKERRQ(ierr); 1154b1fc9764SSatish Balay #else 115505b42c5fSBarry Smith ierr = PetscFree(aij->colmap);CHKERRQ(ierr); 1156b1fc9764SSatish Balay #endif 115705b42c5fSBarry Smith ierr = PetscFree(aij->garray);CHKERRQ(ierr); 11586bf464f9SBarry Smith ierr = VecDestroy(&aij->lvec);CHKERRQ(ierr); 11596bf464f9SBarry Smith ierr = VecScatterDestroy(&aij->Mvctx);CHKERRQ(ierr); 116003095fedSBarry Smith ierr = PetscFree2(aij->rowvalues,aij->rowindices);CHKERRQ(ierr); 11618aa348c1SBarry Smith ierr = PetscFree(aij->ld);CHKERRQ(ierr); 1162bf0cc555SLisandro Dalcin ierr = PetscFree(mat->data);CHKERRQ(ierr); 1163901853e0SKris Buschelman 1164dbd8c25aSHong Zhang ierr = PetscObjectChangeTypeName((PetscObject)mat,0);CHKERRQ(ierr); 1165bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatStoreValues_C",NULL);CHKERRQ(ierr); 1166bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatRetrieveValues_C",NULL);CHKERRQ(ierr); 1167bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatIsTranspose_C",NULL);CHKERRQ(ierr); 1168bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPIAIJSetPreallocation_C",NULL);CHKERRQ(ierr); 1169bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatMPIAIJSetPreallocationCSR_C",NULL);CHKERRQ(ierr); 1170bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatDiagonalScaleLocal_C",NULL);CHKERRQ(ierr); 1171bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_mpiaij_mpisbaij_C",NULL);CHKERRQ(ierr); 11725d7652ecSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 11735d7652ecSHong Zhang ierr = PetscObjectComposeFunction((PetscObject)mat,"MatConvert_mpiaij_elemental_C",NULL);CHKERRQ(ierr); 11745d7652ecSHong Zhang #endif 11753a40ed3dSBarry Smith PetscFunctionReturn(0); 11761eb62cbbSBarry Smith } 1177ee50ffe9SBarry Smith 11784a2ae208SSatish Balay #undef __FUNCT__ 11798e2fed03SBarry Smith #define __FUNCT__ "MatView_MPIAIJ_Binary" 1180dfbe8321SBarry Smith PetscErrorCode MatView_MPIAIJ_Binary(Mat mat,PetscViewer viewer) 11818e2fed03SBarry Smith { 11828e2fed03SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 11838e2fed03SBarry Smith Mat_SeqAIJ *A = (Mat_SeqAIJ*)aij->A->data; 11848e2fed03SBarry Smith Mat_SeqAIJ *B = (Mat_SeqAIJ*)aij->B->data; 11856849ba73SBarry Smith PetscErrorCode ierr; 118632dcc486SBarry Smith PetscMPIInt rank,size,tag = ((PetscObject)viewer)->tag; 11876f69ff64SBarry Smith int fd; 1188a788621eSSatish Balay PetscInt nz,header[4],*row_lengths,*range=0,rlen,i; 1189d892089bSMatthew G. Knepley PetscInt nzmax,*column_indices,j,k,col,*garray = aij->garray,cnt,cstart = mat->cmap->rstart,rnz = 0; 11908e2fed03SBarry Smith PetscScalar *column_values; 119185ebf7a4SBarry Smith PetscInt message_count,flowcontrolcount; 1192b37d52dbSMark F. Adams FILE *file; 11938e2fed03SBarry Smith 11948e2fed03SBarry Smith PetscFunctionBegin; 1195ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr); 1196ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr); 11978e2fed03SBarry Smith nz = A->nz + B->nz; 11985872f025SBarry Smith ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 1199958c9bccSBarry Smith if (!rank) { 12000700a824SBarry Smith header[0] = MAT_FILE_CLASSID; 1201d0f46423SBarry Smith header[1] = mat->rmap->N; 1202d0f46423SBarry Smith header[2] = mat->cmap->N; 12032205254eSKarl Rupp 1204ce94432eSBarry Smith ierr = MPI_Reduce(&nz,&header[3],1,MPIU_INT,MPI_SUM,0,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 12056f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,header,4,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 12068e2fed03SBarry Smith /* get largest number of rows any processor has */ 1207d0f46423SBarry Smith rlen = mat->rmap->n; 1208d0f46423SBarry Smith range = mat->rmap->range; 12092205254eSKarl Rupp for (i=1; i<size; i++) rlen = PetscMax(rlen,range[i+1] - range[i]); 12108e2fed03SBarry Smith } else { 1211ce94432eSBarry Smith ierr = MPI_Reduce(&nz,0,1,MPIU_INT,MPI_SUM,0,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1212d0f46423SBarry Smith rlen = mat->rmap->n; 12138e2fed03SBarry Smith } 12148e2fed03SBarry Smith 12158e2fed03SBarry Smith /* load up the local row counts */ 1216854ce69bSBarry Smith ierr = PetscMalloc1(rlen+1,&row_lengths);CHKERRQ(ierr); 12172205254eSKarl 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]; 12188e2fed03SBarry Smith 12198e2fed03SBarry Smith /* store the row lengths to the file */ 122085ebf7a4SBarry Smith ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr); 1221958c9bccSBarry Smith if (!rank) { 1222d0f46423SBarry Smith ierr = PetscBinaryWrite(fd,row_lengths,mat->rmap->n,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 12238e2fed03SBarry Smith for (i=1; i<size; i++) { 1224639ff905SBarry Smith ierr = PetscViewerFlowControlStepMaster(viewer,i,&message_count,flowcontrolcount);CHKERRQ(ierr); 12258e2fed03SBarry Smith rlen = range[i+1] - range[i]; 1226ce94432eSBarry Smith ierr = MPIULong_Recv(row_lengths,rlen,MPIU_INT,i,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 12276f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,row_lengths,rlen,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 12288e2fed03SBarry Smith } 1229639ff905SBarry Smith ierr = PetscViewerFlowControlEndMaster(viewer,&message_count);CHKERRQ(ierr); 12308e2fed03SBarry Smith } else { 1231639ff905SBarry Smith ierr = PetscViewerFlowControlStepWorker(viewer,rank,&message_count);CHKERRQ(ierr); 1232ce94432eSBarry Smith ierr = MPIULong_Send(row_lengths,mat->rmap->n,MPIU_INT,0,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1233639ff905SBarry Smith ierr = PetscViewerFlowControlEndWorker(viewer,&message_count);CHKERRQ(ierr); 12348e2fed03SBarry Smith } 12358e2fed03SBarry Smith ierr = PetscFree(row_lengths);CHKERRQ(ierr); 12368e2fed03SBarry Smith 12378e2fed03SBarry Smith /* load up the local column indices */ 12381147fc2aSKarl Rupp nzmax = nz; /* th processor needs space a largest processor needs */ 1239ce94432eSBarry Smith ierr = MPI_Reduce(&nz,&nzmax,1,MPIU_INT,MPI_MAX,0,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1240854ce69bSBarry Smith ierr = PetscMalloc1(nzmax+1,&column_indices);CHKERRQ(ierr); 12418e2fed03SBarry Smith cnt = 0; 1242d0f46423SBarry Smith for (i=0; i<mat->rmap->n; i++) { 12438e2fed03SBarry Smith for (j=B->i[i]; j<B->i[i+1]; j++) { 12448e2fed03SBarry Smith if ((col = garray[B->j[j]]) > cstart) break; 12458e2fed03SBarry Smith column_indices[cnt++] = col; 12468e2fed03SBarry Smith } 12472205254eSKarl Rupp for (k=A->i[i]; k<A->i[i+1]; k++) column_indices[cnt++] = A->j[k] + cstart; 12482205254eSKarl Rupp for (; j<B->i[i+1]; j++) column_indices[cnt++] = garray[B->j[j]]; 12498e2fed03SBarry Smith } 1250e32f2f54SBarry 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); 12518e2fed03SBarry Smith 12528e2fed03SBarry Smith /* store the column indices to the file */ 125385ebf7a4SBarry Smith ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr); 1254958c9bccSBarry Smith if (!rank) { 12558e2fed03SBarry Smith MPI_Status status; 12566f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,column_indices,nz,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 12578e2fed03SBarry Smith for (i=1; i<size; i++) { 1258639ff905SBarry Smith ierr = PetscViewerFlowControlStepMaster(viewer,i,&message_count,flowcontrolcount);CHKERRQ(ierr); 1259ce94432eSBarry Smith ierr = MPI_Recv(&rnz,1,MPIU_INT,i,tag,PetscObjectComm((PetscObject)mat),&status);CHKERRQ(ierr); 1260e32f2f54SBarry Smith if (rnz > nzmax) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Internal PETSc error: nz = %D nzmax = %D",nz,nzmax); 1261ce94432eSBarry Smith ierr = MPIULong_Recv(column_indices,rnz,MPIU_INT,i,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 12626f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,column_indices,rnz,PETSC_INT,PETSC_TRUE);CHKERRQ(ierr); 12638e2fed03SBarry Smith } 1264639ff905SBarry Smith ierr = PetscViewerFlowControlEndMaster(viewer,&message_count);CHKERRQ(ierr); 12658e2fed03SBarry Smith } else { 1266639ff905SBarry Smith ierr = PetscViewerFlowControlStepWorker(viewer,rank,&message_count);CHKERRQ(ierr); 1267ce94432eSBarry Smith ierr = MPI_Send(&nz,1,MPIU_INT,0,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1268ce94432eSBarry Smith ierr = MPIULong_Send(column_indices,nz,MPIU_INT,0,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1269639ff905SBarry Smith ierr = PetscViewerFlowControlEndWorker(viewer,&message_count);CHKERRQ(ierr); 12708e2fed03SBarry Smith } 12718e2fed03SBarry Smith ierr = PetscFree(column_indices);CHKERRQ(ierr); 12728e2fed03SBarry Smith 12738e2fed03SBarry Smith /* load up the local column values */ 1274854ce69bSBarry Smith ierr = PetscMalloc1(nzmax+1,&column_values);CHKERRQ(ierr); 12758e2fed03SBarry Smith cnt = 0; 1276d0f46423SBarry Smith for (i=0; i<mat->rmap->n; i++) { 12778e2fed03SBarry Smith for (j=B->i[i]; j<B->i[i+1]; j++) { 12788e2fed03SBarry Smith if (garray[B->j[j]] > cstart) break; 12798e2fed03SBarry Smith column_values[cnt++] = B->a[j]; 12808e2fed03SBarry Smith } 12812205254eSKarl Rupp for (k=A->i[i]; k<A->i[i+1]; k++) column_values[cnt++] = A->a[k]; 12822205254eSKarl Rupp for (; j<B->i[i+1]; j++) column_values[cnt++] = B->a[j]; 12838e2fed03SBarry Smith } 1284e32f2f54SBarry 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); 12858e2fed03SBarry Smith 12868e2fed03SBarry Smith /* store the column values to the file */ 128785ebf7a4SBarry Smith ierr = PetscViewerFlowControlStart(viewer,&message_count,&flowcontrolcount);CHKERRQ(ierr); 1288958c9bccSBarry Smith if (!rank) { 12898e2fed03SBarry Smith MPI_Status status; 12906f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,column_values,nz,PETSC_SCALAR,PETSC_TRUE);CHKERRQ(ierr); 12918e2fed03SBarry Smith for (i=1; i<size; i++) { 1292639ff905SBarry Smith ierr = PetscViewerFlowControlStepMaster(viewer,i,&message_count,flowcontrolcount);CHKERRQ(ierr); 1293ce94432eSBarry Smith ierr = MPI_Recv(&rnz,1,MPIU_INT,i,tag,PetscObjectComm((PetscObject)mat),&status);CHKERRQ(ierr); 1294e32f2f54SBarry Smith if (rnz > nzmax) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"Internal PETSc error: nz = %D nzmax = %D",nz,nzmax); 1295ce94432eSBarry Smith ierr = MPIULong_Recv(column_values,rnz,MPIU_SCALAR,i,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 12966f69ff64SBarry Smith ierr = PetscBinaryWrite(fd,column_values,rnz,PETSC_SCALAR,PETSC_TRUE);CHKERRQ(ierr); 12978e2fed03SBarry Smith } 1298639ff905SBarry Smith ierr = PetscViewerFlowControlEndMaster(viewer,&message_count);CHKERRQ(ierr); 12998e2fed03SBarry Smith } else { 1300639ff905SBarry Smith ierr = PetscViewerFlowControlStepWorker(viewer,rank,&message_count);CHKERRQ(ierr); 1301ce94432eSBarry Smith ierr = MPI_Send(&nz,1,MPIU_INT,0,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1302ce94432eSBarry Smith ierr = MPIULong_Send(column_values,nz,MPIU_SCALAR,0,tag,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1303639ff905SBarry Smith ierr = PetscViewerFlowControlEndWorker(viewer,&message_count);CHKERRQ(ierr); 13048e2fed03SBarry Smith } 13058e2fed03SBarry Smith ierr = PetscFree(column_values);CHKERRQ(ierr); 1306b37d52dbSMark F. Adams 1307b37d52dbSMark F. Adams ierr = PetscViewerBinaryGetInfoPointer(viewer,&file);CHKERRQ(ierr); 130833d57670SJed Brown if (file) fprintf(file,"-matload_block_size %d\n",(int)PetscAbs(mat->rmap->bs)); 13098e2fed03SBarry Smith PetscFunctionReturn(0); 13108e2fed03SBarry Smith } 13118e2fed03SBarry Smith 13129804daf3SBarry Smith #include <petscdraw.h> 13138e2fed03SBarry Smith #undef __FUNCT__ 13144a2ae208SSatish Balay #define __FUNCT__ "MatView_MPIAIJ_ASCIIorDraworSocket" 1315dfbe8321SBarry Smith PetscErrorCode MatView_MPIAIJ_ASCIIorDraworSocket(Mat mat,PetscViewer viewer) 1316416022c9SBarry Smith { 131744a69424SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 1318dfbe8321SBarry Smith PetscErrorCode ierr; 131932dcc486SBarry Smith PetscMPIInt rank = aij->rank,size = aij->size; 1320ace3abfcSBarry Smith PetscBool isdraw,iascii,isbinary; 1321b0a32e0cSBarry Smith PetscViewer sviewer; 1322f3ef73ceSBarry Smith PetscViewerFormat format; 1323416022c9SBarry Smith 13243a40ed3dSBarry Smith PetscFunctionBegin; 1325251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 1326251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1327251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 132832077d6dSBarry Smith if (iascii) { 1329b0a32e0cSBarry Smith ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr); 1330456192e2SBarry Smith if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 13314e220ebcSLois Curfman McInnes MatInfo info; 1332ace3abfcSBarry Smith PetscBool inodes; 1333923f20ffSKris Buschelman 1334ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)mat),&rank);CHKERRQ(ierr); 1335888f2ed8SSatish Balay ierr = MatGetInfo(mat,MAT_LOCAL,&info);CHKERRQ(ierr); 13360298fd71SBarry Smith ierr = MatInodeGetInodeSizes(aij->A,NULL,(PetscInt**)&inodes,NULL);CHKERRQ(ierr); 1337c5e4d11fSDmitry Karpeev ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 1338923f20ffSKris Buschelman if (!inodes) { 133977431f27SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local rows %D nz %D nz alloced %D mem %D, not using I-node routines\n", 1340d0f46423SBarry Smith rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(PetscInt)info.memory);CHKERRQ(ierr); 13416831982aSBarry Smith } else { 134277431f27SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] Local rows %D nz %D nz alloced %D mem %D, using I-node routines\n", 1343d0f46423SBarry Smith rank,mat->rmap->n,(PetscInt)info.nz_used,(PetscInt)info.nz_allocated,(PetscInt)info.memory);CHKERRQ(ierr); 13446831982aSBarry Smith } 1345888f2ed8SSatish Balay ierr = MatGetInfo(aij->A,MAT_LOCAL,&info);CHKERRQ(ierr); 134677431f27SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] on-diagonal part: nz %D \n",rank,(PetscInt)info.nz_used);CHKERRQ(ierr); 1347888f2ed8SSatish Balay ierr = MatGetInfo(aij->B,MAT_LOCAL,&info);CHKERRQ(ierr); 134877431f27SBarry Smith ierr = PetscViewerASCIISynchronizedPrintf(viewer,"[%d] off-diagonal part: nz %D \n",rank,(PetscInt)info.nz_used);CHKERRQ(ierr); 1349b0a32e0cSBarry Smith ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 1350c5e4d11fSDmitry Karpeev ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 135107d81ca4SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"Information on VecScatter used in matrix-vector product: \n");CHKERRQ(ierr); 1352a40aa06bSLois Curfman McInnes ierr = VecScatterView(aij->Mvctx,viewer);CHKERRQ(ierr); 13533a40ed3dSBarry Smith PetscFunctionReturn(0); 1354fb9695e5SSatish Balay } else if (format == PETSC_VIEWER_ASCII_INFO) { 1355923f20ffSKris Buschelman PetscInt inodecount,inodelimit,*inodes; 1356923f20ffSKris Buschelman ierr = MatInodeGetInodeSizes(aij->A,&inodecount,&inodes,&inodelimit);CHKERRQ(ierr); 1357923f20ffSKris Buschelman if (inodes) { 1358923f20ffSKris Buschelman ierr = PetscViewerASCIIPrintf(viewer,"using I-node (on process 0) routines: found %D nodes, limit used is %D\n",inodecount,inodelimit);CHKERRQ(ierr); 1359d38fa0fbSBarry Smith } else { 1360d38fa0fbSBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"not using I-node (on process 0) routines\n");CHKERRQ(ierr); 1361d38fa0fbSBarry Smith } 13623a40ed3dSBarry Smith PetscFunctionReturn(0); 13634aedb280SBarry Smith } else if (format == PETSC_VIEWER_ASCII_FACTOR_INFO) { 13644aedb280SBarry Smith PetscFunctionReturn(0); 136508480c60SBarry Smith } 13668e2fed03SBarry Smith } else if (isbinary) { 13678e2fed03SBarry Smith if (size == 1) { 13687adad957SLisandro Dalcin ierr = PetscObjectSetName((PetscObject)aij->A,((PetscObject)mat)->name);CHKERRQ(ierr); 13698e2fed03SBarry Smith ierr = MatView(aij->A,viewer);CHKERRQ(ierr); 13708e2fed03SBarry Smith } else { 13718e2fed03SBarry Smith ierr = MatView_MPIAIJ_Binary(mat,viewer);CHKERRQ(ierr); 13728e2fed03SBarry Smith } 13738e2fed03SBarry Smith PetscFunctionReturn(0); 13740f5bd95cSBarry Smith } else if (isdraw) { 1375b0a32e0cSBarry Smith PetscDraw draw; 1376ace3abfcSBarry Smith PetscBool isnull; 1377b0a32e0cSBarry Smith ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 1378383922c3SLisandro Dalcin ierr = PetscDrawIsNull(draw,&isnull);CHKERRQ(ierr); 1379383922c3SLisandro Dalcin if (isnull) PetscFunctionReturn(0); 138019bcc07fSBarry Smith } 138119bcc07fSBarry Smith 13827da1fb6eSBarry Smith { 138395373324SBarry Smith /* assemble the entire matrix onto first processor. */ 138495373324SBarry Smith Mat A; 1385ec8511deSBarry Smith Mat_SeqAIJ *Aloc; 1386d0f46423SBarry Smith PetscInt M = mat->rmap->N,N = mat->cmap->N,m,*ai,*aj,row,*cols,i,*ct; 1387dd6ea824SBarry Smith MatScalar *a; 13882ee70a88SLois Curfman McInnes 1389ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)mat),&A);CHKERRQ(ierr); 139017699dbbSLois Curfman McInnes if (!rank) { 1391f69a0ea3SMatthew Knepley ierr = MatSetSizes(A,M,N,M,N);CHKERRQ(ierr); 13923a40ed3dSBarry Smith } else { 1393f69a0ea3SMatthew Knepley ierr = MatSetSizes(A,0,0,M,N);CHKERRQ(ierr); 139495373324SBarry Smith } 1395f204ca49SKris Buschelman /* This is just a temporary matrix, so explicitly using MATMPIAIJ is probably best */ 1396f204ca49SKris Buschelman ierr = MatSetType(A,MATMPIAIJ);CHKERRQ(ierr); 13970298fd71SBarry Smith ierr = MatMPIAIJSetPreallocation(A,0,NULL,0,NULL);CHKERRQ(ierr); 13982b82e772SSatish Balay ierr = MatSetOption(A,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); 13993bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)A);CHKERRQ(ierr); 1400416022c9SBarry Smith 140195373324SBarry Smith /* copy over the A part */ 1402ec8511deSBarry Smith Aloc = (Mat_SeqAIJ*)aij->A->data; 1403d0f46423SBarry Smith m = aij->A->rmap->n; ai = Aloc->i; aj = Aloc->j; a = Aloc->a; 1404d0f46423SBarry Smith row = mat->rmap->rstart; 14052205254eSKarl Rupp for (i=0; i<ai[m]; i++) aj[i] += mat->cmap->rstart; 140695373324SBarry Smith for (i=0; i<m; i++) { 1407416022c9SBarry Smith ierr = MatSetValues(A,1,&row,ai[i+1]-ai[i],aj,a,INSERT_VALUES);CHKERRQ(ierr); 140826fbe8dcSKarl Rupp row++; 140926fbe8dcSKarl Rupp a += ai[i+1]-ai[i]; aj += ai[i+1]-ai[i]; 141095373324SBarry Smith } 14112ee70a88SLois Curfman McInnes aj = Aloc->j; 14122205254eSKarl Rupp for (i=0; i<ai[m]; i++) aj[i] -= mat->cmap->rstart; 141395373324SBarry Smith 141495373324SBarry Smith /* copy over the B part */ 1415ec8511deSBarry Smith Aloc = (Mat_SeqAIJ*)aij->B->data; 1416d0f46423SBarry Smith m = aij->B->rmap->n; ai = Aloc->i; aj = Aloc->j; a = Aloc->a; 1417d0f46423SBarry Smith row = mat->rmap->rstart; 1418854ce69bSBarry Smith ierr = PetscMalloc1(ai[m]+1,&cols);CHKERRQ(ierr); 1419b0a32e0cSBarry Smith ct = cols; 14202205254eSKarl Rupp for (i=0; i<ai[m]; i++) cols[i] = aij->garray[aj[i]]; 142195373324SBarry Smith for (i=0; i<m; i++) { 1422416022c9SBarry Smith ierr = MatSetValues(A,1,&row,ai[i+1]-ai[i],cols,a,INSERT_VALUES);CHKERRQ(ierr); 14232205254eSKarl Rupp row++; 14242205254eSKarl Rupp a += ai[i+1]-ai[i]; cols += ai[i+1]-ai[i]; 142595373324SBarry Smith } 1426606d414cSSatish Balay ierr = PetscFree(ct);CHKERRQ(ierr); 14276d4a8577SBarry Smith ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 14286d4a8577SBarry Smith ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 142955843e3eSBarry Smith /* 143055843e3eSBarry Smith Everyone has to call to draw the matrix since the graphics waits are 1431b0a32e0cSBarry Smith synchronized across all processors that share the PetscDraw object 143255843e3eSBarry Smith */ 1433c5e4d11fSDmitry Karpeev ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 14343e219373SBarry Smith if (!rank) { 1435162ae106SBarry Smith ierr = PetscObjectSetName((PetscObject)((Mat_MPIAIJ*)(A->data))->A,((PetscObject)mat)->name);CHKERRQ(ierr); 14367da1fb6eSBarry Smith ierr = MatView_SeqAIJ(((Mat_MPIAIJ*)(A->data))->A,sviewer);CHKERRQ(ierr); 143795373324SBarry Smith } 1438c5e4d11fSDmitry Karpeev ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 1439c5e4d11fSDmitry Karpeev ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 14406bf464f9SBarry Smith ierr = MatDestroy(&A);CHKERRQ(ierr); 144195373324SBarry Smith } 14423a40ed3dSBarry Smith PetscFunctionReturn(0); 14431eb62cbbSBarry Smith } 14441eb62cbbSBarry Smith 14454a2ae208SSatish Balay #undef __FUNCT__ 14464a2ae208SSatish Balay #define __FUNCT__ "MatView_MPIAIJ" 1447dfbe8321SBarry Smith PetscErrorCode MatView_MPIAIJ(Mat mat,PetscViewer viewer) 1448416022c9SBarry Smith { 1449dfbe8321SBarry Smith PetscErrorCode ierr; 1450ace3abfcSBarry Smith PetscBool iascii,isdraw,issocket,isbinary; 1451416022c9SBarry Smith 14523a40ed3dSBarry Smith PetscFunctionBegin; 1453251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 1454251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 1455251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 1456251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSOCKET,&issocket);CHKERRQ(ierr); 145732077d6dSBarry Smith if (iascii || isdraw || isbinary || issocket) { 14587b2a1423SBarry Smith ierr = MatView_MPIAIJ_ASCIIorDraworSocket(mat,viewer);CHKERRQ(ierr); 1459416022c9SBarry Smith } 14603a40ed3dSBarry Smith PetscFunctionReturn(0); 1461416022c9SBarry Smith } 1462416022c9SBarry Smith 14634a2ae208SSatish Balay #undef __FUNCT__ 146441f059aeSBarry Smith #define __FUNCT__ "MatSOR_MPIAIJ" 146541f059aeSBarry Smith PetscErrorCode MatSOR_MPIAIJ(Mat matin,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,PetscInt its,PetscInt lits,Vec xx) 14668a729477SBarry Smith { 146744a69424SLois Curfman McInnes Mat_MPIAIJ *mat = (Mat_MPIAIJ*)matin->data; 1468dfbe8321SBarry Smith PetscErrorCode ierr; 14696987fefcSBarry Smith Vec bb1 = 0; 1470ace3abfcSBarry Smith PetscBool hasop; 14718a729477SBarry Smith 14723a40ed3dSBarry Smith PetscFunctionBegin; 1473a2b30743SBarry Smith if (flag == SOR_APPLY_UPPER) { 147441f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr); 1475a2b30743SBarry Smith PetscFunctionReturn(0); 1476a2b30743SBarry Smith } 1477a2b30743SBarry Smith 14784e980039SJed Brown if (its > 1 || ~flag & SOR_ZERO_INITIAL_GUESS || flag & SOR_EISENSTAT) { 14794e980039SJed Brown ierr = VecDuplicate(bb,&bb1);CHKERRQ(ierr); 14804e980039SJed Brown } 14814e980039SJed Brown 1482c16cb8f2SBarry Smith if ((flag & SOR_LOCAL_SYMMETRIC_SWEEP) == SOR_LOCAL_SYMMETRIC_SWEEP) { 1483da3a660dSBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 148441f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr); 14852798e883SHong Zhang its--; 1486da3a660dSBarry Smith } 14872798e883SHong Zhang 14882798e883SHong Zhang while (its--) { 1489ca9f406cSSatish Balay ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1490ca9f406cSSatish Balay ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 14912798e883SHong Zhang 1492c14dc6b6SHong Zhang /* update rhs: bb1 = bb - B*x */ 1493efb30889SBarry Smith ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr); 1494c14dc6b6SHong Zhang ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr); 14952798e883SHong Zhang 1496c14dc6b6SHong Zhang /* local sweep */ 149741f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_SYMMETRIC_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr); 14982798e883SHong Zhang } 14993a40ed3dSBarry Smith } else if (flag & SOR_LOCAL_FORWARD_SWEEP) { 1500da3a660dSBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 150141f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr); 15022798e883SHong Zhang its--; 1503da3a660dSBarry Smith } 15042798e883SHong Zhang while (its--) { 1505ca9f406cSSatish Balay ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1506ca9f406cSSatish Balay ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 15072798e883SHong Zhang 1508c14dc6b6SHong Zhang /* update rhs: bb1 = bb - B*x */ 1509efb30889SBarry Smith ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr); 1510c14dc6b6SHong Zhang ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr); 1511c14dc6b6SHong Zhang 1512c14dc6b6SHong Zhang /* local sweep */ 151341f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_FORWARD_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr); 15142798e883SHong Zhang } 15153a40ed3dSBarry Smith } else if (flag & SOR_LOCAL_BACKWARD_SWEEP) { 1516da3a660dSBarry Smith if (flag & SOR_ZERO_INITIAL_GUESS) { 151741f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb,omega,flag,fshift,lits,1,xx);CHKERRQ(ierr); 15182798e883SHong Zhang its--; 1519da3a660dSBarry Smith } 15202798e883SHong Zhang while (its--) { 1521ca9f406cSSatish Balay ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1522ca9f406cSSatish Balay ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 15232798e883SHong Zhang 1524c14dc6b6SHong Zhang /* update rhs: bb1 = bb - B*x */ 1525efb30889SBarry Smith ierr = VecScale(mat->lvec,-1.0);CHKERRQ(ierr); 1526c14dc6b6SHong Zhang ierr = (*mat->B->ops->multadd)(mat->B,mat->lvec,bb,bb1);CHKERRQ(ierr); 15272798e883SHong Zhang 1528c14dc6b6SHong Zhang /* local sweep */ 152941f059aeSBarry Smith ierr = (*mat->A->ops->sor)(mat->A,bb1,omega,SOR_BACKWARD_SWEEP,fshift,lits,1,xx);CHKERRQ(ierr); 15302798e883SHong Zhang } 1531a7420bb7SBarry Smith } else if (flag & SOR_EISENSTAT) { 1532a7420bb7SBarry Smith Vec xx1; 1533a7420bb7SBarry Smith 1534a7420bb7SBarry Smith ierr = VecDuplicate(bb,&xx1);CHKERRQ(ierr); 153541f059aeSBarry 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); 1536a7420bb7SBarry Smith 1537a7420bb7SBarry Smith ierr = VecScatterBegin(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1538a7420bb7SBarry Smith ierr = VecScatterEnd(mat->Mvctx,xx,mat->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 1539a7420bb7SBarry Smith if (!mat->diag) { 15402a7a6963SBarry Smith ierr = MatCreateVecs(matin,&mat->diag,NULL);CHKERRQ(ierr); 1541a7420bb7SBarry Smith ierr = MatGetDiagonal(matin,mat->diag);CHKERRQ(ierr); 1542a7420bb7SBarry Smith } 1543bd0c2dcbSBarry Smith ierr = MatHasOperation(matin,MATOP_MULT_DIAGONAL_BLOCK,&hasop);CHKERRQ(ierr); 1544bd0c2dcbSBarry Smith if (hasop) { 1545bd0c2dcbSBarry Smith ierr = MatMultDiagonalBlock(matin,xx,bb1);CHKERRQ(ierr); 1546bd0c2dcbSBarry Smith } else { 1547a7420bb7SBarry Smith ierr = VecPointwiseMult(bb1,mat->diag,xx);CHKERRQ(ierr); 1548bd0c2dcbSBarry Smith } 1549887ee2caSBarry Smith ierr = VecAYPX(bb1,(omega-2.0)/omega,bb);CHKERRQ(ierr); 1550887ee2caSBarry Smith 1551a7420bb7SBarry Smith ierr = MatMultAdd(mat->B,mat->lvec,bb1,bb1);CHKERRQ(ierr); 1552a7420bb7SBarry Smith 1553a7420bb7SBarry Smith /* local sweep */ 155441f059aeSBarry 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); 1555a7420bb7SBarry Smith ierr = VecAXPY(xx,1.0,xx1);CHKERRQ(ierr); 15566bf464f9SBarry Smith ierr = VecDestroy(&xx1);CHKERRQ(ierr); 1557ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)matin),PETSC_ERR_SUP,"Parallel SOR not supported"); 1558c14dc6b6SHong Zhang 15596bf464f9SBarry Smith ierr = VecDestroy(&bb1);CHKERRQ(ierr); 1560a0808db4SHong Zhang 15617b6c816cSBarry Smith matin->factorerrortype = mat->A->factorerrortype; 15623a40ed3dSBarry Smith PetscFunctionReturn(0); 15638a729477SBarry Smith } 1564a66be287SLois Curfman McInnes 15654a2ae208SSatish Balay #undef __FUNCT__ 156642e855d1Svictor #define __FUNCT__ "MatPermute_MPIAIJ" 156742e855d1Svictor PetscErrorCode MatPermute_MPIAIJ(Mat A,IS rowp,IS colp,Mat *B) 156842e855d1Svictor { 156972e6a0cfSJed Brown Mat aA,aB,Aperm; 157072e6a0cfSJed Brown const PetscInt *rwant,*cwant,*gcols,*ai,*bi,*aj,*bj; 157172e6a0cfSJed Brown PetscScalar *aa,*ba; 157272e6a0cfSJed Brown PetscInt i,j,m,n,ng,anz,bnz,*dnnz,*onnz,*tdnnz,*tonnz,*rdest,*cdest,*work,*gcdest; 157372e6a0cfSJed Brown PetscSF rowsf,sf; 15740298fd71SBarry Smith IS parcolp = NULL; 157572e6a0cfSJed Brown PetscBool done; 157642e855d1Svictor PetscErrorCode ierr; 157742e855d1Svictor 157842e855d1Svictor PetscFunctionBegin; 157972e6a0cfSJed Brown ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); 158072e6a0cfSJed Brown ierr = ISGetIndices(rowp,&rwant);CHKERRQ(ierr); 158172e6a0cfSJed Brown ierr = ISGetIndices(colp,&cwant);CHKERRQ(ierr); 1582dcca6d9dSJed Brown ierr = PetscMalloc3(PetscMax(m,n),&work,m,&rdest,n,&cdest);CHKERRQ(ierr); 158372e6a0cfSJed Brown 158472e6a0cfSJed Brown /* Invert row permutation to find out where my rows should go */ 1585ce94432eSBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)A),&rowsf);CHKERRQ(ierr); 15860298fd71SBarry Smith ierr = PetscSFSetGraphLayout(rowsf,A->rmap,A->rmap->n,NULL,PETSC_OWN_POINTER,rwant);CHKERRQ(ierr); 1587e9e74f11SJed Brown ierr = PetscSFSetFromOptions(rowsf);CHKERRQ(ierr); 158872e6a0cfSJed Brown for (i=0; i<m; i++) work[i] = A->rmap->rstart + i; 15898bfbc91cSJed Brown ierr = PetscSFReduceBegin(rowsf,MPIU_INT,work,rdest,MPIU_REPLACE);CHKERRQ(ierr); 15908bfbc91cSJed Brown ierr = PetscSFReduceEnd(rowsf,MPIU_INT,work,rdest,MPIU_REPLACE);CHKERRQ(ierr); 159172e6a0cfSJed Brown 159272e6a0cfSJed Brown /* Invert column permutation to find out where my columns should go */ 1593ce94432eSBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)A),&sf);CHKERRQ(ierr); 15940298fd71SBarry Smith ierr = PetscSFSetGraphLayout(sf,A->cmap,A->cmap->n,NULL,PETSC_OWN_POINTER,cwant);CHKERRQ(ierr); 1595e9e74f11SJed Brown ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); 159672e6a0cfSJed Brown for (i=0; i<n; i++) work[i] = A->cmap->rstart + i; 15978bfbc91cSJed Brown ierr = PetscSFReduceBegin(sf,MPIU_INT,work,cdest,MPIU_REPLACE);CHKERRQ(ierr); 15988bfbc91cSJed Brown ierr = PetscSFReduceEnd(sf,MPIU_INT,work,cdest,MPIU_REPLACE);CHKERRQ(ierr); 159972e6a0cfSJed Brown ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 160072e6a0cfSJed Brown 160172e6a0cfSJed Brown ierr = ISRestoreIndices(rowp,&rwant);CHKERRQ(ierr); 160272e6a0cfSJed Brown ierr = ISRestoreIndices(colp,&cwant);CHKERRQ(ierr); 160372e6a0cfSJed Brown ierr = MatMPIAIJGetSeqAIJ(A,&aA,&aB,&gcols);CHKERRQ(ierr); 160472e6a0cfSJed Brown 160572e6a0cfSJed Brown /* Find out where my gcols should go */ 16060298fd71SBarry Smith ierr = MatGetSize(aB,NULL,&ng);CHKERRQ(ierr); 1607785e854fSJed Brown ierr = PetscMalloc1(ng,&gcdest);CHKERRQ(ierr); 1608ce94432eSBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)A),&sf);CHKERRQ(ierr); 16090298fd71SBarry Smith ierr = PetscSFSetGraphLayout(sf,A->cmap,ng,NULL,PETSC_OWN_POINTER,gcols);CHKERRQ(ierr); 1610e9e74f11SJed Brown ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); 161172e6a0cfSJed Brown ierr = PetscSFBcastBegin(sf,MPIU_INT,cdest,gcdest);CHKERRQ(ierr); 161272e6a0cfSJed Brown ierr = PetscSFBcastEnd(sf,MPIU_INT,cdest,gcdest);CHKERRQ(ierr); 161372e6a0cfSJed Brown ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 161472e6a0cfSJed Brown 16151795a4d1SJed Brown ierr = PetscCalloc4(m,&dnnz,m,&onnz,m,&tdnnz,m,&tonnz);CHKERRQ(ierr); 161672e6a0cfSJed Brown ierr = MatGetRowIJ(aA,0,PETSC_FALSE,PETSC_FALSE,&anz,&ai,&aj,&done);CHKERRQ(ierr); 161772e6a0cfSJed Brown ierr = MatGetRowIJ(aB,0,PETSC_FALSE,PETSC_FALSE,&bnz,&bi,&bj,&done);CHKERRQ(ierr); 161872e6a0cfSJed Brown for (i=0; i<m; i++) { 161972e6a0cfSJed Brown PetscInt row = rdest[i],rowner; 162072e6a0cfSJed Brown ierr = PetscLayoutFindOwner(A->rmap,row,&rowner);CHKERRQ(ierr); 162172e6a0cfSJed Brown for (j=ai[i]; j<ai[i+1]; j++) { 162272e6a0cfSJed Brown PetscInt cowner,col = cdest[aj[j]]; 162372e6a0cfSJed Brown ierr = PetscLayoutFindOwner(A->cmap,col,&cowner);CHKERRQ(ierr); /* Could build an index for the columns to eliminate this search */ 162472e6a0cfSJed Brown if (rowner == cowner) dnnz[i]++; 162572e6a0cfSJed Brown else onnz[i]++; 162672e6a0cfSJed Brown } 162772e6a0cfSJed Brown for (j=bi[i]; j<bi[i+1]; j++) { 162872e6a0cfSJed Brown PetscInt cowner,col = gcdest[bj[j]]; 162972e6a0cfSJed Brown ierr = PetscLayoutFindOwner(A->cmap,col,&cowner);CHKERRQ(ierr); 163072e6a0cfSJed Brown if (rowner == cowner) dnnz[i]++; 163172e6a0cfSJed Brown else onnz[i]++; 163272e6a0cfSJed Brown } 163372e6a0cfSJed Brown } 163472e6a0cfSJed Brown ierr = PetscSFBcastBegin(rowsf,MPIU_INT,dnnz,tdnnz);CHKERRQ(ierr); 163572e6a0cfSJed Brown ierr = PetscSFBcastEnd(rowsf,MPIU_INT,dnnz,tdnnz);CHKERRQ(ierr); 163672e6a0cfSJed Brown ierr = PetscSFBcastBegin(rowsf,MPIU_INT,onnz,tonnz);CHKERRQ(ierr); 163772e6a0cfSJed Brown ierr = PetscSFBcastEnd(rowsf,MPIU_INT,onnz,tonnz);CHKERRQ(ierr); 163872e6a0cfSJed Brown ierr = PetscSFDestroy(&rowsf);CHKERRQ(ierr); 163972e6a0cfSJed Brown 1640ce94432eSBarry 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); 164172e6a0cfSJed Brown ierr = MatSeqAIJGetArray(aA,&aa);CHKERRQ(ierr); 164272e6a0cfSJed Brown ierr = MatSeqAIJGetArray(aB,&ba);CHKERRQ(ierr); 164372e6a0cfSJed Brown for (i=0; i<m; i++) { 164472e6a0cfSJed Brown PetscInt *acols = dnnz,*bcols = onnz; /* Repurpose now-unneeded arrays */ 1645970468b0SJed Brown PetscInt j0,rowlen; 164672e6a0cfSJed Brown rowlen = ai[i+1] - ai[i]; 1647970468b0SJed Brown for (j0=j=0; j<rowlen; j0=j) { /* rowlen could be larger than number of rows m, so sum in batches */ 1648970468b0SJed Brown for ( ; j<PetscMin(rowlen,j0+m); j++) acols[j-j0] = cdest[aj[ai[i]+j]]; 1649970468b0SJed Brown ierr = MatSetValues(Aperm,1,&rdest[i],j-j0,acols,aa+ai[i]+j0,INSERT_VALUES);CHKERRQ(ierr); 1650970468b0SJed Brown } 165172e6a0cfSJed Brown rowlen = bi[i+1] - bi[i]; 1652970468b0SJed Brown for (j0=j=0; j<rowlen; j0=j) { 1653970468b0SJed Brown for ( ; j<PetscMin(rowlen,j0+m); j++) bcols[j-j0] = gcdest[bj[bi[i]+j]]; 1654970468b0SJed Brown ierr = MatSetValues(Aperm,1,&rdest[i],j-j0,bcols,ba+bi[i]+j0,INSERT_VALUES);CHKERRQ(ierr); 1655970468b0SJed Brown } 165672e6a0cfSJed Brown } 165772e6a0cfSJed Brown ierr = MatAssemblyBegin(Aperm,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 165872e6a0cfSJed Brown ierr = MatAssemblyEnd(Aperm,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 165972e6a0cfSJed Brown ierr = MatRestoreRowIJ(aA,0,PETSC_FALSE,PETSC_FALSE,&anz,&ai,&aj,&done);CHKERRQ(ierr); 166072e6a0cfSJed Brown ierr = MatRestoreRowIJ(aB,0,PETSC_FALSE,PETSC_FALSE,&bnz,&bi,&bj,&done);CHKERRQ(ierr); 166172e6a0cfSJed Brown ierr = MatSeqAIJRestoreArray(aA,&aa);CHKERRQ(ierr); 166272e6a0cfSJed Brown ierr = MatSeqAIJRestoreArray(aB,&ba);CHKERRQ(ierr); 166372e6a0cfSJed Brown ierr = PetscFree4(dnnz,onnz,tdnnz,tonnz);CHKERRQ(ierr); 166472e6a0cfSJed Brown ierr = PetscFree3(work,rdest,cdest);CHKERRQ(ierr); 166572e6a0cfSJed Brown ierr = PetscFree(gcdest);CHKERRQ(ierr); 166672e6a0cfSJed Brown if (parcolp) {ierr = ISDestroy(&colp);CHKERRQ(ierr);} 166772e6a0cfSJed Brown *B = Aperm; 166842e855d1Svictor PetscFunctionReturn(0); 166942e855d1Svictor } 167042e855d1Svictor 167142e855d1Svictor #undef __FUNCT__ 1672c5e4d11fSDmitry Karpeev #define __FUNCT__ "MatGetGhosts_MPIAIJ" 1673c5e4d11fSDmitry Karpeev PetscErrorCode MatGetGhosts_MPIAIJ(Mat mat,PetscInt *nghosts,const PetscInt *ghosts[]) 1674c5e4d11fSDmitry Karpeev { 1675c5e4d11fSDmitry Karpeev Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 1676c5e4d11fSDmitry Karpeev PetscErrorCode ierr; 1677c5e4d11fSDmitry Karpeev 1678c5e4d11fSDmitry Karpeev PetscFunctionBegin; 1679c5e4d11fSDmitry Karpeev ierr = MatGetSize(aij->B,NULL,nghosts);CHKERRQ(ierr); 1680c5e4d11fSDmitry Karpeev if (ghosts) *ghosts = aij->garray; 1681c5e4d11fSDmitry Karpeev PetscFunctionReturn(0); 1682c5e4d11fSDmitry Karpeev } 1683c5e4d11fSDmitry Karpeev 1684c5e4d11fSDmitry Karpeev #undef __FUNCT__ 16854a2ae208SSatish Balay #define __FUNCT__ "MatGetInfo_MPIAIJ" 1686dfbe8321SBarry Smith PetscErrorCode MatGetInfo_MPIAIJ(Mat matin,MatInfoType flag,MatInfo *info) 1687a66be287SLois Curfman McInnes { 1688a66be287SLois Curfman McInnes Mat_MPIAIJ *mat = (Mat_MPIAIJ*)matin->data; 1689a66be287SLois Curfman McInnes Mat A = mat->A,B = mat->B; 1690dfbe8321SBarry Smith PetscErrorCode ierr; 1691329f5518SBarry Smith PetscReal isend[5],irecv[5]; 1692a66be287SLois Curfman McInnes 16933a40ed3dSBarry Smith PetscFunctionBegin; 16944e220ebcSLois Curfman McInnes info->block_size = 1.0; 16954e220ebcSLois Curfman McInnes ierr = MatGetInfo(A,MAT_LOCAL,info);CHKERRQ(ierr); 16962205254eSKarl Rupp 16974e220ebcSLois Curfman McInnes isend[0] = info->nz_used; isend[1] = info->nz_allocated; isend[2] = info->nz_unneeded; 16984e220ebcSLois Curfman McInnes isend[3] = info->memory; isend[4] = info->mallocs; 16992205254eSKarl Rupp 17004e220ebcSLois Curfman McInnes ierr = MatGetInfo(B,MAT_LOCAL,info);CHKERRQ(ierr); 17012205254eSKarl Rupp 17024e220ebcSLois Curfman McInnes isend[0] += info->nz_used; isend[1] += info->nz_allocated; isend[2] += info->nz_unneeded; 17034e220ebcSLois Curfman McInnes isend[3] += info->memory; isend[4] += info->mallocs; 1704a66be287SLois Curfman McInnes if (flag == MAT_LOCAL) { 17054e220ebcSLois Curfman McInnes info->nz_used = isend[0]; 17064e220ebcSLois Curfman McInnes info->nz_allocated = isend[1]; 17074e220ebcSLois Curfman McInnes info->nz_unneeded = isend[2]; 17084e220ebcSLois Curfman McInnes info->memory = isend[3]; 17094e220ebcSLois Curfman McInnes info->mallocs = isend[4]; 1710a66be287SLois Curfman McInnes } else if (flag == MAT_GLOBAL_MAX) { 1711b2566f29SBarry Smith ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)matin));CHKERRQ(ierr); 17122205254eSKarl Rupp 17134e220ebcSLois Curfman McInnes info->nz_used = irecv[0]; 17144e220ebcSLois Curfman McInnes info->nz_allocated = irecv[1]; 17154e220ebcSLois Curfman McInnes info->nz_unneeded = irecv[2]; 17164e220ebcSLois Curfman McInnes info->memory = irecv[3]; 17174e220ebcSLois Curfman McInnes info->mallocs = irecv[4]; 1718a66be287SLois Curfman McInnes } else if (flag == MAT_GLOBAL_SUM) { 1719b2566f29SBarry Smith ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)matin));CHKERRQ(ierr); 17202205254eSKarl Rupp 17214e220ebcSLois Curfman McInnes info->nz_used = irecv[0]; 17224e220ebcSLois Curfman McInnes info->nz_allocated = irecv[1]; 17234e220ebcSLois Curfman McInnes info->nz_unneeded = irecv[2]; 17244e220ebcSLois Curfman McInnes info->memory = irecv[3]; 17254e220ebcSLois Curfman McInnes info->mallocs = irecv[4]; 1726a66be287SLois Curfman McInnes } 17274e220ebcSLois Curfman McInnes info->fill_ratio_given = 0; /* no parallel LU/ILU/Cholesky */ 17284e220ebcSLois Curfman McInnes info->fill_ratio_needed = 0; 17294e220ebcSLois Curfman McInnes info->factor_mallocs = 0; 17303a40ed3dSBarry Smith PetscFunctionReturn(0); 1731a66be287SLois Curfman McInnes } 1732a66be287SLois Curfman McInnes 17334a2ae208SSatish Balay #undef __FUNCT__ 17344a2ae208SSatish Balay #define __FUNCT__ "MatSetOption_MPIAIJ" 1735ace3abfcSBarry Smith PetscErrorCode MatSetOption_MPIAIJ(Mat A,MatOption op,PetscBool flg) 1736c74985f6SBarry Smith { 1737c0bbcb79SLois Curfman McInnes Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1738dfbe8321SBarry Smith PetscErrorCode ierr; 1739c74985f6SBarry Smith 17403a40ed3dSBarry Smith PetscFunctionBegin; 174112c028f9SKris Buschelman switch (op) { 1742512a5fc5SBarry Smith case MAT_NEW_NONZERO_LOCATIONS: 174312c028f9SKris Buschelman case MAT_NEW_NONZERO_ALLOCATION_ERR: 174428b2fa4aSMatthew Knepley case MAT_UNUSED_NONZERO_LOCATION_ERR: 1745a9817697SBarry Smith case MAT_KEEP_NONZERO_PATTERN: 174612c028f9SKris Buschelman case MAT_NEW_NONZERO_LOCATION_ERR: 174712c028f9SKris Buschelman case MAT_USE_INODES: 174812c028f9SKris Buschelman case MAT_IGNORE_ZERO_ENTRIES: 1749fa1f0d2cSMatthew G Knepley MatCheckPreallocated(A,1); 17504e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 17514e0d8c25SBarry Smith ierr = MatSetOption(a->B,op,flg);CHKERRQ(ierr); 175212c028f9SKris Buschelman break; 175312c028f9SKris Buschelman case MAT_ROW_ORIENTED: 175443674050SBarry Smith MatCheckPreallocated(A,1); 17554e0d8c25SBarry Smith a->roworiented = flg; 17562205254eSKarl Rupp 17574e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 17584e0d8c25SBarry Smith ierr = MatSetOption(a->B,op,flg);CHKERRQ(ierr); 175912c028f9SKris Buschelman break; 17604e0d8c25SBarry Smith case MAT_NEW_DIAGONALS: 1761290bbb0aSBarry Smith ierr = PetscInfo1(A,"Option %s ignored\n",MatOptions[op]);CHKERRQ(ierr); 176212c028f9SKris Buschelman break; 176312c028f9SKris Buschelman case MAT_IGNORE_OFF_PROC_ENTRIES: 17645c0f0b64SBarry Smith a->donotstash = flg; 176512c028f9SKris Buschelman break; 1766ffa07934SHong Zhang case MAT_SPD: 1767ffa07934SHong Zhang A->spd_set = PETSC_TRUE; 1768ffa07934SHong Zhang A->spd = flg; 1769ffa07934SHong Zhang if (flg) { 1770ffa07934SHong Zhang A->symmetric = PETSC_TRUE; 1771ffa07934SHong Zhang A->structurally_symmetric = PETSC_TRUE; 1772ffa07934SHong Zhang A->symmetric_set = PETSC_TRUE; 1773ffa07934SHong Zhang A->structurally_symmetric_set = PETSC_TRUE; 1774ffa07934SHong Zhang } 1775ffa07934SHong Zhang break; 177677e54ba9SKris Buschelman case MAT_SYMMETRIC: 177743674050SBarry Smith MatCheckPreallocated(A,1); 17784e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 177925f421beSHong Zhang break; 178077e54ba9SKris Buschelman case MAT_STRUCTURALLY_SYMMETRIC: 178143674050SBarry Smith MatCheckPreallocated(A,1); 1782eeffb40dSHong Zhang ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 1783eeffb40dSHong Zhang break; 1784bf108f30SBarry Smith case MAT_HERMITIAN: 178543674050SBarry Smith MatCheckPreallocated(A,1); 1786eeffb40dSHong Zhang ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 1787eeffb40dSHong Zhang break; 1788bf108f30SBarry Smith case MAT_SYMMETRY_ETERNAL: 178943674050SBarry Smith MatCheckPreallocated(A,1); 17904e0d8c25SBarry Smith ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr); 179177e54ba9SKris Buschelman break; 179212c028f9SKris Buschelman default: 1793e32f2f54SBarry Smith SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"unknown option %d",op); 17943a40ed3dSBarry Smith } 17953a40ed3dSBarry Smith PetscFunctionReturn(0); 1796c74985f6SBarry Smith } 1797c74985f6SBarry Smith 17984a2ae208SSatish Balay #undef __FUNCT__ 17994a2ae208SSatish Balay #define __FUNCT__ "MatGetRow_MPIAIJ" 1800b1d57f15SBarry Smith PetscErrorCode MatGetRow_MPIAIJ(Mat matin,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 180139e00950SLois Curfman McInnes { 1802154123eaSLois Curfman McInnes Mat_MPIAIJ *mat = (Mat_MPIAIJ*)matin->data; 180387828ca2SBarry Smith PetscScalar *vworkA,*vworkB,**pvA,**pvB,*v_p; 18046849ba73SBarry Smith PetscErrorCode ierr; 1805d0f46423SBarry Smith PetscInt i,*cworkA,*cworkB,**pcA,**pcB,cstart = matin->cmap->rstart; 1806d0f46423SBarry Smith PetscInt nztot,nzA,nzB,lrow,rstart = matin->rmap->rstart,rend = matin->rmap->rend; 1807b1d57f15SBarry Smith PetscInt *cmap,*idx_p; 180839e00950SLois Curfman McInnes 18093a40ed3dSBarry Smith PetscFunctionBegin; 1810e32f2f54SBarry Smith if (mat->getrowactive) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Already active"); 18117a0afa10SBarry Smith mat->getrowactive = PETSC_TRUE; 18127a0afa10SBarry Smith 181370f0671dSBarry Smith if (!mat->rowvalues && (idx || v)) { 18147a0afa10SBarry Smith /* 18157a0afa10SBarry Smith allocate enough space to hold information from the longest row. 18167a0afa10SBarry Smith */ 18177a0afa10SBarry Smith Mat_SeqAIJ *Aa = (Mat_SeqAIJ*)mat->A->data,*Ba = (Mat_SeqAIJ*)mat->B->data; 1818b1d57f15SBarry Smith PetscInt max = 1,tmp; 1819d0f46423SBarry Smith for (i=0; i<matin->rmap->n; i++) { 18207a0afa10SBarry Smith tmp = Aa->i[i+1] - Aa->i[i] + Ba->i[i+1] - Ba->i[i]; 18212205254eSKarl Rupp if (max < tmp) max = tmp; 18227a0afa10SBarry Smith } 1823dcca6d9dSJed Brown ierr = PetscMalloc2(max,&mat->rowvalues,max,&mat->rowindices);CHKERRQ(ierr); 18247a0afa10SBarry Smith } 18257a0afa10SBarry Smith 1826e7e72b3dSBarry Smith if (row < rstart || row >= rend) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only local rows"); 1827abc0e9e4SLois Curfman McInnes lrow = row - rstart; 182839e00950SLois Curfman McInnes 1829154123eaSLois Curfman McInnes pvA = &vworkA; pcA = &cworkA; pvB = &vworkB; pcB = &cworkB; 1830154123eaSLois Curfman McInnes if (!v) {pvA = 0; pvB = 0;} 1831154123eaSLois Curfman McInnes if (!idx) {pcA = 0; if (!v) pcB = 0;} 1832f830108cSBarry Smith ierr = (*mat->A->ops->getrow)(mat->A,lrow,&nzA,pcA,pvA);CHKERRQ(ierr); 1833f830108cSBarry Smith ierr = (*mat->B->ops->getrow)(mat->B,lrow,&nzB,pcB,pvB);CHKERRQ(ierr); 1834154123eaSLois Curfman McInnes nztot = nzA + nzB; 1835154123eaSLois Curfman McInnes 183670f0671dSBarry Smith cmap = mat->garray; 1837154123eaSLois Curfman McInnes if (v || idx) { 1838154123eaSLois Curfman McInnes if (nztot) { 1839154123eaSLois Curfman McInnes /* Sort by increasing column numbers, assuming A and B already sorted */ 1840b1d57f15SBarry Smith PetscInt imark = -1; 1841154123eaSLois Curfman McInnes if (v) { 184270f0671dSBarry Smith *v = v_p = mat->rowvalues; 184339e00950SLois Curfman McInnes for (i=0; i<nzB; i++) { 184470f0671dSBarry Smith if (cmap[cworkB[i]] < cstart) v_p[i] = vworkB[i]; 1845154123eaSLois Curfman McInnes else break; 1846154123eaSLois Curfman McInnes } 1847154123eaSLois Curfman McInnes imark = i; 184870f0671dSBarry Smith for (i=0; i<nzA; i++) v_p[imark+i] = vworkA[i]; 184970f0671dSBarry Smith for (i=imark; i<nzB; i++) v_p[nzA+i] = vworkB[i]; 1850154123eaSLois Curfman McInnes } 1851154123eaSLois Curfman McInnes if (idx) { 185270f0671dSBarry Smith *idx = idx_p = mat->rowindices; 185370f0671dSBarry Smith if (imark > -1) { 185470f0671dSBarry Smith for (i=0; i<imark; i++) { 185570f0671dSBarry Smith idx_p[i] = cmap[cworkB[i]]; 185670f0671dSBarry Smith } 185770f0671dSBarry Smith } else { 1858154123eaSLois Curfman McInnes for (i=0; i<nzB; i++) { 185970f0671dSBarry Smith if (cmap[cworkB[i]] < cstart) idx_p[i] = cmap[cworkB[i]]; 1860154123eaSLois Curfman McInnes else break; 1861154123eaSLois Curfman McInnes } 1862154123eaSLois Curfman McInnes imark = i; 186370f0671dSBarry Smith } 186470f0671dSBarry Smith for (i=0; i<nzA; i++) idx_p[imark+i] = cstart + cworkA[i]; 186570f0671dSBarry Smith for (i=imark; i<nzB; i++) idx_p[nzA+i] = cmap[cworkB[i]]; 186639e00950SLois Curfman McInnes } 18673f97c4b0SBarry Smith } else { 18681ca473b0SSatish Balay if (idx) *idx = 0; 18691ca473b0SSatish Balay if (v) *v = 0; 18701ca473b0SSatish Balay } 1871154123eaSLois Curfman McInnes } 187239e00950SLois Curfman McInnes *nz = nztot; 1873f830108cSBarry Smith ierr = (*mat->A->ops->restorerow)(mat->A,lrow,&nzA,pcA,pvA);CHKERRQ(ierr); 1874f830108cSBarry Smith ierr = (*mat->B->ops->restorerow)(mat->B,lrow,&nzB,pcB,pvB);CHKERRQ(ierr); 18753a40ed3dSBarry Smith PetscFunctionReturn(0); 187639e00950SLois Curfman McInnes } 187739e00950SLois Curfman McInnes 18784a2ae208SSatish Balay #undef __FUNCT__ 18794a2ae208SSatish Balay #define __FUNCT__ "MatRestoreRow_MPIAIJ" 1880b1d57f15SBarry Smith PetscErrorCode MatRestoreRow_MPIAIJ(Mat mat,PetscInt row,PetscInt *nz,PetscInt **idx,PetscScalar **v) 188139e00950SLois Curfman McInnes { 18827a0afa10SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 18833a40ed3dSBarry Smith 18843a40ed3dSBarry Smith PetscFunctionBegin; 1885e7e72b3dSBarry Smith if (!aij->getrowactive) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"MatGetRow() must be called first"); 18867a0afa10SBarry Smith aij->getrowactive = PETSC_FALSE; 18873a40ed3dSBarry Smith PetscFunctionReturn(0); 188839e00950SLois Curfman McInnes } 188939e00950SLois Curfman McInnes 18904a2ae208SSatish Balay #undef __FUNCT__ 18914a2ae208SSatish Balay #define __FUNCT__ "MatNorm_MPIAIJ" 1892dfbe8321SBarry Smith PetscErrorCode MatNorm_MPIAIJ(Mat mat,NormType type,PetscReal *norm) 1893855ac2c5SLois Curfman McInnes { 1894855ac2c5SLois Curfman McInnes Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 1895ec8511deSBarry Smith Mat_SeqAIJ *amat = (Mat_SeqAIJ*)aij->A->data,*bmat = (Mat_SeqAIJ*)aij->B->data; 1896dfbe8321SBarry Smith PetscErrorCode ierr; 1897d0f46423SBarry Smith PetscInt i,j,cstart = mat->cmap->rstart; 1898329f5518SBarry Smith PetscReal sum = 0.0; 1899a77337e4SBarry Smith MatScalar *v; 190004ca555eSLois Curfman McInnes 19013a40ed3dSBarry Smith PetscFunctionBegin; 190217699dbbSLois Curfman McInnes if (aij->size == 1) { 190314183eadSLois Curfman McInnes ierr = MatNorm(aij->A,type,norm);CHKERRQ(ierr); 190437fa93a5SLois Curfman McInnes } else { 190504ca555eSLois Curfman McInnes if (type == NORM_FROBENIUS) { 190604ca555eSLois Curfman McInnes v = amat->a; 190704ca555eSLois Curfman McInnes for (i=0; i<amat->nz; i++) { 1908329f5518SBarry Smith sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 190904ca555eSLois Curfman McInnes } 191004ca555eSLois Curfman McInnes v = bmat->a; 191104ca555eSLois Curfman McInnes for (i=0; i<bmat->nz; i++) { 1912329f5518SBarry Smith sum += PetscRealPart(PetscConj(*v)*(*v)); v++; 191304ca555eSLois Curfman McInnes } 1914b2566f29SBarry Smith ierr = MPIU_Allreduce(&sum,norm,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 19158f1a2a5eSBarry Smith *norm = PetscSqrtReal(*norm); 191651f70360SJed Brown ierr = PetscLogFlops(2*amat->nz+2*bmat->nz);CHKERRQ(ierr); 19173a40ed3dSBarry Smith } else if (type == NORM_1) { /* max column norm */ 1918329f5518SBarry Smith PetscReal *tmp,*tmp2; 1919b1d57f15SBarry Smith PetscInt *jj,*garray = aij->garray; 1920854ce69bSBarry Smith ierr = PetscCalloc1(mat->cmap->N+1,&tmp);CHKERRQ(ierr); 1921854ce69bSBarry Smith ierr = PetscMalloc1(mat->cmap->N+1,&tmp2);CHKERRQ(ierr); 192204ca555eSLois Curfman McInnes *norm = 0.0; 192304ca555eSLois Curfman McInnes v = amat->a; jj = amat->j; 192404ca555eSLois Curfman McInnes for (j=0; j<amat->nz; j++) { 1925bfec09a0SHong Zhang tmp[cstart + *jj++] += PetscAbsScalar(*v); v++; 192604ca555eSLois Curfman McInnes } 192704ca555eSLois Curfman McInnes v = bmat->a; jj = bmat->j; 192804ca555eSLois Curfman McInnes for (j=0; j<bmat->nz; j++) { 1929bfec09a0SHong Zhang tmp[garray[*jj++]] += PetscAbsScalar(*v); v++; 193004ca555eSLois Curfman McInnes } 1931b2566f29SBarry Smith ierr = MPIU_Allreduce(tmp,tmp2,mat->cmap->N,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 1932d0f46423SBarry Smith for (j=0; j<mat->cmap->N; j++) { 193304ca555eSLois Curfman McInnes if (tmp2[j] > *norm) *norm = tmp2[j]; 193404ca555eSLois Curfman McInnes } 1935606d414cSSatish Balay ierr = PetscFree(tmp);CHKERRQ(ierr); 1936606d414cSSatish Balay ierr = PetscFree(tmp2);CHKERRQ(ierr); 193751f70360SJed Brown ierr = PetscLogFlops(PetscMax(amat->nz+bmat->nz-1,0));CHKERRQ(ierr); 19383a40ed3dSBarry Smith } else if (type == NORM_INFINITY) { /* max row norm */ 1939329f5518SBarry Smith PetscReal ntemp = 0.0; 1940d0f46423SBarry Smith for (j=0; j<aij->A->rmap->n; j++) { 1941bfec09a0SHong Zhang v = amat->a + amat->i[j]; 194204ca555eSLois Curfman McInnes sum = 0.0; 194304ca555eSLois Curfman McInnes for (i=0; i<amat->i[j+1]-amat->i[j]; i++) { 1944cddf8d76SBarry Smith sum += PetscAbsScalar(*v); v++; 194504ca555eSLois Curfman McInnes } 1946bfec09a0SHong Zhang v = bmat->a + bmat->i[j]; 194704ca555eSLois Curfman McInnes for (i=0; i<bmat->i[j+1]-bmat->i[j]; i++) { 1948cddf8d76SBarry Smith sum += PetscAbsScalar(*v); v++; 194904ca555eSLois Curfman McInnes } 1950515d9167SLois Curfman McInnes if (sum > ntemp) ntemp = sum; 195104ca555eSLois Curfman McInnes } 1952b2566f29SBarry Smith ierr = MPIU_Allreduce(&ntemp,norm,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 195351f70360SJed Brown ierr = PetscLogFlops(PetscMax(amat->nz+bmat->nz-1,0));CHKERRQ(ierr); 1954ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"No support for two norm"); 195537fa93a5SLois Curfman McInnes } 19563a40ed3dSBarry Smith PetscFunctionReturn(0); 1957855ac2c5SLois Curfman McInnes } 1958855ac2c5SLois Curfman McInnes 19594a2ae208SSatish Balay #undef __FUNCT__ 19604a2ae208SSatish Balay #define __FUNCT__ "MatTranspose_MPIAIJ" 1961fc4dec0aSBarry Smith PetscErrorCode MatTranspose_MPIAIJ(Mat A,MatReuse reuse,Mat *matout) 1962b7c46309SBarry Smith { 1963b7c46309SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 1964da668accSHong Zhang Mat_SeqAIJ *Aloc=(Mat_SeqAIJ*)a->A->data,*Bloc=(Mat_SeqAIJ*)a->B->data; 1965dfbe8321SBarry Smith PetscErrorCode ierr; 196680bcc5a1SJed Brown PetscInt M = A->rmap->N,N = A->cmap->N,ma,na,mb,nb,*ai,*aj,*bi,*bj,row,*cols,*cols_tmp,i; 1967d0f46423SBarry Smith PetscInt cstart = A->cmap->rstart,ncol; 19683a40ed3dSBarry Smith Mat B; 1969a77337e4SBarry Smith MatScalar *array; 1970b7c46309SBarry Smith 19713a40ed3dSBarry Smith PetscFunctionBegin; 1972ce94432eSBarry Smith if (reuse == MAT_REUSE_MATRIX && A == *matout && M != N) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_ARG_SIZ,"Square matrix only for in-place"); 1973da668accSHong Zhang 197480bcc5a1SJed Brown ma = A->rmap->n; na = A->cmap->n; mb = a->B->rmap->n; nb = a->B->cmap->n; 1975da668accSHong Zhang ai = Aloc->i; aj = Aloc->j; 1976da668accSHong Zhang bi = Bloc->i; bj = Bloc->j; 1977fc73b1b3SBarry Smith if (reuse == MAT_INITIAL_MATRIX || *matout == A) { 197880bcc5a1SJed Brown PetscInt *d_nnz,*g_nnz,*o_nnz; 197980bcc5a1SJed Brown PetscSFNode *oloc; 1980713c93b4SJed Brown PETSC_UNUSED PetscSF sf; 198180bcc5a1SJed Brown 1982dcca6d9dSJed Brown ierr = PetscMalloc4(na,&d_nnz,na,&o_nnz,nb,&g_nnz,nb,&oloc);CHKERRQ(ierr); 198380bcc5a1SJed Brown /* compute d_nnz for preallocation */ 198480bcc5a1SJed Brown ierr = PetscMemzero(d_nnz,na*sizeof(PetscInt));CHKERRQ(ierr); 1985da668accSHong Zhang for (i=0; i<ai[ma]; i++) { 1986da668accSHong Zhang d_nnz[aj[i]]++; 1987da668accSHong Zhang aj[i] += cstart; /* global col index to be used by MatSetValues() */ 1988d4bb536fSBarry Smith } 198980bcc5a1SJed Brown /* compute local off-diagonal contributions */ 19900beca09bSJed Brown ierr = PetscMemzero(g_nnz,nb*sizeof(PetscInt));CHKERRQ(ierr); 199180bcc5a1SJed Brown for (i=0; i<bi[ma]; i++) g_nnz[bj[i]]++; 199280bcc5a1SJed Brown /* map those to global */ 1993ce94432eSBarry Smith ierr = PetscSFCreate(PetscObjectComm((PetscObject)A),&sf);CHKERRQ(ierr); 19940298fd71SBarry Smith ierr = PetscSFSetGraphLayout(sf,A->cmap,nb,NULL,PETSC_USE_POINTER,a->garray);CHKERRQ(ierr); 1995e9e74f11SJed Brown ierr = PetscSFSetFromOptions(sf);CHKERRQ(ierr); 199680bcc5a1SJed Brown ierr = PetscMemzero(o_nnz,na*sizeof(PetscInt));CHKERRQ(ierr); 199780bcc5a1SJed Brown ierr = PetscSFReduceBegin(sf,MPIU_INT,g_nnz,o_nnz,MPIU_SUM);CHKERRQ(ierr); 199880bcc5a1SJed Brown ierr = PetscSFReduceEnd(sf,MPIU_INT,g_nnz,o_nnz,MPIU_SUM);CHKERRQ(ierr); 199980bcc5a1SJed Brown ierr = PetscSFDestroy(&sf);CHKERRQ(ierr); 2000d4bb536fSBarry Smith 2001ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 2002d0f46423SBarry Smith ierr = MatSetSizes(B,A->cmap->n,A->rmap->n,N,M);CHKERRQ(ierr); 200333d57670SJed Brown ierr = MatSetBlockSizes(B,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr); 20047adad957SLisandro Dalcin ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); 200580bcc5a1SJed Brown ierr = MatMPIAIJSetPreallocation(B,0,d_nnz,0,o_nnz);CHKERRQ(ierr); 200680bcc5a1SJed Brown ierr = PetscFree4(d_nnz,o_nnz,g_nnz,oloc);CHKERRQ(ierr); 2007fc4dec0aSBarry Smith } else { 2008fc4dec0aSBarry Smith B = *matout; 20096ffab4bbSHong Zhang ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 20102205254eSKarl Rupp for (i=0; i<ai[ma]; i++) aj[i] += cstart; /* global col index to be used by MatSetValues() */ 2011fc4dec0aSBarry Smith } 2012b7c46309SBarry Smith 2013b7c46309SBarry Smith /* copy over the A part */ 2014da668accSHong Zhang array = Aloc->a; 2015d0f46423SBarry Smith row = A->rmap->rstart; 2016da668accSHong Zhang for (i=0; i<ma; i++) { 2017da668accSHong Zhang ncol = ai[i+1]-ai[i]; 2018da668accSHong Zhang ierr = MatSetValues(B,ncol,aj,1,&row,array,INSERT_VALUES);CHKERRQ(ierr); 20192205254eSKarl Rupp row++; 20202205254eSKarl Rupp array += ncol; aj += ncol; 2021b7c46309SBarry Smith } 2022b7c46309SBarry Smith aj = Aloc->j; 2023da668accSHong Zhang for (i=0; i<ai[ma]; i++) aj[i] -= cstart; /* resume local col index */ 2024b7c46309SBarry Smith 2025b7c46309SBarry Smith /* copy over the B part */ 20261795a4d1SJed Brown ierr = PetscCalloc1(bi[mb],&cols);CHKERRQ(ierr); 2027da668accSHong Zhang array = Bloc->a; 2028d0f46423SBarry Smith row = A->rmap->rstart; 20292205254eSKarl Rupp for (i=0; i<bi[mb]; i++) cols[i] = a->garray[bj[i]]; 203061a2fbbaSHong Zhang cols_tmp = cols; 2031da668accSHong Zhang for (i=0; i<mb; i++) { 2032da668accSHong Zhang ncol = bi[i+1]-bi[i]; 203361a2fbbaSHong Zhang ierr = MatSetValues(B,ncol,cols_tmp,1,&row,array,INSERT_VALUES);CHKERRQ(ierr); 20342205254eSKarl Rupp row++; 20352205254eSKarl Rupp array += ncol; cols_tmp += ncol; 2036b7c46309SBarry Smith } 2037fc73b1b3SBarry Smith ierr = PetscFree(cols);CHKERRQ(ierr); 2038fc73b1b3SBarry Smith 20396d4a8577SBarry Smith ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 20406d4a8577SBarry Smith ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2041815cbec1SBarry Smith if (reuse == MAT_INITIAL_MATRIX || *matout != A) { 20420de55854SLois Curfman McInnes *matout = B; 20430de55854SLois Curfman McInnes } else { 204428be2f97SBarry Smith ierr = MatHeaderMerge(A,&B);CHKERRQ(ierr); 20450de55854SLois Curfman McInnes } 20463a40ed3dSBarry Smith PetscFunctionReturn(0); 2047b7c46309SBarry Smith } 2048b7c46309SBarry Smith 20494a2ae208SSatish Balay #undef __FUNCT__ 20504a2ae208SSatish Balay #define __FUNCT__ "MatDiagonalScale_MPIAIJ" 2051dfbe8321SBarry Smith PetscErrorCode MatDiagonalScale_MPIAIJ(Mat mat,Vec ll,Vec rr) 2052a008b906SSatish Balay { 20534b967eb1SSatish Balay Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 20544b967eb1SSatish Balay Mat a = aij->A,b = aij->B; 2055dfbe8321SBarry Smith PetscErrorCode ierr; 2056b1d57f15SBarry Smith PetscInt s1,s2,s3; 2057a008b906SSatish Balay 20583a40ed3dSBarry Smith PetscFunctionBegin; 20594b967eb1SSatish Balay ierr = MatGetLocalSize(mat,&s2,&s3);CHKERRQ(ierr); 20604b967eb1SSatish Balay if (rr) { 2061e1311b90SBarry Smith ierr = VecGetLocalSize(rr,&s1);CHKERRQ(ierr); 2062e32f2f54SBarry Smith if (s1!=s3) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"right vector non-conforming local size"); 20634b967eb1SSatish Balay /* Overlap communication with computation. */ 2064ca9f406cSSatish Balay ierr = VecScatterBegin(aij->Mvctx,rr,aij->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2065a008b906SSatish Balay } 20664b967eb1SSatish Balay if (ll) { 2067e1311b90SBarry Smith ierr = VecGetLocalSize(ll,&s1);CHKERRQ(ierr); 2068e32f2f54SBarry Smith if (s1!=s2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"left vector non-conforming local size"); 2069f830108cSBarry Smith ierr = (*b->ops->diagonalscale)(b,ll,0);CHKERRQ(ierr); 20704b967eb1SSatish Balay } 20714b967eb1SSatish Balay /* scale the diagonal block */ 2072f830108cSBarry Smith ierr = (*a->ops->diagonalscale)(a,ll,rr);CHKERRQ(ierr); 20734b967eb1SSatish Balay 20744b967eb1SSatish Balay if (rr) { 20754b967eb1SSatish Balay /* Do a scatter end and then right scale the off-diagonal block */ 2076ca9f406cSSatish Balay ierr = VecScatterEnd(aij->Mvctx,rr,aij->lvec,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); 2077f830108cSBarry Smith ierr = (*b->ops->diagonalscale)(b,0,aij->lvec);CHKERRQ(ierr); 20784b967eb1SSatish Balay } 20793a40ed3dSBarry Smith PetscFunctionReturn(0); 2080a008b906SSatish Balay } 2081a008b906SSatish Balay 20824a2ae208SSatish Balay #undef __FUNCT__ 20834a2ae208SSatish Balay #define __FUNCT__ "MatSetUnfactored_MPIAIJ" 2084dfbe8321SBarry Smith PetscErrorCode MatSetUnfactored_MPIAIJ(Mat A) 2085bb5a7306SBarry Smith { 2086bb5a7306SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2087dfbe8321SBarry Smith PetscErrorCode ierr; 20883a40ed3dSBarry Smith 20893a40ed3dSBarry Smith PetscFunctionBegin; 2090bb5a7306SBarry Smith ierr = MatSetUnfactored(a->A);CHKERRQ(ierr); 20913a40ed3dSBarry Smith PetscFunctionReturn(0); 2092bb5a7306SBarry Smith } 2093bb5a7306SBarry Smith 20944a2ae208SSatish Balay #undef __FUNCT__ 20954a2ae208SSatish Balay #define __FUNCT__ "MatEqual_MPIAIJ" 2096ace3abfcSBarry Smith PetscErrorCode MatEqual_MPIAIJ(Mat A,Mat B,PetscBool *flag) 2097d4bb536fSBarry Smith { 2098d4bb536fSBarry Smith Mat_MPIAIJ *matB = (Mat_MPIAIJ*)B->data,*matA = (Mat_MPIAIJ*)A->data; 2099d4bb536fSBarry Smith Mat a,b,c,d; 2100ace3abfcSBarry Smith PetscBool flg; 2101dfbe8321SBarry Smith PetscErrorCode ierr; 2102d4bb536fSBarry Smith 21033a40ed3dSBarry Smith PetscFunctionBegin; 2104d4bb536fSBarry Smith a = matA->A; b = matA->B; 2105d4bb536fSBarry Smith c = matB->A; d = matB->B; 2106d4bb536fSBarry Smith 2107d4bb536fSBarry Smith ierr = MatEqual(a,c,&flg);CHKERRQ(ierr); 2108abc0a331SBarry Smith if (flg) { 2109d4bb536fSBarry Smith ierr = MatEqual(b,d,&flg);CHKERRQ(ierr); 2110d4bb536fSBarry Smith } 2111b2566f29SBarry Smith ierr = MPIU_Allreduce(&flg,flag,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr); 21123a40ed3dSBarry Smith PetscFunctionReturn(0); 2113d4bb536fSBarry Smith } 2114d4bb536fSBarry Smith 21154a2ae208SSatish Balay #undef __FUNCT__ 21164a2ae208SSatish Balay #define __FUNCT__ "MatCopy_MPIAIJ" 2117dfbe8321SBarry Smith PetscErrorCode MatCopy_MPIAIJ(Mat A,Mat B,MatStructure str) 2118cb5b572fSBarry Smith { 2119dfbe8321SBarry Smith PetscErrorCode ierr; 2120cb5b572fSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2121cb5b572fSBarry Smith Mat_MPIAIJ *b = (Mat_MPIAIJ*)B->data; 2122cb5b572fSBarry Smith 2123cb5b572fSBarry Smith PetscFunctionBegin; 212433f4a19fSKris Buschelman /* If the two matrices don't have the same copy implementation, they aren't compatible for fast copy. */ 212533f4a19fSKris Buschelman if ((str != SAME_NONZERO_PATTERN) || (A->ops->copy != B->ops->copy)) { 2126cb5b572fSBarry Smith /* because of the column compression in the off-processor part of the matrix a->B, 2127cb5b572fSBarry Smith the number of columns in a->B and b->B may be different, hence we cannot call 2128cb5b572fSBarry Smith the MatCopy() directly on the two parts. If need be, we can provide a more 2129cb5b572fSBarry Smith efficient copy than the MatCopy_Basic() by first uncompressing the a->B matrices 2130cb5b572fSBarry Smith then copying the submatrices */ 2131cb5b572fSBarry Smith ierr = MatCopy_Basic(A,B,str);CHKERRQ(ierr); 2132cb5b572fSBarry Smith } else { 2133cb5b572fSBarry Smith ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr); 2134cb5b572fSBarry Smith ierr = MatCopy(a->B,b->B,str);CHKERRQ(ierr); 2135cb5b572fSBarry Smith } 2136cb5b572fSBarry Smith PetscFunctionReturn(0); 2137cb5b572fSBarry Smith } 2138cb5b572fSBarry Smith 21394a2ae208SSatish Balay #undef __FUNCT__ 21404994cf47SJed Brown #define __FUNCT__ "MatSetUp_MPIAIJ" 21414994cf47SJed Brown PetscErrorCode MatSetUp_MPIAIJ(Mat A) 2142273d9f13SBarry Smith { 2143dfbe8321SBarry Smith PetscErrorCode ierr; 2144273d9f13SBarry Smith 2145273d9f13SBarry Smith PetscFunctionBegin; 2146273d9f13SBarry Smith ierr = MatMPIAIJSetPreallocation(A,PETSC_DEFAULT,0,PETSC_DEFAULT,0);CHKERRQ(ierr); 2147273d9f13SBarry Smith PetscFunctionReturn(0); 2148273d9f13SBarry Smith } 2149273d9f13SBarry Smith 2150001ddc4fSHong Zhang /* 2151001ddc4fSHong Zhang Computes the number of nonzeros per row needed for preallocation when X and Y 2152001ddc4fSHong Zhang have different nonzero structure. 2153001ddc4fSHong Zhang */ 2154ac90fabeSBarry Smith #undef __FUNCT__ 2155001ddc4fSHong Zhang #define __FUNCT__ "MatAXPYGetPreallocation_MPIX_private" 2156001ddc4fSHong 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) 215795b7e79eSJed Brown { 2158001ddc4fSHong Zhang PetscInt i,j,k,nzx,nzy; 215995b7e79eSJed Brown 216095b7e79eSJed Brown PetscFunctionBegin; 216195b7e79eSJed Brown /* Set the number of nonzeros in the new matrix */ 216295b7e79eSJed Brown for (i=0; i<m; i++) { 2163001ddc4fSHong Zhang const PetscInt *xjj = xj+xi[i],*yjj = yj+yi[i]; 2164001ddc4fSHong Zhang nzx = xi[i+1] - xi[i]; 2165001ddc4fSHong Zhang nzy = yi[i+1] - yi[i]; 216695b7e79eSJed Brown nnz[i] = 0; 216795b7e79eSJed Brown for (j=0,k=0; j<nzx; j++) { /* Point in X */ 2168001ddc4fSHong Zhang for (; k<nzy && yltog[yjj[k]]<xltog[xjj[j]]; k++) nnz[i]++; /* Catch up to X */ 2169001ddc4fSHong Zhang if (k<nzy && yltog[yjj[k]]==xltog[xjj[j]]) k++; /* Skip duplicate */ 217095b7e79eSJed Brown nnz[i]++; 217195b7e79eSJed Brown } 217295b7e79eSJed Brown for (; k<nzy; k++) nnz[i]++; 217395b7e79eSJed Brown } 217495b7e79eSJed Brown PetscFunctionReturn(0); 217595b7e79eSJed Brown } 217695b7e79eSJed Brown 2177001ddc4fSHong Zhang /* This is the same as MatAXPYGetPreallocation_SeqAIJ, except that the local-to-global map is provided */ 2178001ddc4fSHong Zhang #undef __FUNCT__ 2179001ddc4fSHong Zhang #define __FUNCT__ "MatAXPYGetPreallocation_MPIAIJ" 2180001ddc4fSHong Zhang static PetscErrorCode MatAXPYGetPreallocation_MPIAIJ(Mat Y,const PetscInt *yltog,Mat X,const PetscInt *xltog,PetscInt *nnz) 2181001ddc4fSHong Zhang { 2182001ddc4fSHong Zhang PetscErrorCode ierr; 2183001ddc4fSHong Zhang PetscInt m = Y->rmap->N; 2184001ddc4fSHong Zhang Mat_SeqAIJ *x = (Mat_SeqAIJ*)X->data; 2185001ddc4fSHong Zhang Mat_SeqAIJ *y = (Mat_SeqAIJ*)Y->data; 2186001ddc4fSHong Zhang 2187001ddc4fSHong Zhang PetscFunctionBegin; 2188001ddc4fSHong Zhang ierr = MatAXPYGetPreallocation_MPIX_private(m,x->i,x->j,xltog,y->i,y->j,yltog,nnz);CHKERRQ(ierr); 2189001ddc4fSHong Zhang PetscFunctionReturn(0); 2190001ddc4fSHong Zhang } 2191001ddc4fSHong Zhang 219295b7e79eSJed Brown #undef __FUNCT__ 2193ac90fabeSBarry Smith #define __FUNCT__ "MatAXPY_MPIAIJ" 2194f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_MPIAIJ(Mat Y,PetscScalar a,Mat X,MatStructure str) 2195ac90fabeSBarry Smith { 2196dfbe8321SBarry Smith PetscErrorCode ierr; 2197ac90fabeSBarry Smith Mat_MPIAIJ *xx = (Mat_MPIAIJ*)X->data,*yy = (Mat_MPIAIJ*)Y->data; 21984ce68768SBarry Smith PetscBLASInt bnz,one=1; 2199ac90fabeSBarry Smith Mat_SeqAIJ *x,*y; 2200ac90fabeSBarry Smith 2201ac90fabeSBarry Smith PetscFunctionBegin; 2202ac90fabeSBarry Smith if (str == SAME_NONZERO_PATTERN) { 2203f4df32b1SMatthew Knepley PetscScalar alpha = a; 2204ac90fabeSBarry Smith x = (Mat_SeqAIJ*)xx->A->data; 2205c5df96a5SBarry Smith ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr); 2206ac90fabeSBarry Smith y = (Mat_SeqAIJ*)yy->A->data; 22078b83055fSJed Brown PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one)); 2208ac90fabeSBarry Smith x = (Mat_SeqAIJ*)xx->B->data; 2209ac90fabeSBarry Smith y = (Mat_SeqAIJ*)yy->B->data; 2210c5df96a5SBarry Smith ierr = PetscBLASIntCast(x->nz,&bnz);CHKERRQ(ierr); 22118b83055fSJed Brown PetscStackCallBLAS("BLASaxpy",BLASaxpy_(&bnz,&alpha,x->a,&one,y->a,&one)); 2212a3fa217bSJose E. Roman ierr = PetscObjectStateIncrease((PetscObject)Y);CHKERRQ(ierr); 2213ab784542SHong Zhang } else if (str == SUBSET_NONZERO_PATTERN) { /* nonzeros of X is a subset of Y's */ 2214ab784542SHong Zhang ierr = MatAXPY_Basic(Y,a,X,str);CHKERRQ(ierr); 2215ac90fabeSBarry Smith } else { 22169f5f6813SShri Abhyankar Mat B; 22179f5f6813SShri Abhyankar PetscInt *nnz_d,*nnz_o; 2218785e854fSJed Brown ierr = PetscMalloc1(yy->A->rmap->N,&nnz_d);CHKERRQ(ierr); 2219785e854fSJed Brown ierr = PetscMalloc1(yy->B->rmap->N,&nnz_o);CHKERRQ(ierr); 2220ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)Y),&B);CHKERRQ(ierr); 2221bc5a2726SShri Abhyankar ierr = PetscObjectSetName((PetscObject)B,((PetscObject)Y)->name);CHKERRQ(ierr); 22229f5f6813SShri Abhyankar ierr = MatSetSizes(B,Y->rmap->n,Y->cmap->n,Y->rmap->N,Y->cmap->N);CHKERRQ(ierr); 222333d57670SJed Brown ierr = MatSetBlockSizesFromMats(B,Y,Y);CHKERRQ(ierr); 22249f5f6813SShri Abhyankar ierr = MatSetType(B,MATMPIAIJ);CHKERRQ(ierr); 22259f5f6813SShri Abhyankar ierr = MatAXPYGetPreallocation_SeqAIJ(yy->A,xx->A,nnz_d);CHKERRQ(ierr); 222695b7e79eSJed Brown ierr = MatAXPYGetPreallocation_MPIAIJ(yy->B,yy->garray,xx->B,xx->garray,nnz_o);CHKERRQ(ierr); 2227ecd8bba6SJed Brown ierr = MatMPIAIJSetPreallocation(B,0,nnz_d,0,nnz_o);CHKERRQ(ierr); 22289f5f6813SShri Abhyankar ierr = MatAXPY_BasicWithPreallocation(B,Y,a,X,str);CHKERRQ(ierr); 222928be2f97SBarry Smith ierr = MatHeaderReplace(Y,&B);CHKERRQ(ierr); 22309f5f6813SShri Abhyankar ierr = PetscFree(nnz_d);CHKERRQ(ierr); 22319f5f6813SShri Abhyankar ierr = PetscFree(nnz_o);CHKERRQ(ierr); 2232ac90fabeSBarry Smith } 2233ac90fabeSBarry Smith PetscFunctionReturn(0); 2234ac90fabeSBarry Smith } 2235ac90fabeSBarry Smith 22367087cfbeSBarry Smith extern PetscErrorCode MatConjugate_SeqAIJ(Mat); 2237354c94deSBarry Smith 2238354c94deSBarry Smith #undef __FUNCT__ 2239354c94deSBarry Smith #define __FUNCT__ "MatConjugate_MPIAIJ" 22407087cfbeSBarry Smith PetscErrorCode MatConjugate_MPIAIJ(Mat mat) 2241354c94deSBarry Smith { 2242354c94deSBarry Smith #if defined(PETSC_USE_COMPLEX) 2243354c94deSBarry Smith PetscErrorCode ierr; 2244354c94deSBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 2245354c94deSBarry Smith 2246354c94deSBarry Smith PetscFunctionBegin; 2247354c94deSBarry Smith ierr = MatConjugate_SeqAIJ(aij->A);CHKERRQ(ierr); 2248354c94deSBarry Smith ierr = MatConjugate_SeqAIJ(aij->B);CHKERRQ(ierr); 2249354c94deSBarry Smith #else 2250354c94deSBarry Smith PetscFunctionBegin; 2251354c94deSBarry Smith #endif 2252354c94deSBarry Smith PetscFunctionReturn(0); 2253354c94deSBarry Smith } 2254354c94deSBarry Smith 225599cafbc1SBarry Smith #undef __FUNCT__ 225699cafbc1SBarry Smith #define __FUNCT__ "MatRealPart_MPIAIJ" 225799cafbc1SBarry Smith PetscErrorCode MatRealPart_MPIAIJ(Mat A) 225899cafbc1SBarry Smith { 225999cafbc1SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 226099cafbc1SBarry Smith PetscErrorCode ierr; 226199cafbc1SBarry Smith 226299cafbc1SBarry Smith PetscFunctionBegin; 226399cafbc1SBarry Smith ierr = MatRealPart(a->A);CHKERRQ(ierr); 226499cafbc1SBarry Smith ierr = MatRealPart(a->B);CHKERRQ(ierr); 226599cafbc1SBarry Smith PetscFunctionReturn(0); 226699cafbc1SBarry Smith } 226799cafbc1SBarry Smith 226899cafbc1SBarry Smith #undef __FUNCT__ 226999cafbc1SBarry Smith #define __FUNCT__ "MatImaginaryPart_MPIAIJ" 227099cafbc1SBarry Smith PetscErrorCode MatImaginaryPart_MPIAIJ(Mat A) 227199cafbc1SBarry Smith { 227299cafbc1SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 227399cafbc1SBarry Smith PetscErrorCode ierr; 227499cafbc1SBarry Smith 227599cafbc1SBarry Smith PetscFunctionBegin; 227699cafbc1SBarry Smith ierr = MatImaginaryPart(a->A);CHKERRQ(ierr); 227799cafbc1SBarry Smith ierr = MatImaginaryPart(a->B);CHKERRQ(ierr); 227899cafbc1SBarry Smith PetscFunctionReturn(0); 227999cafbc1SBarry Smith } 228099cafbc1SBarry Smith 228103bc72f1SMatthew Knepley #undef __FUNCT__ 2282c91732d9SHong Zhang #define __FUNCT__ "MatGetRowMaxAbs_MPIAIJ" 2283c91732d9SHong Zhang PetscErrorCode MatGetRowMaxAbs_MPIAIJ(Mat A, Vec v, PetscInt idx[]) 2284c91732d9SHong Zhang { 2285c91732d9SHong Zhang Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2286c91732d9SHong Zhang PetscErrorCode ierr; 2287c91732d9SHong Zhang PetscInt i,*idxb = 0; 2288c91732d9SHong Zhang PetscScalar *va,*vb; 2289c91732d9SHong Zhang Vec vtmp; 2290c91732d9SHong Zhang 2291c91732d9SHong Zhang PetscFunctionBegin; 2292c91732d9SHong Zhang ierr = MatGetRowMaxAbs(a->A,v,idx);CHKERRQ(ierr); 2293c91732d9SHong Zhang ierr = VecGetArray(v,&va);CHKERRQ(ierr); 2294c91732d9SHong Zhang if (idx) { 2295192daf7cSBarry Smith for (i=0; i<A->rmap->n; i++) { 2296d0f46423SBarry Smith if (PetscAbsScalar(va[i])) idx[i] += A->cmap->rstart; 2297c91732d9SHong Zhang } 2298c91732d9SHong Zhang } 2299c91732d9SHong Zhang 2300d0f46423SBarry Smith ierr = VecCreateSeq(PETSC_COMM_SELF,A->rmap->n,&vtmp);CHKERRQ(ierr); 2301c91732d9SHong Zhang if (idx) { 2302785e854fSJed Brown ierr = PetscMalloc1(A->rmap->n,&idxb);CHKERRQ(ierr); 2303c91732d9SHong Zhang } 2304c91732d9SHong Zhang ierr = MatGetRowMaxAbs(a->B,vtmp,idxb);CHKERRQ(ierr); 2305c91732d9SHong Zhang ierr = VecGetArray(vtmp,&vb);CHKERRQ(ierr); 2306c91732d9SHong Zhang 2307d0f46423SBarry Smith for (i=0; i<A->rmap->n; i++) { 2308c91732d9SHong Zhang if (PetscAbsScalar(va[i]) < PetscAbsScalar(vb[i])) { 2309c91732d9SHong Zhang va[i] = vb[i]; 2310c91732d9SHong Zhang if (idx) idx[i] = a->garray[idxb[i]]; 2311c91732d9SHong Zhang } 2312c91732d9SHong Zhang } 2313c91732d9SHong Zhang 2314c91732d9SHong Zhang ierr = VecRestoreArray(v,&va);CHKERRQ(ierr); 2315c91732d9SHong Zhang ierr = VecRestoreArray(vtmp,&vb);CHKERRQ(ierr); 2316c91732d9SHong Zhang ierr = PetscFree(idxb);CHKERRQ(ierr); 23176bf464f9SBarry Smith ierr = VecDestroy(&vtmp);CHKERRQ(ierr); 2318c91732d9SHong Zhang PetscFunctionReturn(0); 2319c91732d9SHong Zhang } 2320c91732d9SHong Zhang 2321c91732d9SHong Zhang #undef __FUNCT__ 2322c87e5d42SMatthew Knepley #define __FUNCT__ "MatGetRowMinAbs_MPIAIJ" 2323c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMinAbs_MPIAIJ(Mat A, Vec v, PetscInt idx[]) 2324c87e5d42SMatthew Knepley { 2325c87e5d42SMatthew Knepley Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 2326c87e5d42SMatthew Knepley PetscErrorCode ierr; 2327c87e5d42SMatthew Knepley PetscInt i,*idxb = 0; 2328c87e5d42SMatthew Knepley PetscScalar *va,*vb; 2329c87e5d42SMatthew Knepley Vec vtmp; 2330c87e5d42SMatthew Knepley 2331c87e5d42SMatthew Knepley PetscFunctionBegin; 2332c87e5d42SMatthew Knepley ierr = MatGetRowMinAbs(a->A,v,idx);CHKERRQ(ierr); 2333c87e5d42SMatthew Knepley ierr = VecGetArray(v,&va);CHKERRQ(ierr); 2334c87e5d42SMatthew Knepley if (idx) { 2335c87e5d42SMatthew Knepley for (i=0; i<A->cmap->n; i++) { 2336c87e5d42SMatthew Knepley if (PetscAbsScalar(va[i])) idx[i] += A->cmap->rstart; 2337c87e5d42SMatthew Knepley } 2338c87e5d42SMatthew Knepley } 2339c87e5d42SMatthew Knepley 2340c87e5d42SMatthew Knepley ierr = VecCreateSeq(PETSC_COMM_SELF,A->rmap->n,&vtmp);CHKERRQ(ierr); 2341c87e5d42SMatthew Knepley if (idx) { 2342785e854fSJed Brown ierr = PetscMalloc1(A->rmap->n,&idxb);CHKERRQ(ierr); 2343c87e5d42SMatthew Knepley } 2344c87e5d42SMatthew Knepley ierr = MatGetRowMinAbs(a->B,vtmp,idxb);CHKERRQ(ierr); 2345c87e5d42SMatthew Knepley ierr = VecGetArray(vtmp,&vb);CHKERRQ(ierr); 2346c87e5d42SMatthew Knepley 2347c87e5d42SMatthew Knepley for (i=0; i<A->rmap->n; i++) { 2348c87e5d42SMatthew Knepley if (PetscAbsScalar(va[i]) > PetscAbsScalar(vb[i])) { 2349c87e5d42SMatthew Knepley va[i] = vb[i]; 2350c87e5d42SMatthew Knepley if (idx) idx[i] = a->garray[idxb[i]]; 2351c87e5d42SMatthew Knepley } 2352c87e5d42SMatthew Knepley } 2353c87e5d42SMatthew Knepley 2354c87e5d42SMatthew Knepley ierr = VecRestoreArray(v,&va);CHKERRQ(ierr); 2355c87e5d42SMatthew Knepley ierr = VecRestoreArray(vtmp,&vb);CHKERRQ(ierr); 2356c87e5d42SMatthew Knepley ierr = PetscFree(idxb);CHKERRQ(ierr); 23576bf464f9SBarry Smith ierr = VecDestroy(&vtmp);CHKERRQ(ierr); 2358c87e5d42SMatthew Knepley PetscFunctionReturn(0); 2359c87e5d42SMatthew Knepley } 2360c87e5d42SMatthew Knepley 2361c87e5d42SMatthew Knepley #undef __FUNCT__ 236203bc72f1SMatthew Knepley #define __FUNCT__ "MatGetRowMin_MPIAIJ" 236303bc72f1SMatthew Knepley PetscErrorCode MatGetRowMin_MPIAIJ(Mat A, Vec v, PetscInt idx[]) 236403bc72f1SMatthew Knepley { 236503bc72f1SMatthew Knepley Mat_MPIAIJ *mat = (Mat_MPIAIJ*) A->data; 2366d0f46423SBarry Smith PetscInt n = A->rmap->n; 2367d0f46423SBarry Smith PetscInt cstart = A->cmap->rstart; 236803bc72f1SMatthew Knepley PetscInt *cmap = mat->garray; 236903bc72f1SMatthew Knepley PetscInt *diagIdx, *offdiagIdx; 237003bc72f1SMatthew Knepley Vec diagV, offdiagV; 237103bc72f1SMatthew Knepley PetscScalar *a, *diagA, *offdiagA; 237203bc72f1SMatthew Knepley PetscInt r; 237303bc72f1SMatthew Knepley PetscErrorCode ierr; 237403bc72f1SMatthew Knepley 237503bc72f1SMatthew Knepley PetscFunctionBegin; 2376dcca6d9dSJed Brown ierr = PetscMalloc2(n,&diagIdx,n,&offdiagIdx);CHKERRQ(ierr); 2377ce94432eSBarry Smith ierr = VecCreateSeq(PetscObjectComm((PetscObject)A), n, &diagV);CHKERRQ(ierr); 2378ce94432eSBarry Smith ierr = VecCreateSeq(PetscObjectComm((PetscObject)A), n, &offdiagV);CHKERRQ(ierr); 237903bc72f1SMatthew Knepley ierr = MatGetRowMin(mat->A, diagV, diagIdx);CHKERRQ(ierr); 238003bc72f1SMatthew Knepley ierr = MatGetRowMin(mat->B, offdiagV, offdiagIdx);CHKERRQ(ierr); 238103bc72f1SMatthew Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 238203bc72f1SMatthew Knepley ierr = VecGetArray(diagV, &diagA);CHKERRQ(ierr); 238303bc72f1SMatthew Knepley ierr = VecGetArray(offdiagV, &offdiagA);CHKERRQ(ierr); 238403bc72f1SMatthew Knepley for (r = 0; r < n; ++r) { 2385028cd4eaSSatish Balay if (PetscAbsScalar(diagA[r]) <= PetscAbsScalar(offdiagA[r])) { 238603bc72f1SMatthew Knepley a[r] = diagA[r]; 238703bc72f1SMatthew Knepley idx[r] = cstart + diagIdx[r]; 238803bc72f1SMatthew Knepley } else { 238903bc72f1SMatthew Knepley a[r] = offdiagA[r]; 239003bc72f1SMatthew Knepley idx[r] = cmap[offdiagIdx[r]]; 239103bc72f1SMatthew Knepley } 239203bc72f1SMatthew Knepley } 239303bc72f1SMatthew Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 239403bc72f1SMatthew Knepley ierr = VecRestoreArray(diagV, &diagA);CHKERRQ(ierr); 239503bc72f1SMatthew Knepley ierr = VecRestoreArray(offdiagV, &offdiagA);CHKERRQ(ierr); 23966bf464f9SBarry Smith ierr = VecDestroy(&diagV);CHKERRQ(ierr); 23976bf464f9SBarry Smith ierr = VecDestroy(&offdiagV);CHKERRQ(ierr); 239803bc72f1SMatthew Knepley ierr = PetscFree2(diagIdx, offdiagIdx);CHKERRQ(ierr); 239903bc72f1SMatthew Knepley PetscFunctionReturn(0); 240003bc72f1SMatthew Knepley } 240103bc72f1SMatthew Knepley 24025494a064SHong Zhang #undef __FUNCT__ 2403c87e5d42SMatthew Knepley #define __FUNCT__ "MatGetRowMax_MPIAIJ" 2404c87e5d42SMatthew Knepley PetscErrorCode MatGetRowMax_MPIAIJ(Mat A, Vec v, PetscInt idx[]) 2405c87e5d42SMatthew Knepley { 2406c87e5d42SMatthew Knepley Mat_MPIAIJ *mat = (Mat_MPIAIJ*) A->data; 2407c87e5d42SMatthew Knepley PetscInt n = A->rmap->n; 2408c87e5d42SMatthew Knepley PetscInt cstart = A->cmap->rstart; 2409c87e5d42SMatthew Knepley PetscInt *cmap = mat->garray; 2410c87e5d42SMatthew Knepley PetscInt *diagIdx, *offdiagIdx; 2411c87e5d42SMatthew Knepley Vec diagV, offdiagV; 2412c87e5d42SMatthew Knepley PetscScalar *a, *diagA, *offdiagA; 2413c87e5d42SMatthew Knepley PetscInt r; 2414c87e5d42SMatthew Knepley PetscErrorCode ierr; 2415c87e5d42SMatthew Knepley 2416c87e5d42SMatthew Knepley PetscFunctionBegin; 2417dcca6d9dSJed Brown ierr = PetscMalloc2(n,&diagIdx,n,&offdiagIdx);CHKERRQ(ierr); 2418d11e49fbSSatish Balay ierr = VecCreateSeq(PETSC_COMM_SELF, n, &diagV);CHKERRQ(ierr); 2419d11e49fbSSatish Balay ierr = VecCreateSeq(PETSC_COMM_SELF, n, &offdiagV);CHKERRQ(ierr); 2420c87e5d42SMatthew Knepley ierr = MatGetRowMax(mat->A, diagV, diagIdx);CHKERRQ(ierr); 2421c87e5d42SMatthew Knepley ierr = MatGetRowMax(mat->B, offdiagV, offdiagIdx);CHKERRQ(ierr); 2422c87e5d42SMatthew Knepley ierr = VecGetArray(v, &a);CHKERRQ(ierr); 2423c87e5d42SMatthew Knepley ierr = VecGetArray(diagV, &diagA);CHKERRQ(ierr); 2424c87e5d42SMatthew Knepley ierr = VecGetArray(offdiagV, &offdiagA);CHKERRQ(ierr); 2425c87e5d42SMatthew Knepley for (r = 0; r < n; ++r) { 2426c87e5d42SMatthew Knepley if (PetscAbsScalar(diagA[r]) >= PetscAbsScalar(offdiagA[r])) { 2427c87e5d42SMatthew Knepley a[r] = diagA[r]; 2428c87e5d42SMatthew Knepley idx[r] = cstart + diagIdx[r]; 2429c87e5d42SMatthew Knepley } else { 2430c87e5d42SMatthew Knepley a[r] = offdiagA[r]; 2431c87e5d42SMatthew Knepley idx[r] = cmap[offdiagIdx[r]]; 2432c87e5d42SMatthew Knepley } 2433c87e5d42SMatthew Knepley } 2434c87e5d42SMatthew Knepley ierr = VecRestoreArray(v, &a);CHKERRQ(ierr); 2435c87e5d42SMatthew Knepley ierr = VecRestoreArray(diagV, &diagA);CHKERRQ(ierr); 2436c87e5d42SMatthew Knepley ierr = VecRestoreArray(offdiagV, &offdiagA);CHKERRQ(ierr); 24376bf464f9SBarry Smith ierr = VecDestroy(&diagV);CHKERRQ(ierr); 24386bf464f9SBarry Smith ierr = VecDestroy(&offdiagV);CHKERRQ(ierr); 2439c87e5d42SMatthew Knepley ierr = PetscFree2(diagIdx, offdiagIdx);CHKERRQ(ierr); 2440c87e5d42SMatthew Knepley PetscFunctionReturn(0); 2441c87e5d42SMatthew Knepley } 2442c87e5d42SMatthew Knepley 2443c87e5d42SMatthew Knepley #undef __FUNCT__ 2444d1adec66SJed Brown #define __FUNCT__ "MatGetSeqNonzeroStructure_MPIAIJ" 2445d1adec66SJed Brown PetscErrorCode MatGetSeqNonzeroStructure_MPIAIJ(Mat mat,Mat *newmat) 24465494a064SHong Zhang { 24475494a064SHong Zhang PetscErrorCode ierr; 2448f6d58c54SBarry Smith Mat *dummy; 24495494a064SHong Zhang 24505494a064SHong Zhang PetscFunctionBegin; 2451f6d58c54SBarry Smith ierr = MatGetSubMatrix_MPIAIJ_All(mat,MAT_DO_NOT_GET_VALUES,MAT_INITIAL_MATRIX,&dummy);CHKERRQ(ierr); 2452f6d58c54SBarry Smith *newmat = *dummy; 2453f6d58c54SBarry Smith ierr = PetscFree(dummy);CHKERRQ(ierr); 24545494a064SHong Zhang PetscFunctionReturn(0); 24555494a064SHong Zhang } 24565494a064SHong Zhang 2457bbead8a2SBarry Smith #undef __FUNCT__ 2458bbead8a2SBarry Smith #define __FUNCT__ "MatInvertBlockDiagonal_MPIAIJ" 2459713ccfa9SJed Brown PetscErrorCode MatInvertBlockDiagonal_MPIAIJ(Mat A,const PetscScalar **values) 2460bbead8a2SBarry Smith { 2461bbead8a2SBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*) A->data; 2462bbead8a2SBarry Smith PetscErrorCode ierr; 2463bbead8a2SBarry Smith 2464bbead8a2SBarry Smith PetscFunctionBegin; 2465bbead8a2SBarry Smith ierr = MatInvertBlockDiagonal(a->A,values);CHKERRQ(ierr); 24667b6c816cSBarry Smith A->factorerrortype = a->A->factorerrortype; 2467bbead8a2SBarry Smith PetscFunctionReturn(0); 2468bbead8a2SBarry Smith } 2469bbead8a2SBarry Smith 247073a71a0fSBarry Smith #undef __FUNCT__ 247173a71a0fSBarry Smith #define __FUNCT__ "MatSetRandom_MPIAIJ" 247273a71a0fSBarry Smith static PetscErrorCode MatSetRandom_MPIAIJ(Mat x,PetscRandom rctx) 247373a71a0fSBarry Smith { 247473a71a0fSBarry Smith PetscErrorCode ierr; 247573a71a0fSBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)x->data; 247673a71a0fSBarry Smith 247773a71a0fSBarry Smith PetscFunctionBegin; 247873a71a0fSBarry Smith ierr = MatSetRandom(aij->A,rctx);CHKERRQ(ierr); 247973a71a0fSBarry Smith ierr = MatSetRandom(aij->B,rctx);CHKERRQ(ierr); 248073a71a0fSBarry Smith ierr = MatAssemblyBegin(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 248173a71a0fSBarry Smith ierr = MatAssemblyEnd(x,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 248273a71a0fSBarry Smith PetscFunctionReturn(0); 248373a71a0fSBarry Smith } 2484bbead8a2SBarry Smith 2485b1b1104fSBarry Smith #undef __FUNCT__ 2486b1b1104fSBarry Smith #define __FUNCT__ "MatMPIAIJSetUseScalableIncreaseOverlap_MPIAIJ" 2487b1b1104fSBarry Smith PetscErrorCode MatMPIAIJSetUseScalableIncreaseOverlap_MPIAIJ(Mat A,PetscBool sc) 2488b1b1104fSBarry Smith { 2489b1b1104fSBarry Smith PetscFunctionBegin; 2490b1b1104fSBarry Smith if (sc) A->ops->increaseoverlap = MatIncreaseOverlap_MPIAIJ_Scalable; 2491b1b1104fSBarry Smith else A->ops->increaseoverlap = MatIncreaseOverlap_MPIAIJ; 2492b1b1104fSBarry Smith PetscFunctionReturn(0); 2493b1b1104fSBarry Smith } 2494b1b1104fSBarry Smith 2495b1b1104fSBarry Smith #undef __FUNCT__ 2496b1b1104fSBarry Smith #define __FUNCT__ "MatMPIAIJSetUseScalableIncreaseOverlap" 2497b1b1104fSBarry Smith /*@ 2498b1b1104fSBarry Smith MatMPIAIJSetUseScalableIncreaseOverlap - Determine if the matrix uses a scalable algorithm to compute the overlap 2499b1b1104fSBarry Smith 2500b1b1104fSBarry Smith Collective on Mat 2501b1b1104fSBarry Smith 2502b1b1104fSBarry Smith Input Parameters: 2503b1b1104fSBarry Smith + A - the matrix 2504b1b1104fSBarry Smith - sc - PETSC_TRUE indicates use the scalable algorithm (default is not to use the scalable algorithm) 2505b1b1104fSBarry Smith 250696a0c994SBarry Smith Level: advanced 250796a0c994SBarry Smith 2508b1b1104fSBarry Smith @*/ 2509b1b1104fSBarry Smith PetscErrorCode MatMPIAIJSetUseScalableIncreaseOverlap(Mat A,PetscBool sc) 2510b1b1104fSBarry Smith { 2511b1b1104fSBarry Smith PetscErrorCode ierr; 2512b1b1104fSBarry Smith 2513b1b1104fSBarry Smith PetscFunctionBegin; 2514b1b1104fSBarry Smith ierr = PetscTryMethod(A,"MatMPIAIJSetUseScalableIncreaseOverlap_C",(Mat,PetscBool),(A,sc));CHKERRQ(ierr); 2515b1b1104fSBarry Smith PetscFunctionReturn(0); 2516b1b1104fSBarry Smith } 2517b1b1104fSBarry Smith 2518b1b1104fSBarry Smith #undef __FUNCT__ 2519b1b1104fSBarry Smith #define __FUNCT__ "MatSetFromOptions_MPIAIJ" 25204416b707SBarry Smith PetscErrorCode MatSetFromOptions_MPIAIJ(PetscOptionItems *PetscOptionsObject,Mat A) 2521b1b1104fSBarry Smith { 2522b1b1104fSBarry Smith PetscErrorCode ierr; 2523b1b1104fSBarry Smith PetscBool sc = PETSC_FALSE,flg; 2524b1b1104fSBarry Smith 2525b1b1104fSBarry Smith PetscFunctionBegin; 2526b1b1104fSBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"MPIAIJ options");CHKERRQ(ierr); 2527b1b1104fSBarry Smith ierr = PetscObjectOptionsBegin((PetscObject)A); 2528b1b1104fSBarry Smith if (A->ops->increaseoverlap == MatIncreaseOverlap_MPIAIJ_Scalable) sc = PETSC_TRUE; 2529b1b1104fSBarry Smith ierr = PetscOptionsBool("-mat_increase_overlap_scalable","Use a scalable algorithm to compute the overlap","MatIncreaseOverlap",sc,&sc,&flg);CHKERRQ(ierr); 2530b1b1104fSBarry Smith if (flg) { 2531b1b1104fSBarry Smith ierr = MatMPIAIJSetUseScalableIncreaseOverlap(A,sc);CHKERRQ(ierr); 2532b1b1104fSBarry Smith } 2533b1b1104fSBarry Smith ierr = PetscOptionsEnd();CHKERRQ(ierr); 2534b1b1104fSBarry Smith PetscFunctionReturn(0); 2535b1b1104fSBarry Smith } 2536b1b1104fSBarry Smith 2537f9185b66SBarry Smith #undef __FUNCT__ 25387d68702bSBarry Smith #define __FUNCT__ "MatShift_MPIAIJ" 25397d68702bSBarry Smith PetscErrorCode MatShift_MPIAIJ(Mat Y,PetscScalar a) 25407d68702bSBarry Smith { 25417d68702bSBarry Smith PetscErrorCode ierr; 25427d68702bSBarry Smith Mat_MPIAIJ *maij = (Mat_MPIAIJ*)Y->data; 2543c5e4d11fSDmitry Karpeev Mat_SeqAIJ *aij = (Mat_SeqAIJ*)maij->A->data; 25447d68702bSBarry Smith 25457d68702bSBarry Smith PetscFunctionBegin; 2546c5e4d11fSDmitry Karpeev if (!Y->preallocated) { 25477d68702bSBarry Smith ierr = MatMPIAIJSetPreallocation(Y,1,NULL,0,NULL);CHKERRQ(ierr); 2548c5e4d11fSDmitry Karpeev } else if (!aij->nz) { 2549b83222d8SBarry Smith PetscInt nonew = aij->nonew; 2550c5e4d11fSDmitry Karpeev ierr = MatSeqAIJSetPreallocation(maij->A,1,NULL);CHKERRQ(ierr); 2551b83222d8SBarry Smith aij->nonew = nonew; 25527d68702bSBarry Smith } 25537d68702bSBarry Smith ierr = MatShift_Basic(Y,a);CHKERRQ(ierr); 25547d68702bSBarry Smith PetscFunctionReturn(0); 25557d68702bSBarry Smith } 25567d68702bSBarry Smith 25573b49f96aSBarry Smith #undef __FUNCT__ 25583b49f96aSBarry Smith #define __FUNCT__ "MatMissingDiagonal_MPIAIJ" 25593b49f96aSBarry Smith PetscErrorCode MatMissingDiagonal_MPIAIJ(Mat A,PetscBool *missing,PetscInt *d) 25603b49f96aSBarry Smith { 25613b49f96aSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 25623b49f96aSBarry Smith PetscErrorCode ierr; 25633b49f96aSBarry Smith 25643b49f96aSBarry Smith PetscFunctionBegin; 25653b49f96aSBarry Smith if (A->rmap->n != A->cmap->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Only works for square matrices"); 25663b49f96aSBarry Smith ierr = MatMissingDiagonal(a->A,missing,d);CHKERRQ(ierr); 25673b49f96aSBarry Smith if (d) { 25683b49f96aSBarry Smith PetscInt rstart; 25693b49f96aSBarry Smith ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr); 25703b49f96aSBarry Smith *d += rstart; 25713b49f96aSBarry Smith 25723b49f96aSBarry Smith } 25733b49f96aSBarry Smith PetscFunctionReturn(0); 25743b49f96aSBarry Smith } 25753b49f96aSBarry Smith 25763b49f96aSBarry Smith 25778a729477SBarry Smith /* -------------------------------------------------------------------*/ 2578cda55fadSBarry Smith static struct _MatOps MatOps_Values = {MatSetValues_MPIAIJ, 2579cda55fadSBarry Smith MatGetRow_MPIAIJ, 2580cda55fadSBarry Smith MatRestoreRow_MPIAIJ, 2581cda55fadSBarry Smith MatMult_MPIAIJ, 258297304618SKris Buschelman /* 4*/ MatMultAdd_MPIAIJ, 25837c922b88SBarry Smith MatMultTranspose_MPIAIJ, 25847c922b88SBarry Smith MatMultTransposeAdd_MPIAIJ, 2585cda55fadSBarry Smith 0, 2586cda55fadSBarry Smith 0, 2587cda55fadSBarry Smith 0, 258897304618SKris Buschelman /*10*/ 0, 2589cda55fadSBarry Smith 0, 2590cda55fadSBarry Smith 0, 259141f059aeSBarry Smith MatSOR_MPIAIJ, 2592b7c46309SBarry Smith MatTranspose_MPIAIJ, 259397304618SKris Buschelman /*15*/ MatGetInfo_MPIAIJ, 2594cda55fadSBarry Smith MatEqual_MPIAIJ, 2595cda55fadSBarry Smith MatGetDiagonal_MPIAIJ, 2596cda55fadSBarry Smith MatDiagonalScale_MPIAIJ, 2597cda55fadSBarry Smith MatNorm_MPIAIJ, 259897304618SKris Buschelman /*20*/ MatAssemblyBegin_MPIAIJ, 2599cda55fadSBarry Smith MatAssemblyEnd_MPIAIJ, 2600cda55fadSBarry Smith MatSetOption_MPIAIJ, 2601cda55fadSBarry Smith MatZeroEntries_MPIAIJ, 2602d519adbfSMatthew Knepley /*24*/ MatZeroRows_MPIAIJ, 2603cda55fadSBarry Smith 0, 2604719d5645SBarry Smith 0, 2605cda55fadSBarry Smith 0, 2606cda55fadSBarry Smith 0, 26074994cf47SJed Brown /*29*/ MatSetUp_MPIAIJ, 2608719d5645SBarry Smith 0, 2609cda55fadSBarry Smith 0, 2610a5b7ff6bSBarry Smith MatGetDiagonalBlock_MPIAIJ, 2611cda55fadSBarry Smith 0, 2612d519adbfSMatthew Knepley /*34*/ MatDuplicate_MPIAIJ, 2613cda55fadSBarry Smith 0, 2614cda55fadSBarry Smith 0, 2615cda55fadSBarry Smith 0, 2616cda55fadSBarry Smith 0, 2617d519adbfSMatthew Knepley /*39*/ MatAXPY_MPIAIJ, 2618cda55fadSBarry Smith MatGetSubMatrices_MPIAIJ, 2619cda55fadSBarry Smith MatIncreaseOverlap_MPIAIJ, 2620cda55fadSBarry Smith MatGetValues_MPIAIJ, 2621cb5b572fSBarry Smith MatCopy_MPIAIJ, 2622d519adbfSMatthew Knepley /*44*/ MatGetRowMax_MPIAIJ, 2623cda55fadSBarry Smith MatScale_MPIAIJ, 26247d68702bSBarry Smith MatShift_MPIAIJ, 262599e65526SBarry Smith MatDiagonalSet_MPIAIJ, 2626564f14d6SBarry Smith MatZeroRowsColumns_MPIAIJ, 262773a71a0fSBarry Smith /*49*/ MatSetRandom_MPIAIJ, 2628cda55fadSBarry Smith 0, 2629cda55fadSBarry Smith 0, 2630cda55fadSBarry Smith 0, 2631cda55fadSBarry Smith 0, 263293dfae19SHong Zhang /*54*/ MatFDColoringCreate_MPIXAIJ, 2633cda55fadSBarry Smith 0, 2634cda55fadSBarry Smith MatSetUnfactored_MPIAIJ, 263572e6a0cfSJed Brown MatPermute_MPIAIJ, 2636cda55fadSBarry Smith 0, 2637d519adbfSMatthew Knepley /*59*/ MatGetSubMatrix_MPIAIJ, 2638e03a110bSBarry Smith MatDestroy_MPIAIJ, 2639e03a110bSBarry Smith MatView_MPIAIJ, 2640357abbc8SBarry Smith 0, 2641f996eeb8SHong Zhang MatMatMatMult_MPIAIJ_MPIAIJ_MPIAIJ, 2642f996eeb8SHong Zhang /*64*/ MatMatMatMultSymbolic_MPIAIJ_MPIAIJ_MPIAIJ, 2643f996eeb8SHong Zhang MatMatMatMultNumeric_MPIAIJ_MPIAIJ_MPIAIJ, 2644a2243be0SBarry Smith 0, 2645a2243be0SBarry Smith 0, 2646a2243be0SBarry Smith 0, 2647d519adbfSMatthew Knepley /*69*/ MatGetRowMaxAbs_MPIAIJ, 2648c87e5d42SMatthew Knepley MatGetRowMinAbs_MPIAIJ, 2649a2243be0SBarry Smith 0, 2650*26bda2c4Sstefano_zampini MatSetLateBlockSizes_MPIAIJ, 26512c93a97aSBarry Smith 0, 26522c93a97aSBarry Smith 0, 26533acb8795SBarry Smith /*75*/ MatFDColoringApply_AIJ, 2654b1b1104fSBarry Smith MatSetFromOptions_MPIAIJ, 265597304618SKris Buschelman 0, 265697304618SKris Buschelman 0, 2657f1f41ecbSJed Brown MatFindZeroDiagonals_MPIAIJ, 265897304618SKris Buschelman /*80*/ 0, 265997304618SKris Buschelman 0, 266097304618SKris Buschelman 0, 26615bba2384SShri Abhyankar /*83*/ MatLoad_MPIAIJ, 26626284ec50SHong Zhang 0, 26636284ec50SHong Zhang 0, 26646284ec50SHong Zhang 0, 26656284ec50SHong Zhang 0, 2666865e5f61SKris Buschelman 0, 2667d519adbfSMatthew Knepley /*89*/ MatMatMult_MPIAIJ_MPIAIJ, 266826be0446SHong Zhang MatMatMultSymbolic_MPIAIJ_MPIAIJ, 266926be0446SHong Zhang MatMatMultNumeric_MPIAIJ_MPIAIJ, 2670cf3ca8ceSHong Zhang MatPtAP_MPIAIJ_MPIAIJ, 2671cf3ca8ceSHong Zhang MatPtAPSymbolic_MPIAIJ_MPIAIJ, 2672cf3ca8ceSHong Zhang /*94*/ MatPtAPNumeric_MPIAIJ_MPIAIJ, 26737a7894deSKris Buschelman 0, 26747a7894deSKris Buschelman 0, 26757a7894deSKris Buschelman 0, 26767a7894deSKris Buschelman 0, 2677d519adbfSMatthew Knepley /*99*/ 0, 2678d2b207f1SPeter Brune 0, 2679d2b207f1SPeter Brune 0, 26802fd7e33dSBarry Smith MatConjugate_MPIAIJ, 26812fd7e33dSBarry Smith 0, 2682d519adbfSMatthew Knepley /*104*/MatSetValuesRow_MPIAIJ, 268399cafbc1SBarry Smith MatRealPart_MPIAIJ, 268469db28dcSHong Zhang MatImaginaryPart_MPIAIJ, 268569db28dcSHong Zhang 0, 268669db28dcSHong Zhang 0, 2687d519adbfSMatthew Knepley /*109*/0, 2688aae456dbSHong Zhang 0, 26895494a064SHong Zhang MatGetRowMin_MPIAIJ, 26905494a064SHong Zhang 0, 26913b49f96aSBarry Smith MatMissingDiagonal_MPIAIJ, 2692d1adec66SJed Brown /*114*/MatGetSeqNonzeroStructure_MPIAIJ, 2693bd0c2dcbSBarry Smith 0, 2694c5e4d11fSDmitry Karpeev MatGetGhosts_MPIAIJ, 2695bd0c2dcbSBarry Smith 0, 2696bd0c2dcbSBarry Smith 0, 26978fb81238SShri Abhyankar /*119*/0, 26988fb81238SShri Abhyankar 0, 26998fb81238SShri Abhyankar 0, 2700d6037b41SHong Zhang 0, 2701b9614d88SDmitry Karpeev MatGetMultiProcBlock_MPIAIJ, 2702f2c98031SJed Brown /*124*/MatFindNonzeroRows_MPIAIJ, 27030716a85fSBarry Smith MatGetColumnNorms_MPIAIJ, 2704bbead8a2SBarry Smith MatInvertBlockDiagonal_MPIAIJ, 2705b9614d88SDmitry Karpeev 0, 270653dd7562SDmitry Karpeev MatGetSubMatricesMPI_MPIAIJ, 2707187b3c17SHong Zhang /*129*/0, 2708187b3c17SHong Zhang MatTransposeMatMult_MPIAIJ_MPIAIJ, 2709187b3c17SHong Zhang MatTransposeMatMultSymbolic_MPIAIJ_MPIAIJ, 2710187b3c17SHong Zhang MatTransposeMatMultNumeric_MPIAIJ_MPIAIJ, 2711187b3c17SHong Zhang 0, 2712187b3c17SHong Zhang /*134*/0, 2713187b3c17SHong Zhang 0, 2714187b3c17SHong Zhang 0, 2715187b3c17SHong Zhang 0, 27163964eb88SJed Brown 0, 27173964eb88SJed Brown /*139*/0, 2718f9426fe0SMark Adams 0, 2719f86b9fbaSHong Zhang 0, 27209c8f2541SHong Zhang MatFDColoringSetUp_MPIXAIJ, 2721a0b6529bSBarry Smith MatFindOffBlockDiagonalEntries_MPIAIJ, 27229c8f2541SHong Zhang /*144*/MatCreateMPIMatConcatenateSeqMat_MPIAIJ 2723bd0c2dcbSBarry Smith }; 272436ce4990SBarry Smith 27252e8a6d31SBarry Smith /* ----------------------------------------------------------------------------------------*/ 27262e8a6d31SBarry Smith 27274a2ae208SSatish Balay #undef __FUNCT__ 27284a2ae208SSatish Balay #define __FUNCT__ "MatStoreValues_MPIAIJ" 27297087cfbeSBarry Smith PetscErrorCode MatStoreValues_MPIAIJ(Mat mat) 27302e8a6d31SBarry Smith { 27312e8a6d31SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 2732dfbe8321SBarry Smith PetscErrorCode ierr; 27332e8a6d31SBarry Smith 27342e8a6d31SBarry Smith PetscFunctionBegin; 27352e8a6d31SBarry Smith ierr = MatStoreValues(aij->A);CHKERRQ(ierr); 27362e8a6d31SBarry Smith ierr = MatStoreValues(aij->B);CHKERRQ(ierr); 27372e8a6d31SBarry Smith PetscFunctionReturn(0); 27382e8a6d31SBarry Smith } 27392e8a6d31SBarry Smith 27404a2ae208SSatish Balay #undef __FUNCT__ 27414a2ae208SSatish Balay #define __FUNCT__ "MatRetrieveValues_MPIAIJ" 27427087cfbeSBarry Smith PetscErrorCode MatRetrieveValues_MPIAIJ(Mat mat) 27432e8a6d31SBarry Smith { 27442e8a6d31SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 2745dfbe8321SBarry Smith PetscErrorCode ierr; 27462e8a6d31SBarry Smith 27472e8a6d31SBarry Smith PetscFunctionBegin; 27482e8a6d31SBarry Smith ierr = MatRetrieveValues(aij->A);CHKERRQ(ierr); 27492e8a6d31SBarry Smith ierr = MatRetrieveValues(aij->B);CHKERRQ(ierr); 27502e8a6d31SBarry Smith PetscFunctionReturn(0); 27512e8a6d31SBarry Smith } 27528a729477SBarry Smith 27534a2ae208SSatish Balay #undef __FUNCT__ 2754a23d5eceSKris Buschelman #define __FUNCT__ "MatMPIAIJSetPreallocation_MPIAIJ" 27557087cfbeSBarry Smith PetscErrorCode MatMPIAIJSetPreallocation_MPIAIJ(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 2756a23d5eceSKris Buschelman { 2757a23d5eceSKris Buschelman Mat_MPIAIJ *b; 2758dfbe8321SBarry Smith PetscErrorCode ierr; 2759a23d5eceSKris Buschelman 2760a23d5eceSKris Buschelman PetscFunctionBegin; 276126283091SBarry Smith ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 276226283091SBarry Smith ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 2763a23d5eceSKris Buschelman b = (Mat_MPIAIJ*)B->data; 2764899cda47SBarry Smith 2765526dfc15SBarry Smith if (!B->preallocated) { 2766899cda47SBarry Smith /* Explicitly create 2 MATSEQAIJ matrices. */ 2767899cda47SBarry Smith ierr = MatCreate(PETSC_COMM_SELF,&b->A);CHKERRQ(ierr); 2768d0f46423SBarry Smith ierr = MatSetSizes(b->A,B->rmap->n,B->cmap->n,B->rmap->n,B->cmap->n);CHKERRQ(ierr); 276933d57670SJed Brown ierr = MatSetBlockSizesFromMats(b->A,B,B);CHKERRQ(ierr); 2770899cda47SBarry Smith ierr = MatSetType(b->A,MATSEQAIJ);CHKERRQ(ierr); 27713bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)B,(PetscObject)b->A);CHKERRQ(ierr); 2772899cda47SBarry Smith ierr = MatCreate(PETSC_COMM_SELF,&b->B);CHKERRQ(ierr); 2773d0f46423SBarry Smith ierr = MatSetSizes(b->B,B->rmap->n,B->cmap->N,B->rmap->n,B->cmap->N);CHKERRQ(ierr); 277433d57670SJed Brown ierr = MatSetBlockSizesFromMats(b->B,B,B);CHKERRQ(ierr); 2775899cda47SBarry Smith ierr = MatSetType(b->B,MATSEQAIJ);CHKERRQ(ierr); 27763bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)B,(PetscObject)b->B);CHKERRQ(ierr); 2777526dfc15SBarry Smith } 2778899cda47SBarry Smith 2779c60e587dSKris Buschelman ierr = MatSeqAIJSetPreallocation(b->A,d_nz,d_nnz);CHKERRQ(ierr); 2780c60e587dSKris Buschelman ierr = MatSeqAIJSetPreallocation(b->B,o_nz,o_nnz);CHKERRQ(ierr); 2781526dfc15SBarry Smith B->preallocated = PETSC_TRUE; 2782a23d5eceSKris Buschelman PetscFunctionReturn(0); 2783a23d5eceSKris Buschelman } 2784a23d5eceSKris Buschelman 27854a2ae208SSatish Balay #undef __FUNCT__ 27864a2ae208SSatish Balay #define __FUNCT__ "MatDuplicate_MPIAIJ" 2787dfbe8321SBarry Smith PetscErrorCode MatDuplicate_MPIAIJ(Mat matin,MatDuplicateOption cpvalues,Mat *newmat) 2788d6dfbf8fSBarry Smith { 2789d6dfbf8fSBarry Smith Mat mat; 2790416022c9SBarry Smith Mat_MPIAIJ *a,*oldmat = (Mat_MPIAIJ*)matin->data; 2791dfbe8321SBarry Smith PetscErrorCode ierr; 2792d6dfbf8fSBarry Smith 27933a40ed3dSBarry Smith PetscFunctionBegin; 2794416022c9SBarry Smith *newmat = 0; 2795ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)matin),&mat);CHKERRQ(ierr); 2796d0f46423SBarry Smith ierr = MatSetSizes(mat,matin->rmap->n,matin->cmap->n,matin->rmap->N,matin->cmap->N);CHKERRQ(ierr); 279733d57670SJed Brown ierr = MatSetBlockSizesFromMats(mat,matin,matin);CHKERRQ(ierr); 27987adad957SLisandro Dalcin ierr = MatSetType(mat,((PetscObject)matin)->type_name);CHKERRQ(ierr); 27991d5dac46SHong Zhang ierr = PetscMemcpy(mat->ops,matin->ops,sizeof(struct _MatOps));CHKERRQ(ierr); 2800273d9f13SBarry Smith a = (Mat_MPIAIJ*)mat->data; 2801e1b6402fSHong Zhang 2802d5f3da31SBarry Smith mat->factortype = matin->factortype; 2803c456f294SBarry Smith mat->assembled = PETSC_TRUE; 2804e7641de0SSatish Balay mat->insertmode = NOT_SET_VALUES; 2805273d9f13SBarry Smith mat->preallocated = PETSC_TRUE; 2806d6dfbf8fSBarry Smith 280717699dbbSLois Curfman McInnes a->size = oldmat->size; 280817699dbbSLois Curfman McInnes a->rank = oldmat->rank; 2809e7641de0SSatish Balay a->donotstash = oldmat->donotstash; 2810e7641de0SSatish Balay a->roworiented = oldmat->roworiented; 2811e7641de0SSatish Balay a->rowindices = 0; 2812bcd2baecSBarry Smith a->rowvalues = 0; 2813bcd2baecSBarry Smith a->getrowactive = PETSC_FALSE; 2814d6dfbf8fSBarry Smith 28151e1e43feSBarry Smith ierr = PetscLayoutReference(matin->rmap,&mat->rmap);CHKERRQ(ierr); 28161e1e43feSBarry Smith ierr = PetscLayoutReference(matin->cmap,&mat->cmap);CHKERRQ(ierr); 2817899cda47SBarry Smith 28182ee70a88SLois Curfman McInnes if (oldmat->colmap) { 2819aa482453SBarry Smith #if defined(PETSC_USE_CTABLE) 28200f5bd95cSBarry Smith ierr = PetscTableCreateCopy(oldmat->colmap,&a->colmap);CHKERRQ(ierr); 2821b1fc9764SSatish Balay #else 2822854ce69bSBarry Smith ierr = PetscMalloc1(mat->cmap->N,&a->colmap);CHKERRQ(ierr); 28233bb1ff40SBarry Smith ierr = PetscLogObjectMemory((PetscObject)mat,(mat->cmap->N)*sizeof(PetscInt));CHKERRQ(ierr); 2824d0f46423SBarry Smith ierr = PetscMemcpy(a->colmap,oldmat->colmap,(mat->cmap->N)*sizeof(PetscInt));CHKERRQ(ierr); 2825b1fc9764SSatish Balay #endif 2826416022c9SBarry Smith } else a->colmap = 0; 28273f41c07dSBarry Smith if (oldmat->garray) { 2828b1d57f15SBarry Smith PetscInt len; 2829d0f46423SBarry Smith len = oldmat->B->cmap->n; 2830854ce69bSBarry Smith ierr = PetscMalloc1(len+1,&a->garray);CHKERRQ(ierr); 28313bb1ff40SBarry Smith ierr = PetscLogObjectMemory((PetscObject)mat,len*sizeof(PetscInt));CHKERRQ(ierr); 2832b1d57f15SBarry Smith if (len) { ierr = PetscMemcpy(a->garray,oldmat->garray,len*sizeof(PetscInt));CHKERRQ(ierr); } 2833416022c9SBarry Smith } else a->garray = 0; 2834d6dfbf8fSBarry Smith 2835416022c9SBarry Smith ierr = VecDuplicate(oldmat->lvec,&a->lvec);CHKERRQ(ierr); 28363bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->lvec);CHKERRQ(ierr); 2837a56f8943SBarry Smith ierr = VecScatterCopy(oldmat->Mvctx,&a->Mvctx);CHKERRQ(ierr); 28383bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->Mvctx);CHKERRQ(ierr); 28392e8a6d31SBarry Smith ierr = MatDuplicate(oldmat->A,cpvalues,&a->A);CHKERRQ(ierr); 28403bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->A);CHKERRQ(ierr); 28412e8a6d31SBarry Smith ierr = MatDuplicate(oldmat->B,cpvalues,&a->B);CHKERRQ(ierr); 28423bb1ff40SBarry Smith ierr = PetscLogObjectParent((PetscObject)mat,(PetscObject)a->B);CHKERRQ(ierr); 2843140e18c1SBarry Smith ierr = PetscFunctionListDuplicate(((PetscObject)matin)->qlist,&((PetscObject)mat)->qlist);CHKERRQ(ierr); 28448a729477SBarry Smith *newmat = mat; 28453a40ed3dSBarry Smith PetscFunctionReturn(0); 28468a729477SBarry Smith } 2847416022c9SBarry Smith 28481a4ee126SBarry Smith 28491a4ee126SBarry Smith 28504a2ae208SSatish Balay #undef __FUNCT__ 28515bba2384SShri Abhyankar #define __FUNCT__ "MatLoad_MPIAIJ" 2852112444f4SShri Abhyankar PetscErrorCode MatLoad_MPIAIJ(Mat newMat, PetscViewer viewer) 28538fb81238SShri Abhyankar { 28548fb81238SShri Abhyankar PetscScalar *vals,*svals; 2855ce94432eSBarry Smith MPI_Comm comm; 28568fb81238SShri Abhyankar PetscErrorCode ierr; 28571a4ee126SBarry Smith PetscMPIInt rank,size,tag = ((PetscObject)viewer)->tag; 2858461878b2SBarry Smith PetscInt i,nz,j,rstart,rend,mmax,maxnz = 0; 28598fb81238SShri Abhyankar PetscInt header[4],*rowlengths = 0,M,N,m,*cols; 28600298fd71SBarry Smith PetscInt *ourlens = NULL,*procsnz = NULL,*offlens = NULL,jj,*mycols,*smycols; 2861461878b2SBarry Smith PetscInt cend,cstart,n,*rowners; 28628fb81238SShri Abhyankar int fd; 28633059b6faSBarry Smith PetscInt bs = newMat->rmap->bs; 28648fb81238SShri Abhyankar 28658fb81238SShri Abhyankar PetscFunctionBegin; 2866c98fd787SBarry Smith /* force binary viewer to load .info file if it has not yet done so */ 2867c98fd787SBarry Smith ierr = PetscViewerSetUp(viewer);CHKERRQ(ierr); 2868ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)viewer,&comm);CHKERRQ(ierr); 28698fb81238SShri Abhyankar ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 28708fb81238SShri Abhyankar ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 28718fb81238SShri Abhyankar ierr = PetscViewerBinaryGetDescriptor(viewer,&fd);CHKERRQ(ierr); 28725872f025SBarry Smith if (!rank) { 28738fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,(char*)header,4,PETSC_INT);CHKERRQ(ierr); 28748fb81238SShri Abhyankar if (header[0] != MAT_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED,"not matrix object"); 28755f4d30c4SBarry Smith if (header[3] < 0) SETERRQ(PetscObjectComm((PetscObject)newMat),PETSC_ERR_FILE_UNEXPECTED,"Matrix stored in special format on disk,cannot load as MATMPIAIJ"); 28768fb81238SShri Abhyankar } 28778fb81238SShri Abhyankar 28785f4d30c4SBarry Smith ierr = PetscOptionsBegin(comm,NULL,"Options for loading MATMPIAIJ matrix","Mat");CHKERRQ(ierr); 28790298fd71SBarry Smith ierr = PetscOptionsInt("-matload_block_size","Set the blocksize used to store the matrix","MatLoad",bs,&bs,NULL);CHKERRQ(ierr); 288008ea439dSMark F. Adams ierr = PetscOptionsEnd();CHKERRQ(ierr); 28813059b6faSBarry Smith if (bs < 0) bs = 1; 288208ea439dSMark F. Adams 28838fb81238SShri Abhyankar ierr = MPI_Bcast(header+1,3,MPIU_INT,0,comm);CHKERRQ(ierr); 28848fb81238SShri Abhyankar M = header[1]; N = header[2]; 28858fb81238SShri Abhyankar 28868fb81238SShri Abhyankar /* If global sizes are set, check if they are consistent with that given in the file */ 2887461878b2SBarry 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); 2888461878b2SBarry 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); 28898fb81238SShri Abhyankar 289008ea439dSMark F. Adams /* determine ownership of all (block) rows */ 289108ea439dSMark F. Adams if (M%bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FILE_UNEXPECTED, "Inconsistent # of rows (%d) and block size (%d)",M,bs); 289208ea439dSMark F. Adams if (newMat->rmap->n < 0) m = bs*((M/bs)/size + (((M/bs) % size) > rank)); /* PETSC_DECIDE */ 28934683f7a4SShri Abhyankar else m = newMat->rmap->n; /* Set by user */ 28948fb81238SShri Abhyankar 2895854ce69bSBarry Smith ierr = PetscMalloc1(size+1,&rowners);CHKERRQ(ierr); 28968fb81238SShri Abhyankar ierr = MPI_Allgather(&m,1,MPIU_INT,rowners+1,1,MPIU_INT,comm);CHKERRQ(ierr); 28978fb81238SShri Abhyankar 28988fb81238SShri Abhyankar /* First process needs enough room for process with most rows */ 28998fb81238SShri Abhyankar if (!rank) { 29008fb81238SShri Abhyankar mmax = rowners[1]; 29015c4ea359SMatthew G Knepley for (i=2; i<=size; i++) { 29028fb81238SShri Abhyankar mmax = PetscMax(mmax, rowners[i]); 29038fb81238SShri Abhyankar } 29043964eb88SJed Brown } else mmax = -1; /* unused, but compilers complain */ 29058fb81238SShri Abhyankar 29068fb81238SShri Abhyankar rowners[0] = 0; 29078fb81238SShri Abhyankar for (i=2; i<=size; i++) { 29088fb81238SShri Abhyankar rowners[i] += rowners[i-1]; 29098fb81238SShri Abhyankar } 29108fb81238SShri Abhyankar rstart = rowners[rank]; 29118fb81238SShri Abhyankar rend = rowners[rank+1]; 29128fb81238SShri Abhyankar 29138fb81238SShri Abhyankar /* distribute row lengths to all processors */ 2914dcca6d9dSJed Brown ierr = PetscMalloc2(m,&ourlens,m,&offlens);CHKERRQ(ierr); 29158fb81238SShri Abhyankar if (!rank) { 29168fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,ourlens,m,PETSC_INT);CHKERRQ(ierr); 2917785e854fSJed Brown ierr = PetscMalloc1(mmax,&rowlengths);CHKERRQ(ierr); 29181795a4d1SJed Brown ierr = PetscCalloc1(size,&procsnz);CHKERRQ(ierr); 29198fb81238SShri Abhyankar for (j=0; j<m; j++) { 29208fb81238SShri Abhyankar procsnz[0] += ourlens[j]; 29218fb81238SShri Abhyankar } 29228fb81238SShri Abhyankar for (i=1; i<size; i++) { 29238fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,rowlengths,rowners[i+1]-rowners[i],PETSC_INT);CHKERRQ(ierr); 29248fb81238SShri Abhyankar /* calculate the number of nonzeros on each processor */ 29258fb81238SShri Abhyankar for (j=0; j<rowners[i+1]-rowners[i]; j++) { 29268fb81238SShri Abhyankar procsnz[i] += rowlengths[j]; 29278fb81238SShri Abhyankar } 2928a25532f0SBarry Smith ierr = MPIULong_Send(rowlengths,rowners[i+1]-rowners[i],MPIU_INT,i,tag,comm);CHKERRQ(ierr); 29298fb81238SShri Abhyankar } 29308fb81238SShri Abhyankar ierr = PetscFree(rowlengths);CHKERRQ(ierr); 29318fb81238SShri Abhyankar } else { 2932a25532f0SBarry Smith ierr = MPIULong_Recv(ourlens,m,MPIU_INT,0,tag,comm);CHKERRQ(ierr); 29338fb81238SShri Abhyankar } 29348fb81238SShri Abhyankar 29358fb81238SShri Abhyankar if (!rank) { 29368fb81238SShri Abhyankar /* determine max buffer needed and allocate it */ 29378fb81238SShri Abhyankar maxnz = 0; 29388fb81238SShri Abhyankar for (i=0; i<size; i++) { 29398fb81238SShri Abhyankar maxnz = PetscMax(maxnz,procsnz[i]); 29408fb81238SShri Abhyankar } 2941785e854fSJed Brown ierr = PetscMalloc1(maxnz,&cols);CHKERRQ(ierr); 29428fb81238SShri Abhyankar 29438fb81238SShri Abhyankar /* read in my part of the matrix column indices */ 29448fb81238SShri Abhyankar nz = procsnz[0]; 2945785e854fSJed Brown ierr = PetscMalloc1(nz,&mycols);CHKERRQ(ierr); 29468fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,mycols,nz,PETSC_INT);CHKERRQ(ierr); 29478fb81238SShri Abhyankar 29488fb81238SShri Abhyankar /* read in every one elses and ship off */ 29498fb81238SShri Abhyankar for (i=1; i<size; i++) { 29508fb81238SShri Abhyankar nz = procsnz[i]; 29518fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,cols,nz,PETSC_INT);CHKERRQ(ierr); 2952a25532f0SBarry Smith ierr = MPIULong_Send(cols,nz,MPIU_INT,i,tag,comm);CHKERRQ(ierr); 29538fb81238SShri Abhyankar } 29548fb81238SShri Abhyankar ierr = PetscFree(cols);CHKERRQ(ierr); 29558fb81238SShri Abhyankar } else { 29568fb81238SShri Abhyankar /* determine buffer space needed for message */ 29578fb81238SShri Abhyankar nz = 0; 29588fb81238SShri Abhyankar for (i=0; i<m; i++) { 29598fb81238SShri Abhyankar nz += ourlens[i]; 29608fb81238SShri Abhyankar } 2961785e854fSJed Brown ierr = PetscMalloc1(nz,&mycols);CHKERRQ(ierr); 29628fb81238SShri Abhyankar 29638fb81238SShri Abhyankar /* receive message of column indices*/ 2964a25532f0SBarry Smith ierr = MPIULong_Recv(mycols,nz,MPIU_INT,0,tag,comm);CHKERRQ(ierr); 29658fb81238SShri Abhyankar } 29668fb81238SShri Abhyankar 29678fb81238SShri Abhyankar /* determine column ownership if matrix is not square */ 29688fb81238SShri Abhyankar if (N != M) { 29698fb81238SShri Abhyankar if (newMat->cmap->n < 0) n = N/size + ((N % size) > rank); 29708fb81238SShri Abhyankar else n = newMat->cmap->n; 29718fb81238SShri Abhyankar ierr = MPI_Scan(&n,&cend,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 29728fb81238SShri Abhyankar cstart = cend - n; 29738fb81238SShri Abhyankar } else { 29748fb81238SShri Abhyankar cstart = rstart; 29758fb81238SShri Abhyankar cend = rend; 29768fb81238SShri Abhyankar n = cend - cstart; 29778fb81238SShri Abhyankar } 29788fb81238SShri Abhyankar 29798fb81238SShri Abhyankar /* loop over local rows, determining number of off diagonal entries */ 29808fb81238SShri Abhyankar ierr = PetscMemzero(offlens,m*sizeof(PetscInt));CHKERRQ(ierr); 29818fb81238SShri Abhyankar jj = 0; 29828fb81238SShri Abhyankar for (i=0; i<m; i++) { 29838fb81238SShri Abhyankar for (j=0; j<ourlens[i]; j++) { 29848fb81238SShri Abhyankar if (mycols[jj] < cstart || mycols[jj] >= cend) offlens[i]++; 29858fb81238SShri Abhyankar jj++; 29868fb81238SShri Abhyankar } 29878fb81238SShri Abhyankar } 29888fb81238SShri Abhyankar 29898fb81238SShri Abhyankar for (i=0; i<m; i++) { 29908fb81238SShri Abhyankar ourlens[i] -= offlens[i]; 29918fb81238SShri Abhyankar } 29928fb81238SShri Abhyankar ierr = MatSetSizes(newMat,m,n,M,N);CHKERRQ(ierr); 299308ea439dSMark F. Adams 299408ea439dSMark F. Adams if (bs > 1) {ierr = MatSetBlockSize(newMat,bs);CHKERRQ(ierr);} 299508ea439dSMark F. Adams 29968fb81238SShri Abhyankar ierr = MatMPIAIJSetPreallocation(newMat,0,ourlens,0,offlens);CHKERRQ(ierr); 29978fb81238SShri Abhyankar 29988fb81238SShri Abhyankar for (i=0; i<m; i++) { 29998fb81238SShri Abhyankar ourlens[i] += offlens[i]; 30008fb81238SShri Abhyankar } 30018fb81238SShri Abhyankar 30028fb81238SShri Abhyankar if (!rank) { 3003854ce69bSBarry Smith ierr = PetscMalloc1(maxnz+1,&vals);CHKERRQ(ierr); 30048fb81238SShri Abhyankar 30058fb81238SShri Abhyankar /* read in my part of the matrix numerical values */ 30068fb81238SShri Abhyankar nz = procsnz[0]; 30078fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr); 30088fb81238SShri Abhyankar 30098fb81238SShri Abhyankar /* insert into matrix */ 30108fb81238SShri Abhyankar jj = rstart; 30118fb81238SShri Abhyankar smycols = mycols; 30128fb81238SShri Abhyankar svals = vals; 30138fb81238SShri Abhyankar for (i=0; i<m; i++) { 30148fb81238SShri Abhyankar ierr = MatSetValues_MPIAIJ(newMat,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr); 30158fb81238SShri Abhyankar smycols += ourlens[i]; 30168fb81238SShri Abhyankar svals += ourlens[i]; 30178fb81238SShri Abhyankar jj++; 30188fb81238SShri Abhyankar } 30198fb81238SShri Abhyankar 30208fb81238SShri Abhyankar /* read in other processors and ship out */ 30218fb81238SShri Abhyankar for (i=1; i<size; i++) { 30228fb81238SShri Abhyankar nz = procsnz[i]; 30238fb81238SShri Abhyankar ierr = PetscBinaryRead(fd,vals,nz,PETSC_SCALAR);CHKERRQ(ierr); 3024a25532f0SBarry Smith ierr = MPIULong_Send(vals,nz,MPIU_SCALAR,i,((PetscObject)newMat)->tag,comm);CHKERRQ(ierr); 30258fb81238SShri Abhyankar } 30268fb81238SShri Abhyankar ierr = PetscFree(procsnz);CHKERRQ(ierr); 30278fb81238SShri Abhyankar } else { 30288fb81238SShri Abhyankar /* receive numeric values */ 3029854ce69bSBarry Smith ierr = PetscMalloc1(nz+1,&vals);CHKERRQ(ierr); 30308fb81238SShri Abhyankar 30318fb81238SShri Abhyankar /* receive message of values*/ 3032a25532f0SBarry Smith ierr = MPIULong_Recv(vals,nz,MPIU_SCALAR,0,((PetscObject)newMat)->tag,comm);CHKERRQ(ierr); 30338fb81238SShri Abhyankar 30348fb81238SShri Abhyankar /* insert into matrix */ 30358fb81238SShri Abhyankar jj = rstart; 30368fb81238SShri Abhyankar smycols = mycols; 30378fb81238SShri Abhyankar svals = vals; 30388fb81238SShri Abhyankar for (i=0; i<m; i++) { 30398fb81238SShri Abhyankar ierr = MatSetValues_MPIAIJ(newMat,1,&jj,ourlens[i],smycols,svals,INSERT_VALUES);CHKERRQ(ierr); 30408fb81238SShri Abhyankar smycols += ourlens[i]; 30418fb81238SShri Abhyankar svals += ourlens[i]; 30428fb81238SShri Abhyankar jj++; 30438fb81238SShri Abhyankar } 30448fb81238SShri Abhyankar } 30458fb81238SShri Abhyankar ierr = PetscFree2(ourlens,offlens);CHKERRQ(ierr); 30468fb81238SShri Abhyankar ierr = PetscFree(vals);CHKERRQ(ierr); 30478fb81238SShri Abhyankar ierr = PetscFree(mycols);CHKERRQ(ierr); 30488fb81238SShri Abhyankar ierr = PetscFree(rowners);CHKERRQ(ierr); 30498fb81238SShri Abhyankar ierr = MatAssemblyBegin(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 30508fb81238SShri Abhyankar ierr = MatAssemblyEnd(newMat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 30518fb81238SShri Abhyankar PetscFunctionReturn(0); 30528fb81238SShri Abhyankar } 30538fb81238SShri Abhyankar 30548fb81238SShri Abhyankar #undef __FUNCT__ 30554a2ae208SSatish Balay #define __FUNCT__ "MatGetSubMatrix_MPIAIJ" 3056c5e4d11fSDmitry Karpeev /* TODO: Not scalable because of ISAllGather() unless getting all columns. */ 30574aa3045dSJed Brown PetscErrorCode MatGetSubMatrix_MPIAIJ(Mat mat,IS isrow,IS iscol,MatReuse call,Mat *newmat) 30584aa3045dSJed Brown { 30594aa3045dSJed Brown PetscErrorCode ierr; 30604aa3045dSJed Brown IS iscol_local; 30614aa3045dSJed Brown PetscInt csize; 30624aa3045dSJed Brown 30634aa3045dSJed Brown PetscFunctionBegin; 30644aa3045dSJed Brown ierr = ISGetLocalSize(iscol,&csize);CHKERRQ(ierr); 3065b79d0421SJed Brown if (call == MAT_REUSE_MATRIX) { 3066b79d0421SJed Brown ierr = PetscObjectQuery((PetscObject)*newmat,"ISAllGather",(PetscObject*)&iscol_local);CHKERRQ(ierr); 3067e32f2f54SBarry Smith if (!iscol_local) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Submatrix passed in was not used before, cannot reuse"); 3068b79d0421SJed Brown } else { 3069c5e4d11fSDmitry Karpeev /* check if we are grabbing all columns*/ 3070c5e4d11fSDmitry Karpeev PetscBool isstride; 3071c5e4d11fSDmitry Karpeev PetscMPIInt lisstride = 0,gisstride; 3072c5e4d11fSDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)iscol,ISSTRIDE,&isstride);CHKERRQ(ierr); 3073c5e4d11fSDmitry Karpeev if (isstride) { 3074c5e4d11fSDmitry Karpeev PetscInt start,len,mstart,mlen; 3075c5e4d11fSDmitry Karpeev ierr = ISStrideGetInfo(iscol,&start,NULL);CHKERRQ(ierr); 3076c5e4d11fSDmitry Karpeev ierr = ISGetLocalSize(iscol,&len);CHKERRQ(ierr); 3077c5e4d11fSDmitry Karpeev ierr = MatGetOwnershipRangeColumn(mat,&mstart,&mlen);CHKERRQ(ierr); 3078c5e4d11fSDmitry Karpeev if (mstart == start && mlen-mstart == len) lisstride = 1; 3079c5e4d11fSDmitry Karpeev } 3080b2566f29SBarry Smith ierr = MPIU_Allreduce(&lisstride,&gisstride,1,MPI_INT,MPI_MIN,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr); 3081c5e4d11fSDmitry Karpeev if (gisstride) { 3082c5e4d11fSDmitry Karpeev PetscInt N; 3083c5e4d11fSDmitry Karpeev ierr = MatGetSize(mat,NULL,&N);CHKERRQ(ierr); 3084c5e4d11fSDmitry Karpeev ierr = ISCreateStride(PetscObjectComm((PetscObject)mat),N,0,1,&iscol_local);CHKERRQ(ierr); 3085c5e4d11fSDmitry Karpeev ierr = ISSetIdentity(iscol_local);CHKERRQ(ierr); 3086c5e4d11fSDmitry Karpeev ierr = PetscInfo(mat,"Optimizing for obtaining all columns of the matrix; skipping ISAllGather()\n");CHKERRQ(ierr); 3087c5e4d11fSDmitry Karpeev } else { 3088c5bfad50SMark F. Adams PetscInt cbs; 3089c5bfad50SMark F. Adams ierr = ISGetBlockSize(iscol,&cbs);CHKERRQ(ierr); 30904aa3045dSJed Brown ierr = ISAllGather(iscol,&iscol_local);CHKERRQ(ierr); 3091c5bfad50SMark F. Adams ierr = ISSetBlockSize(iscol_local,cbs);CHKERRQ(ierr); 3092b79d0421SJed Brown } 3093c5e4d11fSDmitry Karpeev } 30944aa3045dSJed Brown ierr = MatGetSubMatrix_MPIAIJ_Private(mat,isrow,iscol_local,csize,call,newmat);CHKERRQ(ierr); 3095b79d0421SJed Brown if (call == MAT_INITIAL_MATRIX) { 3096b79d0421SJed Brown ierr = PetscObjectCompose((PetscObject)*newmat,"ISAllGather",(PetscObject)iscol_local);CHKERRQ(ierr); 30976bf464f9SBarry Smith ierr = ISDestroy(&iscol_local);CHKERRQ(ierr); 3098b79d0421SJed Brown } 30994aa3045dSJed Brown PetscFunctionReturn(0); 31004aa3045dSJed Brown } 31014aa3045dSJed Brown 310229dcf524SDmitry Karpeev extern PetscErrorCode MatGetSubMatrices_MPIAIJ_Local(Mat,PetscInt,const IS[],const IS[],MatReuse,PetscBool*,Mat*); 31034aa3045dSJed Brown #undef __FUNCT__ 31044aa3045dSJed Brown #define __FUNCT__ "MatGetSubMatrix_MPIAIJ_Private" 3105a0ff6018SBarry Smith /* 310629da9460SBarry Smith Not great since it makes two copies of the submatrix, first an SeqAIJ 310729da9460SBarry Smith in local and then by concatenating the local matrices the end result. 310829da9460SBarry Smith Writing it directly would be much like MatGetSubMatrices_MPIAIJ() 31094aa3045dSJed Brown 31104aa3045dSJed Brown Note: This requires a sequential iscol with all indices. 3111a0ff6018SBarry Smith */ 31124aa3045dSJed Brown PetscErrorCode MatGetSubMatrix_MPIAIJ_Private(Mat mat,IS isrow,IS iscol,PetscInt csize,MatReuse call,Mat *newmat) 3113a0ff6018SBarry Smith { 3114dfbe8321SBarry Smith PetscErrorCode ierr; 311532dcc486SBarry Smith PetscMPIInt rank,size; 3116a2f3521dSMark F. Adams PetscInt i,m,n,rstart,row,rend,nz,*cwork,j,bs,cbs; 311729dcf524SDmitry Karpeev PetscInt *ii,*jj,nlocal,*dlens,*olens,dlen,olen,jend,mglobal,ncol; 311829dcf524SDmitry Karpeev PetscBool allcolumns, colflag; 311929dcf524SDmitry Karpeev Mat M,Mreuse; 3120a77337e4SBarry Smith MatScalar *vwork,*aa; 3121ce94432eSBarry Smith MPI_Comm comm; 312200e6dbe6SBarry Smith Mat_SeqAIJ *aij; 31237e2c5f70SBarry Smith 3124a0ff6018SBarry Smith PetscFunctionBegin; 3125ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr); 31261dab6e02SBarry Smith ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 31271dab6e02SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 312800e6dbe6SBarry Smith 312929dcf524SDmitry Karpeev ierr = ISIdentity(iscol,&colflag);CHKERRQ(ierr); 313029dcf524SDmitry Karpeev ierr = ISGetLocalSize(iscol,&ncol);CHKERRQ(ierr); 313129dcf524SDmitry Karpeev if (colflag && ncol == mat->cmap->N) { 313229dcf524SDmitry Karpeev allcolumns = PETSC_TRUE; 3133c5e4d11fSDmitry Karpeev ierr = PetscInfo(mat,"Optimizing for obtaining all columns of the matrix\n");CHKERRQ(ierr); 313429dcf524SDmitry Karpeev } else { 313529dcf524SDmitry Karpeev allcolumns = PETSC_FALSE; 313629dcf524SDmitry Karpeev } 3137fee21e36SBarry Smith if (call == MAT_REUSE_MATRIX) { 3138fee21e36SBarry Smith ierr = PetscObjectQuery((PetscObject)*newmat,"SubMatrix",(PetscObject*)&Mreuse);CHKERRQ(ierr); 3139e32f2f54SBarry Smith if (!Mreuse) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Submatrix passed in was not used before, cannot reuse"); 314029dcf524SDmitry Karpeev ierr = MatGetSubMatrices_MPIAIJ_Local(mat,1,&isrow,&iscol,MAT_REUSE_MATRIX,&allcolumns,&Mreuse);CHKERRQ(ierr); 3141fee21e36SBarry Smith } else { 314229dcf524SDmitry Karpeev ierr = MatGetSubMatrices_MPIAIJ_Local(mat,1,&isrow,&iscol,MAT_INITIAL_MATRIX,&allcolumns,&Mreuse);CHKERRQ(ierr); 3143fee21e36SBarry Smith } 3144a0ff6018SBarry Smith 3145a0ff6018SBarry Smith /* 3146a0ff6018SBarry Smith m - number of local rows 3147a0ff6018SBarry Smith n - number of columns (same on all processors) 3148a0ff6018SBarry Smith rstart - first row in new global matrix generated 3149a0ff6018SBarry Smith */ 3150fee21e36SBarry Smith ierr = MatGetSize(Mreuse,&m,&n);CHKERRQ(ierr); 3151a2f3521dSMark F. Adams ierr = MatGetBlockSizes(Mreuse,&bs,&cbs);CHKERRQ(ierr); 3152a0ff6018SBarry Smith if (call == MAT_INITIAL_MATRIX) { 3153fee21e36SBarry Smith aij = (Mat_SeqAIJ*)(Mreuse)->data; 315400e6dbe6SBarry Smith ii = aij->i; 315500e6dbe6SBarry Smith jj = aij->j; 315600e6dbe6SBarry Smith 3157a0ff6018SBarry Smith /* 315800e6dbe6SBarry Smith Determine the number of non-zeros in the diagonal and off-diagonal 315900e6dbe6SBarry Smith portions of the matrix in order to do correct preallocation 3160a0ff6018SBarry Smith */ 316100e6dbe6SBarry Smith 316200e6dbe6SBarry Smith /* first get start and end of "diagonal" columns */ 31636a6a5d1dSBarry Smith if (csize == PETSC_DECIDE) { 3164ab50ec6bSBarry Smith ierr = ISGetSize(isrow,&mglobal);CHKERRQ(ierr); 3165ab50ec6bSBarry Smith if (mglobal == n) { /* square matrix */ 3166e2c4fddaSBarry Smith nlocal = m; 31676a6a5d1dSBarry Smith } else { 3168ab50ec6bSBarry Smith nlocal = n/size + ((n % size) > rank); 3169ab50ec6bSBarry Smith } 3170ab50ec6bSBarry Smith } else { 31716a6a5d1dSBarry Smith nlocal = csize; 31726a6a5d1dSBarry Smith } 3173b1d57f15SBarry Smith ierr = MPI_Scan(&nlocal,&rend,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 317400e6dbe6SBarry Smith rstart = rend - nlocal; 317565e19b50SBarry Smith if (rank == size - 1 && rend != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local column sizes %D do not add up to total number of columns %D",rend,n); 317600e6dbe6SBarry Smith 317700e6dbe6SBarry Smith /* next, compute all the lengths */ 3178854ce69bSBarry Smith ierr = PetscMalloc1(2*m+1,&dlens);CHKERRQ(ierr); 317900e6dbe6SBarry Smith olens = dlens + m; 318000e6dbe6SBarry Smith for (i=0; i<m; i++) { 318100e6dbe6SBarry Smith jend = ii[i+1] - ii[i]; 318200e6dbe6SBarry Smith olen = 0; 318300e6dbe6SBarry Smith dlen = 0; 318400e6dbe6SBarry Smith for (j=0; j<jend; j++) { 318500e6dbe6SBarry Smith if (*jj < rstart || *jj >= rend) olen++; 318600e6dbe6SBarry Smith else dlen++; 318700e6dbe6SBarry Smith jj++; 318800e6dbe6SBarry Smith } 318900e6dbe6SBarry Smith olens[i] = olen; 319000e6dbe6SBarry Smith dlens[i] = dlen; 319100e6dbe6SBarry Smith } 3192f69a0ea3SMatthew Knepley ierr = MatCreate(comm,&M);CHKERRQ(ierr); 3193f69a0ea3SMatthew Knepley ierr = MatSetSizes(M,m,nlocal,PETSC_DECIDE,n);CHKERRQ(ierr); 3194a2f3521dSMark F. Adams ierr = MatSetBlockSizes(M,bs,cbs);CHKERRQ(ierr); 31957adad957SLisandro Dalcin ierr = MatSetType(M,((PetscObject)mat)->type_name);CHKERRQ(ierr); 3196e2d9671bSKris Buschelman ierr = MatMPIAIJSetPreallocation(M,0,dlens,0,olens);CHKERRQ(ierr); 3197606d414cSSatish Balay ierr = PetscFree(dlens);CHKERRQ(ierr); 3198a0ff6018SBarry Smith } else { 3199b1d57f15SBarry Smith PetscInt ml,nl; 3200a0ff6018SBarry Smith 3201a0ff6018SBarry Smith M = *newmat; 3202a0ff6018SBarry Smith ierr = MatGetLocalSize(M,&ml,&nl);CHKERRQ(ierr); 3203e32f2f54SBarry Smith if (ml != m) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Previous matrix must be same size/layout as request"); 3204a0ff6018SBarry Smith ierr = MatZeroEntries(M);CHKERRQ(ierr); 3205c48de900SBarry Smith /* 3206c48de900SBarry Smith The next two lines are needed so we may call MatSetValues_MPIAIJ() below directly, 3207c48de900SBarry Smith rather than the slower MatSetValues(). 3208c48de900SBarry Smith */ 3209c48de900SBarry Smith M->was_assembled = PETSC_TRUE; 3210c48de900SBarry Smith M->assembled = PETSC_FALSE; 3211a0ff6018SBarry Smith } 3212a0ff6018SBarry Smith ierr = MatGetOwnershipRange(M,&rstart,&rend);CHKERRQ(ierr); 3213fee21e36SBarry Smith aij = (Mat_SeqAIJ*)(Mreuse)->data; 321400e6dbe6SBarry Smith ii = aij->i; 321500e6dbe6SBarry Smith jj = aij->j; 321600e6dbe6SBarry Smith aa = aij->a; 3217a0ff6018SBarry Smith for (i=0; i<m; i++) { 3218a0ff6018SBarry Smith row = rstart + i; 321900e6dbe6SBarry Smith nz = ii[i+1] - ii[i]; 322000e6dbe6SBarry Smith cwork = jj; jj += nz; 322100e6dbe6SBarry Smith vwork = aa; aa += nz; 32228c638d02SBarry Smith ierr = MatSetValues_MPIAIJ(M,1,&row,nz,cwork,vwork,INSERT_VALUES);CHKERRQ(ierr); 3223a0ff6018SBarry Smith } 3224a0ff6018SBarry Smith 3225a0ff6018SBarry Smith ierr = MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3226a0ff6018SBarry Smith ierr = MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3227a0ff6018SBarry Smith *newmat = M; 3228fee21e36SBarry Smith 3229fee21e36SBarry Smith /* save submatrix used in processor for next request */ 3230fee21e36SBarry Smith if (call == MAT_INITIAL_MATRIX) { 3231fee21e36SBarry Smith ierr = PetscObjectCompose((PetscObject)M,"SubMatrix",(PetscObject)Mreuse);CHKERRQ(ierr); 3232bf0cc555SLisandro Dalcin ierr = MatDestroy(&Mreuse);CHKERRQ(ierr); 3233fee21e36SBarry Smith } 3234a0ff6018SBarry Smith PetscFunctionReturn(0); 3235a0ff6018SBarry Smith } 3236273d9f13SBarry Smith 32374a2ae208SSatish Balay #undef __FUNCT__ 3238ccd8e176SBarry Smith #define __FUNCT__ "MatMPIAIJSetPreallocationCSR_MPIAIJ" 32397087cfbeSBarry Smith PetscErrorCode MatMPIAIJSetPreallocationCSR_MPIAIJ(Mat B,const PetscInt Ii[],const PetscInt J[],const PetscScalar v[]) 3240ccd8e176SBarry Smith { 3241899cda47SBarry Smith PetscInt m,cstart, cend,j,nnz,i,d; 3242899cda47SBarry Smith PetscInt *d_nnz,*o_nnz,nnz_max = 0,rstart,ii; 3243ccd8e176SBarry Smith const PetscInt *JJ; 3244ccd8e176SBarry Smith PetscScalar *values; 3245ccd8e176SBarry Smith PetscErrorCode ierr; 3246ccd8e176SBarry Smith 3247ccd8e176SBarry Smith PetscFunctionBegin; 3248e32f2f54SBarry Smith if (Ii[0]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Ii[0] must be 0 it is %D",Ii[0]); 3249899cda47SBarry Smith 325026283091SBarry Smith ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr); 325126283091SBarry Smith ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr); 3252d0f46423SBarry Smith m = B->rmap->n; 3253d0f46423SBarry Smith cstart = B->cmap->rstart; 3254d0f46423SBarry Smith cend = B->cmap->rend; 3255d0f46423SBarry Smith rstart = B->rmap->rstart; 3256899cda47SBarry Smith 3257dcca6d9dSJed Brown ierr = PetscMalloc2(m,&d_nnz,m,&o_nnz);CHKERRQ(ierr); 3258ccd8e176SBarry Smith 3259ecc77c7aSBarry Smith #if defined(PETSC_USE_DEBUGGING) 3260ecc77c7aSBarry Smith for (i=0; i<m; i++) { 3261ecc77c7aSBarry Smith nnz = Ii[i+1]- Ii[i]; 3262ecc77c7aSBarry Smith JJ = J + Ii[i]; 3263e32f2f54SBarry Smith if (nnz < 0) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local row %D has a negative %D number of columns",i,nnz); 3264ecc77c7aSBarry Smith if (nnz && (JJ[0] < 0)) SETERRRQ1(PETSC_ERR_ARG_WRONGSTATE,"Row %D starts with negative column index",i,j); 3265d0f46423SBarry Smith if (nnz && (JJ[nnz-1] >= B->cmap->N) SETERRRQ3(PETSC_ERR_ARG_WRONGSTATE,"Row %D ends with too large a column index %D (max allowed %D)",i,JJ[nnz-1],B->cmap->N); 3266ecc77c7aSBarry Smith } 3267ecc77c7aSBarry Smith #endif 3268ecc77c7aSBarry Smith 3269ccd8e176SBarry Smith for (i=0; i<m; i++) { 3270b7940d39SSatish Balay nnz = Ii[i+1]- Ii[i]; 3271b7940d39SSatish Balay JJ = J + Ii[i]; 3272ccd8e176SBarry Smith nnz_max = PetscMax(nnz_max,nnz); 3273ccd8e176SBarry Smith d = 0; 32740daa03b5SJed Brown for (j=0; j<nnz; j++) { 32750daa03b5SJed Brown if (cstart <= JJ[j] && JJ[j] < cend) d++; 3276ccd8e176SBarry Smith } 3277ccd8e176SBarry Smith d_nnz[i] = d; 3278ccd8e176SBarry Smith o_nnz[i] = nnz - d; 3279ccd8e176SBarry Smith } 3280ccd8e176SBarry Smith ierr = MatMPIAIJSetPreallocation(B,0,d_nnz,0,o_nnz);CHKERRQ(ierr); 32811d79065fSBarry Smith ierr = PetscFree2(d_nnz,o_nnz);CHKERRQ(ierr); 3282ccd8e176SBarry Smith 3283ccd8e176SBarry Smith if (v) values = (PetscScalar*)v; 3284ccd8e176SBarry Smith else { 3285854ce69bSBarry Smith ierr = PetscCalloc1(nnz_max+1,&values);CHKERRQ(ierr); 3286ccd8e176SBarry Smith } 3287ccd8e176SBarry Smith 3288ccd8e176SBarry Smith for (i=0; i<m; i++) { 3289ccd8e176SBarry Smith ii = i + rstart; 3290b7940d39SSatish Balay nnz = Ii[i+1]- Ii[i]; 3291b7940d39SSatish Balay ierr = MatSetValues_MPIAIJ(B,1,&ii,nnz,J+Ii[i],values+(v ? Ii[i] : 0),INSERT_VALUES);CHKERRQ(ierr); 3292ccd8e176SBarry Smith } 3293ccd8e176SBarry Smith ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3294ccd8e176SBarry Smith ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3295ccd8e176SBarry Smith 3296ccd8e176SBarry Smith if (!v) { 3297ccd8e176SBarry Smith ierr = PetscFree(values);CHKERRQ(ierr); 3298ccd8e176SBarry Smith } 32997827cd58SJed Brown ierr = MatSetOption(B,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 3300ccd8e176SBarry Smith PetscFunctionReturn(0); 3301ccd8e176SBarry Smith } 3302ccd8e176SBarry Smith 3303ccd8e176SBarry Smith #undef __FUNCT__ 3304ccd8e176SBarry Smith #define __FUNCT__ "MatMPIAIJSetPreallocationCSR" 33051eea217eSSatish Balay /*@ 3306ccd8e176SBarry Smith MatMPIAIJSetPreallocationCSR - Allocates memory for a sparse parallel matrix in AIJ format 3307ccd8e176SBarry Smith (the default parallel PETSc format). 3308ccd8e176SBarry Smith 3309ccd8e176SBarry Smith Collective on MPI_Comm 3310ccd8e176SBarry Smith 3311ccd8e176SBarry Smith Input Parameters: 3312a1661176SMatthew Knepley + B - the matrix 3313ccd8e176SBarry Smith . i - the indices into j for the start of each local row (starts with zero) 33140daa03b5SJed Brown . j - the column indices for each local row (starts with zero) 3315ccd8e176SBarry Smith - v - optional values in the matrix 3316ccd8e176SBarry Smith 3317ccd8e176SBarry Smith Level: developer 3318ccd8e176SBarry Smith 331912251496SSatish Balay Notes: 332012251496SSatish Balay The i, j, and a arrays ARE copied by this routine into the internal format used by PETSc; 332112251496SSatish Balay thus you CANNOT change the matrix entries by changing the values of a[] after you have 332212251496SSatish Balay called this routine. Use MatCreateMPIAIJWithSplitArrays() to avoid needing to copy the arrays. 332312251496SSatish Balay 332412251496SSatish Balay The i and j indices are 0 based, and i indices are indices corresponding to the local j array. 332512251496SSatish Balay 332612251496SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 332712251496SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 3328c5e4d11fSDmitry Karpeev as shown 332912251496SSatish Balay 3330c5e4d11fSDmitry Karpeev $ 1 0 0 3331c5e4d11fSDmitry Karpeev $ 2 0 3 P0 3332c5e4d11fSDmitry Karpeev $ ------- 3333c5e4d11fSDmitry Karpeev $ 4 5 6 P1 3334c5e4d11fSDmitry Karpeev $ 3335c5e4d11fSDmitry Karpeev $ Process0 [P0]: rows_owned=[0,1] 3336c5e4d11fSDmitry Karpeev $ i = {0,1,3} [size = nrow+1 = 2+1] 3337c5e4d11fSDmitry Karpeev $ j = {0,0,2} [size = 3] 3338c5e4d11fSDmitry Karpeev $ v = {1,2,3} [size = 3] 3339c5e4d11fSDmitry Karpeev $ 3340c5e4d11fSDmitry Karpeev $ Process1 [P1]: rows_owned=[2] 3341c5e4d11fSDmitry Karpeev $ i = {0,3} [size = nrow+1 = 1+1] 3342c5e4d11fSDmitry Karpeev $ j = {0,1,2} [size = 3] 3343c5e4d11fSDmitry Karpeev $ v = {4,5,6} [size = 3] 334412251496SSatish Balay 3345ccd8e176SBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel 3346ccd8e176SBarry Smith 33475f4d30c4SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatCreateAIJ(), MATMPIAIJ, 33488d7a6e47SBarry Smith MatCreateSeqAIJWithArrays(), MatCreateMPIAIJWithSplitArrays() 3349ccd8e176SBarry Smith @*/ 33507087cfbeSBarry Smith PetscErrorCode MatMPIAIJSetPreallocationCSR(Mat B,const PetscInt i[],const PetscInt j[], const PetscScalar v[]) 3351ccd8e176SBarry Smith { 33524ac538c5SBarry Smith PetscErrorCode ierr; 3353ccd8e176SBarry Smith 3354ccd8e176SBarry Smith PetscFunctionBegin; 33554ac538c5SBarry Smith ierr = PetscTryMethod(B,"MatMPIAIJSetPreallocationCSR_C",(Mat,const PetscInt[],const PetscInt[],const PetscScalar[]),(B,i,j,v));CHKERRQ(ierr); 3356ccd8e176SBarry Smith PetscFunctionReturn(0); 3357ccd8e176SBarry Smith } 3358ccd8e176SBarry Smith 3359ccd8e176SBarry Smith #undef __FUNCT__ 33604a2ae208SSatish Balay #define __FUNCT__ "MatMPIAIJSetPreallocation" 3361273d9f13SBarry Smith /*@C 3362ccd8e176SBarry Smith MatMPIAIJSetPreallocation - Preallocates memory for a sparse parallel matrix in AIJ format 3363273d9f13SBarry Smith (the default parallel PETSc format). For good matrix assembly performance 3364273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameters 3365273d9f13SBarry Smith d_nz (or d_nnz) and o_nz (or o_nnz). By setting these parameters accurately, 3366273d9f13SBarry Smith performance can be increased by more than a factor of 50. 3367273d9f13SBarry Smith 3368273d9f13SBarry Smith Collective on MPI_Comm 3369273d9f13SBarry Smith 3370273d9f13SBarry Smith Input Parameters: 33711c4f3114SJed Brown + B - the matrix 3372273d9f13SBarry Smith . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 3373273d9f13SBarry Smith (same value is used for all local rows) 3374273d9f13SBarry Smith . d_nnz - array containing the number of nonzeros in the various rows of the 3375273d9f13SBarry Smith DIAGONAL portion of the local submatrix (possibly different for each row) 337620fa73abSMatthew G. Knepley or NULL (PETSC_NULL_INTEGER in Fortran), if d_nz is used to specify the nonzero structure. 3377273d9f13SBarry Smith The size of this array is equal to the number of local rows, i.e 'm'. 33783287b5eaSJed Brown For matrices that will be factored, you must leave room for (and set) 33793287b5eaSJed Brown the diagonal entry even if it is zero. 3380273d9f13SBarry Smith . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 3381273d9f13SBarry Smith submatrix (same value is used for all local rows). 3382273d9f13SBarry Smith - o_nnz - array containing the number of nonzeros in the various rows of the 3383273d9f13SBarry Smith OFF-DIAGONAL portion of the local submatrix (possibly different for 338420fa73abSMatthew G. Knepley each row) or NULL (PETSC_NULL_INTEGER in Fortran), if o_nz is used to specify the nonzero 3385273d9f13SBarry Smith structure. The size of this array is equal to the number 3386273d9f13SBarry Smith of local rows, i.e 'm'. 3387273d9f13SBarry Smith 338849a6f317SBarry Smith If the *_nnz parameter is given then the *_nz parameter is ignored 338949a6f317SBarry Smith 3390273d9f13SBarry Smith The AIJ format (also called the Yale sparse matrix format or 3391ccd8e176SBarry Smith compressed row storage (CSR)), is fully compatible with standard Fortran 77 33920598bfebSBarry Smith storage. The stored row and column indices begin with zero. 3393a7f22e61SSatish Balay See Users-Manual: ch_mat for details. 3394273d9f13SBarry Smith 3395273d9f13SBarry Smith The parallel matrix is partitioned such that the first m0 rows belong to 3396273d9f13SBarry Smith process 0, the next m1 rows belong to process 1, the next m2 rows belong 3397273d9f13SBarry Smith to process 2 etc.. where m0,m1,m2... are the input parameter 'm'. 3398273d9f13SBarry Smith 3399273d9f13SBarry Smith The DIAGONAL portion of the local submatrix of a processor can be defined 3400a05b864aSJed Brown as the submatrix which is obtained by extraction the part corresponding to 3401a05b864aSJed Brown the rows r1-r2 and columns c1-c2 of the global matrix, where r1 is the 3402a05b864aSJed Brown first row that belongs to the processor, r2 is the last row belonging to 3403a05b864aSJed Brown the this processor, and c1-c2 is range of indices of the local part of a 3404a05b864aSJed Brown vector suitable for applying the matrix to. This is an mxn matrix. In the 3405a05b864aSJed Brown common case of a square matrix, the row and column ranges are the same and 3406a05b864aSJed Brown the DIAGONAL part is also square. The remaining portion of the local 3407a05b864aSJed Brown submatrix (mxN) constitute the OFF-DIAGONAL portion. 3408273d9f13SBarry Smith 3409273d9f13SBarry Smith If o_nnz, d_nnz are specified, then o_nz, and d_nz are ignored. 3410273d9f13SBarry Smith 3411aa95bbe8SBarry Smith You can call MatGetInfo() to get information on how effective the preallocation was; 3412aa95bbe8SBarry Smith for example the fields mallocs,nz_allocated,nz_used,nz_unneeded; 3413aa95bbe8SBarry Smith You can also run with the option -info and look for messages with the string 3414aa95bbe8SBarry Smith malloc in them to see if additional memory allocation was needed. 3415aa95bbe8SBarry Smith 3416273d9f13SBarry Smith Example usage: 3417273d9f13SBarry Smith 3418273d9f13SBarry Smith Consider the following 8x8 matrix with 34 non-zero values, that is 3419273d9f13SBarry Smith assembled across 3 processors. Lets assume that proc0 owns 3 rows, 3420273d9f13SBarry Smith proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 3421273d9f13SBarry Smith as follows: 3422273d9f13SBarry Smith 3423273d9f13SBarry Smith .vb 3424273d9f13SBarry Smith 1 2 0 | 0 3 0 | 0 4 3425273d9f13SBarry Smith Proc0 0 5 6 | 7 0 0 | 8 0 3426273d9f13SBarry Smith 9 0 10 | 11 0 0 | 12 0 3427273d9f13SBarry Smith ------------------------------------- 3428273d9f13SBarry Smith 13 0 14 | 15 16 17 | 0 0 3429273d9f13SBarry Smith Proc1 0 18 0 | 19 20 21 | 0 0 3430273d9f13SBarry Smith 0 0 0 | 22 23 0 | 24 0 3431273d9f13SBarry Smith ------------------------------------- 3432273d9f13SBarry Smith Proc2 25 26 27 | 0 0 28 | 29 0 3433273d9f13SBarry Smith 30 0 0 | 31 32 33 | 0 34 3434273d9f13SBarry Smith .ve 3435273d9f13SBarry Smith 3436273d9f13SBarry Smith This can be represented as a collection of submatrices as: 3437273d9f13SBarry Smith 3438273d9f13SBarry Smith .vb 3439273d9f13SBarry Smith A B C 3440273d9f13SBarry Smith D E F 3441273d9f13SBarry Smith G H I 3442273d9f13SBarry Smith .ve 3443273d9f13SBarry Smith 3444273d9f13SBarry Smith Where the submatrices A,B,C are owned by proc0, D,E,F are 3445273d9f13SBarry Smith owned by proc1, G,H,I are owned by proc2. 3446273d9f13SBarry Smith 3447273d9f13SBarry Smith The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 3448273d9f13SBarry Smith The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 3449273d9f13SBarry Smith The 'M','N' parameters are 8,8, and have the same values on all procs. 3450273d9f13SBarry Smith 3451273d9f13SBarry Smith The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are 3452273d9f13SBarry Smith submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices 3453273d9f13SBarry Smith corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively. 3454273d9f13SBarry Smith Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL 3455273d9f13SBarry Smith part as SeqAIJ matrices. for eg: proc1 will store [E] as a SeqAIJ 3456273d9f13SBarry Smith matrix, ans [DF] as another SeqAIJ matrix. 3457273d9f13SBarry Smith 3458273d9f13SBarry Smith When d_nz, o_nz parameters are specified, d_nz storage elements are 3459273d9f13SBarry Smith allocated for every row of the local diagonal submatrix, and o_nz 3460273d9f13SBarry Smith storage locations are allocated for every row of the OFF-DIAGONAL submat. 3461273d9f13SBarry Smith One way to choose d_nz and o_nz is to use the max nonzerors per local 3462273d9f13SBarry Smith rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices. 3463273d9f13SBarry Smith In this case, the values of d_nz,o_nz are: 3464273d9f13SBarry Smith .vb 3465273d9f13SBarry Smith proc0 : dnz = 2, o_nz = 2 3466273d9f13SBarry Smith proc1 : dnz = 3, o_nz = 2 3467273d9f13SBarry Smith proc2 : dnz = 1, o_nz = 4 3468273d9f13SBarry Smith .ve 3469273d9f13SBarry Smith We are allocating m*(d_nz+o_nz) storage locations for every proc. This 3470273d9f13SBarry Smith translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10 3471273d9f13SBarry Smith for proc3. i.e we are using 12+15+10=37 storage locations to store 3472273d9f13SBarry Smith 34 values. 3473273d9f13SBarry Smith 3474273d9f13SBarry Smith When d_nnz, o_nnz parameters are specified, the storage is specified 3475273d9f13SBarry Smith for every row, coresponding to both DIAGONAL and OFF-DIAGONAL submatrices. 3476273d9f13SBarry Smith In the above case the values for d_nnz,o_nnz are: 3477273d9f13SBarry Smith .vb 3478273d9f13SBarry Smith proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2] 3479273d9f13SBarry Smith proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1] 3480273d9f13SBarry Smith proc2: d_nnz = [1,1] and o_nnz = [4,4] 3481273d9f13SBarry Smith .ve 3482273d9f13SBarry Smith Here the space allocated is sum of all the above values i.e 34, and 3483273d9f13SBarry Smith hence pre-allocation is perfect. 3484273d9f13SBarry Smith 3485273d9f13SBarry Smith Level: intermediate 3486273d9f13SBarry Smith 3487273d9f13SBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel 3488273d9f13SBarry Smith 348969b1f4b7SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatCreateAIJ(), MatMPIAIJSetPreallocationCSR(), 34905f4d30c4SBarry Smith MATMPIAIJ, MatGetInfo(), PetscSplitOwnership() 3491273d9f13SBarry Smith @*/ 34927087cfbeSBarry Smith PetscErrorCode MatMPIAIJSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[]) 3493273d9f13SBarry Smith { 34944ac538c5SBarry Smith PetscErrorCode ierr; 3495273d9f13SBarry Smith 3496273d9f13SBarry Smith PetscFunctionBegin; 34976ba663aaSJed Brown PetscValidHeaderSpecific(B,MAT_CLASSID,1); 34986ba663aaSJed Brown PetscValidType(B,1); 34994ac538c5SBarry Smith ierr = PetscTryMethod(B,"MatMPIAIJSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr); 3500273d9f13SBarry Smith PetscFunctionReturn(0); 3501273d9f13SBarry Smith } 3502273d9f13SBarry Smith 35034a2ae208SSatish Balay #undef __FUNCT__ 35042fb0ec9aSBarry Smith #define __FUNCT__ "MatCreateMPIAIJWithArrays" 350558d36128SBarry Smith /*@ 35062fb0ec9aSBarry Smith MatCreateMPIAIJWithArrays - creates a MPI AIJ matrix using arrays that contain in standard 35072fb0ec9aSBarry Smith CSR format the local rows. 35082fb0ec9aSBarry Smith 35092fb0ec9aSBarry Smith Collective on MPI_Comm 35102fb0ec9aSBarry Smith 35112fb0ec9aSBarry Smith Input Parameters: 35122fb0ec9aSBarry Smith + comm - MPI communicator 35132fb0ec9aSBarry Smith . m - number of local rows (Cannot be PETSC_DECIDE) 35142fb0ec9aSBarry Smith . n - This value should be the same as the local size used in creating the 35152fb0ec9aSBarry Smith x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have 35162fb0ec9aSBarry Smith calculated if N is given) For square matrices n is almost always m. 35172fb0ec9aSBarry Smith . M - number of global rows (or PETSC_DETERMINE to have calculated if m is given) 35182fb0ec9aSBarry Smith . N - number of global columns (or PETSC_DETERMINE to have calculated if n is given) 35192fb0ec9aSBarry Smith . i - row indices 35202fb0ec9aSBarry Smith . j - column indices 35212fb0ec9aSBarry Smith - a - matrix values 35222fb0ec9aSBarry Smith 35232fb0ec9aSBarry Smith Output Parameter: 35242fb0ec9aSBarry Smith . mat - the matrix 352503bfb495SBarry Smith 35262fb0ec9aSBarry Smith Level: intermediate 35272fb0ec9aSBarry Smith 35282fb0ec9aSBarry Smith Notes: 35292fb0ec9aSBarry Smith The i, j, and a arrays ARE copied by this routine into the internal format used by PETSc; 35302fb0ec9aSBarry Smith thus you CANNOT change the matrix entries by changing the values of a[] after you have 35318d7a6e47SBarry Smith called this routine. Use MatCreateMPIAIJWithSplitArrays() to avoid needing to copy the arrays. 35322fb0ec9aSBarry Smith 353312251496SSatish Balay The i and j indices are 0 based, and i indices are indices corresponding to the local j array. 353412251496SSatish Balay 353512251496SSatish Balay The format which is used for the sparse matrix input, is equivalent to a 353612251496SSatish Balay row-major ordering.. i.e for the following matrix, the input data expected is 3537c5e4d11fSDmitry Karpeev as shown 353812251496SSatish Balay 3539c5e4d11fSDmitry Karpeev $ 1 0 0 3540c5e4d11fSDmitry Karpeev $ 2 0 3 P0 3541c5e4d11fSDmitry Karpeev $ ------- 3542c5e4d11fSDmitry Karpeev $ 4 5 6 P1 3543c5e4d11fSDmitry Karpeev $ 3544c5e4d11fSDmitry Karpeev $ Process0 [P0]: rows_owned=[0,1] 3545c5e4d11fSDmitry Karpeev $ i = {0,1,3} [size = nrow+1 = 2+1] 3546c5e4d11fSDmitry Karpeev $ j = {0,0,2} [size = 3] 3547c5e4d11fSDmitry Karpeev $ v = {1,2,3} [size = 3] 3548c5e4d11fSDmitry Karpeev $ 3549c5e4d11fSDmitry Karpeev $ Process1 [P1]: rows_owned=[2] 3550c5e4d11fSDmitry Karpeev $ i = {0,3} [size = nrow+1 = 1+1] 3551c5e4d11fSDmitry Karpeev $ j = {0,1,2} [size = 3] 3552c5e4d11fSDmitry Karpeev $ v = {4,5,6} [size = 3] 35532fb0ec9aSBarry Smith 35542fb0ec9aSBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel 35552fb0ec9aSBarry Smith 35562fb0ec9aSBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(), 35575f4d30c4SBarry Smith MATMPIAIJ, MatCreateAIJ(), MatCreateMPIAIJWithSplitArrays() 35582fb0ec9aSBarry Smith @*/ 35597087cfbeSBarry 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) 35602fb0ec9aSBarry Smith { 35612fb0ec9aSBarry Smith PetscErrorCode ierr; 35622fb0ec9aSBarry Smith 35632fb0ec9aSBarry Smith PetscFunctionBegin; 356469b1f4b7SBarry Smith if (i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 3565e32f2f54SBarry Smith if (m < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"local number of rows (m) cannot be PETSC_DECIDE, or negative"); 35662fb0ec9aSBarry Smith ierr = MatCreate(comm,mat);CHKERRQ(ierr); 3567d4146a68SBarry Smith ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr); 3568a2f3521dSMark F. Adams /* ierr = MatSetBlockSizes(M,bs,cbs);CHKERRQ(ierr); */ 35692fb0ec9aSBarry Smith ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr); 35702fb0ec9aSBarry Smith ierr = MatMPIAIJSetPreallocationCSR(*mat,i,j,a);CHKERRQ(ierr); 35712fb0ec9aSBarry Smith PetscFunctionReturn(0); 35722fb0ec9aSBarry Smith } 35732fb0ec9aSBarry Smith 35742fb0ec9aSBarry Smith #undef __FUNCT__ 357569b1f4b7SBarry Smith #define __FUNCT__ "MatCreateAIJ" 3576273d9f13SBarry Smith /*@C 357769b1f4b7SBarry Smith MatCreateAIJ - Creates a sparse parallel matrix in AIJ format 3578273d9f13SBarry Smith (the default parallel PETSc format). For good matrix assembly performance 3579273d9f13SBarry Smith the user should preallocate the matrix storage by setting the parameters 3580273d9f13SBarry Smith d_nz (or d_nnz) and o_nz (or o_nnz). By setting these parameters accurately, 3581273d9f13SBarry Smith performance can be increased by more than a factor of 50. 3582273d9f13SBarry Smith 3583273d9f13SBarry Smith Collective on MPI_Comm 3584273d9f13SBarry Smith 3585273d9f13SBarry Smith Input Parameters: 3586273d9f13SBarry Smith + comm - MPI communicator 3587273d9f13SBarry Smith . m - number of local rows (or PETSC_DECIDE to have calculated if M is given) 3588273d9f13SBarry Smith This value should be the same as the local size used in creating the 3589273d9f13SBarry Smith y vector for the matrix-vector product y = Ax. 3590273d9f13SBarry Smith . n - This value should be the same as the local size used in creating the 3591273d9f13SBarry Smith x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have 3592273d9f13SBarry Smith calculated if N is given) For square matrices n is almost always m. 3593273d9f13SBarry Smith . M - number of global rows (or PETSC_DETERMINE to have calculated if m is given) 3594273d9f13SBarry Smith . N - number of global columns (or PETSC_DETERMINE to have calculated if n is given) 3595273d9f13SBarry Smith . d_nz - number of nonzeros per row in DIAGONAL portion of local submatrix 3596273d9f13SBarry Smith (same value is used for all local rows) 3597273d9f13SBarry Smith . d_nnz - array containing the number of nonzeros in the various rows of the 3598273d9f13SBarry Smith DIAGONAL portion of the local submatrix (possibly different for each row) 35990298fd71SBarry Smith or NULL, if d_nz is used to specify the nonzero structure. 3600273d9f13SBarry Smith The size of this array is equal to the number of local rows, i.e 'm'. 3601273d9f13SBarry Smith . o_nz - number of nonzeros per row in the OFF-DIAGONAL portion of local 3602273d9f13SBarry Smith submatrix (same value is used for all local rows). 3603273d9f13SBarry Smith - o_nnz - array containing the number of nonzeros in the various rows of the 3604273d9f13SBarry Smith OFF-DIAGONAL portion of the local submatrix (possibly different for 36050298fd71SBarry Smith each row) or NULL, if o_nz is used to specify the nonzero 3606273d9f13SBarry Smith structure. The size of this array is equal to the number 3607273d9f13SBarry Smith of local rows, i.e 'm'. 3608273d9f13SBarry Smith 3609273d9f13SBarry Smith Output Parameter: 3610273d9f13SBarry Smith . A - the matrix 3611273d9f13SBarry Smith 3612175b88e8SBarry Smith It is recommended that one use the MatCreate(), MatSetType() and/or MatSetFromOptions(), 3613ae1d86c5SBarry Smith MatXXXXSetPreallocation() paradgm instead of this routine directly. 3614175b88e8SBarry Smith [MatXXXXSetPreallocation() is, for example, MatSeqAIJSetPreallocation] 3615175b88e8SBarry Smith 3616273d9f13SBarry Smith Notes: 361749a6f317SBarry Smith If the *_nnz parameter is given then the *_nz parameter is ignored 361849a6f317SBarry Smith 3619273d9f13SBarry Smith m,n,M,N parameters specify the size of the matrix, and its partitioning across 3620273d9f13SBarry Smith processors, while d_nz,d_nnz,o_nz,o_nnz parameters specify the approximate 3621273d9f13SBarry Smith storage requirements for this matrix. 3622273d9f13SBarry Smith 3623273d9f13SBarry Smith If PETSC_DECIDE or PETSC_DETERMINE is used for a particular argument on one 3624273d9f13SBarry Smith processor than it must be used on all processors that share the object for 3625273d9f13SBarry Smith that argument. 3626273d9f13SBarry Smith 3627273d9f13SBarry Smith The user MUST specify either the local or global matrix dimensions 3628273d9f13SBarry Smith (possibly both). 3629273d9f13SBarry Smith 363033a7c187SSatish Balay The parallel matrix is partitioned across processors such that the 363133a7c187SSatish Balay first m0 rows belong to process 0, the next m1 rows belong to 363233a7c187SSatish Balay process 1, the next m2 rows belong to process 2 etc.. where 363333a7c187SSatish Balay m0,m1,m2,.. are the input parameter 'm'. i.e each processor stores 363433a7c187SSatish Balay values corresponding to [m x N] submatrix. 3635273d9f13SBarry Smith 363633a7c187SSatish Balay The columns are logically partitioned with the n0 columns belonging 363733a7c187SSatish Balay to 0th partition, the next n1 columns belonging to the next 3638df3898eeSBarry Smith partition etc.. where n0,n1,n2... are the input parameter 'n'. 363933a7c187SSatish Balay 364033a7c187SSatish Balay The DIAGONAL portion of the local submatrix on any given processor 364133a7c187SSatish Balay is the submatrix corresponding to the rows and columns m,n 364233a7c187SSatish Balay corresponding to the given processor. i.e diagonal matrix on 364333a7c187SSatish Balay process 0 is [m0 x n0], diagonal matrix on process 1 is [m1 x n1] 364433a7c187SSatish Balay etc. The remaining portion of the local submatrix [m x (N-n)] 364533a7c187SSatish Balay constitute the OFF-DIAGONAL portion. The example below better 364633a7c187SSatish Balay illustrates this concept. 364733a7c187SSatish Balay 364833a7c187SSatish Balay For a square global matrix we define each processor's diagonal portion 364933a7c187SSatish Balay to be its local rows and the corresponding columns (a square submatrix); 365033a7c187SSatish Balay each processor's off-diagonal portion encompasses the remainder of the 365133a7c187SSatish Balay local matrix (a rectangular submatrix). 3652273d9f13SBarry Smith 3653273d9f13SBarry Smith If o_nnz, d_nnz are specified, then o_nz, and d_nz are ignored. 3654273d9f13SBarry Smith 365597d05335SKris Buschelman When calling this routine with a single process communicator, a matrix of 36565f4d30c4SBarry Smith type SEQAIJ is returned. If a matrix of type MATMPIAIJ is desired for this 365797d05335SKris Buschelman type of communicator, use the construction mechanism: 365878102f6cSMatthew Knepley MatCreate(...,&A); MatSetType(A,MATMPIAIJ); MatSetSizes(A, m,n,M,N); MatMPIAIJSetPreallocation(A,...); 365997d05335SKris Buschelman 3660273d9f13SBarry Smith By default, this format uses inodes (identical nodes) when possible. 3661273d9f13SBarry Smith We search for consecutive rows with the same nonzero structure, thereby 3662273d9f13SBarry Smith reusing matrix information to achieve increased efficiency. 3663273d9f13SBarry Smith 3664273d9f13SBarry Smith Options Database Keys: 3665923f20ffSKris Buschelman + -mat_no_inode - Do not use inodes 3666923f20ffSKris Buschelman . -mat_inode_limit <limit> - Sets inode limit (max limit=5) 3667273d9f13SBarry Smith - -mat_aij_oneindex - Internally use indexing starting at 1 3668273d9f13SBarry Smith rather than 0. Note that when calling MatSetValues(), 3669273d9f13SBarry Smith the user still MUST index entries starting at 0! 3670273d9f13SBarry Smith 3671273d9f13SBarry Smith 3672273d9f13SBarry Smith Example usage: 3673273d9f13SBarry Smith 3674273d9f13SBarry Smith Consider the following 8x8 matrix with 34 non-zero values, that is 3675273d9f13SBarry Smith assembled across 3 processors. Lets assume that proc0 owns 3 rows, 3676273d9f13SBarry Smith proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown 3677273d9f13SBarry Smith as follows: 3678273d9f13SBarry Smith 3679273d9f13SBarry Smith .vb 3680273d9f13SBarry Smith 1 2 0 | 0 3 0 | 0 4 3681273d9f13SBarry Smith Proc0 0 5 6 | 7 0 0 | 8 0 3682273d9f13SBarry Smith 9 0 10 | 11 0 0 | 12 0 3683273d9f13SBarry Smith ------------------------------------- 3684273d9f13SBarry Smith 13 0 14 | 15 16 17 | 0 0 3685273d9f13SBarry Smith Proc1 0 18 0 | 19 20 21 | 0 0 3686273d9f13SBarry Smith 0 0 0 | 22 23 0 | 24 0 3687273d9f13SBarry Smith ------------------------------------- 3688273d9f13SBarry Smith Proc2 25 26 27 | 0 0 28 | 29 0 3689273d9f13SBarry Smith 30 0 0 | 31 32 33 | 0 34 3690273d9f13SBarry Smith .ve 3691273d9f13SBarry Smith 3692273d9f13SBarry Smith This can be represented as a collection of submatrices as: 3693273d9f13SBarry Smith 3694273d9f13SBarry Smith .vb 3695273d9f13SBarry Smith A B C 3696273d9f13SBarry Smith D E F 3697273d9f13SBarry Smith G H I 3698273d9f13SBarry Smith .ve 3699273d9f13SBarry Smith 3700273d9f13SBarry Smith Where the submatrices A,B,C are owned by proc0, D,E,F are 3701273d9f13SBarry Smith owned by proc1, G,H,I are owned by proc2. 3702273d9f13SBarry Smith 3703273d9f13SBarry Smith The 'm' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 3704273d9f13SBarry Smith The 'n' parameters for proc0,proc1,proc2 are 3,3,2 respectively. 3705273d9f13SBarry Smith The 'M','N' parameters are 8,8, and have the same values on all procs. 3706273d9f13SBarry Smith 3707273d9f13SBarry Smith The DIAGONAL submatrices corresponding to proc0,proc1,proc2 are 3708273d9f13SBarry Smith submatrices [A], [E], [I] respectively. The OFF-DIAGONAL submatrices 3709273d9f13SBarry Smith corresponding to proc0,proc1,proc2 are [BC], [DF], [GH] respectively. 3710273d9f13SBarry Smith Internally, each processor stores the DIAGONAL part, and the OFF-DIAGONAL 3711273d9f13SBarry Smith part as SeqAIJ matrices. for eg: proc1 will store [E] as a SeqAIJ 3712273d9f13SBarry Smith matrix, ans [DF] as another SeqAIJ matrix. 3713273d9f13SBarry Smith 3714273d9f13SBarry Smith When d_nz, o_nz parameters are specified, d_nz storage elements are 3715273d9f13SBarry Smith allocated for every row of the local diagonal submatrix, and o_nz 3716273d9f13SBarry Smith storage locations are allocated for every row of the OFF-DIAGONAL submat. 3717273d9f13SBarry Smith One way to choose d_nz and o_nz is to use the max nonzerors per local 3718273d9f13SBarry Smith rows for each of the local DIAGONAL, and the OFF-DIAGONAL submatrices. 3719273d9f13SBarry Smith In this case, the values of d_nz,o_nz are: 3720273d9f13SBarry Smith .vb 3721273d9f13SBarry Smith proc0 : dnz = 2, o_nz = 2 3722273d9f13SBarry Smith proc1 : dnz = 3, o_nz = 2 3723273d9f13SBarry Smith proc2 : dnz = 1, o_nz = 4 3724273d9f13SBarry Smith .ve 3725273d9f13SBarry Smith We are allocating m*(d_nz+o_nz) storage locations for every proc. This 3726273d9f13SBarry Smith translates to 3*(2+2)=12 for proc0, 3*(3+2)=15 for proc1, 2*(1+4)=10 3727273d9f13SBarry Smith for proc3. i.e we are using 12+15+10=37 storage locations to store 3728273d9f13SBarry Smith 34 values. 3729273d9f13SBarry Smith 3730273d9f13SBarry Smith When d_nnz, o_nnz parameters are specified, the storage is specified 3731273d9f13SBarry Smith for every row, coresponding to both DIAGONAL and OFF-DIAGONAL submatrices. 3732273d9f13SBarry Smith In the above case the values for d_nnz,o_nnz are: 3733273d9f13SBarry Smith .vb 3734273d9f13SBarry Smith proc0: d_nnz = [2,2,2] and o_nnz = [2,2,2] 3735273d9f13SBarry Smith proc1: d_nnz = [3,3,2] and o_nnz = [2,1,1] 3736273d9f13SBarry Smith proc2: d_nnz = [1,1] and o_nnz = [4,4] 3737273d9f13SBarry Smith .ve 3738273d9f13SBarry Smith Here the space allocated is sum of all the above values i.e 34, and 3739273d9f13SBarry Smith hence pre-allocation is perfect. 3740273d9f13SBarry Smith 3741273d9f13SBarry Smith Level: intermediate 3742273d9f13SBarry Smith 3743273d9f13SBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel 3744273d9f13SBarry Smith 3745ccd8e176SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(), 37465f4d30c4SBarry Smith MATMPIAIJ, MatCreateMPIAIJWithArrays() 3747273d9f13SBarry Smith @*/ 374869b1f4b7SBarry 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) 3749273d9f13SBarry Smith { 37506849ba73SBarry Smith PetscErrorCode ierr; 3751b1d57f15SBarry Smith PetscMPIInt size; 3752273d9f13SBarry Smith 3753273d9f13SBarry Smith PetscFunctionBegin; 3754f69a0ea3SMatthew Knepley ierr = MatCreate(comm,A);CHKERRQ(ierr); 3755f69a0ea3SMatthew Knepley ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr); 3756273d9f13SBarry Smith ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 3757273d9f13SBarry Smith if (size > 1) { 3758273d9f13SBarry Smith ierr = MatSetType(*A,MATMPIAIJ);CHKERRQ(ierr); 3759273d9f13SBarry Smith ierr = MatMPIAIJSetPreallocation(*A,d_nz,d_nnz,o_nz,o_nnz);CHKERRQ(ierr); 3760273d9f13SBarry Smith } else { 3761273d9f13SBarry Smith ierr = MatSetType(*A,MATSEQAIJ);CHKERRQ(ierr); 3762273d9f13SBarry Smith ierr = MatSeqAIJSetPreallocation(*A,d_nz,d_nnz);CHKERRQ(ierr); 3763273d9f13SBarry Smith } 3764273d9f13SBarry Smith PetscFunctionReturn(0); 3765273d9f13SBarry Smith } 3766195d93cdSBarry Smith 37674a2ae208SSatish Balay #undef __FUNCT__ 37684a2ae208SSatish Balay #define __FUNCT__ "MatMPIAIJGetSeqAIJ" 37699230625dSJed Brown PetscErrorCode MatMPIAIJGetSeqAIJ(Mat A,Mat *Ad,Mat *Ao,const PetscInt *colmap[]) 3770195d93cdSBarry Smith { 3771195d93cdSBarry Smith Mat_MPIAIJ *a = (Mat_MPIAIJ*)A->data; 377204cf37c7SBarry Smith PetscBool flg; 377304cf37c7SBarry Smith PetscErrorCode ierr; 3774b1d57f15SBarry Smith 3775195d93cdSBarry Smith PetscFunctionBegin; 377604cf37c7SBarry Smith ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&flg);CHKERRQ(ierr); 37775f4d30c4SBarry Smith if (!flg) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"This function requires a MATMPIAIJ matrix as input"); 377821e72a00SBarry Smith if (Ad) *Ad = a->A; 377921e72a00SBarry Smith if (Ao) *Ao = a->B; 378021e72a00SBarry Smith if (colmap) *colmap = a->garray; 3781195d93cdSBarry Smith PetscFunctionReturn(0); 3782195d93cdSBarry Smith } 3783a2243be0SBarry Smith 3784a2243be0SBarry Smith #undef __FUNCT__ 3785110bb6e1SHong Zhang #define __FUNCT__ "MatCreateMPIMatConcatenateSeqMat_MPIAIJ" 3786110bb6e1SHong Zhang PetscErrorCode MatCreateMPIMatConcatenateSeqMat_MPIAIJ(MPI_Comm comm,Mat inmat,PetscInt n,MatReuse scall,Mat *outmat) 37879b8102ccSHong Zhang { 37889b8102ccSHong Zhang PetscErrorCode ierr; 3789110bb6e1SHong Zhang PetscInt m,N,i,rstart,nnz,Ii; 37909b8102ccSHong Zhang PetscInt *indx; 3791110bb6e1SHong Zhang PetscScalar *values; 37929b8102ccSHong Zhang 37939b8102ccSHong Zhang PetscFunctionBegin; 37949b8102ccSHong Zhang ierr = MatGetSize(inmat,&m,&N);CHKERRQ(ierr); 3795110bb6e1SHong Zhang if (scall == MAT_INITIAL_MATRIX) { /* symbolic phase */ 3796110bb6e1SHong Zhang PetscInt *dnz,*onz,sum,bs,cbs; 3797110bb6e1SHong Zhang 37989b8102ccSHong Zhang if (n == PETSC_DECIDE) { 37999b8102ccSHong Zhang ierr = PetscSplitOwnership(comm,&n,&N);CHKERRQ(ierr); 38009b8102ccSHong Zhang } 3801a22543b6SHong Zhang /* Check sum(n) = N */ 3802b2566f29SBarry Smith ierr = MPIU_Allreduce(&n,&sum,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 3803a22543b6SHong Zhang if (sum != N) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Sum of local columns != global columns %d",N); 3804a22543b6SHong Zhang 38059b8102ccSHong Zhang ierr = MPI_Scan(&m, &rstart,1,MPIU_INT,MPI_SUM,comm);CHKERRQ(ierr); 38069b8102ccSHong Zhang rstart -= m; 38079b8102ccSHong Zhang 38089b8102ccSHong Zhang ierr = MatPreallocateInitialize(comm,m,n,dnz,onz);CHKERRQ(ierr); 38099b8102ccSHong Zhang for (i=0; i<m; i++) { 38100298fd71SBarry Smith ierr = MatGetRow_SeqAIJ(inmat,i,&nnz,&indx,NULL);CHKERRQ(ierr); 38119b8102ccSHong Zhang ierr = MatPreallocateSet(i+rstart,nnz,indx,dnz,onz);CHKERRQ(ierr); 38120298fd71SBarry Smith ierr = MatRestoreRow_SeqAIJ(inmat,i,&nnz,&indx,NULL);CHKERRQ(ierr); 38139b8102ccSHong Zhang } 38149b8102ccSHong Zhang 38159b8102ccSHong Zhang ierr = MatCreate(comm,outmat);CHKERRQ(ierr); 38169b8102ccSHong Zhang ierr = MatSetSizes(*outmat,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 3817110bb6e1SHong Zhang ierr = MatGetBlockSizes(inmat,&bs,&cbs);CHKERRQ(ierr); 3818a2f3521dSMark F. Adams ierr = MatSetBlockSizes(*outmat,bs,cbs);CHKERRQ(ierr); 38199b8102ccSHong Zhang ierr = MatSetType(*outmat,MATMPIAIJ);CHKERRQ(ierr); 38209b8102ccSHong Zhang ierr = MatMPIAIJSetPreallocation(*outmat,0,dnz,0,onz);CHKERRQ(ierr); 38219b8102ccSHong Zhang ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 38229b8102ccSHong Zhang } 38239b8102ccSHong Zhang 3824110bb6e1SHong Zhang /* numeric phase */ 3825110bb6e1SHong Zhang ierr = MatGetOwnershipRange(*outmat,&rstart,NULL);CHKERRQ(ierr); 38269b8102ccSHong Zhang for (i=0; i<m; i++) { 38279b8102ccSHong Zhang ierr = MatGetRow_SeqAIJ(inmat,i,&nnz,&indx,&values);CHKERRQ(ierr); 38289b8102ccSHong Zhang Ii = i + rstart; 3829110bb6e1SHong Zhang ierr = MatSetValues(*outmat,1,&Ii,nnz,indx,values,INSERT_VALUES);CHKERRQ(ierr); 38309b8102ccSHong Zhang ierr = MatRestoreRow_SeqAIJ(inmat,i,&nnz,&indx,&values);CHKERRQ(ierr); 38319b8102ccSHong Zhang } 3832110bb6e1SHong Zhang ierr = MatAssemblyBegin(*outmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3833110bb6e1SHong Zhang ierr = MatAssemblyEnd(*outmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3834c5d6d63eSBarry Smith PetscFunctionReturn(0); 3835c5d6d63eSBarry Smith } 3836c5d6d63eSBarry Smith 3837c5d6d63eSBarry Smith #undef __FUNCT__ 3838c5d6d63eSBarry Smith #define __FUNCT__ "MatFileSplit" 3839dfbe8321SBarry Smith PetscErrorCode MatFileSplit(Mat A,char *outfile) 3840c5d6d63eSBarry Smith { 3841dfbe8321SBarry Smith PetscErrorCode ierr; 384232dcc486SBarry Smith PetscMPIInt rank; 3843b1d57f15SBarry Smith PetscInt m,N,i,rstart,nnz; 3844de4209c5SBarry Smith size_t len; 3845b1d57f15SBarry Smith const PetscInt *indx; 3846c5d6d63eSBarry Smith PetscViewer out; 3847c5d6d63eSBarry Smith char *name; 3848c5d6d63eSBarry Smith Mat B; 3849b3cc6726SBarry Smith const PetscScalar *values; 3850c5d6d63eSBarry Smith 3851c5d6d63eSBarry Smith PetscFunctionBegin; 3852c5d6d63eSBarry Smith ierr = MatGetLocalSize(A,&m,0);CHKERRQ(ierr); 3853c5d6d63eSBarry Smith ierr = MatGetSize(A,0,&N);CHKERRQ(ierr); 3854f204ca49SKris Buschelman /* Should this be the type of the diagonal block of A? */ 3855f69a0ea3SMatthew Knepley ierr = MatCreate(PETSC_COMM_SELF,&B);CHKERRQ(ierr); 3856f69a0ea3SMatthew Knepley ierr = MatSetSizes(B,m,N,m,N);CHKERRQ(ierr); 385733d57670SJed Brown ierr = MatSetBlockSizesFromMats(B,A,A);CHKERRQ(ierr); 3858f204ca49SKris Buschelman ierr = MatSetType(B,MATSEQAIJ);CHKERRQ(ierr); 38590298fd71SBarry Smith ierr = MatSeqAIJSetPreallocation(B,0,NULL);CHKERRQ(ierr); 3860c5d6d63eSBarry Smith ierr = MatGetOwnershipRange(A,&rstart,0);CHKERRQ(ierr); 3861c5d6d63eSBarry Smith for (i=0; i<m; i++) { 3862c5d6d63eSBarry Smith ierr = MatGetRow(A,i+rstart,&nnz,&indx,&values);CHKERRQ(ierr); 3863c5d6d63eSBarry Smith ierr = MatSetValues(B,1,&i,nnz,indx,values,INSERT_VALUES);CHKERRQ(ierr); 3864c5d6d63eSBarry Smith ierr = MatRestoreRow(A,i+rstart,&nnz,&indx,&values);CHKERRQ(ierr); 3865c5d6d63eSBarry Smith } 3866c5d6d63eSBarry Smith ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3867c5d6d63eSBarry Smith ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 3868c5d6d63eSBarry Smith 3869ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A),&rank);CHKERRQ(ierr); 3870c5d6d63eSBarry Smith ierr = PetscStrlen(outfile,&len);CHKERRQ(ierr); 3871854ce69bSBarry Smith ierr = PetscMalloc1(len+5,&name);CHKERRQ(ierr); 3872c5d6d63eSBarry Smith sprintf(name,"%s.%d",outfile,rank); 3873852598b0SBarry Smith ierr = PetscViewerBinaryOpen(PETSC_COMM_SELF,name,FILE_MODE_APPEND,&out);CHKERRQ(ierr); 3874a2ea699eSBarry Smith ierr = PetscFree(name);CHKERRQ(ierr); 3875c5d6d63eSBarry Smith ierr = MatView(B,out);CHKERRQ(ierr); 38766bf464f9SBarry Smith ierr = PetscViewerDestroy(&out);CHKERRQ(ierr); 38776bf464f9SBarry Smith ierr = MatDestroy(&B);CHKERRQ(ierr); 3878c5d6d63eSBarry Smith PetscFunctionReturn(0); 3879c5d6d63eSBarry Smith } 3880e5f2cdd8SHong Zhang 388109573ac7SBarry Smith extern PetscErrorCode MatDestroy_MPIAIJ(Mat); 388251a7d1a8SHong Zhang #undef __FUNCT__ 388351a7d1a8SHong Zhang #define __FUNCT__ "MatDestroy_MPIAIJ_SeqsToMPI" 38847087cfbeSBarry Smith PetscErrorCode MatDestroy_MPIAIJ_SeqsToMPI(Mat A) 388551a7d1a8SHong Zhang { 388651a7d1a8SHong Zhang PetscErrorCode ierr; 3887671beff6SHong Zhang Mat_Merge_SeqsToMPI *merge; 3888776b82aeSLisandro Dalcin PetscContainer container; 388951a7d1a8SHong Zhang 389051a7d1a8SHong Zhang PetscFunctionBegin; 3891671beff6SHong Zhang ierr = PetscObjectQuery((PetscObject)A,"MatMergeSeqsToMPI",(PetscObject*)&container);CHKERRQ(ierr); 3892671beff6SHong Zhang if (container) { 3893776b82aeSLisandro Dalcin ierr = PetscContainerGetPointer(container,(void**)&merge);CHKERRQ(ierr); 389451a7d1a8SHong Zhang ierr = PetscFree(merge->id_r);CHKERRQ(ierr); 38953e06a4e6SHong Zhang ierr = PetscFree(merge->len_s);CHKERRQ(ierr); 38963e06a4e6SHong Zhang ierr = PetscFree(merge->len_r);CHKERRQ(ierr); 389751a7d1a8SHong Zhang ierr = PetscFree(merge->bi);CHKERRQ(ierr); 389851a7d1a8SHong Zhang ierr = PetscFree(merge->bj);CHKERRQ(ierr); 3899533163c2SBarry Smith ierr = PetscFree(merge->buf_ri[0]);CHKERRQ(ierr); 390002c68681SHong Zhang ierr = PetscFree(merge->buf_ri);CHKERRQ(ierr); 3901533163c2SBarry Smith ierr = PetscFree(merge->buf_rj[0]);CHKERRQ(ierr); 390202c68681SHong Zhang ierr = PetscFree(merge->buf_rj);CHKERRQ(ierr); 390305b42c5fSBarry Smith ierr = PetscFree(merge->coi);CHKERRQ(ierr); 390405b42c5fSBarry Smith ierr = PetscFree(merge->coj);CHKERRQ(ierr); 390505b42c5fSBarry Smith ierr = PetscFree(merge->owners_co);CHKERRQ(ierr); 39066bf464f9SBarry Smith ierr = PetscLayoutDestroy(&merge->rowmap);CHKERRQ(ierr); 3907bf0cc555SLisandro Dalcin ierr = PetscFree(merge);CHKERRQ(ierr); 3908671beff6SHong Zhang ierr = PetscObjectCompose((PetscObject)A,"MatMergeSeqsToMPI",0);CHKERRQ(ierr); 3909671beff6SHong Zhang } 391051a7d1a8SHong Zhang ierr = MatDestroy_MPIAIJ(A);CHKERRQ(ierr); 391151a7d1a8SHong Zhang PetscFunctionReturn(0); 391251a7d1a8SHong Zhang } 391351a7d1a8SHong Zhang 3914c6db04a5SJed Brown #include <../src/mat/utils/freespace.h> 3915c6db04a5SJed Brown #include <petscbt.h> 39164ebed01fSBarry Smith 3917e5f2cdd8SHong Zhang #undef __FUNCT__ 391890431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJSumSeqAIJNumeric" 391990431a8fSHong Zhang PetscErrorCode MatCreateMPIAIJSumSeqAIJNumeric(Mat seqmat,Mat mpimat) 392055d1abb9SHong Zhang { 392155d1abb9SHong Zhang PetscErrorCode ierr; 3922ce94432eSBarry Smith MPI_Comm comm; 392355d1abb9SHong Zhang Mat_SeqAIJ *a =(Mat_SeqAIJ*)seqmat->data; 3924b1d57f15SBarry Smith PetscMPIInt size,rank,taga,*len_s; 3925a2ea699eSBarry Smith PetscInt N=mpimat->cmap->N,i,j,*owners,*ai=a->i,*aj; 3926b1d57f15SBarry Smith PetscInt proc,m; 3927b1d57f15SBarry Smith PetscInt **buf_ri,**buf_rj; 3928b1d57f15SBarry Smith PetscInt k,anzi,*bj_i,*bi,*bj,arow,bnzi,nextaj; 3929b1d57f15SBarry Smith PetscInt nrows,**buf_ri_k,**nextrow,**nextai; 393055d1abb9SHong Zhang MPI_Request *s_waits,*r_waits; 393155d1abb9SHong Zhang MPI_Status *status; 3932a77337e4SBarry Smith MatScalar *aa=a->a; 3933dd6ea824SBarry Smith MatScalar **abuf_r,*ba_i; 393455d1abb9SHong Zhang Mat_Merge_SeqsToMPI *merge; 3935776b82aeSLisandro Dalcin PetscContainer container; 393655d1abb9SHong Zhang 393755d1abb9SHong Zhang PetscFunctionBegin; 3938bedda5b1SHong Zhang ierr = PetscObjectGetComm((PetscObject)mpimat,&comm);CHKERRQ(ierr); 39394ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Seqstompinum,seqmat,0,0,0);CHKERRQ(ierr); 39403c2c1871SHong Zhang 394155d1abb9SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 394255d1abb9SHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 394355d1abb9SHong Zhang 394455d1abb9SHong Zhang ierr = PetscObjectQuery((PetscObject)mpimat,"MatMergeSeqsToMPI",(PetscObject*)&container);CHKERRQ(ierr); 3945776b82aeSLisandro Dalcin ierr = PetscContainerGetPointer(container,(void**)&merge);CHKERRQ(ierr); 3946bf0cc555SLisandro Dalcin 394755d1abb9SHong Zhang bi = merge->bi; 394855d1abb9SHong Zhang bj = merge->bj; 394955d1abb9SHong Zhang buf_ri = merge->buf_ri; 395055d1abb9SHong Zhang buf_rj = merge->buf_rj; 395155d1abb9SHong Zhang 3952785e854fSJed Brown ierr = PetscMalloc1(size,&status);CHKERRQ(ierr); 39537a2fc3feSBarry Smith owners = merge->rowmap->range; 395455d1abb9SHong Zhang len_s = merge->len_s; 395555d1abb9SHong Zhang 395655d1abb9SHong Zhang /* send and recv matrix values */ 395755d1abb9SHong Zhang /*-----------------------------*/ 3958357abbc8SBarry Smith ierr = PetscObjectGetNewTag((PetscObject)mpimat,&taga);CHKERRQ(ierr); 395955d1abb9SHong Zhang ierr = PetscPostIrecvScalar(comm,taga,merge->nrecv,merge->id_r,merge->len_r,&abuf_r,&r_waits);CHKERRQ(ierr); 396055d1abb9SHong Zhang 3961854ce69bSBarry Smith ierr = PetscMalloc1(merge->nsend+1,&s_waits);CHKERRQ(ierr); 396255d1abb9SHong Zhang for (proc=0,k=0; proc<size; proc++) { 396355d1abb9SHong Zhang if (!len_s[proc]) continue; 396455d1abb9SHong Zhang i = owners[proc]; 396555d1abb9SHong Zhang ierr = MPI_Isend(aa+ai[i],len_s[proc],MPIU_MATSCALAR,proc,taga,comm,s_waits+k);CHKERRQ(ierr); 396655d1abb9SHong Zhang k++; 396755d1abb9SHong Zhang } 396855d1abb9SHong Zhang 39690c468ba9SBarry Smith if (merge->nrecv) {ierr = MPI_Waitall(merge->nrecv,r_waits,status);CHKERRQ(ierr);} 39700c468ba9SBarry Smith if (merge->nsend) {ierr = MPI_Waitall(merge->nsend,s_waits,status);CHKERRQ(ierr);} 397155d1abb9SHong Zhang ierr = PetscFree(status);CHKERRQ(ierr); 397255d1abb9SHong Zhang 397355d1abb9SHong Zhang ierr = PetscFree(s_waits);CHKERRQ(ierr); 397455d1abb9SHong Zhang ierr = PetscFree(r_waits);CHKERRQ(ierr); 397555d1abb9SHong Zhang 397655d1abb9SHong Zhang /* insert mat values of mpimat */ 397755d1abb9SHong Zhang /*----------------------------*/ 3978785e854fSJed Brown ierr = PetscMalloc1(N,&ba_i);CHKERRQ(ierr); 3979dcca6d9dSJed Brown ierr = PetscMalloc3(merge->nrecv,&buf_ri_k,merge->nrecv,&nextrow,merge->nrecv,&nextai);CHKERRQ(ierr); 398055d1abb9SHong Zhang 398155d1abb9SHong Zhang for (k=0; k<merge->nrecv; k++) { 398255d1abb9SHong Zhang buf_ri_k[k] = buf_ri[k]; /* beginning of k-th recved i-structure */ 398355d1abb9SHong Zhang nrows = *(buf_ri_k[k]); 398455d1abb9SHong Zhang nextrow[k] = buf_ri_k[k]+1; /* next row number of k-th recved i-structure */ 398555d1abb9SHong Zhang nextai[k] = buf_ri_k[k] + (nrows + 1); /* poins to the next i-structure of k-th recved i-structure */ 398655d1abb9SHong Zhang } 398755d1abb9SHong Zhang 398855d1abb9SHong Zhang /* set values of ba */ 39897a2fc3feSBarry Smith m = merge->rowmap->n; 399055d1abb9SHong Zhang for (i=0; i<m; i++) { 399155d1abb9SHong Zhang arow = owners[rank] + i; 399255d1abb9SHong Zhang bj_i = bj+bi[i]; /* col indices of the i-th row of mpimat */ 399355d1abb9SHong Zhang bnzi = bi[i+1] - bi[i]; 3994a77337e4SBarry Smith ierr = PetscMemzero(ba_i,bnzi*sizeof(PetscScalar));CHKERRQ(ierr); 399555d1abb9SHong Zhang 399655d1abb9SHong Zhang /* add local non-zero vals of this proc's seqmat into ba */ 399755d1abb9SHong Zhang anzi = ai[arow+1] - ai[arow]; 399855d1abb9SHong Zhang aj = a->j + ai[arow]; 399955d1abb9SHong Zhang aa = a->a + ai[arow]; 400055d1abb9SHong Zhang nextaj = 0; 400155d1abb9SHong Zhang for (j=0; nextaj<anzi; j++) { 400255d1abb9SHong Zhang if (*(bj_i + j) == aj[nextaj]) { /* bcol == acol */ 400355d1abb9SHong Zhang ba_i[j] += aa[nextaj++]; 400455d1abb9SHong Zhang } 400555d1abb9SHong Zhang } 400655d1abb9SHong Zhang 400755d1abb9SHong Zhang /* add received vals into ba */ 400855d1abb9SHong Zhang for (k=0; k<merge->nrecv; k++) { /* k-th received message */ 400955d1abb9SHong Zhang /* i-th row */ 401055d1abb9SHong Zhang if (i == *nextrow[k]) { 401155d1abb9SHong Zhang anzi = *(nextai[k]+1) - *nextai[k]; 401255d1abb9SHong Zhang aj = buf_rj[k] + *(nextai[k]); 401355d1abb9SHong Zhang aa = abuf_r[k] + *(nextai[k]); 401455d1abb9SHong Zhang nextaj = 0; 401555d1abb9SHong Zhang for (j=0; nextaj<anzi; j++) { 401655d1abb9SHong Zhang if (*(bj_i + j) == aj[nextaj]) { /* bcol == acol */ 401755d1abb9SHong Zhang ba_i[j] += aa[nextaj++]; 401855d1abb9SHong Zhang } 401955d1abb9SHong Zhang } 402055d1abb9SHong Zhang nextrow[k]++; nextai[k]++; 402155d1abb9SHong Zhang } 402255d1abb9SHong Zhang } 402355d1abb9SHong Zhang ierr = MatSetValues(mpimat,1,&arow,bnzi,bj_i,ba_i,INSERT_VALUES);CHKERRQ(ierr); 402455d1abb9SHong Zhang } 402555d1abb9SHong Zhang ierr = MatAssemblyBegin(mpimat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 402655d1abb9SHong Zhang ierr = MatAssemblyEnd(mpimat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 402755d1abb9SHong Zhang 4028533163c2SBarry Smith ierr = PetscFree(abuf_r[0]);CHKERRQ(ierr); 402955d1abb9SHong Zhang ierr = PetscFree(abuf_r);CHKERRQ(ierr); 403055d1abb9SHong Zhang ierr = PetscFree(ba_i);CHKERRQ(ierr); 40311d79065fSBarry Smith ierr = PetscFree3(buf_ri_k,nextrow,nextai);CHKERRQ(ierr); 40324ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Seqstompinum,seqmat,0,0,0);CHKERRQ(ierr); 403355d1abb9SHong Zhang PetscFunctionReturn(0); 403455d1abb9SHong Zhang } 403538f152feSBarry Smith 40366bc0bbbfSBarry Smith extern PetscErrorCode MatDestroy_MPIAIJ_SeqsToMPI(Mat); 40376bc0bbbfSBarry Smith 403838f152feSBarry Smith #undef __FUNCT__ 403990431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJSumSeqAIJSymbolic" 404090431a8fSHong Zhang PetscErrorCode MatCreateMPIAIJSumSeqAIJSymbolic(MPI_Comm comm,Mat seqmat,PetscInt m,PetscInt n,Mat *mpimat) 4041e5f2cdd8SHong Zhang { 4042f08fae4eSHong Zhang PetscErrorCode ierr; 404355a3bba9SHong Zhang Mat B_mpi; 4044c2234fe3SHong Zhang Mat_SeqAIJ *a=(Mat_SeqAIJ*)seqmat->data; 4045b1d57f15SBarry Smith PetscMPIInt size,rank,tagi,tagj,*len_s,*len_si,*len_ri; 4046b1d57f15SBarry Smith PetscInt **buf_rj,**buf_ri,**buf_ri_k; 4047d0f46423SBarry Smith PetscInt M=seqmat->rmap->n,N=seqmat->cmap->n,i,*owners,*ai=a->i,*aj=a->j; 4048a2f3521dSMark F. Adams PetscInt len,proc,*dnz,*onz,bs,cbs; 4049b1d57f15SBarry Smith PetscInt k,anzi,*bi,*bj,*lnk,nlnk,arow,bnzi,nspacedouble=0; 4050b1d57f15SBarry Smith PetscInt nrows,*buf_s,*buf_si,*buf_si_i,**nextrow,**nextai; 405155d1abb9SHong Zhang MPI_Request *si_waits,*sj_waits,*ri_waits,*rj_waits; 405258cb9c82SHong Zhang MPI_Status *status; 40530298fd71SBarry Smith PetscFreeSpaceList free_space=NULL,current_space=NULL; 4054be0fcf8dSHong Zhang PetscBT lnkbt; 405551a7d1a8SHong Zhang Mat_Merge_SeqsToMPI *merge; 4056776b82aeSLisandro Dalcin PetscContainer container; 405702c68681SHong Zhang 4058e5f2cdd8SHong Zhang PetscFunctionBegin; 40594ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Seqstompisym,seqmat,0,0,0);CHKERRQ(ierr); 40603c2c1871SHong Zhang 406138f152feSBarry Smith /* make sure it is a PETSc comm */ 40620298fd71SBarry Smith ierr = PetscCommDuplicate(comm,&comm,NULL);CHKERRQ(ierr); 4063e5f2cdd8SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 4064e5f2cdd8SHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 406555d1abb9SHong Zhang 4066b00a9115SJed Brown ierr = PetscNew(&merge);CHKERRQ(ierr); 4067785e854fSJed Brown ierr = PetscMalloc1(size,&status);CHKERRQ(ierr); 4068e5f2cdd8SHong Zhang 40696abd8857SHong Zhang /* determine row ownership */ 4070f08fae4eSHong Zhang /*---------------------------------------------------------*/ 407126283091SBarry Smith ierr = PetscLayoutCreate(comm,&merge->rowmap);CHKERRQ(ierr); 407226283091SBarry Smith ierr = PetscLayoutSetLocalSize(merge->rowmap,m);CHKERRQ(ierr); 407326283091SBarry Smith ierr = PetscLayoutSetSize(merge->rowmap,M);CHKERRQ(ierr); 407426283091SBarry Smith ierr = PetscLayoutSetBlockSize(merge->rowmap,1);CHKERRQ(ierr); 407526283091SBarry Smith ierr = PetscLayoutSetUp(merge->rowmap);CHKERRQ(ierr); 4076785e854fSJed Brown ierr = PetscMalloc1(size,&len_si);CHKERRQ(ierr); 4077785e854fSJed Brown ierr = PetscMalloc1(size,&merge->len_s);CHKERRQ(ierr); 407855d1abb9SHong Zhang 40797a2fc3feSBarry Smith m = merge->rowmap->n; 40807a2fc3feSBarry Smith owners = merge->rowmap->range; 40816abd8857SHong Zhang 40826abd8857SHong Zhang /* determine the number of messages to send, their lengths */ 40836abd8857SHong Zhang /*---------------------------------------------------------*/ 40843e06a4e6SHong Zhang len_s = merge->len_s; 408551a7d1a8SHong Zhang 40862257cef7SHong Zhang len = 0; /* length of buf_si[] */ 4087c2234fe3SHong Zhang merge->nsend = 0; 4088409913e3SHong Zhang for (proc=0; proc<size; proc++) { 40892257cef7SHong Zhang len_si[proc] = 0; 40903e06a4e6SHong Zhang if (proc == rank) { 40916abd8857SHong Zhang len_s[proc] = 0; 40923e06a4e6SHong Zhang } else { 409302c68681SHong Zhang len_si[proc] = owners[proc+1] - owners[proc] + 1; 40943e06a4e6SHong Zhang len_s[proc] = ai[owners[proc+1]] - ai[owners[proc]]; /* num of rows to be sent to [proc] */ 40953e06a4e6SHong Zhang } 40963e06a4e6SHong Zhang if (len_s[proc]) { 4097c2234fe3SHong Zhang merge->nsend++; 40982257cef7SHong Zhang nrows = 0; 40992257cef7SHong Zhang for (i=owners[proc]; i<owners[proc+1]; i++) { 41002257cef7SHong Zhang if (ai[i+1] > ai[i]) nrows++; 41012257cef7SHong Zhang } 41022257cef7SHong Zhang len_si[proc] = 2*(nrows+1); 41032257cef7SHong Zhang len += len_si[proc]; 4104409913e3SHong Zhang } 410558cb9c82SHong Zhang } 4106409913e3SHong Zhang 41072257cef7SHong Zhang /* determine the number and length of messages to receive for ij-structure */ 41082257cef7SHong Zhang /*-------------------------------------------------------------------------*/ 41090298fd71SBarry Smith ierr = PetscGatherNumberOfMessages(comm,NULL,len_s,&merge->nrecv);CHKERRQ(ierr); 411055d1abb9SHong Zhang ierr = PetscGatherMessageLengths2(comm,merge->nsend,merge->nrecv,len_s,len_si,&merge->id_r,&merge->len_r,&len_ri);CHKERRQ(ierr); 4111671beff6SHong Zhang 41123e06a4e6SHong Zhang /* post the Irecv of j-structure */ 41133e06a4e6SHong Zhang /*-------------------------------*/ 41142c72b5baSSatish Balay ierr = PetscCommGetNewTag(comm,&tagj);CHKERRQ(ierr); 41153e06a4e6SHong Zhang ierr = PetscPostIrecvInt(comm,tagj,merge->nrecv,merge->id_r,merge->len_r,&buf_rj,&rj_waits);CHKERRQ(ierr); 411602c68681SHong Zhang 41173e06a4e6SHong Zhang /* post the Isend of j-structure */ 4118affca5deSHong Zhang /*--------------------------------*/ 4119dcca6d9dSJed Brown ierr = PetscMalloc2(merge->nsend,&si_waits,merge->nsend,&sj_waits);CHKERRQ(ierr); 41203e06a4e6SHong Zhang 41212257cef7SHong Zhang for (proc=0, k=0; proc<size; proc++) { 4122409913e3SHong Zhang if (!len_s[proc]) continue; 412302c68681SHong Zhang i = owners[proc]; 4124b1d57f15SBarry Smith ierr = MPI_Isend(aj+ai[i],len_s[proc],MPIU_INT,proc,tagj,comm,sj_waits+k);CHKERRQ(ierr); 412551a7d1a8SHong Zhang k++; 412651a7d1a8SHong Zhang } 412751a7d1a8SHong Zhang 41283e06a4e6SHong Zhang /* receives and sends of j-structure are complete */ 41293e06a4e6SHong Zhang /*------------------------------------------------*/ 41300c468ba9SBarry Smith if (merge->nrecv) {ierr = MPI_Waitall(merge->nrecv,rj_waits,status);CHKERRQ(ierr);} 41310c468ba9SBarry Smith if (merge->nsend) {ierr = MPI_Waitall(merge->nsend,sj_waits,status);CHKERRQ(ierr);} 413202c68681SHong Zhang 413302c68681SHong Zhang /* send and recv i-structure */ 413402c68681SHong Zhang /*---------------------------*/ 41352c72b5baSSatish Balay ierr = PetscCommGetNewTag(comm,&tagi);CHKERRQ(ierr); 413602c68681SHong Zhang ierr = PetscPostIrecvInt(comm,tagi,merge->nrecv,merge->id_r,len_ri,&buf_ri,&ri_waits);CHKERRQ(ierr); 413702c68681SHong Zhang 4138854ce69bSBarry Smith ierr = PetscMalloc1(len+1,&buf_s);CHKERRQ(ierr); 41393e06a4e6SHong Zhang buf_si = buf_s; /* points to the beginning of k-th msg to be sent */ 41402257cef7SHong Zhang for (proc=0,k=0; proc<size; proc++) { 414102c68681SHong Zhang if (!len_s[proc]) continue; 41423e06a4e6SHong Zhang /* form outgoing message for i-structure: 41433e06a4e6SHong Zhang buf_si[0]: nrows to be sent 41443e06a4e6SHong Zhang [1:nrows]: row index (global) 41453e06a4e6SHong Zhang [nrows+1:2*nrows+1]: i-structure index 41463e06a4e6SHong Zhang */ 41473e06a4e6SHong Zhang /*-------------------------------------------*/ 41482257cef7SHong Zhang nrows = len_si[proc]/2 - 1; 41493e06a4e6SHong Zhang buf_si_i = buf_si + nrows+1; 41503e06a4e6SHong Zhang buf_si[0] = nrows; 41513e06a4e6SHong Zhang buf_si_i[0] = 0; 41523e06a4e6SHong Zhang nrows = 0; 41533e06a4e6SHong Zhang for (i=owners[proc]; i<owners[proc+1]; i++) { 41543e06a4e6SHong Zhang anzi = ai[i+1] - ai[i]; 41553e06a4e6SHong Zhang if (anzi) { 41563e06a4e6SHong Zhang buf_si_i[nrows+1] = buf_si_i[nrows] + anzi; /* i-structure */ 41573e06a4e6SHong Zhang buf_si[nrows+1] = i-owners[proc]; /* local row index */ 41583e06a4e6SHong Zhang nrows++; 41593e06a4e6SHong Zhang } 41603e06a4e6SHong Zhang } 4161b1d57f15SBarry Smith ierr = MPI_Isend(buf_si,len_si[proc],MPIU_INT,proc,tagi,comm,si_waits+k);CHKERRQ(ierr); 416202c68681SHong Zhang k++; 41632257cef7SHong Zhang buf_si += len_si[proc]; 416402c68681SHong Zhang } 41652257cef7SHong Zhang 41660c468ba9SBarry Smith if (merge->nrecv) {ierr = MPI_Waitall(merge->nrecv,ri_waits,status);CHKERRQ(ierr);} 41670c468ba9SBarry Smith if (merge->nsend) {ierr = MPI_Waitall(merge->nsend,si_waits,status);CHKERRQ(ierr);} 416802c68681SHong Zhang 4169ae15b995SBarry Smith ierr = PetscInfo2(seqmat,"nsend: %D, nrecv: %D\n",merge->nsend,merge->nrecv);CHKERRQ(ierr); 41703e06a4e6SHong Zhang for (i=0; i<merge->nrecv; i++) { 4171ae15b995SBarry 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); 41723e06a4e6SHong Zhang } 41733e06a4e6SHong Zhang 41743e06a4e6SHong Zhang ierr = PetscFree(len_si);CHKERRQ(ierr); 417502c68681SHong Zhang ierr = PetscFree(len_ri);CHKERRQ(ierr); 417602c68681SHong Zhang ierr = PetscFree(rj_waits);CHKERRQ(ierr); 41771d79065fSBarry Smith ierr = PetscFree2(si_waits,sj_waits);CHKERRQ(ierr); 41782257cef7SHong Zhang ierr = PetscFree(ri_waits);CHKERRQ(ierr); 41793e06a4e6SHong Zhang ierr = PetscFree(buf_s);CHKERRQ(ierr); 4180bcc1bcd5SHong Zhang ierr = PetscFree(status);CHKERRQ(ierr); 418158cb9c82SHong Zhang 4182bcc1bcd5SHong Zhang /* compute a local seq matrix in each processor */ 4183bcc1bcd5SHong Zhang /*----------------------------------------------*/ 418458cb9c82SHong Zhang /* allocate bi array and free space for accumulating nonzero column info */ 4185854ce69bSBarry Smith ierr = PetscMalloc1(m+1,&bi);CHKERRQ(ierr); 418658cb9c82SHong Zhang bi[0] = 0; 418758cb9c82SHong Zhang 4188be0fcf8dSHong Zhang /* create and initialize a linked list */ 4189be0fcf8dSHong Zhang nlnk = N+1; 4190be0fcf8dSHong Zhang ierr = PetscLLCreate(N,N,nlnk,lnk,lnkbt);CHKERRQ(ierr); 419158cb9c82SHong Zhang 4192bcc1bcd5SHong Zhang /* initial FreeSpace size is 2*(num of local nnz(seqmat)) */ 4193bcc1bcd5SHong Zhang len = ai[owners[rank+1]] - ai[owners[rank]]; 4194f91af8c7SBarry Smith ierr = PetscFreeSpaceGet(PetscIntMultTruncate(2,len)+1,&free_space);CHKERRQ(ierr); 41952205254eSKarl Rupp 419658cb9c82SHong Zhang current_space = free_space; 419758cb9c82SHong Zhang 4198bcc1bcd5SHong Zhang /* determine symbolic info for each local row */ 4199dcca6d9dSJed Brown ierr = PetscMalloc3(merge->nrecv,&buf_ri_k,merge->nrecv,&nextrow,merge->nrecv,&nextai);CHKERRQ(ierr); 42001d79065fSBarry Smith 42013e06a4e6SHong Zhang for (k=0; k<merge->nrecv; k++) { 42022257cef7SHong Zhang buf_ri_k[k] = buf_ri[k]; /* beginning of k-th recved i-structure */ 42033e06a4e6SHong Zhang nrows = *buf_ri_k[k]; 42043e06a4e6SHong Zhang nextrow[k] = buf_ri_k[k] + 1; /* next row number of k-th recved i-structure */ 42052257cef7SHong Zhang nextai[k] = buf_ri_k[k] + (nrows + 1); /* poins to the next i-structure of k-th recved i-structure */ 42063e06a4e6SHong Zhang } 42072257cef7SHong Zhang 4208bcc1bcd5SHong Zhang ierr = MatPreallocateInitialize(comm,m,n,dnz,onz);CHKERRQ(ierr); 4209bcc1bcd5SHong Zhang len = 0; 421058cb9c82SHong Zhang for (i=0; i<m; i++) { 421158cb9c82SHong Zhang bnzi = 0; 421258cb9c82SHong Zhang /* add local non-zero cols of this proc's seqmat into lnk */ 421358cb9c82SHong Zhang arow = owners[rank] + i; 421458cb9c82SHong Zhang anzi = ai[arow+1] - ai[arow]; 421558cb9c82SHong Zhang aj = a->j + ai[arow]; 4216dadf0e6bSHong Zhang ierr = PetscLLAddSorted(anzi,aj,N,nlnk,lnk,lnkbt);CHKERRQ(ierr); 421758cb9c82SHong Zhang bnzi += nlnk; 421858cb9c82SHong Zhang /* add received col data into lnk */ 421951a7d1a8SHong Zhang for (k=0; k<merge->nrecv; k++) { /* k-th received message */ 422055d1abb9SHong Zhang if (i == *nextrow[k]) { /* i-th row */ 42213e06a4e6SHong Zhang anzi = *(nextai[k]+1) - *nextai[k]; 42223e06a4e6SHong Zhang aj = buf_rj[k] + *nextai[k]; 4223dadf0e6bSHong Zhang ierr = PetscLLAddSorted(anzi,aj,N,nlnk,lnk,lnkbt);CHKERRQ(ierr); 42243e06a4e6SHong Zhang bnzi += nlnk; 42253e06a4e6SHong Zhang nextrow[k]++; nextai[k]++; 42263e06a4e6SHong Zhang } 422758cb9c82SHong Zhang } 4228bcc1bcd5SHong Zhang if (len < bnzi) len = bnzi; /* =max(bnzi) */ 422958cb9c82SHong Zhang 423058cb9c82SHong Zhang /* if free space is not available, make more free space */ 423158cb9c82SHong Zhang if (current_space->local_remaining<bnzi) { 4232f91af8c7SBarry Smith ierr = PetscFreeSpaceGet(PetscIntSumTruncate(bnzi,current_space->total_array_size),¤t_space);CHKERRQ(ierr); 423358cb9c82SHong Zhang nspacedouble++; 423458cb9c82SHong Zhang } 423558cb9c82SHong Zhang /* copy data into free space, then initialize lnk */ 4236be0fcf8dSHong Zhang ierr = PetscLLClean(N,N,bnzi,lnk,current_space->array,lnkbt);CHKERRQ(ierr); 4237bcc1bcd5SHong Zhang ierr = MatPreallocateSet(i+owners[rank],bnzi,current_space->array,dnz,onz);CHKERRQ(ierr); 4238bcc1bcd5SHong Zhang 423958cb9c82SHong Zhang current_space->array += bnzi; 424058cb9c82SHong Zhang current_space->local_used += bnzi; 424158cb9c82SHong Zhang current_space->local_remaining -= bnzi; 424258cb9c82SHong Zhang 424358cb9c82SHong Zhang bi[i+1] = bi[i] + bnzi; 424458cb9c82SHong Zhang } 4245bcc1bcd5SHong Zhang 42461d79065fSBarry Smith ierr = PetscFree3(buf_ri_k,nextrow,nextai);CHKERRQ(ierr); 4247bcc1bcd5SHong Zhang 4248854ce69bSBarry Smith ierr = PetscMalloc1(bi[m]+1,&bj);CHKERRQ(ierr); 4249a1a86e44SBarry Smith ierr = PetscFreeSpaceContiguous(&free_space,bj);CHKERRQ(ierr); 4250be0fcf8dSHong Zhang ierr = PetscLLDestroy(lnk,lnkbt);CHKERRQ(ierr); 4251409913e3SHong Zhang 4252bcc1bcd5SHong Zhang /* create symbolic parallel matrix B_mpi */ 4253bcc1bcd5SHong Zhang /*---------------------------------------*/ 4254a2f3521dSMark F. Adams ierr = MatGetBlockSizes(seqmat,&bs,&cbs);CHKERRQ(ierr); 4255f69a0ea3SMatthew Knepley ierr = MatCreate(comm,&B_mpi);CHKERRQ(ierr); 425654b84b50SHong Zhang if (n==PETSC_DECIDE) { 4257f69a0ea3SMatthew Knepley ierr = MatSetSizes(B_mpi,m,n,PETSC_DETERMINE,N);CHKERRQ(ierr); 425854b84b50SHong Zhang } else { 4259f69a0ea3SMatthew Knepley ierr = MatSetSizes(B_mpi,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 426054b84b50SHong Zhang } 4261a2f3521dSMark F. Adams ierr = MatSetBlockSizes(B_mpi,bs,cbs);CHKERRQ(ierr); 4262bcc1bcd5SHong Zhang ierr = MatSetType(B_mpi,MATMPIAIJ);CHKERRQ(ierr); 4263bcc1bcd5SHong Zhang ierr = MatMPIAIJSetPreallocation(B_mpi,0,dnz,0,onz);CHKERRQ(ierr); 4264bcc1bcd5SHong Zhang ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr); 42657e63b356SHong Zhang ierr = MatSetOption(B_mpi,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); 426658cb9c82SHong Zhang 426790431a8fSHong Zhang /* B_mpi is not ready for use - assembly will be done by MatCreateMPIAIJSumSeqAIJNumeric() */ 42686abd8857SHong Zhang B_mpi->assembled = PETSC_FALSE; 4269affca5deSHong Zhang B_mpi->ops->destroy = MatDestroy_MPIAIJ_SeqsToMPI; 4270affca5deSHong Zhang merge->bi = bi; 4271affca5deSHong Zhang merge->bj = bj; 427202c68681SHong Zhang merge->buf_ri = buf_ri; 427302c68681SHong Zhang merge->buf_rj = buf_rj; 42740298fd71SBarry Smith merge->coi = NULL; 42750298fd71SBarry Smith merge->coj = NULL; 42760298fd71SBarry Smith merge->owners_co = NULL; 4277affca5deSHong Zhang 4278bf0cc555SLisandro Dalcin ierr = PetscCommDestroy(&comm);CHKERRQ(ierr); 4279bf0cc555SLisandro Dalcin 4280affca5deSHong Zhang /* attach the supporting struct to B_mpi for reuse */ 4281776b82aeSLisandro Dalcin ierr = PetscContainerCreate(PETSC_COMM_SELF,&container);CHKERRQ(ierr); 4282776b82aeSLisandro Dalcin ierr = PetscContainerSetPointer(container,merge);CHKERRQ(ierr); 4283affca5deSHong Zhang ierr = PetscObjectCompose((PetscObject)B_mpi,"MatMergeSeqsToMPI",(PetscObject)container);CHKERRQ(ierr); 4284bf0cc555SLisandro Dalcin ierr = PetscContainerDestroy(&container);CHKERRQ(ierr); 4285affca5deSHong Zhang *mpimat = B_mpi; 428638f152feSBarry Smith 42874ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Seqstompisym,seqmat,0,0,0);CHKERRQ(ierr); 4288e5f2cdd8SHong Zhang PetscFunctionReturn(0); 4289e5f2cdd8SHong Zhang } 429025616d81SHong Zhang 429138f152feSBarry Smith #undef __FUNCT__ 429290431a8fSHong Zhang #define __FUNCT__ "MatCreateMPIAIJSumSeqAIJ" 4293d4036a1aSHong Zhang /*@C 42945f4d30c4SBarry Smith MatCreateMPIAIJSumSeqAIJ - Creates a MATMPIAIJ matrix by adding sequential 4295d4036a1aSHong Zhang matrices from each processor 4296d4036a1aSHong Zhang 4297d4036a1aSHong Zhang Collective on MPI_Comm 4298d4036a1aSHong Zhang 4299d4036a1aSHong Zhang Input Parameters: 4300d4036a1aSHong Zhang + comm - the communicators the parallel matrix will live on 4301d4036a1aSHong Zhang . seqmat - the input sequential matrices 4302d4036a1aSHong Zhang . m - number of local rows (or PETSC_DECIDE) 4303d4036a1aSHong Zhang . n - number of local columns (or PETSC_DECIDE) 4304d4036a1aSHong Zhang - scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 4305d4036a1aSHong Zhang 4306d4036a1aSHong Zhang Output Parameter: 4307d4036a1aSHong Zhang . mpimat - the parallel matrix generated 4308d4036a1aSHong Zhang 4309d4036a1aSHong Zhang Level: advanced 4310d4036a1aSHong Zhang 4311d4036a1aSHong Zhang Notes: 4312d4036a1aSHong Zhang The dimensions of the sequential matrix in each processor MUST be the same. 4313d4036a1aSHong Zhang The input seqmat is included into the container "Mat_Merge_SeqsToMPI", and will be 4314d4036a1aSHong Zhang destroyed when mpimat is destroyed. Call PetscObjectQuery() to access seqmat. 4315d4036a1aSHong Zhang @*/ 431690431a8fSHong Zhang PetscErrorCode MatCreateMPIAIJSumSeqAIJ(MPI_Comm comm,Mat seqmat,PetscInt m,PetscInt n,MatReuse scall,Mat *mpimat) 431755d1abb9SHong Zhang { 431855d1abb9SHong Zhang PetscErrorCode ierr; 43197e63b356SHong Zhang PetscMPIInt size; 432055d1abb9SHong Zhang 432155d1abb9SHong Zhang PetscFunctionBegin; 43227e63b356SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 43237e63b356SHong Zhang if (size == 1) { 43247e63b356SHong Zhang ierr = PetscLogEventBegin(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr); 43257e63b356SHong Zhang if (scall == MAT_INITIAL_MATRIX) { 43267e63b356SHong Zhang ierr = MatDuplicate(seqmat,MAT_COPY_VALUES,mpimat);CHKERRQ(ierr); 43277e63b356SHong Zhang } else { 43287e63b356SHong Zhang ierr = MatCopy(seqmat,*mpimat,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 43297e63b356SHong Zhang } 43307e63b356SHong Zhang ierr = PetscLogEventEnd(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr); 43317e63b356SHong Zhang PetscFunctionReturn(0); 43327e63b356SHong Zhang } 43334ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr); 433455d1abb9SHong Zhang if (scall == MAT_INITIAL_MATRIX) { 433590431a8fSHong Zhang ierr = MatCreateMPIAIJSumSeqAIJSymbolic(comm,seqmat,m,n,mpimat);CHKERRQ(ierr); 433655d1abb9SHong Zhang } 433790431a8fSHong Zhang ierr = MatCreateMPIAIJSumSeqAIJNumeric(seqmat,*mpimat);CHKERRQ(ierr); 43384ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Seqstompi,seqmat,0,0,0);CHKERRQ(ierr); 433955d1abb9SHong Zhang PetscFunctionReturn(0); 434055d1abb9SHong Zhang } 43414ebed01fSBarry Smith 434225616d81SHong Zhang #undef __FUNCT__ 43434a2b5492SBarry Smith #define __FUNCT__ "MatMPIAIJGetLocalMat" 4344bc08b0f1SBarry Smith /*@ 43455f4d30c4SBarry Smith MatMPIAIJGetLocalMat - Creates a SeqAIJ from a MATMPIAIJ matrix by taking all its local rows and putting them into a sequential vector with 43468661ff28SBarry Smith mlocal rows and n columns. Where mlocal is the row count obtained with MatGetLocalSize() and n is the global column count obtained 43478661ff28SBarry Smith with MatGetSize() 434825616d81SHong Zhang 434932fba14fSHong Zhang Not Collective 435025616d81SHong Zhang 435125616d81SHong Zhang Input Parameters: 435225616d81SHong Zhang + A - the matrix 435325616d81SHong Zhang . scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 435425616d81SHong Zhang 435525616d81SHong Zhang Output Parameter: 435625616d81SHong Zhang . A_loc - the local sequential matrix generated 435725616d81SHong Zhang 435825616d81SHong Zhang Level: developer 435925616d81SHong Zhang 4360ba264940SBarry Smith .seealso: MatGetOwnerShipRange(), MatMPIAIJGetLocalMatCondensed() 43618661ff28SBarry Smith 436225616d81SHong Zhang @*/ 43634a2b5492SBarry Smith PetscErrorCode MatMPIAIJGetLocalMat(Mat A,MatReuse scall,Mat *A_loc) 436425616d81SHong Zhang { 436525616d81SHong Zhang PetscErrorCode ierr; 436601b7ae99SHong Zhang Mat_MPIAIJ *mpimat=(Mat_MPIAIJ*)A->data; 4367b78526a6SJose E. Roman Mat_SeqAIJ *mat,*a,*b; 4368b78526a6SJose E. Roman PetscInt *ai,*aj,*bi,*bj,*cmap=mpimat->garray; 4369b78526a6SJose E. Roman MatScalar *aa,*ba,*cam; 4370a77337e4SBarry Smith PetscScalar *ca; 4371d0f46423SBarry Smith PetscInt am=A->rmap->n,i,j,k,cstart=A->cmap->rstart; 43725a7d977cSHong Zhang PetscInt *ci,*cj,col,ncols_d,ncols_o,jo; 43738661ff28SBarry Smith PetscBool match; 437470a9ba44SHong Zhang MPI_Comm comm; 437570a9ba44SHong Zhang PetscMPIInt size; 437625616d81SHong Zhang 437725616d81SHong Zhang PetscFunctionBegin; 4378251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&match);CHKERRQ(ierr); 43795f4d30c4SBarry Smith if (!match) SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_SUP,"Requires MATMPIAIJ matrix as input"); 438070a9ba44SHong Zhang ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 438170a9ba44SHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 438270a9ba44SHong Zhang if (size == 1 && scall == MAT_REUSE_MATRIX) PetscFunctionReturn(0); 438370a9ba44SHong Zhang 43844ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Getlocalmat,A,0,0,0);CHKERRQ(ierr); 4385b78526a6SJose E. Roman a = (Mat_SeqAIJ*)(mpimat->A)->data; 4386b78526a6SJose E. Roman b = (Mat_SeqAIJ*)(mpimat->B)->data; 4387b78526a6SJose E. Roman ai = a->i; aj = a->j; bi = b->i; bj = b->j; 4388b78526a6SJose E. Roman aa = a->a; ba = b->a; 438901b7ae99SHong Zhang if (scall == MAT_INITIAL_MATRIX) { 439070a9ba44SHong Zhang if (size == 1) { 439170a9ba44SHong Zhang ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,am,A->cmap->N,ai,aj,aa,A_loc);CHKERRQ(ierr); 439270a9ba44SHong Zhang PetscFunctionReturn(0); 439370a9ba44SHong Zhang } 439470a9ba44SHong Zhang 4395854ce69bSBarry Smith ierr = PetscMalloc1(1+am,&ci);CHKERRQ(ierr); 4396dea91ad1SHong Zhang ci[0] = 0; 439701b7ae99SHong Zhang for (i=0; i<am; i++) { 4398dea91ad1SHong Zhang ci[i+1] = ci[i] + (ai[i+1] - ai[i]) + (bi[i+1] - bi[i]); 439901b7ae99SHong Zhang } 4400854ce69bSBarry Smith ierr = PetscMalloc1(1+ci[am],&cj);CHKERRQ(ierr); 4401854ce69bSBarry Smith ierr = PetscMalloc1(1+ci[am],&ca);CHKERRQ(ierr); 4402dea91ad1SHong Zhang k = 0; 440301b7ae99SHong Zhang for (i=0; i<am; i++) { 44045a7d977cSHong Zhang ncols_o = bi[i+1] - bi[i]; 44055a7d977cSHong Zhang ncols_d = ai[i+1] - ai[i]; 440601b7ae99SHong Zhang /* off-diagonal portion of A */ 44075a7d977cSHong Zhang for (jo=0; jo<ncols_o; jo++) { 44085a7d977cSHong Zhang col = cmap[*bj]; 44095a7d977cSHong Zhang if (col >= cstart) break; 44105a7d977cSHong Zhang cj[k] = col; bj++; 44115a7d977cSHong Zhang ca[k++] = *ba++; 44125a7d977cSHong Zhang } 44135a7d977cSHong Zhang /* diagonal portion of A */ 44145a7d977cSHong Zhang for (j=0; j<ncols_d; j++) { 44155a7d977cSHong Zhang cj[k] = cstart + *aj++; 44165a7d977cSHong Zhang ca[k++] = *aa++; 44175a7d977cSHong Zhang } 44185a7d977cSHong Zhang /* off-diagonal portion of A */ 44195a7d977cSHong Zhang for (j=jo; j<ncols_o; j++) { 44205a7d977cSHong Zhang cj[k] = cmap[*bj++]; 44215a7d977cSHong Zhang ca[k++] = *ba++; 44225a7d977cSHong Zhang } 442325616d81SHong Zhang } 4424dea91ad1SHong Zhang /* put together the new matrix */ 4425d0f46423SBarry Smith ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,am,A->cmap->N,ci,cj,ca,A_loc);CHKERRQ(ierr); 4426dea91ad1SHong Zhang /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 4427dea91ad1SHong Zhang /* Since these are PETSc arrays, change flags to free them as necessary. */ 4428dea91ad1SHong Zhang mat = (Mat_SeqAIJ*)(*A_loc)->data; 4429e6b907acSBarry Smith mat->free_a = PETSC_TRUE; 4430e6b907acSBarry Smith mat->free_ij = PETSC_TRUE; 4431dea91ad1SHong Zhang mat->nonew = 0; 44325a7d977cSHong Zhang } else if (scall == MAT_REUSE_MATRIX) { 44335a7d977cSHong Zhang mat=(Mat_SeqAIJ*)(*A_loc)->data; 4434a77337e4SBarry Smith ci = mat->i; cj = mat->j; cam = mat->a; 44355a7d977cSHong Zhang for (i=0; i<am; i++) { 44365a7d977cSHong Zhang /* off-diagonal portion of A */ 44375a7d977cSHong Zhang ncols_o = bi[i+1] - bi[i]; 44385a7d977cSHong Zhang for (jo=0; jo<ncols_o; jo++) { 44395a7d977cSHong Zhang col = cmap[*bj]; 44405a7d977cSHong Zhang if (col >= cstart) break; 4441a77337e4SBarry Smith *cam++ = *ba++; bj++; 44425a7d977cSHong Zhang } 44435a7d977cSHong Zhang /* diagonal portion of A */ 4444ecc9b87dSHong Zhang ncols_d = ai[i+1] - ai[i]; 4445a77337e4SBarry Smith for (j=0; j<ncols_d; j++) *cam++ = *aa++; 44465a7d977cSHong Zhang /* off-diagonal portion of A */ 4447f33d1a9aSHong Zhang for (j=jo; j<ncols_o; j++) { 4448a77337e4SBarry Smith *cam++ = *ba++; bj++; 4449f33d1a9aSHong Zhang } 44505a7d977cSHong Zhang } 44518661ff28SBarry Smith } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid MatReuse %d",(int)scall); 44524ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Getlocalmat,A,0,0,0);CHKERRQ(ierr); 445325616d81SHong Zhang PetscFunctionReturn(0); 445425616d81SHong Zhang } 445525616d81SHong Zhang 445632fba14fSHong Zhang #undef __FUNCT__ 44574a2b5492SBarry Smith #define __FUNCT__ "MatMPIAIJGetLocalMatCondensed" 445832fba14fSHong Zhang /*@C 44595f4d30c4SBarry Smith MatMPIAIJGetLocalMatCondensed - Creates a SeqAIJ matrix from an MATMPIAIJ matrix by taking all its local rows and NON-ZERO columns 446032fba14fSHong Zhang 446132fba14fSHong Zhang Not Collective 446232fba14fSHong Zhang 446332fba14fSHong Zhang Input Parameters: 446432fba14fSHong Zhang + A - the matrix 446532fba14fSHong Zhang . scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 44660298fd71SBarry Smith - row, col - index sets of rows and columns to extract (or NULL) 446732fba14fSHong Zhang 446832fba14fSHong Zhang Output Parameter: 446932fba14fSHong Zhang . A_loc - the local sequential matrix generated 447032fba14fSHong Zhang 447132fba14fSHong Zhang Level: developer 447232fba14fSHong Zhang 4473ba264940SBarry Smith .seealso: MatGetOwnershipRange(), MatMPIAIJGetLocalMat() 4474ba264940SBarry Smith 447532fba14fSHong Zhang @*/ 44764a2b5492SBarry Smith PetscErrorCode MatMPIAIJGetLocalMatCondensed(Mat A,MatReuse scall,IS *row,IS *col,Mat *A_loc) 447732fba14fSHong Zhang { 447832fba14fSHong Zhang Mat_MPIAIJ *a=(Mat_MPIAIJ*)A->data; 447932fba14fSHong Zhang PetscErrorCode ierr; 448032fba14fSHong Zhang PetscInt i,start,end,ncols,nzA,nzB,*cmap,imark,*idx; 448132fba14fSHong Zhang IS isrowa,iscola; 448232fba14fSHong Zhang Mat *aloc; 44834a2b5492SBarry Smith PetscBool match; 448432fba14fSHong Zhang 448532fba14fSHong Zhang PetscFunctionBegin; 4486251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ,&match);CHKERRQ(ierr); 44875f4d30c4SBarry Smith if (!match) SETERRQ(PetscObjectComm((PetscObject)A), PETSC_ERR_SUP,"Requires MATMPIAIJ matrix as input"); 44884ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_Getlocalmatcondensed,A,0,0,0);CHKERRQ(ierr); 448932fba14fSHong Zhang if (!row) { 4490d0f46423SBarry Smith start = A->rmap->rstart; end = A->rmap->rend; 449132fba14fSHong Zhang ierr = ISCreateStride(PETSC_COMM_SELF,end-start,start,1,&isrowa);CHKERRQ(ierr); 449232fba14fSHong Zhang } else { 449332fba14fSHong Zhang isrowa = *row; 449432fba14fSHong Zhang } 449532fba14fSHong Zhang if (!col) { 4496d0f46423SBarry Smith start = A->cmap->rstart; 449732fba14fSHong Zhang cmap = a->garray; 4498d0f46423SBarry Smith nzA = a->A->cmap->n; 4499d0f46423SBarry Smith nzB = a->B->cmap->n; 4500854ce69bSBarry Smith ierr = PetscMalloc1(nzA+nzB, &idx);CHKERRQ(ierr); 450132fba14fSHong Zhang ncols = 0; 450232fba14fSHong Zhang for (i=0; i<nzB; i++) { 450332fba14fSHong Zhang if (cmap[i] < start) idx[ncols++] = cmap[i]; 450432fba14fSHong Zhang else break; 450532fba14fSHong Zhang } 450632fba14fSHong Zhang imark = i; 450732fba14fSHong Zhang for (i=0; i<nzA; i++) idx[ncols++] = start + i; 450832fba14fSHong Zhang for (i=imark; i<nzB; i++) idx[ncols++] = cmap[i]; 4509d67e408aSBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,ncols,idx,PETSC_OWN_POINTER,&iscola);CHKERRQ(ierr); 451032fba14fSHong Zhang } else { 451132fba14fSHong Zhang iscola = *col; 451232fba14fSHong Zhang } 451332fba14fSHong Zhang if (scall != MAT_INITIAL_MATRIX) { 4514854ce69bSBarry Smith ierr = PetscMalloc1(1,&aloc);CHKERRQ(ierr); 451532fba14fSHong Zhang aloc[0] = *A_loc; 451632fba14fSHong Zhang } 451732fba14fSHong Zhang ierr = MatGetSubMatrices(A,1,&isrowa,&iscola,scall,&aloc);CHKERRQ(ierr); 451832fba14fSHong Zhang *A_loc = aloc[0]; 451932fba14fSHong Zhang ierr = PetscFree(aloc);CHKERRQ(ierr); 452032fba14fSHong Zhang if (!row) { 45216bf464f9SBarry Smith ierr = ISDestroy(&isrowa);CHKERRQ(ierr); 452232fba14fSHong Zhang } 452332fba14fSHong Zhang if (!col) { 45246bf464f9SBarry Smith ierr = ISDestroy(&iscola);CHKERRQ(ierr); 452532fba14fSHong Zhang } 45264ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_Getlocalmatcondensed,A,0,0,0);CHKERRQ(ierr); 452732fba14fSHong Zhang PetscFunctionReturn(0); 452832fba14fSHong Zhang } 452932fba14fSHong Zhang 453025616d81SHong Zhang #undef __FUNCT__ 453125616d81SHong Zhang #define __FUNCT__ "MatGetBrowsOfAcols" 453225616d81SHong Zhang /*@C 453332fba14fSHong Zhang MatGetBrowsOfAcols - Creates a SeqAIJ matrix by taking rows of B that equal to nonzero columns of local A 453425616d81SHong Zhang 453525616d81SHong Zhang Collective on Mat 453625616d81SHong Zhang 453725616d81SHong Zhang Input Parameters: 4538e240928fSHong Zhang + A,B - the matrices in mpiaij format 453925616d81SHong Zhang . scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 45400298fd71SBarry Smith - rowb, colb - index sets of rows and columns of B to extract (or NULL) 454125616d81SHong Zhang 454225616d81SHong Zhang Output Parameter: 454325616d81SHong Zhang + rowb, colb - index sets of rows and columns of B to extract 454425616d81SHong Zhang - B_seq - the sequential matrix generated 454525616d81SHong Zhang 454625616d81SHong Zhang Level: developer 454725616d81SHong Zhang 454825616d81SHong Zhang @*/ 454966bfb163SHong Zhang PetscErrorCode MatGetBrowsOfAcols(Mat A,Mat B,MatReuse scall,IS *rowb,IS *colb,Mat *B_seq) 455025616d81SHong Zhang { 4551899cda47SBarry Smith Mat_MPIAIJ *a=(Mat_MPIAIJ*)A->data; 455225616d81SHong Zhang PetscErrorCode ierr; 4553b1d57f15SBarry Smith PetscInt *idx,i,start,ncols,nzA,nzB,*cmap,imark; 455425616d81SHong Zhang IS isrowb,iscolb; 45550298fd71SBarry Smith Mat *bseq=NULL; 455625616d81SHong Zhang 455725616d81SHong Zhang PetscFunctionBegin; 4558d0f46423SBarry Smith if (A->cmap->rstart != B->rmap->rstart || A->cmap->rend != B->rmap->rend) { 4559e32f2f54SBarry 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); 456025616d81SHong Zhang } 45614ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_GetBrowsOfAcols,A,B,0,0);CHKERRQ(ierr); 456225616d81SHong Zhang 456325616d81SHong Zhang if (scall == MAT_INITIAL_MATRIX) { 4564d0f46423SBarry Smith start = A->cmap->rstart; 456525616d81SHong Zhang cmap = a->garray; 4566d0f46423SBarry Smith nzA = a->A->cmap->n; 4567d0f46423SBarry Smith nzB = a->B->cmap->n; 4568854ce69bSBarry Smith ierr = PetscMalloc1(nzA+nzB, &idx);CHKERRQ(ierr); 456925616d81SHong Zhang ncols = 0; 45700390132cSHong Zhang for (i=0; i<nzB; i++) { /* row < local row index */ 457125616d81SHong Zhang if (cmap[i] < start) idx[ncols++] = cmap[i]; 457225616d81SHong Zhang else break; 457325616d81SHong Zhang } 457425616d81SHong Zhang imark = i; 45750390132cSHong Zhang for (i=0; i<nzA; i++) idx[ncols++] = start + i; /* local rows */ 45760390132cSHong Zhang for (i=imark; i<nzB; i++) idx[ncols++] = cmap[i]; /* row > local row index */ 4577d67e408aSBarry Smith ierr = ISCreateGeneral(PETSC_COMM_SELF,ncols,idx,PETSC_OWN_POINTER,&isrowb);CHKERRQ(ierr); 4578d0f46423SBarry Smith ierr = ISCreateStride(PETSC_COMM_SELF,B->cmap->N,0,1,&iscolb);CHKERRQ(ierr); 457925616d81SHong Zhang } else { 4580e32f2f54SBarry Smith if (!rowb || !colb) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"IS rowb and colb must be provided for MAT_REUSE_MATRIX"); 458125616d81SHong Zhang isrowb = *rowb; iscolb = *colb; 4582854ce69bSBarry Smith ierr = PetscMalloc1(1,&bseq);CHKERRQ(ierr); 458325616d81SHong Zhang bseq[0] = *B_seq; 458425616d81SHong Zhang } 458525616d81SHong Zhang ierr = MatGetSubMatrices(B,1,&isrowb,&iscolb,scall,&bseq);CHKERRQ(ierr); 458625616d81SHong Zhang *B_seq = bseq[0]; 458725616d81SHong Zhang ierr = PetscFree(bseq);CHKERRQ(ierr); 458825616d81SHong Zhang if (!rowb) { 45896bf464f9SBarry Smith ierr = ISDestroy(&isrowb);CHKERRQ(ierr); 459025616d81SHong Zhang } else { 459125616d81SHong Zhang *rowb = isrowb; 459225616d81SHong Zhang } 459325616d81SHong Zhang if (!colb) { 45946bf464f9SBarry Smith ierr = ISDestroy(&iscolb);CHKERRQ(ierr); 459525616d81SHong Zhang } else { 459625616d81SHong Zhang *colb = iscolb; 459725616d81SHong Zhang } 45984ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_GetBrowsOfAcols,A,B,0,0);CHKERRQ(ierr); 459925616d81SHong Zhang PetscFunctionReturn(0); 460025616d81SHong Zhang } 4601429d309bSHong Zhang 4602a61c8c0fSHong Zhang #undef __FUNCT__ 4603f8487c73SHong Zhang #define __FUNCT__ "MatGetBrowsOfAoCols_MPIAIJ" 4604f8487c73SHong Zhang /* 4605f8487c73SHong Zhang MatGetBrowsOfAoCols_MPIAIJ - Creates a SeqAIJ matrix by taking rows of B that equal to nonzero columns 460601b7ae99SHong Zhang of the OFF-DIAGONAL portion of local A 4607429d309bSHong Zhang 4608429d309bSHong Zhang Collective on Mat 4609429d309bSHong Zhang 4610429d309bSHong Zhang Input Parameters: 4611429d309bSHong Zhang + A,B - the matrices in mpiaij format 4612598bc09dSHong Zhang - scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX 4613429d309bSHong Zhang 4614429d309bSHong Zhang Output Parameter: 46150298fd71SBarry Smith + startsj_s - starting point in B's sending j-arrays, saved for MAT_REUSE (or NULL) 46160298fd71SBarry Smith . startsj_r - starting point in B's receiving j-arrays, saved for MAT_REUSE (or NULL) 46170298fd71SBarry Smith . bufa_ptr - array for sending matrix values, saved for MAT_REUSE (or NULL) 4618598bc09dSHong Zhang - B_oth - the sequential matrix generated with size aBn=a->B->cmap->n by B->cmap->N 4619429d309bSHong Zhang 4620429d309bSHong Zhang Level: developer 4621429d309bSHong Zhang 4622f8487c73SHong Zhang */ 4623b7f45c76SHong Zhang PetscErrorCode MatGetBrowsOfAoCols_MPIAIJ(Mat A,Mat B,MatReuse scall,PetscInt **startsj_s,PetscInt **startsj_r,MatScalar **bufa_ptr,Mat *B_oth) 4624429d309bSHong Zhang { 4625a6b2eed2SHong Zhang VecScatter_MPI_General *gen_to,*gen_from; 4626429d309bSHong Zhang PetscErrorCode ierr; 4627899cda47SBarry Smith Mat_MPIAIJ *a=(Mat_MPIAIJ*)A->data; 462887025532SHong Zhang Mat_SeqAIJ *b_oth; 4629a6b2eed2SHong Zhang VecScatter ctx =a->Mvctx; 4630ce94432eSBarry Smith MPI_Comm comm; 46317adad957SLisandro Dalcin PetscMPIInt *rprocs,*sprocs,tag=((PetscObject)ctx)->tag,rank; 4632d0f46423SBarry Smith PetscInt *rowlen,*bufj,*bufJ,ncols,aBn=a->B->cmap->n,row,*b_othi,*b_othj; 4633dd6ea824SBarry Smith PetscScalar *rvalues,*svalues; 4634dd6ea824SBarry Smith MatScalar *b_otha,*bufa,*bufA; 4635e42f35eeSHong Zhang PetscInt i,j,k,l,ll,nrecvs,nsends,nrows,*srow,*rstarts,*rstartsj = 0,*sstarts,*sstartsj,len; 46360298fd71SBarry Smith MPI_Request *rwaits = NULL,*swaits = NULL; 463787025532SHong Zhang MPI_Status *sstatus,rstatus; 4638a7c7454dSHong Zhang PetscMPIInt jj,size; 4639e42f35eeSHong Zhang PetscInt *cols,sbs,rbs; 4640ba8c8a56SBarry Smith PetscScalar *vals; 4641429d309bSHong Zhang 4642429d309bSHong Zhang PetscFunctionBegin; 4643ce94432eSBarry Smith ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr); 4644a7c7454dSHong Zhang ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 4645a7c7454dSHong Zhang 4646d0f46423SBarry Smith if (A->cmap->rstart != B->rmap->rstart || A->cmap->rend != B->rmap->rend) { 4647e32f2f54SBarry 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); 4648429d309bSHong Zhang } 46494ebed01fSBarry Smith ierr = PetscLogEventBegin(MAT_GetBrowsOfAocols,A,B,0,0);CHKERRQ(ierr); 4650a6b2eed2SHong Zhang ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 4651a6b2eed2SHong Zhang 4652a6b2eed2SHong Zhang gen_to = (VecScatter_MPI_General*)ctx->todata; 4653a6b2eed2SHong Zhang gen_from = (VecScatter_MPI_General*)ctx->fromdata; 4654e42f35eeSHong Zhang rvalues = gen_from->values; /* holds the length of receiving row */ 4655e42f35eeSHong Zhang svalues = gen_to->values; /* holds the length of sending row */ 4656a6b2eed2SHong Zhang nrecvs = gen_from->n; 4657a6b2eed2SHong Zhang nsends = gen_to->n; 4658d7ee0231SBarry Smith 4659dcca6d9dSJed Brown ierr = PetscMalloc2(nrecvs,&rwaits,nsends,&swaits);CHKERRQ(ierr); 4660a6b2eed2SHong Zhang srow = gen_to->indices; /* local row index to be sent */ 4661a6b2eed2SHong Zhang sstarts = gen_to->starts; 4662a6b2eed2SHong Zhang sprocs = gen_to->procs; 4663a6b2eed2SHong Zhang sstatus = gen_to->sstatus; 4664e42f35eeSHong Zhang sbs = gen_to->bs; 4665e42f35eeSHong Zhang rstarts = gen_from->starts; 4666e42f35eeSHong Zhang rprocs = gen_from->procs; 4667e42f35eeSHong Zhang rbs = gen_from->bs; 4668429d309bSHong Zhang 4669b7f45c76SHong Zhang if (!startsj_s || !bufa_ptr) scall = MAT_INITIAL_MATRIX; 4670429d309bSHong Zhang if (scall == MAT_INITIAL_MATRIX) { 4671a6b2eed2SHong Zhang /* i-array */ 4672a6b2eed2SHong Zhang /*---------*/ 4673a6b2eed2SHong Zhang /* post receives */ 4674a6b2eed2SHong Zhang for (i=0; i<nrecvs; i++) { 4675e42f35eeSHong Zhang rowlen = (PetscInt*)rvalues + rstarts[i]*rbs; 4676e42f35eeSHong Zhang nrows = (rstarts[i+1]-rstarts[i])*rbs; /* num of indices to be received */ 467787025532SHong Zhang ierr = MPI_Irecv(rowlen,nrows,MPIU_INT,rprocs[i],tag,comm,rwaits+i);CHKERRQ(ierr); 4678429d309bSHong Zhang } 4679a6b2eed2SHong Zhang 4680a6b2eed2SHong Zhang /* pack the outgoing message */ 4681dcca6d9dSJed Brown ierr = PetscMalloc2(nsends+1,&sstartsj,nrecvs+1,&rstartsj);CHKERRQ(ierr); 46822205254eSKarl Rupp 46832205254eSKarl Rupp sstartsj[0] = 0; 46842205254eSKarl Rupp rstartsj[0] = 0; 4685a6b2eed2SHong Zhang len = 0; /* total length of j or a array to be sent */ 4686a6b2eed2SHong Zhang k = 0; 4687a6b2eed2SHong Zhang for (i=0; i<nsends; i++) { 4688e42f35eeSHong Zhang rowlen = (PetscInt*)svalues + sstarts[i]*sbs; 4689e42f35eeSHong Zhang nrows = sstarts[i+1]-sstarts[i]; /* num of block rows */ 469087025532SHong Zhang for (j=0; j<nrows; j++) { 4691d0f46423SBarry Smith row = srow[k] + B->rmap->range[rank]; /* global row idx */ 4692e42f35eeSHong Zhang for (l=0; l<sbs; l++) { 46930298fd71SBarry Smith ierr = MatGetRow_MPIAIJ(B,row+l,&ncols,NULL,NULL);CHKERRQ(ierr); /* rowlength */ 46942205254eSKarl Rupp 4695e42f35eeSHong Zhang rowlen[j*sbs+l] = ncols; 46962205254eSKarl Rupp 4697e42f35eeSHong Zhang len += ncols; 46980298fd71SBarry Smith ierr = MatRestoreRow_MPIAIJ(B,row+l,&ncols,NULL,NULL);CHKERRQ(ierr); 4699e42f35eeSHong Zhang } 4700a6b2eed2SHong Zhang k++; 4701429d309bSHong Zhang } 4702e42f35eeSHong Zhang ierr = MPI_Isend(rowlen,nrows*sbs,MPIU_INT,sprocs[i],tag,comm,swaits+i);CHKERRQ(ierr); 47032205254eSKarl Rupp 4704dea91ad1SHong Zhang sstartsj[i+1] = len; /* starting point of (i+1)-th outgoing msg in bufj and bufa */ 4705429d309bSHong Zhang } 470687025532SHong Zhang /* recvs and sends of i-array are completed */ 470787025532SHong Zhang i = nrecvs; 470887025532SHong Zhang while (i--) { 4709aa5bb8c0SSatish Balay ierr = MPI_Waitany(nrecvs,rwaits,&jj,&rstatus);CHKERRQ(ierr); 471087025532SHong Zhang } 47110c468ba9SBarry Smith if (nsends) {ierr = MPI_Waitall(nsends,swaits,sstatus);CHKERRQ(ierr);} 4712e42f35eeSHong Zhang 4713a6b2eed2SHong Zhang /* allocate buffers for sending j and a arrays */ 4714854ce69bSBarry Smith ierr = PetscMalloc1(len+1,&bufj);CHKERRQ(ierr); 4715854ce69bSBarry Smith ierr = PetscMalloc1(len+1,&bufa);CHKERRQ(ierr); 4716a6b2eed2SHong Zhang 471787025532SHong Zhang /* create i-array of B_oth */ 4718854ce69bSBarry Smith ierr = PetscMalloc1(aBn+2,&b_othi);CHKERRQ(ierr); 47192205254eSKarl Rupp 472087025532SHong Zhang b_othi[0] = 0; 4721a6b2eed2SHong Zhang len = 0; /* total length of j or a array to be received */ 4722a6b2eed2SHong Zhang k = 0; 4723a6b2eed2SHong Zhang for (i=0; i<nrecvs; i++) { 4724fd0ff01cSHong Zhang rowlen = (PetscInt*)rvalues + rstarts[i]*rbs; 4725f91af8c7SBarry Smith nrows = rbs*(rstarts[i+1]-rstarts[i]); /* num of rows to be received */ 472687025532SHong Zhang for (j=0; j<nrows; j++) { 472787025532SHong Zhang b_othi[k+1] = b_othi[k] + rowlen[j]; 4728f416af30SBarry Smith ierr = PetscIntSumError(rowlen[j],len,&len);CHKERRQ(ierr); 4729f91af8c7SBarry Smith k++; 4730a6b2eed2SHong Zhang } 4731dea91ad1SHong Zhang rstartsj[i+1] = len; /* starting point of (i+1)-th incoming msg in bufj and bufa */ 4732a6b2eed2SHong Zhang } 4733a6b2eed2SHong Zhang 473487025532SHong Zhang /* allocate space for j and a arrrays of B_oth */ 4735854ce69bSBarry Smith ierr = PetscMalloc1(b_othi[aBn]+1,&b_othj);CHKERRQ(ierr); 4736854ce69bSBarry Smith ierr = PetscMalloc1(b_othi[aBn]+1,&b_otha);CHKERRQ(ierr); 4737a6b2eed2SHong Zhang 473887025532SHong Zhang /* j-array */ 473987025532SHong Zhang /*---------*/ 4740a6b2eed2SHong Zhang /* post receives of j-array */ 4741a6b2eed2SHong Zhang for (i=0; i<nrecvs; i++) { 474287025532SHong Zhang nrows = rstartsj[i+1]-rstartsj[i]; /* length of the msg received */ 474387025532SHong Zhang ierr = MPI_Irecv(b_othj+rstartsj[i],nrows,MPIU_INT,rprocs[i],tag,comm,rwaits+i);CHKERRQ(ierr); 4744a6b2eed2SHong Zhang } 4745e42f35eeSHong Zhang 4746e42f35eeSHong Zhang /* pack the outgoing message j-array */ 4747a6b2eed2SHong Zhang k = 0; 4748a6b2eed2SHong Zhang for (i=0; i<nsends; i++) { 4749e42f35eeSHong Zhang nrows = sstarts[i+1]-sstarts[i]; /* num of block rows */ 4750a6b2eed2SHong Zhang bufJ = bufj+sstartsj[i]; 475187025532SHong Zhang for (j=0; j<nrows; j++) { 4752d0f46423SBarry Smith row = srow[k++] + B->rmap->range[rank]; /* global row idx */ 4753e42f35eeSHong Zhang for (ll=0; ll<sbs; ll++) { 47540298fd71SBarry Smith ierr = MatGetRow_MPIAIJ(B,row+ll,&ncols,&cols,NULL);CHKERRQ(ierr); 4755a6b2eed2SHong Zhang for (l=0; l<ncols; l++) { 4756a6b2eed2SHong Zhang *bufJ++ = cols[l]; 475787025532SHong Zhang } 47580298fd71SBarry Smith ierr = MatRestoreRow_MPIAIJ(B,row+ll,&ncols,&cols,NULL);CHKERRQ(ierr); 4759e42f35eeSHong Zhang } 476087025532SHong Zhang } 476187025532SHong Zhang ierr = MPI_Isend(bufj+sstartsj[i],sstartsj[i+1]-sstartsj[i],MPIU_INT,sprocs[i],tag,comm,swaits+i);CHKERRQ(ierr); 476287025532SHong Zhang } 476387025532SHong Zhang 476487025532SHong Zhang /* recvs and sends of j-array are completed */ 476587025532SHong Zhang i = nrecvs; 476687025532SHong Zhang while (i--) { 4767aa5bb8c0SSatish Balay ierr = MPI_Waitany(nrecvs,rwaits,&jj,&rstatus);CHKERRQ(ierr); 476887025532SHong Zhang } 47690c468ba9SBarry Smith if (nsends) {ierr = MPI_Waitall(nsends,swaits,sstatus);CHKERRQ(ierr);} 477087025532SHong Zhang } else if (scall == MAT_REUSE_MATRIX) { 4771b7f45c76SHong Zhang sstartsj = *startsj_s; 47721d79065fSBarry Smith rstartsj = *startsj_r; 477387025532SHong Zhang bufa = *bufa_ptr; 477487025532SHong Zhang b_oth = (Mat_SeqAIJ*)(*B_oth)->data; 477587025532SHong Zhang b_otha = b_oth->a; 4776f23aa3ddSBarry Smith } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Matrix P does not posses an object container"); 477787025532SHong Zhang 477887025532SHong Zhang /* a-array */ 477987025532SHong Zhang /*---------*/ 478087025532SHong Zhang /* post receives of a-array */ 478187025532SHong Zhang for (i=0; i<nrecvs; i++) { 478287025532SHong Zhang nrows = rstartsj[i+1]-rstartsj[i]; /* length of the msg received */ 478387025532SHong Zhang ierr = MPI_Irecv(b_otha+rstartsj[i],nrows,MPIU_SCALAR,rprocs[i],tag,comm,rwaits+i);CHKERRQ(ierr); 478487025532SHong Zhang } 4785e42f35eeSHong Zhang 4786e42f35eeSHong Zhang /* pack the outgoing message a-array */ 478787025532SHong Zhang k = 0; 478887025532SHong Zhang for (i=0; i<nsends; i++) { 4789e42f35eeSHong Zhang nrows = sstarts[i+1]-sstarts[i]; /* num of block rows */ 479087025532SHong Zhang bufA = bufa+sstartsj[i]; 479187025532SHong Zhang for (j=0; j<nrows; j++) { 4792d0f46423SBarry Smith row = srow[k++] + B->rmap->range[rank]; /* global row idx */ 4793e42f35eeSHong Zhang for (ll=0; ll<sbs; ll++) { 47940298fd71SBarry Smith ierr = MatGetRow_MPIAIJ(B,row+ll,&ncols,NULL,&vals);CHKERRQ(ierr); 479587025532SHong Zhang for (l=0; l<ncols; l++) { 4796a6b2eed2SHong Zhang *bufA++ = vals[l]; 4797a6b2eed2SHong Zhang } 47980298fd71SBarry Smith ierr = MatRestoreRow_MPIAIJ(B,row+ll,&ncols,NULL,&vals);CHKERRQ(ierr); 4799e42f35eeSHong Zhang } 4800a6b2eed2SHong Zhang } 480187025532SHong Zhang ierr = MPI_Isend(bufa+sstartsj[i],sstartsj[i+1]-sstartsj[i],MPIU_SCALAR,sprocs[i],tag,comm,swaits+i);CHKERRQ(ierr); 4802a6b2eed2SHong Zhang } 480387025532SHong Zhang /* recvs and sends of a-array are completed */ 480487025532SHong Zhang i = nrecvs; 480587025532SHong Zhang while (i--) { 4806aa5bb8c0SSatish Balay ierr = MPI_Waitany(nrecvs,rwaits,&jj,&rstatus);CHKERRQ(ierr); 480787025532SHong Zhang } 48080c468ba9SBarry Smith if (nsends) {ierr = MPI_Waitall(nsends,swaits,sstatus);CHKERRQ(ierr);} 4809d7ee0231SBarry Smith ierr = PetscFree2(rwaits,swaits);CHKERRQ(ierr); 4810a6b2eed2SHong Zhang 481187025532SHong Zhang if (scall == MAT_INITIAL_MATRIX) { 4812a6b2eed2SHong Zhang /* put together the new matrix */ 4813d0f46423SBarry Smith ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,aBn,B->cmap->N,b_othi,b_othj,b_otha,B_oth);CHKERRQ(ierr); 4814a6b2eed2SHong Zhang 4815a6b2eed2SHong Zhang /* MatCreateSeqAIJWithArrays flags matrix so PETSc doesn't free the user's arrays. */ 4816a6b2eed2SHong Zhang /* Since these are PETSc arrays, change flags to free them as necessary. */ 481787025532SHong Zhang b_oth = (Mat_SeqAIJ*)(*B_oth)->data; 4818e6b907acSBarry Smith b_oth->free_a = PETSC_TRUE; 4819e6b907acSBarry Smith b_oth->free_ij = PETSC_TRUE; 482087025532SHong Zhang b_oth->nonew = 0; 4821a6b2eed2SHong Zhang 4822a6b2eed2SHong Zhang ierr = PetscFree(bufj);CHKERRQ(ierr); 4823b7f45c76SHong Zhang if (!startsj_s || !bufa_ptr) { 48241d79065fSBarry Smith ierr = PetscFree2(sstartsj,rstartsj);CHKERRQ(ierr); 4825dea91ad1SHong Zhang ierr = PetscFree(bufa_ptr);CHKERRQ(ierr); 4826dea91ad1SHong Zhang } else { 4827b7f45c76SHong Zhang *startsj_s = sstartsj; 48281d79065fSBarry Smith *startsj_r = rstartsj; 482987025532SHong Zhang *bufa_ptr = bufa; 483087025532SHong Zhang } 4831dea91ad1SHong Zhang } 48324ebed01fSBarry Smith ierr = PetscLogEventEnd(MAT_GetBrowsOfAocols,A,B,0,0);CHKERRQ(ierr); 4833429d309bSHong Zhang PetscFunctionReturn(0); 4834429d309bSHong Zhang } 4835ccd8e176SBarry Smith 483643eb5e2fSMatthew Knepley #undef __FUNCT__ 483743eb5e2fSMatthew Knepley #define __FUNCT__ "MatGetCommunicationStructs" 483843eb5e2fSMatthew Knepley /*@C 483943eb5e2fSMatthew Knepley MatGetCommunicationStructs - Provides access to the communication structures used in matrix-vector multiplication. 484043eb5e2fSMatthew Knepley 484143eb5e2fSMatthew Knepley Not Collective 484243eb5e2fSMatthew Knepley 484343eb5e2fSMatthew Knepley Input Parameters: 484443eb5e2fSMatthew Knepley . A - The matrix in mpiaij format 484543eb5e2fSMatthew Knepley 484643eb5e2fSMatthew Knepley Output Parameter: 484743eb5e2fSMatthew Knepley + lvec - The local vector holding off-process values from the argument to a matrix-vector product 484843eb5e2fSMatthew Knepley . colmap - A map from global column index to local index into lvec 484943eb5e2fSMatthew Knepley - multScatter - A scatter from the argument of a matrix-vector product to lvec 485043eb5e2fSMatthew Knepley 485143eb5e2fSMatthew Knepley Level: developer 485243eb5e2fSMatthew Knepley 485343eb5e2fSMatthew Knepley @*/ 485443eb5e2fSMatthew Knepley #if defined(PETSC_USE_CTABLE) 48557087cfbeSBarry Smith PetscErrorCode MatGetCommunicationStructs(Mat A, Vec *lvec, PetscTable *colmap, VecScatter *multScatter) 485643eb5e2fSMatthew Knepley #else 48577087cfbeSBarry Smith PetscErrorCode MatGetCommunicationStructs(Mat A, Vec *lvec, PetscInt *colmap[], VecScatter *multScatter) 485843eb5e2fSMatthew Knepley #endif 485943eb5e2fSMatthew Knepley { 486043eb5e2fSMatthew Knepley Mat_MPIAIJ *a; 486143eb5e2fSMatthew Knepley 486243eb5e2fSMatthew Knepley PetscFunctionBegin; 48630700a824SBarry Smith PetscValidHeaderSpecific(A, MAT_CLASSID, 1); 4864e414b56bSJed Brown PetscValidPointer(lvec, 2); 4865e414b56bSJed Brown PetscValidPointer(colmap, 3); 4866e414b56bSJed Brown PetscValidPointer(multScatter, 4); 486743eb5e2fSMatthew Knepley a = (Mat_MPIAIJ*) A->data; 486843eb5e2fSMatthew Knepley if (lvec) *lvec = a->lvec; 486943eb5e2fSMatthew Knepley if (colmap) *colmap = a->colmap; 487043eb5e2fSMatthew Knepley if (multScatter) *multScatter = a->Mvctx; 487143eb5e2fSMatthew Knepley PetscFunctionReturn(0); 487243eb5e2fSMatthew Knepley } 487343eb5e2fSMatthew Knepley 4874cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPIAIJCRL(Mat,MatType,MatReuse,Mat*); 4875cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPIAIJPERM(Mat,MatType,MatReuse,Mat*); 4876cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_MPISBAIJ(Mat,MatType,MatReuse,Mat*); 48775d7652ecSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 4878cc2e6a90SBarry Smith PETSC_INTERN PetscErrorCode MatConvert_MPIAIJ_Elemental(Mat,MatType,MatReuse,Mat*); 48795d7652ecSHong Zhang #endif 488017667f90SBarry Smith 4881fc4dec0aSBarry Smith #undef __FUNCT__ 4882fc4dec0aSBarry Smith #define __FUNCT__ "MatMatMultNumeric_MPIDense_MPIAIJ" 4883fc4dec0aSBarry Smith /* 4884fc4dec0aSBarry Smith Computes (B'*A')' since computing B*A directly is untenable 4885fc4dec0aSBarry Smith 4886fc4dec0aSBarry Smith n p p 4887fc4dec0aSBarry Smith ( ) ( ) ( ) 4888fc4dec0aSBarry Smith m ( A ) * n ( B ) = m ( C ) 4889fc4dec0aSBarry Smith ( ) ( ) ( ) 4890fc4dec0aSBarry Smith 4891fc4dec0aSBarry Smith */ 4892fc4dec0aSBarry Smith PetscErrorCode MatMatMultNumeric_MPIDense_MPIAIJ(Mat A,Mat B,Mat C) 4893fc4dec0aSBarry Smith { 4894fc4dec0aSBarry Smith PetscErrorCode ierr; 4895fc4dec0aSBarry Smith Mat At,Bt,Ct; 4896fc4dec0aSBarry Smith 4897fc4dec0aSBarry Smith PetscFunctionBegin; 4898fc4dec0aSBarry Smith ierr = MatTranspose(A,MAT_INITIAL_MATRIX,&At);CHKERRQ(ierr); 4899fc4dec0aSBarry Smith ierr = MatTranspose(B,MAT_INITIAL_MATRIX,&Bt);CHKERRQ(ierr); 4900fc4dec0aSBarry Smith ierr = MatMatMult(Bt,At,MAT_INITIAL_MATRIX,1.0,&Ct);CHKERRQ(ierr); 49016bf464f9SBarry Smith ierr = MatDestroy(&At);CHKERRQ(ierr); 49026bf464f9SBarry Smith ierr = MatDestroy(&Bt);CHKERRQ(ierr); 4903fc4dec0aSBarry Smith ierr = MatTranspose(Ct,MAT_REUSE_MATRIX,&C);CHKERRQ(ierr); 49046bf464f9SBarry Smith ierr = MatDestroy(&Ct);CHKERRQ(ierr); 4905fc4dec0aSBarry Smith PetscFunctionReturn(0); 4906fc4dec0aSBarry Smith } 4907fc4dec0aSBarry Smith 4908fc4dec0aSBarry Smith #undef __FUNCT__ 4909fc4dec0aSBarry Smith #define __FUNCT__ "MatMatMultSymbolic_MPIDense_MPIAIJ" 4910fc4dec0aSBarry Smith PetscErrorCode MatMatMultSymbolic_MPIDense_MPIAIJ(Mat A,Mat B,PetscReal fill,Mat *C) 4911fc4dec0aSBarry Smith { 4912fc4dec0aSBarry Smith PetscErrorCode ierr; 4913d0f46423SBarry Smith PetscInt m=A->rmap->n,n=B->cmap->n; 4914fc4dec0aSBarry Smith Mat Cmat; 4915fc4dec0aSBarry Smith 4916fc4dec0aSBarry Smith PetscFunctionBegin; 4917e32f2f54SBarry 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); 4918ce94432eSBarry Smith ierr = MatCreate(PetscObjectComm((PetscObject)A),&Cmat);CHKERRQ(ierr); 4919fc4dec0aSBarry Smith ierr = MatSetSizes(Cmat,m,n,PETSC_DETERMINE,PETSC_DETERMINE);CHKERRQ(ierr); 492033d57670SJed Brown ierr = MatSetBlockSizesFromMats(Cmat,A,B);CHKERRQ(ierr); 4921fc4dec0aSBarry Smith ierr = MatSetType(Cmat,MATMPIDENSE);CHKERRQ(ierr); 49220298fd71SBarry Smith ierr = MatMPIDenseSetPreallocation(Cmat,NULL);CHKERRQ(ierr); 492338556019SBarry Smith ierr = MatAssemblyBegin(Cmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 492438556019SBarry Smith ierr = MatAssemblyEnd(Cmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 4925f75ecaa4SHong Zhang 4926f75ecaa4SHong Zhang Cmat->ops->matmultnumeric = MatMatMultNumeric_MPIDense_MPIAIJ; 49272205254eSKarl Rupp 4928fc4dec0aSBarry Smith *C = Cmat; 4929fc4dec0aSBarry Smith PetscFunctionReturn(0); 4930fc4dec0aSBarry Smith } 4931fc4dec0aSBarry Smith 4932fc4dec0aSBarry Smith /* ----------------------------------------------------------------*/ 4933fc4dec0aSBarry Smith #undef __FUNCT__ 4934fc4dec0aSBarry Smith #define __FUNCT__ "MatMatMult_MPIDense_MPIAIJ" 4935150d2497SBarry Smith PETSC_INTERN PetscErrorCode MatMatMult_MPIDense_MPIAIJ(Mat A,Mat B,MatReuse scall,PetscReal fill,Mat *C) 4936fc4dec0aSBarry Smith { 4937fc4dec0aSBarry Smith PetscErrorCode ierr; 4938fc4dec0aSBarry Smith 4939fc4dec0aSBarry Smith PetscFunctionBegin; 4940fc4dec0aSBarry Smith if (scall == MAT_INITIAL_MATRIX) { 49413ff4c91cSHong Zhang ierr = PetscLogEventBegin(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 4942fc4dec0aSBarry Smith ierr = MatMatMultSymbolic_MPIDense_MPIAIJ(A,B,fill,C);CHKERRQ(ierr); 49433ff4c91cSHong Zhang ierr = PetscLogEventEnd(MAT_MatMultSymbolic,A,B,0,0);CHKERRQ(ierr); 4944fc4dec0aSBarry Smith } 49453ff4c91cSHong Zhang ierr = PetscLogEventBegin(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 4946fc4dec0aSBarry Smith ierr = MatMatMultNumeric_MPIDense_MPIAIJ(A,B,*C);CHKERRQ(ierr); 49473ff4c91cSHong Zhang ierr = PetscLogEventEnd(MAT_MatMultNumeric,A,B,0,0);CHKERRQ(ierr); 4948fc4dec0aSBarry Smith PetscFunctionReturn(0); 4949fc4dec0aSBarry Smith } 4950fc4dec0aSBarry Smith 4951ccd8e176SBarry Smith /*MC 4952ccd8e176SBarry Smith MATMPIAIJ - MATMPIAIJ = "mpiaij" - A matrix type to be used for parallel sparse matrices. 4953ccd8e176SBarry Smith 4954ccd8e176SBarry Smith Options Database Keys: 4955ccd8e176SBarry Smith . -mat_type mpiaij - sets the matrix type to "mpiaij" during a call to MatSetFromOptions() 4956ccd8e176SBarry Smith 4957ccd8e176SBarry Smith Level: beginner 4958ccd8e176SBarry Smith 495969b1f4b7SBarry Smith .seealso: MatCreateAIJ() 4960ccd8e176SBarry Smith M*/ 4961ccd8e176SBarry Smith 4962ccd8e176SBarry Smith #undef __FUNCT__ 4963ccd8e176SBarry Smith #define __FUNCT__ "MatCreate_MPIAIJ" 49648cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_MPIAIJ(Mat B) 4965ccd8e176SBarry Smith { 4966ccd8e176SBarry Smith Mat_MPIAIJ *b; 4967ccd8e176SBarry Smith PetscErrorCode ierr; 4968ccd8e176SBarry Smith PetscMPIInt size; 4969ccd8e176SBarry Smith 4970ccd8e176SBarry Smith PetscFunctionBegin; 4971ce94432eSBarry Smith ierr = MPI_Comm_size(PetscObjectComm((PetscObject)B),&size);CHKERRQ(ierr); 49722205254eSKarl Rupp 4973b00a9115SJed Brown ierr = PetscNewLog(B,&b);CHKERRQ(ierr); 4974ccd8e176SBarry Smith B->data = (void*)b; 4975ccd8e176SBarry Smith ierr = PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));CHKERRQ(ierr); 4976ccd8e176SBarry Smith B->assembled = PETSC_FALSE; 4977ccd8e176SBarry Smith B->insertmode = NOT_SET_VALUES; 4978ccd8e176SBarry Smith b->size = size; 49792205254eSKarl Rupp 4980ce94432eSBarry Smith ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)B),&b->rank);CHKERRQ(ierr); 4981ccd8e176SBarry Smith 4982ccd8e176SBarry Smith /* build cache for off array entries formed */ 4983ce94432eSBarry Smith ierr = MatStashCreate_Private(PetscObjectComm((PetscObject)B),1,&B->stash);CHKERRQ(ierr); 49842205254eSKarl Rupp 4985ccd8e176SBarry Smith b->donotstash = PETSC_FALSE; 4986ccd8e176SBarry Smith b->colmap = 0; 4987ccd8e176SBarry Smith b->garray = 0; 4988ccd8e176SBarry Smith b->roworiented = PETSC_TRUE; 4989ccd8e176SBarry Smith 4990ccd8e176SBarry Smith /* stuff used for matrix vector multiply */ 49910298fd71SBarry Smith b->lvec = NULL; 49920298fd71SBarry Smith b->Mvctx = NULL; 4993ccd8e176SBarry Smith 4994ccd8e176SBarry Smith /* stuff for MatGetRow() */ 4995ccd8e176SBarry Smith b->rowindices = 0; 4996ccd8e176SBarry Smith b->rowvalues = 0; 4997ccd8e176SBarry Smith b->getrowactive = PETSC_FALSE; 4998ccd8e176SBarry Smith 4999bbf3fe20SPaul Mullowney /* flexible pointer used in CUSP/CUSPARSE classes */ 50000298fd71SBarry Smith b->spptr = NULL; 5001f60c3dc2SHong Zhang 5002b1b1104fSBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMPIAIJSetUseScalableIncreaseOverlap_C",MatMPIAIJSetUseScalableIncreaseOverlap_MPIAIJ);CHKERRQ(ierr); 5003bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatStoreValues_C",MatStoreValues_MPIAIJ);CHKERRQ(ierr); 5004bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatRetrieveValues_C",MatRetrieveValues_MPIAIJ);CHKERRQ(ierr); 5005bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatIsTranspose_C",MatIsTranspose_MPIAIJ);CHKERRQ(ierr); 5006bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMPIAIJSetPreallocation_C",MatMPIAIJSetPreallocation_MPIAIJ);CHKERRQ(ierr); 5007bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMPIAIJSetPreallocationCSR_C",MatMPIAIJSetPreallocationCSR_MPIAIJ);CHKERRQ(ierr); 5008bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatDiagonalScaleLocal_C",MatDiagonalScaleLocal_MPIAIJ);CHKERRQ(ierr); 5009bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_mpiaijperm_C",MatConvert_MPIAIJ_MPIAIJPERM);CHKERRQ(ierr); 5010bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_mpiaijcrl_C",MatConvert_MPIAIJ_MPIAIJCRL);CHKERRQ(ierr); 5011bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_mpisbaij_C",MatConvert_MPIAIJ_MPISBAIJ);CHKERRQ(ierr); 50125d7652ecSHong Zhang #if defined(PETSC_HAVE_ELEMENTAL) 50135d7652ecSHong Zhang ierr = PetscObjectComposeFunction((PetscObject)B,"MatConvert_mpiaij_elemental_C",MatConvert_MPIAIJ_Elemental);CHKERRQ(ierr); 50145d7652ecSHong Zhang #endif 5015bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMult_mpidense_mpiaij_C",MatMatMult_MPIDense_MPIAIJ);CHKERRQ(ierr); 5016bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultSymbolic_mpidense_mpiaij_C",MatMatMultSymbolic_MPIDense_MPIAIJ);CHKERRQ(ierr); 5017bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)B,"MatMatMultNumeric_mpidense_mpiaij_C",MatMatMultNumeric_MPIDense_MPIAIJ);CHKERRQ(ierr); 501817667f90SBarry Smith ierr = PetscObjectChangeTypeName((PetscObject)B,MATMPIAIJ);CHKERRQ(ierr); 5019ccd8e176SBarry Smith PetscFunctionReturn(0); 5020ccd8e176SBarry Smith } 502181824310SBarry Smith 502203bfb495SBarry Smith #undef __FUNCT__ 502303bfb495SBarry Smith #define __FUNCT__ "MatCreateMPIAIJWithSplitArrays" 5024e72c4023SBarry Smith /*@C 502503bfb495SBarry Smith MatCreateMPIAIJWithSplitArrays - creates a MPI AIJ matrix using arrays that contain the "diagonal" 502603bfb495SBarry Smith and "off-diagonal" part of the matrix in CSR format. 502703bfb495SBarry Smith 502803bfb495SBarry Smith Collective on MPI_Comm 502903bfb495SBarry Smith 503003bfb495SBarry Smith Input Parameters: 503103bfb495SBarry Smith + comm - MPI communicator 503203bfb495SBarry Smith . m - number of local rows (Cannot be PETSC_DECIDE) 503303bfb495SBarry Smith . n - This value should be the same as the local size used in creating the 503403bfb495SBarry Smith x vector for the matrix-vector product y = Ax. (or PETSC_DECIDE to have 503503bfb495SBarry Smith calculated if N is given) For square matrices n is almost always m. 503603bfb495SBarry Smith . M - number of global rows (or PETSC_DETERMINE to have calculated if m is given) 503703bfb495SBarry Smith . N - number of global columns (or PETSC_DETERMINE to have calculated if n is given) 503803bfb495SBarry Smith . i - row indices for "diagonal" portion of matrix 503903bfb495SBarry Smith . j - column indices 504003bfb495SBarry Smith . a - matrix values 504103bfb495SBarry Smith . oi - row indices for "off-diagonal" portion of matrix 504203bfb495SBarry Smith . oj - column indices 504303bfb495SBarry Smith - oa - matrix values 504403bfb495SBarry Smith 504503bfb495SBarry Smith Output Parameter: 504603bfb495SBarry Smith . mat - the matrix 504703bfb495SBarry Smith 504803bfb495SBarry Smith Level: advanced 504903bfb495SBarry Smith 505003bfb495SBarry Smith Notes: 5051292fb18eSBarry Smith The i, j, and a arrays ARE NOT copied by this routine into the internal format used by PETSc. The user 5052292fb18eSBarry Smith must free the arrays once the matrix has been destroyed and not before. 505303bfb495SBarry Smith 505403bfb495SBarry Smith The i and j indices are 0 based 505503bfb495SBarry Smith 505669b1f4b7SBarry Smith See MatCreateAIJ() for the definition of "diagonal" and "off-diagonal" portion of the matrix 505703bfb495SBarry Smith 50587b55108eSBarry Smith This sets local rows and cannot be used to set off-processor values. 50597b55108eSBarry Smith 5060dca341c0SJed Brown Use of this routine is discouraged because it is inflexible and cumbersome to use. It is extremely rare that a 5061dca341c0SJed Brown legacy application natively assembles into exactly this split format. The code to do so is nontrivial and does 5062dca341c0SJed Brown not easily support in-place reassembly. It is recommended to use MatSetValues() (or a variant thereof) because 5063dca341c0SJed Brown the resulting assembly is easier to implement, will work with any matrix format, and the user does not have to 5064dca341c0SJed Brown keep track of the underlying array. Use MatSetOption(A,MAT_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE) to disable all 5065dca341c0SJed Brown communication if it is known that only local entries will be set. 506603bfb495SBarry Smith 506703bfb495SBarry Smith .keywords: matrix, aij, compressed row, sparse, parallel 506803bfb495SBarry Smith 506903bfb495SBarry Smith .seealso: MatCreate(), MatCreateSeqAIJ(), MatSetValues(), MatMPIAIJSetPreallocation(), MatMPIAIJSetPreallocationCSR(), 50705f4d30c4SBarry Smith MATMPIAIJ, MatCreateAIJ(), MatCreateMPIAIJWithArrays() 50712b26979fSBarry Smith @*/ 50722205254eSKarl 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) 507303bfb495SBarry Smith { 507403bfb495SBarry Smith PetscErrorCode ierr; 507503bfb495SBarry Smith Mat_MPIAIJ *maij; 507603bfb495SBarry Smith 507703bfb495SBarry Smith PetscFunctionBegin; 5078e32f2f54SBarry Smith if (m < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"local number of rows (m) cannot be PETSC_DECIDE, or negative"); 5079ea345e14SBarry Smith if (i[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"i (row indices) must start with 0"); 5080ea345e14SBarry Smith if (oi[0]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"oi (row indices) must start with 0"); 508103bfb495SBarry Smith ierr = MatCreate(comm,mat);CHKERRQ(ierr); 508203bfb495SBarry Smith ierr = MatSetSizes(*mat,m,n,M,N);CHKERRQ(ierr); 508303bfb495SBarry Smith ierr = MatSetType(*mat,MATMPIAIJ);CHKERRQ(ierr); 508403bfb495SBarry Smith maij = (Mat_MPIAIJ*) (*mat)->data; 50852205254eSKarl Rupp 50868d7a6e47SBarry Smith (*mat)->preallocated = PETSC_TRUE; 508703bfb495SBarry Smith 508826283091SBarry Smith ierr = PetscLayoutSetUp((*mat)->rmap);CHKERRQ(ierr); 508926283091SBarry Smith ierr = PetscLayoutSetUp((*mat)->cmap);CHKERRQ(ierr); 509003bfb495SBarry Smith 509103bfb495SBarry Smith ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,m,n,i,j,a,&maij->A);CHKERRQ(ierr); 5092d0f46423SBarry Smith ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,m,(*mat)->cmap->N,oi,oj,oa,&maij->B);CHKERRQ(ierr); 509303bfb495SBarry Smith 50948d7a6e47SBarry Smith ierr = MatAssemblyBegin(maij->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 50958d7a6e47SBarry Smith ierr = MatAssemblyEnd(maij->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 50968d7a6e47SBarry Smith ierr = MatAssemblyBegin(maij->B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 50978d7a6e47SBarry Smith ierr = MatAssemblyEnd(maij->B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 50988d7a6e47SBarry Smith 509903bfb495SBarry Smith ierr = MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 510003bfb495SBarry Smith ierr = MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 5101dca341c0SJed Brown ierr = MatSetOption(*mat,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 510203bfb495SBarry Smith PetscFunctionReturn(0); 510303bfb495SBarry Smith } 510403bfb495SBarry Smith 510581824310SBarry Smith /* 510681824310SBarry Smith Special version for direct calls from Fortran 510781824310SBarry Smith */ 5108af0996ceSBarry Smith #include <petsc/private/fortranimpl.h> 51097087cfbeSBarry Smith 511081824310SBarry Smith #if defined(PETSC_HAVE_FORTRAN_CAPS) 511181824310SBarry Smith #define matsetvaluesmpiaij_ MATSETVALUESMPIAIJ 511281824310SBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE) 511381824310SBarry Smith #define matsetvaluesmpiaij_ matsetvaluesmpiaij 511481824310SBarry Smith #endif 511581824310SBarry Smith 511681824310SBarry Smith /* Change these macros so can be used in void function */ 511781824310SBarry Smith #undef CHKERRQ 5118e32f2f54SBarry Smith #define CHKERRQ(ierr) CHKERRABORT(PETSC_COMM_WORLD,ierr) 511981824310SBarry Smith #undef SETERRQ2 5120e32f2f54SBarry Smith #define SETERRQ2(comm,ierr,b,c,d) CHKERRABORT(comm,ierr) 51214994cf47SJed Brown #undef SETERRQ3 51224994cf47SJed Brown #define SETERRQ3(comm,ierr,b,c,d,e) CHKERRABORT(comm,ierr) 512381824310SBarry Smith #undef SETERRQ 5124e32f2f54SBarry Smith #define SETERRQ(c,ierr,b) CHKERRABORT(c,ierr) 512581824310SBarry Smith 512681824310SBarry Smith #undef __FUNCT__ 512781824310SBarry Smith #define __FUNCT__ "matsetvaluesmpiaij_" 51288cc058d9SJed 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) 512981824310SBarry Smith { 513081824310SBarry Smith Mat mat = *mmat; 513181824310SBarry Smith PetscInt m = *mm, n = *mn; 513281824310SBarry Smith InsertMode addv = *maddv; 513381824310SBarry Smith Mat_MPIAIJ *aij = (Mat_MPIAIJ*)mat->data; 513481824310SBarry Smith PetscScalar value; 513581824310SBarry Smith PetscErrorCode ierr; 5136899cda47SBarry Smith 51374994cf47SJed Brown MatCheckPreallocated(mat,1); 51382205254eSKarl Rupp if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv; 51392205254eSKarl Rupp 514081824310SBarry Smith #if defined(PETSC_USE_DEBUG) 5141f23aa3ddSBarry Smith else if (mat->insertmode != addv) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Cannot mix add values and insert values"); 514281824310SBarry Smith #endif 514381824310SBarry Smith { 5144d0f46423SBarry Smith PetscInt i,j,rstart = mat->rmap->rstart,rend = mat->rmap->rend; 5145d0f46423SBarry Smith PetscInt cstart = mat->cmap->rstart,cend = mat->cmap->rend,row,col; 5146ace3abfcSBarry Smith PetscBool roworiented = aij->roworiented; 514781824310SBarry Smith 514881824310SBarry Smith /* Some Variables required in the macro */ 514981824310SBarry Smith Mat A = aij->A; 515081824310SBarry Smith Mat_SeqAIJ *a = (Mat_SeqAIJ*)A->data; 515181824310SBarry Smith PetscInt *aimax = a->imax,*ai = a->i,*ailen = a->ilen,*aj = a->j; 5152dd6ea824SBarry Smith MatScalar *aa = a->a; 5153ace3abfcSBarry Smith PetscBool ignorezeroentries = (((a->ignorezeroentries)&&(addv==ADD_VALUES)) ? PETSC_TRUE : PETSC_FALSE); 515481824310SBarry Smith Mat B = aij->B; 515581824310SBarry Smith Mat_SeqAIJ *b = (Mat_SeqAIJ*)B->data; 5156d0f46423SBarry Smith PetscInt *bimax = b->imax,*bi = b->i,*bilen = b->ilen,*bj = b->j,bm = aij->B->rmap->n,am = aij->A->rmap->n; 5157dd6ea824SBarry Smith MatScalar *ba = b->a; 515881824310SBarry Smith 515981824310SBarry Smith PetscInt *rp1,*rp2,ii,nrow1,nrow2,_i,rmax1,rmax2,N,low1,high1,low2,high2,t,lastcol1,lastcol2; 516081824310SBarry Smith PetscInt nonew = a->nonew; 5161dd6ea824SBarry Smith MatScalar *ap1,*ap2; 516281824310SBarry Smith 516381824310SBarry Smith PetscFunctionBegin; 516481824310SBarry Smith for (i=0; i<m; i++) { 516581824310SBarry Smith if (im[i] < 0) continue; 516681824310SBarry Smith #if defined(PETSC_USE_DEBUG) 5167e32f2f54SBarry 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); 516881824310SBarry Smith #endif 516981824310SBarry Smith if (im[i] >= rstart && im[i] < rend) { 517081824310SBarry Smith row = im[i] - rstart; 517181824310SBarry Smith lastcol1 = -1; 517281824310SBarry Smith rp1 = aj + ai[row]; 517381824310SBarry Smith ap1 = aa + ai[row]; 517481824310SBarry Smith rmax1 = aimax[row]; 517581824310SBarry Smith nrow1 = ailen[row]; 517681824310SBarry Smith low1 = 0; 517781824310SBarry Smith high1 = nrow1; 517881824310SBarry Smith lastcol2 = -1; 517981824310SBarry Smith rp2 = bj + bi[row]; 518081824310SBarry Smith ap2 = ba + bi[row]; 518181824310SBarry Smith rmax2 = bimax[row]; 518281824310SBarry Smith nrow2 = bilen[row]; 518381824310SBarry Smith low2 = 0; 518481824310SBarry Smith high2 = nrow2; 518581824310SBarry Smith 518681824310SBarry Smith for (j=0; j<n; j++) { 51872205254eSKarl Rupp if (roworiented) value = v[i*n+j]; 51882205254eSKarl Rupp else value = v[i+j*m]; 518981824310SBarry Smith if (ignorezeroentries && value == 0.0 && (addv == ADD_VALUES)) continue; 519081824310SBarry Smith if (in[j] >= cstart && in[j] < cend) { 519181824310SBarry Smith col = in[j] - cstart; 5192d40312a9SBarry Smith MatSetValues_SeqAIJ_A_Private(row,col,value,addv,im[i],in[j]); 519381824310SBarry Smith } else if (in[j] < 0) continue; 519481824310SBarry Smith #if defined(PETSC_USE_DEBUG) 5195cb9801acSJed 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); 519681824310SBarry Smith #endif 519781824310SBarry Smith else { 519881824310SBarry Smith if (mat->was_assembled) { 519981824310SBarry Smith if (!aij->colmap) { 5200ab9863d7SBarry Smith ierr = MatCreateColmap_MPIAIJ_Private(mat);CHKERRQ(ierr); 520181824310SBarry Smith } 520281824310SBarry Smith #if defined(PETSC_USE_CTABLE) 520381824310SBarry Smith ierr = PetscTableFind(aij->colmap,in[j]+1,&col);CHKERRQ(ierr); 520481824310SBarry Smith col--; 520581824310SBarry Smith #else 520681824310SBarry Smith col = aij->colmap[in[j]] - 1; 520781824310SBarry Smith #endif 520881824310SBarry Smith if (col < 0 && !((Mat_SeqAIJ*)(aij->A->data))->nonew) { 5209ab9863d7SBarry Smith ierr = MatDisAssemble_MPIAIJ(mat);CHKERRQ(ierr); 521081824310SBarry Smith col = in[j]; 521181824310SBarry Smith /* Reinitialize the variables required by MatSetValues_SeqAIJ_B_Private() */ 521281824310SBarry Smith B = aij->B; 521381824310SBarry Smith b = (Mat_SeqAIJ*)B->data; 521481824310SBarry Smith bimax = b->imax; bi = b->i; bilen = b->ilen; bj = b->j; 521581824310SBarry Smith rp2 = bj + bi[row]; 521681824310SBarry Smith ap2 = ba + bi[row]; 521781824310SBarry Smith rmax2 = bimax[row]; 521881824310SBarry Smith nrow2 = bilen[row]; 521981824310SBarry Smith low2 = 0; 522081824310SBarry Smith high2 = nrow2; 5221d0f46423SBarry Smith bm = aij->B->rmap->n; 522281824310SBarry Smith ba = b->a; 522381824310SBarry Smith } 522481824310SBarry Smith } else col = in[j]; 5225d40312a9SBarry Smith MatSetValues_SeqAIJ_B_Private(row,col,value,addv,im[i],in[j]); 522681824310SBarry Smith } 522781824310SBarry Smith } 52282205254eSKarl Rupp } else if (!aij->donotstash) { 522981824310SBarry Smith if (roworiented) { 5230ace3abfcSBarry Smith ierr = MatStashValuesRow_Private(&mat->stash,im[i],n,in,v+i*n,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr); 523181824310SBarry Smith } else { 5232ace3abfcSBarry Smith ierr = MatStashValuesCol_Private(&mat->stash,im[i],n,in,v+i,m,(PetscBool)(ignorezeroentries && (addv == ADD_VALUES)));CHKERRQ(ierr); 523381824310SBarry Smith } 523481824310SBarry Smith } 523581824310SBarry Smith } 52362205254eSKarl Rupp } 523781824310SBarry Smith PetscFunctionReturnVoid(); 523881824310SBarry Smith } 523903bfb495SBarry Smith 5240