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