LCOV - code coverage report
Current view: top level - svd/impls/external/primme - svdprimme.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 175 188 93.1 %
Date: 2019-10-20 05:41:02 Functions: 16 17 94.1 %

          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 SVD solver
      12             : */
      13             : 
      14             : #include <slepc/private/svdimpl.h>    /*I "slepcsvd.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_svds
      21             : #else
      22             : #define PRIMME_DRIVER zprimme_svds
      23             : #endif
      24             : #else
      25             : #if defined(PETSC_USE_REAL_SINGLE)
      26             : #define PRIMME_DRIVER sprimme_svds
      27             : #else
      28             : #define PRIMME_DRIVER dprimme_svds
      29             : #endif
      30             : #endif
      31             : 
      32             : typedef struct {
      33             :   primme_svds_params primme;         /* param struct */
      34             :   primme_svds_preset_method method;  /* primme method */
      35             :   SVD       svd;                     /* reference to the solver */
      36             :   Vec       x,y;                     /* auxiliary vectors */
      37             : } SVD_PRIMME;
      38             : 
      39             : static void multMatvec_PRIMME(void*,PRIMME_INT*,void*,PRIMME_INT*,int*,int*,struct primme_svds_params*,int*);
      40             : 
      41           6 : static void par_GlobalSumReal(void *sendBuf,void *recvBuf,int *count,primme_svds_params *primme,int *ierr)
      42             : {
      43          12 :   *ierr = MPI_Allreduce(sendBuf,recvBuf,*count,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)primme->commInfo));CHKERRABORT(PetscObjectComm((PetscObject)primme->commInfo),*ierr);
      44           6 : }
      45             : 
      46           6 : PetscErrorCode SVDSetUp_PRIMME(SVD svd)
      47             : {
      48             :   PetscErrorCode     ierr;
      49             :   PetscMPIInt        numProcs,procID;
      50             :   PetscInt           n,m,nloc,mloc;
      51           6 :   SVD_PRIMME         *ops = (SVD_PRIMME*)svd->data;
      52           6 :   primme_svds_params *primme = &ops->primme;
      53             : 
      54           6 :   PetscFunctionBegin;
      55           6 :   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)svd),&numProcs);CHKERRQ(ierr);
      56           6 :   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)svd),&procID);CHKERRQ(ierr);
      57             : 
      58             :   /* Check some constraints and set some default values */
      59           6 :   ierr = SVDMatGetSize(svd,&m,&n);CHKERRQ(ierr);
      60           6 :   ierr = SVDMatGetLocalSize(svd,&mloc,&nloc);CHKERRQ(ierr);
      61           6 :   ierr = SVDSetDimensions_Default(svd);CHKERRQ(ierr);
      62           6 :   if (!svd->max_it) svd->max_it = PetscMax(n/svd->ncv,1000);
      63           6 :   svd->leftbasis = PETSC_TRUE;
      64           6 :   if (svd->stopping!=SVDStoppingBasic) SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_SUP,"External packages do not support user-defined stopping test");
      65           6 :   if (svd->converged != SVDConvergedAbsolute) { ierr = PetscInfo(svd,"Warning: using absolute convergence test\n");CHKERRQ(ierr); }
      66             : 
      67             :   /* Transfer SLEPc options to PRIMME options */
      68           6 :   primme->m          = m;
      69           6 :   primme->n          = n;
      70           6 :   primme->mLocal     = mloc;
      71           6 :   primme->nLocal     = nloc;
      72           6 :   primme->numSvals   = svd->nsv;
      73           6 :   primme->matrix     = ops;
      74           6 :   primme->commInfo   = svd;
      75           6 :   primme->maxMatvecs = svd->max_it;
      76           6 :   primme->eps        = svd->tol==PETSC_DEFAULT?SLEPC_DEFAULT_TOL:svd->tol;
      77           6 :   primme->numProcs   = numProcs;
      78           6 :   primme->procID     = procID;
      79           6 :   primme->locking    = 1;
      80           6 :   primme->printLevel = 0;
      81             : 
      82           6 :   switch (svd->which) {
      83             :     case SVD_LARGEST:
      84           5 :       primme->target = primme_svds_largest;
      85           5 :       break;
      86             :     case SVD_SMALLEST:
      87           1 :       primme->target = primme_svds_smallest;
      88           1 :       break;
      89             :     default:
      90           0 :       SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_SUP,"'which' value not supported by PRIMME");
      91             :       break;
      92             :   }
      93             : 
      94             :   /* If user sets mpd or ncv, maxBasisSize is modified */
      95           6 :   if (svd->mpd) primme->maxBasisSize = svd->mpd;
      96           0 :   else if (svd->ncv) primme->maxBasisSize = svd->ncv;
      97             : 
      98           6 :   if (primme_svds_set_method(ops->method,(primme_preset_method)EPS_PRIMME_DEFAULT_MIN_TIME,(primme_preset_method)EPS_PRIMME_DEFAULT_MIN_TIME,primme) < 0) SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_SUP,"PRIMME method not valid");
      99             : 
     100           6 :   svd->mpd = primme->maxBasisSize;
     101           6 :   svd->ncv = svd->nsv;
     102             : 
     103             :   /* Set workspace */
     104           6 :   ierr = SVDAllocateSolution(svd,0);CHKERRQ(ierr);
     105             : 
     106             :   /* Prepare auxiliary vectors */
     107           6 :   if (!ops->x) {
     108           5 :     ierr = MatCreateVecsEmpty(svd->A,&ops->x,&ops->y);CHKERRQ(ierr);
     109           5 :     ierr = PetscLogObjectParent((PetscObject)svd,(PetscObject)ops->x);CHKERRQ(ierr);
     110           5 :     ierr = PetscLogObjectParent((PetscObject)svd,(PetscObject)ops->y);CHKERRQ(ierr);
     111             :   }
     112           6 :   PetscFunctionReturn(0);
     113             : }
     114             : 
     115           6 : PetscErrorCode SVDSolve_PRIMME(SVD svd)
     116             : {
     117             :   PetscErrorCode ierr;
     118           6 :   SVD_PRIMME     *ops = (SVD_PRIMME*)svd->data;
     119             :   PetscScalar    *svecs, *a;
     120             : 
     121           6 :   PetscFunctionBegin;
     122             :   /* Reset some parameters left from previous runs */
     123           6 :   ops->primme.aNorm    = 0.0;
     124           6 :   ops->primme.initSize = svd->nini;
     125           6 :   ops->primme.iseed[0] = -1;
     126           6 :   ops->primme.iseed[1] = -1;
     127           6 :   ops->primme.iseed[2] = -1;
     128           6 :   ops->primme.iseed[3] = -1;
     129             : 
     130             :   /* Allocating left and right singular vectors contiguously */
     131           6 :   ierr = PetscCalloc1(ops->primme.numSvals*(ops->primme.mLocal+ops->primme.nLocal),&svecs);CHKERRQ(ierr);
     132           6 :   ierr = PetscLogObjectMemory((PetscObject)svd,sizeof(PetscReal)*ops->primme.numSvals*(ops->primme.mLocal+ops->primme.nLocal));CHKERRQ(ierr);
     133             : 
     134             :   /* Call PRIMME solver */
     135           6 :   ierr = PRIMME_DRIVER(svd->sigma,svecs,svd->errest,&ops->primme);
     136           6 :   if (ierr) SETERRQ1(PetscObjectComm((PetscObject)svd),PETSC_ERR_LIB,"PRIMME library failed with error code=%d",ierr);
     137             : 
     138             :   /* Copy left and right singular vectors into svd */
     139           6 :   ierr = BVGetArray(svd->U,&a);CHKERRQ(ierr);
     140           6 :   ierr = PetscArraycpy(a,svecs,ops->primme.mLocal*ops->primme.initSize);CHKERRQ(ierr);
     141           6 :   ierr = BVRestoreArray(svd->U,&a);CHKERRQ(ierr);
     142             : 
     143           6 :   ierr = BVGetArray(svd->V,&a);CHKERRQ(ierr);
     144           6 :   ierr = PetscArraycpy(a,svecs+ops->primme.mLocal*ops->primme.initSize,ops->primme.nLocal*ops->primme.initSize);CHKERRQ(ierr);
     145           6 :   ierr = BVRestoreArray(svd->V,&a);CHKERRQ(ierr);
     146             : 
     147           6 :   ierr = PetscFree(svecs);CHKERRQ(ierr);
     148             : 
     149           6 :   svd->nconv  = ops->primme.initSize >= 0 ? ops->primme.initSize : 0;
     150           6 :   svd->reason = svd->nconv >= svd->nsv ? SVD_CONVERGED_TOL: SVD_DIVERGED_ITS;
     151           6 :   svd->its    = ops->primme.stats.numOuterIterations;
     152           6 :   PetscFunctionReturn(0);
     153             : }
     154             : 
     155        1048 : static void multMatvec_PRIMME(void *xa,PRIMME_INT *ldx,void *ya,PRIMME_INT *ldy,int *blockSize,int *transpose,struct primme_svds_params *primme,int *ierr)
     156             : {
     157             :   PetscInt   i;
     158        1048 :   SVD_PRIMME *ops = (SVD_PRIMME*)primme->matrix;
     159        1048 :   Vec        x = ops->x,y = ops->y;
     160        1048 :   SVD        svd = ops->svd;
     161             : 
     162        1048 :   PetscFunctionBegin;
     163        1136 :   for (i=0;i<*blockSize;i++) {
     164        1136 :     if (*transpose) {
     165         556 :       *ierr = VecPlaceArray(y,(PetscScalar*)xa+(*ldx)*i);CHKERRABORT(PetscObjectComm((PetscObject)svd),*ierr);
     166         556 :       *ierr = VecPlaceArray(x,(PetscScalar*)ya+(*ldy)*i);CHKERRABORT(PetscObjectComm((PetscObject)svd),*ierr);
     167         556 :       *ierr = SVDMatMult(svd,PETSC_TRUE,y,x);CHKERRABORT(PetscObjectComm((PetscObject)svd),*ierr);
     168             :     } else {
     169         580 :       *ierr = VecPlaceArray(x,(PetscScalar*)xa+(*ldx)*i);CHKERRABORT(PetscObjectComm((PetscObject)svd),*ierr);
     170         580 :       *ierr = VecPlaceArray(y,(PetscScalar*)ya+(*ldy)*i);CHKERRABORT(PetscObjectComm((PetscObject)svd),*ierr);
     171         580 :       *ierr = SVDMatMult(svd,PETSC_FALSE,x,y);CHKERRABORT(PetscObjectComm((PetscObject)svd),*ierr);
     172             :     }
     173        1136 :     *ierr = VecResetArray(x);CHKERRABORT(PetscObjectComm((PetscObject)svd),*ierr);
     174        1136 :     *ierr = VecResetArray(y);CHKERRABORT(PetscObjectComm((PetscObject)svd),*ierr);
     175             :   }
     176        1048 :   PetscFunctionReturnVoid();
     177             : }
     178             : 
     179           5 : PetscErrorCode SVDReset_PRIMME(SVD svd)
     180             : {
     181             :   PetscErrorCode ierr;
     182           5 :   SVD_PRIMME     *ops = (SVD_PRIMME*)svd->data;
     183             : 
     184           5 :   PetscFunctionBegin;
     185           5 :   primme_svds_free(&ops->primme);
     186           5 :   ierr = VecDestroy(&ops->x);CHKERRQ(ierr);
     187           5 :   ierr = VecDestroy(&ops->y);CHKERRQ(ierr);
     188           5 :   PetscFunctionReturn(0);
     189             : }
     190             : 
     191           5 : PetscErrorCode SVDDestroy_PRIMME(SVD svd)
     192             : {
     193             :   PetscErrorCode ierr;
     194             : 
     195           5 :   PetscFunctionBegin;
     196           5 :   ierr = PetscFree(svd->data);CHKERRQ(ierr);
     197           5 :   ierr = PetscObjectComposeFunction((PetscObject)svd,"SVDPRIMMESetBlockSize_C",NULL);CHKERRQ(ierr);
     198           5 :   ierr = PetscObjectComposeFunction((PetscObject)svd,"SVDPRIMMEGetBlockSize_C",NULL);CHKERRQ(ierr);
     199           5 :   ierr = PetscObjectComposeFunction((PetscObject)svd,"SVDPRIMMESetMethod_C",NULL);CHKERRQ(ierr);
     200           5 :   ierr = PetscObjectComposeFunction((PetscObject)svd,"SVDPRIMMEGetMethod_C",NULL);CHKERRQ(ierr);
     201           5 :   PetscFunctionReturn(0);
     202             : }
     203             : 
     204           0 : PetscErrorCode SVDView_PRIMME(SVD svd,PetscViewer viewer)
     205             : {
     206             :   PetscErrorCode     ierr;
     207             :   PetscBool          isascii;
     208           0 :   primme_svds_params *primme = &((SVD_PRIMME*)svd->data)->primme;
     209             :   SVDPRIMMEMethod    methodn;
     210             :   PetscMPIInt        rank;
     211             : 
     212           0 :   PetscFunctionBegin;
     213           0 :   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
     214           0 :   if (isascii) {
     215           0 :     ierr = PetscViewerASCIIPrintf(viewer,"  block size=%D\n",primme->maxBlockSize);CHKERRQ(ierr);
     216           0 :     ierr = SVDPRIMMEGetMethod(svd,&methodn);CHKERRQ(ierr);
     217           0 :     ierr = PetscViewerASCIIPrintf(viewer,"  solver method: %s\n",SVDPRIMMEMethods[methodn]);CHKERRQ(ierr);
     218             : 
     219             :     /* Display PRIMME params */
     220           0 :     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)svd),&rank);CHKERRQ(ierr);
     221           0 :     if (!rank) primme_svds_display_params(*primme);
     222             :   }
     223           0 :   PetscFunctionReturn(0);
     224             : }
     225             : 
     226           4 : PetscErrorCode SVDSetFromOptions_PRIMME(PetscOptionItems *PetscOptionsObject,SVD svd)
     227             : {
     228             :   PetscErrorCode  ierr;
     229           4 :   SVD_PRIMME      *ctx = (SVD_PRIMME*)svd->data;
     230             :   PetscInt        bs;
     231             :   SVDPRIMMEMethod meth;
     232             :   PetscBool       flg;
     233             : 
     234           4 :   PetscFunctionBegin;
     235           4 :   ierr = PetscOptionsHead(PetscOptionsObject,"SVD PRIMME Options");CHKERRQ(ierr);
     236             : 
     237           4 :     ierr = PetscOptionsInt("-svd_primme_blocksize","Maximum block size","SVDPRIMMESetBlockSize",ctx->primme.maxBlockSize,&bs,&flg);CHKERRQ(ierr);
     238           4 :     if (flg) { ierr = SVDPRIMMESetBlockSize(svd,bs);CHKERRQ(ierr); }
     239             : 
     240           4 :     ierr = PetscOptionsEnum("-svd_primme_method","Method for solving the singular value problem","SVDPRIMMESetMethod",SVDPRIMMEMethods,(PetscEnum)ctx->method,(PetscEnum*)&meth,&flg);CHKERRQ(ierr);
     241           4 :     if (flg) { ierr = SVDPRIMMESetMethod(svd,meth);CHKERRQ(ierr); }
     242             : 
     243           4 :   ierr = PetscOptionsTail();CHKERRQ(ierr);
     244           4 :   PetscFunctionReturn(0);
     245             : }
     246             : 
     247           2 : static PetscErrorCode SVDPRIMMESetBlockSize_PRIMME(SVD svd,PetscInt bs)
     248             : {
     249           2 :   SVD_PRIMME *ops = (SVD_PRIMME*)svd->data;
     250             : 
     251           2 :   PetscFunctionBegin;
     252           2 :   if (bs == PETSC_DEFAULT) ops->primme.maxBlockSize = 1;
     253           2 :   else if (bs <= 0) SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_ARG_OUTOFRANGE,"PRIMME: block size must be positive");
     254           2 :   else ops->primme.maxBlockSize = bs;
     255           2 :   PetscFunctionReturn(0);
     256             : }
     257             : 
     258             : /*@
     259             :    SVDPRIMMESetBlockSize - The maximum block size that PRIMME will try to use.
     260             : 
     261             :    Logically Collective on svd
     262             : 
     263             :    Input Parameters:
     264             : +  svd - the singular value solver context
     265             : -  bs - block size
     266             : 
     267             :    Options Database Key:
     268             : .  -svd_primme_blocksize - Sets the max allowed block size value
     269             : 
     270             :    Notes:
     271             :    If the block size is not set, the value established by primme_svds_initialize
     272             :    is used.
     273             : 
     274             :    The user should set the block size based on the architecture specifics
     275             :    of the target computer, as well as any a priori knowledge of multiplicities.
     276             :    The code does NOT require bs > 1 to find multiple eigenvalues. For some
     277             :    methods, keeping bs = 1 yields the best overall performance.
     278             : 
     279             :    Level: advanced
     280             : 
     281             : .seealso: SVDPRIMMEGetBlockSize()
     282             : @*/
     283           2 : PetscErrorCode SVDPRIMMESetBlockSize(SVD svd,PetscInt bs)
     284             : {
     285             :   PetscErrorCode ierr;
     286             : 
     287           2 :   PetscFunctionBegin;
     288           2 :   PetscValidHeaderSpecific(svd,SVD_CLASSID,1);
     289           4 :   PetscValidLogicalCollectiveInt(svd,bs,2);
     290           2 :   ierr = PetscTryMethod(svd,"SVDPRIMMESetBlockSize_C",(SVD,PetscInt),(svd,bs));CHKERRQ(ierr);
     291           4 :   PetscFunctionReturn(0);
     292             : }
     293             : 
     294           1 : static PetscErrorCode SVDPRIMMEGetBlockSize_PRIMME(SVD svd,PetscInt *bs)
     295             : {
     296           1 :   SVD_PRIMME *ops = (SVD_PRIMME*)svd->data;
     297             : 
     298           1 :   PetscFunctionBegin;
     299           1 :   *bs = ops->primme.maxBlockSize;
     300           1 :   PetscFunctionReturn(0);
     301             : }
     302             : 
     303             : /*@
     304             :    SVDPRIMMEGetBlockSize - Get the maximum block size the code will try to use.
     305             : 
     306             :    Not Collective
     307             : 
     308             :    Input Parameter:
     309             : .  svd - the singular value solver context
     310             : 
     311             :    Output Parameter:
     312             : .  bs - returned block size
     313             : 
     314             :    Level: advanced
     315             : 
     316             : .seealso: SVDPRIMMESetBlockSize()
     317             : @*/
     318           1 : PetscErrorCode SVDPRIMMEGetBlockSize(SVD svd,PetscInt *bs)
     319             : {
     320             :   PetscErrorCode ierr;
     321             : 
     322           1 :   PetscFunctionBegin;
     323           1 :   PetscValidHeaderSpecific(svd,SVD_CLASSID,1);
     324           1 :   PetscValidIntPointer(bs,2);
     325           1 :   ierr = PetscUseMethod(svd,"SVDPRIMMEGetBlockSize_C",(SVD,PetscInt*),(svd,bs));CHKERRQ(ierr);
     326           2 :   PetscFunctionReturn(0);
     327             : }
     328             : 
     329           2 : static PetscErrorCode SVDPRIMMESetMethod_PRIMME(SVD svd,SVDPRIMMEMethod method)
     330             : {
     331           2 :   SVD_PRIMME *ops = (SVD_PRIMME*)svd->data;
     332             : 
     333           2 :   PetscFunctionBegin;
     334           2 :   ops->method = (primme_svds_preset_method)method;
     335           2 :   PetscFunctionReturn(0);
     336             : }
     337             : 
     338             : /*@
     339             :    SVDPRIMMESetMethod - Sets the method for the PRIMME SVD solver.
     340             : 
     341             :    Logically Collective on svd
     342             : 
     343             :    Input Parameters:
     344             : +  svd - the singular value solver context
     345             : -  method - method that will be used by PRIMME
     346             : 
     347             :    Options Database Key:
     348             : .  -svd_primme_method - Sets the method for the PRIMME SVD solver
     349             : 
     350             :    Note:
     351             :    If not set, the method defaults to SVD_PRIMME_HYBRID.
     352             : 
     353             :    Level: advanced
     354             : 
     355             : .seealso: SVDPRIMMEGetMethod(), SVDPRIMMEMethod
     356             : @*/
     357           2 : PetscErrorCode SVDPRIMMESetMethod(SVD svd,SVDPRIMMEMethod method)
     358             : {
     359             :   PetscErrorCode ierr;
     360             : 
     361           2 :   PetscFunctionBegin;
     362           2 :   PetscValidHeaderSpecific(svd,SVD_CLASSID,1);
     363           4 :   PetscValidLogicalCollectiveEnum(svd,method,2);
     364           2 :   ierr = PetscTryMethod(svd,"SVDPRIMMESetMethod_C",(SVD,SVDPRIMMEMethod),(svd,method));CHKERRQ(ierr);
     365           4 :   PetscFunctionReturn(0);
     366             : }
     367             : 
     368           1 : static PetscErrorCode SVDPRIMMEGetMethod_PRIMME(SVD svd,SVDPRIMMEMethod *method)
     369             : {
     370           1 :   SVD_PRIMME *ops = (SVD_PRIMME*)svd->data;
     371             : 
     372           1 :   PetscFunctionBegin;
     373           1 :   *method = (SVDPRIMMEMethod)ops->method;
     374           1 :   PetscFunctionReturn(0);
     375             : }
     376             : 
     377             : /*@
     378             :    SVDPRIMMEGetMethod - Gets the method for the PRIMME SVD solver.
     379             : 
     380             :    Not Collective
     381             : 
     382             :    Input Parameter:
     383             : .  svd - the singular value solver context
     384             : 
     385             :    Output Parameter:
     386             : .  method - method that will be used by PRIMME
     387             : 
     388             :    Level: advanced
     389             : 
     390             : .seealso: SVDPRIMMESetMethod(), SVDPRIMMEMethod
     391             : @*/
     392           1 : PetscErrorCode SVDPRIMMEGetMethod(SVD svd,SVDPRIMMEMethod *method)
     393             : {
     394             :   PetscErrorCode ierr;
     395             : 
     396           1 :   PetscFunctionBegin;
     397           1 :   PetscValidHeaderSpecific(svd,SVD_CLASSID,1);
     398           1 :   PetscValidPointer(method,2);
     399           1 :   ierr = PetscUseMethod(svd,"SVDPRIMMEGetMethod_C",(SVD,SVDPRIMMEMethod*),(svd,method));CHKERRQ(ierr);
     400           2 :   PetscFunctionReturn(0);
     401             : }
     402             : 
     403           5 : SLEPC_EXTERN PetscErrorCode SVDCreate_PRIMME(SVD svd)
     404             : {
     405             :   PetscErrorCode ierr;
     406             :   SVD_PRIMME     *primme;
     407             : 
     408           5 :   PetscFunctionBegin;
     409           5 :   ierr = PetscNewLog(svd,&primme);CHKERRQ(ierr);
     410           5 :   svd->data = (void*)primme;
     411             : 
     412           5 :   primme_svds_initialize(&primme->primme);
     413           5 :   primme->primme.matrixMatvec = multMatvec_PRIMME;
     414           5 :   primme->primme.globalSumReal = par_GlobalSumReal;
     415           5 :   primme->method = (primme_svds_preset_method)SVD_PRIMME_HYBRID;
     416           5 :   primme->svd = svd;
     417             : 
     418           5 :   svd->ops->solve          = SVDSolve_PRIMME;
     419           5 :   svd->ops->setup          = SVDSetUp_PRIMME;
     420           5 :   svd->ops->setfromoptions = SVDSetFromOptions_PRIMME;
     421           5 :   svd->ops->destroy        = SVDDestroy_PRIMME;
     422           5 :   svd->ops->reset          = SVDReset_PRIMME;
     423           5 :   svd->ops->view           = SVDView_PRIMME;
     424             : 
     425           5 :   ierr = PetscObjectComposeFunction((PetscObject)svd,"SVDPRIMMESetBlockSize_C",SVDPRIMMESetBlockSize_PRIMME);CHKERRQ(ierr);
     426           5 :   ierr = PetscObjectComposeFunction((PetscObject)svd,"SVDPRIMMEGetBlockSize_C",SVDPRIMMEGetBlockSize_PRIMME);CHKERRQ(ierr);
     427           5 :   ierr = PetscObjectComposeFunction((PetscObject)svd,"SVDPRIMMESetMethod_C",SVDPRIMMESetMethod_PRIMME);CHKERRQ(ierr);
     428           5 :   ierr = PetscObjectComposeFunction((PetscObject)svd,"SVDPRIMMEGetMethod_C",SVDPRIMMEGetMethod_PRIMME);CHKERRQ(ierr);
     429           5 :   PetscFunctionReturn(0);
     430             : }
     431             : 

Generated by: LCOV version 1.13