Subversion Repositories slepc-dev

Rev

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

Rev Author Line No. Line
2808 carcamgo 1
/*
2
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3
   SLEPc - Scalable Library for Eigenvalue Problem Computations
4
   Copyright (c) 2002-2011, Universitat Politecnica de Valencia, Spain
5
 
6
   This file is part of SLEPc.
7
 
8
   SLEPc is free software: you can redistribute it and/or modify it under  the
9
   terms of version 3 of the GNU Lesser General Public License as published by
10
   the Free Software Foundation.
11
 
12
   SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
13
   WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
14
   FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
15
   more details.
16
 
17
   You  should have received a copy of the GNU Lesser General  Public  License
18
   along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
19
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
20
*/
21
 
22
#include <slepc-private/psimpl.h>      /*I "slepcps.h" I*/
23
#include <slepcblaslapack.h>
24
 
25
#undef __FUNCT__  
26
#define __FUNCT__ "PSAllocate_GHIEP"
27
PetscErrorCode PSAllocate_GHIEP(PS ps,PetscInt ld)
28
{
29
  PetscErrorCode ierr;
30
 
31
  PetscFunctionBegin;
32
  ierr = PSAllocateMat_Private(ps,PS_MAT_A);CHKERRQ(ierr);
33
  ierr = PSAllocateMat_Private(ps,PS_MAT_Q);CHKERRQ(ierr);
34
  ierr = PSAllocateMatReal_Private(ps,PS_MAT_T);CHKERRQ(ierr);
35
  PetscFunctionReturn(0);
36
}
37
 
38
#undef __FUNCT__  
39
#define __FUNCT__ "PSView_GHIEP"
40
PetscErrorCode PSView_GHIEP(PS ps,PetscViewer viewer)
41
{
42
  PetscErrorCode    ierr;
43
  PetscViewerFormat format;
44
  PetscInt          i,j,r,c;
45
  PetscReal         value;
46
  const char        *meth[] = { "LAPACK's _steqr" };
47
 
48
  PetscFunctionBegin;
49
  ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
50
  if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
51
    ierr = PetscViewerASCIIPrintf(viewer,"solving the problem with: %s\n",meth[ps->method]);CHKERRQ(ierr);
52
    PetscFunctionReturn(0);
53
  }
54
  if (ps->compact) {
55
    ierr = PetscViewerASCIIUseTabs(viewer,PETSC_FALSE);CHKERRQ(ierr);
56
    if (format == PETSC_VIEWER_ASCII_MATLAB) {
57
      ierr = PetscViewerASCIIPrintf(viewer,"%% Size = %D %D\n",ps->n,ps->n);CHKERRQ(ierr);
58
      ierr = PetscViewerASCIIPrintf(viewer,"zzz = zeros(%D,3);\n",3*ps->n);CHKERRQ(ierr);
59
      ierr = PetscViewerASCIIPrintf(viewer,"zzz = [\n");CHKERRQ(ierr);
60
      for (i=0;i<ps->n;i++) {
61
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",i+1,i+1,*(ps->rmat[PS_MAT_T]+i));CHKERRQ(ierr);
62
      }
63
      for (i=0;i<ps->n-1;i++) {
64
        r = PetscMax(i+2,ps->k+1);
65
        c = i+1;
66
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",r,c,*(ps->rmat[PS_MAT_T]+ps->ld+i));CHKERRQ(ierr);
67
        ierr = PetscViewerASCIIPrintf(viewer,"%D %D  %18.16e\n",c,r,*(ps->rmat[PS_MAT_T]+ps->ld+i));CHKERRQ(ierr);
68
      }
69
      ierr = PetscViewerASCIIPrintf(viewer,"];\n%s = spconvert(zzz);\n",PSMatName[PS_MAT_T]);CHKERRQ(ierr);
70
    } else {
71
      for (i=0;i<ps->n;i++) {
72
        for (j=0;j<ps->n;j++) {
73
          if (i==j) value = *(ps->rmat[PS_MAT_T]+i);
74
          else if ((i<ps->k && j==ps->k) || (i==ps->k && j<ps->k)) value = *(ps->rmat[PS_MAT_T]+ps->ld+PetscMin(i,j));
75
          else if (i==j+1 && i>ps->k) value = *(ps->rmat[PS_MAT_T]+ps->ld+i-1);
76
          else if (i+1==j && j>ps->k) value = *(ps->rmat[PS_MAT_T]+ps->ld+j-1);
77
          else value = 0.0;
78
          ierr = PetscViewerASCIIPrintf(viewer," %18.16e ",value);CHKERRQ(ierr);
79
        }
80
        ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
81
      }
82
    }
83
    ierr = PetscViewerASCIIUseTabs(viewer,PETSC_TRUE);CHKERRQ(ierr);
84
    ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
85
  } else {
86
    ierr = PSViewMat_Private(ps,viewer,PS_MAT_A);CHKERRQ(ierr);
87
  }
88
  if (ps->state>PS_STATE_INTERMEDIATE) {
89
    ierr = PSViewMat_Private(ps,viewer,PS_MAT_Q);CHKERRQ(ierr);
90
  }
