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
11
   Copyright (c) 2002-2009, 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 {
34
  EPS eps;
2024 eromero 35
  PetscTruth setfromoptionscalled;
1324 slepc 36
  Mat mat;
37
  Vec w,diag;
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;
2055 eromero 116
  PetscTruth        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);
2024 eromero 141
  if (cross->setfromoptionscalled == PETSC_TRUE) {
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;
221
  PetscValidHeaderSpecific(eps,EPS_COOKIE,2);
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
{
249
  PetscErrorCode ierr, (*f)(SVD,EPS eps);
250
 
251
  PetscFunctionBegin;
252
  PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
253
  ierr = PetscObjectQueryFunction((PetscObject)svd,"SVDCrossSetEPS_C",(void (**)())&f);CHKERRQ(ierr);
254
  if (f) {
255
    ierr = (*f)(svd,eps);CHKERRQ(ierr);
256
  }
257
  PetscFunctionReturn(0);
258
}
259
 
260
EXTERN_C_BEGIN
261
#undef __FUNCT__  
262
#define __FUNCT__ "SVDCrossGetEPS_CROSS"
263
PetscErrorCode SVDCrossGetEPS_CROSS(SVD svd,EPS *eps)
264
{
265
  SVD_CROSS *cross = (SVD_CROSS *)svd->data;
266
 
267
  PetscFunctionBegin;
268
  PetscValidPointer(eps,2);
269
  *eps = cross->eps;
270
  PetscFunctionReturn(0);
271
}
272
EXTERN_C_END
273
 
274
#undef __FUNCT__  
275
#define __FUNCT__ "SVDCrossGetEPS"
2061 eromero 276
/*@
1324 slepc 277
   SVDCrossGetEPS - Retrieve the eigensolver object (EPS) associated
278
   to the singular value solver.
279
 
280
   Not Collective
281
 
1325 slepc 282
   Input Parameter:
1324 slepc 283
.  svd - singular value solver
284
 
285
   Output Parameter:
286
.  eps - the eigensolver object
287
 
288
   Level: advanced
289
 
290
.seealso: SVDCrossSetEPS()
291
@*/
292
PetscErrorCode SVDCrossGetEPS(SVD svd,EPS *eps)
293
{
294
  PetscErrorCode ierr, (*f)(SVD,EPS *eps);
295
 
296
  PetscFunctionBegin;
297
  PetscValidHeaderSpecific(svd,SVD_COOKIE,1);
298
  ierr = PetscObjectQueryFunction((PetscObject)svd,"SVDCrossGetEPS_C",(void (**)())&f);CHKERRQ(ierr);
299
  if (f) {
300
    ierr = (*f)(svd,eps);CHKERRQ(ierr);
301
  }
302
  PetscFunctionReturn(0);
303
}
304
 
305
#undef __FUNCT__  
306
#define __FUNCT__ "SVDView_CROSS"
307
PetscErrorCode SVDView_CROSS(SVD svd,PetscViewer viewer)
308
{
309
  PetscErrorCode ierr;
310
  SVD_CROSS      *cross = (SVD_CROSS *)svd->data;
311
 
312
  PetscFunctionBegin;
313
  ierr = EPSView(cross->eps,viewer);CHKERRQ(ierr);
314
  PetscFunctionReturn(0);
315
}
316
 
317
#undef __FUNCT__  
318
#define __FUNCT__ "SVDDestroy_CROSS"
319
PetscErrorCode SVDDestroy_CROSS(SVD svd)
320
{
321
  PetscErrorCode ierr;
322
  SVD_CROSS      *cross = (SVD_CROSS *)svd->data;
323
 
324
  PetscFunctionBegin;
325
  ierr = EPSDestroy(cross->eps);CHKERRQ(ierr);
326
  if (cross->mat) {
327
    ierr = MatDestroy(cross->mat);CHKERRQ(ierr);
328
    ierr = VecDestroy(cross->w);CHKERRQ(ierr);
329
  }
330
  if (cross->diag) {
331
    ierr = VecDestroy(cross->diag);CHKERRQ(ierr);
332
  }
1396 slepc 333
  ierr = PetscFree(svd->data);CHKERRQ(ierr);
1925 jroman 334
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossSetEPS_C","",PETSC_NULL);CHKERRQ(ierr);
335
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossGetEPS_C","",PETSC_NULL);CHKERRQ(ierr);
1324 slepc 336
  PetscFunctionReturn(0);
337
}
338
 
339
EXTERN_C_BEGIN
340
#undef __FUNCT__  
341
#define __FUNCT__ "SVDCreate_CROSS"
342
PetscErrorCode SVDCreate_CROSS(SVD svd)
343
{
344
  PetscErrorCode ierr;
345
  SVD_CROSS      *cross;
346
  ST             st;
347
 
348
  PetscFunctionBegin;
349
  ierr = PetscNew(SVD_CROSS,&cross);CHKERRQ(ierr);
350
  PetscLogObjectMemory(svd,sizeof(SVD_CROSS));
351
  svd->data                = (void *)cross;
352
  svd->ops->solve          = SVDSolve_CROSS;
353
  svd->ops->setup          = SVDSetUp_CROSS;
354
  svd->ops->setfromoptions = SVDSetFromOptions_CROSS;
355
  svd->ops->destroy        = SVDDestroy_CROSS;
356
  svd->ops->view           = SVDView_CROSS;
357
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossSetEPS_C","SVDCrossSetEPS_CROSS",SVDCrossSetEPS_CROSS);CHKERRQ(ierr);
358
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)svd,"SVDCrossGetEPS_C","SVDCrossGetEPS_CROSS",SVDCrossGetEPS_CROSS);CHKERRQ(ierr);
359
 
1422 slepc 360
  ierr = EPSCreate(((PetscObject)svd)->comm,&cross->eps);CHKERRQ(ierr);
361
  ierr = EPSSetOptionsPrefix(cross->eps,((PetscObject)svd)->prefix);CHKERRQ(ierr);
1324 slepc 362
  ierr = EPSAppendOptionsPrefix(cross->eps,"svd_");CHKERRQ(ierr);
1532 slepc 363
  ierr = PetscObjectIncrementTabLevel((PetscObject)cross->eps,(PetscObject)svd,1);CHKERRQ(ierr);  
1324 slepc 364
  PetscLogObjectParent(svd,cross->eps);
1345 slepc 365
  ierr = EPSSetIP(cross->eps,svd->ip);CHKERRQ(ierr);
1324 slepc 366
  ierr = EPSSetWhichEigenpairs(cross->eps,EPS_LARGEST_REAL);CHKERRQ(ierr);
1331 slepc 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