Subversion Repositories slepc-dev

Rev

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

Rev Author Line No. Line
2840 eromero 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_GNHEP"
27
PetscErrorCode PSAllocate_GNHEP(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_B);CHKERRQ(ierr);
2842 jroman 34
  ierr = PSAllocateMat_Private(ps,PS_MAT_Z);CHKERRQ(ierr);
2840 eromero 35
  ierr = PSAllocateMat_Private(ps,PS_MAT_Q);CHKERRQ(ierr);
36
  PetscFunctionReturn(0);
37
}
38
 
39
#undef __FUNCT__  
40
#define __FUNCT__ "PSView_GNHEP"
41
PetscErrorCode PSView_GNHEP(PS ps,PetscViewer viewer)
42
{
43
  PetscErrorCode ierr;
44
 
45
  PetscFunctionBegin;
46
  ierr = PSViewMat_Private(ps,viewer,PS_MAT_A);CHKERRQ(ierr);
47
  ierr = PSViewMat_Private(ps,viewer,PS_MAT_B);CHKERRQ(ierr);
48
  if (ps->state>PS_STATE_INTERMEDIATE) {
2842 jroman 49
    ierr = PSViewMat_Private(ps,viewer,PS_MAT_Z);CHKERRQ(ierr);
2840 eromero 50
    ierr = PSViewMat_Private(ps,viewer,PS_MAT_Q);CHKERRQ(ierr);
51
  }
52
  PetscFunctionReturn(0);
53
}
54
 
55
#undef __FUNCT__  
56
#define __FUNCT__ "PSVectors_GNHEP_Eigen_All"
57
PetscErrorCode PSVectors_GNHEP_Eigen_All(PS ps,PetscBool left)
58
{
59
#if defined(SLEPC_MISSING_LAPACK_TGEVC)
60
  PetscFunctionBegin;
61
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"TGEVC - Lapack routine is unavailable.");
62
#else
63
  PetscErrorCode ierr;
64
  PetscBLASInt   n,ld,mout,info;
2842 jroman 65
  PetscScalar    *X,*Y,*A = ps->mat[PS_MAT_A],*B = ps->mat[PS_MAT_B];
2840 eromero 66
  const char     *side,*back;
67
 
68
  PetscFunctionBegin;
69
  n  = PetscBLASIntCast(ps->n);
70
  ld = PetscBLASIntCast(ps->ld);
71
  if (left) {
72
    X = PETSC_NULL;
73
    Y = ps->mat[PS_MAT_Y];
74
    side = "L";
75
  } else {
76
    X = ps->mat[PS_MAT_X];
77
    Y = PETSC_NULL;
78
    side = "R";
79
  }
80
  if (ps->state>=PS_STATE_CONDENSED) {
81
    /* PSSolve() has been called, backtransform with matrix Q */
82
    back = "B";
2842 jroman 83
    ierr = PetscMemcpy(left?Y:X,ps->mat[left?PS_MAT_Z:PS_MAT_Q],ld*ld*sizeof(PetscScalar));CHKERRQ(ierr);
2840 eromero 84
  } else back = "A";
85
#if defined(PETSC_USE_COMPLEX)
86
  ierr = PSAllocateWork_Private(ps,2*ld,2*ld,0);CHKERRQ(ierr);
87
  LAPACKtgevc_(side,back,PETSC_NULL,&n,A,&ld,B,&ld,Y,&ld,X,&ld,&n,&mout,ps->work,ps->rwork,&info);
88
#else
89
  ierr = PSAllocateWork_Private(ps,6*ld,0,0);CHKERRQ(ierr);
90
  LAPACKtgevc_(side,back,PETSC_NULL,&n,A,&ld,B,&ld,Y,&ld,X,&ld,&n,&mout,ps->work,&info);
91
#endif
92
  if (info) SETERRQ1(((PetscObject)ps)->comm,PETSC_ERR_LIB,"Error in Lapack xTREVC %i",info);
93
  PetscFunctionReturn(0);
94
#endif
95
}
96
 
