Actual source code: bvbiorthog.c
slepc-main 2024-11-09
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 bi-orthogonalization routines
12: */
14: #include <slepc/private/bvimpl.h>
16: /*
17: BVBiorthogonalizeMGS1 - Compute one step of Modified Gram-Schmidt bi-orthogonalization
18: */
19: static PetscErrorCode BVBiorthogonalizeMGS1(BV V,BV W,Vec v,PetscScalar *h,PetscScalar *c)
20: {
21: PetscInt i;
22: PetscScalar dot;
23: Vec vi,wi;
25: PetscFunctionBegin;
26: for (i=-V->nc;i<V->k;i++) {
27: PetscCall(BVGetColumn(W,i,&wi));
28: /* h_i = (v, w_i) */
29: PetscCall(VecDot(v,wi,&dot));
30: PetscCall(BVRestoreColumn(W,i,&wi));
31: /* v <- v - h_i v_i */
32: PetscCall(BV_SetValue(V,i,0,c,dot));
33: PetscCall(BVGetColumn(V,i,&vi));
34: PetscCall(VecAXPY(v,-dot,vi));
35: PetscCall(BVRestoreColumn(V,i,&vi));
36: }
37: PetscCall(BV_AddCoefficients(V,V->k,h,c));
38: PetscFunctionReturn(PETSC_SUCCESS);
39: }
41: /*
42: BVBiorthogonalizeCGS1 - Compute one step of CGS bi-orthogonalization: v = (I-V*W')*v
43: */
44: static PetscErrorCode BVBiorthogonalizeCGS1(BV V,BV W,Vec v,PetscScalar *h,PetscScalar *c)
45: {
46: PetscFunctionBegin;
47: /* h = W'*v */
48: PetscCall(BVDotVec(W,v,c));
50: /* v = v - V h */
51: PetscCall(BVMultVec(V,-1.0,1.0,v,c));
53: PetscCall(BV_AddCoefficients(V,V->k,h,c));
54: PetscFunctionReturn(PETSC_SUCCESS);
55: }
57: #define BVBiorthogonalizeGS1(a,b,c,d,e) ((V->orthog_type==BV_ORTHOG_MGS)?BVBiorthogonalizeMGS1:BVBiorthogonalizeCGS1)(a,b,c,d,e)
59: /*
60: BVBiorthogonalizeGS - Orthogonalize with (classical or modified) Gram-Schmidt
62: V, W - the two basis vectors objects
63: v - the vector to bi-orthogonalize
64: */
65: static PetscErrorCode BVBiorthogonalizeGS(BV V,BV W,Vec v)
66: {
67: PetscScalar *h,*c;
69: PetscFunctionBegin;
70: h = V->h;
71: c = V->c;
72: PetscCall(BV_CleanCoefficients(V,V->k,h));
73: PetscCall(BVBiorthogonalizeGS1(V,W,v,h,c));
74: if (V->orthog_ref!=BV_ORTHOG_REFINE_NEVER) PetscCall(BVBiorthogonalizeGS1(V,W,v,h,c));
75: PetscFunctionReturn(PETSC_SUCCESS);
76: }
78: /*@
79: BVBiorthogonalizeColumn - Bi-orthogonalize a column of two BV objects.
81: Collective
83: Input Parameters:
84: + V - first basis vectors context
85: . W - second basis vectors context
86: - j - index of column to be bi-orthonormalized
88: Notes:
89: This function bi-orthogonalizes vectors V[j],W[j] against W[0..j-1],
90: and V[0..j-1], respectively, so that W[0..j]'*V[0..j] = diagonal.
92: Level: advanced
94: .seealso: BVOrthogonalizeColumn(), BVBiorthonormalizeColumn()
95: @*/
96: PetscErrorCode BVBiorthogonalizeColumn(BV V,BV W,PetscInt j)
97: {
98: PetscInt ksavev,lsavev,ksavew,lsavew;
99: Vec y,z;
101: PetscFunctionBegin;
106: BVCheckSizes(V,1);
108: BVCheckSizes(W,2);
109: PetscCheckSameTypeAndComm(V,1,W,2);
110: PetscCheck(j>=0,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Index j must be non-negative");
111: PetscCheck(j<V->m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Index j=%" PetscInt_FMT " but V only has %" PetscInt_FMT " columns",j,V->m);
112: PetscCheck(j<W->m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Index j=%" PetscInt_FMT " but W only has %" PetscInt_FMT " columns",j,W->m);
113: PetscCheck(V->n==W->n,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Mismatching local dimension V %" PetscInt_FMT ", W %" PetscInt_FMT,V->n,W->n);
114: PetscCheck(!V->matrix && !W->matrix,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_WRONGSTATE,"V,W must not have an inner product matrix");
115: PetscCheck(!V->nc && !W->nc,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_WRONGSTATE,"V,W cannot have different number of constraints");
116: PetscCheck(!V->ops->gramschmidt && !W->ops->gramschmidt,PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Object has a special GS function");
118: /* bi-orthogonalize */
119: PetscCall(PetscLogEventBegin(BV_OrthogonalizeVec,V,0,0,0));
120: ksavev = V->k;
121: lsavev = V->l;
122: ksavew = W->k;
123: lsavew = W->l;
124: V->k = j;
125: V->l = -V->nc; /* must also bi-orthogonalize against constraints and leading columns */
126: W->k = j;
127: W->l = -W->nc;
128: PetscCall(BV_AllocateCoeffs(V));
129: PetscCall(BV_AllocateCoeffs(W));
130: PetscCall(BVGetColumn(V,j,&y));
131: PetscCall(BVBiorthogonalizeGS(V,W,y));
132: PetscCall(BVRestoreColumn(V,j,&y));
133: PetscCall(BVGetColumn(W,j,&z));
134: PetscCall(BVBiorthogonalizeGS(W,V,z));
135: PetscCall(BVRestoreColumn(W,j,&z));
136: V->k = ksavev;
137: V->l = lsavev;
138: W->k = ksavew;
139: W->l = lsavew;
140: PetscCall(PetscLogEventEnd(BV_OrthogonalizeVec,V,0,0,0));
141: PetscCall(PetscObjectStateIncrease((PetscObject)V));
142: PetscCall(PetscObjectStateIncrease((PetscObject)W));
143: PetscFunctionReturn(PETSC_SUCCESS);
144: }
146: /*@
147: BVBiorthonormalizeColumn - Bi-orthonormalize a column of two BV objects.
149: Collective
151: Input Parameters:
152: + V - first basis vectors context
153: . W - second basis vectors context
154: - j - index of column to be bi-orthonormalized
156: Output Parameters:
157: . delta - (optional) value used for normalization
159: Notes:
160: This function first bi-orthogonalizes vectors V[j],W[j] against W[0..j-1],
161: and V[0..j-1], respectively. Then, it scales the vectors with 1/delta, so
162: that the resulting vectors satisfy W[j]'*V[j] = 1.
164: Level: advanced
166: .seealso: BVOrthonormalizeColumn(), BVBiorthogonalizeColumn()
167: @*/
168: PetscErrorCode BVBiorthonormalizeColumn(BV V,BV W,PetscInt j,PetscReal *delta)
169: {
170: PetscScalar alpha;
171: PetscReal deltat;
172: PetscInt ksavev,lsavev,ksavew,lsavew;
173: Vec y,z;
175: PetscFunctionBegin;
180: BVCheckSizes(V,1);
182: BVCheckSizes(W,2);
183: PetscCheckSameTypeAndComm(V,1,W,2);
184: PetscCheck(j>=0,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Index j must be non-negative");
185: PetscCheck(j<V->m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Index j=%" PetscInt_FMT " but V only has %" PetscInt_FMT " columns",j,V->m);
186: PetscCheck(j<W->m,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_OUTOFRANGE,"Index j=%" PetscInt_FMT " but W only has %" PetscInt_FMT " columns",j,W->m);
187: PetscCheck(V->n==W->n,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_INCOMP,"Mismatching local dimension V %" PetscInt_FMT ", W %" PetscInt_FMT,V->n,W->n);
188: PetscCheck(!V->matrix && !W->matrix,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_WRONGSTATE,"V,W must not have an inner product matrix");
189: PetscCheck(!V->nc && !W->nc,PetscObjectComm((PetscObject)V),PETSC_ERR_ARG_WRONGSTATE,"V,W cannot have different number of constraints");
190: PetscCheck(!V->ops->gramschmidt && !W->ops->gramschmidt,PetscObjectComm((PetscObject)V),PETSC_ERR_SUP,"Object has a special GS function");
192: /* bi-orthogonalize */
193: PetscCall(PetscLogEventBegin(BV_OrthogonalizeVec,V,0,0,0));
194: ksavev = V->k;
195: lsavev = V->l;
196: ksavew = W->k;
197: lsavew = W->l;
198: V->k = j;
199: V->l = -V->nc; /* must also bi-orthogonalize against constraints and leading columns */
200: W->k = j;
201: W->l = -W->nc;
202: PetscCall(BV_AllocateCoeffs(V));
203: PetscCall(BV_AllocateCoeffs(W));
204: PetscCall(BVGetColumn(V,j,&y));
205: PetscCall(BVBiorthogonalizeGS(V,W,y));
206: PetscCall(BVRestoreColumn(V,j,&y));
207: PetscCall(BVGetColumn(W,j,&z));
208: PetscCall(BVBiorthogonalizeGS(W,V,z));
209: PetscCall(BVRestoreColumn(W,j,&z));
210: V->k = ksavev;
211: V->l = lsavev;
212: W->k = ksavew;
213: W->l = lsavew;
214: PetscCall(PetscLogEventEnd(BV_OrthogonalizeVec,V,0,0,0));
216: /* scale */
217: PetscCall(PetscLogEventBegin(BV_Scale,V,0,0,0));
218: PetscCall(BVGetColumn(V,j,&y));
219: PetscCall(BVGetColumn(W,j,&z));
220: PetscCall(VecDot(z,y,&alpha));
221: PetscCall(BVRestoreColumn(V,j,&y));
222: PetscCall(BVRestoreColumn(W,j,&z));
223: deltat = PetscSqrtReal(PetscAbsScalar(alpha));
224: PetscUseTypeMethod(V,scale,j,1.0/PetscConj(alpha/deltat));
225: PetscUseTypeMethod(W,scale,j,1.0/deltat);
226: PetscCall(PetscLogEventEnd(BV_Scale,V,0,0,0));
227: if (delta) *delta = deltat;
228: PetscCall(PetscObjectStateIncrease((PetscObject)V));
229: PetscCall(PetscObjectStateIncrease((PetscObject)W));
230: PetscFunctionReturn(PETSC_SUCCESS);
231: }