Subversion Repositories slepc-dev

Rev

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
2116 eromero 11
   Copyright (c) 2002-2010, Universidad 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
 
1521 slepc 29
#include "private/svdimpl.h"                /*I "slepcsvd.h" I*/
2054 eromero 30
#include "private/epsimpl.h"                /*I "slepceps.h" I*/
1324 slepc 31
#include "slepceps.h"
32
 
33
typedef struct {
2216 jroman 34
  EPS       eps;
35
  PetscBool setfromoptionscalled;
36
  Mat       mat;
37
  Vec       w,diag;
1324 slepc 38
} SVD_CROSS;
39
 
40
#undef __FUNCT__  
41
#define __FUNCT__ "ShellMatMult_CROSS"
42
PetscErrorCode ShellMatMult_CROSS(Mat B,Vec x, Vec y)
43
{
44
  PetscErrorCode ierr;
45
  SVD            svd;
46
  SVD_CROSS      *cross;
47
 
48
  PetscFunctionBegin;
49
  ierr = MatShellGetContext(B,(void**)&svd);CHKERRQ(ierr);
50
  cross = (SVD_CROSS *)svd->data;
51
  ierr = SVDMatMult(svd,PETSC_FALSE,x,cross->w);CHKERRQ(ierr);
52
  ierr = SVDMatMult(svd,PETSC_TRUE,cross->w,y);CHKERRQ(ierr);
53
  PetscFunctionReturn(0);
54
}
55
 
56
#undef __FUNCT__  
57
#define __FUNCT__ "ShellMatGetDiagonal_CROSS"
58
PetscErrorCode ShellMatGetDiagonal_CROSS(Mat B,Vec d)
59
{
60
  PetscErrorCode    ierr;
61
  SVD               svd;
62
  SVD_CROSS         *cross;
63
  PetscInt          N,n,i,j,start,end,ncols;
64
  PetscScalar       *work1,*work2,*diag;
65
  const PetscInt    *cols;
66
  const PetscScalar *vals;
67
 
68
  PetscFunctionBegin;
69
  ierr = MatShellGetContext(B,(void**)&svd);CHKERRQ(ierr);
70
  cross = (SVD_CROSS *)svd->data;
71
  if (!cross->diag) {
72
    /* compute diagonal from rows and store in cross->diag */
73
    ierr = VecDuplicate(d,&cross->diag);CHKERRQ(ierr);
74
    ierr = SVDMatGetSize(svd,PETSC_NULL,&N);CHKERRQ(ierr);
75
    ierr = SVDMatGetLocalSize(svd,PETSC_NULL,&n);CHKERRQ(ierr);
76
    ierr = PetscMalloc(sizeof(PetscScalar)*N,&work1);CHKERRQ(ierr);
77
    ierr = PetscMalloc(sizeof(PetscScalar)*N,&work2);CHKERRQ(ierr);
78
    for (i=0;i<n;i++) work1[i] = work2[i] = 0.0;
79
    if (svd->AT) {
80
      ierr = MatGetOwnershipRange(svd->AT,&start,&end);CHKERRQ(ierr);
81
      for (i=start;i<end;i++) {
82
        ierr = MatGetRow(svd->AT,i,&ncols,PETSC_NULL,&vals);CHKERRQ(ierr);
83
        for (j=0;j<ncols;j++)
84
          work1[i] += vals[j]*vals[j];
85
        ierr = MatRestoreRow(svd->AT,i,&ncols,PETSC_NULL,&vals);CHKERRQ(ierr);
86
      }
87
    } else {
88
      ierr = MatGetOwnershipRange(svd->A,&start,&end);CHKERRQ(ierr);
89
      for (i=start;i<end;i++) {
90
        ierr = MatGetRow(svd->A,i,&ncols,&cols,&vals);CHKERRQ(ierr);
91
        for (j=0;j<ncols;j++)
92
          work1[cols[j]] += vals[j]*vals[j];
93
        ierr = MatRestoreRow(svd->A,i,&ncols,&cols,&vals);CHKERRQ(ierr);
94
      }
95
    }
1422 slepc 96
    ierr = MPI_Allreduce(work1,work2,N,MPIU_SCALAR,MPI_SUM,((PetscObject)svd)->comm);CHKERRQ(ierr);
1324 slepc 97
    ierr = VecGetOwnershipRange(cross->diag,&start,&end);CHKERRQ(ierr);
98
    ierr = VecGetArray(cross->diag,&diag);CHKERRQ(ierr);
99
    for (i=start;i<end;i++)
100
      diag[i-start] = work2[i];
101
    ierr = VecRestoreArray(cross->diag,&diag);CHKERRQ(ierr);
102
    ierr = PetscFree(work1);CHKERRQ(ierr);
103
    ierr = PetscFree(work2);CHKERRQ(ierr);
104
  }
105
  ierr = VecCopy(cross->diag,d);CHKERRQ(ierr);
106
  PetscFunctionReturn(0);
107
}
108
 