97
#undef __FUNCT__  
98
#define __FUNCT__ "PSVectors_GNHEP"
99
PetscErrorCode PSVectors_GNHEP(PS ps,PSMatType mat,PetscInt *k,PetscReal *rnorm)
100
{
101
  PetscErrorCode ierr;
102
 
103
  PetscFunctionBegin;
104
  if (k) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented yet");
105
  switch (mat) {
106
    case PS_MAT_X:
107
      ierr = PSVectors_GNHEP_Eigen_All(ps,PETSC_FALSE);CHKERRQ(ierr);
108
      break;
109
    case PS_MAT_Y:
110
      ierr = PSVectors_GNHEP_Eigen_All(ps,PETSC_TRUE);CHKERRQ(ierr);
111
      break;
112
    default:
113
      SETERRQ(((PetscObject)ps)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Invalid mat parameter");
114
  }
115
  PetscFunctionReturn(0);
116
}
117
 
118
#undef __FUNCT__  
119
#define __FUNCT__ "PSSolve_GNHEP"
120
PetscErrorCode PSSolve_GNHEP(PS ps,PetscScalar *wr,PetscScalar *wi)
121
{
122
#if defined(SLEPC_MISSING_LAPACK_GGES)
123
  PetscFunctionBegin;
124
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"GGES - Lapack routines are unavailable.");
125
#else
126
  PetscErrorCode ierr;
127
  PetscScalar    *work,*beta,a;
128
  PetscInt       i;
129
  PetscBLASInt   lwork,info,n,ld,iaux;
2842 jroman 130
  PetscScalar    *A = ps->mat[PS_MAT_A],*B = ps->mat[PS_MAT_B],*Z = ps->mat[PS_MAT_Z],*Q = ps->mat[PS_MAT_Q];
2840 eromero 131
 
132
  PetscFunctionBegin;
133
  PetscValidPointer(wi,2);
134
  n   = PetscBLASIntCast(ps->n);
135
  ld  = PetscBLASIntCast(ps->ld);
136
  if (ps->state==PS_STATE_INTERMEDIATE) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not implemented for the intermediate state");
137
  lwork = -1;
138
#if !defined(PETSC_USE_COMPLEX)
139
  LAPACKgges_("V","V","N",PETSC_NULL,&ld,PETSC_NULL,&ld,PETSC_NULL,&ld,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,&ld,PETSC_NULL,&ld,&a,&lwork,PETSC_NULL,&info);
2850 jroman 140
  lwork = (PetscBLASInt)a;
2840 eromero 141
  ierr = PSAllocateWork_Private(ps,lwork+ld,0,0);CHKERRQ(ierr);
142
  beta = ps->work;
143
  work = beta+ps->n;
144
  lwork = PetscBLASIntCast(ps->lwork-ps->n);
2842 jroman 145
  LAPACKgges_("V","V","N",PETSC_NULL,&n,A,&ld,B,&ld,&iaux,wr,wi,beta,Z,&ld,Q,&ld,work,&lwork,PETSC_NULL,&info);
2840 eromero 146
#else
147
  LAPACKgges_("V","V","N",PETSC_NULL,&ld,PETSC_NULL,&ld,PETSC_NULL,&ld,PETSC_NULL,PETSC_NULL,PETSC_NULL,PETSC_NULL,&ld,PETSC_NULL,&ld,&a,&lwork,PETSC_NULL,PETSC_NULL,&info);
2850 jroman 148
  lwork = (PetscBLASInt)PetscRealPart(a);
2840 eromero 149
  ierr = PSAllocateWork_Private(ps,lwork+ld,8*ld,0);CHKERRQ(ierr);
150
  beta = ps->work;
151
  work = beta+ps->n;
152
  lwork = PetscBLASIntCast(ps->lwork-ps->n);
2850 jroman 153
  LAPACKgges_("V","V","N",PETSC_NULL,&n,A,&ld,B,&ld,&iaux,wr,beta,Z,&ld,Q,&ld,work,&lwork,ps->rwork,PETSC_NULL,&info);
2840 eromero 154
#endif
155
  if (info) SETERRQ1(((PetscObject)ps)->comm,PETSC_ERR_LIB,"Error in Lapack xGGES %i",info);
2842 jroman 156
  for (i=0;i<n;i++) {
2851 jroman 157
    if (beta[i]==0.0) wr[i] = (PetscRealPart(wr[i])>0.0)? PETSC_MAX_REAL: PETSC_MIN_REAL;
2845 jroman 158
    else wr[i] /= beta[i];
2840 eromero 159
#if !defined(PETSC_USE_COMPLEX)
2850 jroman 160
    if (beta[i]==0.0) wi[i] = (wi[i]>0.0)? PETSC_MAX_REAL: PETSC_MIN_REAL;
2845 jroman 161
    else wi[i] /= beta[i];
2840 eromero 162
#endif
163
  }
164
  PetscFunctionReturn(0);
165
#endif
166
}
167
 
168
#undef __FUNCT__  
169
#define __FUNCT__ "PSSort_GNHEP"
170
PetscErrorCode PSSort_GNHEP(PS ps,PetscScalar *wr,PetscScalar *wi,PetscErrorCode (*comp_func)(PetscScalar,PetscScalar,PetscScalar,PetscScalar,PetscInt*,void*),void *comp_ctx)
171
{
172
#if defined(SLEPC_MISSING_LAPACK_TGEXC) || !defined(PETSC_USE_COMPLEX) && (defined(SLEPC_MISSING_LAPACK_LAMCH) || defined(SLEPC_MISSING_LAPACK_LAG2))
173
  PetscFunctionBegin;
174
  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"TGEXC/LAMCH/LAG2 - Lapack routines are unavailable.");
175
#else
176
  PetscErrorCode ierr;
177
  PetscScalar    re,im;
178
  PetscInt       i,j,pos,result;
179
  PetscBLASInt   ifst,ilst,info,n,ld,one=1;
