xref: /petsc/src/ksp/pc/impls/factor/qr/qr.c (revision 174dc0c8cee294b82b85e4dd3b331b29396264fc)
1 /*
2    Defines a direct QR factorization preconditioner for any Mat implementation
3    Note: this need not be considered a preconditioner since it supplies
4          a direct solver.
5 */
6 #include <../src/ksp/pc/impls/factor/qr/qr.h> /*I "petscpc.h" I*/
7 
8 static PetscErrorCode PCSetUp_QR(PC pc)
9 {
10   PC_QR         *dir = (PC_QR *)pc->data;
11   MatSolverType  stype;
12   MatFactorError err;
13   const char    *prefix;
14 
15   PetscFunctionBegin;
16   PetscCall(PCGetOptionsPrefix(pc, &prefix));
17   PetscCall(MatSetOptionsPrefix(pc->pmat, prefix));
18   pc->failedreason = PC_NOERROR;
19   if (dir->hdr.reusefill && pc->setupcalled) ((PC_Factor *)dir)->info.fill = dir->hdr.actualfill;
20 
21   PetscCall(MatSetErrorIfFailure(pc->pmat, pc->erroriffailure));
22   if (dir->hdr.inplace) {
23     MatFactorType ftype;
24 
25     PetscCall(MatGetFactorType(pc->pmat, &ftype));
26     if (ftype == MAT_FACTOR_NONE) {
27       PetscCall(MatQRFactor(pc->pmat, dir->col, &((PC_Factor *)dir)->info));
28       PetscCall(MatFactorGetError(pc->pmat, &err));
29       if (err) { /* Factor() fails */
30         pc->failedreason = (PCFailedReason)err;
31         PetscFunctionReturn(PETSC_SUCCESS);
32       }
33     }
34     ((PC_Factor *)dir)->fact = pc->pmat;
35   } else {
36     MatInfo info;
37 
38     if (!pc->setupcalled) {
39       if (!((PC_Factor *)dir)->fact) { PetscCall(MatGetFactor(pc->pmat, ((PC_Factor *)dir)->solvertype, MAT_FACTOR_QR, &((PC_Factor *)dir)->fact)); }
40       PetscCall(MatQRFactorSymbolic(((PC_Factor *)dir)->fact, pc->pmat, dir->col, &((PC_Factor *)dir)->info));
41       PetscCall(MatGetInfo(((PC_Factor *)dir)->fact, MAT_LOCAL, &info));
42       dir->hdr.actualfill = info.fill_ratio_needed;
43     } else if (pc->flag != SAME_NONZERO_PATTERN) {
44       PetscCall(MatQRFactorSymbolic(((PC_Factor *)dir)->fact, pc->pmat, dir->col, &((PC_Factor *)dir)->info));
45       PetscCall(MatGetInfo(((PC_Factor *)dir)->fact, MAT_LOCAL, &info));
46       dir->hdr.actualfill = info.fill_ratio_needed;
47     } else {
48       PetscCall(MatFactorGetError(((PC_Factor *)dir)->fact, &err));
49     }
50     PetscCall(MatFactorGetError(((PC_Factor *)dir)->fact, &err));
51     if (err) { /* FactorSymbolic() fails */
52       pc->failedreason = (PCFailedReason)err;
53       PetscFunctionReturn(PETSC_SUCCESS);
54     }
55 
56     PetscCall(MatQRFactorNumeric(((PC_Factor *)dir)->fact, pc->pmat, &((PC_Factor *)dir)->info));
57     PetscCall(MatFactorGetError(((PC_Factor *)dir)->fact, &err));
58     if (err) { /* FactorNumeric() fails */
59       pc->failedreason = (PCFailedReason)err;
60     }
61   }
62 
63   PetscCall(PCFactorGetMatSolverType(pc, &stype));
64   if (!stype) {
65     MatSolverType solverpackage;
66     PetscCall(MatFactorGetSolverType(((PC_Factor *)dir)->fact, &solverpackage));
67     PetscCall(PCFactorSetMatSolverType(pc, solverpackage));
68   }
69   PetscFunctionReturn(PETSC_SUCCESS);
70 }
71 
72 static PetscErrorCode PCReset_QR(PC pc)
73 {
74   PC_QR *dir = (PC_QR *)pc->data;
75 
76   PetscFunctionBegin;
77   if (!dir->hdr.inplace && ((PC_Factor *)dir)->fact) PetscCall(MatDestroy(&((PC_Factor *)dir)->fact));
78   PetscCall(ISDestroy(&dir->col));
79   PetscFunctionReturn(PETSC_SUCCESS);
80 }
81 
82 static PetscErrorCode PCDestroy_QR(PC pc)
83 {
84   PC_QR *dir = (PC_QR *)pc->data;
85 
86   PetscFunctionBegin;
87   PetscCall(PCReset_QR(pc));
88   PetscCall(PetscFree(((PC_Factor *)dir)->ordering));
89   PetscCall(PetscFree(((PC_Factor *)dir)->solvertype));
90   PetscCall(PCFactorClearComposedFunctions(pc));
91   PetscCall(PetscFree(pc->data));
92   PetscFunctionReturn(PETSC_SUCCESS);
93 }
94 
95 static PetscErrorCode PCApply_QR(PC pc, Vec x, Vec y)
96 {
97   PC_QR *dir = (PC_QR *)pc->data;
98   Mat    fact;
99 
100   PetscFunctionBegin;
101   fact = dir->hdr.inplace ? pc->pmat : ((PC_Factor *)dir)->fact;
102   PetscCall(MatSolve(fact, x, y));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 static PetscErrorCode PCMatApply_QR(PC pc, Mat X, Mat Y)
107 {
108   PC_QR *dir = (PC_QR *)pc->data;
109   Mat    fact;
110 
111   PetscFunctionBegin;
112   fact = dir->hdr.inplace ? pc->pmat : ((PC_Factor *)dir)->fact;
113   PetscCall(MatMatSolve(fact, X, Y));
114   PetscFunctionReturn(PETSC_SUCCESS);
115 }
116 
117 static PetscErrorCode PCApplyTranspose_QR(PC pc, Vec x, Vec y)
118 {
119   PC_QR *dir = (PC_QR *)pc->data;
120   Mat    fact;
121 
122   PetscFunctionBegin;
123   fact = dir->hdr.inplace ? pc->pmat : ((PC_Factor *)dir)->fact;
124   PetscCall(MatSolveTranspose(fact, x, y));
125   PetscFunctionReturn(PETSC_SUCCESS);
126 }
127 
128 /*MC
129   PCQR - Uses a direct solver, based on QR factorization, as a preconditioner
130 
131   Level: beginner
132 
133   Notes:
134   This is usually used as a preconditioner for `KSPLSQR`
135 
136   If the matrix used to construct the preconditioner is a `MATNORMAL` or `MATNORMALHERMITIAN` matrix, then the QR is performed on the
137   inner matrix to provide the preconditioner.
138 
139 .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCSVD`,
140           `PCILU`, `PCLU`, `PCCHOLESKY`, `PCICC`, `PCFactorSetReuseOrdering()`, `PCFactorSetReuseFill()`, `PCFactorGetMatrix()`,
141           `PCFactorSetFill()`, `PCFactorSetUseInPlace()`, `PCFactorSetMatOrderingType()`, `PCFactorSetColumnPivot()`,
142           `PCFactorSetPivotingInBlocks()`, `PCFactorSetShiftType()`, `PCFactorSetShiftAmount()`
143           `PCFactorReorderForNonzeroDiagonal()`, `KSPLSQR`
144 M*/
145 
146 PETSC_EXTERN PetscErrorCode PCCreate_QR(PC pc)
147 {
148   PC_QR *dir;
149 
150   PetscFunctionBegin;
151   PetscCall(PetscNew(&dir));
152   pc->data = (void *)dir;
153   PetscCall(PCFactorInitialize(pc, MAT_FACTOR_QR));
154 
155   dir->col                 = NULL;
156   pc->ops->reset           = PCReset_QR;
157   pc->ops->destroy         = PCDestroy_QR;
158   pc->ops->apply           = PCApply_QR;
159   pc->ops->matapply        = PCMatApply_QR;
160   pc->ops->applytranspose  = PCApplyTranspose_QR;
161   pc->ops->setup           = PCSetUp_QR;
162   pc->ops->setfromoptions  = PCSetFromOptions_Factor;
163   pc->ops->view            = PCView_Factor;
164   pc->ops->applyrichardson = NULL;
165   PetscFunctionReturn(PETSC_SUCCESS);
166 }
167