109
#undef __FUNCT__  
110
#define __FUNCT__ "SVDSetUp_CROSS"
111
PetscErrorCode SVDSetUp_CROSS(SVD svd)
112
{
113
  PetscErrorCode    ierr;
114
  SVD_CROSS         *cross = (SVD_CROSS *)svd->data;
2080 eromero 115
  PetscInt          n,i;
2216 jroman 116
  PetscBool         trackall;
1324 slepc 117
 
118
  PetscFunctionBegin;
119
  if (cross->mat) {
120
     ierr = MatDestroy(cross->mat);CHKERRQ(ierr);
121
     ierr = VecDestroy(cross->w);CHKERRQ(ierr);
122
  }
123
  if (cross->diag) {
124
     ierr = VecDestroy(cross->diag);CHKERRQ(ierr);
125
  }
126
 
127
  ierr = SVDMatGetLocalSize(svd,PETSC_NULL,&n);CHKERRQ(ierr);
1422 slepc 128
  ierr = MatCreateShell(((PetscObject)svd)->comm,n,n,PETSC_DETERMINE,PETSC_DETERMINE,svd,&cross->mat);CHKERRQ(ierr);
1324 slepc 129
  ierr = MatShellSetOperation(cross->mat,MATOP_MULT,(void(*)(void))ShellMatMult_CROSS);CHKERRQ(ierr);  
130
  ierr = MatShellSetOperation(cross->mat,MATOP_GET_DIAGONAL,(void(*)(void))ShellMatGetDiagonal_CROSS);CHKERRQ(ierr);  
131
  ierr = SVDMatGetVecs(svd,PETSC_NULL,&cross->w);CHKERRQ(ierr);
132
 
133
  ierr = EPSSetOperators(cross->eps,cross->mat,PETSC_NULL);CHKERRQ(ierr);
134
  ierr = EPSSetProblemType(cross->eps,EPS_HEP);CHKERRQ(ierr);
1406 slepc 135
  ierr = EPSSetWhichEigenpairs(cross->eps,svd->which == SVD_LARGEST ? EPS_LARGEST_REAL : EPS_SMALLEST_REAL);CHKERRQ(ierr);
1575 slepc 136
  ierr = EPSSetDimensions(cross->eps,svd->nsv,svd->ncv,svd->mpd);CHKERRQ(ierr);
1324 slepc 137
  ierr = EPSSetTolerances(cross->eps,svd->tol,svd->max_it);CHKERRQ(ierr);
2055 eromero 138
  /* Transfer the trackall option from svd to eps */
139
  ierr = SVDGetTrackAll(svd,&trackall);CHKERRQ(ierr);
140
  ierr = EPSSetTrackAll(cross->eps,trackall);CHKERRQ(ierr);
2177 jroman 141
  if (cross->setfromoptionscalled) {
2024 eromero 142
    ierr = EPSSetFromOptions(cross->eps);CHKERRQ(ierr);
143
    cross->setfromoptionscalled = PETSC_FALSE;
144
  }
1324 slepc 145
  ierr = EPSSetUp(cross->eps);CHKERRQ(ierr);
1575 slepc 146
  ierr = EPSGetDimensions(cross->eps,PETSC_NULL,&svd->ncv,&svd->mpd);CHKERRQ(ierr);
1324 slepc 147
  ierr = EPSGetTolerances(cross->eps,&svd->tol,&svd->max_it);CHKERRQ(ierr);
2063 eromero 148
  /* Transfer the initial space from svd to eps */
149
  if (svd->nini < 0) {
150
    ierr = EPSSetInitialSpace(cross->eps,-svd->nini,svd->IS);CHKERRQ(ierr);
2080 eromero 151
    for(i=0; i<-svd->nini; i++) {
152
      ierr = VecDestroy(svd->IS[i]);CHKERRQ(ierr);
153
    }
154
    ierr = PetscFree(svd->IS);CHKERRQ(ierr);
155
    svd->nini = 0;
2063 eromero 156
  }
1324 slepc 157
  PetscFunctionReturn(0);
158
}
159
 
