Subversion Repositories slepc-dev

Rev

Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1887 jroman 1
/*
2
      QEP routines related to problem setup.
3
 
4
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5
   SLEPc - Scalable Library for Eigenvalue Problem Computations
2575 eromero 6
   Copyright (c) 2002-2011, Universitat Politecnica de Valencia, Spain
1887 jroman 7
 
8
   This file is part of SLEPc.
9
 
10
   SLEPc is free software: you can redistribute it and/or modify it under  the
11
   terms of version 3 of the GNU Lesser General Public License as published by
12
   the Free Software Foundation.
13
 
14
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
15
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
16
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
17
   more details.
18
 
19
   You  should have received a copy of the GNU Lesser General  Public  License
20
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
21
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22
*/
23
 
2729 jroman 24
#include <slepc-private/qepimpl.h>       /*I "slepcqep.h" I*/
25
#include <slepc-private/ipimpl.h>
1887 jroman 26
 
27
#undef __FUNCT__  
28
#define __FUNCT__ "QEPSetUp"
29
/*@
30
   QEPSetUp - Sets up all the internal data structures necessary for the
31
   execution of the QEP solver.
32
 
33
   Collective on QEP
34
 
35
   Input Parameter:
36
.  qep   - solver context
37
 
38
   Notes:
39
   This function need not be called explicitly in most cases, since QEPSolve()
40
   calls it. It can be useful when one wants to measure the set-up time
41
   separately from the solve time.
42
 
43
   Level: advanced
44
 
45
.seealso: QEPCreate(), QEPSolve(), QEPDestroy()
46
@*/
47
PetscErrorCode QEPSetUp(QEP qep)
48
{
49
  PetscErrorCode ierr;
1952 jroman 50
  PetscInt       i,k;
2216 jroman 51
  PetscBool      khas,mhas,lindep;
1952 jroman 52
  PetscReal      knorm,mnorm,norm;
1887 jroman 53
 
54
  PetscFunctionBegin;
2213 jroman 55
  PetscValidHeaderSpecific(qep,QEP_CLASSID,1);
1887 jroman 56
  if (qep->setupcalled) PetscFunctionReturn(0);
57
  ierr = PetscLogEventBegin(QEP_SetUp,qep,0,0,0);CHKERRQ(ierr);
58
 
2412 jroman 59
  /* Set default solver type (QEPSetFromOptions was not called) */
1887 jroman 60
  if (!((PetscObject)qep)->type_name) {
61
    ierr = QEPSetType(qep,QEPLINEAR);CHKERRQ(ierr);
62
  }
2412 jroman 63
  if (!qep->ip) { ierr = QEPGetIP(qep,&qep->ip);CHKERRQ(ierr); }
64
  if (!((PetscObject)qep->ip)->type_name) {
65
    ierr = IPSetDefaultType_Private(qep->ip);CHKERRQ(ierr);
66
  }
2458 eromero 67
  if (!((PetscObject)qep->rand)->type_name) {
68
    ierr = PetscRandomSetFromOptions(qep->rand);CHKERRQ(ierr);
69
  }
1887 jroman 70
 
71
  /* Check matrices */
2762 jroman 72
  if (!qep->M || !qep->C || !qep->K) SETERRQ(((PetscObject)qep)->comm,PETSC_ERR_ARG_WRONGSTATE,"QEPSetOperators must be called first");
1887 jroman 73
 
1930 jroman 74
  /* Set problem dimensions */
75
  ierr = MatGetSize(qep->M,&qep->n,PETSC_NULL);CHKERRQ(ierr);
76
  ierr = MatGetLocalSize(qep->M,&qep->nloc,PETSC_NULL);CHKERRQ(ierr);
2507 jroman 77
  ierr = VecDestroy(&qep->t);CHKERRQ(ierr);
2410 jroman 78
  ierr = SlepcMatGetVecsTemplate(qep->M,&qep->t,PETSC_NULL);CHKERRQ(ierr);
1930 jroman 79
 
1907 jroman 80
  /* Set default problem type */
81
  if (!qep->problem_type) {
82
    ierr = QEPSetProblemType(qep,QEP_GENERAL);CHKERRQ(ierr);
83
  }
84
 
1918 jroman 85
  /* Compute scaling factor if not set by user */
86
  if (qep->sfactor==0.0) {
87
    ierr = MatHasOperation(qep->K,MATOP_NORM,&khas);CHKERRQ(ierr);
88
    ierr = MatHasOperation(qep->M,MATOP_NORM,&mhas);CHKERRQ(ierr);
89
    if (khas && mhas) {
90
      ierr = MatNorm(qep->K,NORM_INFINITY,&knorm);CHKERRQ(ierr);
91
      ierr = MatNorm(qep->M,NORM_INFINITY,&mnorm);CHKERRQ(ierr);
2473 jroman 92
      qep->sfactor = PetscSqrtReal(knorm/mnorm);
1918 jroman 93
    }
94
    else qep->sfactor = 1.0;
95
  }
96
 
1887 jroman 97
  /* Call specific solver setup */
98
  ierr = (*qep->ops->setup)(qep);CHKERRQ(ierr);
99
 
2622 jroman 100
  /* set tolerance if not yet set */
101
  if (qep->tol==PETSC_DEFAULT) qep->tol = SLEPC_DEFAULT_TOL;
102
 
2762 jroman 103
  if (qep->ncv > 2*qep->n) SETERRQ(((PetscObject)qep)->comm,PETSC_ERR_ARG_OUTOFRANGE,"ncv must be twice the problem size at most");
104
  if (qep->nev > qep->ncv) SETERRQ(((PetscObject)qep)->comm,PETSC_ERR_ARG_OUTOFRANGE,"nev bigger than ncv");
1887 jroman 105
 
1952 jroman 106
  /* process initial vectors */
107
  if (qep->nini<0) {
108
    qep->nini = -qep->nini;
2219 jroman 109
    if (qep->nini>qep->ncv) SETERRQ(((PetscObject)qep)->comm,1,"The number of initial vectors is larger than ncv");
1952 jroman 110
    k = 0;
111
    for (i=0;i<qep->nini;i++) {
112
      ierr = VecCopy(qep->IS[i],qep->V[k]);CHKERRQ(ierr);
2305 jroman 113
      ierr = VecDestroy(&qep->IS[i]);CHKERRQ(ierr);
1952 jroman 114
      ierr = IPOrthogonalize(qep->ip,0,PETSC_NULL,k,PETSC_NULL,qep->V,qep->V[k],PETSC_NULL,&norm,&lindep);CHKERRQ(ierr);
2730 jroman 115
      if (norm==0.0 || lindep) { ierr = PetscInfo(qep,"Linearly dependent initial vector found, removing...\n");CHKERRQ(ierr); }
1952 jroman 116
      else {
117
        ierr = VecScale(qep->V[k],1.0/norm);CHKERRQ(ierr);
118
        k++;
119
      }
120
    }
121
    qep->nini = k;
122
    ierr = PetscFree(qep->IS);CHKERRQ(ierr);
123
  }
124
  if (qep->ninil<0) {
2730 jroman 125
    if (!qep->leftvecs) { ierr = PetscInfo(qep,"Ignoring initial left vectors\n");CHKERRQ(ierr); }
1952 jroman 126
    else {
127
      qep->ninil = -qep->ninil;
2219 jroman 128
      if (qep->ninil>qep->ncv) SETERRQ(((PetscObject)qep)->comm,1,"The number of initial left vectors is larger than ncv");
1952 jroman 129
      k = 0;
130
      for (i=0;i<qep->ninil;i++) {
131
        ierr = VecCopy(qep->ISL[i],qep->W[k]);CHKERRQ(ierr);
2305 jroman 132
        ierr = VecDestroy(&qep->ISL[i]);CHKERRQ(ierr);
1952 jroman 133
        ierr = IPOrthogonalize(qep->ip,0,PETSC_NULL,k,PETSC_NULL,qep->W,qep->W[k],PETSC_NULL,&norm,&lindep);CHKERRQ(ierr);
2730 jroman 134
        if (norm==0.0 || lindep) { ierr = PetscInfo(qep,"Linearly dependent initial left vector found, removing...\n");CHKERRQ(ierr); }
1952 jroman 135
        else {
136
          ierr = VecScale(qep->W[k],1.0/norm);CHKERRQ(ierr);
137
          k++;
138
        }
139
      }
140
      qep->ninil = k;
141
      ierr = PetscFree(qep->ISL);CHKERRQ(ierr);
142
    }
143
  }
1887 jroman 144
  ierr = PetscLogEventEnd(QEP_SetUp,qep,0,0,0);CHKERRQ(ierr);
145
  qep->setupcalled = 1;
146
  PetscFunctionReturn(0);
147
}
148
 
