xref: /petsc/src/mat/utils/convert.c (revision 25cdf11f00656cd6142ccc252ca9e2f99af554b2)
156fe5c5cSLois Curfman McInnes #ifndef lint
2*25cdf11fSBarry Smith static char vcid[] = "$Id: convert.c,v 1.40 1995/12/21 18:33:04 bsmith Exp bsmith $";
356fe5c5cSLois Curfman McInnes #endif
456fe5c5cSLois Curfman McInnes 
556fe5c5cSLois Curfman McInnes #include "mpiaij.h"
68b6375c0SLois Curfman McInnes #include "mpibdiag.h"
756fe5c5cSLois Curfman McInnes 
88b6375c0SLois Curfman McInnes /* This file contains a generic conversion routine and implementation specific
98b6375c0SLois Curfman McInnes    versions for increased efficiency. */
108b6375c0SLois Curfman McInnes 
118b6375c0SLois Curfman McInnes /*
128b6375c0SLois Curfman McInnes   MatConvert_Basic - Converts from any input format to another format. For
138b6375c0SLois Curfman McInnes   parallel formats, the new matrix distribution is determined by PETSc.
148b6375c0SLois Curfman McInnes  */
158b6375c0SLois Curfman McInnes int MatConvert_Basic(Mat mat,MatType newtype,Mat *M)
168b6375c0SLois Curfman McInnes {
178b6375c0SLois Curfman McInnes   Scalar *vwork;
18*25cdf11fSBarry Smith   int    ierr, i, nz, m, n, *cwork, rstart, rend,flg;
19*25cdf11fSBarry Smith 
208b6375c0SLois Curfman McInnes   ierr = MatGetSize(mat,&m,&n); CHKERRQ(ierr);
217181dc05SLois Curfman McInnes   if (newtype == MATSAME) newtype = (MatType)mat->type;
228b6375c0SLois Curfman McInnes   switch (newtype) {
238b6375c0SLois Curfman McInnes     case MATSEQAIJ:
24b4fd4287SBarry Smith       ierr = MatCreateSeqAIJ(mat->comm,m,n,0,PETSC_NULL,M); CHKERRQ(ierr);
258b6375c0SLois Curfman McInnes       break;
268b6375c0SLois Curfman McInnes     case MATSEQROW:
27b4fd4287SBarry Smith       ierr = MatCreateSeqRow(mat->comm,m,n,0,PETSC_NULL,M); CHKERRQ(ierr);
288b6375c0SLois Curfman McInnes       break;
298b6375c0SLois Curfman McInnes     case MATMPIROW:
308b6375c0SLois Curfman McInnes       ierr = MatCreateMPIRow(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
31b4fd4287SBarry Smith              m,n,0,PETSC_NULL,0,PETSC_NULL,M); CHKERRQ(ierr);
328b6375c0SLois Curfman McInnes       break;
338b6375c0SLois Curfman McInnes     case MATMPIROWBS:
348b6375c0SLois Curfman McInnes       if (m != n) SETERRQ(1,"MatConvert:MATMPIROWBS matrix must be square");
35b4fd4287SBarry Smith       ierr = MatCreateMPIRowbs(MPI_COMM_WORLD,PETSC_DECIDE,m,0,PETSC_NULL,
36b4fd4287SBarry Smith              PETSC_NULL,M); CHKERRQ(ierr);
378b6375c0SLois Curfman McInnes       break;
388b6375c0SLois Curfman McInnes     case MATMPIAIJ:
398b6375c0SLois Curfman McInnes       ierr = MatCreateMPIAIJ(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
40b4fd4287SBarry Smith              m,n,0,PETSC_NULL,0,PETSC_NULL,M); CHKERRQ(ierr);
418b6375c0SLois Curfman McInnes       break;
428b6375c0SLois Curfman McInnes     case MATSEQDENSE:
43b4fd4287SBarry Smith       ierr = MatCreateSeqDense(mat->comm,m,n,PETSC_NULL,M); CHKERRQ(ierr);
448b6375c0SLois Curfman McInnes       break;
458b6375c0SLois Curfman McInnes     case MATMPIDENSE:
468b6375c0SLois Curfman McInnes       ierr = MatCreateMPIDense(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
47b4fd4287SBarry Smith              m,n,PETSC_NULL,M); CHKERRQ(ierr);
488b6375c0SLois Curfman McInnes       break;
498b6375c0SLois Curfman McInnes     case MATSEQBDIAG:
508b6375c0SLois Curfman McInnes       {
518b6375c0SLois Curfman McInnes       int nb = 1; /* Default block size = 1 */
52*25cdf11fSBarry Smith       ierr = OptionsGetInt(PETSC_NULL,"-mat_bdiag_bsize",&nb,&flg);  CHKERRQ(ierr);
53b4fd4287SBarry Smith       ierr = MatCreateSeqBDiag(mat->comm,m,n,0,nb,PETSC_NULL,PETSC_NULL,M); CHKERRQ(ierr);
548b6375c0SLois Curfman McInnes       break;
558b6375c0SLois Curfman McInnes       }
568b6375c0SLois Curfman McInnes     case MATMPIBDIAG:
578b6375c0SLois Curfman McInnes       {
588b6375c0SLois Curfman McInnes       int nb = 1; /* Default block size = 1 */
59*25cdf11fSBarry Smith       ierr = OptionsGetInt(PETSC_NULL,"-mat_bdiag_bsize",&nb,&flg);   CHKERRQ(ierr);
60b4fd4287SBarry Smith       ierr = MatCreateMPIBDiag(MPI_COMM_WORLD,PETSC_DECIDE,m,n,0,nb,PETSC_NULL,
61b4fd4287SBarry Smith              PETSC_NULL,M); CHKERRQ(ierr);
628b6375c0SLois Curfman McInnes       break;
638b6375c0SLois Curfman McInnes       }
648b6375c0SLois Curfman McInnes     default:
658b6375c0SLois Curfman McInnes       SETERRQ(1,"MatConvert:Matrix type is not currently supported");
668b6375c0SLois Curfman McInnes   }
678b6375c0SLois Curfman McInnes   ierr = MatGetOwnershipRange(*M,&rstart,&rend); CHKERRQ(ierr);
688b6375c0SLois Curfman McInnes   for (i=rstart; i<rend; i++) {
698b6375c0SLois Curfman McInnes     ierr = MatGetRow(mat,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
708b6375c0SLois Curfman McInnes     ierr = MatSetValues(*M,1,&i,nz,cwork,vwork,INSERT_VALUES); CHKERRQ(ierr);
718b6375c0SLois Curfman McInnes     ierr = MatRestoreRow(mat,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
728b6375c0SLois Curfman McInnes   }
738b6375c0SLois Curfman McInnes   ierr = MatAssemblyBegin(*M,FINAL_ASSEMBLY); CHKERRQ(ierr);
748b6375c0SLois Curfman McInnes   ierr = MatAssemblyEnd(*M,FINAL_ASSEMBLY); CHKERRQ(ierr);
758b6375c0SLois Curfman McInnes   return 0;
768b6375c0SLois Curfman McInnes }
778b6375c0SLois Curfman McInnes /* -------------------------------------------------------------- */
7856fe5c5cSLois Curfman McInnes /*
79ec8511deSBarry Smith   MatConvert_SeqAIJ - Converts from MATSEQAIJ format to another format. For
8044ae05bdSLois Curfman McInnes   parallel formats, the new matrix distribution is determined by PETSc.
8156fe5c5cSLois Curfman McInnes  */
822399e097SLois Curfman McInnes int MatConvert_SeqAIJ(Mat A, MatType newtype, Mat *B)
8356fe5c5cSLois Curfman McInnes {
842399e097SLois Curfman McInnes   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
8556fe5c5cSLois Curfman McInnes   Scalar     *vwork;
862399e097SLois Curfman McInnes   int        i, ierr, nz, m = a->m, n = a->n, *cwork, rstart, rend;
8756fe5c5cSLois Curfman McInnes 
8856fe5c5cSLois Curfman McInnes   switch (newtype) {
89ec8511deSBarry Smith     case MATSEQROW:
902399e097SLois Curfman McInnes       ierr = MatCreateSeqRow(A->comm,m,n,0,a->ilen,B); CHKERRQ(ierr);
91416022c9SBarry Smith       break;
9244ae05bdSLois Curfman McInnes     case MATMPIROW:
9344ae05bdSLois Curfman McInnes       ierr = MatCreateMPIRow(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
94b4fd4287SBarry Smith              m,n,0,PETSC_NULL,0,PETSC_NULL,B); CHKERRQ(ierr);
95416022c9SBarry Smith       break;
96ec8511deSBarry Smith     case MATMPIROWBS:
972399e097SLois Curfman McInnes       if (m != n) SETERRQ(1,"MatConvert_SeqAIJ:MATMPIROWBS matrix must be square");
98b4fd4287SBarry Smith       ierr = MatCreateMPIRowbs(MPI_COMM_WORLD,PETSC_DECIDE,m,0,PETSC_NULL,PETSC_NULL,B);
99ed2daf61SLois Curfman McInnes              CHKERRQ(ierr);
100416022c9SBarry Smith       break;
10144ae05bdSLois Curfman McInnes     case MATMPIAIJ:
10244ae05bdSLois Curfman McInnes       ierr = MatCreateMPIAIJ(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
103b4fd4287SBarry Smith              m,n,0,PETSC_NULL,0,PETSC_NULL,B); CHKERRQ(ierr);
104416022c9SBarry Smith       break;
105ec8511deSBarry Smith     case MATSEQDENSE:
106b4fd4287SBarry Smith       ierr = MatCreateSeqDense(A->comm,m,n,PETSC_NULL,B); CHKERRQ(ierr);
1072399e097SLois Curfman McInnes       break;
1082399e097SLois Curfman McInnes     case MATMPIDENSE:
1092399e097SLois Curfman McInnes       ierr = MatCreateMPIDense(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
110b4fd4287SBarry Smith              m,n,PETSC_NULL,B); CHKERRQ(ierr);
111416022c9SBarry Smith       break;
112ec8511deSBarry Smith     case MATSEQBDIAG:
113416022c9SBarry Smith       {
11458154824SLois Curfman McInnes       int nb = 1; /* Default block size = 1 */
115*25cdf11fSBarry Smith       ierr = OptionsGetInt(PETSC_NULL,"-mat_bdiag_bsize",&nb,&flg);  CHKERRQ(ierr);
116b4fd4287SBarry Smith       ierr = MatCreateSeqBDiag(A->comm,m,n,0,nb,PETSC_NULL,PETSC_NULL,B); CHKERRQ(ierr);
11744ae05bdSLois Curfman McInnes       break;
11844ae05bdSLois Curfman McInnes       }
11944ae05bdSLois Curfman McInnes     case MATMPIBDIAG:
120416022c9SBarry Smith       {
12158154824SLois Curfman McInnes       int nb = 1; /* Default block size = 1 */
122*25cdf11fSBarry Smith       ierr = OptionsGetInt(PETSC_NULL,"-mat_bdiag_bsize",&nb,&flg); CHKERRQ(ierr);
123b4fd4287SBarry Smith       ierr = MatCreateMPIBDiag(MPI_COMM_WORLD,PETSC_DECIDE,m,n,0,nb,PETSC_NULL,
124b4fd4287SBarry Smith              PETSC_NULL,B); CHKERRQ(ierr);
125416022c9SBarry Smith       break;
12656fe5c5cSLois Curfman McInnes       }
127f3ba505bSLois Curfman McInnes     default:
128ec8511deSBarry Smith       SETERRQ(1,"MatConvert_SeqAIJ:Matrix type is not currently supported");
129f3ba505bSLois Curfman McInnes   }
1302399e097SLois Curfman McInnes   ierr = MatGetOwnershipRange(*B,&rstart,&rend); CHKERRQ(ierr);
13144ae05bdSLois Curfman McInnes   for (i=rstart; i<rend; i++) {
1322399e097SLois Curfman McInnes     ierr = MatGetRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
1332399e097SLois Curfman McInnes     ierr = MatSetValues(*B,1,&i,nz,cwork,vwork,INSERT_VALUES); CHKERRQ(ierr);
1342399e097SLois Curfman McInnes     ierr = MatRestoreRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
13556fe5c5cSLois Curfman McInnes   }
1362399e097SLois Curfman McInnes   ierr = MatAssemblyBegin(*B,FINAL_ASSEMBLY); CHKERRQ(ierr);
1372399e097SLois Curfman McInnes   ierr = MatAssemblyEnd(*B,FINAL_ASSEMBLY); CHKERRQ(ierr);
13856fe5c5cSLois Curfman McInnes   return 0;
13956fe5c5cSLois Curfman McInnes }
14056fe5c5cSLois Curfman McInnes /* ------------------------------------------------------------------ */
14156fe5c5cSLois Curfman McInnes /*
1421fb19edaSLois Curfman McInnes   MatConvert_MPIAIJ - Converts from MATMPIAIJ format to another
14356fe5c5cSLois Curfman McInnes   parallel format.
14456fe5c5cSLois Curfman McInnes  */
1452399e097SLois Curfman McInnes int MatConvert_MPIAIJ(Mat A, MatType newtype, Mat *B)
14656fe5c5cSLois Curfman McInnes {
1472399e097SLois Curfman McInnes   Mat_MPIAIJ *a = (Mat_MPIAIJ *) A->data;
1482399e097SLois Curfman McInnes   Mat_SeqAIJ *Ad = (Mat_SeqAIJ *)(a->A->data), *Bd = (Mat_SeqAIJ *)(a->B->data);
1492399e097SLois Curfman McInnes   int        ierr, nz, i, ig, rstart = a->rstart, m = a->m, *cwork;
15056fe5c5cSLois Curfman McInnes   Scalar     *vwork;
15156fe5c5cSLois Curfman McInnes 
15256fe5c5cSLois Curfman McInnes   switch (newtype) {
1531fb19edaSLois Curfman McInnes     case MATMPIROW:
1542399e097SLois Curfman McInnes       ierr = MatCreateMPIRow(A->comm,m,a->n,a->M,a->N,0,Ad->ilen,
1552399e097SLois Curfman McInnes              0,Bd->ilen,B); CHKERRQ(ierr);
156abc0e9e4SLois Curfman McInnes       break;
15756fe5c5cSLois Curfman McInnes     default:
158bbb6d6a8SBarry Smith       SETERRQ(1,"MatConvert_MPIAIJ:Only MATMPIROW is currently suported");
15956fe5c5cSLois Curfman McInnes   }
160abc0e9e4SLois Curfman McInnes   /* Each processor converts its local rows */
16156fe5c5cSLois Curfman McInnes   for (i=0; i<m; i++) {
16256fe5c5cSLois Curfman McInnes     ig   = i + rstart;
1632399e097SLois Curfman McInnes     ierr = MatGetRow(A,ig,&nz,&cwork,&vwork); CHKERRQ(ierr);
1642399e097SLois Curfman McInnes     ierr = MatSetValues(*B,1,&ig,nz,cwork,vwork,INSERT_VALUES); CHKERRQ(ierr);
1652399e097SLois Curfman McInnes     ierr = MatRestoreRow(A,ig,&nz,&cwork,&vwork); CHKERRQ(ierr);
16656fe5c5cSLois Curfman McInnes   }
1672399e097SLois Curfman McInnes   ierr = MatAssemblyBegin(*B,FINAL_ASSEMBLY); CHKERRQ(ierr);
1682399e097SLois Curfman McInnes   ierr = MatAssemblyEnd(*B,FINAL_ASSEMBLY); CHKERRQ(ierr);
16956fe5c5cSLois Curfman McInnes   return 0;
17056fe5c5cSLois Curfman McInnes }
1718b6375c0SLois Curfman McInnes /* ------------------------------------------------------------------ */
172567e79a1SLois Curfman McInnes /*
173567e79a1SLois Curfman McInnes   MatConvert_SeqBDiag - Converts from MATSEQBDiag format to another format. For
174567e79a1SLois Curfman McInnes   parallel formats, the new matrix distribution is determined by PETSc.
175567e79a1SLois Curfman McInnes  */
176567e79a1SLois Curfman McInnes int MatConvert_SeqBDiag(Mat A, MatType newtype, Mat *B)
177567e79a1SLois Curfman McInnes {
178567e79a1SLois Curfman McInnes   Mat_SeqBDiag *a = (Mat_SeqBDiag *) A->data;
1798b6375c0SLois Curfman McInnes   Scalar       *vwork, *vw2;
180567e79a1SLois Curfman McInnes   int          i, ierr, nz, m = a->m, n = a->n, *cwork, rstart, rend;
1818b6375c0SLois Curfman McInnes   int          j, *cw2, ict;
182567e79a1SLois Curfman McInnes 
183dad23ff5SLois Curfman McInnes   /* rough over-estimate; could refine for individual rows */
1840452661fSBarry Smith   nz = PetscMin(n,a->nd*a->nb);
185567e79a1SLois Curfman McInnes   switch (newtype) {
186567e79a1SLois Curfman McInnes     case MATSEQAIJ:
187b4fd4287SBarry Smith       ierr = MatCreateSeqAIJ(A->comm,m,n,nz,PETSC_NULL,B); CHKERRQ(ierr);
188567e79a1SLois Curfman McInnes       break;
189567e79a1SLois Curfman McInnes     case MATSEQROW:
190b4fd4287SBarry Smith       ierr = MatCreateSeqRow(A->comm,m,n,nz,PETSC_NULL,B); CHKERRQ(ierr);
191567e79a1SLois Curfman McInnes       break;
192567e79a1SLois Curfman McInnes     case MATMPIROW:
193567e79a1SLois Curfman McInnes       ierr = MatCreateMPIRow(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
194b4fd4287SBarry Smith                              m,n,0,PETSC_NULL,0,PETSC_NULL,B); CHKERRQ(ierr);
195567e79a1SLois Curfman McInnes       break;
196567e79a1SLois Curfman McInnes     case MATMPIROWBS:
197567e79a1SLois Curfman McInnes       if (m != n) SETERRQ(1,"MatConvert_SeqBDiag:MATMPIROWBS matrix must be square");
198b4fd4287SBarry Smith       ierr = MatCreateMPIRowbs(MPI_COMM_WORLD,PETSC_DECIDE,m,0,PETSC_NULL,PETSC_NULL,
199ed2daf61SLois Curfman McInnes              B); CHKERRQ(ierr);
200567e79a1SLois Curfman McInnes       break;
201567e79a1SLois Curfman McInnes     case MATMPIAIJ:
202567e79a1SLois Curfman McInnes       ierr = MatCreateMPIAIJ(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
203b4fd4287SBarry Smith                              m,n,0,PETSC_NULL,0,PETSC_NULL,B); CHKERRQ(ierr);
204567e79a1SLois Curfman McInnes       break;
205567e79a1SLois Curfman McInnes     case MATSEQDENSE:
206b4fd4287SBarry Smith       ierr = MatCreateSeqDense(A->comm,m,n,PETSC_NULL,B); CHKERRQ(ierr);
207567e79a1SLois Curfman McInnes       break;
208567e79a1SLois Curfman McInnes     case MATMPIDENSE:
209567e79a1SLois Curfman McInnes       ierr = MatCreateMPIDense(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
210b4fd4287SBarry Smith                                m,n,PETSC_NULL,B); CHKERRQ(ierr);
211567e79a1SLois Curfman McInnes       break;
212567e79a1SLois Curfman McInnes     case MATMPIBDIAG:
213567e79a1SLois Curfman McInnes       {
214ed2daf61SLois Curfman McInnes       ierr = MatCreateMPIBDiag(MPI_COMM_WORLD,PETSC_DECIDE,m,n,a->nd,a->nb,
215b4fd4287SBarry Smith              PETSC_NULL,PETSC_NULL,B); CHKERRQ(ierr);
216567e79a1SLois Curfman McInnes       break;
217567e79a1SLois Curfman McInnes       }
218567e79a1SLois Curfman McInnes     default:
219567e79a1SLois Curfman McInnes       SETERRQ(1,"MatConvert_SeqBDiag:Matrix type is not currently supported");
220567e79a1SLois Curfman McInnes   }
221567e79a1SLois Curfman McInnes   ierr = MatGetOwnershipRange(*B,&rstart,&rend); CHKERRQ(ierr);
2228b6375c0SLois Curfman McInnes 
2230452661fSBarry Smith   cw2 = (int *)PetscMalloc( n * sizeof(int) ); CHKPTRQ(cw2);
2240452661fSBarry Smith   vw2 = (Scalar *)PetscMalloc( n * sizeof(Scalar) ); CHKPTRQ(vw2);
225567e79a1SLois Curfman McInnes   for (i=rstart; i<rend; i++) {
226567e79a1SLois Curfman McInnes    ierr = MatGetRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
2278b6375c0SLois Curfman McInnes    ict = 0; /* strip out the zero elements ... is this what we really want? */
2288b6375c0SLois Curfman McInnes    for (j=0; j<nz; j++) {
2298b6375c0SLois Curfman McInnes      if (vwork[j] != 0) {vw2[ict] = vwork[j]; cw2[ict] = cwork[j]; ict++;}
2308b6375c0SLois Curfman McInnes    }
2318b6375c0SLois Curfman McInnes    if (ict)
2328b6375c0SLois Curfman McInnes      {ierr = MatSetValues(*B,1,&i,ict,cw2,vw2,INSERT_VALUES); CHKERRQ(ierr);}
233567e79a1SLois Curfman McInnes    ierr = MatRestoreRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
234567e79a1SLois Curfman McInnes   }
2350452661fSBarry Smith   PetscFree(cw2); PetscFree(vw2);
236567e79a1SLois Curfman McInnes   ierr = MatAssemblyBegin(*B,FINAL_ASSEMBLY); CHKERRQ(ierr);
237567e79a1SLois Curfman McInnes   ierr = MatAssemblyEnd(*B,FINAL_ASSEMBLY); CHKERRQ(ierr);
238567e79a1SLois Curfman McInnes   return 0;
239567e79a1SLois Curfman McInnes }
240