xref: /petsc/src/mat/utils/axpy.c (revision 6f79c3a498eb7f87007ee26a412c5a5b83c5f8cd)
1*6f79c3a4SBarry Smith #ifndef lint
2*6f79c3a4SBarry Smith static char vcid[] = "$Id: convert.c,v 1.14 1995/05/05 15:57:56 curfman Exp $";
3*6f79c3a4SBarry Smith #endif
4*6f79c3a4SBarry Smith 
5*6f79c3a4SBarry Smith /* Matrix conversion routines.  For now, this supports only AIJ */
6*6f79c3a4SBarry Smith 
7*6f79c3a4SBarry Smith #include "mpiaij.h"
8*6f79c3a4SBarry Smith #include "options.h"
9*6f79c3a4SBarry Smith 
10*6f79c3a4SBarry Smith /* Determines the block diagonals within a subset of a matrix */
11*6f79c3a4SBarry Smith /* For now this is just sequential -- not parallel */
12*6f79c3a4SBarry Smith 
13*6f79c3a4SBarry Smith /*
14*6f79c3a4SBarry Smith    MatDetermineDiagonals_Private - Determines the diagonal structure
15*6f79c3a4SBarry Smith    of a matrix.
16*6f79c3a4SBarry Smith 
17*6f79c3a4SBarry Smith    Input Parameters:
18*6f79c3a4SBarry Smith .  mat - the matrix
19*6f79c3a4SBarry Smith .  nb - block size
20*6f79c3a4SBarry Smith .  irows - rows to use
21*6f79c3a4SBarry Smith .  icols - columns to use
22*6f79c3a4SBarry Smith 
23*6f79c3a4SBarry Smith    Output Parameters:
24*6f79c3a4SBarry Smith .  ndiag - number of diagonals
25*6f79c3a4SBarry Smith .  diagonals - the diagonal numbers
26*6f79c3a4SBarry Smith 
27*6f79c3a4SBarry Smith    Note:  The user must free the diagonals array.
28*6f79c3a4SBarry Smith  */
29*6f79c3a4SBarry Smith 
30*6f79c3a4SBarry Smith int MatDetermineDiagonals_Private(Mat mat,int nb,int newr,int newc,
31*6f79c3a4SBarry Smith             int *rowrange, int *colrange,int *ndiag, int **diagonals)
32*6f79c3a4SBarry Smith {
33*6f79c3a4SBarry Smith   int    nd, clast, cfirst, ierr, nnc, maxd, nz, *col, *cwork, *diag;
34*6f79c3a4SBarry Smith   int    i, j, k, jdiag, cshift, row, dnew, temp;
35*6f79c3a4SBarry Smith   Scalar *v;
36*6f79c3a4SBarry Smith 
37*6f79c3a4SBarry Smith   VALIDHEADER(mat,MAT_COOKIE);
38*6f79c3a4SBarry Smith   if ((newr%nb) || (newc%nb)) SETERR(1,"Invalid block size.");
39*6f79c3a4SBarry Smith   cfirst = colrange[0];
40*6f79c3a4SBarry Smith   clast  = colrange[newc-1];
41*6f79c3a4SBarry Smith   nnc    = clast - cfirst + 1;
42*6f79c3a4SBarry Smith   cwork  = (int *) MALLOC( nnc * sizeof(int) );	CHKPTR(cwork);
43*6f79c3a4SBarry Smith   for (i=0; i<nnc; i++)  cwork[i] = -1;
44*6f79c3a4SBarry Smith   for (i=0; i<newc; i++) cwork[colrange[i]-cfirst] = i;
45*6f79c3a4SBarry Smith 
46*6f79c3a4SBarry Smith   /* Determine which diagonals exist:  compute nd, diag[]: */
47*6f79c3a4SBarry Smith   /* Temporarily ssume diag[0] = 0 (main diagonal) */
48*6f79c3a4SBarry Smith   maxd = newr + newc - 1;	/* maximum possible diagonals */
49*6f79c3a4SBarry Smith   diag = (int *)MALLOC( maxd * sizeof(int) );	CHKPTR(diag);
50*6f79c3a4SBarry Smith   nd = 1;
51*6f79c3a4SBarry Smith   for (i=0; i<maxd; i++) diag[i] = 0;
52*6f79c3a4SBarry Smith   for (i=0; i<newr; i++) {
53*6f79c3a4SBarry Smith     ierr = MatGetRow( mat, rowrange[i], &nz, &col, &v ); CHKERR(ierr);
54*6f79c3a4SBarry Smith     row = i;
55*6f79c3a4SBarry Smith     j   = 0;
56*6f79c3a4SBarry Smith     /* Skip values until we reach the first column */
57*6f79c3a4SBarry Smith     while (j < nz && col[j] < cfirst) j++;
58*6f79c3a4SBarry Smith     while (j < nz) {
59*6f79c3a4SBarry Smith       if (clast < col[j]) break;
60*6f79c3a4SBarry Smith       cshift = cwork[col[j] - cfirst];
61*6f79c3a4SBarry Smith       if (cshift >= 0) {
62*6f79c3a4SBarry Smith         /* Determine if diagonal block already exits for valid colum */
63*6f79c3a4SBarry Smith         dnew = 1;
64*6f79c3a4SBarry Smith         jdiag = row/nb - cshift/nb;
65*6f79c3a4SBarry Smith         for (k=0; k<nd; k++) {
66*6f79c3a4SBarry Smith           if (diag[k] == jdiag) {	/* diagonal exists */
67*6f79c3a4SBarry Smith             dnew = 0;	break;
68*6f79c3a4SBarry Smith           }
69*6f79c3a4SBarry Smith         }
70*6f79c3a4SBarry Smith         if (dnew) {
71*6f79c3a4SBarry Smith 	  diag[nd] = jdiag;
72*6f79c3a4SBarry Smith 	  nd++;
73*6f79c3a4SBarry Smith           if (abs(jdiag) > newr/nb)
74*6f79c3a4SBarry Smith              { printf("ERROR jdiag\n"); }
75*6f79c3a4SBarry Smith         }
76*6f79c3a4SBarry Smith       }
77*6f79c3a4SBarry Smith       j++;
78*6f79c3a4SBarry Smith     }
79*6f79c3a4SBarry Smith     ierr = MatRestoreRow( mat, rowrange[i], &nz, &col, &v ); CHKERR(ierr);
80*6f79c3a4SBarry Smith   }
81*6f79c3a4SBarry Smith   /* Sort diagonals in decreasing order. */
82*6f79c3a4SBarry Smith   for (k=0; k<nd; k++) {
83*6f79c3a4SBarry Smith     for (j=k+1; j<nd; j++) {
84*6f79c3a4SBarry Smith       if (diag[k] < diag[j]) {
85*6f79c3a4SBarry Smith         temp = diag[k];
86*6f79c3a4SBarry Smith         diag[k] = diag[j];
87*6f79c3a4SBarry Smith         diag[j] = temp;
88*6f79c3a4SBarry Smith       }
89*6f79c3a4SBarry Smith     }
90*6f79c3a4SBarry Smith   }
91*6f79c3a4SBarry Smith   FREE( cwork );
92*6f79c3a4SBarry Smith   *ndiag = nd;
93*6f79c3a4SBarry Smith   *diagonals = diag;
94*6f79c3a4SBarry Smith   return 0;
95*6f79c3a4SBarry Smith }
96*6f79c3a4SBarry Smith 
97*6f79c3a4SBarry Smith /*
98*6f79c3a4SBarry Smith   MatConvert_AIJ - Converts from MATAIJ format to another sequential format.
99*6f79c3a4SBarry Smith  */
100*6f79c3a4SBarry Smith int MatConvert_AIJ(Mat mat, MatType newtype, Mat *newmat)
101*6f79c3a4SBarry Smith {
102*6f79c3a4SBarry Smith   Mat_AIJ *aij = (Mat_AIJ *) mat->data;
103*6f79c3a4SBarry Smith   Scalar  *vwork;
104*6f79c3a4SBarry Smith   int     i, ierr, nz, m = aij->m, n = aij->n, *cwork;
105*6f79c3a4SBarry Smith 
106*6f79c3a4SBarry Smith   if (mat->type != MATAIJ) SETERR(1,"Input matrix must be MATAIJ.");
107*6f79c3a4SBarry Smith   switch (newtype) {
108*6f79c3a4SBarry Smith     case MATROW:
109*6f79c3a4SBarry Smith       ierr = MatCreateSequentialRow(mat->comm,m,n,0,aij->ilen,newmat);
110*6f79c3a4SBarry Smith       CHKERR(ierr); break;
111*6f79c3a4SBarry Smith     case MATDENSE:
112*6f79c3a4SBarry Smith       ierr = MatCreateSequentialDense(mat->comm,m,n,newmat);
113*6f79c3a4SBarry Smith       CHKERR(ierr); break;
114*6f79c3a4SBarry Smith     case MATBDIAG:
115*6f79c3a4SBarry Smith     { int nb = 1; /* Default block size = 1 */
116*6f79c3a4SBarry Smith       int ndiag, *diag, *rr, *cr;
117*6f79c3a4SBarry Smith       rr = (int *) MALLOC( (m+n) * sizeof(int) ); CHKPTR(rr);
118*6f79c3a4SBarry Smith       cr = rr + m;
119*6f79c3a4SBarry Smith       for (i=0; i<m; i++) rr[i] = i;
120*6f79c3a4SBarry Smith       for (i=0; i<n; i++) cr[i] = i;
121*6f79c3a4SBarry Smith       OptionsGetInt(0,0,"-mat_bdiag_bsize",&nb);
122*6f79c3a4SBarry Smith       ierr = MatDetermineDiagonals_Private(mat,nb,m,n,rr,cr,&ndiag,&diag);
123*6f79c3a4SBarry Smith       ierr = MatCreateSequentialBDiag(mat->comm,m,n,ndiag,nb,diag,0,newmat);
124*6f79c3a4SBarry Smith       FREE(rr), FREE(diag);
125*6f79c3a4SBarry Smith       CHKERR(ierr); break;
126*6f79c3a4SBarry Smith     }
127*6f79c3a4SBarry Smith     default:
128*6f79c3a4SBarry Smith       SETERR(1,"Only MATROW, MATDENSE, and MATBDIAG are currently supported.");
129*6f79c3a4SBarry Smith   }
130*6f79c3a4SBarry Smith   for (i=0; i<m; i++) {
131*6f79c3a4SBarry Smith     ierr = MatGetRow(mat,i,&nz,&cwork,&vwork); CHKERR(ierr);
132*6f79c3a4SBarry Smith     ierr = MatSetValues(*newmat,1,&i,nz,cwork,vwork,INSERTVALUES);
133*6f79c3a4SBarry Smith            CHKERR(ierr);
134*6f79c3a4SBarry Smith     ierr = MatRestoreRow(mat,i,&nz,&cwork,&vwork); CHKERR(ierr);
135*6f79c3a4SBarry Smith   }
136*6f79c3a4SBarry Smith   ierr = MatAssemblyBegin(*newmat,FINAL_ASSEMBLY); CHKERR(ierr);
137*6f79c3a4SBarry Smith   ierr = MatAssemblyEnd(*newmat,FINAL_ASSEMBLY); CHKERR(ierr);
138*6f79c3a4SBarry Smith   return 0;
139*6f79c3a4SBarry Smith }
140*6f79c3a4SBarry Smith /* ------------------------------------------------------------------ */
141*6f79c3a4SBarry Smith /*
142*6f79c3a4SBarry Smith   MatConvert_MPIAIJ - Converts from MATMPIAIJ format to another
143*6f79c3a4SBarry Smith   parallel format.
144*6f79c3a4SBarry Smith  */
145*6f79c3a4SBarry Smith int MatConvert_MPIAIJ(Mat mat, MatType newtype, Mat *newmat)
146*6f79c3a4SBarry Smith {
147*6f79c3a4SBarry Smith   Mat_MPIAIJ *aij = (Mat_MPIAIJ *) mat->data;
148*6f79c3a4SBarry Smith   Mat_AIJ    *Ad = (Mat_AIJ *)(aij->A->data), *Bd = (Mat_AIJ *)(aij->B->data);
149*6f79c3a4SBarry Smith   int        ierr, nz, i, ig,rstart = aij->rstart, m = aij->m, *cwork;
150*6f79c3a4SBarry Smith   Scalar     *vwork;
151*6f79c3a4SBarry Smith 
152*6f79c3a4SBarry Smith   if (mat->type != MATMPIAIJ) SETERR(1,"Input matrix must be MATMPIAIJ.");
153*6f79c3a4SBarry Smith   switch (newtype) {
154*6f79c3a4SBarry Smith     case MATMPIROW:
155*6f79c3a4SBarry Smith       for (i=0; i<m; i++)
156*6f79c3a4SBarry Smith         {ierr = MatCreateMPIRow(mat->comm,m,aij->n,aij->M,aij->N,0,Ad->ilen,
157*6f79c3a4SBarry Smith 			0,Bd->ilen,newmat); CHKERR(ierr); }
158*6f79c3a4SBarry Smith       break;
159*6f79c3a4SBarry Smith     default:
160*6f79c3a4SBarry Smith       SETERR(1,"Only MATMPIROW is currently suported.");
161*6f79c3a4SBarry Smith   }
162*6f79c3a4SBarry Smith   /* Each processor converts its local rows */
163*6f79c3a4SBarry Smith   for (i=0; i<m; i++) {
164*6f79c3a4SBarry Smith     ig   = i + rstart;
165*6f79c3a4SBarry Smith     ierr = MatGetRow(mat,ig,&nz,&cwork,&vwork);	CHKERR(ierr);
166*6f79c3a4SBarry Smith     ierr = MatSetValues(*newmat,1,&ig,nz,cwork,vwork,
167*6f79c3a4SBarry Smith 		INSERTVALUES); CHKERR(ierr);
168*6f79c3a4SBarry Smith     ierr = MatRestoreRow(mat,ig,&nz,&cwork,&vwork); CHKERR(ierr);
169*6f79c3a4SBarry Smith   }
170*6f79c3a4SBarry Smith   ierr = MatAssemblyBegin(*newmat,FINAL_ASSEMBLY); CHKERR(ierr);
171*6f79c3a4SBarry Smith   ierr = MatAssemblyEnd(*newmat,FINAL_ASSEMBLY); CHKERR(ierr);
172*6f79c3a4SBarry Smith   return 0;
173*6f79c3a4SBarry Smith }
174