149
#undef __FUNCT__  
150
#define __FUNCT__ "QEPSetOperators"
151
/*@
152
   QEPSetOperators - Sets the matrices associated with the quadratic eigenvalue problem.
153
 
154
   Collective on QEP and Mat
155
 
156
   Input Parameters:
157
+  qep - the eigenproblem solver context
158
.  M   - the first coefficient matrix
159
.  C   - the second coefficient matrix
160
-  K   - the third coefficient matrix
161
 
162
   Notes:
163
   The quadratic eigenproblem is defined as (l^2*M + l*C + K)*x = 0, where l is
164
   the eigenvalue and x is the eigenvector.
165
 
166
   Level: beginner
167
 
168
.seealso: QEPSolve(), QEPGetOperators()
169
@*/
170
PetscErrorCode QEPSetOperators(QEP qep,Mat M,Mat C,Mat K)
171
{
172
  PetscErrorCode ierr;
1902 jroman 173
  PetscInt       m,n,m0;
1887 jroman 174
 
175
  PetscFunctionBegin;
2213 jroman 176
  PetscValidHeaderSpecific(qep,QEP_CLASSID,1);
177
  PetscValidHeaderSpecific(M,MAT_CLASSID,2);
178
  PetscValidHeaderSpecific(C,MAT_CLASSID,3);
179
  PetscValidHeaderSpecific(K,MAT_CLASSID,4);
1887 jroman 180
  PetscCheckSameComm(qep,1,M,2);
1902 jroman 181
  PetscCheckSameComm(qep,1,C,3);
182
  PetscCheckSameComm(qep,1,K,4);
1887 jroman 183
 
184
  /* Check for square matrices */
185
  ierr = MatGetSize(M,&m,&n);CHKERRQ(ierr);
2762 jroman 186
  if (m!=n) SETERRQ(((PetscObject)qep)->comm,1,"M is a non-square matrix");
1902 jroman 187
  m0=m;
1887 jroman 188
  ierr = MatGetSize(C,&m,&n);CHKERRQ(ierr);
2762 jroman 189
  if (m!=n) SETERRQ(((PetscObject)qep)->comm,1,"C is a non-square matrix");
190
  if (m!=m0) SETERRQ(((PetscObject)qep)->comm,1,"Dimensions of M and C do not match");
1887 jroman 191
  ierr = MatGetSize(K,&m,&n);CHKERRQ(ierr);
2762 jroman 192
  if (m!=n) SETERRQ(((PetscObject)qep)->comm,1,"K is a non-square matrix");
193
  if (m!=m0) SETERRQ(((PetscObject)qep)->comm,1,"Dimensions of M and K do not match");
1887 jroman 194
 
195
  /* Store a copy of the matrices */
2361 jroman 196
  if (qep->setupcalled) { ierr = QEPReset(qep);CHKERRQ(ierr); }
1887 jroman 197
  ierr = PetscObjectReference((PetscObject)M);CHKERRQ(ierr);
2305 jroman 198
  ierr = MatDestroy(&qep->M);CHKERRQ(ierr);
1887 jroman 199
  qep->M = M;
200
  ierr = PetscObjectReference((PetscObject)C);CHKERRQ(ierr);
2305 jroman 201
  ierr = MatDestroy(&qep->C);CHKERRQ(ierr);
1887 jroman 202
  qep->C = C;
203
  ierr = PetscObjectReference((PetscObject)K);CHKERRQ(ierr);
2305 jroman 204
  ierr = MatDestroy(&qep->K);CHKERRQ(ierr);
1887 jroman 205
  qep->K = K;
206
  PetscFunctionReturn(0);
207
}
208
 
