xref: /petsc/src/mat/utils/convert.c (revision 2f8a729c95982efb3e50c82c45a5cc0e4d951579)
1 #ifndef lint
2 static char vcid[] = "$Id: convert.c,v 1.37 1995/11/21 03:09:43 curfman Exp bsmith $";
3 #endif
4 
5 #include "mpiaij.h"
6 #include "mpibdiag.h"
7 
8 /* This file contains a generic conversion routine and implementation specific
9    versions for increased efficiency. */
10 
11 /*
12   MatConvert_Basic - Converts from any input format to another format. For
13   parallel formats, the new matrix distribution is determined by PETSc.
14  */
15 int MatConvert_Basic(Mat mat,MatType newtype,Mat *M)
16 {
17   Scalar *vwork;
18   int    ierr, i, nz, m, n, *cwork, rstart, rend;
19   ierr = MatGetSize(mat,&m,&n); CHKERRQ(ierr);
20   if (newtype == MATSAME) newtype = (MatType)mat->type;
21   switch (newtype) {
22     case MATSEQAIJ:
23       ierr = MatCreateSeqAIJ(mat->comm,m,n,0,0,M); CHKERRQ(ierr);
24       break;
25     case MATSEQROW:
26       ierr = MatCreateSeqRow(mat->comm,m,n,0,0,M); CHKERRQ(ierr);
27       break;
28     case MATMPIROW:
29       ierr = MatCreateMPIRow(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
30                              m,n,0,0,0,0,M); CHKERRQ(ierr);
31       break;
32     case MATMPIROWBS:
33       if (m != n) SETERRQ(1,"MatConvert:MATMPIROWBS matrix must be square");
34       ierr = MatCreateMPIRowbs(MPI_COMM_WORLD,PETSC_DECIDE,m,0,0,0,M);
35              CHKERRQ(ierr);
36       break;
37     case MATMPIAIJ:
38       ierr = MatCreateMPIAIJ(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
39                              m,n,0,0,0,0,M); CHKERRQ(ierr);
40       break;
41     case MATSEQDENSE:
42       ierr = MatCreateSeqDense(mat->comm,m,n,0,M); CHKERRQ(ierr);
43       break;
44     case MATMPIDENSE:
45       ierr = MatCreateMPIDense(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
46                                m,n,0,M); CHKERRQ(ierr);
47       break;
48     case MATSEQBDIAG:
49       {
50       int nb = 1; /* Default block size = 1 */
51       OptionsGetInt(PetscNull,"-mat_bdiag_bsize",&nb);
52       ierr = MatCreateSeqBDiag(mat->comm,m,n,0,nb,0,0,M); CHKERRQ(ierr);
53       break;
54       }
55     case MATMPIBDIAG:
56       {
57       int nb = 1; /* Default block size = 1 */
58       OptionsGetInt(PetscNull,"-mat_bdiag_bsize",&nb);
59       ierr = MatCreateMPIBDiag(MPI_COMM_WORLD,PETSC_DECIDE,m,n,0,nb,0,0,M);
60       CHKERRQ(ierr);
61       break;
62       }
63     default:
64       SETERRQ(1,"MatConvert:Matrix type is not currently supported");
65   }
66   ierr = MatGetOwnershipRange(*M,&rstart,&rend); CHKERRQ(ierr);
67   for (i=rstart; i<rend; i++) {
68     ierr = MatGetRow(mat,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
69     ierr = MatSetValues(*M,1,&i,nz,cwork,vwork,INSERT_VALUES); CHKERRQ(ierr);
70     ierr = MatRestoreRow(mat,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
71   }
72   ierr = MatAssemblyBegin(*M,FINAL_ASSEMBLY); CHKERRQ(ierr);
73   ierr = MatAssemblyEnd(*M,FINAL_ASSEMBLY); CHKERRQ(ierr);
74   return 0;
75 }
76 /* -------------------------------------------------------------- */
77 /*
78   MatConvert_SeqAIJ - Converts from MATSEQAIJ format to another format. For
79   parallel formats, the new matrix distribution is determined by PETSc.
80  */
81 int MatConvert_SeqAIJ(Mat A, MatType newtype, Mat *B)
82 {
83   Mat_SeqAIJ *a = (Mat_SeqAIJ *) A->data;
84   Scalar     *vwork;
85   int        i, ierr, nz, m = a->m, n = a->n, *cwork, rstart, rend;
86 
87   switch (newtype) {
88     case MATSEQROW:
89       ierr = MatCreateSeqRow(A->comm,m,n,0,a->ilen,B); CHKERRQ(ierr);
90       break;
91     case MATMPIROW:
92       ierr = MatCreateMPIRow(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
93                              m,n,0,0,0,0,B); CHKERRQ(ierr);
94       break;
95     case MATMPIROWBS:
96       if (m != n) SETERRQ(1,"MatConvert_SeqAIJ:MATMPIROWBS matrix must be square");
97       ierr = MatCreateMPIRowbs(MPI_COMM_WORLD,PETSC_DECIDE,m,0,0,0,B); CHKERRQ(ierr);
98       break;
99     case MATMPIAIJ:
100       ierr = MatCreateMPIAIJ(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
101                              m,n,0,0,0,0,B); CHKERRQ(ierr);
102       break;
103     case MATSEQDENSE:
104       ierr = MatCreateSeqDense(A->comm,m,n,0,B); CHKERRQ(ierr);
105       break;
106     case MATMPIDENSE:
107       ierr = MatCreateMPIDense(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
108                                m,n,0,B); CHKERRQ(ierr);
109       break;
110     case MATSEQBDIAG:
111       {
112       int nb = 1; /* Default block size = 1 */
113       OptionsGetInt(PetscNull,"-mat_bdiag_bsize",&nb);
114       ierr = MatCreateSeqBDiag(A->comm,m,n,0,nb,0,0,B); CHKERRQ(ierr);
115       break;
116       }
117     case MATMPIBDIAG:
118       {
119       int nb = 1; /* Default block size = 1 */
120       OptionsGetInt(PetscNull,"-mat_bdiag_bsize",&nb);
121       ierr = MatCreateMPIBDiag(MPI_COMM_WORLD,PETSC_DECIDE,m,n,0,nb,0,0,B);
122       CHKERRQ(ierr);
123       break;
124       }
125     default:
126       SETERRQ(1,"MatConvert_SeqAIJ:Matrix type is not currently supported");
127   }
128   ierr = MatGetOwnershipRange(*B,&rstart,&rend); CHKERRQ(ierr);
129   for (i=rstart; i<rend; i++) {
130     ierr = MatGetRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
131     ierr = MatSetValues(*B,1,&i,nz,cwork,vwork,INSERT_VALUES); CHKERRQ(ierr);
132     ierr = MatRestoreRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
133   }
134   ierr = MatAssemblyBegin(*B,FINAL_ASSEMBLY); CHKERRQ(ierr);
135   ierr = MatAssemblyEnd(*B,FINAL_ASSEMBLY); CHKERRQ(ierr);
136   return 0;
137 }
138 /* ------------------------------------------------------------------ */
139 /*
140   MatConvert_MPIAIJ - Converts from MATMPIAIJ format to another
141   parallel format.
142  */
143 int MatConvert_MPIAIJ(Mat A, MatType newtype, Mat *B)
144 {
145   Mat_MPIAIJ *a = (Mat_MPIAIJ *) A->data;
146   Mat_SeqAIJ *Ad = (Mat_SeqAIJ *)(a->A->data), *Bd = (Mat_SeqAIJ *)(a->B->data);
147   int        ierr, nz, i, ig, rstart = a->rstart, m = a->m, *cwork;
148   Scalar     *vwork;
149 
150   switch (newtype) {
151     case MATMPIROW:
152       ierr = MatCreateMPIRow(A->comm,m,a->n,a->M,a->N,0,Ad->ilen,
153 			0,Bd->ilen,B); CHKERRQ(ierr);
154       break;
155     default:
156       SETERRQ(1,"MatConvert_MPIAIJ:Only MATMPIROW is currently suported");
157   }
158   /* Each processor converts its local rows */
159   for (i=0; i<m; i++) {
160     ig   = i + rstart;
161     ierr = MatGetRow(A,ig,&nz,&cwork,&vwork);	CHKERRQ(ierr);
162     ierr = MatSetValues(*B,1,&ig,nz,cwork,vwork,INSERT_VALUES); CHKERRQ(ierr);
163     ierr = MatRestoreRow(A,ig,&nz,&cwork,&vwork); CHKERRQ(ierr);
164   }
165   ierr = MatAssemblyBegin(*B,FINAL_ASSEMBLY); CHKERRQ(ierr);
166   ierr = MatAssemblyEnd(*B,FINAL_ASSEMBLY); CHKERRQ(ierr);
167   return 0;
168 }
169 /* ------------------------------------------------------------------ */
170 /*
171   MatConvert_SeqBDiag - Converts from MATSEQBDiag format to another format. For
172   parallel formats, the new matrix distribution is determined by PETSc.
173  */
174 int MatConvert_SeqBDiag(Mat A, MatType newtype, Mat *B)
175 {
176   Mat_SeqBDiag *a = (Mat_SeqBDiag *) A->data;
177   Scalar       *vwork, *vw2;
178   int          i, ierr, nz, m = a->m, n = a->n, *cwork, rstart, rend;
179   int          j, *cw2, ict;
180 
181   /* rough over-estimate; could refine for individual rows */
182   nz = PetscMin(n,a->nd*a->nb);
183   switch (newtype) {
184     case MATSEQAIJ:
185       ierr = MatCreateSeqAIJ(A->comm,m,n,nz,0,B); CHKERRQ(ierr);
186       break;
187     case MATSEQROW:
188       ierr = MatCreateSeqRow(A->comm,m,n,nz,0,B); CHKERRQ(ierr);
189       break;
190     case MATMPIROW:
191       ierr = MatCreateMPIRow(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
192                              m,n,0,0,0,0,B); CHKERRQ(ierr);
193       break;
194     case MATMPIROWBS:
195       if (m != n) SETERRQ(1,"MatConvert_SeqBDiag:MATMPIROWBS matrix must be square");
196       ierr = MatCreateMPIRowbs(MPI_COMM_WORLD,PETSC_DECIDE,m,0,0,0,B); CHKERRQ(ierr);
197       break;
198     case MATMPIAIJ:
199       ierr = MatCreateMPIAIJ(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
200                              m,n,0,0,0,0,B); CHKERRQ(ierr);
201       break;
202     case MATSEQDENSE:
203       ierr = MatCreateSeqDense(A->comm,m,n,0,B); CHKERRQ(ierr);
204       break;
205     case MATMPIDENSE:
206       ierr = MatCreateMPIDense(MPI_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,
207                                m,n,0,B); CHKERRQ(ierr);
208       break;
209     case MATMPIBDIAG:
210       {
211       ierr = MatCreateMPIBDiag(MPI_COMM_WORLD,PETSC_DECIDE,m,n,a->nd,a->nb,0,0,B);
212       CHKERRQ(ierr);
213       break;
214       }
215     default:
216       SETERRQ(1,"MatConvert_SeqBDiag:Matrix type is not currently supported");
217   }
218   ierr = MatGetOwnershipRange(*B,&rstart,&rend); CHKERRQ(ierr);
219 
220   cw2 = (int *)PetscMalloc( n * sizeof(int) ); CHKPTRQ(cw2);
221   vw2 = (Scalar *)PetscMalloc( n * sizeof(Scalar) ); CHKPTRQ(vw2);
222   for (i=rstart; i<rend; i++) {
223    ierr = MatGetRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
224    ict = 0; /* strip out the zero elements ... is this what we really want? */
225    for (j=0; j<nz; j++) {
226      if (vwork[j] != 0) {vw2[ict] = vwork[j]; cw2[ict] = cwork[j]; ict++;}
227    }
228    if (ict)
229      {ierr = MatSetValues(*B,1,&i,ict,cw2,vw2,INSERT_VALUES); CHKERRQ(ierr);}
230    ierr = MatRestoreRow(A,i,&nz,&cwork,&vwork); CHKERRQ(ierr);
231   }
232   PetscFree(cw2); PetscFree(vw2);
233   ierr = MatAssemblyBegin(*B,FINAL_ASSEMBLY); CHKERRQ(ierr);
234   ierr = MatAssemblyEnd(*B,FINAL_ASSEMBLY); CHKERRQ(ierr);
235   return 0;
236 }
237