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: }