Date: 2013-09-02T10:08:32+00:00

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