160
#undef __FUNCT__  
161
#define __FUNCT__ "SVDSolve_CROSS"
162
PetscErrorCode SVDSolve_CROSS(SVD svd)
163
{
164
  PetscErrorCode ierr;
165
  SVD_CROSS      *cross = (SVD_CROSS *)svd->data;
1504 slepc 166
  PetscInt       i;
1324 slepc 167
  PetscScalar    sigma;
168
 
169
  PetscFunctionBegin;
170
  ierr = EPSSolve(cross->eps);CHKERRQ(ierr);
171
  ierr = EPSGetConverged(cross->eps,&svd->nconv);CHKERRQ(ierr);
172
  ierr = EPSGetIterationNumber(cross->eps,&svd->its);CHKERRQ(ierr);
173
  ierr = EPSGetConvergedReason(cross->eps,(EPSConvergedReason*)&svd->reason);CHKERRQ(ierr);
174
  for (i=0;i<svd->nconv;i++) {
175
    ierr = EPSGetEigenpair(cross->eps,i,&sigma,PETSC_NULL,svd->V[i],PETSC_NULL);CHKERRQ(ierr);
176
    svd->sigma[i] = sqrt(PetscRealPart(sigma));
177
  }
178
  PetscFunctionReturn(0);
179
}
180
 
181
#undef __FUNCT__  
182
#define __FUNCT__ "SVDMonitor_CROSS"
1504 slepc 183
PetscErrorCode SVDMonitor_CROSS(EPS eps,PetscInt its,PetscInt nconv,PetscScalar *eigr,PetscScalar *eigi,PetscReal *errest,PetscInt nest,void *ctx)
1324 slepc 184
{
2054 eromero 185
  PetscInt       i;
186
  SVD            svd = (SVD)ctx;
187
  PetscScalar    er,ei;
188
  PetscErrorCode ierr;
1324 slepc 189
 
190
  PetscFunctionBegin;
191
  for (i=0;i<nest;i++) {
2054 eromero 192
    er = eigr[i]; ei = eigi[i];
193
    ierr = STBackTransform(eps->OP, 1, &er, &ei); CHKERRQ(ierr);
194
    svd->sigma[i] = sqrt(PetscRealPart(er));
1324 slepc 195
    svd->errest[i] = errest[i];
196
  }
197
  SVDMonitor(svd,its,nconv,svd->sigma,svd->errest,nest);
198
  PetscFunctionReturn(0);
199
}
200
 
201
#undef __FUNCT__  
202
#define __FUNCT__ "SVDSetFromOptions_CROSS"
203
PetscErrorCode SVDSetFromOptions_CROSS(SVD svd)
204
{
205
  SVD_CROSS      *cross = (SVD_CROSS *)svd->data;
206
 
207
  PetscFunctionBegin;
2024 eromero 208
  cross->setfromoptionscalled = PETSC_TRUE;
1324 slepc 209
  PetscFunctionReturn(0);
210
}
211
 
