/* Defines a direct QR factorization preconditioner for any Mat implementation Note: this need not be considered a preconditioner since it supplies a direct solver. */ #include <../src/ksp/pc/impls/factor/qr/qr.h> /*I "petscpc.h" I*/ static PetscErrorCode PCSetUp_QR(PC pc) { PC_QR *dir = (PC_QR *)pc->data; MatSolverType stype; MatFactorError err; const char *prefix; PetscFunctionBegin; PetscCall(PCGetOptionsPrefix(pc, &prefix)); PetscCall(MatSetOptionsPrefix(pc->pmat, prefix)); pc->failedreason = PC_NOERROR; if (dir->hdr.reusefill && pc->setupcalled) ((PC_Factor *)dir)->info.fill = dir->hdr.actualfill; PetscCall(MatSetErrorIfFailure(pc->pmat, pc->erroriffailure)); if (dir->hdr.inplace) { MatFactorType ftype; PetscCall(MatGetFactorType(pc->pmat, &ftype)); if (ftype == MAT_FACTOR_NONE) { PetscCall(MatQRFactor(pc->pmat, dir->col, &((PC_Factor *)dir)->info)); PetscCall(MatFactorGetError(pc->pmat, &err)); if (err) { /* Factor() fails */ pc->failedreason = (PCFailedReason)err; PetscFunctionReturn(PETSC_SUCCESS); } } ((PC_Factor *)dir)->fact = pc->pmat; } else { MatInfo info; if (!pc->setupcalled) { if (!((PC_Factor *)dir)->fact) PetscCall(MatGetFactor(pc->pmat, ((PC_Factor *)dir)->solvertype, MAT_FACTOR_QR, &((PC_Factor *)dir)->fact)); PetscCall(MatQRFactorSymbolic(((PC_Factor *)dir)->fact, pc->pmat, dir->col, &((PC_Factor *)dir)->info)); PetscCall(MatGetInfo(((PC_Factor *)dir)->fact, MAT_LOCAL, &info)); dir->hdr.actualfill = info.fill_ratio_needed; } else if (pc->flag != SAME_NONZERO_PATTERN) { PetscCall(MatQRFactorSymbolic(((PC_Factor *)dir)->fact, pc->pmat, dir->col, &((PC_Factor *)dir)->info)); PetscCall(MatGetInfo(((PC_Factor *)dir)->fact, MAT_LOCAL, &info)); dir->hdr.actualfill = info.fill_ratio_needed; } else { PetscCall(MatFactorGetError(((PC_Factor *)dir)->fact, &err)); } PetscCall(MatFactorGetError(((PC_Factor *)dir)->fact, &err)); if (err) { /* FactorSymbolic() fails */ pc->failedreason = (PCFailedReason)err; PetscFunctionReturn(PETSC_SUCCESS); } PetscCall(MatQRFactorNumeric(((PC_Factor *)dir)->fact, pc->pmat, &((PC_Factor *)dir)->info)); PetscCall(MatFactorGetError(((PC_Factor *)dir)->fact, &err)); if (err) { /* FactorNumeric() fails */ pc->failedreason = (PCFailedReason)err; } } PetscCall(PCFactorGetMatSolverType(pc, &stype)); if (!stype) { MatSolverType solverpackage; PetscCall(MatFactorGetSolverType(((PC_Factor *)dir)->fact, &solverpackage)); PetscCall(PCFactorSetMatSolverType(pc, solverpackage)); } PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode PCReset_QR(PC pc) { PC_QR *dir = (PC_QR *)pc->data; PetscFunctionBegin; if (!dir->hdr.inplace && ((PC_Factor *)dir)->fact) PetscCall(MatDestroy(&((PC_Factor *)dir)->fact)); PetscCall(ISDestroy(&dir->col)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode PCDestroy_QR(PC pc) { PC_QR *dir = (PC_QR *)pc->data; PetscFunctionBegin; PetscCall(PCReset_QR(pc)); PetscCall(PetscFree(((PC_Factor *)dir)->ordering)); PetscCall(PetscFree(((PC_Factor *)dir)->solvertype)); PetscCall(PCFactorClearComposedFunctions(pc)); PetscCall(PetscFree(pc->data)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode PCApply_QR(PC pc, Vec x, Vec y) { PC_QR *dir = (PC_QR *)pc->data; Mat fact; PetscFunctionBegin; fact = dir->hdr.inplace ? pc->pmat : ((PC_Factor *)dir)->fact; PetscCall(MatSolve(fact, x, y)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode PCMatApply_QR(PC pc, Mat X, Mat Y) { PC_QR *dir = (PC_QR *)pc->data; Mat fact; PetscFunctionBegin; fact = dir->hdr.inplace ? pc->pmat : ((PC_Factor *)dir)->fact; PetscCall(MatMatSolve(fact, X, Y)); PetscFunctionReturn(PETSC_SUCCESS); } static PetscErrorCode PCApplyTranspose_QR(PC pc, Vec x, Vec y) { PC_QR *dir = (PC_QR *)pc->data; Mat fact; PetscFunctionBegin; fact = dir->hdr.inplace ? pc->pmat : ((PC_Factor *)dir)->fact; PetscCall(MatSolveTranspose(fact, x, y)); PetscFunctionReturn(PETSC_SUCCESS); } /*MC PCQR - Uses a direct solver, based on QR factorization, as a preconditioner Level: beginner Notes: This is usually used as a preconditioner for `KSPLSQR` If the matrix used to construct the preconditioner is a `MATNORMAL` or `MATNORMALHERMITIAN` matrix, then the QR is performed on the inner matrix to provide the preconditioner. .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`, `PCSVD`, `PCILU`, `PCLU`, `PCCHOLESKY`, `PCICC`, `PCFactorSetReuseOrdering()`, `PCFactorSetReuseFill()`, `PCFactorGetMatrix()`, `PCFactorSetFill()`, `PCFactorSetUseInPlace()`, `PCFactorSetMatOrderingType()`, `PCFactorSetColumnPivot()`, `PCFactorSetPivotingInBlocks()`, `PCFactorSetShiftType()`, `PCFactorSetShiftAmount()` `PCFactorReorderForNonzeroDiagonal()`, `KSPLSQR` M*/ PETSC_EXTERN PetscErrorCode PCCreate_QR(PC pc) { PC_QR *dir; PetscFunctionBegin; PetscCall(PetscNew(&dir)); pc->data = (void *)dir; PetscCall(PCFactorInitialize(pc, MAT_FACTOR_QR)); dir->col = NULL; pc->ops->reset = PCReset_QR; pc->ops->destroy = PCDestroy_QR; pc->ops->apply = PCApply_QR; pc->ops->matapply = PCMatApply_QR; pc->ops->applytranspose = PCApplyTranspose_QR; pc->ops->setup = PCSetUp_QR; pc->ops->setfromoptions = PCSetFromOptions_Factor; pc->ops->view = PCView_Factor; pc->ops->applyrichardson = NULL; PetscFunctionReturn(PETSC_SUCCESS); }