2842 jroman 180
  PetscScalar    *S = ps->mat[PS_MAT_A],*T = ps->mat[PS_MAT_B],*Z = ps->mat[PS_MAT_Z],*Q = ps->mat[PS_MAT_Q];
2840 eromero 181
#if !defined(PETSC_USE_COMPLEX)
182
  PetscBLASInt   lwork;
183
  PetscScalar    *work,a,safmin,scale1,scale2;
184
#endif
185
 
186
  PetscFunctionBegin;
187
  PetscValidPointer(wi,2);
188
  n  = PetscBLASIntCast(ps->n);
189
  ld = PetscBLASIntCast(ps->ld);
190
#if !defined(PETSC_USE_COMPLEX)
191
  lwork = -1;
192
  LAPACKtgexc_(&one,&one,&ld,PETSC_NULL,&ld,PETSC_NULL,&ld,PETSC_NULL,&ld,PETSC_NULL,&ld,&one,&one,&a,&lwork,&info);
193
  safmin = LAPACKlamch_("S");
194
  lwork = a;
195
  ierr = PSAllocateWork_Private(ps,lwork,0,0);CHKERRQ(ierr);
196
  work = ps->work;
197
#endif
198
  /* selection sort */
199
  for (i=ps->l;i<n-1;i++) {
200
    re = wr[i];
201
    im = wi[i];
202
    pos = 0;
203
    j=i+1; /* j points to the next eigenvalue */
204
#if !defined(PETSC_USE_COMPLEX)
205
    if (im != 0) j=i+2;
206
#endif
207
    /* find minimum eigenvalue */
208
    for (;j<n;j++) {
209
      ierr = (*comp_func)(re,im,wr[j],wi[j],&result,comp_ctx);CHKERRQ(ierr);
210
      if (result > 0) {
211
        re = wr[j];
212
        im = wi[j];
213
        pos = j;
214
      }
215
#if !defined(PETSC_USE_COMPLEX)
216
      if (wi[j] != 0) j++;
217
#endif
218
    }
219
    if (pos) {
220
      /* interchange blocks */
221
      ifst = PetscBLASIntCast(pos+1);
222
      ilst = PetscBLASIntCast(i+1);
223
#if !defined(PETSC_USE_COMPLEX)
2842 jroman 224
      LAPACKtgexc_(&one,&one,&n,S,&ld,T,&ld,Z,&n,Q,&n,&ifst,&ilst,work,&lwork,&info);
2840 eromero 225
#else
2842 jroman 226
      LAPACKtgexc_(&one,&one,&n,S,&ld,T,&ld,Z,&ld,Q,&ld,&ifst,&ilst,&info);
2840 eromero 227
#endif
228
      if (info) SETERRQ1(((PetscObject)ps)->comm,PETSC_ERR_LIB,"Error in Lapack xTGEXC %i",info);
229
      /* recover original eigenvalues from T and S matrices */
230
      for (j=i;j<n;j++) {
231
#if !defined(PETSC_USE_COMPLEX)
232
        if (j<n-1 && S[j*ld+j+1] != 0.0) {
233
          /* complex conjugate eigenvalue */
234
          LAPACKlag2_(S+j*ld+j,&ld,T+j*ld+j,&ld,&safmin,&scale1,&scale2,&re,&a,&im);
235
          wr[j] = re / scale1;
236
          wi[j] = im / scale1;
237
          wr[j+1] = a / scale2;
238
          wi[j+1] = -wi[j];
239
          j++;
240
        } else
241
#endif
242
        {
2851 jroman 243
          if (T[j*ld+j] == 0.0) wr[j] = (PetscRealPart(S[j*ld+j])>0.0)? PETSC_MAX_REAL: PETSC_MIN_REAL;
2845 jroman 244
          else wr[j] = S[j*ld+j] / T[j*ld+j];
2840 eromero 245
          wi[j] = 0.0;
246
        }
247
      }
248
    }
249
#if !defined(PETSC_USE_COMPLEX)
250
    if (wi[i] != 0.0) i++;
251
#endif
252
  }
253
  PetscFunctionReturn(0);
254
#endif
255
}
256
 
257
EXTERN_C_BEGIN
258
#undef __FUNCT__  
259
#define __FUNCT__ "PSCreate_GNHEP"
260
PetscErrorCode PSCreate_GNHEP(PS ps)
261
{
262
  PetscFunctionBegin;
263
  ps->ops->allocate      = PSAllocate_GNHEP;
264
  ps->ops->view          = PSView_GNHEP;
265
  ps->ops->vectors       = PSVectors_GNHEP;
2842 jroman 266
  ps->ops->solve[0]      = PSSolve_GNHEP;
2840 eromero 267
  ps->ops->sort          = PSSort_GNHEP;
268
  ps->ops->cond          = PETSC_NULL;
269
  ps->ops->transharm     = PETSC_NULL;
270
  PetscFunctionReturn(0);
271
}
272
EXTERN_C_END
273