xref: /petsc/src/mat/utils/convert.c (revision f97672e55eacc8688507b9471cd7ec2664d7f203)
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) {
46       PetscCall(MatSetOption(M,MAT_IGNORE_LOWER_TRIANGULAR,PETSC_TRUE));
47     }
48   }
49 
50   PetscCall(MatGetOwnershipRange(mat,&rstart,&rend));
51   for (i=rstart; i<rend; i++) {
52     PetscCall(MatGetRow(mat,i,&nz,&cwork,&vwork));
53     PetscCall(MatSetValues(M,1,&i,nz,cwork,vwork,INSERT_VALUES));
54     PetscCall(MatRestoreRow(mat,i,&nz,&cwork,&vwork));
55   }
56   PetscCall(MatAssemblyBegin(M,MAT_FINAL_ASSEMBLY));
57   PetscCall(MatAssemblyEnd(M,MAT_FINAL_ASSEMBLY));
58 
59   if (reuse == MAT_INPLACE_MATRIX) {
60     PetscCall(MatHeaderReplace(mat,&M));
61   } else {
62     *newmat = M;
63   }
64   PetscFunctionReturn(0);
65 }
66