xref: /petsc/src/ksp/pc/impls/rowscalingviennacl/rowscalingviennacl.cxx (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
170baa948SKarl Rupp 
270baa948SKarl Rupp /*  -------------------------------------------------------------------- */
370baa948SKarl Rupp 
470baa948SKarl Rupp /*
570baa948SKarl Rupp    Include files needed for the ViennaCL row-scaling preconditioner:
670baa948SKarl Rupp      pcimpl.h - private include file intended for use by all preconditioners
770baa948SKarl Rupp */
870baa948SKarl Rupp #define PETSC_SKIP_SPINLOCK
999acd6aaSStefano Zampini #define PETSC_SKIP_IMMINTRIN_H_CUDAWORKAROUND 1
1099acd6aaSStefano Zampini 
1170baa948SKarl Rupp #include <petsc/private/pcimpl.h>   /*I "petscpc.h" I*/
1270baa948SKarl Rupp #include <../src/mat/impls/aij/seq/aij.h>
1370baa948SKarl Rupp #include <../src/vec/vec/impls/dvecimpl.h>
1470baa948SKarl Rupp #include <../src/mat/impls/aij/seq/seqviennacl/viennaclmatimpl.h>
1570baa948SKarl Rupp #include <../src/vec/vec/impls/seq/seqviennacl/viennaclvecimpl.h>
1670baa948SKarl Rupp #include <viennacl/linalg/row_scaling.hpp>
1770baa948SKarl Rupp 
1870baa948SKarl Rupp /*
1970baa948SKarl Rupp    Private context (data structure) for the ROWSCALINGVIENNACL preconditioner.
2070baa948SKarl Rupp */
2170baa948SKarl Rupp typedef struct {
2270baa948SKarl Rupp   viennacl::linalg::row_scaling< viennacl::compressed_matrix<PetscScalar> > *ROWSCALINGVIENNACL;
2370baa948SKarl Rupp } PC_ROWSCALINGVIENNACL;
2470baa948SKarl Rupp 
2570baa948SKarl Rupp /* -------------------------------------------------------------------------- */
2670baa948SKarl Rupp /*
2770baa948SKarl Rupp    PCSetUp_ROWSCALINGVIENNACL - Prepares for the use of the ROWSCALINGVIENNACL preconditioner
2870baa948SKarl Rupp                                 by setting data structures and options.
2970baa948SKarl Rupp 
3070baa948SKarl Rupp    Input Parameter:
3170baa948SKarl Rupp .  pc - the preconditioner context
3270baa948SKarl Rupp 
3370baa948SKarl Rupp    Application Interface Routine: PCSetUp()
3470baa948SKarl Rupp 
3570baa948SKarl Rupp    Notes:
3670baa948SKarl Rupp    The interface routine PCSetUp() is not usually called directly by
3770baa948SKarl Rupp    the user, but instead is called by PCApply() if necessary.
3870baa948SKarl Rupp */
3970baa948SKarl Rupp static PetscErrorCode PCSetUp_ROWSCALINGVIENNACL(PC pc)
4070baa948SKarl Rupp {
4170baa948SKarl Rupp   PC_ROWSCALINGVIENNACL  *rowscaling = (PC_ROWSCALINGVIENNACL*)pc->data;
4270baa948SKarl Rupp   PetscBool              flg = PETSC_FALSE;
4370baa948SKarl Rupp   PetscErrorCode         ierr;
4470baa948SKarl Rupp   Mat_SeqAIJViennaCL     *gpustruct;
4570baa948SKarl Rupp 
4670baa948SKarl Rupp   PetscFunctionBegin;
4770baa948SKarl Rupp   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATSEQAIJVIENNACL,&flg);CHKERRQ(ierr);
48*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Currently only handles ViennaCL matrices");
4970baa948SKarl Rupp   if (pc->setupcalled != 0) {
5070baa948SKarl Rupp     try {
5170baa948SKarl Rupp       delete rowscaling->ROWSCALINGVIENNACL;
5270baa948SKarl Rupp     } catch(char *ex) {
5398921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex);
5470baa948SKarl Rupp     }
5570baa948SKarl Rupp   }
5670baa948SKarl Rupp   try {
5770baa948SKarl Rupp #if defined(PETSC_USE_COMPLEX)
5870baa948SKarl Rupp     gpustruct = NULL;
5970baa948SKarl Rupp     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"No support for complex arithmetic in ROWSCALINGVIENNACL preconditioner");
6070baa948SKarl Rupp #else
6170baa948SKarl Rupp     ierr      = MatViennaCLCopyToGPU(pc->pmat);CHKERRQ(ierr);
6270baa948SKarl Rupp     gpustruct = (Mat_SeqAIJViennaCL*)(pc->pmat->spptr);
6370baa948SKarl Rupp 
6470baa948SKarl Rupp     viennacl::linalg::row_scaling_tag pc_tag(1);
6570baa948SKarl Rupp     ViennaCLAIJMatrix *mat = (ViennaCLAIJMatrix*)gpustruct->mat;
6670baa948SKarl Rupp     rowscaling->ROWSCALINGVIENNACL = new viennacl::linalg::row_scaling<viennacl::compressed_matrix<PetscScalar> >(*mat, pc_tag);
6770baa948SKarl Rupp #endif
6870baa948SKarl Rupp   } catch(char *ex) {
6998921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex);
7070baa948SKarl Rupp   }
7170baa948SKarl Rupp   PetscFunctionReturn(0);
7270baa948SKarl Rupp }
7370baa948SKarl Rupp 
7470baa948SKarl Rupp /* -------------------------------------------------------------------------- */
7570baa948SKarl Rupp /*
7670baa948SKarl Rupp    PCApply_ROWSCALINGVIENNACL - Applies the ROWSCALINGVIENNACL preconditioner to a vector.
7770baa948SKarl Rupp 
7870baa948SKarl Rupp    Input Parameters:
7970baa948SKarl Rupp .  pc - the preconditioner context
8070baa948SKarl Rupp .  x - input vector
8170baa948SKarl Rupp 
8270baa948SKarl Rupp    Output Parameter:
8370baa948SKarl Rupp .  y - output vector
8470baa948SKarl Rupp 
8570baa948SKarl Rupp    Application Interface Routine: PCApply()
8670baa948SKarl Rupp  */
8770baa948SKarl Rupp static PetscErrorCode PCApply_ROWSCALINGVIENNACL(PC pc,Vec x,Vec y)
8870baa948SKarl Rupp {
8970baa948SKarl Rupp   PC_ROWSCALINGVIENNACL         *ilu = (PC_ROWSCALINGVIENNACL*)pc->data;
9070baa948SKarl Rupp   PetscErrorCode                ierr;
9170baa948SKarl Rupp   PetscBool                     flg1,flg2;
9270baa948SKarl Rupp   viennacl::vector<PetscScalar> const *xarray=NULL;
9370baa948SKarl Rupp   viennacl::vector<PetscScalar> *yarray=NULL;
9470baa948SKarl Rupp 
9570baa948SKarl Rupp   PetscFunctionBegin;
9670baa948SKarl Rupp   /*how to apply a certain fixed number of iterations?*/
9770baa948SKarl Rupp   ierr = PetscObjectTypeCompare((PetscObject)x,VECSEQVIENNACL,&flg1);CHKERRQ(ierr);
9870baa948SKarl Rupp   ierr = PetscObjectTypeCompare((PetscObject)y,VECSEQVIENNACL,&flg2);CHKERRQ(ierr);
99*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!(flg1 && flg2),PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP, "Currently only handles ViennaCL vectors");
10070baa948SKarl Rupp   if (!ilu->ROWSCALINGVIENNACL) {
10170baa948SKarl Rupp     ierr = PCSetUp_ROWSCALINGVIENNACL(pc);CHKERRQ(ierr);
10270baa948SKarl Rupp   }
10370baa948SKarl Rupp   ierr = VecSet(y,0.0);CHKERRQ(ierr);
10470baa948SKarl Rupp   ierr = VecViennaCLGetArrayRead(x,&xarray);CHKERRQ(ierr);
10570baa948SKarl Rupp   ierr = VecViennaCLGetArrayWrite(y,&yarray);CHKERRQ(ierr);
10670baa948SKarl Rupp   try {
10770baa948SKarl Rupp #if defined(PETSC_USE_COMPLEX)
10870baa948SKarl Rupp 
10970baa948SKarl Rupp #else
11070baa948SKarl Rupp     *yarray = *xarray;
11170baa948SKarl Rupp     ilu->ROWSCALINGVIENNACL->apply(*yarray);
11270baa948SKarl Rupp #endif
11370baa948SKarl Rupp   } catch(char * ex) {
11498921bdaSJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex);
11570baa948SKarl Rupp   }
11670baa948SKarl Rupp   ierr = VecViennaCLRestoreArrayRead(x,&xarray);CHKERRQ(ierr);
11770baa948SKarl Rupp   ierr = VecViennaCLRestoreArrayWrite(y,&yarray);CHKERRQ(ierr);
11870baa948SKarl Rupp   ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr);
11970baa948SKarl Rupp   PetscFunctionReturn(0);
12070baa948SKarl Rupp }
12170baa948SKarl Rupp /* -------------------------------------------------------------------------- */
12270baa948SKarl Rupp /*
12370baa948SKarl Rupp    PCDestroy_ROWSCALINGVIENNACL - Destroys the private context for the ROWSCALINGVIENNACL preconditioner
12470baa948SKarl Rupp    that was created with PCCreate_ROWSCALINGVIENNACL().
12570baa948SKarl Rupp 
12670baa948SKarl Rupp    Input Parameter:
12770baa948SKarl Rupp .  pc - the preconditioner context
12870baa948SKarl Rupp 
12970baa948SKarl Rupp    Application Interface Routine: PCDestroy()
13070baa948SKarl Rupp */
13170baa948SKarl Rupp static PetscErrorCode PCDestroy_ROWSCALINGVIENNACL(PC pc)
13270baa948SKarl Rupp {
13370baa948SKarl Rupp   PC_ROWSCALINGVIENNACL  *rowscaling = (PC_ROWSCALINGVIENNACL*)pc->data;
13470baa948SKarl Rupp   PetscErrorCode ierr;
13570baa948SKarl Rupp 
13670baa948SKarl Rupp   PetscFunctionBegin;
13770baa948SKarl Rupp   if (rowscaling->ROWSCALINGVIENNACL) {
13870baa948SKarl Rupp     try {
13970baa948SKarl Rupp       delete rowscaling->ROWSCALINGVIENNACL;
14070baa948SKarl Rupp     } catch(char *ex) {
14198921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"ViennaCL error: %s", ex);
14270baa948SKarl Rupp     }
14370baa948SKarl Rupp   }
14470baa948SKarl Rupp 
14570baa948SKarl Rupp   /*
14670baa948SKarl Rupp       Free the private data structure that was hanging off the PC
14770baa948SKarl Rupp   */
14870baa948SKarl Rupp   ierr = PetscFree(pc->data);CHKERRQ(ierr);
14970baa948SKarl Rupp   PetscFunctionReturn(0);
15070baa948SKarl Rupp }
15170baa948SKarl Rupp 
15270baa948SKarl Rupp static PetscErrorCode PCSetFromOptions_ROWSCALINGVIENNACL(PetscOptionItems *PetscOptionsObject,PC pc)
15370baa948SKarl Rupp {
15470baa948SKarl Rupp   PetscErrorCode ierr;
15570baa948SKarl Rupp 
15670baa948SKarl Rupp   PetscFunctionBegin;
15770baa948SKarl Rupp   ierr = PetscOptionsHead(PetscOptionsObject,"ROWSCALINGVIENNACL options");CHKERRQ(ierr);
15870baa948SKarl Rupp   ierr = PetscOptionsTail();CHKERRQ(ierr);
15970baa948SKarl Rupp   PetscFunctionReturn(0);
16070baa948SKarl Rupp }
16170baa948SKarl Rupp 
16270baa948SKarl Rupp /* -------------------------------------------------------------------------- */
16370baa948SKarl Rupp 
16470baa948SKarl Rupp /*MC
16570baa948SKarl Rupp      PCRowScalingViennaCL  - A diagonal preconditioner (scaling rows of matrices by their norm) that can be used via the CUDA, OpenCL, and OpenMP backends of ViennaCL
16670baa948SKarl Rupp 
16770baa948SKarl Rupp    Level: advanced
16870baa948SKarl Rupp 
16970baa948SKarl Rupp .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC
17070baa948SKarl Rupp 
17170baa948SKarl Rupp M*/
17270baa948SKarl Rupp 
17370baa948SKarl Rupp PETSC_EXTERN PetscErrorCode PCCreate_ROWSCALINGVIENNACL(PC pc)
17470baa948SKarl Rupp {
17570baa948SKarl Rupp   PC_ROWSCALINGVIENNACL  *rowscaling;
17670baa948SKarl Rupp   PetscErrorCode ierr;
17770baa948SKarl Rupp 
17870baa948SKarl Rupp   PetscFunctionBegin;
17970baa948SKarl Rupp   /*
18070baa948SKarl Rupp      Creates the private data structure for this preconditioner and
18170baa948SKarl Rupp      attach it to the PC object.
18270baa948SKarl Rupp   */
18370baa948SKarl Rupp   ierr     = PetscNewLog(pc,&rowscaling);CHKERRQ(ierr);
18470baa948SKarl Rupp   pc->data = (void*)rowscaling;
18570baa948SKarl Rupp 
18670baa948SKarl Rupp   /*
18770baa948SKarl Rupp      Initialize the pointer to zero
18870baa948SKarl Rupp      Initialize number of v-cycles to default (1)
18970baa948SKarl Rupp   */
19070baa948SKarl Rupp   rowscaling->ROWSCALINGVIENNACL = 0;
19170baa948SKarl Rupp 
19270baa948SKarl Rupp   /*
19370baa948SKarl Rupp       Set the pointers for the functions that are provided above.
19470baa948SKarl Rupp       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
19570baa948SKarl Rupp       are called, they will automatically call these functions.  Note we
19670baa948SKarl Rupp       choose not to provide a couple of these functions since they are
19770baa948SKarl Rupp       not needed.
19870baa948SKarl Rupp   */
19970baa948SKarl Rupp   pc->ops->apply               = PCApply_ROWSCALINGVIENNACL;
20070baa948SKarl Rupp   pc->ops->applytranspose      = 0;
20170baa948SKarl Rupp   pc->ops->setup               = PCSetUp_ROWSCALINGVIENNACL;
20270baa948SKarl Rupp   pc->ops->destroy             = PCDestroy_ROWSCALINGVIENNACL;
20370baa948SKarl Rupp   pc->ops->setfromoptions      = PCSetFromOptions_ROWSCALINGVIENNACL;
20470baa948SKarl Rupp   pc->ops->view                = 0;
20570baa948SKarl Rupp   pc->ops->applyrichardson     = 0;
20670baa948SKarl Rupp   pc->ops->applysymmetricleft  = 0;
20770baa948SKarl Rupp   pc->ops->applysymmetricright = 0;
20870baa948SKarl Rupp   PetscFunctionReturn(0);
20970baa948SKarl Rupp }
210