91
  PetscFunctionReturn(0);
92
}
93
 
94
#undef __FUNCT__  
95
#define __FUNCT__ "PSVectors_GHIEP"
96
PetscErrorCode PSVectors_GHIEP(PS ps,PSMatType mat,PetscInt *k,PetscReal *rnorm)
97
{
98
  PetscScalar    *Q = ps->mat[PS_MAT_Q];
99
  PetscInt       ld = ps->ld;
100
  PetscErrorCode ierr;
101
 
102
  PetscFunctionBegin;
103
  if (ps->state<PS_STATE_CONDENSED) SETERRQ(((PetscObject)ps)->comm,PETSC_ERR_ORDER,"Must call PSSolve() first");
104
  switch (mat) {
105
    case PS_MAT_X:
106
    case PS_MAT_Y:
107
      if (k) {
108
        ierr = PetscMemcpy(ps->mat[mat]+(*k)*ld,Q+(*k)*ld,ld*sizeof(PetscScalar));CHKERRQ(ierr);
109
      } else {
110
        ierr = PetscMemcpy(ps->mat[mat],Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
111
      }
112
      if (rnorm) *rnorm = PetscAbsScalar(Q[ps->n-1+(*k)*ld]);
113
      break;
114
    case PS_MAT_U:
115
    case PS_MAT_VT:
116
      SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented yet");
117
      break;
118
    default:
119
      SETERRQ(((PetscObject)ps)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Invalid mat parameter");
120
  }
121
  PetscFunctionReturn(0);
122
}
123
 
124
#undef __FUNCT__  
125
#define __FUNCT__ "PSSolve_GHIEP"
126
PetscErrorCode PSSolve_GHIEP(PS ps,PetscScalar *wr,PetscScalar *wi)
127
{
128
#if defined(SLEPC_MISSING_LAPACK_SYTRD) || defined(SLEPC_MISSING_LAPACK_ORGTR) || defined(SLEPC_MISSING_LAPACK_STEQR)
129
  PetscFunctionBegin;
130
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"SYTRD/ORGTR/STEQR - Lapack routine is unavailable.");
131
#else
132
  PetscErrorCode ierr;
133
  PetscInt       i,j;
134
  PetscBLASInt   n1,n2,lwork,info,n,ld;
135
  PetscScalar    *A,*S,*Q,*work,*tau;
136
  PetscReal      *d,*e;
137
 
138
  PetscFunctionBegin;
139
  n  = PetscBLASIntCast(ps->n);
140
  ld = PetscBLASIntCast(ps->ld);
141
  Q  = ps->mat[PS_MAT_Q];
142
  d  = ps->rmat[PS_MAT_T];
143
  e  = ps->rmat[PS_MAT_T]+ld;
144
 
145
  if (ps->compact) {
146
 
147
    n1 = PetscBLASIntCast(ps->k+1);    /* size of leading block, including residuals */
148
    n2 = PetscBLASIntCast(n-ps->k-1);  /* size of trailing block */
149
 
150
    /* initialize orthogonal matrix */
151
    ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
152
    for (i=0;i<n;i++) Q[i+i*ld] = 1.0;
153
    if (n==1) { wr[0] = d[0]; PetscFunctionReturn(0); }
154
 
155
    /* reduce to tridiagonal form */
156
    if (ps->state<PS_STATE_INTERMEDIATE) {
157
 
158
      ierr = PSAllocateMat_Private(ps,PS_MAT_W);CHKERRQ(ierr);
159
      S = ps->mat[PS_MAT_W];
160
      ierr = PetscMemzero(S,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
161
      ierr = PSAllocateWork_Private(ps,ld+ld*ld,0,0);CHKERRQ(ierr);
162
      tau  = ps->work;
163
      work = ps->work+ld;
164
      lwork = ld*ld;
165
 
166
      /* Flip matrix S */
167
      for (i=0;i<n;i++) S[(n-1-i)+(n-1-i)*ld] = d[i];
168
      for (i=0;i<ps->k;i++) S[(n-1-i)+(n-1-ps->k)*ld] = e[i];
169
      for (i=ps->k;i<n-1;i++) S[(n-1-i)+(n-1-i-1)*ld] = e[i];
170
 
171
      /* Reduce (2,2)-block of flipped S to tridiagonal form */
172
      LAPACKsytrd_("L",&n1,S+n2+n2*ld,&ld,d,e,tau,work,&lwork,&info);
173
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
174
 
175
      /* Flip back diag and subdiag, put them in d and e */
176
      for (i=0;i<n-1;i++) {
177
        d[n-i-1] = PetscRealPart(S[i+i*ld]);
178
        e[n-i-2] = PetscRealPart(S[i+1+i*ld]);
179
      }
180
      d[0] = PetscRealPart(S[n-1+(n-1)*ld]);
181
 
182
      /* Compute the orthogonal matrix used for tridiagonalization */
183
      LAPACKorgtr_("L",&n1,S+n2+n2*ld,&ld,tau,work,&lwork,&info);
184
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
185
 
186
      /* Create full-size Q, flipped back to original order */
187
      for (i=0;i<n1;i++)
188
        for (j=0;j<n1;j++)
189
          Q[i+j*ld] = S[n-i-1+(n-j-1)*ld];
190
 
191
    }
192
 
193
  } else {
194
 
195
    A  = ps->mat[PS_MAT_A];
196
    if (n==1) { d[0] = PetscRealPart(A[0]); wr[0] = d[0]; Q[0] = 1.0; PetscFunctionReturn(0); }
197
 
198
    if (ps->state<PS_STATE_INTERMEDIATE) {
199
      /* reduce to tridiagonal form */
200
      ierr = PetscMemcpy(Q,A,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
201
      ierr = PSAllocateWork_Private(ps,ld+ld*ld,0,0);CHKERRQ(ierr);
202
      tau  = ps->work;
203
      work = ps->work+ld;
204
      lwork = ld*ld;
205
      LAPACKsytrd_("L",&n,Q,&ld,d,e,tau,work,&lwork,&info);
206
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSYTRD %d",info);
207
      LAPACKorgtr_("L",&n,Q,&ld,tau,work,&lwork,&info);
208
      if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xORGTR %d",info);
209
    } else {
210
      /* initialize orthogonal matrix; copy tridiagonal to d,e */
211
      ierr = PetscMemzero(Q,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
212
      for (i=0;i<n;i++) Q[i+i*ld] = 1.0;
213
      for (i=0;i<n;i++) d[i] = PetscRealPart(A[i+i*ld]);
214
      for (i=0;i<n-1;i++) e[i] = PetscRealPart(A[(i+1)+i*ld]);
215
    }
216
  }
217
 
218
  /* Solve the tridiagonal eigenproblem */
219
  ierr = PSAllocateWork_Private(ps,0,2*ld,0);CHKERRQ(ierr);
220
  LAPACKsteqr_("V",&n,d,e,Q,&ld,ps->rwork,&info);
221
  if (info) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in Lapack xSTEQR %d",info);
222
  for (i=0;i<n;i++) wr[i] = d[i];
223
  if (ps->compact) {
224
    ierr = PetscMemzero(e,(n-1)*sizeof(PetscReal));CHKERRQ(ierr);
225
  } else {
226
    ierr = PetscMemzero(A,ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
227
    for (i=0;i<n;i++) A[i+i*ld] = d[i];
228
  }
229
 
230
  /* The result is stored in both places (compact and regular) */
231
  ps->compact = PETSC_TRUE;
232
  PetscFunctionReturn(0);
233
#endif
234
}
235
 
236
#undef __FUNCT__  
237
#define __FUNCT__ "PSSort_GHIEP"
238
PetscErrorCode PSSort_GHIEP(PS ps,PetscScalar *wr,PetscScalar *wi,PetscErrorCode (*comp_func)(PetscScalar,PetscScalar,PetscScalar,PetscScalar,PetscInt*,void*),void *comp_ctx)
239
{
240
  PetscErrorCode ierr;
2818 jroman 241
  PetscInt       n,l,i,*perm;
2808 carcamgo 242
  PetscScalar    *A;
243
  PetscReal      *d;
244
 
245
  PetscFunctionBegin;
246
  n = ps->n;
2818 jroman 247
  l = ps->l;
2808 carcamgo 248
  d = ps->rmat[PS_MAT_T];
249
  ierr = PSAllocateWork_Private(ps,0,0,ps->ld);CHKERRQ(ierr);
250
  perm = ps->iwork;
2818 jroman 251
  ierr = PSSortEigenvaluesReal_Private(ps,n,l,d,perm,comp_func,comp_ctx);CHKERRQ(ierr);
252
  for (i=l;i<n;i++) wr[i] = d[perm[i]];
253
  ierr = PSPermuteColumns_Private(ps,l,n,PS_MAT_Q,perm);CHKERRQ(ierr);
2808 carcamgo 254
  if (ps->compact) {
2818 jroman 255
    for (i=l;i<n;i++) d[i] = PetscRealPart(wr[i]);
2808 carcamgo 256
  } else {
257
    A  = ps->mat[PS_MAT_A];
2818 jroman 258
    for (i=l;i<n;i++) A[i+i*ps->ld] = wr[i];
2808 carcamgo 259
  }
260
  PetscFunctionReturn(0);
261
}
262
 
263
EXTERN_C_BEGIN
264
#undef __FUNCT__  
265
#define __FUNCT__ "PSCreate_GHIEP"
266
PetscErrorCode PSCreate_GHIEP(PS ps)
267
{
268
  PetscFunctionBegin;
269
  ps->ops->allocate      = PSAllocate_GHIEP;
270
  ps->ops->view          = PSView_GHIEP;
271
  ps->ops->vectors       = PSVectors_GHIEP;
2832 jroman 272
  ps->ops->solve[0]      = PSSolve_GHIEP;
2808 carcamgo 273
  ps->ops->sort          = PSSort_GHIEP;
274
  PetscFunctionReturn(0);
275
}
276
EXTERN_C_END
277