209
#undef __FUNCT__
210
#define __FUNCT__ "QEPGetOperators"
211
/*@
212
   QEPGetOperators - Gets the matrices associated with the quadratic eigensystem.
213
 
214
   Collective on QEP and Mat
215
 
216
   Input Parameter:
217
.  qep - the QEP context
218
 
219
   Output Parameters:
220
+  M   - the first coefficient matrix
221
.  C   - the second coefficient matrix
222
-  K   - the third coefficient matrix
223
 
224
   Level: intermediate
225
 
226
.seealso: QEPSolve(), QEPSetOperators()
227
@*/
2331 jroman 228
PetscErrorCode QEPGetOperators(QEP qep,Mat *M,Mat *C,Mat *K)
1887 jroman 229
{
230
  PetscFunctionBegin;
2213 jroman 231
  PetscValidHeaderSpecific(qep,QEP_CLASSID,1);
1887 jroman 232
  if (M) { PetscValidPointer(M,2); *M = qep->M; }
233
  if (C) { PetscValidPointer(C,3); *C = qep->C; }
234
  if (K) { PetscValidPointer(K,4); *K = qep->K; }
235
  PetscFunctionReturn(0);
236
}
237
 
1952 jroman 238
#undef __FUNCT__  
239
#define __FUNCT__ "QEPSetInitialSpace"
240
/*@
241
   QEPSetInitialSpace - Specify a basis of vectors that constitute the initial
242
   space, that is, the subspace from which the solver starts to iterate.
243
 
244
   Collective on QEP and Vec
245
 
246
   Input Parameter:
247
+  qep   - the quadratic eigensolver context
248
.  n     - number of vectors
249
-  is    - set of basis vectors of the initial space
250
 
251
   Notes:
252
   Some solvers start to iterate on a single vector (initial vector). In that case,
253
   the other vectors are ignored.
254
 
255
   These vectors do not persist from one QEPSolve() call to the other, so the
256
   initial space should be set every time.
257
 
258
   The vectors do not need to be mutually orthonormal, since they are explicitly
259
   orthonormalized internally.
260
 
261
   Common usage of this function is when the user can provide a rough approximation
262
   of the wanted eigenspace. Then, convergence may be faster.
263
 
264
   Level: intermediate
265
 
266
.seealso: QEPSetInitialSpaceLeft()
267
@*/
268
PetscErrorCode QEPSetInitialSpace(QEP qep,PetscInt n,Vec *is)
269
{
270
  PetscErrorCode ierr;
271
  PetscInt       i;
272
 
273
  PetscFunctionBegin;
2213 jroman 274
  PetscValidHeaderSpecific(qep,QEP_CLASSID,1);
2326 jroman 275
  PetscValidLogicalCollectiveInt(qep,n,2);
2214 jroman 276
  if (n<0) SETERRQ(((PetscObject)qep)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Argument n cannot be negative");
1952 jroman 277
 
278
  /* free previous non-processed vectors */
279
  if (qep->nini<0) {
280
    for (i=0;i<-qep->nini;i++) {
2305 jroman 281
      ierr = VecDestroy(&qep->IS[i]);CHKERRQ(ierr);
1952 jroman 282
    }
283
    ierr = PetscFree(qep->IS);CHKERRQ(ierr);
284
  }
285
 
286
  /* get references of passed vectors */
287
  ierr = PetscMalloc(n*sizeof(Vec),&qep->IS);CHKERRQ(ierr);
288
  for (i=0;i<n;i++) {
289
    ierr = PetscObjectReference((PetscObject)is[i]);CHKERRQ(ierr);
290
    qep->IS[i] = is[i];
291
  }
292
 
293
  qep->nini = -n;
294
  qep->setupcalled = 0;
295
  PetscFunctionReturn(0);
296
}
297
 
298
#undef __FUNCT__  
299
#define __FUNCT__ "QEPSetInitialSpaceLeft"
300
/*@
301
   QEPSetInitialSpaceLeft - Specify a basis of vectors that constitute the initial
302
   left space, that is, the subspace from which the solver starts to iterate for
303
   building the left subspace (in methods that work with two subspaces).
304
 
305
   Collective on QEP and Vec
306
 
307
   Input Parameter:
308
+  qep   - the quadratic eigensolver context
309
.  n     - number of vectors
310
-  is    - set of basis vectors of the initial left space
311
 
312
   Notes:
313
   Some solvers start to iterate on a single vector (initial left vector). In that case,
314
   the other vectors are ignored.
315
 
316
   These vectors do not persist from one QEPSolve() call to the other, so the
317
   initial left space should be set every time.
318
 
319
   The vectors do not need to be mutually orthonormal, since they are explicitly
320
   orthonormalized internally.
321
 
322
   Common usage of this function is when the user can provide a rough approximation
323
   of the wanted left eigenspace. Then, convergence may be faster.
324
 
325
   Level: intermediate
326
 
327
.seealso: QEPSetInitialSpace()
328
@*/
329
PetscErrorCode QEPSetInitialSpaceLeft(QEP qep,PetscInt n,Vec *is)
330
{
331
  PetscErrorCode ierr;
332
  PetscInt       i;
333
 
334
  PetscFunctionBegin;
2213 jroman 335
  PetscValidHeaderSpecific(qep,QEP_CLASSID,1);
2326 jroman 336
  PetscValidLogicalCollectiveInt(qep,n,2);
2214 jroman 337
  if (n<0) SETERRQ(((PetscObject)qep)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Argument n cannot be negative");
1952 jroman 338
 
339
  /* free previous non-processed vectors */
340
  if (qep->ninil<0) {
341
    for (i=0;i<-qep->ninil;i++) {
2305 jroman 342
      ierr = VecDestroy(&qep->ISL[i]);CHKERRQ(ierr);
1952 jroman 343
    }
344
    ierr = PetscFree(qep->ISL);CHKERRQ(ierr);
345
  }
346
 
347
  /* get references of passed vectors */
348
  ierr = PetscMalloc(n*sizeof(Vec),&qep->ISL);CHKERRQ(ierr);
349
  for (i=0;i<n;i++) {
350
    ierr = PetscObjectReference((PetscObject)is[i]);CHKERRQ(ierr);
351
    qep->ISL[i] = is[i];
352
  }
353
 
354
  qep->ninil = -n;
355
  qep->setupcalled = 0;
356
  PetscFunctionReturn(0);
357
}
358
 
2369 jroman 359
#undef __FUNCT__  
360
#define __FUNCT__ "QEPAllocateSolution"
361
/*
362
  QEPAllocateSolution - Allocate memory storage for common variables such
363
  as eigenvalues and eigenvectors. All vectors in V (and W) share a
364
  contiguous chunk of memory.
365
*/
366
PetscErrorCode QEPAllocateSolution(QEP qep)
367
{
368
  PetscErrorCode ierr;
369
 
370
  PetscFunctionBegin;
371
  if (qep->allocated_ncv != qep->ncv) {
372
    ierr = QEPFreeSolution(qep);CHKERRQ(ierr);
373
    ierr = PetscMalloc(qep->ncv*sizeof(PetscScalar),&qep->eigr);CHKERRQ(ierr);
374
    ierr = PetscMalloc(qep->ncv*sizeof(PetscScalar),&qep->eigi);CHKERRQ(ierr);
375
    ierr = PetscMalloc(qep->ncv*sizeof(PetscReal),&qep->errest);CHKERRQ(ierr);
376
    ierr = PetscMalloc(qep->ncv*sizeof(PetscInt),&qep->perm);CHKERRQ(ierr);
2410 jroman 377
    ierr = VecDuplicateVecs(qep->t,qep->ncv,&qep->V);CHKERRQ(ierr);
2369 jroman 378
    qep->allocated_ncv = qep->ncv;
379
  }
380
  PetscFunctionReturn(0);
381
}
382
 
383
#undef __FUNCT__  
384
#define __FUNCT__ "QEPFreeSolution"
385
/*
386
  QEPFreeSolution - Free memory storage. This routine is related to
387
  QEPAllocateSolution().
388
*/
389
PetscErrorCode QEPFreeSolution(QEP qep)
390
{
391
  PetscErrorCode ierr;
392
 
393
  PetscFunctionBegin;
394
  if (qep->allocated_ncv > 0) {
395
    ierr = PetscFree(qep->eigr);CHKERRQ(ierr);
396
    ierr = PetscFree(qep->eigi);CHKERRQ(ierr);
397
    ierr = PetscFree(qep->errest);CHKERRQ(ierr);
398
    ierr = PetscFree(qep->perm);CHKERRQ(ierr);
2410 jroman 399
    ierr = VecDestroyVecs(qep->allocated_ncv,&qep->V);CHKERRQ(ierr);
2369 jroman 400
    qep->allocated_ncv = 0;
401
  }
402
  PetscFunctionReturn(0);
403
}
404