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