Actual source code: ipdot.c
1: /*
2: Dot product routines
4: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5: SLEPc - Scalable Library for Eigenvalue Problem Computations
6: Copyright (c) 2002-2011, Universitat Politecnica de Valencia, Spain
8: This file is part of SLEPc.
9:
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 <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: Level: developer
64: .seealso: IPInnerProduct()
65: @*/
66: PetscErrorCode IPNorm(IP ip,Vec x,PetscReal *norm)
67: {
74: (*ip->ops->normbegin)(ip,x,norm);
75: (*ip->ops->normend)(ip,x,norm);
76: return(0);
77: }
81: PetscErrorCode IPNormBegin_Bilinear(IP ip,Vec x,PetscReal *norm)
82: {
84: PetscScalar p;
87: IPInnerProductBegin(ip,x,x,&p);
88: return(0);
89: }
93: PetscErrorCode IPNormBegin_Sesquilinear(IP ip,Vec x,PetscReal *norm)
94: {
96: PetscScalar p;
99: if (!ip->matrix) {
100: VecNormBegin(x,NORM_2,norm);
101: } else {
102: IPInnerProductBegin(ip,x,x,&p);
103: }
104: return(0);
105: }
109: /*@
110: IPNormBegin - Starts a split phase norm computation.
112: Collective on IP and Vec
114: Input Parameters:
115: + ip - the inner product context
116: . x - input vector
117: - norm - where the result will go
119: Level: developer
121: Notes:
122: Each call to IPNormBegin() should be paired with a call to IPNormEnd().
124: .seealso: IPNormEnd(), IPNorm(), IPInnerProduct(), IPMInnerProduct(),
125: IPInnerProductBegin(), IPInnerProductEnd()
126: @*/
127: PetscErrorCode IPNormBegin(IP ip,Vec x,PetscReal *norm)
128: {
135: (*ip->ops->normbegin)(ip,x,norm);
136: return(0);
137: }
141: PetscErrorCode IPNormEnd_Bilinear(IP ip,Vec x,PetscReal *norm)
142: {
144: PetscScalar p;
147: IPInnerProductEnd(ip,x,x,&p);
148: if (PetscAbsScalar(p)<PETSC_MACHINE_EPSILON)
149: PetscInfo(ip,"Zero norm, either the vector is zero or a semi-inner product is being used\n");
150: #if defined(PETSC_USE_COMPLEX)
151: if (PetscRealPart(p)<0.0 || PetscAbsReal(PetscImaginaryPart(p))>PETSC_MACHINE_EPSILON)
152: SETERRQ(((PetscObject)ip)->comm,1,"IPNorm: The inner product is not well defined");
153: *norm = PetscSqrtScalar(PetscRealPart(p));
154: #else
155: if (p<0.0) SETERRQ(((PetscObject)ip)->comm,1,"IPNorm: The inner product is not well defined");
156: *norm = PetscSqrtScalar(p);
157: #endif
158: return(0);
159: }
163: PetscErrorCode IPNormEnd_Sesquilinear(IP ip,Vec x,PetscReal *norm)
164: {
166: PetscScalar p;
169: if (!ip->matrix) {
170: VecNormEnd(x,NORM_2,norm);
171: } else {
172: IPInnerProductEnd(ip,x,x,&p);
173: if (PetscAbsScalar(p)<PETSC_MACHINE_EPSILON)
174: PetscInfo(ip,"Zero norm, either the vector is zero or a semi-inner product is being used\n");
175: if (PetscRealPart(p)<0.0 || PetscAbsReal(PetscImaginaryPart(p))/PetscAbsScalar(p)>PETSC_MACHINE_EPSILON)
176: SETERRQ(((PetscObject)ip)->comm,1,"IPNorm: The inner product is not well defined");
177: *norm = PetscSqrtScalar(PetscRealPart(p));
178: }
179: return(0);
180: }
184: /*@
185: IPNormEnd - Ends a split phase norm computation.
187: Collective on IP and Vec
189: Input Parameters:
190: + ip - the inner product context
191: - x - input vector
193: Output Parameter:
194: . norm - the computed norm
196: Level: developer
198: Notes:
199: Each call to IPNormBegin() should be paired with a call to IPNormEnd().
201: .seealso: IPNormBegin(), IPNorm(), IPInnerProduct(), IPMInnerProduct(),
202: IPInnerProductBegin(), IPInnerProductEnd()
203: @*/
204: PetscErrorCode IPNormEnd(IP ip,Vec x,PetscReal *norm)
205: {
212: (*ip->ops->normend)(ip,x,norm);
213: return(0);
214: }
218: /*@
219: IPInnerProduct - Computes the inner product of two vectors.
221: Collective on IP and Vec
223: Input Parameters:
224: + ip - the inner product context
225: . x - input vector
226: - y - input vector
228: Output Parameter:
229: . p - result of the inner product
231: Notes:
232: This function will usually compute the standard dot product of vectors
233: x and y, (x,y)=y^H x. However this behaviour may be different if changed
234: via IPSetMatrix(). This allows use of other inner products such as
235: the indefinite product y^T x for complex symmetric problems or the
236: B-inner product for positive definite B, (x,y)_B=y^H Bx.
238: Level: developer
240: .seealso: IPSetMatrix(), VecDot(), IPMInnerProduct()
241: @*/
242: PetscErrorCode IPInnerProduct(IP ip,Vec x,Vec y,PetscScalar *p)
243: {
251: PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);
252: ip->innerproducts++;
253: (*ip->ops->innerproductbegin)(ip,x,y,p);
254: (*ip->ops->innerproductend)(ip,x,y,p);
255: PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);
256: return(0);
257: }
261: PetscErrorCode IPInnerProductBegin_Bilinear(IP ip,Vec x,Vec y,PetscScalar *p)
262: {
266: if (ip->matrix) {
267: IPApplyMatrix_Private(ip,x);
268: VecXDotBegin(ip->Bx,y,p);
269: } else {
270: VecXDotBegin(x,y,p);
271: }
272: return(0);
273: }
277: PetscErrorCode IPInnerProductBegin_Sesquilinear(IP ip,Vec x,Vec y,PetscScalar *p)
278: {
282: if (ip->matrix) {
283: IPApplyMatrix_Private(ip,x);
284: VecDotBegin(ip->Bx,y,p);
285: } else {
286: VecDotBegin(x,y,p);
287: }
288: return(0);
289: }
293: /*@
294: IPInnerProductBegin - Starts a split phase inner product computation.
296: Collective on IP and Vec
298: Input Parameters:
299: + ip - the inner product context
300: . x - the first vector
301: . y - the second vector
302: - p - where the result will go
304: Level: developer
306: Notes:
307: Each call to IPInnerProductBegin() should be paired with a call to IPInnerProductEnd().
309: .seealso: IPInnerProductEnd(), IPInnerProduct(), IPNorm(), IPNormBegin(),
310: IPNormEnd(), IPMInnerProduct()
311: @*/
312: PetscErrorCode IPInnerProductBegin(IP ip,Vec x,Vec y,PetscScalar *p)
313: {
321: PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);
322: ip->innerproducts++;
323: (*ip->ops->innerproductbegin)(ip,x,y,p);
324: PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);
325: return(0);
326: }
330: PetscErrorCode IPInnerProductEnd_Bilinear(IP ip,Vec x,Vec y,PetscScalar *p)
331: {
335: if (ip->matrix) {
336: VecXDotEnd(ip->Bx,y,p);
337: } else {
338: VecXDotEnd(x,y,p);
339: }
340: return(0);
341: }
345: PetscErrorCode IPInnerProductEnd_Sesquilinear(IP ip,Vec x,Vec y,PetscScalar *p)
346: {
350: if (ip->matrix) {
351: VecDotEnd(ip->Bx,y,p);
352: } else {
353: VecDotEnd(x,y,p);
354: }
355: return(0);
356: }
360: /*@
361: IPInnerProductEnd - Ends a split phase inner product computation.
363: Collective on IP and Vec
365: Input Parameters:
366: + ip - the inner product context
367: . x - the first vector
368: - y - the second vector
370: Output Parameter:
371: . p - result of the inner product
373: Level: developer
375: Notes:
376: Each call to IPInnerProductBegin() should be paired with a call to IPInnerProductEnd().
378: .seealso: IPInnerProductBegin(), IPInnerProduct(), IPNorm(), IPNormBegin(),
379: IPNormEnd(), IPMInnerProduct()
380: @*/
381: PetscErrorCode IPInnerProductEnd(IP ip,Vec x,Vec y,PetscScalar *p)
382: {
390: PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);
391: (*ip->ops->innerproductend)(ip,x,y,p);
392: PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);
393: return(0);
394: }
398: /*@
399: IPMInnerProduct - Computes the inner products a vector x with a set of
400: vectors (columns of Y).
402: Collective on IP and Vec
404: Input Parameters:
405: + ip - the inner product context
406: . x - the first input vector
407: . n - number of vectors in y
408: - y - array of vectors
410: Output Parameter:
411: . p - result of the inner products
413: Notes:
414: This function will usually compute the standard dot product of x and y_i,
415: (x,y_i)=y_i^H x, for each column of Y. However this behaviour may be different
416: if changed via IPSetMatrix(). This allows use of other inner products
417: such as the indefinite product y_i^T x for complex symmetric problems or the
418: B-inner product for positive definite B, (x,y_i)_B=y_i^H Bx.
420: Level: developer
422: .seealso: IPSetMatrix(), VecMDot(), IPInnerProduct()
423: @*/
424: PetscErrorCode IPMInnerProduct(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
425: {
434: PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);
435: ip->innerproducts += n;
436: (*ip->ops->minnerproductbegin)(ip,x,n,y,p);
437: (*ip->ops->minnerproductend)(ip,x,n,y,p);
438: PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);
439: return(0);
440: }
444: PetscErrorCode IPMInnerProductBegin_Bilinear(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
445: {
449: if (ip->matrix) {
450: IPApplyMatrix_Private(ip,x);
451: VecMXDotBegin(ip->Bx,n,y,p);
452: } else {
453: VecMXDotBegin(x,n,y,p);
454: }
455: return(0);
456: }
460: PetscErrorCode IPMInnerProductBegin_Sesquilinear(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
461: {
465: if (ip->matrix) {
466: IPApplyMatrix_Private(ip,x);
467: VecMDotBegin(ip->Bx,n,y,p);
468: } else {
469: VecMDotBegin(x,n,y,p);
470: }
471: return(0);
472: }
476: /*@
477: IPMInnerProductBegin - Starts a split phase multiple inner product computation.
479: Collective on IP and Vec
481: Input Parameters:
482: + ip - the inner product context
483: . x - the first input vector
484: . n - number of vectors in y
485: . y - array of vectors
486: - p - where the result will go
488: Level: developer
490: Notes:
491: Each call to IPMInnerProductBegin() should be paired with a call to IPMInnerProductEnd().
493: .seealso: IPMInnerProductEnd(), IPMInnerProduct(), IPNorm(), IPNormBegin(),
494: IPNormEnd(), IPInnerProduct()
495: @*/
496: PetscErrorCode IPMInnerProductBegin(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
497: {
503: if (n == 0) return(0);
507: PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);
508: ip->innerproducts += n;
509: (*ip->ops->minnerproductbegin)(ip,x,n,y,p);
510: PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);
511: return(0);
512: }
516: PetscErrorCode IPMInnerProductEnd_Bilinear(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
517: {
521: if (ip->matrix) {
522: VecMXDotEnd(ip->Bx,n,y,p);
523: } else {
524: VecMXDotEnd(x,n,y,p);
525: }
526: return(0);
527: }
531: PetscErrorCode IPMInnerProductEnd_Sesquilinear(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
532: {
536: if (ip->matrix) {
537: VecMDotEnd(ip->Bx,n,y,p);
538: } else {
539: VecMDotEnd(x,n,y,p);
540: }
541: return(0);
542: }
546: /*@
547: IPMInnerProductEnd - Ends a split phase multiple inner product computation.
549: Collective on IP and Vec
551: Input Parameters:
552: + ip - the inner product context
553: . x - the first input vector
554: . n - number of vectors in y
555: - y - array of vectors
557: Output Parameter:
558: . p - result of the inner products
560: Level: developer
562: Notes:
563: Each call to IPMInnerProductBegin() should be paired with a call to IPMInnerProductEnd().
565: .seealso: IPMInnerProductBegin(), IPMInnerProduct(), IPNorm(), IPNormBegin(),
566: IPNormEnd(), IPInnerProduct()
567: @*/
568: PetscErrorCode IPMInnerProductEnd(IP ip,Vec x,PetscInt n,const Vec y[],PetscScalar *p)
569: {
575: if (n == 0) return(0);
579: PetscLogEventBegin(IP_InnerProduct,ip,x,0,0);
580: (*ip->ops->minnerproductend)(ip,x,n,y,p);
581: PetscLogEventEnd(IP_InnerProduct,ip,x,0,0);
582: return(0);
583: }
588: PetscErrorCode IPCreate_Bilinear(IP ip)
589: {
591: ip->ops->normbegin = IPNormBegin_Bilinear;
592: ip->ops->normend = IPNormEnd_Bilinear;
593: ip->ops->innerproductbegin = IPInnerProductBegin_Bilinear;
594: ip->ops->innerproductend = IPInnerProductEnd_Bilinear;
595: ip->ops->minnerproductbegin = IPMInnerProductBegin_Bilinear;
596: ip->ops->minnerproductend = IPMInnerProductEnd_Bilinear;
597: return(0);
598: }
600: #if defined(PETSC_USE_COMPLEX)
603: PetscErrorCode IPCreate_Sesquilinear(IP ip)
604: {
606: ip->ops->normbegin = IPNormBegin_Sesquilinear;
607: ip->ops->normend = IPNormEnd_Sesquilinear;
608: ip->ops->innerproductbegin = IPInnerProductBegin_Sesquilinear;
609: ip->ops->innerproductend = IPInnerProductEnd_Sesquilinear;
610: ip->ops->minnerproductbegin = IPMInnerProductBegin_Sesquilinear;
611: ip->ops->minnerproductend = IPMInnerProductEnd_Sesquilinear;
612: return(0);
613: }
614: #endif