/*
SVD routines for setting up the solver.
*/
#include "src/svd/svdimpl.h" /*I "slepcsvd.h" I*/
#undef __FUNCT__
#define __FUNCT__ "SVDSetOperator"
/*@C
SVDSetOperator - Set the matrix associated with the singular value problem.
Collective on SVD and Mat
Input Parameters:
+ svd - the singular value solver context
- A - the matrix associated with the singular value problem
Level: beginner
.seealso: SVDSolve(), SVDGetOperator()
@*/
PetscErrorCode SVDSetOperator(SVD svd,Mat mat)
{
PetscErrorCode ierr;
PetscFunctionBegin;
PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
PetscValidHeaderSpecific(mat,MAT_COOKIE,2);
PetscCheckSameComm(svd,1,mat,2);
ierr = PetscObjectReference((PetscObject)mat);CHKERRQ(ierr);
if (svd->A) {
ierr = MatDestroy(svd->A);CHKERRQ(ierr);
}
svd->A = mat;
if (svd->vec_initial) {
ierr = VecDestroy(svd->vec_initial);CHKERRQ(ierr);
svd->vec_initial = PETSC_NULL;
}
svd->setupcalled = 0;
PetscFunctionReturn(0);
}
#undef __FUNCT__
#define __FUNCT__ "SVDGetOperator"
/*@C
SVDGetOperators - Get the matrix associated with the singular value problem.
Not collective, though parallel Mats are returned if the SVD is parallel
Input Parameter:
. svd - the singular value solver context
Output Parameters:
. A - the matrix associated with the singular value problem
Level: advanced
.seealso: SVDSolve(), SVDSetOperator()
@*/
PetscErrorCode SVDGetOperator(SVD svd,Mat *A)
{
PetscFunctionBegin;
PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
PetscValidPointer(A,2);
*A = svd->A;
PetscFunctionReturn(0);
}
#undef __FUNCT__
#define __FUNCT__ "SVDSetInitialVector"
/*@
SVDSetInitialVector - Sets the initial vector from which the
singular value solver starts to iterate.
Collective on SVD and Vec
Input Parameters:
+ svd - the singular value solver context
- vec - the vector
Level: intermediate
.seealso: SVDGetInitialVector()
@*/
PetscErrorCode SVDSetInitialVector(SVD svd,Vec vec)
{
PetscErrorCode ierr;
PetscFunctionBegin;
PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
PetscValidHeaderSpecific(vec,VEC_COOKIE,2);
PetscCheckSameComm(svd,1,vec,2);
ierr = PetscObjectReference((PetscObject)vec);CHKERRQ(ierr);
if (svd->vec_initial) {
ierr = VecDestroy(svd->vec_initial); CHKERRQ(ierr);
}
svd->vec_initial = vec;
PetscFunctionReturn(0);
}
#undef __FUNCT__
#define __FUNCT__ "SVDGetInitialVector"
/*@
SVDGetInitialVector - Gets the initial vector associated with the
singular value solver; if the vector was not set it will return a 0
pointer or a vector randomly generated by SVDSetUp().
Not collective, but vector is shared by all processors that share the SVD
Input Parameter:
. svd - the singular value solver context
Output Parameter:
. vec - the vector
Level: intermediate
.seealso: SVDSetInitialVector()
@*/
PetscErrorCode SVDGetInitialVector(SVD svd,Vec *vec)
{
PetscFunctionBegin;
PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
PetscValidPointer(vec,2);
*vec = svd->vec_initial;
PetscFunctionReturn(0);
}
#undef __FUNCT__
#define __FUNCT__ "SVDSetUp"
/*@
SVDSetUp - Sets up all the internal data structures necessary for the
execution of the singular value solver.
Collective on SVD
Input Parameter:
. SVD - singular value solver context
Level: advanced
Notes:
This function need not be called explicitly in most cases, since SVDSolve()
calls it. It can be useful when one wants to measure the set-up time
separately from the solve time.
.seealso: SVDCreate(), SVDSolve(), SVDDestroy()
@*/
PetscErrorCode SVDSetUp(SVD svd)
{
PetscErrorCode ierr;
int i;
PetscTruth flg;
PetscInt M,N;
PetscFunctionBegin;
PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
if (svd->setupcalled) PetscFunctionReturn(0);
ierr = PetscLogEventBegin(SVD_SetUp,svd,0,0,0);CHKERRQ(ierr);
/* Set default solver type */
if (!svd->type_name) {
ierr = SVDSetType(svd,SVDEIGENSOLVER);CHKERRQ(ierr);
}
/* check matrix */
if (!svd->A)
SETERRQ(PETSC_ERR_ARG_WRONGSTATE, "SVDSetOperator must be called first");
/* determine how to build the transpose */
if (svd->transmode == PETSC_DECIDE) {
ierr = MatHasOperation(svd->A,MATOP_TRANSPOSE,&flg);CHKERRQ(ierr);
if (flg) svd->transmode = SVD_TRANSPOSE_EXPLICIT;
else svd->transmode = SVD_TRANSPOSE_IMPLICIT;
}
/* build transpose matrix */
if (svd->AT) { ierr = MatDestroy(svd->AT);CHKERRQ(ierr); }
switch (svd->transmode) {
case SVD_TRANSPOSE_EXPLICIT:
ierr = MatTranspose(svd->A,&svd->AT);CHKERRQ(ierr);
break;
case SVD_TRANSPOSE_IMPLICIT:
svd->AT = PETSC_NULL;
break;
default:
SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Invalid transpose mode");
}
/* set initial vector */
if (!svd->vec_initial) {
ierr = MatGetVecs(svd->A,&svd->vec_initial,PETSC_NULL);CHKERRQ(ierr);
ierr = SlepcVecSetRandom(svd->vec_initial);CHKERRQ(ierr);
}
/* call specific solver setup */
ierr = (*svd->ops->setup)(svd);CHKERRQ(ierr);
ierr = MatGetSize(svd->A,&M,&N);CHKERRQ(ierr);
if (svd->ncv > M || svd->ncv > N)
SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"ncv bigger than matrix dimensions");
if (svd->nsv > svd->ncv)
SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"nsv bigger than ncv");
if (svd->ncv != svd->n) {
/* free memory for previous solution */
if (svd->n) {
ierr = PetscFree(svd->sigma);CHKERRQ(ierr);
for (i=0;i<svd->n;i++) {
ierr = VecDestroy(svd->U[i]); CHKERRQ(ierr);
}
ierr = PetscFree(svd->U);CHKERRQ(ierr);
for (i=0;i<svd->n;i++) {
ierr = VecDestroy(svd->V[i]);CHKERRQ(ierr);
}
ierr = PetscFree(svd->V);CHKERRQ(ierr);
}
/* allocate memory for next solution */
ierr = PetscMalloc(svd->ncv*sizeof(PetscReal),&svd->sigma);CHKERRQ(ierr);
ierr = PetscMalloc(svd->ncv*sizeof(Vec),&svd->U);CHKERRQ(ierr);
ierr = PetscMalloc(svd->ncv*sizeof(Vec),&svd->V);CHKERRQ(ierr);
for (i=0;i<svd->ncv;i++) {
ierr = MatGetVecs(svd->A,svd->V+i,svd->U+i);CHKERRQ(ierr);
}
svd->n = svd->ncv;
}
ierr = PetscLogEventEnd(SVD_SetUp,svd,0,0,0);CHKERRQ(ierr);
svd->setupcalled = 1;
PetscFunctionReturn(0);
}