Date: 2021-09-20T09:44:01+00:00

Actual source code: cyclic.c
slepc-3.15.2 2021-09-20
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-2021, Universitat Politecnica de Valencia, Spain

      6:    This file is part of SLEPc.
      7:    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
      8:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      9: */
     10: /*
     11:    SLEPc singular value solver: "cyclic"

     13:    Method: Uses a Hermitian eigensolver for H(A) = [ 0  A ; A^T 0 ]
     14: */

     16: #include <slepc/private/svdimpl.h>
     17: #include <slepc/private/epsimpl.h>
     18: #include "cyclic.h"

     20: static PetscErrorCode MatMult_Cyclic(Mat B,Vec x,Vec y)
     21: {
     22:   PetscErrorCode    ierr;
     23:   SVD               svd;
     24:   SVD_CYCLIC        *cyclic;
     25:   const PetscScalar *px;
     26:   PetscScalar       *py;
     27:   PetscInt          m;

     30:   MatShellGetContext(B,(void**)&svd);
     31:   cyclic = (SVD_CYCLIC*)svd->data;
     32:   MatGetLocalSize(svd->A,&m,NULL);
     33:   VecGetArrayRead(x,&px);
     34:   VecGetArray(y,&py);
     35:   VecPlaceArray(cyclic->x1,px);
     36:   VecPlaceArray(cyclic->x2,px+m);
     37:   VecPlaceArray(cyclic->y1,py);
     38:   VecPlaceArray(cyclic->y2,py+m);
     39:   MatMult(svd->A,cyclic->x2,cyclic->y1);
     40:   MatMult(svd->AT,cyclic->x1,cyclic->y2);
     41:   VecResetArray(cyclic->x1);
     42:   VecResetArray(cyclic->x2);
     43:   VecResetArray(cyclic->y1);
     44:   VecResetArray(cyclic->y2);
     45:   VecRestoreArrayRead(x,&px);
     46:   VecRestoreArray(y,&py);
     47:   return(0);
     48: }

     50: static PetscErrorCode MatGetDiagonal_Cyclic(Mat B,Vec diag)
     51: {

     55:   VecSet(diag,0.0);
     56:   return(0);
     57: }

     59: PetscErrorCode SVDSetUp_Cyclic(SVD svd)
     60: {
     61:   PetscErrorCode    ierr;
     62:   SVD_CYCLIC        *cyclic = (SVD_CYCLIC*)svd->data;
     63:   PetscInt          M,N,m,n,i,isl,Istart,Iend;
     64:   const PetscScalar *isa;
     65:   PetscScalar       *va;
     66:   PetscBool         trackall,issinv;
     67:   Vec               v;
     68:   Mat               Zm,Zn;
     69:   ST                st;
     70: #if defined(PETSC_HAVE_CUDA)
     71:   PetscBool         cuda;
     72: #endif

     75:   SVDCheckStandard(svd);
     76:   MatGetSize(svd->A,&M,&N);
     77:   MatGetLocalSize(svd->A,&m,&n);
     78:   MatDestroy(&cyclic->mat);
     79:   if (cyclic->explicitmatrix) {
     80:     if (!svd->expltrans) SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_SUP,"Cannot use explicit cyclic matrix with implicit transpose");
     81:     MatCreate(PetscObjectComm((PetscObject)svd),&Zm);
     82:     MatSetSizes(Zm,m,m,M,M);
     83:     MatSetFromOptions(Zm);
     84:     MatSetUp(Zm);
     85:     MatGetOwnershipRange(Zm,&Istart,&Iend);
     86:     for (i=Istart;i<Iend;i++) {
     87:       MatSetValue(Zm,i,i,0.0,INSERT_VALUES);
     88:     }
     89:     MatAssemblyBegin(Zm,MAT_FINAL_ASSEMBLY);
     90:     MatAssemblyEnd(Zm,MAT_FINAL_ASSEMBLY);
     91:     MatCreate(PetscObjectComm((PetscObject)svd),&Zn);
     92:     MatSetSizes(Zn,n,n,N,N);
     93:     MatSetFromOptions(Zn);
     94:     MatSetUp(Zn);
     95:     MatGetOwnershipRange(Zn,&Istart,&Iend);
     96:     for (i=Istart;i<Iend;i++) {
     97:       MatSetValue(Zn,i,i,0.0,INSERT_VALUES);
     98:     }
     99:     MatAssemblyBegin(Zn,MAT_FINAL_ASSEMBLY);
    100:     MatAssemblyEnd(Zn,MAT_FINAL_ASSEMBLY);
    101:     MatCreateTile(1.0,Zm,1.0,svd->A,1.0,svd->AT,1.0,Zn,&cyclic->mat);
    102:     PetscLogObjectParent((PetscObject)svd,(PetscObject)cyclic->mat);
    103:     MatDestroy(&Zm);
    104:     MatDestroy(&Zn);
    105:   } else {
    106:     VecDestroy(&cyclic->x1);
    107:     VecDestroy(&cyclic->x2);
    108:     VecDestroy(&cyclic->y1);
    109:     VecDestroy(&cyclic->y2);
    110:     MatCreateVecsEmpty(svd->A,&cyclic->x2,&cyclic->x1);
    111:     MatCreateVecsEmpty(svd->A,&cyclic->y2,&cyclic->y1);
    112:     PetscLogObjectParent((PetscObject)svd,(PetscObject)cyclic->x1);
    113:     PetscLogObjectParent((PetscObject)svd,(PetscObject)cyclic->x2);
    114:     PetscLogObjectParent((PetscObject)svd,(PetscObject)cyclic->y1);
    115:     PetscLogObjectParent((PetscObject)svd,(PetscObject)cyclic->y2);
    116:     MatCreateShell(PetscObjectComm((PetscObject)svd),m+n,m+n,M+N,M+N,svd,&cyclic->mat);
    117:     MatShellSetOperation(cyclic->mat,MATOP_GET_DIAGONAL,(void(*)(void))MatGetDiagonal_Cyclic);
    118: #if defined(PETSC_HAVE_CUDA)
    119:     PetscObjectTypeCompareAny((PetscObject)(svd->A?svd->A:svd->AT),&cuda,MATSEQAIJCUSPARSE,MATMPIAIJCUSPARSE,"");
    120:     if (cuda) {
    121:       MatShellSetVecType(cyclic->mat,VECCUDA);
    122:       MatShellSetOperation(cyclic->mat,MATOP_MULT,(void(*)(void))MatMult_Cyclic_CUDA);
    123:     } else
    124: #endif
    125:     {
    126:       MatShellSetOperation(cyclic->mat,MATOP_MULT,(void(*)(void))MatMult_Cyclic);
    127:     }
    128:   }
    129:   PetscLogObjectParent((PetscObject)svd,(PetscObject)cyclic->mat);

    131:   if (!cyclic->eps) { SVDCyclicGetEPS(svd,&cyclic->eps); }
    132:   EPSSetOperators(cyclic->eps,cyclic->mat,NULL);
    133:   EPSSetProblemType(cyclic->eps,EPS_HEP);
    134:   if (!cyclic->usereps) {
    135:     if (svd->which == SVD_LARGEST) {
    136:       EPSGetST(cyclic->eps,&st);
    137:       PetscObjectTypeCompare((PetscObject)st,STSINVERT,&issinv);
    138:       if (issinv) {
    139:         EPSSetWhichEigenpairs(cyclic->eps,EPS_TARGET_MAGNITUDE);
    140:       } else {
    141:         EPSSetWhichEigenpairs(cyclic->eps,EPS_LARGEST_REAL);
    142:       }
    143:     } else {
    144:       EPSSetEigenvalueComparison(cyclic->eps,SlepcCompareSmallestPosReal,NULL);
    145:       EPSSetTarget(cyclic->eps,0.0);
    146:     }
    147:     EPSSetDimensions(cyclic->eps,svd->nsv,svd->ncv,svd->mpd);
    148:     EPSSetTolerances(cyclic->eps,svd->tol==PETSC_DEFAULT?SLEPC_DEFAULT_TOL/10.0:svd->tol,svd->max_it);
    149:     switch (svd->conv) {
    150:     case SVD_CONV_ABS:
    151:       EPSSetConvergenceTest(cyclic->eps,EPS_CONV_ABS);break;
    152:     case SVD_CONV_REL:
    153:       EPSSetConvergenceTest(cyclic->eps,EPS_CONV_REL);break;
    154:     case SVD_CONV_MAXIT:
    155:       SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_SUP,"Maxit convergence test not supported in this solver");
    156:     case SVD_CONV_USER:
    157:       SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_SUP,"User-defined convergence test not supported in this solver");
    158:     }
    159:   }
    160:   SVDCheckUnsupported(svd,SVD_FEATURE_STOPPING);
    161:   /* Transfer the trackall option from svd to eps */
    162:   SVDGetTrackAll(svd,&trackall);
    163:   EPSSetTrackAll(cyclic->eps,trackall);
    164:   /* Transfer the initial subspace from svd to eps */
    165:   if (svd->nini<0 || svd->ninil<0) {
    166:     for (i=0;i<-PetscMin(svd->nini,svd->ninil);i++) {
    167:       MatCreateVecs(cyclic->mat,&v,NULL);
    168:       VecGetArray(v,&va);
    169:       if (i<-svd->ninil) {
    170:         VecGetSize(svd->ISL[i],&isl);
    171:         if (isl!=m) SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_SUP,"Size mismatch for left initial vector");
    172:         VecGetArrayRead(svd->ISL[i],&isa);
    173:         PetscArraycpy(va,isa,m);
    174:         VecRestoreArrayRead(svd->IS[i],&isa);
    175:       } else {
    176:         PetscArrayzero(&va,m);
    177:       }
    178:       if (i<-svd->nini) {
    179:         VecGetSize(svd->IS[i],&isl);
    180:         if (isl!=n) SETERRQ(PetscObjectComm((PetscObject)svd),PETSC_ERR_SUP,"Size mismatch for right initial vector");
    181:         VecGetArrayRead(svd->IS[i],&isa);
    182:         PetscArraycpy(va+m,isa,n);
    183:         VecRestoreArrayRead(svd->IS[i],&isa);
    184:       } else {
    185:         PetscArrayzero(va+m,n);
    186:       }
    187:       VecRestoreArray(v,&va);
    188:       VecDestroy(&svd->IS[i]);
    189:       svd->IS[i] = v;
    190:     }
    191:     svd->nini = PetscMin(svd->nini,svd->ninil);
    192:     EPSSetInitialSpace(cyclic->eps,-svd->nini,svd->IS);
    193:     SlepcBasisDestroy_Private(&svd->nini,&svd->IS);
    194:     SlepcBasisDestroy_Private(&svd->ninil,&svd->ISL);
    195:   }
    196:   EPSSetUp(cyclic->eps);
    197:   EPSGetDimensions(cyclic->eps,NULL,&svd->ncv,&svd->mpd);
    198:   svd->ncv = PetscMin(svd->ncv,PetscMin(M,N));
    199:   EPSGetTolerances(cyclic->eps,NULL,&svd->max_it);
    200:   if (svd->tol==PETSC_DEFAULT) svd->tol = SLEPC_DEFAULT_TOL;

    202:   svd->leftbasis = PETSC_TRUE;
    203:   SVDAllocateSolution(svd,0);
    204:   return(0);
    205: }

    207: PetscErrorCode SVDSolve_Cyclic(SVD svd)
    208: {
    210:   SVD_CYCLIC     *cyclic = (SVD_CYCLIC*)svd->data;
    211:   PetscInt       i,j,nconv;
    212:   PetscScalar    sigma;

    215:   EPSSolve(cyclic->eps);
    216:   EPSGetConverged(cyclic->eps,&nconv);
    217:   EPSGetIterationNumber(cyclic->eps,&svd->its);
    218:   EPSGetConvergedReason(cyclic->eps,(EPSConvergedReason*)&svd->reason);
    219:   for (i=0,j=0;i<nconv;i++) {
    220:     EPSGetEigenvalue(cyclic->eps,i,&sigma,NULL);
    221:     if (PetscRealPart(sigma) > 0.0) {
    222:       svd->sigma[j] = PetscRealPart(sigma);
    223:       j++;
    224:     }
    225:   }
    226:   svd->nconv = j;
    227:   return(0);
    228: }

    230: PetscErrorCode SVDComputeVectors_Cyclic(SVD svd)
    231: {
    232:   PetscErrorCode    ierr;
    233:   SVD_CYCLIC        *cyclic = (SVD_CYCLIC*)svd->data;
    234:   PetscInt          i,j,M,N,m,n,nconv;
    235:   PetscScalar       sigma;
    236:   const PetscScalar *px;
    237:   Vec               x,x1,x2;

    240:   EPSGetConverged(cyclic->eps,&nconv);
    241:   MatCreateVecs(cyclic->mat,&x,NULL);
    242:   MatGetSize(svd->A,&M,&N);
    243:   MatGetLocalSize(svd->A,&m,&n);
    244:   MatCreateVecsEmpty(svd->A,&x2,&x1);
    245:   for (i=0,j=0;i<nconv;i++) {
    246:     EPSGetEigenpair(cyclic->eps,i,&sigma,NULL,x,NULL);
    247:     if (PetscRealPart(sigma) > 0.0) {
    248:       VecGetArrayRead(x,&px);
    249:       VecPlaceArray(x1,px);
    250:       VecPlaceArray(x2,px+m);
    251:       BVInsertVec(svd->U,j,x1);
    252:       BVScaleColumn(svd->U,j,PETSC_SQRT2);
    253:       BVInsertVec(svd->V,j,x2);
    254:       BVScaleColumn(svd->V,j,PETSC_SQRT2);
    255:       VecResetArray(x1);
    256:       VecResetArray(x2);
    257:       VecRestoreArrayRead(x,&px);
    258:       j++;
    259:     }
    260:   }
    261:   VecDestroy(&x);
    262:   VecDestroy(&x1);
    263:   VecDestroy(&x2);
    264:   return(0);
    265: }

    267: static PetscErrorCode EPSMonitor_Cyclic(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *ctx)
    268: {
    269:   PetscInt       i,j;
    270:   SVD            svd = (SVD)ctx;
    271:   PetscScalar    er,ei;

    275:   nconv = 0;
    276:   for (i=0,j=0;i<PetscMin(nest,svd->ncv);i++) {
    277:     er = eigr[i]; ei = eigi[i];
    278:     STBackTransform(eps->st,1,&er,&ei);
    279:     if (PetscRealPart(er) > 0.0) {
    280:       svd->sigma[j] = PetscRealPart(er);
    281:       svd->errest[j] = errest[i];
    282:       if (errest[i] && errest[i] < svd->tol) nconv++;
    283:       j++;
    284:     }
    285:   }
    286:   nest = j;
    287:   SVDMonitor(svd,its,nconv,svd->sigma,svd->errest,nest);
    288:   return(0);
    289: }

    291: PetscErrorCode SVDSetFromOptions_Cyclic(PetscOptionItems *PetscOptionsObject,SVD svd)
    292: {
    294:   PetscBool      set,val;
    295:   SVD_CYCLIC     *cyclic = (SVD_CYCLIC*)svd->data;
    296:   ST             st;

    299:   PetscOptionsHead(PetscOptionsObject,"SVD Cyclic Options");

    301:     PetscOptionsBool("-svd_cyclic_explicitmatrix","Use cyclic explicit matrix","SVDCyclicSetExplicitMatrix",cyclic->explicitmatrix,&val,&set);
    302:     if (set) { SVDCyclicSetExplicitMatrix(svd,val); }

    304:   PetscOptionsTail();

    306:   if (!cyclic->eps) { SVDCyclicGetEPS(svd,&cyclic->eps); }
    307:   if (!cyclic->explicitmatrix && !cyclic->usereps) {
    308:     /* use as default an ST with shell matrix and Jacobi */
    309:     EPSGetST(cyclic->eps,&st);
    310:     STSetMatMode(st,ST_MATMODE_SHELL);
    311:   }
    312:   EPSSetFromOptions(cyclic->eps);
    313:   return(0);
    314: }

    316: static PetscErrorCode SVDCyclicSetExplicitMatrix_Cyclic(SVD svd,PetscBool explicitmatrix)
    317: {
    318:   SVD_CYCLIC *cyclic = (SVD_CYCLIC*)svd->data;

    321:   if (cyclic->explicitmatrix != explicitmatrix) {
    322:     cyclic->explicitmatrix = explicitmatrix;
    323:     svd->state = SVD_STATE_INITIAL;
    324:   }
    325:   return(0);
    326: }

    328: /*@
    329:    SVDCyclicSetExplicitMatrix - Indicate if the eigensolver operator
    330:    H(A) = [ 0  A ; A^T 0 ] must be computed explicitly.

    332:    Logically Collective on svd

    334:    Input Parameters:
    335: +  svd      - singular value solver
    336: -  explicit - boolean flag indicating if H(A) is built explicitly

    338:    Options Database Key:
    339: .  -svd_cyclic_explicitmatrix <boolean> - Indicates the boolean flag

    341:    Level: advanced

    343: .seealso: SVDCyclicGetExplicitMatrix()
    344: @*/
    345: PetscErrorCode SVDCyclicSetExplicitMatrix(SVD svd,PetscBool explicitmatrix)
    346: {

    352:   PetscTryMethod(svd,"SVDCyclicSetExplicitMatrix_C",(SVD,PetscBool),(svd,explicitmatrix));
    353:   return(0);
    354: }

    356: static PetscErrorCode SVDCyclicGetExplicitMatrix_Cyclic(SVD svd,PetscBool *explicitmatrix)
    357: {
    358:   SVD_CYCLIC *cyclic = (SVD_CYCLIC*)svd->data;

    361:   *explicitmatrix = cyclic->explicitmatrix;
    362:   return(0);
    363: }

    365: /*@
    366:    SVDCyclicGetExplicitMatrix - Returns the flag indicating if H(A) is built explicitly.

    368:    Not Collective

    370:    Input Parameter:
    371: .  svd  - singular value solver

    373:    Output Parameter:
    374: .  explicit - the mode flag

    376:    Level: advanced

    378: .seealso: SVDCyclicSetExplicitMatrix()
    379: @*/
    380: PetscErrorCode SVDCyclicGetExplicitMatrix(SVD svd,PetscBool *explicitmatrix)
    381: {

    387:   PetscUseMethod(svd,"SVDCyclicGetExplicitMatrix_C",(SVD,PetscBool*),(svd,explicitmatrix));
    388:   return(0);
    389: }

    391: static PetscErrorCode SVDCyclicSetEPS_Cyclic(SVD svd,EPS eps)
    392: {
    393:   PetscErrorCode  ierr;
    394:   SVD_CYCLIC      *cyclic = (SVD_CYCLIC*)svd->data;

    397:   PetscObjectReference((PetscObject)eps);
    398:   EPSDestroy(&cyclic->eps);
    399:   cyclic->eps = eps;
    400:   cyclic->usereps = PETSC_TRUE;
    401:   PetscLogObjectParent((PetscObject)svd,(PetscObject)cyclic->eps);
    402:   svd->state = SVD_STATE_INITIAL;
    403:   return(0);
    404: }

    406: /*@
    407:    SVDCyclicSetEPS - Associate an eigensolver object (EPS) to the
    408:    singular value solver.

    410:    Collective on svd

    412:    Input Parameters:
    413: +  svd - singular value solver
    414: -  eps - the eigensolver object

    416:    Level: advanced

    418: .seealso: SVDCyclicGetEPS()
    419: @*/
    420: PetscErrorCode SVDCyclicSetEPS(SVD svd,EPS eps)
    421: {

    428:   PetscTryMethod(svd,"SVDCyclicSetEPS_C",(SVD,EPS),(svd,eps));
    429:   return(0);
    430: }

    432: static PetscErrorCode SVDCyclicGetEPS_Cyclic(SVD svd,EPS *eps)
    433: {
    435:   SVD_CYCLIC     *cyclic = (SVD_CYCLIC*)svd->data;

    438:   if (!cyclic->eps) {
    439:     EPSCreate(PetscObjectComm((PetscObject)svd),&cyclic->eps);
    440:     PetscObjectIncrementTabLevel((PetscObject)cyclic->eps,(PetscObject)svd,1);
    441:     EPSSetOptionsPrefix(cyclic->eps,((PetscObject)svd)->prefix);
    442:     EPSAppendOptionsPrefix(cyclic->eps,"svd_cyclic_");
    443:     PetscLogObjectParent((PetscObject)svd,(PetscObject)cyclic->eps);
    444:     PetscObjectSetOptions((PetscObject)cyclic->eps,((PetscObject)svd)->options);
    445:     EPSSetWhichEigenpairs(cyclic->eps,EPS_LARGEST_REAL);
    446:     EPSMonitorSet(cyclic->eps,EPSMonitor_Cyclic,svd,NULL);
    447:   }
    448:   *eps = cyclic->eps;
    449:   return(0);
    450: }

    452: /*@
    453:    SVDCyclicGetEPS - Retrieve the eigensolver object (EPS) associated
    454:    to the singular value solver.

    456:    Not Collective

    458:    Input Parameter:
    459: .  svd - singular value solver

    461:    Output Parameter:
    462: .  eps - the eigensolver object

    464:    Level: advanced

    466: .seealso: SVDCyclicSetEPS()
    467: @*/
    468: PetscErrorCode SVDCyclicGetEPS(SVD svd,EPS *eps)
    469: {

    475:   PetscUseMethod(svd,"SVDCyclicGetEPS_C",(SVD,EPS*),(svd,eps));
    476:   return(0);
    477: }

    479: PetscErrorCode SVDView_Cyclic(SVD svd,PetscViewer viewer)
    480: {
    482:   SVD_CYCLIC     *cyclic = (SVD_CYCLIC*)svd->data;
    483:   PetscBool      isascii;

    486:   PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
    487:   if (isascii) {
    488:     if (!cyclic->eps) { SVDCyclicGetEPS(svd,&cyclic->eps); }
    489:     PetscViewerASCIIPrintf(viewer,"  %s matrix\n",cyclic->explicitmatrix?"explicit":"implicit");
    490:     PetscViewerASCIIPushTab(viewer);
    491:     EPSView(cyclic->eps,viewer);
    492:     PetscViewerASCIIPopTab(viewer);
    493:   }
    494:   return(0);
    495: }

    497: PetscErrorCode SVDReset_Cyclic(SVD svd)
    498: {
    500:   SVD_CYCLIC     *cyclic = (SVD_CYCLIC*)svd->data;

    503:   EPSReset(cyclic->eps);
    504:   MatDestroy(&cyclic->mat);
    505:   VecDestroy(&cyclic->x1);
    506:   VecDestroy(&cyclic->x2);
    507:   VecDestroy(&cyclic->y1);
    508:   VecDestroy(&cyclic->y2);
    509:   return(0);
    510: }

    512: PetscErrorCode SVDDestroy_Cyclic(SVD svd)
    513: {
    515:   SVD_CYCLIC     *cyclic = (SVD_CYCLIC*)svd->data;

    518:   EPSDestroy(&cyclic->eps);
    519:   PetscFree(svd->data);
    520:   PetscObjectComposeFunction((PetscObject)svd,"SVDCyclicSetEPS_C",NULL);
    521:   PetscObjectComposeFunction((PetscObject)svd,"SVDCyclicGetEPS_C",NULL);
    522:   PetscObjectComposeFunction((PetscObject)svd,"SVDCyclicSetExplicitMatrix_C",NULL);
    523:   PetscObjectComposeFunction((PetscObject)svd,"SVDCyclicGetExplicitMatrix_C",NULL);
    524:   return(0);
    525: }

    527: SLEPC_EXTERN PetscErrorCode SVDCreate_Cyclic(SVD svd)
    528: {
    530:   SVD_CYCLIC     *cyclic;

    533:   PetscNewLog(svd,&cyclic);
    534:   svd->data                = (void*)cyclic;
    535:   svd->ops->solve          = SVDSolve_Cyclic;
    536:   svd->ops->setup          = SVDSetUp_Cyclic;
    537:   svd->ops->setfromoptions = SVDSetFromOptions_Cyclic;
    538:   svd->ops->destroy        = SVDDestroy_Cyclic;
    539:   svd->ops->reset          = SVDReset_Cyclic;
    540:   svd->ops->view           = SVDView_Cyclic;
    541:   svd->ops->computevectors = SVDComputeVectors_Cyclic;
    542:   PetscObjectComposeFunction((PetscObject)svd,"SVDCyclicSetEPS_C",SVDCyclicSetEPS_Cyclic);
    543:   PetscObjectComposeFunction((PetscObject)svd,"SVDCyclicGetEPS_C",SVDCyclicGetEPS_Cyclic);
    544:   PetscObjectComposeFunction((PetscObject)svd,"SVDCyclicSetExplicitMatrix_C",SVDCyclicSetExplicitMatrix_Cyclic);
    545:   PetscObjectComposeFunction((PetscObject)svd,"SVDCyclicGetExplicitMatrix_C",SVDCyclicGetExplicitMatrix_Cyclic);
    546:   return(0);
    547: }