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
1324 slepc 1
/*                      
2
 
3
   SLEPc singular value solver: "cross"
4
 
1325 slepc 5
   Method: Uses a Hermitian eigensolver for A^T*A
1324 slepc 6
 
1397 slepc 7
   Last update: Jun 2007
1324 slepc 8
 
1376 slepc 9
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1672 slepc 10
   SLEPc - Scalable Library for Eigenvalue Problem Computations
2575 eromero 11
   Copyright (c) 2002-2011, Universitat Politecnica de Valencia, Spain
1376 slepc 12
 
1672 slepc 13
   This file is part of SLEPc.
14
 
15
   SLEPc is free software: you can redistribute it and/or modify it under  the
16
   terms of version 3 of the GNU Lesser General Public License as published by
17
   the Free Software Foundation.
18
 
19
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
20
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
21
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
22
   more details.
23
 
24
   You  should have received a copy of the GNU Lesser General  Public  License
25
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
1376 slepc 26
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1324 slepc 27
*/
1376 slepc 28
 
2284 jroman 29
#include <private/svdimpl.h>                /*I "slepcsvd.h" I*/
30
#include <private/epsimpl.h>                /*I "slepceps.h" I*/
1324 slepc 31
 
32
typedef struct {
2216 jroman 33
  EPS       eps;
34
  PetscBool setfromoptionscalled;
35
  Mat       mat;
36
  Vec       w,diag;
1324 slepc 37
} SVD_CROSS;
38
 
39
#undef __FUNCT__  
2324 jroman 40
#define __FUNCT__ "ShellMatMult_Cross"
2331 jroman 41
PetscErrorCode ShellMatMult_Cross(Mat B,Vec x,Vec y)
1324 slepc 42
{
43
  PetscErrorCode ierr;
44
  SVD            svd;
45
  SVD_CROSS      *cross;
46
 
47
  PetscFunctionBegin;
48
  ierr = MatShellGetContext(B,(void**)&svd);CHKERRQ(ierr);
2350 jroman 49
  cross = (SVD_CROSS*)svd->data;
1324 slepc 50
  ierr = SVDMatMult(svd,PETSC_FALSE,x,cross->w);CHKERRQ(ierr);
51
  ierr = SVDMatMult(svd,PETSC_TRUE,cross->w,y);CHKERRQ(ierr);
52
  PetscFunctionReturn(0);
53
}
54
 
55
#undef __FUNCT__  
2324 jroman 56
#define __FUNCT__ "ShellMatGetDiagonal_Cross"
57
PetscErrorCode ShellMatGetDiagonal_Cross(Mat B,Vec d)
1324 slepc 58
{
59
  PetscErrorCode    ierr;
60
  SVD               svd;
61
  SVD_CROSS         *cross;
62
  PetscInt          N,n,i,j,start,end,ncols;
63
  PetscScalar       *work1,*work2,*diag;
64
  const PetscInt    *cols;
65
  const PetscScalar *vals;
66
 
67
  PetscFunctionBegin;
68
  ierr = MatShellGetContext(B,(void**)&svd);CHKERRQ(ierr);
2350 jroman 69
  cross = (SVD_CROSS*)svd->data;
1324 slepc 70
  if (!cross->diag) {
71
    /* compute diagonal from rows and store in cross->diag */
72
    ierr = VecDuplicate(d,&cross->diag);CHKERRQ(ierr);
73
    ierr = SVDMatGetSize(svd,PETSC_NULL,&N);CHKERRQ(ierr);
74
    ierr = SVDMatGetLocalSize(svd,PETSC_NULL,&n);CHKERRQ(ierr);
75
    ierr = PetscMalloc(sizeof(PetscScalar)*N,&work1);CHKERRQ(ierr);
76
    ierr = PetscMalloc(sizeof(PetscScalar)*N,&work2);CHKERRQ(ierr);
77
    for (i=0;i<n;i++) work1[i] = work2[i] = 0.0;
78
    if (svd->AT) {
79
      ierr = MatGetOwnershipRange(svd->AT,&start,&end);CHKERRQ(ierr);
80
      for (i=start;i<end;i++) {
81
        ierr = MatGetRow(svd->AT,i,&ncols,PETSC_NULL,&vals);CHKERRQ(ierr);
82
        for (j=0;j<ncols;j++)
83
          work1[i] += vals[j]*vals[j];
84
        ierr = MatRestoreRow(svd->AT,i,&ncols,PETSC_NULL,&vals);CHKERRQ(ierr);
85
      }
86
    } else {
87
      ierr = MatGetOwnershipRange(svd->A,&start,&end);CHKERRQ(ierr);
88
      for (i=start;i<end;i++) {
89
        ierr = MatGetRow(svd->A,i,&ncols,&cols,&vals);CHKERRQ(ierr);
90
        for (j=0;j<ncols;j++)
91
          work1[cols[j]] += vals[j]*vals[j];
92
        ierr = MatRestoreRow(svd->A,i,&ncols,&cols,&vals);CHKERRQ(ierr);
93
      }
94
    }
1422 slepc 95
    ierr = MPI_Allreduce(work1,work2,N,MPIU_SCALAR,MPI_SUM,((PetscObject)svd)->comm);CHKERRQ(ierr);
1324 slepc 96
    ierr = VecGetOwnershipRange(cross->diag,&start,&end);CHKERRQ(ierr);
97
    ierr = VecGetArray(cross->diag,&diag);CHKERRQ(ierr);
98
    for (i=start;i<end;i++)
99
      diag[i-start] = work2[i];
100
    ierr = VecRestoreArray(cross->diag,&diag);CHKERRQ(ierr);
101
    ierr = PetscFree(work1);CHKERRQ(ierr);
102
    ierr = PetscFree(work2);CHKERRQ(ierr);
103
  }
104
  ierr = VecCopy(cross->diag,d);CHKERRQ(ierr);
105
  PetscFunctionReturn(0);
106
}
107
 