212
EXTERN_C_BEGIN
213
#undef __FUNCT__  
214
#define __FUNCT__ "SVDCrossSetEPS_CROSS"
215
PetscErrorCode SVDCrossSetEPS_CROSS(SVD svd,EPS eps)
216
{
217
  PetscErrorCode ierr;
218
  SVD_CROSS      *cross = (SVD_CROSS *)svd->data;
219
 
220
  PetscFunctionBegin;
2213 jroman 221
  PetscValidHeaderSpecific(eps,EPS_CLASSID,2);
1324 slepc 222
  PetscCheckSameComm(svd,1,eps,2);
223
  ierr = PetscObjectReference((PetscObject)eps);CHKERRQ(ierr);
224
  ierr = EPSDestroy(cross->eps);CHKERRQ(ierr);  
225
  cross->eps = eps;
226
  svd->setupcalled = 0;
227
  PetscFunctionReturn(0);
228
}
229
EXTERN_C_END
230
 
231
#undef __FUNCT__  
232
#define __FUNCT__ "SVDCrossSetEPS"
233
/*@
1325 slepc 234
   SVDCrossSetEPS - Associate an eigensolver object (EPS) to the
1324 slepc 235
   singular value solver.
236
 
237
   Collective on SVD
238
 
239
   Input Parameters:
240
+  svd - singular value solver
241
-  eps - the eigensolver object
242
 
243
   Level: advanced
244
 
245
.seealso: SVDCrossGetEPS()
246
@*/
247
PetscErrorCode SVDCrossSetEPS(SVD svd,EPS eps)
248
{
2221 jroman 249
  PetscErrorCode ierr;
1324 slepc 250
 
251
  PetscFunctionBegin;
2213 jroman 252
  PetscValidHeaderSpecific(svd,SVD_CLASSID,1);
2221 jroman 253
  PetscValidHeaderSpecific(eps,EPS_CLASSID,2);
254
  ierr = PetscTryMethod(svd,"SVDCrossSetEPS_C",(SVD,EPS),(svd,eps));CHKERRQ(ierr);
1324 slepc 255
  PetscFunctionReturn(0);
256
}
257
 
258
EXTERN_C_BEGIN
259
#undef __FUNCT__  
260
#define __FUNCT__ "SVDCrossGetEPS_CROSS"
261
PetscErrorCode SVDCrossGetEPS_CROSS(SVD svd,EPS *eps)
262
{
263
  SVD_CROSS *cross = (SVD_CROSS *)svd->data;
264
 
265
  PetscFunctionBegin;
266
  PetscValidPointer(eps,2);
267
  *eps = cross->eps;
268
  PetscFunctionReturn(0);
269
}
270
EXTERN_C_END
271
 
272
#undef __FUNCT__  
273
#define __FUNCT__ "SVDCrossGetEPS"
2061 eromero 274
/*@
1324 slepc 275
   SVDCrossGetEPS - Retrieve the eigensolver object (EPS) associated
276
   to the singular value solver.
277
 
278
   Not Collective
279
 
1325 slepc 280
   Input Parameter:
1324 slepc 281
.  svd - singular value solver
282
 
283
   Output Parameter:
284
.  eps - the eigensolver object
285
 
286
   Level: advanced
287
 
288
.seealso: SVDCrossSetEPS()
289
@*/
290
PetscErrorCode SVDCrossGetEPS(SVD svd,EPS *eps)
291
{
2221 jroman 292
  PetscErrorCode ierr;
1324 slepc 293
 
294
  PetscFunctionBegin;
2213 jroman 295
  PetscValidHeaderSpecific(svd,SVD_CLASSID,1);
2221 jroman 296
  ierr = PetscTryMethod(svd,"SVDCrossGetEPS_C",(SVD,EPS*),(svd,eps));CHKERRQ(ierr);
1324 slepc 297
  PetscFunctionReturn(0);
298
}
299
 
300
#undef __FUNCT__  
301
#define __FUNCT__ "SVDView_CROSS"
302
PetscErrorCode SVDView_CROSS(SVD svd,PetscViewer viewer)
303
{
304
  PetscErrorCode ierr;
305
  SVD_CROSS      *cross = (SVD_CROSS *)svd->data;
306
 
307
  PetscFunctionBegin;
308
  ierr = EPSView(cross->eps,viewer);CHKERRQ(ierr);
309
  PetscFunctionReturn(0);
310
}
311
 
