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
1298 slepc 1
/*                      
2
 
3
   SLEPc singular value solver: "trlanczos"
4
 
5
   Method: Golub-Kahan-Lanczos bidiagonalization with thick-restart
6
 
1397 slepc 7
   Last update: Jun 2007
1298 slepc 8
 
1376 slepc 9
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
10
      SLEPc - Scalable Library for Eigenvalue Problem Computations
11
      Copyright (c) 2002-2007, Universidad Politecnica de Valencia, Spain
12
 
13
      This file is part of SLEPc. See the README file for conditions of use
14
      and additional information.
15
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1298 slepc 16
*/
1376 slepc 17
 
1521 slepc 18
#include "private/svdimpl.h"                /*I "slepcsvd.h" I*/
19
#include "private/ipimpl.h"
1298 slepc 20
#include "slepcblaslapack.h"
21
 
22
typedef struct {
23
  PetscTruth oneside;
24
} SVD_TRLANCZOS;
25
 
26
#undef __FUNCT__  
27
#define __FUNCT__ "SVDSetUp_TRLANCZOS"
28
PetscErrorCode SVDSetUp_TRLANCZOS(SVD svd)
29
{
30
  PetscErrorCode  ierr;
1605 slepc 31
  PetscInt        i,N,nloc;
32
  PetscScalar     *pU;
1298 slepc 33
 
34
  PetscFunctionBegin;
1314 slepc 35
  ierr = SVDMatGetSize(svd,PETSC_NULL,&N);CHKERRQ(ierr);
1595 slepc 36
  if (svd->ncv) { /* ncv set */
37
    if (svd->ncv<svd->nsv) SETERRQ(1,"The value of ncv must be at least nsv");
38
  }
39
  else if (svd->mpd) { /* mpd set */
40
    svd->ncv = PetscMin(N,svd->nsv+svd->mpd);
41
  }
42
  else { /* neither set: defaults depend on nsv being small or large */
43
    if (svd->nsv<500) svd->ncv = PetscMin(N,PetscMax(2*svd->nsv,10));
44
    else { svd->mpd = 500; svd->ncv = PetscMin(N,svd->nsv+svd->mpd); }
45
  }
46
  if (!svd->mpd) svd->mpd = svd->ncv;
47
  if (svd->ncv>svd->nsv+svd->mpd) SETERRQ(1,"The value of ncv must not be larger than nev+mpd");
1594 slepc 48
  if (!svd->max_it)
1314 slepc 49
    svd->max_it = PetscMax(N/svd->ncv,100);
50
  if (svd->ncv!=svd->n) {  
51
    if (svd->U) {
1605 slepc 52
      ierr = VecGetArray(svd->U[0],&pU);CHKERRQ(ierr);
1314 slepc 53
      for (i=0;i<svd->n;i++) { ierr = VecDestroy(svd->U[i]); CHKERRQ(ierr); }
1605 slepc 54
      ierr = PetscFree(pU);CHKERRQ(ierr);
1314 slepc 55
      ierr = PetscFree(svd->U);CHKERRQ(ierr);
56
    }
57
    ierr = PetscMalloc(sizeof(Vec)*svd->ncv,&svd->U);CHKERRQ(ierr);
1605 slepc 58
    ierr = SVDMatGetLocalSize(svd,&nloc,PETSC_NULL);CHKERRQ(ierr);
59
    ierr = PetscMalloc(svd->ncv*nloc*sizeof(PetscScalar),&pU);CHKERRQ(ierr);
60
    for (i=0;i<svd->ncv;i++) {
61
      ierr = VecCreateMPIWithArray(((PetscObject)svd)->comm,nloc,PETSC_DECIDE,pU+i*nloc,&svd->U[i]);CHKERRQ(ierr);
62
    }
1314 slepc 63
  }
1298 slepc 64
  PetscFunctionReturn(0);
65
}
66
 
