xref: /petsc/src/mat/utils/convert.c (revision 11486bccf1aeea1ca5536228f99d437b39bdaca6)
1 
2 #include <petsc/private/matimpl.h>
3 
4 /*
5   MatConvert_Basic - Converts from any input format to another format.
6   Does not do preallocation so in general will be slow
7  */
8 PETSC_INTERN PetscErrorCode MatConvert_Basic(Mat mat,MatType newtype,MatReuse reuse,Mat *newmat)
9 {
10   Mat               M;
11   const PetscScalar *vwork;
12   PetscInt          i,rstart,rend,nz;
13   const PetscInt    *cwork;
14   PetscBool         isSBAIJ;
15 
16   PetscFunctionBegin;
17   if (!mat->ops->getrow) { /* missing get row, use matvecs */
18     PetscCall(MatConvert_Shell(mat,newtype,reuse,newmat));
19     PetscFunctionReturn(0);
20   }
21   PetscCall(PetscObjectTypeCompare((PetscObject)mat,MATSEQSBAIJ,&isSBAIJ));
22   if (!isSBAIJ) {
23     PetscCall(PetscObjectTypeCompare((PetscObject)mat,MATMPISBAIJ,&isSBAIJ));
24   }
25   PetscCheck(!isSBAIJ,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot convert from SBAIJ matrix since cannot obtain entire rows of matrix");
26 
27   if (reuse == MAT_REUSE_MATRIX) {
28     M = *newmat;
29   } else {
30     PetscInt m,n,lm,ln;
31     PetscCall(MatGetSize(mat,&m,&n));
32     PetscCall(MatGetLocalSize(mat,&lm,&ln));
33     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat),&M));
34     PetscCall(MatSetSizes(M,lm,ln,m,n));
35     PetscCall(MatSetBlockSizesFromMats(M,mat,mat));
36     PetscCall(MatSetType(M,newtype));
37     PetscCall(MatSetUp(M));
38 
39     PetscCall(MatSetOption(M,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_FALSE));
40     PetscCall(MatSetOption(M,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE));
41     PetscCall(PetscObjectTypeCompare((PetscObject)M,MATSEQSBAIJ,&isSBAIJ));
42     if (!isSBAIJ) {
43       PetscCall(PetscObjectTypeCompare((PetscObject)M,MATMPISBAIJ,&isSBAIJ));
44     }
45     if (isSBAIJ) PetscCall(MatSetOption(M,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE));
46   }
47 
48   PetscCall(MatGetOwnershipRange(mat,&rstart,&rend));
49   for (i=rstart; i<rend; i++) {
50     PetscCall(MatGetRow(mat,i,&nz,&cwork,&vwork));
51     PetscCall(MatSetValues(M,1,&i,nz,cwork,vwork,INSERT_VALUES));
52     PetscCall(MatRestoreRow(mat,i,&nz,&cwork,&vwork));
53   }
54   PetscCall(MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY));
55   PetscCall(MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY));
56 
57   if (reuse == MAT_INPLACE_MATRIX) {
58     PetscCall(MatHeaderReplace(mat,&M));
59   } else {
60     *newmat = M;
61   }
62   PetscFunctionReturn(0);
63 }
64