312
#undef __FUNCT__  
313
#define __FUNCT__ "SVDDestroy_CROSS"
314
PetscErrorCode SVDDestroy_CROSS(SVD svd)
315
{
316
  PetscErrorCode ierr;
317
  SVD_CROSS      *cross = (SVD_CROSS *)svd->data;
318
 
319
  PetscFunctionBegin;
320
  ierr = EPSDestroy(cross->eps);CHKERRQ(ierr);
321
  if (cross->mat) {
322
    ierr = MatDestroy(cross->mat);CHKERRQ(ierr);
323
    ierr = VecDestroy(cross->w);CHKERRQ(ierr);
324
  }
325
  if (cross->diag) {
326
    ierr = VecDestroy(cross->diag);CHKERRQ(ierr);
327
  }
1396 slepc 328
  ierr = PetscFree(svd->data);CHKERRQ(ierr);
1925 jroman 329
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossSetEPS_C","",PETSC_NULL);CHKERRQ(ierr);
330
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossGetEPS_C","",PETSC_NULL);CHKERRQ(ierr);
1324 slepc 331
  PetscFunctionReturn(0);
332
}
333
 
334
EXTERN_C_BEGIN
335
#undef __FUNCT__  
336
#define __FUNCT__ "SVDCreate_CROSS"
337
PetscErrorCode SVDCreate_CROSS(SVD svd)
338
{
339
  PetscErrorCode ierr;
340
  SVD_CROSS      *cross;
341
  ST             st;
342
 
343
  PetscFunctionBegin;
344
  ierr = PetscNew(SVD_CROSS,&cross);CHKERRQ(ierr);
345
  PetscLogObjectMemory(svd,sizeof(SVD_CROSS));
346
  svd->data                = (void *)cross;
347
  svd->ops->solve          = SVDSolve_CROSS;
348
  svd->ops->setup          = SVDSetUp_CROSS;
349
  svd->ops->setfromoptions = SVDSetFromOptions_CROSS;
350
  svd->ops->destroy        = SVDDestroy_CROSS;
351
  svd->ops->view           = SVDView_CROSS;
352
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossSetEPS_C","SVDCrossSetEPS_CROSS",SVDCrossSetEPS_CROSS);CHKERRQ(ierr);
353
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossGetEPS_C","SVDCrossGetEPS_CROSS",SVDCrossGetEPS_CROSS);CHKERRQ(ierr);
354
 
1422 slepc 355
  ierr = EPSCreate(((PetscObject)svd)->comm,&cross->eps);CHKERRQ(ierr);
356
  ierr = EPSSetOptionsPrefix(cross->eps,((PetscObject)svd)->prefix);CHKERRQ(ierr);
1324 slepc 357
  ierr = EPSAppendOptionsPrefix(cross->eps,"svd_");CHKERRQ(ierr);
1532 slepc 358
  ierr = PetscObjectIncrementTabLevel((PetscObject)cross->eps,(PetscObject)svd,1);CHKERRQ(ierr);  
1324 slepc 359
  PetscLogObjectParent(svd,cross->eps);
1345 slepc 360
  ierr = EPSSetIP(cross->eps,svd->ip);CHKERRQ(ierr);
1324 slepc 361
  ierr = EPSSetWhichEigenpairs(cross->eps,EPS_LARGEST_REAL);CHKERRQ(ierr);
1331 slepc 362
  ierr = EPSMonitorSet(cross->eps,SVDMonitor_CROSS,svd,PETSC_NULL);CHKERRQ(ierr);
1324 slepc 363
  ierr = EPSGetST(cross->eps,&st);CHKERRQ(ierr);
1940 jroman 364
  ierr = STSetMatMode(st,ST_MATMODE_SHELL);CHKERRQ(ierr);
1324 slepc 365
  cross->mat = PETSC_NULL;
366
  cross->w = PETSC_NULL;
367
  cross->diag = PETSC_NULL;
2024 eromero 368
  cross->setfromoptionscalled = PETSC_FALSE;
1324 slepc 369
  PetscFunctionReturn(0);
370
}
371
EXTERN_C_END