Actual source code: saviennacl.cxx

  1: /*
  2:    Include files needed for the ViennaCL Smoothed Aggregation preconditioner:
  3:      pcimpl.h - private include file intended for use by all preconditioners
  4: */
  5: #define PETSC_SKIP_IMMINTRIN_H_CUDAWORKAROUND 1
  6: #include <petsc/private/pcimpl.h>
  7: #include <../src/mat/impls/aij/seq/aij.h>
  8: #include <../src/vec/vec/impls/dvecimpl.h>
  9: #include <../src/mat/impls/aij/seq/seqviennacl/viennaclmatimpl.h>
 10: #include <../src/vec/vec/impls/seq/seqviennacl/viennaclvecimpl.h>
 11: #include <viennacl/linalg/amg.hpp>

 13: /*
 14:    Private context (data structure) for the SAVIENNACL preconditioner.
 15: */
 16: typedef struct {
 17:   viennacl::linalg::amg_precond<viennacl::compressed_matrix<PetscScalar>> *SAVIENNACL;
 18: } PC_SAVIENNACL;

 20: /*
 21:    PCSetUp_SAVIENNACL - Prepares for the use of the SAVIENNACL preconditioner
 22:                         by setting data structures and options.

 24:    Input Parameter:
 25: .  pc - the preconditioner context

 27:    Application Interface Routine: PCSetUp()

 29:    Note:
 30:    The interface routine PCSetUp() is not usually called directly by
 31:    the user, but instead is called by PCApply() if necessary.
 32: */
 33: static PetscErrorCode PCSetUp_SAVIENNACL(PC pc)
 34: {
 35:   PC_SAVIENNACL      *sa  = (PC_SAVIENNACL *)pc->data;
 36:   PetscBool           flg = PETSC_FALSE;
 37:   Mat_SeqAIJViennaCL *gpustruct;

 39:   PetscFunctionBegin;
 40:   PetscCall(PetscObjectTypeCompare((PetscObject)pc->pmat, MATSEQAIJVIENNACL, &flg));
 41:   PetscCheck(flg, PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Currently only handles ViennaCL matrices");
 42:   if (pc->setupcalled != 0) {
 43:     try {
 44:       delete sa->SAVIENNACL;
 45:     } catch (char *ex) {
 46:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "ViennaCL error: %s", ex);
 47:     }
 48:   }
 49:   try {
 50: #if defined(PETSC_USE_COMPLEX)
 51:     gpustruct = NULL;
 52:     SETERRQ(PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "No support for complex arithmetic in SAVIENNACL preconditioner");
 53: #else
 54:     PetscCall(MatViennaCLCopyToGPU(pc->pmat));
 55:     gpustruct = (Mat_SeqAIJViennaCL *)pc->pmat->spptr;

 57:     viennacl::linalg::amg_tag amg_tag_sa_pmis;
 58:     amg_tag_sa_pmis.set_coarsening_method(viennacl::linalg::AMG_COARSENING_METHOD_MIS2_AGGREGATION);
 59:     amg_tag_sa_pmis.set_interpolation_method(viennacl::linalg::AMG_INTERPOLATION_METHOD_SMOOTHED_AGGREGATION);
 60:     ViennaCLAIJMatrix *mat = (ViennaCLAIJMatrix *)gpustruct->mat;
 61:     sa->SAVIENNACL         = new viennacl::linalg::amg_precond<viennacl::compressed_matrix<PetscScalar>>(*mat, amg_tag_sa_pmis);
 62:     sa->SAVIENNACL->setup();
 63: #endif
 64:   } catch (char *ex) {
 65:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "ViennaCL error: %s", ex);
 66:   }
 67:   PetscFunctionReturn(PETSC_SUCCESS);
 68: }

 70: /*
 71:    PCApply_SAVIENNACL - Applies the SAVIENNACL preconditioner to a vector.

 73:    Input Parameters:
 74: .  pc - the preconditioner context
 75: .  x - input vector

 77:    Output Parameter:
 78: .  y - output vector

 80:    Application Interface Routine: PCApply()
 81:  */
 82: static PetscErrorCode PCApply_SAVIENNACL(PC pc, Vec x, Vec y)
 83: {
 84:   PC_SAVIENNACL                       *sac = (PC_SAVIENNACL *)pc->data;
 85:   PetscBool                            flg1, flg2;
 86:   viennacl::vector<PetscScalar> const *xarray = NULL;
 87:   viennacl::vector<PetscScalar>       *yarray = NULL;

 89:   PetscFunctionBegin;
 90:   /*how to apply a certain fixed number of iterations?*/
 91:   PetscCall(PetscObjectTypeCompare((PetscObject)x, VECSEQVIENNACL, &flg1));
 92:   PetscCall(PetscObjectTypeCompare((PetscObject)y, VECSEQVIENNACL, &flg2));
 93:   PetscCheck((flg1 && flg2), PetscObjectComm((PetscObject)pc), PETSC_ERR_SUP, "Currently only handles ViennaCL vectors");
 94:   if (!sac->SAVIENNACL) PetscCall(PCSetUp_SAVIENNACL(pc));
 95:   PetscCall(VecViennaCLGetArrayRead(x, &xarray));
 96:   PetscCall(VecViennaCLGetArrayWrite(y, &yarray));
 97:   try {
 98: #if !defined(PETSC_USE_COMPLEX)
 99:     *yarray = *xarray;
100:     sac->SAVIENNACL->apply(*yarray);
101: #endif
102:   } catch (char *ex) {
103:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "ViennaCL error: %s", ex);
104:   }
105:   PetscCall(VecViennaCLRestoreArrayRead(x, &xarray));
106:   PetscCall(VecViennaCLRestoreArrayWrite(y, &yarray));
107:   PetscCall(PetscObjectStateIncrease((PetscObject)y));
108:   PetscFunctionReturn(PETSC_SUCCESS);
109: }

