Subversion Repositories slepc-dev

Rev

Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1278 slepc 1
/*                      
2
 
3
   SLEPc singular value solver: "lanczos"
4
 
1281 slepc 5
   Method: Golub-Kahan-Lanczos bidiagonalization
1278 slepc 6
 
7
   Last update: Nov 2006
8
 
9
*/
10
#include "src/svd/svdimpl.h"                /*I "slepcsvd.h" I*/
1283 slepc 11
#include "slepcblaslapack.h"
1278 slepc 12
 
13
#undef __FUNCT__  
14
#define __FUNCT__ "SVDSetUp_LANCZOS"
15
PetscErrorCode SVDSetUp_LANCZOS(SVD svd)
16
{
17
  PetscErrorCode  ierr;
18
  PetscInt        M,N;
19
 
20
  PetscFunctionBegin;
21
  ierr = MatGetSize(svd->A,&M,&N);CHKERRQ(ierr);
22
  if (svd->ncv == PETSC_DECIDE)
1283 slepc 23
    svd->ncv = PetscMin(PetscMin(M,N),PetscMax(2*svd->nsv,10));
24
  if (svd->max_it == PETSC_DECIDE)
25
    svd->max_it = PetscMax(PetscMin(M,N)/svd->ncv,100);
1278 slepc 26
  PetscFunctionReturn(0);
27
}
28
 
29
#undef __FUNCT__  
1281 slepc 30
#define __FUNCT__ "cgs"
31
PetscErrorCode cgs(Vec v, int n, Vec *V)
1278 slepc 32
{
33
  PetscErrorCode ierr;
34
  Vec            w;
35
  PetscScalar    *h;
36
 
37
  PetscFunctionBegin;
38
  if (n>0) {
39
    ierr = VecDuplicate(v,&w);CHKERRQ(ierr);
40
    ierr = PetscMalloc(sizeof(PetscScalar)*n,&h);CHKERRQ(ierr);
41
 
42
    ierr = VecMDot(v,n,V,h);CHKERRQ(ierr);
43
    ierr = VecSet(w,0.0);CHKERRQ(ierr);
44
    ierr = VecMAXPY(w,n,h,V);CHKERRQ(ierr);
45
    ierr = VecAXPY(v,-1.0,w);CHKERRQ(ierr);
46
 
47
    ierr = VecDestroy(w);CHKERRQ(ierr);
48
    ierr = PetscFree(h);CHKERRQ(ierr);
49
  }
50
  PetscFunctionReturn(0);
51
}
52
 
53
#undef __FUNCT__  
54
#define __FUNCT__ "computeres"
1280 slepc 55
PetscErrorCode computeres(SVD svd,PetscScalar sigma,Vec u,Vec v,PetscReal *norm1,PetscReal *norm2)
1278 slepc 56
{
57
  PetscErrorCode ierr;
58
  Vec            x,y;
59
 
60
  PetscFunctionBegin;
61
  ierr = VecDuplicate(u,&x);CHKERRQ(ierr);
62
  ierr = MatMult(svd->A,v,x);CHKERRQ(ierr);
63
  ierr = VecAXPY(x,-sigma,u);CHKERRQ(ierr);
1280 slepc 64
  ierr = VecNorm(x,NORM_2,norm1);CHKERRQ(ierr);
1278 slepc 65
 
66
  ierr = VecDuplicate(v,&y);CHKERRQ(ierr);
67
  if (svd->AT) {
68
    ierr = MatMult(svd->AT,u,y);CHKERRQ(ierr);
69
  } else {
70
    ierr = MatMultTranspose(svd->A,u,y);CHKERRQ(ierr);
71
  }
72
  ierr = VecAXPY(y,-sigma,v);CHKERRQ(ierr);
1280 slepc 73
  ierr = VecNorm(y,NORM_2,norm2);CHKERRQ(ierr);
1278 slepc 74
 
75
  ierr = VecDestroy(x);CHKERRQ(ierr);
76
  ierr = VecDestroy(y);CHKERRQ(ierr);
77
  PetscFunctionReturn(0);
78
}
79
 
80
 