67
#undef __FUNCT__  
1431 slepc 68
#define __FUNCT__ "SVDOneSideTRLanczosMGS"
1504 slepc 69
static PetscErrorCode SVDOneSideTRLanczosMGS(SVD svd,PetscReal *alpha,PetscReal *beta,PetscScalar* bb,Vec *V,Vec v,Vec* U,PetscInt nconv,PetscInt l,PetscInt n,PetscScalar* work,Vec wv,Vec wu)
1431 slepc 70
{
71
  PetscErrorCode ierr;
72
  PetscReal      a,b;
1504 slepc 73
  PetscInt       i,k=nconv+l;
1431 slepc 74
 
75
  PetscFunctionBegin;
76
  ierr = SVDMatMult(svd,PETSC_FALSE,V[k],U[k]);CHKERRQ(ierr);
77
  if (l>0) {
78
    ierr = VecSet(wu,0.0);CHKERRQ(ierr);
79
    ierr = VecMAXPY(wu,l,bb,U+nconv);CHKERRQ(ierr);
80
    ierr = VecAXPY(U[k],-1.0,wu);CHKERRQ(ierr);
81
  }
82
  ierr = IPNorm(svd->ip,U[k],&a);CHKERRQ(ierr);
83
  ierr = VecScale(U[k],1.0/a);CHKERRQ(ierr);
84
  alpha[0] = a;
85
  for (i=k+1;i<n;i++) {
86
    ierr = SVDMatMult(svd,PETSC_TRUE,U[i-1],V[i]);CHKERRQ(ierr);
1538 slepc 87
    ierr = IPOrthogonalize(svd->ip,i,PETSC_NULL,V,V[i],work,&b,PETSC_NULL,wv,PETSC_NULL);CHKERRQ(ierr);  
1431 slepc 88
    ierr = VecScale(V[i],1.0/b);CHKERRQ(ierr);
89
    beta[i-k-1] = b;
90
 
91
    ierr = SVDMatMult(svd,PETSC_FALSE,V[i],U[i]);CHKERRQ(ierr);
92
    ierr = VecAXPY(U[i],-b,U[i-1]);CHKERRQ(ierr);
93
    ierr = IPNorm(svd->ip,U[i],&a);CHKERRQ(ierr);
94
    ierr = VecScale(U[i],1.0/a);CHKERRQ(ierr);
95
    alpha[i-k] = a;
96
  }
97
  ierr = SVDMatMult(svd,PETSC_TRUE,U[n-1],v);CHKERRQ(ierr);
1538 slepc 98
  ierr = IPOrthogonalize(svd->ip,n,PETSC_NULL,V,v,work,&b,PETSC_NULL,wv,PETSC_NULL);CHKERRQ(ierr);      
1431 slepc 99
  beta[n-k-1] = b;
100
  PetscFunctionReturn(0);
101
}
102
 