108
#undef __FUNCT__  
2324 jroman 109
#define __FUNCT__ "SVDSetUp_Cross"
110
PetscErrorCode SVDSetUp_Cross(SVD svd)
1324 slepc 111
{
2317 jroman 112
  PetscErrorCode ierr;
2350 jroman 113
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
2317 jroman 114
  PetscInt       n,i;
115
  PetscBool      trackall;
1324 slepc 116
 
117
  PetscFunctionBegin;
2520 jroman 118
  if (!cross->mat) {
119
    ierr = SVDMatGetLocalSize(svd,PETSC_NULL,&n);CHKERRQ(ierr);
120
    ierr = MatCreateShell(((PetscObject)svd)->comm,n,n,PETSC_DETERMINE,PETSC_DETERMINE,svd,&cross->mat);CHKERRQ(ierr);
121
    ierr = MatShellSetOperation(cross->mat,MATOP_MULT,(void(*)(void))ShellMatMult_Cross);CHKERRQ(ierr);  
122
    ierr = MatShellSetOperation(cross->mat,MATOP_GET_DIAGONAL,(void(*)(void))ShellMatGetDiagonal_Cross);CHKERRQ(ierr);  
123
    ierr = SVDMatGetVecs(svd,PETSC_NULL,&cross->w);CHKERRQ(ierr);
124
  }
1324 slepc 125
 
126
  ierr = EPSSetOperators(cross->eps,cross->mat,PETSC_NULL);CHKERRQ(ierr);
127
  ierr = EPSSetProblemType(cross->eps,EPS_HEP);CHKERRQ(ierr);
1406 slepc 128
  ierr = EPSSetWhichEigenpairs(cross->eps,svd->which == SVD_LARGEST ? EPS_LARGEST_REAL : EPS_SMALLEST_REAL);CHKERRQ(ierr);
1575 slepc 129
  ierr = EPSSetDimensions(cross->eps,svd->nsv,svd->ncv,svd->mpd);CHKERRQ(ierr);
1324 slepc 130
  ierr = EPSSetTolerances(cross->eps,svd->tol,svd->max_it);CHKERRQ(ierr);
2055 eromero 131
  /* Transfer the trackall option from svd to eps */
132
  ierr = SVDGetTrackAll(svd,&trackall);CHKERRQ(ierr);
133
  ierr = EPSSetTrackAll(cross->eps,trackall);CHKERRQ(ierr);
2177 jroman 134
  if (cross->setfromoptionscalled) {
2024 eromero 135
    ierr = EPSSetFromOptions(cross->eps);CHKERRQ(ierr);
136
    cross->setfromoptionscalled = PETSC_FALSE;
137
  }
1324 slepc 138
  ierr = EPSSetUp(cross->eps);CHKERRQ(ierr);
1575 slepc 139
  ierr = EPSGetDimensions(cross->eps,PETSC_NULL,&svd->ncv,&svd->mpd);CHKERRQ(ierr);
1324 slepc 140
  ierr = EPSGetTolerances(cross->eps,&svd->tol,&svd->max_it);CHKERRQ(ierr);
2063 eromero 141
  /* Transfer the initial space from svd to eps */
142
  if (svd->nini < 0) {
143
    ierr = EPSSetInitialSpace(cross->eps,-svd->nini,svd->IS);CHKERRQ(ierr);
2080 eromero 144
    for(i=0; i<-svd->nini; i++) {
2305 jroman 145
      ierr = VecDestroy(&svd->IS[i]);CHKERRQ(ierr);
2080 eromero 146
    }
147
    ierr = PetscFree(svd->IS);CHKERRQ(ierr);
148
    svd->nini = 0;
2063 eromero 149
  }
1324 slepc 150
  PetscFunctionReturn(0);
151
}
152
 
