LCOV - code coverage report
Current view: top level - eps/impls/external/primme - primme.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 187 204 91.7 %
Date: 2019-10-20 05:41:02 Functions: 17 18 94.4 %

          Line data    Source code
       1             : /*
       2             :    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       3             :    SLEPc - Scalable Library for Eigenvalue Problem Computations
       4             :    Copyright (c) 2002-2019, Universitat Politecnica de Valencia, Spain
       5             : 
       6             :    This file is part of SLEPc.
       7             :    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
       8             :    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       9             : */
      10             : /*
      11             :    This file implements a wrapper to the PRIMME package
      12             : */
      13             : 
      14             : #include <slepc/private/epsimpl.h>    /*I "slepceps.h" I*/
      15             : 
      16             : #include <primme.h>
      17             : 
      18             : #if defined(PETSC_USE_COMPLEX)
      19             : #if defined(PETSC_USE_REAL_SINGLE)
      20             : #define PRIMME_DRIVER cprimme
      21             : #else
      22             : #define PRIMME_DRIVER zprimme
      23             : #endif
      24             : #else
      25             : #if defined(PETSC_USE_REAL_SINGLE)
      26             : #define PRIMME_DRIVER sprimme
      27             : #else
      28             : #define PRIMME_DRIVER dprimme
      29             : #endif
      30             : #endif
      31             : 
      32             : typedef struct {
      33             :   primme_params primme;           /* param struc */
      34             :   primme_preset_method method;    /* primme method */
      35             :   Mat       A;                    /* problem matrix */
      36             :   KSP       ksp;                  /* linear solver and preconditioner */
      37             :   Vec       x,y;                  /* auxiliary vectors */
      38             :   double    target;               /* a copy of eps's target */
      39             : } EPS_PRIMME;
      40             : 
      41             : static void multMatvec_PRIMME(void*,PRIMME_INT*,void*,PRIMME_INT*,int*,struct primme_params*,int*);
      42             : static void applyPreconditioner_PRIMME(void*,PRIMME_INT*,void*,PRIMME_INT*,int*,struct primme_params*,int*);
      43             : 
      44        9785 : static void par_GlobalSumReal(void *sendBuf,void *recvBuf,int *count,primme_params *primme,int *ierr)
      45             : {
      46       19570 :   *ierr = MPI_Allreduce(sendBuf,recvBuf,*count,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)primme->commInfo));CHKERRABORT(PetscObjectComm((PetscObject)primme->commInfo),*ierr);
      47        9785 : }
      48             : 
      49           6 : PetscErrorCode EPSSetUp_PRIMME(EPS eps)
      50             : {
      51             :   PetscErrorCode ierr;
      52             :   PetscMPIInt    numProcs,procID;
      53           6 :   EPS_PRIMME     *ops = (EPS_PRIMME*)eps->data;
      54           6 :   primme_params  *primme = &ops->primme;
      55             :   PetscBool      istrivial,flg;
      56             : 
      57           6 :   PetscFunctionBegin;
      58           6 :   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)eps),&numProcs);CHKERRQ(ierr);
      59           6 :   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)eps),&procID);CHKERRQ(ierr);
      60             : 
      61             :   /* Check some constraints and set some default values */
      62           6 :   if (!eps->max_it) eps->max_it = PetscMax(1000,eps->n);
      63           6 :   ierr = STGetMatrix(eps->st,0,&ops->A);CHKERRQ(ierr);
      64           6 :   if (!eps->ishermitian) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"PRIMME is only available for Hermitian problems");
      65           6 :   if (eps->isgeneralized) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"PRIMME is not available for generalized problems");
      66           6 :   if (eps->arbitrary) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"Arbitrary selection of eigenpairs not supported in this solver");
      67           6 :   if (eps->stopping!=EPSStoppingBasic) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"External packages do not support user-defined stopping test");
      68           6 :   if (!eps->which) eps->which = EPS_LARGEST_REAL;
      69           6 :   if (eps->converged != EPSConvergedAbsolute) { ierr = PetscInfo(eps,"Warning: using absolute convergence test\n");CHKERRQ(ierr); }
      70           6 :   ierr = RGIsTrivial(eps->rg,&istrivial);CHKERRQ(ierr);
      71           6 :   if (!istrivial) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"This solver does not support region filtering");
      72             : 
      73             :   /* Transfer SLEPc options to PRIMME options */
      74           6 :   primme->n          = eps->n;
      75           6 :   primme->nLocal     = eps->nloc;
      76           6 :   primme->numEvals   = eps->nev;
      77           6 :   primme->matrix     = ops;
      78           6 :   primme->commInfo   = eps;
      79           6 :   primme->maxMatvecs = eps->max_it;
      80           6 :   primme->eps        = eps->tol==PETSC_DEFAULT?SLEPC_DEFAULT_TOL:eps->tol;
      81           6 :   primme->numProcs   = numProcs;
      82           6 :   primme->procID     = procID;
      83           6 :   primme->printLevel = 0;
      84           6 :   primme->correctionParams.precondition = 1;
      85             : 
      86           6 :   switch (eps->which) {
      87             :     case EPS_LARGEST_REAL:
      88           4 :       primme->target = primme_largest;
      89           4 :       break;
      90             :     case EPS_SMALLEST_REAL:
      91           2 :       primme->target = primme_smallest;
      92           2 :       break;
      93             :     case EPS_TARGET_MAGNITUDE:
      94             :     case EPS_TARGET_REAL:
      95           0 :       primme->target = primme_closest_abs;
      96           0 :       primme->numTargetShifts = 1;
      97           0 :       ops->target = PetscRealPart(eps->target);
      98           0 :       primme->targetShifts = &ops->target;
      99           0 :       break;
     100             :     default:
     101           0 :       SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"'which' value not supported by PRIMME");
     102             :       break;
     103             :   }
     104             : 
     105           6 :   if (primme_set_method(ops->method,primme) < 0) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"PRIMME method not valid");
     106             : 
     107             :   /* If user sets ncv, maxBasisSize is modified. If not, ncv is set as maxBasisSize */
     108           6 :   if (eps->ncv) primme->maxBasisSize = eps->ncv;
     109           3 :   else eps->ncv = primme->maxBasisSize;
     110           6 :   if (eps->ncv < eps->nev+primme->maxBlockSize) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"PRIMME needs ncv >= nev+maxBlockSize");
     111           6 :   if (eps->mpd) { ierr = PetscInfo(eps,"Warning: parameter mpd ignored\n");CHKERRQ(ierr); }
     112             : 
     113           6 :   if (eps->extraction) { ierr = PetscInfo(eps,"Warning: extraction type ignored\n");CHKERRQ(ierr); }
     114             : 
     115             :   /* Set workspace */
     116           6 :   ierr = EPSAllocateSolution(eps,0);CHKERRQ(ierr);
     117           6 :   ierr = PetscObjectTypeCompare((PetscObject)eps->V,BVVECS,&flg);CHKERRQ(ierr);
     118           6 :   if (flg) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"This solver requires a BV with contiguous storage");
     119             : 
     120             :   /* Setup the preconditioner */
     121           6 :   if (primme->correctionParams.precondition) {
     122           6 :     ierr = STGetKSP(eps->st,&ops->ksp);CHKERRQ(ierr);
     123           6 :     ierr = PetscObjectTypeCompare((PetscObject)ops->ksp,KSPPREONLY,&flg);CHKERRQ(ierr);
     124           6 :     if (!flg) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_SUP,"PRIMME only works with KSPPREONLY");
     125           6 :     primme->preconditioner = NULL;
     126           6 :     primme->applyPreconditioner = applyPreconditioner_PRIMME;
     127             :   }
     128             : 
     129             :   /* Prepare auxiliary vectors */
     130           6 :   if (!ops->x) {
     131           5 :     ierr = MatCreateVecsEmpty(ops->A,&ops->x,&ops->y);CHKERRQ(ierr);
     132           5 :     ierr = PetscLogObjectParent((PetscObject)eps,(PetscObject)ops->x);CHKERRQ(ierr);
     133           5 :     ierr = PetscLogObjectParent((PetscObject)eps,(PetscObject)ops->y);CHKERRQ(ierr);
     134             :   }
     135           6 :   PetscFunctionReturn(0);
     136             : }
     137             : 
     138           6 : PetscErrorCode EPSSolve_PRIMME(EPS eps)
     139             : {
     140             :   PetscErrorCode ierr;
     141           6 :   EPS_PRIMME     *ops = (EPS_PRIMME*)eps->data;
     142             :   PetscScalar    *a;
     143             :   Vec            v0;
     144             : #if defined(PETSC_USE_COMPLEX)
     145             :   PetscInt       i;
     146             :   PetscReal      *evals;
     147             : #endif
     148             : 
     149           6 :   PetscFunctionBegin;
     150             :   /* Reset some parameters left from previous runs */
     151           6 :   ops->primme.aNorm    = 1.0;
     152           6 :   ops->primme.initSize = eps->nini;
     153           6 :   ops->primme.iseed[0] = -1;
     154             : 
     155             :   /* Call PRIMME solver */
     156           6 :   ierr = BVGetColumn(eps->V,0,&v0);CHKERRQ(ierr);
     157           6 :   ierr = VecGetArray(v0,&a);CHKERRQ(ierr);
     158             : #if !defined(PETSC_USE_COMPLEX)
     159           6 :   ierr = PRIMME_DRIVER(eps->eigr,a,eps->errest,&ops->primme);
     160           6 :   if (ierr) SETERRQ1(PetscObjectComm((PetscObject)eps),PETSC_ERR_LIB,"PRIMME library failed with error code=%d",ierr);
     161             : #else
     162             :   /* PRIMME returns real eigenvalues, but SLEPc works with complex ones */
     163             :   ierr = PetscMalloc1(eps->ncv,&evals);CHKERRQ(ierr);
     164             :   ierr = PRIMME_DRIVER(evals,a,eps->errest,&ops->primme);
     165             :   if (ierr) SETERRQ1(PetscObjectComm((PetscObject)eps),PETSC_ERR_LIB,"PRIMME library failed with error code=%d",ierr);
     166             :   for (i=0;i<eps->ncv;i++) eps->eigr[i] = evals[i];
     167             :   ierr = PetscFree(evals);CHKERRQ(ierr);
     168             : #endif
     169           6 :   ierr = VecRestoreArray(v0,&a);CHKERRQ(ierr);
     170           6 :   ierr = BVRestoreColumn(eps->V,0,&v0);CHKERRQ(ierr);
     171             : 
     172           6 :   eps->nconv  = ops->primme.initSize >= 0 ? ops->primme.initSize : 0;
     173           6 :   eps->reason = eps->ncv >= eps->nev ? EPS_CONVERGED_TOL: EPS_DIVERGED_ITS;
     174           6 :   eps->its    = ops->primme.stats.numOuterIterations;
     175           6 :   PetscFunctionReturn(0);
     176             : }
     177             : 
     178        2070 : static void multMatvec_PRIMME(void *xa,PRIMME_INT *ldx,void *ya,PRIMME_INT *ldy,int *blockSize,struct primme_params *primme,int *ierr)
     179             : {
     180             :   PetscInt   i;
     181        2070 :   EPS_PRIMME *ops = (EPS_PRIMME*)primme->matrix;
     182        2070 :   Vec        x = ops->x,y = ops->y;
     183        2070 :   Mat        A = ops->A;
     184             : 
     185        2070 :   PetscFunctionBegin;
     186        2273 :   for (i=0;i<*blockSize;i++) {
     187        2273 :     *ierr = VecPlaceArray(x,(PetscScalar*)xa+(*ldx)*i);CHKERRABORT(PetscObjectComm((PetscObject)A),*ierr);
     188        2273 :     *ierr = VecPlaceArray(y,(PetscScalar*)ya+(*ldy)*i);CHKERRABORT(PetscObjectComm((PetscObject)A),*ierr);
     189        2273 :     *ierr = MatMult(A,x,y);CHKERRABORT(PetscObjectComm((PetscObject)A),*ierr);
     190        2273 :     *ierr = VecResetArray(x);CHKERRABORT(PetscObjectComm((PetscObject)A),*ierr);
     191        2273 :     *ierr = VecResetArray(y);CHKERRABORT(PetscObjectComm((PetscObject)A),*ierr);
     192             :   }
     193        2070 :   PetscFunctionReturnVoid();
     194             : }
     195             : 
     196        1915 : static void applyPreconditioner_PRIMME(void *xa,PRIMME_INT *ldx,void *ya,PRIMME_INT *ldy,int *blockSize,struct primme_params *primme,int *ierr)
     197             : {
     198             :   PetscInt   i;
     199        1915 :   EPS_PRIMME *ops = (EPS_PRIMME*)primme->matrix;
     200        1915 :   Vec        x = ops->x,y = ops->y;
     201             : 
     202        1915 :   PetscFunctionBegin;
     203        2011 :   for (i=0;i<*blockSize;i++) {
     204        2011 :     *ierr = VecPlaceArray(x,(PetscScalar*)xa+(*ldx)*i);CHKERRABORT(PetscObjectComm((PetscObject)ops->ksp),*ierr);
     205        2011 :     *ierr = VecPlaceArray(y,(PetscScalar*)ya+(*ldy)*i);CHKERRABORT(PetscObjectComm((PetscObject)ops->ksp),*ierr);
     206        2011 :     *ierr = KSPSolve(ops->ksp,x,y);CHKERRABORT(PetscObjectComm((PetscObject)ops->ksp),*ierr);
     207        2011 :     *ierr = VecResetArray(x);CHKERRABORT(PetscObjectComm((PetscObject)ops->ksp),*ierr);
     208        2011 :     *ierr = VecResetArray(y);CHKERRABORT(PetscObjectComm((PetscObject)ops->ksp),*ierr);
     209             :   }
     210        1915 :   PetscFunctionReturnVoid();
     211             : }
     212             : 
     213           5 : PetscErrorCode EPSReset_PRIMME(EPS eps)
     214             : {
     215             :   PetscErrorCode ierr;
     216           5 :   EPS_PRIMME     *ops = (EPS_PRIMME*)eps->data;
     217             : 
     218           5 :   PetscFunctionBegin;
     219           5 :   primme_free(&ops->primme);
     220           5 :   ierr = VecDestroy(&ops->x);CHKERRQ(ierr);
     221           5 :   ierr = VecDestroy(&ops->y);CHKERRQ(ierr);
     222           5 :   PetscFunctionReturn(0);
     223             : }
     224             : 
     225           5 : PetscErrorCode EPSDestroy_PRIMME(EPS eps)
     226             : {
     227             :   PetscErrorCode ierr;
     228             : 
     229           5 :   PetscFunctionBegin;
     230           5 :   ierr = PetscFree(eps->data);CHKERRQ(ierr);
     231           5 :   ierr = PetscObjectComposeFunction((PetscObject)eps,"EPSPRIMMESetBlockSize_C",NULL);CHKERRQ(ierr);
     232           5 :   ierr = PetscObjectComposeFunction((PetscObject)eps,"EPSPRIMMESetMethod_C",NULL);CHKERRQ(ierr);
     233           5 :   ierr = PetscObjectComposeFunction((PetscObject)eps,"EPSPRIMMEGetBlockSize_C",NULL);CHKERRQ(ierr);
     234           5 :   ierr = PetscObjectComposeFunction((PetscObject)eps,"EPSPRIMMEGetMethod_C",NULL);CHKERRQ(ierr);
     235           5 :   PetscFunctionReturn(0);
     236             : }
     237             : 
     238           0 : PetscErrorCode EPSView_PRIMME(EPS eps,PetscViewer viewer)
     239             : {
     240             :   PetscErrorCode  ierr;
     241             :   PetscBool       isascii;
     242           0 :   primme_params   *primme = &((EPS_PRIMME*)eps->data)->primme;
     243             :   EPSPRIMMEMethod methodn;
     244             :   PetscMPIInt     rank;
     245             : 
     246           0 :   PetscFunctionBegin;
     247           0 :   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
     248           0 :   if (isascii) {
     249           0 :     ierr = PetscViewerASCIIPrintf(viewer,"  block size=%D\n",primme->maxBlockSize);CHKERRQ(ierr);
     250           0 :     ierr = EPSPRIMMEGetMethod(eps,&methodn);CHKERRQ(ierr);
     251           0 :     ierr = PetscViewerASCIIPrintf(viewer,"  solver method: %s\n",EPSPRIMMEMethods[methodn]);CHKERRQ(ierr);
     252             : 
     253             :     /* Display PRIMME params */
     254           0 :     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)eps),&rank);CHKERRQ(ierr);
     255           0 :     if (!rank) primme_display_params(*primme);
     256             :   }
     257           0 :   PetscFunctionReturn(0);
     258             : }
     259             : 
     260           4 : PetscErrorCode EPSSetFromOptions_PRIMME(PetscOptionItems *PetscOptionsObject,EPS eps)
     261             : {
     262             :   PetscErrorCode  ierr;
     263           4 :   EPS_PRIMME      *ctx = (EPS_PRIMME*)eps->data;
     264             :   PetscInt        bs;
     265             :   EPSPRIMMEMethod meth;
     266             :   PetscBool       flg;
     267             : 
     268           4 :   PetscFunctionBegin;
     269           4 :   ierr = PetscOptionsHead(PetscOptionsObject,"EPS PRIMME Options");CHKERRQ(ierr);
     270             : 
     271           4 :     ierr = PetscOptionsInt("-eps_primme_blocksize","Maximum block size","EPSPRIMMESetBlockSize",ctx->primme.maxBlockSize,&bs,&flg);CHKERRQ(ierr);
     272           4 :     if (flg) { ierr = EPSPRIMMESetBlockSize(eps,bs);CHKERRQ(ierr); }
     273             : 
     274           4 :     ierr = PetscOptionsEnum("-eps_primme_method","Method for solving the eigenproblem","EPSPRIMMESetMethod",EPSPRIMMEMethods,(PetscEnum)ctx->method,(PetscEnum*)&meth,&flg);CHKERRQ(ierr);
     275           4 :     if (flg) { ierr = EPSPRIMMESetMethod(eps,meth);CHKERRQ(ierr); }
     276             : 
     277           4 :   ierr = PetscOptionsTail();CHKERRQ(ierr);
     278           4 :   PetscFunctionReturn(0);
     279             : }
     280             : 
     281           2 : static PetscErrorCode EPSPRIMMESetBlockSize_PRIMME(EPS eps,PetscInt bs)
     282             : {
     283           2 :   EPS_PRIMME *ops = (EPS_PRIMME*)eps->data;
     284             : 
     285           2 :   PetscFunctionBegin;
     286           2 :   if (bs == PETSC_DEFAULT) ops->primme.maxBlockSize = 1;
     287           2 :   else if (bs <= 0) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_OUTOFRANGE,"PRIMME: block size must be positive");
     288           2 :   else ops->primme.maxBlockSize = bs;
     289           2 :   PetscFunctionReturn(0);
     290             : }
     291             : 
     292             : /*@
     293             :    EPSPRIMMESetBlockSize - The maximum block size that PRIMME will try to use.
     294             : 
     295             :    Logically Collective on eps
     296             : 
     297             :    Input Parameters:
     298             : +  eps - the eigenproblem solver context
     299             : -  bs - block size
     300             : 
     301             :    Options Database Key:
     302             : .  -eps_primme_blocksize - Sets the max allowed block size value
     303             : 
     304             :    Notes:
     305             :    If the block size is not set, the value established by primme_initialize
     306             :    is used.
     307             : 
     308             :    The user should set the block size based on the architecture specifics
     309             :    of the target computer, as well as any a priori knowledge of multiplicities.
     310             :    The code does NOT require bs > 1 to find multiple eigenvalues. For some
     311             :    methods, keeping bs = 1 yields the best overall performance.
     312             : 
     313             :    Level: advanced
     314             : 
     315             : .seealso: EPSPRIMMEGetBlockSize()
     316             : @*/
     317           2 : PetscErrorCode EPSPRIMMESetBlockSize(EPS eps,PetscInt bs)
     318             : {
     319             :   PetscErrorCode ierr;
     320             : 
     321           2 :   PetscFunctionBegin;
     322           2 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     323           4 :   PetscValidLogicalCollectiveInt(eps,bs,2);
     324           2 :   ierr = PetscTryMethod(eps,"EPSPRIMMESetBlockSize_C",(EPS,PetscInt),(eps,bs));CHKERRQ(ierr);
     325           4 :   PetscFunctionReturn(0);
     326             : }
     327             : 
     328           1 : static PetscErrorCode EPSPRIMMEGetBlockSize_PRIMME(EPS eps,PetscInt *bs)
     329             : {
     330           1 :   EPS_PRIMME *ops = (EPS_PRIMME*)eps->data;
     331             : 
     332           1 :   PetscFunctionBegin;
     333           1 :   *bs = ops->primme.maxBlockSize;
     334           1 :   PetscFunctionReturn(0);
     335             : }
     336             : 
     337             : /*@
     338             :    EPSPRIMMEGetBlockSize - Get the maximum block size the code will try to use.
     339             : 
     340             :    Not Collective
     341             : 
     342             :    Input Parameter:
     343             : .  eps - the eigenproblem solver context
     344             : 
     345             :    Output Parameter:
     346             : .  bs - returned block size
     347             : 
     348             :    Level: advanced
     349             : 
     350             : .seealso: EPSPRIMMESetBlockSize()
     351             : @*/
     352           1 : PetscErrorCode EPSPRIMMEGetBlockSize(EPS eps,PetscInt *bs)
     353             : {
     354             :   PetscErrorCode ierr;
     355             : 
     356           1 :   PetscFunctionBegin;
     357           1 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     358           1 :   PetscValidIntPointer(bs,2);
     359           1 :   ierr = PetscUseMethod(eps,"EPSPRIMMEGetBlockSize_C",(EPS,PetscInt*),(eps,bs));CHKERRQ(ierr);
     360           2 :   PetscFunctionReturn(0);
     361             : }
     362             : 
     363           2 : static PetscErrorCode EPSPRIMMESetMethod_PRIMME(EPS eps,EPSPRIMMEMethod method)
     364             : {
     365           2 :   EPS_PRIMME *ops = (EPS_PRIMME*)eps->data;
     366             : 
     367           2 :   PetscFunctionBegin;
     368           2 :   ops->method = (primme_preset_method)method;
     369           2 :   PetscFunctionReturn(0);
     370             : }
     371             : 
     372             : /*@
     373             :    EPSPRIMMESetMethod - Sets the method for the PRIMME library.
     374             : 
     375             :    Logically Collective on eps
     376             : 
     377             :    Input Parameters:
     378             : +  eps - the eigenproblem solver context
     379             : -  method - method that will be used by PRIMME
     380             : 
     381             :    Options Database Key:
     382             : .  -eps_primme_method - Sets the method for the PRIMME library
     383             : 
     384             :    Note:
     385             :    If not set, the method defaults to EPS_PRIMME_DEFAULT_MIN_TIME.
     386             : 
     387             :    Level: advanced
     388             : 
     389             : .seealso: EPSPRIMMEGetMethod(), EPSPRIMMEMethod
     390             : @*/
     391           2 : PetscErrorCode EPSPRIMMESetMethod(EPS eps,EPSPRIMMEMethod method)
     392             : {
     393             :   PetscErrorCode ierr;
     394             : 
     395           2 :   PetscFunctionBegin;
     396           2 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     397           4 :   PetscValidLogicalCollectiveEnum(eps,method,2);
     398           2 :   ierr = PetscTryMethod(eps,"EPSPRIMMESetMethod_C",(EPS,EPSPRIMMEMethod),(eps,method));CHKERRQ(ierr);
     399           4 :   PetscFunctionReturn(0);
     400             : }
     401             : 
     402           1 : static PetscErrorCode EPSPRIMMEGetMethod_PRIMME(EPS eps,EPSPRIMMEMethod *method)
     403             : {
     404           1 :   EPS_PRIMME *ops = (EPS_PRIMME*)eps->data;
     405             : 
     406           1 :   PetscFunctionBegin;
     407           1 :   *method = (EPSPRIMMEMethod)ops->method;
     408           1 :   PetscFunctionReturn(0);
     409             : }
     410             : 
     411             : /*@
     412             :    EPSPRIMMEGetMethod - Gets the method for the PRIMME library.
     413             : 
     414             :    Not Collective
     415             : 
     416             :    Input Parameter:
     417             : .  eps - the eigenproblem solver context
     418             : 
     419             :    Output Parameter:
     420             : .  method - method that will be used by PRIMME
     421             : 
     422             :    Level: advanced
     423             : 
     424             : .seealso: EPSPRIMMESetMethod(), EPSPRIMMEMethod
     425             : @*/
     426           1 : PetscErrorCode EPSPRIMMEGetMethod(EPS eps,EPSPRIMMEMethod *method)
     427             : {
     428             :   PetscErrorCode ierr;
     429             : 
     430           1 :   PetscFunctionBegin;
     431           1 :   PetscValidHeaderSpecific(eps,EPS_CLASSID,1);
     432           1 :   PetscValidPointer(method,2);
     433           1 :   ierr = PetscUseMethod(eps,"EPSPRIMMEGetMethod_C",(EPS,EPSPRIMMEMethod*),(eps,method));CHKERRQ(ierr);
     434           2 :   PetscFunctionReturn(0);
     435             : }
     436             : 
     437           5 : SLEPC_EXTERN PetscErrorCode EPSCreate_PRIMME(EPS eps)
     438             : {
     439             :   PetscErrorCode ierr;
     440             :   EPS_PRIMME     *primme;
     441             : 
     442           5 :   PetscFunctionBegin;
     443           5 :   ierr = PetscNewLog(eps,&primme);CHKERRQ(ierr);
     444           5 :   eps->data = (void*)primme;
     445             : 
     446           5 :   primme_initialize(&primme->primme);
     447           5 :   primme->primme.matrixMatvec = multMatvec_PRIMME;
     448           5 :   primme->primme.globalSumReal = par_GlobalSumReal;
     449           5 :   primme->method = (primme_preset_method)EPS_PRIMME_DEFAULT_MIN_TIME;
     450             : 
     451           5 :   eps->categ = EPS_CATEGORY_PRECOND;
     452             : 
     453           5 :   eps->ops->solve          = EPSSolve_PRIMME;
     454           5 :   eps->ops->setup          = EPSSetUp_PRIMME;
     455           5 :   eps->ops->setfromoptions = EPSSetFromOptions_PRIMME;
     456           5 :   eps->ops->destroy        = EPSDestroy_PRIMME;
     457           5 :   eps->ops->reset          = EPSReset_PRIMME;
     458           5 :   eps->ops->view           = EPSView_PRIMME;
     459           5 :   eps->ops->backtransform  = EPSBackTransform_Default;
     460           5 :   eps->ops->setdefaultst   = EPSSetDefaultST_Precond;
     461             : 
     462           5 :   ierr = PetscObjectComposeFunction((PetscObject)eps,"EPSPRIMMESetBlockSize_C",EPSPRIMMESetBlockSize_PRIMME);CHKERRQ(ierr);
     463           5 :   ierr = PetscObjectComposeFunction((PetscObject)eps,"EPSPRIMMESetMethod_C",EPSPRIMMESetMethod_PRIMME);CHKERRQ(ierr);
     464           5 :   ierr = PetscObjectComposeFunction((PetscObject)eps,"EPSPRIMMEGetBlockSize_C",EPSPRIMMEGetBlockSize_PRIMME);CHKERRQ(ierr);
     465           5 :   ierr = PetscObjectComposeFunction((PetscObject)eps,"EPSPRIMMEGetMethod_C",EPSPRIMMEGetMethod_PRIMME);CHKERRQ(ierr);
     466           5 :   PetscFunctionReturn(0);
     467             : }
     468             : 

Generated by: LCOV version 1.13