111: /*
112:    PCDestroy_SAVIENNACL - Destroys the private context for the SAVIENNACL preconditioner
113:    that was created with PCCreate_SAVIENNACL().

115:    Input Parameter:
116: .  pc - the preconditioner context

118:    Application Interface Routine: PCDestroy()
119: */
120: static PetscErrorCode PCDestroy_SAVIENNACL(PC pc)
121: {
122:   PC_SAVIENNACL *sac = (PC_SAVIENNACL *)pc->data;

124:   PetscFunctionBegin;
125:   if (sac->SAVIENNACL) {
126:     try {
127:       delete sac->SAVIENNACL;
128:     } catch (char *ex) {
129:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "ViennaCL error: %s", ex);
130:     }
131:   }

133:   /*
134:       Free the private data structure that was hanging off the PC
135:   */
136:   PetscCall(PetscFree(pc->data));
137:   PetscFunctionReturn(PETSC_SUCCESS);
138: }

140: static PetscErrorCode PCSetFromOptions_SAVIENNACL(PC pc, PetscOptionItems *PetscOptionsObject)
141: {
142:   PetscFunctionBegin;
143:   PetscOptionsHeadBegin(PetscOptionsObject, "SAVIENNACL options");
144:   PetscOptionsHeadEnd();
145:   PetscFunctionReturn(PETSC_SUCCESS);
146: }

148: /*MC
149:   PCSAVIENNACL  - A smoothed agglomeration algorithm that can be used via the CUDA, OpenCL, and OpenMP backends of ViennaCL

151:   Level: advanced

153:   Developer Notes:
154:   This `PCType` does not appear to be registered

156: .seealso: [](ch_ksp), `PCCreate()`, `PCSetType()`, `PCType`, `PC`
157: M*/

159: PETSC_EXTERN PetscErrorCode PCCreate_SAVIENNACL(PC pc)
160: {
161:   PC_SAVIENNACL *sac;

163:   PetscFunctionBegin;
164:   /*
165:      Creates the private data structure for this preconditioner and
166:      attach it to the PC object.
167:   */
168:   PetscCall(PetscNew(&sac));
169:   pc->data = (void *)sac;

171:   /*
172:      Initialize the pointer to zero
173:      Initialize number of v-cycles to default (1)
174:   */
175:   sac->SAVIENNACL = 0;

177:   /*
178:       Set the pointers for the functions that are provided above.
179:       Now when the user-level routines (such as PCApply(), PCDestroy(), etc.)
180:       are called, they will automatically call these functions.  Note we
181:       choose not to provide a couple of these functions since they are
182:       not needed.
183:   */
184:   pc->ops->apply               = PCApply_SAVIENNACL;
185:   pc->ops->applytranspose      = 0;
186:   pc->ops->setup               = PCSetUp_SAVIENNACL;
187:   pc->ops->destroy             = PCDestroy_SAVIENNACL;
188:   pc->ops->setfromoptions      = PCSetFromOptions_SAVIENNACL;
189:   pc->ops->view                = 0;
190:   pc->ops->applyrichardson     = 0;
191:   pc->ops->applysymmetricleft  = 0;
192:   pc->ops->applysymmetricright = 0;
193:   PetscFunctionReturn(PETSC_SUCCESS);
194: }