103
#undef __FUNCT__  
1489 slepc 104
#define __FUNCT__ "SVDOneSideTRLanczosCGS"
1504 slepc 105
static PetscErrorCode SVDOneSideTRLanczosCGS(SVD svd,PetscReal *alpha,PetscReal *beta,PetscScalar* bb,Vec *V,Vec v,Vec* U,PetscInt nconv,PetscInt l,PetscInt n,PetscScalar* work,Vec wv,Vec wu)
1328 slepc 106
{
107
  PetscErrorCode ierr;
1414 slepc 108
  PetscReal      a,b,sum,onorm;
109
  PetscScalar    dot;
1504 slepc 110
  PetscInt       i,j,k=nconv+l;
1328 slepc 111
 
112
  PetscFunctionBegin;
113
  ierr = SVDMatMult(svd,PETSC_FALSE,V[k],U[k]);CHKERRQ(ierr);
114
  if (l>0) {
115
    ierr = VecSet(wu,0.0);CHKERRQ(ierr);
116
    ierr = VecMAXPY(wu,l,bb,U+nconv);CHKERRQ(ierr);
117
    ierr = VecAXPY(U[k],-1.0,wu);CHKERRQ(ierr);
118
  }
119
  for (i=k+1;i<n;i++) {
120
    ierr = SVDMatMult(svd,PETSC_TRUE,U[i-1],V[i]);CHKERRQ(ierr);
1352 slepc 121
    ierr = IPNormBegin(svd->ip,U[i-1],&a);CHKERRQ(ierr);
1414 slepc 122
    if (svd->ip->orthog_ref == IP_ORTH_REFINE_IFNEEDED) {
123
      ierr = IPInnerProductBegin(svd->ip,V[i],V[i],&dot);CHKERRQ(ierr);
124
    }
1381 slepc 125
    ierr = IPMInnerProductBegin(svd->ip,V[i],i,V,work);CHKERRQ(ierr);
1352 slepc 126
    ierr = IPNormEnd(svd->ip,U[i-1],&a);CHKERRQ(ierr);
1414 slepc 127
    if (svd->ip->orthog_ref == IP_ORTH_REFINE_IFNEEDED) {
128
      ierr = IPInnerProductEnd(svd->ip,V[i],V[i],&dot);CHKERRQ(ierr);
129
    }
1381 slepc 130
    ierr = IPMInnerProductEnd(svd->ip,V[i],i,V,work);CHKERRQ(ierr);
1328 slepc 131
 
132
    ierr = VecScale(U[i-1],1.0/a);CHKERRQ(ierr);
133
    ierr = VecScale(V[i],1.0/a);CHKERRQ(ierr);
134
    for (j=0;j<i;j++) work[j] = - work[j] / a;
135
    ierr = VecMAXPY(V[i],i,work,V);CHKERRQ(ierr);
136
 
1414 slepc 137
    switch (svd->ip->orthog_ref) {
138
    case IP_ORTH_REFINE_NEVER:
139
      ierr = IPNorm(svd->ip,V[i],&b);CHKERRQ(ierr);
140
      break;      
141
    case IP_ORTH_REFINE_ALWAYS:
142
      ierr = IPOrthogonalizeCGS(svd->ip,i,PETSC_NULL,V,V[i],work,PETSC_NULL,&b,wv);CHKERRQ(ierr);
143
      break;
144
    case IP_ORTH_REFINE_IFNEEDED:
145
      onorm = sqrt(PetscRealPart(dot)) / a;
146
      sum = 0.0;
147
      for (j=0;j<i;j++) {
148
        sum += PetscRealPart(work[j] * PetscConj(work[j]));
149
      }
150
      b = PetscRealPart(dot)/(a*a) - sum;
151
      if (b>0.0) b = sqrt(b);
152
      else {
153
        ierr = IPNorm(svd->ip,V[i],&b);CHKERRQ(ierr);
154
      }
155
      if (b < svd->ip->orthog_eta * onorm) {
156
        ierr = IPOrthogonalizeCGS(svd->ip,i,PETSC_NULL,V,V[i],work,PETSC_NULL,&b,wv);CHKERRQ(ierr);
157
      }
158
      break;
159
    }
160
 
1328 slepc 161
    ierr = VecScale(V[i],1.0/b);CHKERRQ(ierr);
162
 
163
    ierr = SVDMatMult(svd,PETSC_FALSE,V[i],U[i]);CHKERRQ(ierr);
164
    ierr = VecAXPY(U[i],-b,U[i-1]);CHKERRQ(ierr);
165
 
166
    alpha[i-k-1] = a;
167
    beta[i-k-1] = b;
168
  }
169
  ierr = SVDMatMult(svd,PETSC_TRUE,U[n-1],v);CHKERRQ(ierr);
1352 slepc 170
  ierr = IPNormBegin(svd->ip,U[n-1],&a);CHKERRQ(ierr);
1415 slepc 171
  if (svd->ip->orthog_ref == IP_ORTH_REFINE_IFNEEDED) {
172
    ierr = IPInnerProductBegin(svd->ip,v,v,&dot);CHKERRQ(ierr);
173
  }
1381 slepc 174
  ierr = IPMInnerProductBegin(svd->ip,v,n,V,work);CHKERRQ(ierr);
1352 slepc 175
  ierr = IPNormEnd(svd->ip,U[n-1],&a);CHKERRQ(ierr);
1415 slepc 176
  if (svd->ip->orthog_ref == IP_ORTH_REFINE_IFNEEDED) {
177
    ierr = IPInnerProductEnd(svd->ip,v,v,&dot);CHKERRQ(ierr);
178
  }
1381 slepc 179
  ierr = IPMInnerProductEnd(svd->ip,v,n,V,work);CHKERRQ(ierr);
1328 slepc 180
 
181
  ierr = VecScale(U[n-1],1.0/a);CHKERRQ(ierr);
182
  ierr = VecScale(v,1.0/a);CHKERRQ(ierr);
183
  for (j=0;j<n;j++) work[j] = - work[j] / a;
184
  ierr = VecMAXPY(v,n,work,V);CHKERRQ(ierr);
185
 
1415 slepc 186
  switch (svd->ip->orthog_ref) {
187
  case IP_ORTH_REFINE_NEVER:
188
    ierr = IPNorm(svd->ip,v,&b);CHKERRQ(ierr);
189
    break;      
190
  case IP_ORTH_REFINE_ALWAYS:
191
    ierr = IPOrthogonalizeCGS(svd->ip,n,PETSC_NULL,V,v,work,PETSC_NULL,&b,wv);CHKERRQ(ierr);
192
    break;
193
  case IP_ORTH_REFINE_IFNEEDED:
194
    onorm = sqrt(PetscRealPart(dot)) / a;
195
    sum = 0.0;
196
    for (j=0;j<i;j++) {
197
      sum += PetscRealPart(work[j] * PetscConj(work[j]));
198
    }
199
    b = PetscRealPart(dot)/(a*a) - sum;
200
    if (b>0.0) b = sqrt(b);
201
    else {
202
      ierr = IPNorm(svd->ip,v,&b);CHKERRQ(ierr);
203
    }
204
    if (b < svd->ip->orthog_eta * onorm) {
205
      ierr = IPOrthogonalizeCGS(svd->ip,n,PETSC_NULL,V,v,work,PETSC_NULL,&b,wv);CHKERRQ(ierr);
206
    }
207
    break;
208
  }
209
 
1328 slepc 210
  alpha[n-k-1] = a;
211
  beta[n-k-1] = b;
212
  PetscFunctionReturn(0);
213
}
214
 