153
#undef __FUNCT__  
2324 jroman 154
#define __FUNCT__ "SVDSolve_Cross"
155
PetscErrorCode SVDSolve_Cross(SVD svd)
1324 slepc 156
{
157
  PetscErrorCode ierr;
2350 jroman 158
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
1504 slepc 159
  PetscInt       i;
1324 slepc 160
  PetscScalar    sigma;
161
 
162
  PetscFunctionBegin;
163
  ierr = EPSSolve(cross->eps);CHKERRQ(ierr);
164
  ierr = EPSGetConverged(cross->eps,&svd->nconv);CHKERRQ(ierr);
165
  ierr = EPSGetIterationNumber(cross->eps,&svd->its);CHKERRQ(ierr);
166
  ierr = EPSGetConvergedReason(cross->eps,(EPSConvergedReason*)&svd->reason);CHKERRQ(ierr);
167
  for (i=0;i<svd->nconv;i++) {
168
    ierr = EPSGetEigenpair(cross->eps,i,&sigma,PETSC_NULL,svd->V[i],PETSC_NULL);CHKERRQ(ierr);
2383 jroman 169
    if (PetscRealPart(sigma)<0.0) SETERRQ(((PetscObject)svd)->comm,1,"Negative eigenvalue computed by EPS");
2473 jroman 170
    svd->sigma[i] = PetscSqrtReal(PetscRealPart(sigma));
1324 slepc 171
  }
172
  PetscFunctionReturn(0);
173
}
174
 
175
#undef __FUNCT__  
2324 jroman 176
#define __FUNCT__ "SVDMonitor_Cross"
2382 jroman 177
static PetscErrorCode SVDMonitor_Cross(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *ctx)
1324 slepc 178
{
2054 eromero 179
  PetscInt       i;
180
  SVD            svd = (SVD)ctx;
181
  PetscScalar    er,ei;
182
  PetscErrorCode ierr;
1324 slepc 183
 
184
  PetscFunctionBegin;
185
  for (i=0;i<nest;i++) {
2054 eromero 186
    er = eigr[i]; ei = eigi[i];
2331 jroman 187
    ierr = STBackTransform(eps->OP,1,&er,&ei);CHKERRQ(ierr);
2473 jroman 188
    svd->sigma[i] = PetscSqrtReal(PetscRealPart(er));
1324 slepc 189
    svd->errest[i] = errest[i];
190
  }
2313 jroman 191
  ierr = SVDMonitor(svd,its,nconv,svd->sigma,svd->errest,nest);CHKERRQ(ierr);
1324 slepc 192
  PetscFunctionReturn(0);
193
}
194
 
195
#undef __FUNCT__  
2324 jroman 196
#define __FUNCT__ "SVDSetFromOptions_Cross"
197
PetscErrorCode SVDSetFromOptions_Cross(SVD svd)
1324 slepc 198
{
2350 jroman 199
  SVD_CROSS *cross = (SVD_CROSS*)svd->data;
1324 slepc 200
 
201
  PetscFunctionBegin;
2024 eromero 202
  cross->setfromoptionscalled = PETSC_TRUE;
1324 slepc 203
  PetscFunctionReturn(0);
204
}
205
 
206
EXTERN_C_BEGIN
207
#undef __FUNCT__  
2324 jroman 208
#define __FUNCT__ "SVDCrossSetEPS_Cross"
209
PetscErrorCode SVDCrossSetEPS_Cross(SVD svd,EPS eps)
1324 slepc 210
{
211
  PetscErrorCode ierr;
2350 jroman 212
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
1324 slepc 213
 
214
  PetscFunctionBegin;
215
  ierr = PetscObjectReference((PetscObject)eps);CHKERRQ(ierr);
2308 jroman 216
  ierr = EPSDestroy(&cross->eps);CHKERRQ(ierr);  
1324 slepc 217
  cross->eps = eps;
2327 jroman 218
  ierr = PetscLogObjectParent(svd,cross->eps);CHKERRQ(ierr);
1324 slepc 219
  svd->setupcalled = 0;
220
  PetscFunctionReturn(0);
221
}
222
EXTERN_C_END
223
 
