170baa948SKarl Rupp 270baa948SKarl Rupp /* 370baa948SKarl Rupp Include files needed for the ViennaCL row-scaling preconditioner: 470baa948SKarl Rupp pcimpl.h - private include file intended for use by all preconditioners 570baa948SKarl Rupp */ 699acd6aaSStefano Zampini #define PETSC_SKIP_IMMINTRIN_H_CUDAWORKAROUND 1 799acd6aaSStefano Zampini 870baa948SKarl Rupp #include <petsc/private/pcimpl.h> /*I "petscpc.h" I*/ 970baa948SKarl Rupp #include <../src/mat/impls/aij/seq/aij.h> 1070baa948SKarl Rupp #include <../src/vec/vec/impls/dvecimpl.h> 1170baa948SKarl Rupp #include <../src/mat/impls/aij/seq/seqviennacl/viennaclmatimpl.h> 1270baa948SKarl Rupp #include <../src/vec/vec/impls/seq/seqviennacl/viennaclvecimpl.h> 1370baa948SKarl Rupp #include <viennacl/linalg/row_scaling.hpp> 1470baa948SKarl Rupp 1570baa948SKarl Rupp /* 1670baa948SKarl Rupp Private context (data structure) for the ROWSCALINGVIENNACL preconditioner. 1770baa948SKarl Rupp */ 1870baa948SKarl Rupp typedef struct { 1970baa948SKarl Rupp viennacl::linalg::row_scaling<viennacl::compressed_matrix<PetscScalar>> *ROWSCALINGVIENNACL; 2070baa948SKarl Rupp } PC_ROWSCALINGVIENNACL; 2170baa948SKarl Rupp 2270baa948SKarl Rupp /* 2370baa948SKarl Rupp PCSetUp_ROWSCALINGVIENNACL - Prepares for the use of the ROWSCALINGVIENNACL preconditioner 2470baa948SKarl Rupp by setting data structures and options. 2570baa948SKarl Rupp 2670baa948SKarl Rupp Input Parameter: 2770baa948SKarl Rupp . pc - the preconditioner context 2870baa948SKarl Rupp 2970baa948SKarl Rupp Application Interface Routine: PCSetUp() 3070baa948SKarl Rupp 31f1580f4eSBarry Smith Note: 3270baa948SKarl Rupp The interface routine PCSetUp() is not usually called directly by 3370baa948SKarl Rupp the user, but instead is called by PCApply() if necessary. 3470baa948SKarl Rupp */ 35d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetUp_ROWSCALINGVIENNACL(PC pc) 36d71ae5a4SJacob Faibussowitsch { 3770baa948SKarl Rupp PC_ROWSCALINGVIENNACL *rowscaling = (PC_ROWSCALINGVIENNACL *)pc->data; 3870baa948SKarl Rupp PetscBool flg = PETSC_FALSE; 3970baa948SKarl Rupp Mat_SeqAIJViennaCL *gpustruct; 4070baa948SKarl Rupp 4170baa948SKarl Rupp PetscFunctionBegin; 429566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATSEQAIJVIENNACL, &flg)); 4328b400f6SJacob Faibussowitsch PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Currently only handles ViennaCL matrices"); 4470baa948SKarl Rupp if (pc->setupcalled != 0) { 4570baa948SKarl Rupp try { 4670baa948SKarl Rupp delete rowscaling->ROWSCALINGVIENNACL; 47d71ae5a4SJacob Faibussowitsch } catch (char *ex) { 48d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "ViennaCL error: %s", ex); 49d71ae5a4SJacob Faibussowitsch } 5070baa948SKarl Rupp } 5170baa948SKarl Rupp try { 5270baa948SKarl Rupp #if defined(PETSC_USE_COMPLEX) 5370baa948SKarl Rupp gpustruct = NULL; 5470baa948SKarl Rupp SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "No support for complex arithmetic in ROWSCALINGVIENNACL preconditioner"); 5570baa948SKarl Rupp #else 569566063dSJacob Faibussowitsch PetscCall(MatViennaCLCopyToGPU(pc->pmat)); 5770baa948SKarl Rupp gpustruct = (Mat_SeqAIJViennaCL *)(pc->pmat->spptr); 5870baa948SKarl Rupp 5970baa948SKarl Rupp viennacl::linalg::row_scaling_tag pc_tag(1); 6070baa948SKarl Rupp ViennaCLAIJMatrix *mat = (ViennaCLAIJMatrix *)gpustruct->mat; 6170baa948SKarl Rupp rowscaling->ROWSCALINGVIENNACL = new viennacl::linalg::row_scaling<viennacl::compressed_matrix<PetscScalar>>(*mat, pc_tag); 6270baa948SKarl Rupp #endif 63d71ae5a4SJacob Faibussowitsch } catch (char *ex) { 64d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "ViennaCL error: %s", ex); 65d71ae5a4SJacob Faibussowitsch } 663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6770baa948SKarl Rupp } 6870baa948SKarl Rupp 6970baa948SKarl Rupp /* 7070baa948SKarl Rupp PCApply_ROWSCALINGVIENNACL - Applies the ROWSCALINGVIENNACL preconditioner to a vector. 7170baa948SKarl Rupp 7270baa948SKarl Rupp Input Parameters: 7370baa948SKarl Rupp . pc - the preconditioner context 7470baa948SKarl Rupp . x - input vector 7570baa948SKarl Rupp 7670baa948SKarl Rupp Output Parameter: 7770baa948SKarl Rupp . y - output vector 7870baa948SKarl Rupp 7970baa948SKarl Rupp Application Interface Routine: PCApply() 8070baa948SKarl Rupp */ 81d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCApply_ROWSCALINGVIENNACL(PC pc, Vec x, Vec y) 82d71ae5a4SJacob Faibussowitsch { 8370baa948SKarl Rupp PC_ROWSCALINGVIENNACL *ilu = (PC_ROWSCALINGVIENNACL *)pc->data; 8470baa948SKarl Rupp PetscBool flg1, flg2; 8570baa948SKarl Rupp viennacl::vector<PetscScalar> const *xarray = NULL; 8670baa948SKarl Rupp viennacl::vector<PetscScalar> *yarray = NULL; 8770baa948SKarl Rupp 8870baa948SKarl Rupp PetscFunctionBegin; 8970baa948SKarl Rupp /*how to apply a certain fixed number of iterations?*/ 909566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)x, VECSEQVIENNACL, &flg1)); 919566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)y, VECSEQVIENNACL, &flg2)); 9208401ef6SPierre Jolivet PetscCheck((flg1 && flg2), PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Currently only handles ViennaCL vectors"); 9348a46eb9SPierre Jolivet if (!ilu->ROWSCALINGVIENNACL) PetscCall(PCSetUp_ROWSCALINGVIENNACL(pc)); 949566063dSJacob Faibussowitsch PetscCall(VecSet(y, 0.0)); 959566063dSJacob Faibussowitsch PetscCall(VecViennaCLGetArrayRead(x, &xarray)); 969566063dSJacob Faibussowitsch PetscCall(VecViennaCLGetArrayWrite(y, &yarray)); 9770baa948SKarl Rupp try { 9870baa948SKarl Rupp #if defined(PETSC_USE_COMPLEX) 9970baa948SKarl Rupp 10070baa948SKarl Rupp #else 10170baa948SKarl Rupp *yarray = *xarray; 10270baa948SKarl Rupp ilu->ROWSCALINGVIENNACL->apply(*yarray); 10370baa948SKarl Rupp #endif 104d71ae5a4SJacob Faibussowitsch } catch (char *ex) { 105d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "ViennaCL error: %s", ex); 106d71ae5a4SJacob Faibussowitsch } 1079566063dSJacob Faibussowitsch PetscCall(VecViennaCLRestoreArrayRead(x, &xarray)); 1089566063dSJacob Faibussowitsch PetscCall(VecViennaCLRestoreArrayWrite(y, &yarray)); 1099566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)y)); 1103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 11170baa948SKarl Rupp } 112f1580f4eSBarry Smith 11370baa948SKarl Rupp /* 11470baa948SKarl Rupp PCDestroy_ROWSCALINGVIENNACL - Destroys the private context for the ROWSCALINGVIENNACL preconditioner 11570baa948SKarl Rupp that was created with PCCreate_ROWSCALINGVIENNACL(). 11670baa948SKarl Rupp 11770baa948SKarl Rupp Input Parameter: 11870baa948SKarl Rupp . pc - the preconditioner context 11970baa948SKarl Rupp 12070baa948SKarl Rupp Application Interface Routine: PCDestroy() 12170baa948SKarl Rupp */ 122d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCDestroy_ROWSCALINGVIENNACL(PC pc) 123d71ae5a4SJacob Faibussowitsch { 12470baa948SKarl Rupp PC_ROWSCALINGVIENNACL *rowscaling = (PC_ROWSCALINGVIENNACL *)pc->data; 12570baa948SKarl Rupp 12670baa948SKarl Rupp PetscFunctionBegin; 12770baa948SKarl Rupp if (rowscaling->ROWSCALINGVIENNACL) { 12870baa948SKarl Rupp try { 12970baa948SKarl Rupp delete rowscaling->ROWSCALINGVIENNACL; 130d71ae5a4SJacob Faibussowitsch } catch (char *ex) { 131d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "ViennaCL error: %s", ex); 132d71ae5a4SJacob Faibussowitsch } 13370baa948SKarl Rupp } 13470baa948SKarl Rupp 13570baa948SKarl Rupp /* 13670baa948SKarl Rupp Free the private data structure that was hanging off the PC 13770baa948SKarl Rupp */ 1389566063dSJacob Faibussowitsch PetscCall(PetscFree(pc->data)); 1393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14070baa948SKarl Rupp } 14170baa948SKarl Rupp 142d71ae5a4SJacob Faibussowitsch static PetscErrorCode PCSetFromOptions_ROWSCALINGVIENNACL(PC pc, PetscOptionItems *PetscOptionsObject) 143d71ae5a4SJacob Faibussowitsch { 14470baa948SKarl Rupp PetscFunctionBegin; 145d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "ROWSCALINGVIENNACL options"); 146d0609cedSBarry Smith PetscOptionsHeadEnd(); 1473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 14870baa948SKarl Rupp } 14970baa948SKarl Rupp 15070baa948SKarl Rupp /*MC 151*04c3f3b8SBarry Smith PCROWSCALINGVIENNACLL - A diagonal preconditioner (scaling rows of matrices by their norm) that can be used via the CUDA, 152*04c3f3b8SBarry Smith OpenCL, and OpenMP backends of ViennaCL 15370baa948SKarl Rupp 15470baa948SKarl Rupp Level: advanced 15570baa948SKarl Rupp 156f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC` 15770baa948SKarl Rupp M*/ 158d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_ROWSCALINGVIENNACL(PC pc) 159d71ae5a4SJacob Faibussowitsch { 16070baa948SKarl Rupp PC_ROWSCALINGVIENNACL *rowscaling; 16170baa948SKarl Rupp 16270baa948SKarl Rupp PetscFunctionBegin; 16370baa948SKarl Rupp /* 16470baa948SKarl Rupp Creates the private data structure for this preconditioner and 16570baa948SKarl Rupp attach it to the PC object. 16670baa948SKarl Rupp */ 1674dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&rowscaling)); 16870baa948SKarl Rupp pc->data = (void *)rowscaling; 16970baa948SKarl Rupp 17070baa948SKarl Rupp /* 17170baa948SKarl Rupp Initialize the pointer to zero 17270baa948SKarl Rupp Initialize number of v-cycles to default (1) 17370baa948SKarl Rupp */ 17470baa948SKarl Rupp rowscaling->ROWSCALINGVIENNACL = 0; 17570baa948SKarl Rupp 17670baa948SKarl Rupp /* 17770baa948SKarl Rupp Set the pointers for the functions that are provided above. 17870baa948SKarl Rupp Now when the user-level routines (such as PCApply(), PCDestroy(), etc.) 17970baa948SKarl Rupp are called, they will automatically call these functions. Note we 18070baa948SKarl Rupp choose not to provide a couple of these functions since they are 18170baa948SKarl Rupp not needed. 18270baa948SKarl Rupp */ 18370baa948SKarl Rupp pc->ops->apply = PCApply_ROWSCALINGVIENNACL; 18470baa948SKarl Rupp pc->ops->applytranspose = 0; 18570baa948SKarl Rupp pc->ops->setup = PCSetUp_ROWSCALINGVIENNACL; 18670baa948SKarl Rupp pc->ops->destroy = PCDestroy_ROWSCALINGVIENNACL; 18770baa948SKarl Rupp pc->ops->setfromoptions = PCSetFromOptions_ROWSCALINGVIENNACL; 18870baa948SKarl Rupp pc->ops->view = 0; 18970baa948SKarl Rupp pc->ops->applyrichardson = 0; 19070baa948SKarl Rupp pc->ops->applysymmetricleft = 0; 19170baa948SKarl Rupp pc->ops->applysymmetricright = 0; 1923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19370baa948SKarl Rupp } 194