Actual source code: bvkrylov.c
slepc-main 2024-12-17
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
6: This file is part of SLEPc.
7: SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9: */
10: /*
11: BV routines related to Krylov decompositions
12: */
14: #include <slepc/private/bvimpl.h>
16: /*@
17: BVMatArnoldi - Computes an Arnoldi factorization associated with a matrix.
19: Collective
21: Input Parameters:
22: + V - basis vectors context
23: . A - the matrix
24: . H - (optional) the upper Hessenberg matrix
25: . k - number of locked columns
26: - m - dimension of the Arnoldi basis, may be modified
28: Output Parameters:
29: + beta - (optional) norm of last vector before normalization
30: - breakdown - (optional) flag indicating that breakdown occurred
32: Notes:
33: Computes an m-step Arnoldi factorization for matrix A. The first k columns
34: are assumed to be locked and therefore they are not modified. On exit, the
35: following relation is satisfied
37: $ A * V - V * H = beta*v_m * e_m^T
39: where the columns of V are the Arnoldi vectors (which are orthonormal), H is
40: an upper Hessenberg matrix, e_m is the m-th vector of the canonical basis.
41: On exit, beta contains the norm of V[m] before normalization.
43: The breakdown flag indicates that orthogonalization failed, see
44: BVOrthonormalizeColumn(). In that case, on exit m contains the index of
45: the column that failed.
47: The values of k and m are not restricted to the active columns of V.
49: To create an Arnoldi factorization from scratch, set k=0 and make sure the
50: first column contains the normalized initial vector.
52: Level: advanced
54: .seealso: BVMatLanczos(), BVSetActiveColumns(), BVOrthonormalizeColumn()
55: @*/
56: PetscErrorCode BVMatArnoldi(BV V,Mat A,Mat H,PetscInt k,PetscInt *m,PetscReal *beta,PetscBool *breakdown)
57: {
58: PetscScalar *h;
59: const PetscScalar *a;
60: PetscInt j,ldh,rows,cols;
61: PetscBool lindep=PETSC_FALSE;
62: Vec buf;
64: PetscFunctionBegin;
68: PetscAssertPointer(m,5);
71: BVCheckSizes(V,1);
73: PetscCheckSameComm(V,1,A,2);
75: PetscCheck(k>=0 && k<=V->m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument k has wrong value %" PetscInt_FMT ", should be between 0 and %" PetscInt_FMT,k,V->m);
76: PetscCheck(*m>0 && *m<=V->m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument m has wrong value %" PetscInt_FMT ", should be between 1 and %" PetscInt_FMT,*m,V->m);
77: PetscCheck(*m>k,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument m should be at least equal to k+1");
78: if (H) {
81: PetscCheckTypeName(H,MATSEQDENSE);
82: PetscCall(MatGetSize(H,&rows,&cols));
83: PetscCall(MatDenseGetLDA(H,&ldh));
84: PetscCheck(rows>=*m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"Matrix H has %" PetscInt_FMT " rows, should have at least %" PetscInt_FMT,rows,*m);
85: PetscCheck(cols>=*m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"Matrix H has %" PetscInt_FMT " columns, should have at least %" PetscInt_FMT,cols,*m);
86: }
88: for (j=k;j<*m;j++) {
89: PetscCall(BVMatMultColumn(V,A,j));
90: if (PetscUnlikely(j==V->N-1)) PetscCall(BV_OrthogonalizeColumn_Safe(V,j+1,NULL,beta,&lindep)); /* safeguard in case the full basis is requested */
91: else PetscCall(BVOrthonormalizeColumn(V,j+1,PETSC_FALSE,beta,&lindep));
92: if (PetscUnlikely(lindep)) {
93: *m = j+1;
94: break;
95: }
96: }
97: if (breakdown) *breakdown = lindep;
98: if (lindep) PetscCall(PetscInfo(V,"Arnoldi finished early at m=%" PetscInt_FMT "\n",*m));
100: if (H) {
101: PetscCall(MatDenseGetArray(H,&h));
102: PetscCall(BVGetBufferVec(V,&buf));
103: PetscCall(VecGetArrayRead(buf,&a));
104: for (j=k;j<*m-1;j++) PetscCall(PetscArraycpy(h+j*ldh,a+V->nc+(j+1)*(V->nc+V->m),j+2));
105: PetscCall(PetscArraycpy(h+(*m-1)*ldh,a+V->nc+(*m)*(V->nc+V->m),*m));
106: if (ldh>*m) h[(*m)+(*m-1)*ldh] = a[V->nc+(*m)+(*m)*(V->nc+V->m)];
107: PetscCall(VecRestoreArrayRead(buf,&a));
108: PetscCall(MatDenseRestoreArray(H,&h));
109: }
111: PetscCall(PetscObjectStateIncrease((PetscObject)V));
112: PetscFunctionReturn(PETSC_SUCCESS);
113: }
115: /*@
116: BVMatLanczos - Computes a Lanczos factorization associated with a matrix.
118: Collective
120: Input Parameters:
121: + V - basis vectors context
122: . A - the matrix
123: . T - (optional) the tridiagonal matrix
124: . k - number of locked columns
125: - m - dimension of the Lanczos basis, may be modified
127: Output Parameters:
128: + beta - (optional) norm of last vector before normalization
129: - breakdown - (optional) flag indicating that breakdown occurred
131: Notes:
132: Computes an m-step Lanczos factorization for matrix A, with full
133: reorthogonalization. At each Lanczos step, the corresponding Lanczos
134: vector is orthogonalized with respect to all previous Lanczos vectors.
135: This is equivalent to computing an m-step Arnoldi factorization and
136: exploting symmetry of the operator.
138: The first k columns are assumed to be locked and therefore they are
139: not modified. On exit, the following relation is satisfied
141: $ A * V - V * T = beta*v_m * e_m^T
143: where the columns of V are the Lanczos vectors (which are B-orthonormal),
144: T is a real symmetric tridiagonal matrix, and e_m is the m-th vector of
145: the canonical basis. On exit, beta contains the B-norm of V[m] before
146: normalization. The T matrix is stored in a special way, its first column
147: contains the diagonal elements, and its second column the off-diagonal
148: ones. In complex scalars, the elements are stored as PetscReal and thus
149: occupy only the first column of the Mat object. This is the same storage
150: scheme used in matrix DS_MAT_T obtained with DSGetMat().
152: The breakdown flag indicates that orthogonalization failed, see
153: BVOrthonormalizeColumn(). In that case, on exit m contains the index of
154: the column that failed.
156: The values of k and m are not restricted to the active columns of V.
158: To create a Lanczos factorization from scratch, set k=0 and make sure the
159: first column contains the normalized initial vector.
161: Level: advanced
163: .seealso: BVMatArnoldi(), BVSetActiveColumns(), BVOrthonormalizeColumn(), DSGetMat()
164: @*/
165: PetscErrorCode BVMatLanczos(BV V,Mat A,Mat T,PetscInt k,PetscInt *m,PetscReal *beta,PetscBool *breakdown)
166: {
167: PetscScalar *t;
168: const PetscScalar *a;
169: PetscReal *alpha,*betat;
170: PetscInt j,ldt,rows,cols,mincols=PetscDefined(USE_COMPLEX)?1:2;
171: PetscBool lindep=PETSC_FALSE;
172: Vec buf;
174: PetscFunctionBegin;
178: PetscAssertPointer(m,5);
181: BVCheckSizes(V,1);
183: PetscCheckSameComm(V,1,A,2);
185: PetscCheck(k>=0 || k<=V->m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument k has wrong value %" PetscInt_FMT ", should be between 0 and %" PetscInt_FMT,k,V->m);
186: PetscCheck(*m>0 || *m<=V->m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument m has wrong value %" PetscInt_FMT ", should be between 1 and %" PetscInt_FMT,*m,V->m);
187: PetscCheck(*m>k,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Argument m should be at least equal to k+1");
188: if (T) {
191: PetscCheckTypeName(T,MATSEQDENSE);
192: PetscCall(MatGetSize(T,&rows,&cols));
193: PetscCall(MatDenseGetLDA(T,&ldt));
194: PetscCheck(rows>=*m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"Matrix T has %" PetscInt_FMT " rows, should have at least %" PetscInt_FMT,rows,*m);
195: PetscCheck(cols>=mincols,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_SIZ,"Matrix T has %" PetscInt_FMT " columns, should have at least %" PetscInt_FMT,cols,mincols);
196: }
198: for (j=k;j<*m;j++) {
199: PetscCall(BVMatMultColumn(V,A,j));
200: if (PetscUnlikely(j==V->N-1)) PetscCall(BV_OrthogonalizeColumn_Safe(V,j+1,NULL,beta,&lindep)); /* safeguard in case the full basis is requested */
201: else PetscCall(BVOrthonormalizeColumn(V,j+1,PETSC_FALSE,beta,&lindep));
202: if (PetscUnlikely(lindep)) {
203: *m = j+1;
204: break;
205: }
206: }
207: if (breakdown) *breakdown = lindep;
208: if (lindep) PetscCall(PetscInfo(V,"Lanczos finished early at m=%" PetscInt_FMT "\n",*m));
210: if (T) {
211: PetscCall(MatDenseGetArray(T,&t));
212: alpha = (PetscReal*)t;
213: betat = alpha+ldt;
214: PetscCall(BVGetBufferVec(V,&buf));
215: PetscCall(VecGetArrayRead(buf,&a));
216: for (j=k;j<*m;j++) {
217: alpha[j] = PetscRealPart(a[V->nc+j+(j+1)*(V->nc+V->m)]);
218: betat[j] = PetscRealPart(a[V->nc+j+1+(j+1)*(V->nc+V->m)]);
219: }
220: PetscCall(VecRestoreArrayRead(buf,&a));
221: PetscCall(MatDenseRestoreArray(T,&t));
222: }
224: PetscCall(PetscObjectStateIncrease((PetscObject)V));
225: PetscFunctionReturn(PETSC_SUCCESS);
226: }