xref: /petsc/src/mat/impls/is/matis.c (revision c77832ed7683be3617520af8bc25e940b04481a1)
1be1d678aSKris Buschelman 
2b4319ba4SBarry Smith /*
3b4319ba4SBarry Smith     Creates a matrix class for using the Neumann-Neumann type preconditioners.
4b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
5b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
6b4319ba4SBarry Smith    product is handled "implicitly".
7b4319ba4SBarry Smith 
8b4319ba4SBarry Smith      We provide:
9b4319ba4SBarry Smith          MatMult()
10b4319ba4SBarry Smith 
11b4319ba4SBarry Smith     Currently this allows for only one subdomain per processor.
12b4319ba4SBarry Smith 
13b4319ba4SBarry Smith */
14b4319ba4SBarry Smith 
15c6db04a5SJed Brown #include <../src/mat/impls/is/matis.h>      /*I "petscmat.h" I*/
1628f4e0baSStefano Zampini 
17a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat);
18a72627d2SStefano Zampini 
1928f4e0baSStefano Zampini #undef __FUNCT__
2028f4e0baSStefano Zampini #define __FUNCT__ "MatISComputeSF_Private"
21a72627d2SStefano Zampini static PetscErrorCode MatISComputeSF_Private(Mat B)
2228f4e0baSStefano Zampini {
2328f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
2428f4e0baSStefano Zampini   const PetscInt *gidxs;
2528f4e0baSStefano Zampini   PetscErrorCode ierr;
2628f4e0baSStefano Zampini 
2728f4e0baSStefano Zampini   PetscFunctionBegin;
2828f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,&matis->sf_nleaves,NULL);CHKERRQ(ierr);
2928f4e0baSStefano Zampini   ierr = MatGetLocalSize(B,&matis->sf_nroots,NULL);CHKERRQ(ierr);
3028f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
313bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
3228f4e0baSStefano Zampini   /* PETSC_OWN_POINTER refers to ilocal which is NULL */
3328f4e0baSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,matis->sf_nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
343bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
3528f4e0baSStefano Zampini   ierr = PetscMalloc2(matis->sf_nroots,&matis->sf_rootdata,matis->sf_nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
3628f4e0baSStefano Zampini   PetscFunctionReturn(0);
3728f4e0baSStefano Zampini }
382e1947a5SStefano Zampini 
392e1947a5SStefano Zampini #undef __FUNCT__
402e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation"
41eb82efa4SStefano Zampini /*@
42a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
43a88811baSStefano Zampini 
44a88811baSStefano Zampini    Collective on MPI_Comm
45a88811baSStefano Zampini 
46a88811baSStefano Zampini    Input Parameters:
47a88811baSStefano Zampini +  B - the matrix
48a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
49a88811baSStefano Zampini            (same value is used for all local rows)
50a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
51a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
52a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
53a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
54a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
55a88811baSStefano Zampini            the diagonal entry even if it is zero.
56a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
57a88811baSStefano Zampini            submatrix (same value is used for all local rows).
58a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
59a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
60a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
61a88811baSStefano Zampini            structure. The size of this array is equal to the number
62a88811baSStefano Zampini            of local rows, i.e 'm'.
63a88811baSStefano Zampini 
64a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
65a88811baSStefano Zampini 
66a88811baSStefano Zampini    Level: intermediate
67a88811baSStefano Zampini 
68a88811baSStefano Zampini    Notes: This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
69a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
70a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
71a88811baSStefano Zampini 
72a88811baSStefano Zampini .keywords: matrix
73a88811baSStefano Zampini 
74a88811baSStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat()
75a88811baSStefano Zampini @*/
762e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
772e1947a5SStefano Zampini {
782e1947a5SStefano Zampini   PetscErrorCode ierr;
792e1947a5SStefano Zampini 
802e1947a5SStefano Zampini   PetscFunctionBegin;
812e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
822e1947a5SStefano Zampini   PetscValidType(B,1);
832e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
842e1947a5SStefano Zampini   PetscFunctionReturn(0);
852e1947a5SStefano Zampini }
862e1947a5SStefano Zampini 
872e1947a5SStefano Zampini #undef __FUNCT__
882e1947a5SStefano Zampini #define __FUNCT__ "MatISSetPreallocation_IS"
892e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
902e1947a5SStefano Zampini {
912e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
9228f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
932e1947a5SStefano Zampini   PetscErrorCode ierr;
942e1947a5SStefano Zampini 
952e1947a5SStefano Zampini   PetscFunctionBegin;
966c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
9728f4e0baSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
9828f4e0baSStefano Zampini     ierr = MatISComputeSF_Private(B);CHKERRQ(ierr);
9928f4e0baSStefano Zampini   }
1002e1947a5SStefano Zampini   if (!d_nnz) {
10128f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nz;
1022e1947a5SStefano Zampini   } else {
10328f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
1042e1947a5SStefano Zampini   }
1052e1947a5SStefano Zampini   if (!o_nnz) {
10628f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nz;
1072e1947a5SStefano Zampini   } else {
10828f4e0baSStefano Zampini     for (i=0;i<matis->sf_nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
1092e1947a5SStefano Zampini   }
11028f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
11128f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
11228f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
11328f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
11428f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves;i++) {
11528f4e0baSStefano Zampini     matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
1162e1947a5SStefano Zampini   }
11728f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
11828f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
11928f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
1202e1947a5SStefano Zampini   }
12128f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
12228f4e0baSStefano Zampini   for (i=0;i<matis->sf_nleaves/bs;i++) {
12328f4e0baSStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
1242e1947a5SStefano Zampini   }
12528f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
1262e1947a5SStefano Zampini   PetscFunctionReturn(0);
1272e1947a5SStefano Zampini }
128b4319ba4SBarry Smith 
129b4319ba4SBarry Smith #undef __FUNCT__
1303927de2eSStefano Zampini #define __FUNCT__ "MatISSetMPIXAIJPreallocation_Private"
1313927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
1323927de2eSStefano Zampini {
1333927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
1343927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
135ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
1363927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
1373927de2eSStefano Zampini   PetscInt        lrows,lcols;
1383927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
1393927de2eSStefano Zampini   PetscMPIInt     nsubdomains;
1403927de2eSStefano Zampini   PetscBool       isdense,issbaij;
1413927de2eSStefano Zampini   PetscErrorCode  ierr;
1423927de2eSStefano Zampini 
1433927de2eSStefano Zampini   PetscFunctionBegin;
1443927de2eSStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&nsubdomains);CHKERRQ(ierr);
1453927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
1463927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
1473927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1483927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
1493927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
150ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
151ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
1520ea065fbSStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
153ecf5a873SStefano Zampini   } else {
154ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
155ecf5a873SStefano Zampini   }
156ecf5a873SStefano Zampini 
1573927de2eSStefano Zampini   if (issbaij) {
1583927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
1593927de2eSStefano Zampini   }
1603927de2eSStefano Zampini   /*
161ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
1623927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
1633927de2eSStefano Zampini   */
1643927de2eSStefano Zampini   if (!matis->sf) { /* setup SF if not yet created and allocate rootdata and leafdata */
1653927de2eSStefano Zampini     ierr = MatISComputeSF_Private(A);CHKERRQ(ierr);
1663927de2eSStefano Zampini   }
1673927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
1683927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
1693927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
1703927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
1713927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
1723927de2eSStefano Zampini   for (i=0;i<nsubdomains;i++) {
1733927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
1743927de2eSStefano Zampini       row_ownership[j] = i;
1753927de2eSStefano Zampini     }
1763927de2eSStefano Zampini   }
1770ea065fbSStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
1783927de2eSStefano Zampini 
1793927de2eSStefano Zampini   /*
1803927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
1813927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
1823927de2eSStefano Zampini   */
1833927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
1843927de2eSStefano Zampini   /* preallocation as a MATAIJ */
1853927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
1863927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
18712dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
18812dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
189ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
1903927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1913927de2eSStefano Zampini           my_dnz[i] += 1;
1923927de2eSStefano Zampini         } else { /* offdiag block */
1933927de2eSStefano Zampini           my_onz[i] += 1;
1943927de2eSStefano Zampini         }
1953927de2eSStefano Zampini       }
1963927de2eSStefano Zampini     }
197ecf5a873SStefano Zampini   } else { /* TODO: this could be optimized using MatGetRowIJ */
1983927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
1993927de2eSStefano Zampini       const PetscInt *cols;
200ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
2013927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
2023927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
2033927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
204ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
2053927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
2063927de2eSStefano Zampini           my_dnz[i] += 1;
2073927de2eSStefano Zampini         } else { /* offdiag block */
2083927de2eSStefano Zampini           my_onz[i] += 1;
2093927de2eSStefano Zampini         }
2103927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
211d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
2123927de2eSStefano Zampini           owner = row_ownership[index_col];
2133927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
214d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
2153927de2eSStefano Zampini           } else {
216d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
2173927de2eSStefano Zampini           }
2183927de2eSStefano Zampini         }
2193927de2eSStefano Zampini       }
2203927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
2213927de2eSStefano Zampini     }
2223927de2eSStefano Zampini   }
223ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
2240ea065fbSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
225ecf5a873SStefano Zampini   }
2264f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
2273927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
228ecf5a873SStefano Zampini 
229ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
2303927de2eSStefano Zampini   if (maxreduce) {
2313927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
2323927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
2333927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
2343927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
2353927de2eSStefano Zampini   } else {
2363927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
2373927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
2383927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
2393927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
2403927de2eSStefano Zampini   }
2413927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
2423927de2eSStefano Zampini 
2433927de2eSStefano Zampini   /* Resize preallocation if overestimated */
2443927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
2453927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
2463927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
2473927de2eSStefano Zampini   }
2483927de2eSStefano Zampini   /* set preallocation */
2493927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
2503927de2eSStefano Zampini   for (i=0;i<lrows/bs;i++) {
2513927de2eSStefano Zampini     dnz[i] = dnz[i*bs]/bs;
2523927de2eSStefano Zampini     onz[i] = onz[i*bs]/bs;
2533927de2eSStefano Zampini   }
2543927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
2553927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
2563927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
2573927de2eSStefano Zampini   if (issbaij) {
2583927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
2593927de2eSStefano Zampini   }
2603927de2eSStefano Zampini   PetscFunctionReturn(0);
2613927de2eSStefano Zampini }
2623927de2eSStefano Zampini 
2633927de2eSStefano Zampini #undef __FUNCT__
264b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ_IS"
265b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ_IS(Mat mat, MatReuse reuse, Mat *M)
266b7ce53b6SStefano Zampini {
267b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
268d9a9e74cSStefano Zampini   Mat            local_mat;
269b7ce53b6SStefano Zampini   /* info on mat */
2703cfa4ea4SStefano Zampini   PetscInt       bs,rows,cols,lrows,lcols;
271b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
272686e3a49SStefano Zampini   PetscBool      isdense,issbaij,isseqaij;
2737c03b4e8SStefano Zampini   PetscMPIInt    nsubdomains;
274b7ce53b6SStefano Zampini   /* values insertion */
275b7ce53b6SStefano Zampini   PetscScalar    *array;
276b7ce53b6SStefano Zampini   /* work */
277b7ce53b6SStefano Zampini   PetscErrorCode ierr;
278b7ce53b6SStefano Zampini 
279b7ce53b6SStefano Zampini   PetscFunctionBegin;
280b7ce53b6SStefano Zampini   /* get info from mat */
2817c03b4e8SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&nsubdomains);CHKERRQ(ierr);
2827c03b4e8SStefano Zampini   if (nsubdomains == 1) {
2837c03b4e8SStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) {
2847c03b4e8SStefano Zampini       ierr = MatDuplicate(matis->A,MAT_COPY_VALUES,&(*M));CHKERRQ(ierr);
2857c03b4e8SStefano Zampini     } else {
2867c03b4e8SStefano Zampini       ierr = MatCopy(matis->A,*M,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
2877c03b4e8SStefano Zampini     }
2887c03b4e8SStefano Zampini     PetscFunctionReturn(0);
2897c03b4e8SStefano Zampini   }
290b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
291b7ce53b6SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
2923cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
293b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
294b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
295686e3a49SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
296b7ce53b6SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
297b7ce53b6SStefano Zampini 
298b7ce53b6SStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
299b7ce53b6SStefano Zampini     MatType     new_mat_type;
3003927de2eSStefano Zampini     PetscBool   issbaij_red;
301b7ce53b6SStefano Zampini 
302b7ce53b6SStefano Zampini     /* determining new matrix type */
303b2566f29SBarry Smith     ierr = MPIU_Allreduce(&issbaij,&issbaij_red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
304b7ce53b6SStefano Zampini     if (issbaij_red) {
305b7ce53b6SStefano Zampini       new_mat_type = MATSBAIJ;
306b7ce53b6SStefano Zampini     } else {
307b7ce53b6SStefano Zampini       if (bs>1) {
308b7ce53b6SStefano Zampini         new_mat_type = MATBAIJ;
309b7ce53b6SStefano Zampini       } else {
310b7ce53b6SStefano Zampini         new_mat_type = MATAIJ;
311b7ce53b6SStefano Zampini       }
312b7ce53b6SStefano Zampini     }
313b7ce53b6SStefano Zampini 
3143927de2eSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),M);CHKERRQ(ierr);
3153cfa4ea4SStefano Zampini     ierr = MatSetSizes(*M,lrows,lcols,rows,cols);CHKERRQ(ierr);
3163927de2eSStefano Zampini     ierr = MatSetBlockSize(*M,bs);CHKERRQ(ierr);
3173927de2eSStefano Zampini     ierr = MatSetType(*M,new_mat_type);CHKERRQ(ierr);
3183927de2eSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,*M,PETSC_FALSE);CHKERRQ(ierr);
319b7ce53b6SStefano Zampini   } else {
3203cfa4ea4SStefano Zampini     PetscInt mbs,mrows,mcols,mlrows,mlcols;
321b7ce53b6SStefano Zampini     /* some checks */
322b7ce53b6SStefano Zampini     ierr = MatGetBlockSize(*M,&mbs);CHKERRQ(ierr);
323b7ce53b6SStefano Zampini     ierr = MatGetSize(*M,&mrows,&mcols);CHKERRQ(ierr);
3243cfa4ea4SStefano Zampini     ierr = MatGetLocalSize(*M,&mlrows,&mlcols);CHKERRQ(ierr);
3256c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
3266c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
3276c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
3286c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
3296c4ed002SBarry Smith     if (mbs != bs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong block size (%d != %d)",bs,mbs);
330b7ce53b6SStefano Zampini     ierr = MatZeroEntries(*M);CHKERRQ(ierr);
331b7ce53b6SStefano Zampini   }
332d9a9e74cSStefano Zampini 
333d9a9e74cSStefano Zampini   if (issbaij) {
334d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
335d9a9e74cSStefano Zampini   } else {
336d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
337d9a9e74cSStefano Zampini     local_mat = matis->A;
338d9a9e74cSStefano Zampini   }
339686e3a49SStefano Zampini 
340b7ce53b6SStefano Zampini   /* Set values */
341ecf5a873SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*M,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
342b7ce53b6SStefano Zampini   if (isdense) { /* special case for dense local matrices */
34365066ba5SStefano Zampini     PetscInt i,*dummy;
344ecf5a873SStefano Zampini 
34565066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
34665066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
347b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
348d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
34965066ba5SStefano Zampini     ierr = MatSetValuesLocal(*M,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
350d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
35165066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
352686e3a49SStefano Zampini   } else if (isseqaij) {
353ecf5a873SStefano Zampini     PetscInt  i,nvtxs,*xadj,*adjncy;
354686e3a49SStefano Zampini     PetscBool done;
355686e3a49SStefano Zampini 
356d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
3576c4ed002SBarry Smith     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
358d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
359686e3a49SStefano Zampini     for (i=0;i<nvtxs;i++) {
360ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
361686e3a49SStefano Zampini     }
362d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
3636c4ed002SBarry Smith     if (!done) SETERRQ1(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ called in %s\n",__FUNCT__);
364d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
365686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
366ecf5a873SStefano Zampini     PetscInt i;
367c0962df8SStefano Zampini 
368686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
369686e3a49SStefano Zampini       PetscInt       j;
370ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
371686e3a49SStefano Zampini 
372ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
373ecf5a873SStefano Zampini       ierr = MatSetValuesLocal(*M,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
374ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
375686e3a49SStefano Zampini     }
376b7ce53b6SStefano Zampini   }
377b7ce53b6SStefano Zampini   ierr = MatAssemblyBegin(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
378d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
379b7ce53b6SStefano Zampini   ierr = MatAssemblyEnd(*M,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
380b7ce53b6SStefano Zampini   if (isdense) {
381b7ce53b6SStefano Zampini     ierr = MatSetOption(*M,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
382b7ce53b6SStefano Zampini   }
383b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
384b7ce53b6SStefano Zampini }
385b7ce53b6SStefano Zampini 
386b7ce53b6SStefano Zampini #undef __FUNCT__
387b7ce53b6SStefano Zampini #define __FUNCT__ "MatISGetMPIXAIJ"
388b7ce53b6SStefano Zampini /*@
389b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
390b7ce53b6SStefano Zampini 
391b7ce53b6SStefano Zampini   Input Parameter:
392b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
393b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
394b7ce53b6SStefano Zampini 
395b7ce53b6SStefano Zampini   Output Parameter:
396b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
397b7ce53b6SStefano Zampini 
398b7ce53b6SStefano Zampini   Level: developer
399b7ce53b6SStefano Zampini 
400eb82efa4SStefano Zampini   Notes: mat and *newmat cannot be the same object when MAT_REUSE_MATRIX is requested.
401b7ce53b6SStefano Zampini 
402b7ce53b6SStefano Zampini .seealso: MATIS
403b7ce53b6SStefano Zampini @*/
404b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
405b7ce53b6SStefano Zampini {
406b7ce53b6SStefano Zampini   PetscErrorCode ierr;
407b7ce53b6SStefano Zampini 
408b7ce53b6SStefano Zampini   PetscFunctionBegin;
409b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
410b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
411b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
412b7ce53b6SStefano Zampini   if (reuse != MAT_INITIAL_MATRIX) {
413b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
414b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
4156c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
416b7ce53b6SStefano Zampini   }
417b7ce53b6SStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatReuse,Mat*),(mat,reuse,newmat));CHKERRQ(ierr);
418b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
419b7ce53b6SStefano Zampini }
420b7ce53b6SStefano Zampini 
421b7ce53b6SStefano Zampini #undef __FUNCT__
422ad6194a2SStefano Zampini #define __FUNCT__ "MatDuplicate_IS"
423ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
424ad6194a2SStefano Zampini {
425ad6194a2SStefano Zampini   PetscErrorCode ierr;
426ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
427ad6194a2SStefano Zampini   PetscInt       bs,m,n,M,N;
428ad6194a2SStefano Zampini   Mat            B,localmat;
429ad6194a2SStefano Zampini 
430ad6194a2SStefano Zampini   PetscFunctionBegin;
431ad6194a2SStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
432ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
433ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
434e176bc59SStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),bs,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
435ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
436ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
437b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
438ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
439ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
440ad6194a2SStefano Zampini   *newmat = B;
441ad6194a2SStefano Zampini   PetscFunctionReturn(0);
442ad6194a2SStefano Zampini }
443ad6194a2SStefano Zampini 
444ad6194a2SStefano Zampini #undef __FUNCT__
44569796d55SStefano Zampini #define __FUNCT__ "MatIsHermitian_IS"
44669796d55SStefano Zampini PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
44769796d55SStefano Zampini {
44869796d55SStefano Zampini   PetscErrorCode ierr;
44969796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
45069796d55SStefano Zampini   PetscBool      local_sym;
45169796d55SStefano Zampini 
45269796d55SStefano Zampini   PetscFunctionBegin;
45369796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
454b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
45569796d55SStefano Zampini   PetscFunctionReturn(0);
45669796d55SStefano Zampini }
45769796d55SStefano Zampini 
45869796d55SStefano Zampini #undef __FUNCT__
45969796d55SStefano Zampini #define __FUNCT__ "MatIsSymmetric_IS"
46069796d55SStefano Zampini PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
46169796d55SStefano Zampini {
46269796d55SStefano Zampini   PetscErrorCode ierr;
46369796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
46469796d55SStefano Zampini   PetscBool      local_sym;
46569796d55SStefano Zampini 
46669796d55SStefano Zampini   PetscFunctionBegin;
46769796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
468b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
46969796d55SStefano Zampini   PetscFunctionReturn(0);
47069796d55SStefano Zampini }
47169796d55SStefano Zampini 
47269796d55SStefano Zampini #undef __FUNCT__
473b4319ba4SBarry Smith #define __FUNCT__ "MatDestroy_IS"
474dfbe8321SBarry Smith PetscErrorCode MatDestroy_IS(Mat A)
475b4319ba4SBarry Smith {
476dfbe8321SBarry Smith   PetscErrorCode ierr;
477b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
478b4319ba4SBarry Smith 
479b4319ba4SBarry Smith   PetscFunctionBegin;
4806bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
481e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
482e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
4836bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
4846bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
48528f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
48628f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
487bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
488dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
489bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
490b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
491b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
4922e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
493b4319ba4SBarry Smith   PetscFunctionReturn(0);
494b4319ba4SBarry Smith }
495b4319ba4SBarry Smith 
496b4319ba4SBarry Smith #undef __FUNCT__
497b4319ba4SBarry Smith #define __FUNCT__ "MatMult_IS"
498dfbe8321SBarry Smith PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
499b4319ba4SBarry Smith {
500dfbe8321SBarry Smith   PetscErrorCode ierr;
501b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
502b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
503b4319ba4SBarry Smith 
504b4319ba4SBarry Smith   PetscFunctionBegin;
505b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
506e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
507e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
508b4319ba4SBarry Smith 
509b4319ba4SBarry Smith   /* multiply the local matrix */
510b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
511b4319ba4SBarry Smith 
512b4319ba4SBarry Smith   /* scatter product back into global memory */
5132dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
514e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
515e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
516b4319ba4SBarry Smith   PetscFunctionReturn(0);
517b4319ba4SBarry Smith }
518b4319ba4SBarry Smith 
519b4319ba4SBarry Smith #undef __FUNCT__
5202e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultAdd_IS"
521b7ce53b6SStefano Zampini PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
5222e74eeadSLisandro Dalcin {
523650997f4SStefano Zampini   Vec            temp_vec;
5242e74eeadSLisandro Dalcin   PetscErrorCode ierr;
5252e74eeadSLisandro Dalcin 
5262e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
527650997f4SStefano Zampini   if (v3 != v2) {
528650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
529650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
530650997f4SStefano Zampini   } else {
531650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
532650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
533650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
534650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
535650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
536650997f4SStefano Zampini   }
5372e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
5382e74eeadSLisandro Dalcin }
5392e74eeadSLisandro Dalcin 
5402e74eeadSLisandro Dalcin #undef __FUNCT__
5412e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTranspose_IS"
542e176bc59SStefano Zampini PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
5432e74eeadSLisandro Dalcin {
5442e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
5452e74eeadSLisandro Dalcin   PetscErrorCode ierr;
5462e74eeadSLisandro Dalcin 
547e176bc59SStefano Zampini   PetscFunctionBegin;
5482e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
549e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
550e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
5512e74eeadSLisandro Dalcin 
5522e74eeadSLisandro Dalcin   /* multiply the local matrix */
553e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
5542e74eeadSLisandro Dalcin 
5552e74eeadSLisandro Dalcin   /* scatter product back into global vector */
556e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
557e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
558e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
5592e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
5602e74eeadSLisandro Dalcin }
5612e74eeadSLisandro Dalcin 
5622e74eeadSLisandro Dalcin #undef __FUNCT__
5632e74eeadSLisandro Dalcin #define __FUNCT__ "MatMultTransposeAdd_IS"
5642e74eeadSLisandro Dalcin PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
5652e74eeadSLisandro Dalcin {
566650997f4SStefano Zampini   Vec            temp_vec;
5672e74eeadSLisandro Dalcin   PetscErrorCode ierr;
5682e74eeadSLisandro Dalcin 
5692e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
570650997f4SStefano Zampini   if (v3 != v2) {
571650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
572650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
573650997f4SStefano Zampini   } else {
574650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
575650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
576650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
577650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
578650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
579650997f4SStefano Zampini   }
5802e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
5812e74eeadSLisandro Dalcin }
5822e74eeadSLisandro Dalcin 
5832e74eeadSLisandro Dalcin #undef __FUNCT__
584b4319ba4SBarry Smith #define __FUNCT__ "MatView_IS"
585dfbe8321SBarry Smith PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
586b4319ba4SBarry Smith {
587b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
588dfbe8321SBarry Smith   PetscErrorCode ierr;
589b4319ba4SBarry Smith   PetscViewer    sviewer;
590b4319ba4SBarry Smith 
591b4319ba4SBarry Smith   PetscFunctionBegin;
5923f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
593b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
5943f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
595b4319ba4SBarry Smith   PetscFunctionReturn(0);
596b4319ba4SBarry Smith }
597b4319ba4SBarry Smith 
598b4319ba4SBarry Smith #undef __FUNCT__
599b4319ba4SBarry Smith #define __FUNCT__ "MatSetLocalToGlobalMapping_IS"
600784ac674SJed Brown PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
601b4319ba4SBarry Smith {
602dfbe8321SBarry Smith   PetscErrorCode ierr;
603e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
604b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
605b4319ba4SBarry Smith   IS             from,to;
606e176bc59SStefano Zampini   Vec            cglobal,rglobal;
607b4319ba4SBarry Smith 
608b4319ba4SBarry Smith   PetscFunctionBegin;
609784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
610e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
6113bbff08aSStefano Zampini   /* Destroy any previous data */
61270cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
61370cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
614e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
615e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
6161c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
61728f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
61828f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
6193bbff08aSStefano Zampini 
6203bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
621fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
622fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
623fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
624fa7f1dd8SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
625b4319ba4SBarry Smith 
626b4319ba4SBarry Smith   /* Create the local matrix A */
627e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
628e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
629e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
630e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
631f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
632e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
633e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
634e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
635ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
636ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
637b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
638*c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
639*c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
640b4319ba4SBarry Smith 
641b4319ba4SBarry Smith   /* Create the local work vectors */
6423bbff08aSStefano Zampini   ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
643b4319ba4SBarry Smith 
644e176bc59SStefano Zampini   /* setup the global to local scatters */
645e176bc59SStefano Zampini   ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
646e176bc59SStefano Zampini   ierr = ISCreateStride(PETSC_COMM_SELF,nr,0,1,&to);CHKERRQ(ierr);
647784ac674SJed Brown   ierr = ISLocalToGlobalMappingApplyIS(rmapping,to,&from);CHKERRQ(ierr);
648e176bc59SStefano Zampini   ierr = VecScatterCreate(rglobal,from,is->y,to,&is->rctx);CHKERRQ(ierr);
649e176bc59SStefano Zampini   if (rmapping != cmapping) {
650e176bc59SStefano Zampini     ierr = ISDestroy(&to);CHKERRQ(ierr);
651e176bc59SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
652e176bc59SStefano Zampini     ierr = ISCreateStride(PETSC_COMM_SELF,nc,0,1,&to);CHKERRQ(ierr);
653e176bc59SStefano Zampini     ierr = ISLocalToGlobalMappingApplyIS(cmapping,to,&from);CHKERRQ(ierr);
654e176bc59SStefano Zampini     ierr = VecScatterCreate(cglobal,from,is->x,to,&is->cctx);CHKERRQ(ierr);
655e176bc59SStefano Zampini   } else {
656e176bc59SStefano Zampini     ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
657e176bc59SStefano Zampini     is->cctx = is->rctx;
658e176bc59SStefano Zampini   }
659e176bc59SStefano Zampini   ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
660e176bc59SStefano Zampini   ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
6616bf464f9SBarry Smith   ierr = ISDestroy(&to);CHKERRQ(ierr);
6626bf464f9SBarry Smith   ierr = ISDestroy(&from);CHKERRQ(ierr);
663b4319ba4SBarry Smith   PetscFunctionReturn(0);
664b4319ba4SBarry Smith }
665b4319ba4SBarry Smith 
6662e74eeadSLisandro Dalcin #undef __FUNCT__
6672e74eeadSLisandro Dalcin #define __FUNCT__ "MatSetValues_IS"
6682e74eeadSLisandro Dalcin PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
6692e74eeadSLisandro Dalcin {
6702e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
6712e74eeadSLisandro Dalcin   PetscInt       rows_l[2048],cols_l[2048];
6722e74eeadSLisandro Dalcin   PetscErrorCode ierr;
6732e74eeadSLisandro Dalcin 
6742e74eeadSLisandro Dalcin   PetscFunctionBegin;
6752e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
676f23aa3ddSBarry Smith   if (m > 2048 || n > 2048) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= 2048: they are %D %D",m,n);
6772e74eeadSLisandro Dalcin #endif
6783bbff08aSStefano Zampini   ierr = ISG2LMapApply(mat->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
6793bbff08aSStefano Zampini   ierr = ISG2LMapApply(mat->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
6802e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
6812e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
6822e74eeadSLisandro Dalcin }
6832e74eeadSLisandro Dalcin 
684b4319ba4SBarry Smith #undef __FUNCT__
685b4319ba4SBarry Smith #define __FUNCT__ "MatSetValuesLocal_IS"
68613f74950SBarry Smith PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
687b4319ba4SBarry Smith {
688dfbe8321SBarry Smith   PetscErrorCode ierr;
689b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
690b4319ba4SBarry Smith 
691b4319ba4SBarry Smith   PetscFunctionBegin;
692b4319ba4SBarry Smith   ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
693b4319ba4SBarry Smith   PetscFunctionReturn(0);
694b4319ba4SBarry Smith }
695b4319ba4SBarry Smith 
696b4319ba4SBarry Smith #undef __FUNCT__
697f0006bf2SLisandro Dalcin #define __FUNCT__ "MatSetValuesBlockedLocal_IS"
698f0006bf2SLisandro Dalcin PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
699f0006bf2SLisandro Dalcin {
700f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
701f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
702f0006bf2SLisandro Dalcin 
703f0006bf2SLisandro Dalcin   PetscFunctionBegin;
704f0006bf2SLisandro Dalcin   ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
705f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
706f0006bf2SLisandro Dalcin }
707f0006bf2SLisandro Dalcin 
708f0006bf2SLisandro Dalcin #undef __FUNCT__
7092e74eeadSLisandro Dalcin #define __FUNCT__ "MatZeroRows_IS"
7102b40b63fSBarry Smith PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
7112e74eeadSLisandro Dalcin {
7120298fd71SBarry Smith   PetscInt       n_l = 0, *rows_l = NULL;
7132e74eeadSLisandro Dalcin   PetscErrorCode ierr;
7142e74eeadSLisandro Dalcin 
7152e74eeadSLisandro Dalcin   PetscFunctionBegin;
716ce94432eSBarry Smith   if (x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support");
7172e74eeadSLisandro Dalcin   if (n) {
718785e854fSJed Brown     ierr = PetscMalloc1(n,&rows_l);CHKERRQ(ierr);
7193bbff08aSStefano Zampini     ierr = ISGlobalToLocalMappingApply(A->rmap->mapping,IS_GTOLM_DROP,n,rows,&n_l,rows_l);CHKERRQ(ierr);
7202e74eeadSLisandro Dalcin   }
7212b40b63fSBarry Smith   ierr = MatZeroRowsLocal(A,n_l,rows_l,diag,x,b);CHKERRQ(ierr);
722c31cb41cSBarry Smith   ierr = PetscFree(rows_l);CHKERRQ(ierr);
7232e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
7242e74eeadSLisandro Dalcin }
7252e74eeadSLisandro Dalcin 
7262e74eeadSLisandro Dalcin #undef __FUNCT__
727b4319ba4SBarry Smith #define __FUNCT__ "MatZeroRowsLocal_IS"
7282b40b63fSBarry Smith PetscErrorCode MatZeroRowsLocal_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
729b4319ba4SBarry Smith {
730b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
731dfbe8321SBarry Smith   PetscErrorCode ierr;
732f4df32b1SMatthew Knepley   PetscInt       i;
733b4319ba4SBarry Smith   PetscScalar    *array;
734b4319ba4SBarry Smith 
735b4319ba4SBarry Smith   PetscFunctionBegin;
736ce94432eSBarry Smith   if (x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"No support");
737b4319ba4SBarry Smith   {
738b4319ba4SBarry Smith     /*
739b4319ba4SBarry Smith        Set up is->x as a "counting vector". This is in order to MatMult_IS
740b4319ba4SBarry Smith        work properly in the interface nodes.
741b4319ba4SBarry Smith     */
742b4319ba4SBarry Smith     Vec counter;
743e176bc59SStefano Zampini     ierr = MatCreateVecs(A,NULL,&counter);CHKERRQ(ierr);
744e176bc59SStefano Zampini     ierr = VecSet(counter,0.);CHKERRQ(ierr);
745e176bc59SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
746e176bc59SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
747e176bc59SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,counter,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
748e176bc59SStefano Zampini     ierr = VecScatterBegin(is->rctx,counter,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
749e176bc59SStefano Zampini     ierr = VecScatterEnd(is->rctx,counter,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
7506bf464f9SBarry Smith     ierr = VecDestroy(&counter);CHKERRQ(ierr);
751b4319ba4SBarry Smith   }
752958c9bccSBarry Smith   if (!n) {
753b4319ba4SBarry Smith     is->pure_neumann = PETSC_TRUE;
754b4319ba4SBarry Smith   } else {
755b4319ba4SBarry Smith     is->pure_neumann = PETSC_FALSE;
7562205254eSKarl Rupp 
757e176bc59SStefano Zampini     ierr = VecGetArray(is->y,&array);CHKERRQ(ierr);
7582b40b63fSBarry Smith     ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
759b4319ba4SBarry Smith     for (i=0; i<n; i++) {
760f4df32b1SMatthew Knepley       ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
761b4319ba4SBarry Smith     }
762b4319ba4SBarry Smith     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
763b4319ba4SBarry Smith     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
764e176bc59SStefano Zampini     ierr = VecRestoreArray(is->y,&array);CHKERRQ(ierr);
765b4319ba4SBarry Smith   }
766b4319ba4SBarry Smith   PetscFunctionReturn(0);
767b4319ba4SBarry Smith }
768b4319ba4SBarry Smith 
769b4319ba4SBarry Smith #undef __FUNCT__
770b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyBegin_IS"
771dfbe8321SBarry Smith PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
772b4319ba4SBarry Smith {
773b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
774dfbe8321SBarry Smith   PetscErrorCode ierr;
775b4319ba4SBarry Smith 
776b4319ba4SBarry Smith   PetscFunctionBegin;
777b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
778b4319ba4SBarry Smith   PetscFunctionReturn(0);
779b4319ba4SBarry Smith }
780b4319ba4SBarry Smith 
781b4319ba4SBarry Smith #undef __FUNCT__
782b4319ba4SBarry Smith #define __FUNCT__ "MatAssemblyEnd_IS"
783dfbe8321SBarry Smith PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
784b4319ba4SBarry Smith {
785b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
786dfbe8321SBarry Smith   PetscErrorCode ierr;
787b4319ba4SBarry Smith 
788b4319ba4SBarry Smith   PetscFunctionBegin;
789b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
790b4319ba4SBarry Smith   PetscFunctionReturn(0);
791b4319ba4SBarry Smith }
792b4319ba4SBarry Smith 
793b4319ba4SBarry Smith #undef __FUNCT__
794b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat_IS"
7957087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
796b4319ba4SBarry Smith {
797b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
798b4319ba4SBarry Smith 
799b4319ba4SBarry Smith   PetscFunctionBegin;
800b4319ba4SBarry Smith   *local = is->A;
801b4319ba4SBarry Smith   PetscFunctionReturn(0);
802b4319ba4SBarry Smith }
803b4319ba4SBarry Smith 
804b4319ba4SBarry Smith #undef __FUNCT__
805b4319ba4SBarry Smith #define __FUNCT__ "MatISGetLocalMat"
806b4319ba4SBarry Smith /*@
807b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
808b4319ba4SBarry Smith 
809b4319ba4SBarry Smith   Input Parameter:
810b4319ba4SBarry Smith .  mat - the matrix
811b4319ba4SBarry Smith 
812b4319ba4SBarry Smith   Output Parameter:
813eb82efa4SStefano Zampini .  local - the local matrix
814b4319ba4SBarry Smith 
815b4319ba4SBarry Smith   Level: advanced
816b4319ba4SBarry Smith 
817b4319ba4SBarry Smith   Notes:
818b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
819b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
820b4319ba4SBarry Smith   of the MatSetValues() operation.
821b4319ba4SBarry Smith 
82296a6f129SJed Brown   This function does not increase the reference count for the local Mat.  Do not destroy it and do not attempt to use
82396a6f129SJed Brown   your reference after destroying the parent mat.
82496a6f129SJed Brown 
825b4319ba4SBarry Smith .seealso: MATIS
826b4319ba4SBarry Smith @*/
8277087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
828b4319ba4SBarry Smith {
8294ac538c5SBarry Smith   PetscErrorCode ierr;
830b4319ba4SBarry Smith 
831b4319ba4SBarry Smith   PetscFunctionBegin;
8320700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
833b4319ba4SBarry Smith   PetscValidPointer(local,2);
8344ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
835b4319ba4SBarry Smith   PetscFunctionReturn(0);
836b4319ba4SBarry Smith }
837b4319ba4SBarry Smith 
8383b03a366Sstefano_zampini #undef __FUNCT__
8393b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat_IS"
8403b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
8413b03a366Sstefano_zampini {
8423b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
8433b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
8443b03a366Sstefano_zampini   PetscErrorCode ierr;
8453b03a366Sstefano_zampini 
8463b03a366Sstefano_zampini   PetscFunctionBegin;
8474e4c7dbeSStefano Zampini   if (is->A) {
8483b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
8493b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
850f23aa3ddSBarry Smith     if (orows != nrows || ocols != ncols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %dx%d (you passed a %dx%d matrix)\n",orows,ocols,nrows,ncols);
8514e4c7dbeSStefano Zampini   }
8523b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
8533b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
8543b03a366Sstefano_zampini   is->A = local;
8553b03a366Sstefano_zampini   PetscFunctionReturn(0);
8563b03a366Sstefano_zampini }
8573b03a366Sstefano_zampini 
8583b03a366Sstefano_zampini #undef __FUNCT__
8593b03a366Sstefano_zampini #define __FUNCT__ "MatISSetLocalMat"
8603b03a366Sstefano_zampini /*@
861eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
8623b03a366Sstefano_zampini 
8633b03a366Sstefano_zampini   Input Parameter:
8643b03a366Sstefano_zampini .  mat - the matrix
865eb82efa4SStefano Zampini .  local - the local matrix
8663b03a366Sstefano_zampini 
8673b03a366Sstefano_zampini   Output Parameter:
8683b03a366Sstefano_zampini 
8693b03a366Sstefano_zampini   Level: advanced
8703b03a366Sstefano_zampini 
8713b03a366Sstefano_zampini   Notes:
8723b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
8733b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
8743b03a366Sstefano_zampini 
8753b03a366Sstefano_zampini .seealso: MATIS
8763b03a366Sstefano_zampini @*/
8773b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
8783b03a366Sstefano_zampini {
8793b03a366Sstefano_zampini   PetscErrorCode ierr;
8803b03a366Sstefano_zampini 
8813b03a366Sstefano_zampini   PetscFunctionBegin;
8823b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
883b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
8843b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
8853b03a366Sstefano_zampini   PetscFunctionReturn(0);
8863b03a366Sstefano_zampini }
8873b03a366Sstefano_zampini 
8886726f965SBarry Smith #undef __FUNCT__
8896726f965SBarry Smith #define __FUNCT__ "MatZeroEntries_IS"
8906726f965SBarry Smith PetscErrorCode MatZeroEntries_IS(Mat A)
8916726f965SBarry Smith {
8926726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
8936726f965SBarry Smith   PetscErrorCode ierr;
8946726f965SBarry Smith 
8956726f965SBarry Smith   PetscFunctionBegin;
8966726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
8976726f965SBarry Smith   PetscFunctionReturn(0);
8986726f965SBarry Smith }
8996726f965SBarry Smith 
9006726f965SBarry Smith #undef __FUNCT__
9012e74eeadSLisandro Dalcin #define __FUNCT__ "MatScale_IS"
9022e74eeadSLisandro Dalcin PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
9032e74eeadSLisandro Dalcin {
9042e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
9052e74eeadSLisandro Dalcin   PetscErrorCode ierr;
9062e74eeadSLisandro Dalcin 
9072e74eeadSLisandro Dalcin   PetscFunctionBegin;
9082e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
9092e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
9102e74eeadSLisandro Dalcin }
9112e74eeadSLisandro Dalcin 
9122e74eeadSLisandro Dalcin #undef __FUNCT__
9132e74eeadSLisandro Dalcin #define __FUNCT__ "MatGetDiagonal_IS"
9142e74eeadSLisandro Dalcin PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
9152e74eeadSLisandro Dalcin {
9162e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
9172e74eeadSLisandro Dalcin   PetscErrorCode ierr;
9182e74eeadSLisandro Dalcin 
9192e74eeadSLisandro Dalcin   PetscFunctionBegin;
9202e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
921e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
9222e74eeadSLisandro Dalcin 
9232e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
9242e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
925e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
926e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
9272e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
9282e74eeadSLisandro Dalcin }
9292e74eeadSLisandro Dalcin 
9302e74eeadSLisandro Dalcin #undef __FUNCT__
9316726f965SBarry Smith #define __FUNCT__ "MatSetOption_IS"
932ace3abfcSBarry Smith PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
9336726f965SBarry Smith {
9346726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
9356726f965SBarry Smith   PetscErrorCode ierr;
9366726f965SBarry Smith 
9376726f965SBarry Smith   PetscFunctionBegin;
9384e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
9396726f965SBarry Smith   PetscFunctionReturn(0);
9406726f965SBarry Smith }
9416726f965SBarry Smith 
942284134d9SBarry Smith #undef __FUNCT__
943284134d9SBarry Smith #define __FUNCT__ "MatCreateIS"
944284134d9SBarry Smith /*@
945284134d9SBarry Smith     MatCreateIS - Creates a "process" unassmembled matrix, it is assembled on each
946284134d9SBarry Smith        process but not across processes.
947284134d9SBarry Smith 
948284134d9SBarry Smith    Input Parameters:
949284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
950e176bc59SStefano Zampini .     bs      - block size of the matrix
951df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
952e176bc59SStefano Zampini .     rmap    - local to global map for rows
953e176bc59SStefano Zampini -     cmap    - local to global map for cols
954284134d9SBarry Smith 
955284134d9SBarry Smith    Output Parameter:
956284134d9SBarry Smith .    A - the resulting matrix
957284134d9SBarry Smith 
9588e6c10adSSatish Balay    Level: advanced
9598e6c10adSSatish Balay 
960284134d9SBarry Smith    Notes: See MATIS for more details
9618cda6cd7SBarry Smith           m and n are NOT related to the size of the map, they are the size of the part of the vector owned
962e176bc59SStefano Zampini           by that process. The sizes of rmap and cmap define the size of the local matrices.
963e176bc59SStefano Zampini           If either rmap or cmap are NULL, than the matrix is assumed to be square
964284134d9SBarry Smith 
965284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
966284134d9SBarry Smith @*/
967e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
968284134d9SBarry Smith {
969284134d9SBarry Smith   PetscErrorCode ierr;
970284134d9SBarry Smith 
971284134d9SBarry Smith   PetscFunctionBegin;
972e176bc59SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mapping");
973284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
974284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
9754f619741Sstefano_zampini   ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
976284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
9773b03a366Sstefano_zampini   ierr = MatSetUp(*A);CHKERRQ(ierr);
978e176bc59SStefano Zampini   if (rmap && cmap) {
979e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
980e176bc59SStefano Zampini   } else if (!rmap) {
981e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
982e176bc59SStefano Zampini   } else {
983e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
984e176bc59SStefano Zampini   }
985284134d9SBarry Smith   PetscFunctionReturn(0);
986284134d9SBarry Smith }
987284134d9SBarry Smith 
988b4319ba4SBarry Smith /*MC
989eb82efa4SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition type preconditioners (e.g. PCBDDC).
990b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
991b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
992b4319ba4SBarry Smith    product is handled "implicitly".
993b4319ba4SBarry Smith 
994b4319ba4SBarry Smith    Operations Provided:
9956726f965SBarry Smith +  MatMult()
9962e74eeadSLisandro Dalcin .  MatMultAdd()
9972e74eeadSLisandro Dalcin .  MatMultTranspose()
9982e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
9996726f965SBarry Smith .  MatZeroEntries()
10006726f965SBarry Smith .  MatSetOption()
10012e74eeadSLisandro Dalcin .  MatZeroRows()
10026726f965SBarry Smith .  MatZeroRowsLocal()
10032e74eeadSLisandro Dalcin .  MatSetValues()
10046726f965SBarry Smith .  MatSetValuesLocal()
10052e74eeadSLisandro Dalcin .  MatScale()
10062e74eeadSLisandro Dalcin .  MatGetDiagonal()
10076726f965SBarry Smith -  MatSetLocalToGlobalMapping()
1008b4319ba4SBarry Smith 
1009b4319ba4SBarry Smith    Options Database Keys:
1010b4319ba4SBarry Smith . -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
1011b4319ba4SBarry Smith 
1012b4319ba4SBarry Smith    Notes: Options prefix for the inner matrix are given by -is_mat_xxx
1013b4319ba4SBarry Smith 
1014b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
1015b4319ba4SBarry Smith 
1016b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
1017eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
1018b4319ba4SBarry Smith 
1019b4319ba4SBarry Smith   Level: advanced
1020b4319ba4SBarry Smith 
1021eb82efa4SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), PCBDDC
1022b4319ba4SBarry Smith 
1023b4319ba4SBarry Smith M*/
1024b4319ba4SBarry Smith 
1025b4319ba4SBarry Smith #undef __FUNCT__
1026b4319ba4SBarry Smith #define __FUNCT__ "MatCreate_IS"
10278cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
1028b4319ba4SBarry Smith {
1029dfbe8321SBarry Smith   PetscErrorCode ierr;
1030b4319ba4SBarry Smith   Mat_IS         *b;
1031b4319ba4SBarry Smith 
1032b4319ba4SBarry Smith   PetscFunctionBegin;
1033b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
1034b4319ba4SBarry Smith   A->data = (void*)b;
1035b4319ba4SBarry Smith 
1036e176bc59SStefano Zampini   /* matrix ops */
1037e176bc59SStefano Zampini   ierr    = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
1038b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
10392e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
10402e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
10412e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
1042b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
1043b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
10442e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
1045b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
1046f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
10472e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
1048b4319ba4SBarry Smith   A->ops->zerorowslocal           = MatZeroRowsLocal_IS;
1049b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
1050b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
1051b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
10526726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
10532e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
10542e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
10556726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
105669796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
105769796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
1058ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
1059b4319ba4SBarry Smith 
1060b7ce53b6SStefano Zampini   /* special MATIS functions */
1061bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
1062bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
1063b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatISGetMPIXAIJ_IS);CHKERRQ(ierr);
10642e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
106517667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
1066b4319ba4SBarry Smith   PetscFunctionReturn(0);
1067b4319ba4SBarry Smith }
1068