215
#undef __FUNCT__  
1298 slepc 216
#define __FUNCT__ "SVDSolve_TRLANCZOS"
217
PetscErrorCode SVDSolve_TRLANCZOS(SVD svd)
218
{
219
  PetscErrorCode ierr;
220
  SVD_TRLANCZOS  *lanczos = (SVD_TRLANCZOS *)svd->data;
1328 slepc 221
  PetscReal      *alpha,*beta,norm;
1341 slepc 222
  PetscScalar    *b,*Q,*PT,*swork;
1605 slepc 223
  PetscInt       i,j,k,l,m,n,nv;
224
  Vec            v,wv,wu;
1328 slepc 225
  PetscTruth     conv;
1431 slepc 226
  IPOrthogonalizationType orthog;
1298 slepc 227
 
228
  PetscFunctionBegin;
229
  /* allocate working space */
1307 slepc 230
  ierr = PetscMalloc(sizeof(PetscReal)*svd->n,&alpha);CHKERRQ(ierr);
231
  ierr = PetscMalloc(sizeof(PetscReal)*svd->n,&beta);CHKERRQ(ierr);
232
  ierr = PetscMalloc(sizeof(PetscScalar)*svd->n,&b);CHKERRQ(ierr);
233
  ierr = PetscMalloc(sizeof(PetscScalar)*svd->n*svd->n,&Q);CHKERRQ(ierr);
234
  ierr = PetscMalloc(sizeof(PetscScalar)*svd->n*svd->n,&PT);CHKERRQ(ierr);
1605 slepc 235
#if !defined(PETSC_USE_COMPLEX)
236
  if (svd->which == SVD_SMALLEST) {
237
#endif
238
    ierr = PetscMalloc(sizeof(PetscScalar)*svd->n*svd->n,&swork);CHKERRQ(ierr);
239
#if !defined(PETSC_USE_COMPLEX)
240
  } else {
241
    ierr = PetscMalloc(sizeof(PetscScalar)*svd->n,&swork);CHKERRQ(ierr);
242
  }
243
#endif
1328 slepc 244
  ierr = VecDuplicate(svd->V[0],&v);CHKERRQ(ierr);
245
  ierr = VecDuplicate(svd->V[0],&wv);CHKERRQ(ierr);
246
  ierr = VecDuplicate(svd->U[0],&wu);CHKERRQ(ierr);
1431 slepc 247
  ierr = IPGetOrthogonalization(svd->ip,&orthog,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1298 slepc 248
 
249
  /* normalize start vector */
1328 slepc 250
  ierr = VecCopy(svd->vec_initial,svd->V[0]);CHKERRQ(ierr);
251
  ierr = VecNormalize(svd->V[0],&norm);CHKERRQ(ierr);
1298 slepc 252
 
253
  l = 0;
254
  while (svd->reason == SVD_CONVERGED_ITERATING) {
255
    svd->its++;
256
 
257
    /* inner loop */
1595 slepc 258
    nv = PetscMin(svd->nconv+svd->mpd,svd->n);
1328 slepc 259
    if (lanczos->oneside) {
1431 slepc 260
      if (orthog == IP_MGS_ORTH) {
1595 slepc 261
        ierr = SVDOneSideTRLanczosMGS(svd,alpha,beta,b+svd->nconv,svd->V,v,svd->U,svd->nconv,l,nv,swork,wv,wu);CHKERRQ(ierr);
1431 slepc 262
      } else {
1595 slepc 263
        ierr = SVDOneSideTRLanczosCGS(svd,alpha,beta,b+svd->nconv,svd->V,v,svd->U,svd->nconv,l,nv,swork,wv,wu);CHKERRQ(ierr);
1431 slepc 264
      }
1328 slepc 265
    } else {
1595 slepc 266
      ierr = SVDTwoSideLanczos(svd,alpha,beta,svd->V,v,svd->U,svd->nconv+l,nv,swork,wv,wu);CHKERRQ(ierr);
1298 slepc 267
    }
1595 slepc 268
    ierr = VecScale(v,1.0/beta[nv-svd->nconv-l-1]);CHKERRQ(ierr);
1328 slepc 269
 
1298 slepc 270
    /* compute SVD of general matrix */
1595 slepc 271
    n = nv - svd->nconv;
1298 slepc 272
    /* first l columns */
273
    for (j=0;j<l;j++) {
274
      for (i=0;i<j;i++) Q[j*n+i] = 0.0;    
1328 slepc 275
      Q[j*n+j] = svd->sigma[svd->nconv+j];
1298 slepc 276
      for (i=j+1;i<n;i++) Q[j*n+i] = 0.0;
277
    }
278
    /* l+1 column */
1328 slepc 279
    for (i=0;i<l;i++) Q[l*n+i] = b[i+svd->nconv];
280
    Q[l*n+l] = alpha[0];
1298 slepc 281
    for (i=l+1;i<n;i++) Q[l*n+i] = 0.0;
282
    /* rest of matrix */
283
    for (j=l+1;j<n;j++) {
284
      for (i=0;i<j-1;i++) Q[j*n+i] = 0.0;
1328 slepc 285
      Q[j*n+j-1] = beta[j-l-1];
286
      Q[j*n+j] = alpha[j-l];
1298 slepc 287
      for (i=j+1;i<n;i++) Q[j*n+i] = 0.0;
288
    }
1328 slepc 289
    ierr = SVDDense(n,n,Q,alpha,PETSC_NULL,PT);CHKERRQ(ierr);
1298 slepc 290
 
291
    /* compute error estimates */
1328 slepc 292
    k = 0;
293
    conv = PETSC_TRUE;
294
    for (i=svd->nconv;i<svd->n;i++) {
295
      if (svd->which == SVD_SMALLEST) j = n-i+svd->nconv-1;
296
      else j = i-svd->nconv;
297
      svd->sigma[i] = alpha[j];
298
      b[i] = Q[j*n+n-1]*beta[n-l-1];
299
      svd->errest[i] = PetscAbsScalar(b[i]);
300
      if (alpha[j] > svd->tol) svd->errest[i] /= alpha[j];
301
      if (conv) {
302
        if (svd->errest[i] < svd->tol) k++;
303
        else conv = PETSC_FALSE;
1304 slepc 304
      }
1298 slepc 305
    }
306
 
1328 slepc 307
    /* check convergence and update l */
308
    if (svd->its >= svd->max_it) svd->reason = SVD_DIVERGED_ITS;
309
    if (svd->nconv+k >= svd->nsv) svd->reason = SVD_CONVERGED_TOL;
310
    if (svd->reason != SVD_CONVERGED_ITERATING) l = 0;
1595 slepc 311
    else l = PetscMax((nv - svd->nconv - k) / 2,1);
1300 slepc 312
 
1328 slepc 313
    /* compute converged singular vectors and restart vectors*/
1605 slepc 314
#if !defined(PETSC_USE_COMPLEX)
315
    if (svd->which == SVD_SMALLEST) {
316
#endif
1328 slepc 317
    for (i=0;i<k+l;i++) {
318
      if (svd->which == SVD_SMALLEST) j = n-i-1;
319
      else j = i;
1605 slepc 320
      for (m=0;m<n;m++) swork[j*n+m] = PT[m*n+j];
1328 slepc 321
    }
1605 slepc 322
    ierr = SlepcUpdateVectors(n,svd->V+svd->nconv,0,k+l,swork,n,PETSC_FALSE);CHKERRQ(ierr);
323
    for (i=0;i<k+l;i++) {
324
      if (svd->which == SVD_SMALLEST) j = n-i-1;
325
      else j = i;
326
      for (m=0;m<n;m++) swork[j*n+m] = Q[j*n+m];
327
    }
328
    ierr = SlepcUpdateVectors(n,svd->U+svd->nconv,0,k+l,swork,n,PETSC_FALSE);CHKERRQ(ierr);
329
#if !defined(PETSC_USE_COMPLEX)
330
    } else {
331
      ierr = SlepcUpdateVectors(n,svd->V+svd->nconv,0,k+l,PT,n,PETSC_TRUE);CHKERRQ(ierr);
332
      ierr = SlepcUpdateVectors(n,svd->U+svd->nconv,0,k+l,Q,n,PETSC_FALSE);CHKERRQ(ierr);
333
    }
334
#endif
1328 slepc 335
 
1298 slepc 336
    /* copy the last vector to be the next initial vector */
337
    if (svd->reason == SVD_CONVERGED_ITERATING) {
1328 slepc 338
      ierr = VecCopy(v,svd->V[svd->nconv+k+l]);CHKERRQ(ierr);
1298 slepc 339
    }
340
 
1328 slepc 341
    svd->nconv += k;
1595 slepc 342
    SVDMonitor(svd,svd->its,svd->nconv,svd->sigma,svd->errest,nv);
1298 slepc 343
  }
344
 
1603 slepc 345
  /* orthonormalize U columns in one side method */
346
  if (lanczos->oneside) {
347
    for (i=0;i<svd->nconv;i++) {
1538 slepc 348
      ierr = IPOrthogonalize(svd->ip,i,PETSC_NULL,svd->U,svd->U[i],PETSC_NULL,&norm,PETSC_NULL,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1489 slepc 349
      ierr = VecScale(svd->U[i],1.0/norm);CHKERRQ(ierr);
350
    }
1298 slepc 351
  }
352
 
353
  /* free working space */
1328 slepc 354
  ierr = VecDestroy(v);CHKERRQ(ierr);
355
  ierr = VecDestroy(wv);CHKERRQ(ierr);
356
  ierr = VecDestroy(wu);CHKERRQ(ierr);
1298 slepc 357
 
358
  ierr = PetscFree(alpha);CHKERRQ(ierr);
359
  ierr = PetscFree(beta);CHKERRQ(ierr);
360
  ierr = PetscFree(b);CHKERRQ(ierr);
361
  ierr = PetscFree(Q);CHKERRQ(ierr);
362
  ierr = PetscFree(PT);CHKERRQ(ierr);
1341 slepc 363
  ierr = PetscFree(swork);CHKERRQ(ierr);
1298 slepc 364
  PetscFunctionReturn(0);
365
}
366
 
367
#undef __FUNCT__  
368
#define __FUNCT__ "SVDSetFromOptions_TRLANCZOS"
369
PetscErrorCode SVDSetFromOptions_TRLANCZOS(SVD svd)
370
{
371
  PetscErrorCode ierr;
372
  SVD_TRLANCZOS  *lanczos = (SVD_TRLANCZOS *)svd->data;
373
 
374
  PetscFunctionBegin;
1422 slepc 375
  ierr = PetscOptionsBegin(((PetscObject)svd)->comm,((PetscObject)svd)->prefix,"TRLANCZOS Singular Value Solver Options","SVD");CHKERRQ(ierr);
1359 slepc 376
  ierr = PetscOptionsTruth("-svd_trlanczos_oneside","Lanczos one-side reorthogonalization","SVDTRLanczosSetOneSide",PETSC_FALSE,&lanczos->oneside,PETSC_NULL);CHKERRQ(ierr);
1298 slepc 377
  ierr = PetscOptionsEnd();CHKERRQ(ierr);
378
  PetscFunctionReturn(0);
379
}
1370 slepc 380
 
1298 slepc 381
EXTERN_C_BEGIN
382
#undef __FUNCT__  
1359 slepc 383
#define __FUNCT__ "SVDTRLanczosSetOneSide_TRLANCZOS"
384
PetscErrorCode SVDTRLanczosSetOneSide_TRLANCZOS(SVD svd,PetscTruth oneside)
1298 slepc 385
{
386
  SVD_TRLANCZOS *lanczos = (SVD_TRLANCZOS *)svd->data;
387
 
388
  PetscFunctionBegin;
389
  lanczos->oneside = oneside;
390
  PetscFunctionReturn(0);
391
}
1370 slepc 392
EXTERN_C_END
1298 slepc 393
 
394
#undef __FUNCT__
1359 slepc 395
#define __FUNCT__ "SVDTRLanczosSetOneSide"
1393 slepc 396
/*@
397
   SVDTRLanczosSetOneSide - Indicate if the variant of the Lanczos method
398
   to be used is one-sided or two-sided.
399
 
400
   Collective on SVD
401
 
402
   Input Parameters:
403
+  svd     - singular value solver
404
-  oneside - boolean flag indicating if the method is one-sided or not
405
 
406
   Options Database Key:
407
.  -svd_trlanczos_oneside <boolean> - Indicates the boolean flag
408
 
409
   Note:
410
   By default, a two-sided variant is selected, which is sometimes slightly
411
   more robust. However, the one-sided variant is faster because it avoids
412
   the orthogonalization associated to left singular vectors.
413
 
414
   Level: advanced
415
 
416
.seealso: SVDLanczosSetOneSide()
417
@*/
1359 slepc 418
PetscErrorCode SVDTRLanczosSetOneSide(SVD svd,PetscTruth oneside)
1298 slepc 419
{
420
  PetscErrorCode ierr, (*f)(SVD,PetscTruth);
421
 
422
  PetscFunctionBegin;
423
  PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
1359 slepc 424
  ierr = PetscObjectQueryFunction((PetscObject)svd,"SVDTRLanczosSetOneSide_C",(void (**)())&f);CHKERRQ(ierr);
1298 slepc 425
  if (f) {
426
    ierr = (*f)(svd,oneside);CHKERRQ(ierr);
427
  }
428
  PetscFunctionReturn(0);
429
}
430
 
431
#undef __FUNCT__  
432
#define __FUNCT__ "SVDView_TRLANCZOS"
433
PetscErrorCode SVDView_TRLANCZOS(SVD svd,PetscViewer viewer)
434
{
435
  PetscErrorCode ierr;
436
  SVD_TRLANCZOS  *lanczos = (SVD_TRLANCZOS *)svd->data;
437
 
438
  PetscFunctionBegin;
439
  ierr = PetscViewerASCIIPrintf(viewer,"Lanczos reorthogonalization: %s\n",lanczos->oneside ? "one-side" : "two-side");CHKERRQ(ierr);
440
  PetscFunctionReturn(0);
441
}
442
 
443
EXTERN_C_BEGIN
444
#undef __FUNCT__  
445
#define __FUNCT__ "SVDCreate_TRLANCZOS"
446
PetscErrorCode SVDCreate_TRLANCZOS(SVD svd)
447
{
448
  PetscErrorCode ierr;
449
  SVD_TRLANCZOS  *lanczos;
450
 
451
  PetscFunctionBegin;
452
  ierr = PetscNew(SVD_TRLANCZOS,&lanczos);CHKERRQ(ierr);
453
  PetscLogObjectMemory(svd,sizeof(SVD_TRLANCZOS));
454
  svd->data                = (void *)lanczos;
455
  svd->ops->setup          = SVDSetUp_TRLANCZOS;
456
  svd->ops->solve          = SVDSolve_TRLANCZOS;
1391 slepc 457
  svd->ops->destroy        = SVDDestroy_Default;
1298 slepc 458
  svd->ops->setfromoptions = SVDSetFromOptions_TRLANCZOS;
459
  svd->ops->view           = SVDView_TRLANCZOS;
460
  lanczos->oneside         = PETSC_FALSE;
1359 slepc 461
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDTRLanczosSetOneSide_C","SVDTRLanczosSetOneSide_TRLANCZOS",SVDTRLanczosSetOneSide_TRLANCZOS);CHKERRQ(ierr);
1298 slepc 462
  PetscFunctionReturn(0);
463
}
464
EXTERN_C_END