xref: /petsc/src/ksp/pc/impls/rowscalingviennacl/rowscalingviennacl.cxx (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
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   }
66*3ba16761SJacob 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));
110*3ba16761SJacob 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));
139*3ba16761SJacob 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();
147*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14870baa948SKarl Rupp }
14970baa948SKarl Rupp 
15070baa948SKarl Rupp /*MC
15170baa948SKarl 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
15270baa948SKarl Rupp 
15370baa948SKarl Rupp    Level: advanced
15470baa948SKarl Rupp 
155f1580f4eSBarry Smith    Developer Note:
156f1580f4eSBarry Smith    This `PCType` does not appear to be registered
15770baa948SKarl Rupp 
158f1580f4eSBarry Smith .seealso: `PCCreate()`, `PCSetType()`, `PCType`, `PC`
15970baa948SKarl Rupp M*/
16070baa948SKarl Rupp 
161d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PCCreate_ROWSCALINGVIENNACL(PC pc)
162d71ae5a4SJacob Faibussowitsch {
16370baa948SKarl Rupp   PC_ROWSCALINGVIENNACL *rowscaling;
16470baa948SKarl Rupp 
16570baa948SKarl Rupp   PetscFunctionBegin;
16670baa948SKarl Rupp   /*
16770baa948SKarl Rupp      Creates the private data structure for this preconditioner and
16870baa948SKarl Rupp      attach it to the PC object.
16970baa948SKarl Rupp   */
1704dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&rowscaling));
17170baa948SKarl Rupp   pc->data = (void *)rowscaling;
17270baa948SKarl Rupp 
17370baa948SKarl Rupp   /*
17470baa948SKarl Rupp      Initialize the pointer to zero
17570baa948SKarl Rupp      Initialize number of v-cycles to default (1)
17670baa948SKarl Rupp   */
17770baa948SKarl Rupp   rowscaling->ROWSCALINGVIENNACL = 0;
17870baa948SKarl Rupp 
17970baa948SKarl Rupp   /*
18070baa948SKarl Rupp       Set the pointers for the functions that are provided above.
18170baa948SKarl Rupp       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
18270baa948SKarl Rupp       are called, they will automatically call these functions.  Note we
18370baa948SKarl Rupp       choose not to provide a couple of these functions since they are
18470baa948SKarl Rupp       not needed.
18570baa948SKarl Rupp   */
18670baa948SKarl Rupp   pc->ops->apply               = PCApply_ROWSCALINGVIENNACL;
18770baa948SKarl Rupp   pc->ops->applytranspose      = 0;
18870baa948SKarl Rupp   pc->ops->setup               = PCSetUp_ROWSCALINGVIENNACL;
18970baa948SKarl Rupp   pc->ops->destroy             = PCDestroy_ROWSCALINGVIENNACL;
19070baa948SKarl Rupp   pc->ops->setfromoptions      = PCSetFromOptions_ROWSCALINGVIENNACL;
19170baa948SKarl Rupp   pc->ops->view                = 0;
19270baa948SKarl Rupp   pc->ops->applyrichardson     = 0;
19370baa948SKarl Rupp   pc->ops->applysymmetricleft  = 0;
19470baa948SKarl Rupp   pc->ops->applysymmetricright = 0;
195*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19670baa948SKarl Rupp }
197