Actual source code: ipdot.c
1: /*
2: Dot product routines
4: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5: SLEPc - Scalable Library for Eigenvalue Problem Computations
6: Copyright (c) 2002-2013, Universitat Politecnica de Valencia, Spain
8: This file is part of SLEPc.
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.
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.
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: */
24: #include <slepc-private/ipimpl.h> /*I "slepcip.h" I*/
26: /* The following definitions are intended to avoid using the "T" versions
27: of dot products in the case of real scalars */
28: #if defined(PETSC_USE_COMPLEX)
29: #define VecXDotBegin VecTDotBegin
30: #define VecXDotEnd VecTDotEnd
31: #define VecMXDotBegin VecMTDotBegin
32: #define VecMXDotEnd VecMTDotEnd
33: #else
34: #define VecXDotBegin VecDotBegin
35: #define VecXDotEnd VecDotEnd
36: #define VecMXDotBegin VecMDotBegin
37: #define VecMXDotEnd VecMDotEnd
38: #endif
42: /*@
43: IPNorm - Computes the norm of a vector as the square root of the inner
44: product (x,x) as defined by IPInnerProduct().
46: Collective on IP and Vec
48: Input Parameters:
49: + ip - the inner product context
50: - x - input vector
52: Output Parameter:
53: . norm - the computed norm
55: Notes:
56: This function will usually compute the 2-norm of a vector, ||x||_2. But
57: this behaviour may be different if using a non-standard inner product changed
58: via IPSetMatrix(). For example, if using the B-inner product for
59: positive definite B, (x,y)_B=y^H Bx, then the computed norm is ||x||_B =
60: sqrt(x^H Bx).
62: In an indefinite inner product, matrix B is indefinite and the norm is
63: defined as s*sqrt(abs(x^H Bx)), where s = sign(x^H Bx).
65: Level: developer
67: .seealso: IPInnerProduct()
68: @*/
69: PetscErrorCode IPNorm(IP ip,Vec x,PetscReal *norm)
70: {
77: (*ip->ops->normbegin)(ip,x,norm);
78: (*ip->ops->normend)(ip,x,norm);
79: return(0);
80: }
84: PetscErrorCode IPNormBegin_Bilinear(IP ip,Vec x,PetscReal *norm)
85: {
87: PetscScalar p;
90: IPInnerProductBegin(ip,x,x,&p);
91: return(0);
92: }
96: PetscErrorCode IPNormBegin_Sesquilin(IP ip,Vec x,PetscReal *norm)
97: {
99: PetscScalar p;
102: if (!ip->matrix) {
103: VecNormBegin(x,NORM_2,norm);
104: } else {
105: IPInnerProductBegin(ip,x,x,&p);
106: }
107: return(0);
108: }
112: PetscErrorCode IPNormBegin_Indefinite(IP ip,Vec x,PetscReal *norm)
113: {
115: PetscScalar p;
118: if (!ip->matrix) {
119: VecNormBegin(x,NORM_2,norm);
120: } else {
121: IPInnerProductBegin(ip,x,x,&p);
122: }
123: return(0);
124: }
128: /*@
129: IPNormBegin - Starts a split phase norm computation.
131: Collective on IP and Vec
133: Input Parameters:
134: + ip - the inner product context
135: . x - input vector
136: - norm - where the result will go
138: Level: developer
140: Notes:
141: Each call to IPNormBegin() should be paired with a call to IPNormEnd().
143: .seealso: IPNormEnd(), IPNorm(), IPInnerProduct(), IPMInnerProduct(),
144: IPInnerProductBegin(), IPInnerProductEnd()
145: @*/
146: PetscErrorCode IPNormBegin(IP ip,Vec x,PetscReal *norm)
147: {
154: (*ip->ops->normbegin)(ip,x,norm);
155: return(0);
156: }
160: PetscErrorCode IPNormEnd_Bilinear(IP ip,Vec x,PetscReal *norm)
161: {
163: PetscScalar p;
166: IPInnerProductEnd(ip,x,x,&p);
167: if (PetscAbsScalar(p)<PETSC_MACHINE_EPSILON)
168: PetscInfo(ip,"Zero norm, either the vector is zero or a semi-inner product is being used\n");
169: #if defined(PETSC_USE_COMPLEX)
170: if (PetscRealPart(p)<0.0 || PetscAbsReal(PetscImaginaryPart(p))>PETSC_MACHINE_EPSILON)
171: SETERRQ(PetscObjectComm((PetscObject)ip),1,"IPNorm: The inner product is not well defined");
172: *norm = PetscSqrtScalar(PetscRealPart(p));
173: #else
174: if (p<0.0) SETERRQ(PetscObjectComm((PetscObject)ip),1,"IPNorm: The inner product is not well defined");
175: *norm = PetscSqrtScalar(p);
176: #endif
177: return(0);
178: }
182: PetscErrorCode IPNormEnd_Sesquilin(IP ip,Vec x,PetscReal *norm)
183: {
185: PetscScalar p;
188: if (!ip->matrix) {
189: VecNormEnd(x,NORM_2,norm);
190: } else {
191: IPInnerProductEnd(ip,x,x,&p);
192: if (PetscAbsScalar(p)<PETSC_MACHINE_EPSILON)
193: PetscInfo(ip,"Zero norm, either the vector is zero or a semi-inner product is being used\n");
194: if (PetscRealPart(p)<0.0 || PetscAbsReal(PetscImaginaryPart(p))/PetscAbsScalar(p)>PETSC_MACHINE_EPSILON)
195: SETERRQ(PetscObjectComm((PetscObject)ip),1,"IPNorm: The inner product is not well defined");
196: *norm = PetscSqrtScalar(PetscRealPart(p));
197: }
198: return(0);
199: }
203: PetscErrorCode IPNormEnd_Indefinite(IP ip,Vec x,PetscReal *norm)
204: {
206: PetscScalar p;
209: if (!ip->matrix) {
210: VecNormEnd(x,NORM_2,norm);
211: } else {
212: IPInnerProductEnd(ip,x,x,&p);
213: if (PetscAbsScalar(p)<PETSC_MACHINE_EPSILON)
214: PetscInfo(ip,"Zero norm, either the vector is zero or a semi-inner product is being used\n");
215: if (PetscAbsReal(PetscImaginaryPart(p))/PetscAbsScalar(p)>PETSC_SQRT_MACHINE_EPSILON)
216: SETERRQ(PetscObjectComm((PetscObject)ip),1,"IPNorm: The inner product is not well defined");
217: if (PetscRealPart(p)<0.0) *norm = -PetscSqrtScalar(-PetscRealPart(p));
218: else *norm = PetscSqrtScalar(PetscRealPart(p));
219: }
220: return(0);
221: }
225: /*@
226: IPNormEnd - Ends a split phase norm computation.
228: Collective on IP and Vec
230: Input Parameters:
231: + ip - the inner product context
232: - x - input vector
234: Output Parameter:
235: . norm - the computed norm
237: Level: developer
239: Notes:
240: Each call to IPNormBegin() should be paired with a call to IPNormEnd().
242: .seealso: IPNormBegin(), IPNorm(), IPInnerProduct(), IPMInnerProduct(),
243: IPInnerProductBegin(), IPInnerProductEnd()
244: @*/
245: PetscErrorCode IPNormEnd(IP ip,Vec x,PetscReal *norm)
246: {
253: (*ip->ops->normend)(ip,x,norm);
254: return(0);
255: }
259: /*@
260: IPInnerProduct - Computes the inner product of two vectors.
262: Collective on IP and Vec
264: Input Parameters:
265: + ip - the inner product context
266: . x - input vector
267: - y - input vector
269: Output Parameter:
270: . p - result of the inner product
272: Notes:
273: This function will usually compute the standard dot product of vectors
274: x and y, (x,y)=y^H x. However this behaviour may be different if changed
275: via IPSetMatrix(). This allows use of other inner products such as
276: the indefinite product y^T x for complex symmetric problems or the
277: B-inner product for positive definite B, (x,y)_B=y^H Bx.
279: Level: developer
281: .seealso: IPSetMatrix(), VecDot(), IPMInnerProduct()
282: @*/
283: PetscErrorCode IPInnerProduct(IP ip,Vec x,Vec y,PetscScalar *p)
284: {
292: PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);
293: ip->innerproducts++;
294: (*ip->ops->innerproductbegin)(ip,x,y,p);
295: (*ip->ops->innerproductend)(ip,x,y,p);
296: PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);
297: return(0);
298: }
302: PetscErrorCode IPInnerProductBegin_Bilinear(IP ip,Vec x,Vec y,PetscScalar *p)
303: {
307: if (ip->matrix) {
308: IPApplyMatrix_Private(ip,x);
309: VecXDotBegin(ip->Bx,y,p);
310: } else {
311: VecXDotBegin(x,y,p);
312: }
313: return(0);
314: }
318: PetscErrorCode IPInnerProductBegin_Sesquilin(IP ip,Vec x,Vec y,PetscScalar *p)
319: {
323: if (ip->matrix) {
324: IPApplyMatrix_Private(ip,x);
325: VecDotBegin(ip->Bx,y,p);
326: } else {
327: VecDotBegin(x,y,p);
328: }
329: return(0);
330: }
334: /*@
335: IPInnerProductBegin - Starts a split phase inner product computation.
337: Collective on IP and Vec
339: Input Parameters:
340: + ip - the inner product context
341: . x - the first vector
342: . y - the second vector
343: - p - where the result will go
345: Level: developer
347: Notes:
348: Each call to IPInnerProductBegin() should be paired with a call to IPInnerProductEnd().
350: .seealso: IPInnerProductEnd(), IPInnerProduct(), IPNorm(), IPNormBegin(),
351: IPNormEnd(), IPMInnerProduct()
352: @*/
353: PetscErrorCode IPInnerProductBegin(IP ip,Vec x,Vec y,PetscScalar *p)
354: {
362: PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);
363: ip->innerproducts++;
364: (*ip->ops->innerproductbegin)(ip,x,y,p);
365: PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);
366: return(0);
367: }
371: PetscErrorCode IPInnerProductEnd_Bilinear(IP ip,Vec x,Vec y,PetscScalar *p)
372: {
376: if (ip->matrix) {
377: VecXDotEnd(ip->Bx,y,p);
378: } else {
379: VecXDotEnd(x,y,p);
380: }
381: return(0);
382: }
386: PetscErrorCode IPInnerProductEnd_Sesquilin(IP ip,Vec x,Vec y,PetscScalar *p)
387: {
391: if (ip->matrix) {
392: VecDotEnd(ip->Bx,y,p);
393: } else {
394: VecDotEnd(x,y,p);
395: }
396: return(0);
397: }
401: /*@
402: IPInnerProductEnd - Ends a split phase inner product computation.
404: Collective on IP and Vec
406: Input Parameters:
407: + ip - the inner product context
408: . x - the first vector
409: - y - the second vector
411: Output Parameter:
412: . p - result of the inner product
414: Level: developer
416: Notes:
417: Each call to IPInnerProductBegin() should be paired with a call to IPInnerProductEnd().
419: .seealso: IPInnerProductBegin(), IPInnerProduct(), IPNorm(), IPNormBegin(),
420: IPNormEnd(), IPMInnerProduct()
421: @*/
422: PetscErrorCode IPInnerProductEnd(IP ip,Vec x,Vec y,PetscScalar *p)
423: {
431: PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);
432: (*ip->ops->innerproductend)(ip,x,y,p);
433: PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);
434: return(0);
435: }
439: /*@
440: IPMInnerProduct - Computes the inner products a vector x with a set of
441: vectors (columns of Y).
443: Collective on IP and Vec
445: Input Parameters:
446: + ip - the inner product context
447: . x - the first input vector
448: . n - number of vectors in y
449: - y - array of vectors
451: Output Parameter:
452: . p - result of the inner products
454: Notes:
455: This function will usually compute the standard dot product of x and y_i,
456: (x,y_i)=y_i^H x, for each column of Y. However this behaviour may be different
457: if changed via IPSetMatrix(). This allows use of other inner products
458: such as the indefinite product y_i^T x for complex symmetric problems or the
459: B-inner product for positive definite B, (x,y_i)_B=y_i^H Bx.
461: Level: developer
463: .seealso: IPSetMatrix(), VecMDot(), IPInnerProduct()
464: @*/
465: PetscErrorCode IPMInnerProduct(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
466: {
475: PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);
476: ip->innerproducts += n;
477: (*ip->ops->minnerproductbegin)(ip,x,n,y,p);
478: (*ip->ops->minnerproductend)(ip,x,n,y,p);
479: PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);
480: return(0);
481: }
485: PetscErrorCode IPMInnerProductBegin_Bilinear(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
486: {
490: if (ip->matrix) {
491: IPApplyMatrix_Private(ip,x);
492: VecMXDotBegin(ip->Bx,n,y,p);
493: } else {
494: VecMXDotBegin(x,n,y,p);
495: }
496: return(0);
497: }
501: PetscErrorCode IPMInnerProductBegin_Sesquilin(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
502: {
506: if (ip->matrix) {
507: IPApplyMatrix_Private(ip,x);
508: VecMDotBegin(ip->Bx,n,y,p);
509: } else {
510: VecMDotBegin(x,n,y,p);
511: }
512: return(0);
513: }
517: /*@
518: IPMInnerProductBegin - Starts a split phase multiple inner product computation.
520: Collective on IP and Vec
522: Input Parameters:
523: + ip - the inner product context
524: . x - the first input vector
525: . n - number of vectors in y
526: . y - array of vectors
527: - p - where the result will go
529: Level: developer
531: Notes:
532: Each call to IPMInnerProductBegin() should be paired with a call to IPMInnerProductEnd().
534: .seealso: IPMInnerProductEnd(), IPMInnerProduct(), IPNorm(), IPNormBegin(),
535: IPNormEnd(), IPInnerProduct()
536: @*/
537: PetscErrorCode IPMInnerProductBegin(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
538: {
544: if (n == 0) return(0);
548: PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);
549: ip->innerproducts += n;
550: (*ip->ops->minnerproductbegin)(ip,x,n,y,p);
551: PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);
552: return(0);
553: }
557: PetscErrorCode IPMInnerProductEnd_Bilinear(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
558: {
562: if (ip->matrix) {
563: VecMXDotEnd(ip->Bx,n,y,p);
564: } else {
565: VecMXDotEnd(x,n,y,p);
566: }
567: return(0);
568: }
572: PetscErrorCode IPMInnerProductEnd_Sesquilin(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
573: {
577: if (ip->matrix) {
578: VecMDotEnd(ip->Bx,n,y,p);
579: } else {
580: VecMDotEnd(x,n,y,p);
581: }
582: return(0);
583: }
587: /*@
588: IPMInnerProductEnd - Ends a split phase multiple inner product computation.
590: Collective on IP and Vec
592: Input Parameters:
593: + ip - the inner product context
594: . x - the first input vector
595: . n - number of vectors in y
596: - y - array of vectors
598: Output Parameter:
599: . p - result of the inner products
601: Level: developer
603: Notes:
604: Each call to IPMInnerProductBegin() should be paired with a call to IPMInnerProductEnd().
606: .seealso: IPMInnerProductBegin(), IPMInnerProduct(), IPNorm(), IPNormBegin(),
607: IPNormEnd(), IPInnerProduct()
608: @*/
609: PetscErrorCode IPMInnerProductEnd(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
610: {
616: if (n == 0) return(0);
620: PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);
621: (*ip->ops->minnerproductend)(ip,x,n,y,p);
622: PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);
623: return(0);
624: }
628: PETSC_EXTERN PetscErrorCode IPCreate_Bilinear(IP ip)
629: {
631: ip->ops->normbegin = IPNormBegin_Bilinear;
632: ip->ops->normend = IPNormEnd_Bilinear;
633: ip->ops->innerproductbegin = IPInnerProductBegin_Bilinear;
634: ip->ops->innerproductend = IPInnerProductEnd_Bilinear;
635: ip->ops->minnerproductbegin = IPMInnerProductBegin_Bilinear;
636: ip->ops->minnerproductend = IPMInnerProductEnd_Bilinear;
637: return(0);
638: }
640: #if defined(PETSC_USE_COMPLEX)
643: PETSC_EXTERN PetscErrorCode IPCreate_Sesquilin(IP ip)
644: {
646: ip->ops->normbegin = IPNormBegin_Sesquilin;
647: ip->ops->normend = IPNormEnd_Sesquilin;
648: ip->ops->innerproductbegin = IPInnerProductBegin_Sesquilin;
649: ip->ops->innerproductend = IPInnerProductEnd_Sesquilin;
650: ip->ops->minnerproductbegin = IPMInnerProductBegin_Sesquilin;
651: ip->ops->minnerproductend = IPMInnerProductEnd_Sesquilin;
652: return(0);
653: }
654: #endif
658: PETSC_EXTERN PetscErrorCode IPCreate_Indefinite(IP ip)
659: {
661: ip->ops->normbegin = IPNormBegin_Indefinite;
662: ip->ops->normend = IPNormEnd_Indefinite;
663: #if defined(PETSC_USE_COMPLEX)
664: ip->ops->innerproductbegin = IPInnerProductBegin_Sesquilin;
665: ip->ops->innerproductend = IPInnerProductEnd_Sesquilin;
666: ip->ops->minnerproductbegin = IPMInnerProductBegin_Sesquilin;
667: ip->ops->minnerproductend = IPMInnerProductEnd_Sesquilin;
668: #else
669: ip->ops->innerproductbegin = IPInnerProductBegin_Bilinear;
670: ip->ops->innerproductend = IPInnerProductEnd_Bilinear;
671: ip->ops->minnerproductbegin = IPMInnerProductBegin_Bilinear;
672: ip->ops->minnerproductend = IPMInnerProductEnd_Bilinear;
673: #endif
674: return(0);
675: }