224
#undef __FUNCT__  
225
#define __FUNCT__ "SVDCrossSetEPS"
226
/*@
1325 slepc 227
   SVDCrossSetEPS - Associate an eigensolver object (EPS) to the
1324 slepc 228
   singular value solver.
229
 
230
   Collective on SVD
231
 
232
   Input Parameters:
233
+  svd - singular value solver
234
-  eps - the eigensolver object
235
 
236
   Level: advanced
237
 
238
.seealso: SVDCrossGetEPS()
239
@*/
240
PetscErrorCode SVDCrossSetEPS(SVD svd,EPS eps)
241
{
2221 jroman 242
  PetscErrorCode ierr;
1324 slepc 243
 
244
  PetscFunctionBegin;
2213 jroman 245
  PetscValidHeaderSpecific(svd,SVD_CLASSID,1);
2221 jroman 246
  PetscValidHeaderSpecific(eps,EPS_CLASSID,2);
2326 jroman 247
  PetscCheckSameComm(svd,1,eps,2);
2221 jroman 248
  ierr = PetscTryMethod(svd,"SVDCrossSetEPS_C",(SVD,EPS),(svd,eps));CHKERRQ(ierr);
1324 slepc 249
  PetscFunctionReturn(0);
250
}
251
 
252
EXTERN_C_BEGIN
253
#undef __FUNCT__  
2324 jroman 254
#define __FUNCT__ "SVDCrossGetEPS_Cross"
255
PetscErrorCode SVDCrossGetEPS_Cross(SVD svd,EPS *eps)
1324 slepc 256
{
2350 jroman 257
  SVD_CROSS *cross = (SVD_CROSS*)svd->data;
1324 slepc 258
 
259
  PetscFunctionBegin;
260
  *eps = cross->eps;
261
  PetscFunctionReturn(0);
262
}
263
EXTERN_C_END
264
 
265
#undef __FUNCT__  
266
#define __FUNCT__ "SVDCrossGetEPS"
2061 eromero 267
/*@
1324 slepc 268
   SVDCrossGetEPS - Retrieve the eigensolver object (EPS) associated
269
   to the singular value solver.
270
 
271
   Not Collective
272
 
1325 slepc 273
   Input Parameter:
1324 slepc 274
.  svd - singular value solver
275
 
276
   Output Parameter:
277
.  eps - the eigensolver object
278
 
279
   Level: advanced
280
 
281
.seealso: SVDCrossSetEPS()
282
@*/
283
PetscErrorCode SVDCrossGetEPS(SVD svd,EPS *eps)
284
{
2221 jroman 285
  PetscErrorCode ierr;
1324 slepc 286
 
287
  PetscFunctionBegin;
2213 jroman 288
  PetscValidHeaderSpecific(svd,SVD_CLASSID,1);
2326 jroman 289
  PetscValidPointer(eps,2);
2221 jroman 290
  ierr = PetscTryMethod(svd,"SVDCrossGetEPS_C",(SVD,EPS*),(svd,eps));CHKERRQ(ierr);
1324 slepc 291
  PetscFunctionReturn(0);
292
}
293
 
294
#undef __FUNCT__  
2324 jroman 295
#define __FUNCT__ "SVDView_Cross"
296
PetscErrorCode SVDView_Cross(SVD svd,PetscViewer viewer)
1324 slepc 297
{
298
  PetscErrorCode ierr;
2350 jroman 299
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
1324 slepc 300
 
301
  PetscFunctionBegin;
2367 jroman 302
  ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
1324 slepc 303
  ierr = EPSView(cross->eps,viewer);CHKERRQ(ierr);
2367 jroman 304
  ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
1324 slepc 305
  PetscFunctionReturn(0);
306
}
307
 
