Subversion Repositories slepc-dev

Rev

Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2520 Rev 2575
/*                      
/*                      
 
 
   SLEPc singular value solver: "cross"
   SLEPc singular value solver: "cross"
 
 
   Method: Uses a Hermitian eigensolver for A^T*A
   Method: Uses a Hermitian eigensolver for A^T*A
 
 
   Last update: Jun 2007
   Last update: Jun 2007
 
 
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   SLEPc - Scalable Library for Eigenvalue Problem Computations
   SLEPc - Scalable Library for Eigenvalue Problem Computations
   Copyright (c) 2002-2010, Universidad Politecnica de Valencia, Spain
   Copyright (c) 2002-2011, Universitat Politecnica de Valencia, Spain
 
 
   This file is part of SLEPc.
   This file is part of SLEPc.
     
     
   SLEPc is free software: you can redistribute it and/or modify it under  the
   SLEPc is free software: you can redistribute it and/or modify it under  the
   terms of version 3 of the GNU Lesser General Public License as published by
   terms of version 3 of the GNU Lesser General Public License as published by
   the Free Software Foundation.
   the Free Software Foundation.
 
 
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
   more details.
   more details.
 
 
   You  should have received a copy of the GNU Lesser General  Public  License
   You  should have received a copy of the GNU Lesser General  Public  License
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
*/
 
 
#include <private/svdimpl.h>                /*I "slepcsvd.h" I*/
#include <private/svdimpl.h>                /*I "slepcsvd.h" I*/
#include <private/epsimpl.h>                /*I "slepceps.h" I*/
#include <private/epsimpl.h>                /*I "slepceps.h" I*/
 
 
typedef struct {
typedef struct {
  EPS       eps;
  EPS       eps;
  PetscBool setfromoptionscalled;
  PetscBool setfromoptionscalled;
  Mat       mat;
  Mat       mat;
  Vec       w,diag;
  Vec       w,diag;
} SVD_CROSS;
} SVD_CROSS;
 
 
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "ShellMatMult_Cross"
#define __FUNCT__ "ShellMatMult_Cross"
PetscErrorCode ShellMatMult_Cross(Mat B,Vec x,Vec y)
PetscErrorCode ShellMatMult_Cross(Mat B,Vec x,Vec y)
{
{
  PetscErrorCode ierr;
  PetscErrorCode ierr;
  SVD            svd;
  SVD            svd;
  SVD_CROSS      *cross;
  SVD_CROSS      *cross;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  ierr = MatShellGetContext(B,(void**)&svd);CHKERRQ(ierr);
  ierr = MatShellGetContext(B,(void**)&svd);CHKERRQ(ierr);
  cross = (SVD_CROSS*)svd->data;
  cross = (SVD_CROSS*)svd->data;
  ierr = SVDMatMult(svd,PETSC_FALSE,x,cross->w);CHKERRQ(ierr);
  ierr = SVDMatMult(svd,PETSC_FALSE,x,cross->w);CHKERRQ(ierr);
  ierr = SVDMatMult(svd,PETSC_TRUE,cross->w,y);CHKERRQ(ierr);
  ierr = SVDMatMult(svd,PETSC_TRUE,cross->w,y);CHKERRQ(ierr);
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
 
 
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "ShellMatGetDiagonal_Cross"
#define __FUNCT__ "ShellMatGetDiagonal_Cross"
PetscErrorCode ShellMatGetDiagonal_Cross(Mat B,Vec d)
PetscErrorCode ShellMatGetDiagonal_Cross(Mat B,Vec d)
{
{
  PetscErrorCode    ierr;
  PetscErrorCode    ierr;
  SVD               svd;
  SVD               svd;
  SVD_CROSS         *cross;
  SVD_CROSS         *cross;
  PetscInt          N,n,i,j,start,end,ncols;
  PetscInt          N,n,i,j,start,end,ncols;
  PetscScalar       *work1,*work2,*diag;
  PetscScalar       *work1,*work2,*diag;
  const PetscInt    *cols;
  const PetscInt    *cols;
  const PetscScalar *vals;
  const PetscScalar *vals;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  ierr = MatShellGetContext(B,(void**)&svd);CHKERRQ(ierr);
  ierr = MatShellGetContext(B,(void**)&svd);CHKERRQ(ierr);
  cross = (SVD_CROSS*)svd->data;
  cross = (SVD_CROSS*)svd->data;
  if (!cross->diag) {
  if (!cross->diag) {
    /* compute diagonal from rows and store in cross->diag */
    /* compute diagonal from rows and store in cross->diag */
    ierr = VecDuplicate(d,&cross->diag);CHKERRQ(ierr);
    ierr = VecDuplicate(d,&cross->diag);CHKERRQ(ierr);
    ierr = SVDMatGetSize(svd,PETSC_NULL,&N);CHKERRQ(ierr);
    ierr = SVDMatGetSize(svd,PETSC_NULL,&N);CHKERRQ(ierr);
    ierr = SVDMatGetLocalSize(svd,PETSC_NULL,&n);CHKERRQ(ierr);
    ierr = SVDMatGetLocalSize(svd,PETSC_NULL,&n);CHKERRQ(ierr);
    ierr = PetscMalloc(sizeof(PetscScalar)*N,&work1);CHKERRQ(ierr);
    ierr = PetscMalloc(sizeof(PetscScalar)*N,&work1);CHKERRQ(ierr);
    ierr = PetscMalloc(sizeof(PetscScalar)*N,&work2);CHKERRQ(ierr);
    ierr = PetscMalloc(sizeof(PetscScalar)*N,&work2);CHKERRQ(ierr);
    for (i=0;i<n;i++) work1[i] = work2[i] = 0.0;
    for (i=0;i<n;i++) work1[i] = work2[i] = 0.0;
    if (svd->AT) {
    if (svd->AT) {
      ierr = MatGetOwnershipRange(svd->AT,&start,&end);CHKERRQ(ierr);
      ierr = MatGetOwnershipRange(svd->AT,&start,&end);CHKERRQ(ierr);
      for (i=start;i<end;i++) {
      for (i=start;i<end;i++) {
        ierr = MatGetRow(svd->AT,i,&ncols,PETSC_NULL,&vals);CHKERRQ(ierr);
        ierr = MatGetRow(svd->AT,i,&ncols,PETSC_NULL,&vals);CHKERRQ(ierr);
        for (j=0;j<ncols;j++)
        for (j=0;j<ncols;j++)
          work1[i] += vals[j]*vals[j];
          work1[i] += vals[j]*vals[j];
        ierr = MatRestoreRow(svd->AT,i,&ncols,PETSC_NULL,&vals);CHKERRQ(ierr);
        ierr = MatRestoreRow(svd->AT,i,&ncols,PETSC_NULL,&vals);CHKERRQ(ierr);
      }
      }
    } else {
    } else {
      ierr = MatGetOwnershipRange(svd->A,&start,&end);CHKERRQ(ierr);
      ierr = MatGetOwnershipRange(svd->A,&start,&end);CHKERRQ(ierr);
      for (i=start;i<end;i++) {
      for (i=start;i<end;i++) {
        ierr = MatGetRow(svd->A,i,&ncols,&cols,&vals);CHKERRQ(ierr);
        ierr = MatGetRow(svd->A,i,&ncols,&cols,&vals);CHKERRQ(ierr);
        for (j=0;j<ncols;j++)
        for (j=0;j<ncols;j++)
          work1[cols[j]] += vals[j]*vals[j];
          work1[cols[j]] += vals[j]*vals[j];
        ierr = MatRestoreRow(svd->A,i,&ncols,&cols,&vals);CHKERRQ(ierr);
        ierr = MatRestoreRow(svd->A,i,&ncols,&cols,&vals);CHKERRQ(ierr);
      }
      }
    }
    }
    ierr = MPI_Allreduce(work1,work2,N,MPIU_SCALAR,MPI_SUM,((PetscObject)svd)->comm);CHKERRQ(ierr);
    ierr = MPI_Allreduce(work1,work2,N,MPIU_SCALAR,MPI_SUM,((PetscObject)svd)->comm);CHKERRQ(ierr);
    ierr = VecGetOwnershipRange(cross->diag,&start,&end);CHKERRQ(ierr);
    ierr = VecGetOwnershipRange(cross->diag,&start,&end);CHKERRQ(ierr);
    ierr = VecGetArray(cross->diag,&diag);CHKERRQ(ierr);
    ierr = VecGetArray(cross->diag,&diag);CHKERRQ(ierr);
    for (i=start;i<end;i++)
    for (i=start;i<end;i++)
      diag[i-start] = work2[i];
      diag[i-start] = work2[i];
    ierr = VecRestoreArray(cross->diag,&diag);CHKERRQ(ierr);
    ierr = VecRestoreArray(cross->diag,&diag);CHKERRQ(ierr);
    ierr = PetscFree(work1);CHKERRQ(ierr);
    ierr = PetscFree(work1);CHKERRQ(ierr);
    ierr = PetscFree(work2);CHKERRQ(ierr);
    ierr = PetscFree(work2);CHKERRQ(ierr);
  }
  }
  ierr = VecCopy(cross->diag,d);CHKERRQ(ierr);
  ierr = VecCopy(cross->diag,d);CHKERRQ(ierr);
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
 
 
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "SVDSetUp_Cross"
#define __FUNCT__ "SVDSetUp_Cross"
PetscErrorCode SVDSetUp_Cross(SVD svd)
PetscErrorCode SVDSetUp_Cross(SVD svd)
{
{
  PetscErrorCode ierr;
  PetscErrorCode ierr;
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
  PetscInt       n,i;
  PetscInt       n,i;
  PetscBool      trackall;
  PetscBool      trackall;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  if (!cross->mat) {
  if (!cross->mat) {
    ierr = SVDMatGetLocalSize(svd,PETSC_NULL,&n);CHKERRQ(ierr);
    ierr = SVDMatGetLocalSize(svd,PETSC_NULL,&n);CHKERRQ(ierr);
    ierr = MatCreateShell(((PetscObject)svd)->comm,n,n,PETSC_DETERMINE,PETSC_DETERMINE,svd,&cross->mat);CHKERRQ(ierr);
    ierr = MatCreateShell(((PetscObject)svd)->comm,n,n,PETSC_DETERMINE,PETSC_DETERMINE,svd,&cross->mat);CHKERRQ(ierr);
    ierr = MatShellSetOperation(cross->mat,MATOP_MULT,(void(*)(void))ShellMatMult_Cross);CHKERRQ(ierr);  
    ierr = MatShellSetOperation(cross->mat,MATOP_MULT,(void(*)(void))ShellMatMult_Cross);CHKERRQ(ierr);  
    ierr = MatShellSetOperation(cross->mat,MATOP_GET_DIAGONAL,(void(*)(void))ShellMatGetDiagonal_Cross);CHKERRQ(ierr);  
    ierr = MatShellSetOperation(cross->mat,MATOP_GET_DIAGONAL,(void(*)(void))ShellMatGetDiagonal_Cross);CHKERRQ(ierr);  
    ierr = SVDMatGetVecs(svd,PETSC_NULL,&cross->w);CHKERRQ(ierr);
    ierr = SVDMatGetVecs(svd,PETSC_NULL,&cross->w);CHKERRQ(ierr);
  }
  }
 
 
  ierr = EPSSetOperators(cross->eps,cross->mat,PETSC_NULL);CHKERRQ(ierr);
  ierr = EPSSetOperators(cross->eps,cross->mat,PETSC_NULL);CHKERRQ(ierr);
  ierr = EPSSetProblemType(cross->eps,EPS_HEP);CHKERRQ(ierr);
  ierr = EPSSetProblemType(cross->eps,EPS_HEP);CHKERRQ(ierr);
  ierr = EPSSetWhichEigenpairs(cross->eps,svd->which == SVD_LARGEST ? EPS_LARGEST_REAL : EPS_SMALLEST_REAL);CHKERRQ(ierr);
  ierr = EPSSetWhichEigenpairs(cross->eps,svd->which == SVD_LARGEST ? EPS_LARGEST_REAL : EPS_SMALLEST_REAL);CHKERRQ(ierr);
  ierr = EPSSetDimensions(cross->eps,svd->nsv,svd->ncv,svd->mpd);CHKERRQ(ierr);
  ierr = EPSSetDimensions(cross->eps,svd->nsv,svd->ncv,svd->mpd);CHKERRQ(ierr);
  ierr = EPSSetTolerances(cross->eps,svd->tol,svd->max_it);CHKERRQ(ierr);
  ierr = EPSSetTolerances(cross->eps,svd->tol,svd->max_it);CHKERRQ(ierr);
  /* Transfer the trackall option from svd to eps */
  /* Transfer the trackall option from svd to eps */
  ierr = SVDGetTrackAll(svd,&trackall);CHKERRQ(ierr);
  ierr = SVDGetTrackAll(svd,&trackall);CHKERRQ(ierr);
  ierr = EPSSetTrackAll(cross->eps,trackall);CHKERRQ(ierr);
  ierr = EPSSetTrackAll(cross->eps,trackall);CHKERRQ(ierr);
  if (cross->setfromoptionscalled) {
  if (cross->setfromoptionscalled) {
    ierr = EPSSetFromOptions(cross->eps);CHKERRQ(ierr);
    ierr = EPSSetFromOptions(cross->eps);CHKERRQ(ierr);
    cross->setfromoptionscalled = PETSC_FALSE;
    cross->setfromoptionscalled = PETSC_FALSE;
  }
  }
  ierr = EPSSetUp(cross->eps);CHKERRQ(ierr);
  ierr = EPSSetUp(cross->eps);CHKERRQ(ierr);
  ierr = EPSGetDimensions(cross->eps,PETSC_NULL,&svd->ncv,&svd->mpd);CHKERRQ(ierr);
  ierr = EPSGetDimensions(cross->eps,PETSC_NULL,&svd->ncv,&svd->mpd);CHKERRQ(ierr);
  ierr = EPSGetTolerances(cross->eps,&svd->tol,&svd->max_it);CHKERRQ(ierr);
  ierr = EPSGetTolerances(cross->eps,&svd->tol,&svd->max_it);CHKERRQ(ierr);
  /* Transfer the initial space from svd to eps */
  /* Transfer the initial space from svd to eps */
  if (svd->nini < 0) {
  if (svd->nini < 0) {
    ierr = EPSSetInitialSpace(cross->eps,-svd->nini,svd->IS);CHKERRQ(ierr);
    ierr = EPSSetInitialSpace(cross->eps,-svd->nini,svd->IS);CHKERRQ(ierr);
    for(i=0; i<-svd->nini; i++) {
    for(i=0; i<-svd->nini; i++) {
      ierr = VecDestroy(&svd->IS[i]);CHKERRQ(ierr);
      ierr = VecDestroy(&svd->IS[i]);CHKERRQ(ierr);
    }
    }
    ierr = PetscFree(svd->IS);CHKERRQ(ierr);
    ierr = PetscFree(svd->IS);CHKERRQ(ierr);
    svd->nini = 0;
    svd->nini = 0;
  }
  }
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
 
 
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "SVDSolve_Cross"
#define __FUNCT__ "SVDSolve_Cross"
PetscErrorCode SVDSolve_Cross(SVD svd)
PetscErrorCode SVDSolve_Cross(SVD svd)
{
{
  PetscErrorCode ierr;
  PetscErrorCode ierr;
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
  PetscInt       i;
  PetscInt       i;
  PetscScalar    sigma;
  PetscScalar    sigma;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  ierr = EPSSolve(cross->eps);CHKERRQ(ierr);
  ierr = EPSSolve(cross->eps);CHKERRQ(ierr);
  ierr = EPSGetConverged(cross->eps,&svd->nconv);CHKERRQ(ierr);
  ierr = EPSGetConverged(cross->eps,&svd->nconv);CHKERRQ(ierr);
  ierr = EPSGetIterationNumber(cross->eps,&svd->its);CHKERRQ(ierr);
  ierr = EPSGetIterationNumber(cross->eps,&svd->its);CHKERRQ(ierr);
  ierr = EPSGetConvergedReason(cross->eps,(EPSConvergedReason*)&svd->reason);CHKERRQ(ierr);
  ierr = EPSGetConvergedReason(cross->eps,(EPSConvergedReason*)&svd->reason);CHKERRQ(ierr);
  for (i=0;i<svd->nconv;i++) {
  for (i=0;i<svd->nconv;i++) {
    ierr = EPSGetEigenpair(cross->eps,i,&sigma,PETSC_NULL,svd->V[i],PETSC_NULL);CHKERRQ(ierr);
    ierr = EPSGetEigenpair(cross->eps,i,&sigma,PETSC_NULL,svd->V[i],PETSC_NULL);CHKERRQ(ierr);
    if (PetscRealPart(sigma)<0.0) SETERRQ(((PetscObject)svd)->comm,1,"Negative eigenvalue computed by EPS");
    if (PetscRealPart(sigma)<0.0) SETERRQ(((PetscObject)svd)->comm,1,"Negative eigenvalue computed by EPS");
    svd->sigma[i] = PetscSqrtReal(PetscRealPart(sigma));
    svd->sigma[i] = PetscSqrtReal(PetscRealPart(sigma));
  }
  }
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
 
 
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "SVDMonitor_Cross"
#define __FUNCT__ "SVDMonitor_Cross"
static PetscErrorCode SVDMonitor_Cross(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *ctx)
static PetscErrorCode SVDMonitor_Cross(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *ctx)
{
{
  PetscInt       i;
  PetscInt       i;
  SVD            svd = (SVD)ctx;
  SVD            svd = (SVD)ctx;
  PetscScalar    er,ei;
  PetscScalar    er,ei;
  PetscErrorCode ierr;
  PetscErrorCode ierr;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  for (i=0;i<nest;i++) {
  for (i=0;i<nest;i++) {
    er = eigr[i]; ei = eigi[i];
    er = eigr[i]; ei = eigi[i];
    ierr = STBackTransform(eps->OP,1,&er,&ei);CHKERRQ(ierr);
    ierr = STBackTransform(eps->OP,1,&er,&ei);CHKERRQ(ierr);
    svd->sigma[i] = PetscSqrtReal(PetscRealPart(er));
    svd->sigma[i] = PetscSqrtReal(PetscRealPart(er));
    svd->errest[i] = errest[i];
    svd->errest[i] = errest[i];
  }
  }
  ierr = SVDMonitor(svd,its,nconv,svd->sigma,svd->errest,nest);CHKERRQ(ierr);
  ierr = SVDMonitor(svd,its,nconv,svd->sigma,svd->errest,nest);CHKERRQ(ierr);
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
 
 
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "SVDSetFromOptions_Cross"
#define __FUNCT__ "SVDSetFromOptions_Cross"
PetscErrorCode SVDSetFromOptions_Cross(SVD svd)
PetscErrorCode SVDSetFromOptions_Cross(SVD svd)
{
{
  SVD_CROSS *cross = (SVD_CROSS*)svd->data;
  SVD_CROSS *cross = (SVD_CROSS*)svd->data;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  cross->setfromoptionscalled = PETSC_TRUE;
  cross->setfromoptionscalled = PETSC_TRUE;
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
 
 
EXTERN_C_BEGIN
EXTERN_C_BEGIN
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "SVDCrossSetEPS_Cross"
#define __FUNCT__ "SVDCrossSetEPS_Cross"
PetscErrorCode SVDCrossSetEPS_Cross(SVD svd,EPS eps)
PetscErrorCode SVDCrossSetEPS_Cross(SVD svd,EPS eps)
{
{
  PetscErrorCode ierr;
  PetscErrorCode ierr;
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  ierr = PetscObjectReference((PetscObject)eps);CHKERRQ(ierr);
  ierr = PetscObjectReference((PetscObject)eps);CHKERRQ(ierr);
  ierr = EPSDestroy(&cross->eps);CHKERRQ(ierr);  
  ierr = EPSDestroy(&cross->eps);CHKERRQ(ierr);  
  cross->eps = eps;
  cross->eps = eps;
  ierr = PetscLogObjectParent(svd,cross->eps);CHKERRQ(ierr);
  ierr = PetscLogObjectParent(svd,cross->eps);CHKERRQ(ierr);
  svd->setupcalled = 0;
  svd->setupcalled = 0;
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
EXTERN_C_END
EXTERN_C_END
 
 
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "SVDCrossSetEPS"
#define __FUNCT__ "SVDCrossSetEPS"
/*@
/*@
   SVDCrossSetEPS - Associate an eigensolver object (EPS) to the
   SVDCrossSetEPS - Associate an eigensolver object (EPS) to the
   singular value solver.
   singular value solver.
 
 
   Collective on SVD
   Collective on SVD
 
 
   Input Parameters:
   Input Parameters:
+  svd - singular value solver
+  svd - singular value solver
-  eps - the eigensolver object
-  eps - the eigensolver object
 
 
   Level: advanced
   Level: advanced
 
 
.seealso: SVDCrossGetEPS()
.seealso: SVDCrossGetEPS()
@*/
@*/
PetscErrorCode SVDCrossSetEPS(SVD svd,EPS eps)
PetscErrorCode SVDCrossSetEPS(SVD svd,EPS eps)
{
{
  PetscErrorCode ierr;
  PetscErrorCode ierr;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  PetscValidHeaderSpecific(svd,SVD_CLASSID,1);
  PetscValidHeaderSpecific(svd,SVD_CLASSID,1);
  PetscValidHeaderSpecific(eps,EPS_CLASSID,2);
  PetscValidHeaderSpecific(eps,EPS_CLASSID,2);
  PetscCheckSameComm(svd,1,eps,2);
  PetscCheckSameComm(svd,1,eps,2);
  ierr = PetscTryMethod(svd,"SVDCrossSetEPS_C",(SVD,EPS),(svd,eps));CHKERRQ(ierr);
  ierr = PetscTryMethod(svd,"SVDCrossSetEPS_C",(SVD,EPS),(svd,eps));CHKERRQ(ierr);
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
 
 
EXTERN_C_BEGIN
EXTERN_C_BEGIN
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "SVDCrossGetEPS_Cross"
#define __FUNCT__ "SVDCrossGetEPS_Cross"
PetscErrorCode SVDCrossGetEPS_Cross(SVD svd,EPS *eps)
PetscErrorCode SVDCrossGetEPS_Cross(SVD svd,EPS *eps)
{
{
  SVD_CROSS *cross = (SVD_CROSS*)svd->data;
  SVD_CROSS *cross = (SVD_CROSS*)svd->data;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  *eps = cross->eps;
  *eps = cross->eps;
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
EXTERN_C_END
EXTERN_C_END
 
 
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "SVDCrossGetEPS"
#define __FUNCT__ "SVDCrossGetEPS"
/*@
/*@
   SVDCrossGetEPS - Retrieve the eigensolver object (EPS) associated
   SVDCrossGetEPS - Retrieve the eigensolver object (EPS) associated
   to the singular value solver.
   to the singular value solver.
 
 
   Not Collective
   Not Collective
 
 
   Input Parameter:
   Input Parameter:
.  svd - singular value solver
.  svd - singular value solver
 
 
   Output Parameter:
   Output Parameter:
.  eps - the eigensolver object
.  eps - the eigensolver object
 
 
   Level: advanced
   Level: advanced
 
 
.seealso: SVDCrossSetEPS()
.seealso: SVDCrossSetEPS()
@*/
@*/
PetscErrorCode SVDCrossGetEPS(SVD svd,EPS *eps)
PetscErrorCode SVDCrossGetEPS(SVD svd,EPS *eps)
{
{
  PetscErrorCode ierr;
  PetscErrorCode ierr;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  PetscValidHeaderSpecific(svd,SVD_CLASSID,1);
  PetscValidHeaderSpecific(svd,SVD_CLASSID,1);
  PetscValidPointer(eps,2);
  PetscValidPointer(eps,2);
  ierr = PetscTryMethod(svd,"SVDCrossGetEPS_C",(SVD,EPS*),(svd,eps));CHKERRQ(ierr);
  ierr = PetscTryMethod(svd,"SVDCrossGetEPS_C",(SVD,EPS*),(svd,eps));CHKERRQ(ierr);
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
 
 
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "SVDView_Cross"
#define __FUNCT__ "SVDView_Cross"
PetscErrorCode SVDView_Cross(SVD svd,PetscViewer viewer)
PetscErrorCode SVDView_Cross(SVD svd,PetscViewer viewer)
{
{
  PetscErrorCode ierr;
  PetscErrorCode ierr;
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
  ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
  ierr = EPSView(cross->eps,viewer);CHKERRQ(ierr);
  ierr = EPSView(cross->eps,viewer);CHKERRQ(ierr);
  ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
  ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
 
 
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "SVDReset_Cross"
#define __FUNCT__ "SVDReset_Cross"
PetscErrorCode SVDReset_Cross(SVD svd)
PetscErrorCode SVDReset_Cross(SVD svd)
{
{
  PetscErrorCode ierr;
  PetscErrorCode ierr;
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  ierr = EPSReset(cross->eps);CHKERRQ(ierr);
  ierr = EPSReset(cross->eps);CHKERRQ(ierr);
  ierr = MatDestroy(&cross->mat);CHKERRQ(ierr);
  ierr = MatDestroy(&cross->mat);CHKERRQ(ierr);
  ierr = VecDestroy(&cross->w);CHKERRQ(ierr);
  ierr = VecDestroy(&cross->w);CHKERRQ(ierr);
  ierr = VecDestroy(&cross->diag);CHKERRQ(ierr);
  ierr = VecDestroy(&cross->diag);CHKERRQ(ierr);
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
 
 
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "SVDDestroy_Cross"
#define __FUNCT__ "SVDDestroy_Cross"
PetscErrorCode SVDDestroy_Cross(SVD svd)
PetscErrorCode SVDDestroy_Cross(SVD svd)
{
{
  PetscErrorCode ierr;
  PetscErrorCode ierr;
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  ierr = EPSDestroy(&cross->eps);CHKERRQ(ierr);
  ierr = EPSDestroy(&cross->eps);CHKERRQ(ierr);
  ierr = PetscFree(svd->data);CHKERRQ(ierr);
  ierr = PetscFree(svd->data);CHKERRQ(ierr);
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossSetEPS_C","",PETSC_NULL);CHKERRQ(ierr);
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossSetEPS_C","",PETSC_NULL);CHKERRQ(ierr);
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossGetEPS_C","",PETSC_NULL);CHKERRQ(ierr);
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossGetEPS_C","",PETSC_NULL);CHKERRQ(ierr);
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
 
 
EXTERN_C_BEGIN
EXTERN_C_BEGIN
#undef __FUNCT__  
#undef __FUNCT__  
#define __FUNCT__ "SVDCreate_Cross"
#define __FUNCT__ "SVDCreate_Cross"
PetscErrorCode SVDCreate_Cross(SVD svd)
PetscErrorCode SVDCreate_Cross(SVD svd)
{
{
  PetscErrorCode ierr;
  PetscErrorCode ierr;
  SVD_CROSS      *cross;
  SVD_CROSS      *cross;
  ST             st;
  ST             st;
 
 
  PetscFunctionBegin;
  PetscFunctionBegin;
  ierr = PetscNewLog(svd,SVD_CROSS,&cross);CHKERRQ(ierr);
  ierr = PetscNewLog(svd,SVD_CROSS,&cross);CHKERRQ(ierr);
  svd->data                = (void*)cross;
  svd->data                = (void*)cross;
  svd->ops->solve          = SVDSolve_Cross;
  svd->ops->solve          = SVDSolve_Cross;
  svd->ops->setup          = SVDSetUp_Cross;
  svd->ops->setup          = SVDSetUp_Cross;
  svd->ops->setfromoptions = SVDSetFromOptions_Cross;
  svd->ops->setfromoptions = SVDSetFromOptions_Cross;
  svd->ops->destroy        = SVDDestroy_Cross;
  svd->ops->destroy        = SVDDestroy_Cross;
  svd->ops->reset          = SVDReset_Cross;
  svd->ops->reset          = SVDReset_Cross;
  svd->ops->view           = SVDView_Cross;
  svd->ops->view           = SVDView_Cross;
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossSetEPS_C","SVDCrossSetEPS_Cross",SVDCrossSetEPS_Cross);CHKERRQ(ierr);
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossSetEPS_C","SVDCrossSetEPS_Cross",SVDCrossSetEPS_Cross);CHKERRQ(ierr);
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossGetEPS_C","SVDCrossGetEPS_Cross",SVDCrossGetEPS_Cross);CHKERRQ(ierr);
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossGetEPS_C","SVDCrossGetEPS_Cross",SVDCrossGetEPS_Cross);CHKERRQ(ierr);
 
 
  ierr = EPSCreate(((PetscObject)svd)->comm,&cross->eps);CHKERRQ(ierr);
  ierr = EPSCreate(((PetscObject)svd)->comm,&cross->eps);CHKERRQ(ierr);
  ierr = EPSSetOptionsPrefix(cross->eps,((PetscObject)svd)->prefix);CHKERRQ(ierr);
  ierr = EPSSetOptionsPrefix(cross->eps,((PetscObject)svd)->prefix);CHKERRQ(ierr);
  ierr = EPSAppendOptionsPrefix(cross->eps,"svd_");CHKERRQ(ierr);
  ierr = EPSAppendOptionsPrefix(cross->eps,"svd_");CHKERRQ(ierr);
  ierr = PetscObjectIncrementTabLevel((PetscObject)cross->eps,(PetscObject)svd,1);CHKERRQ(ierr);  
  ierr = PetscObjectIncrementTabLevel((PetscObject)cross->eps,(PetscObject)svd,1);CHKERRQ(ierr);  
  ierr = PetscLogObjectParent(svd,cross->eps);CHKERRQ(ierr);
  ierr = PetscLogObjectParent(svd,cross->eps);CHKERRQ(ierr);
  if (!svd->ip) { ierr = SVDGetIP(svd,&svd->ip);CHKERRQ(ierr); }
  if (!svd->ip) { ierr = SVDGetIP(svd,&svd->ip);CHKERRQ(ierr); }
  ierr = EPSSetIP(cross->eps,svd->ip);CHKERRQ(ierr);
  ierr = EPSSetIP(cross->eps,svd->ip);CHKERRQ(ierr);
  ierr = EPSSetWhichEigenpairs(cross->eps,EPS_LARGEST_REAL);CHKERRQ(ierr);
  ierr = EPSSetWhichEigenpairs(cross->eps,EPS_LARGEST_REAL);CHKERRQ(ierr);
  ierr = EPSMonitorSet(cross->eps,SVDMonitor_Cross,svd,PETSC_NULL);CHKERRQ(ierr);
  ierr = EPSMonitorSet(cross->eps,SVDMonitor_Cross,svd,PETSC_NULL);CHKERRQ(ierr);
  ierr = EPSGetST(cross->eps,&st);CHKERRQ(ierr);
  ierr = EPSGetST(cross->eps,&st);CHKERRQ(ierr);
  ierr = STSetMatMode(st,ST_MATMODE_SHELL);CHKERRQ(ierr);
  ierr = STSetMatMode(st,ST_MATMODE_SHELL);CHKERRQ(ierr);
  cross->mat = PETSC_NULL;
  cross->mat = PETSC_NULL;
  cross->w = PETSC_NULL;
  cross->w = PETSC_NULL;
  cross->diag = PETSC_NULL;
  cross->diag = PETSC_NULL;
  cross->setfromoptionscalled = PETSC_FALSE;
  cross->setfromoptionscalled = PETSC_FALSE;
  PetscFunctionReturn(0);
  PetscFunctionReturn(0);
}
}
EXTERN_C_END
EXTERN_C_END