81
#undef __FUNCT__  
82
#define __FUNCT__ "SVDSolve_LANCZOS"
83
PetscErrorCode SVDSolve_LANCZOS(SVD svd)
84
{
85
  PetscErrorCode ierr;
1280 slepc 86
  PetscReal      *alpha,*beta,norm1,norm2,*work;
1278 slepc 87
  PetscScalar    *Q,*PT;
1285 slepc 88
  int            i,j,k,l,n,zero=0,info;
1278 slepc 89
  Vec            *V,*U;
90
 
91
  PetscFunctionBegin;
92
  ierr = PetscMalloc(sizeof(PetscReal)*svd->n,&alpha);CHKERRQ(ierr);
93
  ierr = PetscMalloc(sizeof(PetscReal)*svd->n,&beta);CHKERRQ(ierr);
94
  ierr = PetscMalloc(sizeof(PetscScalar)*svd->n*svd->n,&Q);CHKERRQ(ierr);
95
  ierr = PetscMalloc(sizeof(PetscScalar)*svd->n*svd->n,&PT);CHKERRQ(ierr);
96
  ierr = PetscMalloc(sizeof(PetscReal)*4*svd->n,&work);CHKERRQ(ierr);
97
 
98
  ierr = VecDuplicateVecs(svd->V[0],svd->n+1,&V);CHKERRQ(ierr);
99
  ierr = VecDuplicateVecs(svd->U[0],svd->n,&U);CHKERRQ(ierr);
100
 
101
  ierr = VecCopy(svd->vec_initial,V[0]);CHKERRQ(ierr);
1281 slepc 102
  ierr = VecNormalize(V[0],&norm1);CHKERRQ(ierr);
1278 slepc 103
 
1283 slepc 104
  while (svd->reason == SVD_CONVERGED_ITERATING) {
105
    svd->its++;
106
 
1280 slepc 107
    for (i=svd->nconv;i<svd->n;i++) {
1278 slepc 108
      ierr = MatMult(svd->A,V[i],U[i]);CHKERRQ(ierr);
1281 slepc 109
//      if (i>svd->nconv) { ierr = VecAXPY(U[i],-beta[i-1],U[i-1]);CHKERRQ(ierr); }
110
      ierr = cgs(U[i],i,U);CHKERRQ(ierr);
111
      ierr = cgs(U[i],i,U);CHKERRQ(ierr);
1285 slepc 112
      ierr = VecNormalize(U[i],alpha+i-svd->nconv);CHKERRQ(ierr);
1278 slepc 113
 
114
      if (svd->AT) {
115
        ierr = MatMult(svd->AT,U[i],V[i+1]);CHKERRQ(ierr);
116
      } else {
117
        ierr = MatMultTranspose(svd->A,U[i],V[i+1]);CHKERRQ(ierr);
118
      }
1281 slepc 119
//      ierr = VecAXPY(V[i+1],-alpha[i],V[i]);CHKERRQ(ierr);
120
      ierr = cgs(V[i+1],i+1,V);CHKERRQ(ierr);
121
      ierr = cgs(V[i+1],i+1,V);CHKERRQ(ierr);
1285 slepc 122
      ierr = VecNormalize(V[i+1],beta+i-svd->nconv);CHKERRQ(ierr);    
1278 slepc 123
    }
124
 
1281 slepc 125
    n = svd->n - svd->nconv;
1278 slepc 126
    ierr = PetscMemzero(PT,sizeof(PetscScalar)*n*n);CHKERRQ(ierr);
127
    ierr = PetscMemzero(Q,sizeof(PetscScalar)*n*n);CHKERRQ(ierr);
128
    for (i=0;i<n;i++)
129
      PT[i*n+i] = Q[i*n+i] = 1.0;
1285 slepc 130
    LAPACKbdsqr_("U",&n,&n,&n,&zero,alpha,beta,PT,&n,Q,&n,PETSC_NULL,&n,work,&info,1);
1278 slepc 131
 
132
    k = svd->nconv;
1280 slepc 133
    for (i=svd->nconv;i<svd->n;i++) {
1285 slepc 134
      if (svd->which == SVD_SMALLEST) j = n-i+svd->nconv-1;
135
      else j = i-svd->nconv;
136
      svd->sigma[i] = alpha[j];
1278 slepc 137
 
138
      ierr = VecSet(svd->V[i],0.0);CHKERRQ(ierr);
1285 slepc 139
      for (l=0;l<n;l++) {
140
        ierr = VecAXPY(svd->V[i],PT[l*n+j],V[l+svd->nconv]);CHKERRQ(ierr);
1278 slepc 141
      }
142
 
143
      ierr = VecSet(svd->U[i],0.0);CHKERRQ(ierr);
1285 slepc 144
      ierr = VecMAXPY(svd->U[i],n,Q+j*n,U+svd->nconv);CHKERRQ(ierr);
1278 slepc 145
 
1280 slepc 146
      ierr = computeres(svd,svd->sigma[i],svd->U[i],svd->V[i],&norm1,&norm2);CHKERRQ(ierr);
1288 slepc 147
      svd->errest[i] = sqrt(norm1*norm1+norm2*norm2);
148
      if (svd->errest[i] < svd->tol) {
1278 slepc 149
        k++;
150
      } else break;
151
    }
1281 slepc 152
    for (i=svd->nconv;i<k;i++) {
153
      ierr = VecCopy(svd->V[i],V[i]);CHKERRQ(ierr);
154
      ierr = VecCopy(svd->U[i],U[i]);CHKERRQ(ierr);
155
    }
1278 slepc 156
    svd->nconv = k;
1288 slepc 157
 
158
    SVDMonitor(svd,svd->its,svd->nconv,svd->sigma,svd->errest,svd->ncv);
159
 
1283 slepc 160
    if (svd->its > svd->max_it) svd->reason = SVD_DIVERGED_ITS;
161
    if (svd->nconv >= svd->nsv) svd->reason = SVD_CONVERGED_TOL;
162
    if (svd->reason == SVD_CONVERGED_ITERATING) {
163
      ierr = VecCopy(svd->V[svd->nconv],V[svd->nconv]);CHKERRQ(ierr);
164
    }
1278 slepc 165
  }
166
 
167
  ierr = VecDestroyVecs(V,n+1);CHKERRQ(ierr);
168
  ierr = VecDestroyVecs(U,n);CHKERRQ(ierr);
169
 
170
  ierr = PetscFree(alpha);CHKERRQ(ierr);
171
  ierr = PetscFree(beta);CHKERRQ(ierr);
172
  ierr = PetscFree(Q);CHKERRQ(ierr);
173
  ierr = PetscFree(PT);CHKERRQ(ierr);
174
  ierr = PetscFree(work);CHKERRQ(ierr);
175
  PetscFunctionReturn(0);
176
}
177
 
178
EXTERN_C_BEGIN
179
#undef __FUNCT__  
180
#define __FUNCT__ "SVDCreate_LANCZOS"
181
PetscErrorCode SVDCreate_LANCZOS(SVD svd)
182
{
183
  PetscFunctionBegin;
184
  svd->ops->setup = SVDSetUp_LANCZOS;
185
  svd->ops->solve = SVDSolve_LANCZOS;
186
  PetscFunctionReturn(0);
187
}
188
EXTERN_C_END