308
#undef __FUNCT__  
2350 jroman 309
#define __FUNCT__ "SVDReset_Cross"
310
PetscErrorCode SVDReset_Cross(SVD svd)
311
{
312
  PetscErrorCode ierr;
313
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
314
 
315
  PetscFunctionBegin;
316
  ierr = EPSReset(cross->eps);CHKERRQ(ierr);
317
  ierr = MatDestroy(&cross->mat);CHKERRQ(ierr);
318
  ierr = VecDestroy(&cross->w);CHKERRQ(ierr);
319
  ierr = VecDestroy(&cross->diag);CHKERRQ(ierr);
320
  PetscFunctionReturn(0);
321
}
322
 
323
#undef __FUNCT__  
2324 jroman 324
#define __FUNCT__ "SVDDestroy_Cross"
325
PetscErrorCode SVDDestroy_Cross(SVD svd)
1324 slepc 326
{
327
  PetscErrorCode ierr;
2350 jroman 328
  SVD_CROSS      *cross = (SVD_CROSS*)svd->data;
1324 slepc 329
 
330
  PetscFunctionBegin;
2308 jroman 331
  ierr = EPSDestroy(&cross->eps);CHKERRQ(ierr);
1396 slepc 332
  ierr = PetscFree(svd->data);CHKERRQ(ierr);
1925 jroman 333
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossSetEPS_C","",PETSC_NULL);CHKERRQ(ierr);
334
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossGetEPS_C","",PETSC_NULL);CHKERRQ(ierr);
1324 slepc 335
  PetscFunctionReturn(0);
336
}
337
 
338
EXTERN_C_BEGIN
339
#undef __FUNCT__  
2324 jroman 340
#define __FUNCT__ "SVDCreate_Cross"
341
PetscErrorCode SVDCreate_Cross(SVD svd)
1324 slepc 342
{
343
  PetscErrorCode ierr;
344
  SVD_CROSS      *cross;
345
  ST             st;
346
 
347
  PetscFunctionBegin;
2329 jroman 348
  ierr = PetscNewLog(svd,SVD_CROSS,&cross);CHKERRQ(ierr);
2350 jroman 349
  svd->data                = (void*)cross;
2324 jroman 350
  svd->ops->solve          = SVDSolve_Cross;
351
  svd->ops->setup          = SVDSetUp_Cross;
352
  svd->ops->setfromoptions = SVDSetFromOptions_Cross;
353
  svd->ops->destroy        = SVDDestroy_Cross;
2350 jroman 354
  svd->ops->reset          = SVDReset_Cross;
2324 jroman 355
  svd->ops->view           = SVDView_Cross;
356
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossSetEPS_C","SVDCrossSetEPS_Cross",SVDCrossSetEPS_Cross);CHKERRQ(ierr);
357
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossGetEPS_C","SVDCrossGetEPS_Cross",SVDCrossGetEPS_Cross);CHKERRQ(ierr);
1324 slepc 358
 
1422 slepc 359
  ierr = EPSCreate(((PetscObject)svd)->comm,&cross->eps);CHKERRQ(ierr);
360
  ierr = EPSSetOptionsPrefix(cross->eps,((PetscObject)svd)->prefix);CHKERRQ(ierr);
1324 slepc 361
  ierr = EPSAppendOptionsPrefix(cross->eps,"svd_");CHKERRQ(ierr);
1532 slepc 362
  ierr = PetscObjectIncrementTabLevel((PetscObject)cross->eps,(PetscObject)svd,1);CHKERRQ(ierr);  
2327 jroman 363
  ierr = PetscLogObjectParent(svd,cross->eps);CHKERRQ(ierr);
2449 eromero 364
  if (!svd->ip) { ierr = SVDGetIP(svd,&svd->ip);CHKERRQ(ierr); }
1345 slepc 365
  ierr = EPSSetIP(cross->eps,svd->ip);CHKERRQ(ierr);
1324 slepc 366
  ierr = EPSSetWhichEigenpairs(cross->eps,EPS_LARGEST_REAL);CHKERRQ(ierr);
2324 jroman 367
  ierr = EPSMonitorSet(cross->eps,SVDMonitor_Cross,svd,PETSC_NULL);CHKERRQ(ierr);
1324 slepc 368
  ierr = EPSGetST(cross->eps,&st);CHKERRQ(ierr);
1940 jroman 369
  ierr = STSetMatMode(st,ST_MATMODE_SHELL);CHKERRQ(ierr);
1324 slepc 370
  cross->mat = PETSC_NULL;
371
  cross->w = PETSC_NULL;
372
  cross->diag = PETSC_NULL;
2024 eromero 373
  cross->setfromoptionscalled = PETSC_FALSE;
1324 slepc 374
  PetscFunctionReturn(0);
375
}
376
EXTERN_C_END