Date: 2013-09-02T10:10:12+00:00

Actual source code: veccomp0.h

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-2013, Universitat Politecnica de Valencia, Spain

      6:    This file is part of SLEPc.

      8:    SLEPc is free software: you can redistribute it and/or modify it under  the
      9:    terms of version 3 of the GNU Lesser General Public License as published by
     10:    the Free Software Foundation.

     12:    SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY
     13:    WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS
     14:    FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for
     15:    more details.

     17:    You  should have received a copy of the GNU Lesser General  Public  License
     18:    along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
     19:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     20: */

     22: #include <petsc-private/vecimpl.h>     /*I  "petsvec.h"  I*/

     24: #if defined(__WITH_MPI__)
     26: #else
     28: #endif

     36: PetscErrorCode __SUF__(VecDot_Comp)(Vec a,Vec b,PetscScalar *z)
     37: {
     38:   PetscScalar    sum = 0.0,work;
     39:   PetscInt       i;
     41:   Vec_Comp       *as = (Vec_Comp*)a->data,*bs = (Vec_Comp*)b->data;

     44:   SlepcValidVecComp(a);
     45:   SlepcValidVecComp(b);
     46:   if (as->x[0]->ops->dot_local) {
     47:     for (i=0,sum=0.0;i<as->n->n;i++) {
     48:       as->x[i]->ops->dot_local(as->x[i],bs->x[i],&work);
     49:       sum += work;
     50:     }
     51: #if defined(__WITH_MPI__)
     52:     work = sum;
     53:     MPI_Allreduce(&work,&sum,1,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)a));
     54: #endif
     55:   } else {
     56:     for (i=0,sum=0.0;i<as->n->n;i++) {
     57:       VecDot(as->x[i],bs->x[i],&work);
     58:       sum += work;
     59:     }
     60:   }
     61:   *z = sum;
     62:   return(0);
     63: }

     67: PetscErrorCode __SUF__(VecMDot_Comp)(Vec a,PetscInt n,const Vec b[],PetscScalar *z)
     68: {
     69:   PetscScalar    *work,*work0,*r;
     71:   Vec_Comp       *as = (Vec_Comp*)a->data;
     72:   Vec            *bx;
     73:   PetscInt       i,j;

     76:   SlepcValidVecComp(a);
     77:   for (i=0;i<n;i++) SlepcValidVecComp(b[i]);

     79:   if (as->n->n == 0) {
     80:     *z = 0;
     81:     return(0);
     82:   }

     84:   PetscMalloc(sizeof(PetscScalar)*n,&work0);
     85:   PetscMalloc(sizeof(Vec)*n,&bx);

     87: #if defined(__WITH_MPI__)
     88:   if (as->x[0]->ops->mdot_local) {
     89:     r = work0; work = z;
     90:   } else
     91: #endif
     92:   {
     93:     r = z; work = work0;
     94:   }

     96:   /* z[i] <- a.x' * b[i].x */
     97:   for (i=0;i<n;i++) bx[i] = ((Vec_Comp*)b[i]->data)->x[0];
     98:   if (as->x[0]->ops->mdot_local) {
     99:     as->x[0]->ops->mdot_local(as->x[0],n,bx,r);
    100:   } else {
    101:     VecMDot(as->x[0],n,bx,r);
    102:   }
    103:   for (j=0;j<as->n->n;j++) {
    104:     for (i=0;i<n;i++) bx[i] = ((Vec_Comp*)b[i]->data)->x[j];
    105:     if (as->x[0]->ops->mdot_local) {
    106:       as->x[j]->ops->mdot_local(as->x[j],n,bx,work);
    107:     } else {
    108:       VecMDot(as->x[j],n,bx,work);
    109:     }
    110:     for (i=0;i<n;i++) r[i] += work[i];
    111:   }

    113:   /* If def(__WITH_MPI__) and exists mdot_local */
    114: #if defined(__WITH_MPI__)
    115:   if (as->x[0]->ops->mdot_local) {
    116:     /* z[i] <- Allreduce(work[i]) */
    117:     MPI_Allreduce(r,z,n,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)a));
    118:   }
    119: #endif

    121:   PetscFree(work0);
    122:   PetscFree(bx);
    123:   return(0);
    124: }

    128: PetscErrorCode __SUF__(VecTDot_Comp)(Vec a,Vec b,PetscScalar *z)
    129: {
    130:   PetscScalar    sum = 0.0,work;
    131:   PetscInt       i;
    133:   Vec_Comp       *as = (Vec_Comp*)a->data,*bs = (Vec_Comp*)b->data;

    136:   SlepcValidVecComp(a);
    137:   SlepcValidVecComp(b);
    138:   if (as->x[0]->ops->tdot_local) {
    139:     for (i=0,sum=0.0;i<as->n->n;i++) {
    140:       as->x[i]->ops->tdot_local(as->x[i],bs->x[i],&work);
    141:       sum += work;
    142:     }
    143: #if defined(__WITH_MPI__)
    144:     work = sum;
    145:     MPI_Allreduce(&work,&sum,1,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)a));
    146: #endif
    147:   } else {
    148:     for (i=0,sum=0.0;i<as->n->n;i++) {
    149:       VecTDot(as->x[i],bs->x[i],&work);
    150:       sum += work;
    151:     }
    152:   }
    153:   *z = sum;
    154:   return(0);
    155: }

    159: PetscErrorCode __SUF__(VecMTDot_Comp)(Vec a,PetscInt n,const Vec b[],PetscScalar *z)
    160: {
    161:   PetscScalar    *work,*work0,*r;
    163:   Vec_Comp       *as = (Vec_Comp*)a->data;
    164:   Vec            *bx;
    165:   PetscInt       i,j;

    168:   SlepcValidVecComp(a);
    169:   for (i=0;i<n;i++) SlepcValidVecComp(b[i]);

    171:   if (as->n->n == 0) {
    172:     *z = 0;
    173:     return(0);
    174:   }

    176:   PetscMalloc(sizeof(PetscScalar)*n,&work0);
    177:   PetscMalloc(sizeof(Vec)*n,&bx);

    179: #if defined(__WITH_MPI__)
    180:   if (as->x[0]->ops->mtdot_local) {
    181:     r = work0; work = z;
    182:   } else
    183: #endif
    184:   {
    185:     r = z; work = work0;
    186:   }

    188:   /* z[i] <- a.x' * b[i].x */
    189:   for (i=0;i<n;i++) bx[i] = ((Vec_Comp*)b[i]->data)->x[0];
    190:   if (as->x[0]->ops->mtdot_local) {
    191:     as->x[0]->ops->mtdot_local(as->x[0],n,bx,r);
    192:   } else {
    193:     VecMTDot(as->x[0],n,bx,r);
    194:   }
    195:   for (j=0;j<as->n->n;j++) {
    196:     for (i=0;i<n;i++) bx[i] = ((Vec_Comp*)b[i]->data)->x[j];
    197:     if (as->x[0]->ops->mtdot_local) {
    198:       as->x[j]->ops->mtdot_local(as->x[j],n,bx,work);
    199:     } else {
    200:       VecMTDot(as->x[j],n,bx,work);
    201:     }
    202:     for (i=0;i<n;i++) r[i] += work[i];
    203:   }

    205:   /* If def(__WITH_MPI__) and exists mtdot_local */
    206: #if defined(__WITH_MPI__)
    207:   if (as->x[0]->ops->mtdot_local) {
    208:     /* z[i] <- Allreduce(work[i]) */
    209:     MPI_Allreduce(r,z,n,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)a));
    210:   }
    211: #endif

    213:   PetscFree(work0);
    214:   PetscFree(bx);
    215:   return(0);
    216: }

    220: PetscErrorCode __SUF__(VecNorm_Comp)(Vec a,NormType t,PetscReal *norm)
    221: {
    222:   PetscReal      work[3],s=0.0;
    224:   Vec_Comp       *as = (Vec_Comp*)a->data;
    225:   PetscInt       i;

    228:   SlepcValidVecComp(a);
    229:   /* Initialize norm */
    230:   switch (t) {
    231:     case NORM_1: case NORM_INFINITY: *norm = 0.0; break;
    232:     case NORM_2: case NORM_FROBENIUS: *norm = 1.0; s = 0.0; break;
    233:     case NORM_1_AND_2: norm[0] = 0.0; norm[1] = 1.0; s = 0.0; break;
    234:   }
    235:   for (i=0;i<as->n->n;i++) {
    236:     if (as->x[0]->ops->norm_local) {
    237:       as->x[0]->ops->norm_local(as->x[i],t,work);
    238:     } else {
    239:       VecNorm(as->x[i],t,work);
    240:     }
    241:     /* norm+= work */
    242:     switch (t) {
    243:       case NORM_1: *norm+= *work; break;
    244:       case NORM_2: case NORM_FROBENIUS: AddNorm2(norm,&s,*work); break;
    245:       case NORM_1_AND_2: norm[0]+= work[0]; AddNorm2(&norm[1],&s,work[1]); break;
    246:       case NORM_INFINITY: *norm = PetscMax(*norm,*work); break;
    247:     }
    248:   }

    250:   /* If def(__WITH_MPI__) and exists norm_local */
    251: #if defined(__WITH_MPI__)
    252:   if (as->x[0]->ops->norm_local) {
    253:     PetscReal work0[3];
    254:     /* norm <- Allreduce(work) */
    255:     switch (t) {
    256:     case NORM_1:
    257:       work[0] = *norm;
    258:       MPI_Allreduce(work,norm,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)a));
    259:       break;
    260:     case NORM_2: case NORM_FROBENIUS:
    261:       work[0] = *norm; work[1] = s;
    262:       MPI_Allreduce(work,work0,1,MPIU_NORM2,MPIU_NORM2_SUM,PetscObjectComm((PetscObject)a));
    263:       *norm = GetNorm2(work0[0],work0[1]);
    264:       break;
    265:     case NORM_1_AND_2:
    266:       work[0] = norm[0]; work[1] = norm[1]; work[2] = s;
    267:       MPI_Allreduce(work,work0,1,MPIU_NORM1_AND_2,MPIU_NORM2_SUM,PetscObjectComm((PetscObject)a));
    268:       norm[0] = work0[0];
    269:       norm[1] = GetNorm2(work0[1],work0[2]);
    270:       break;
    271:     case NORM_INFINITY:
    272:       work[0] = *norm;
    273:       MPI_Allreduce(work,norm,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)a));
    274:       break;
    275:     }
    276:   }
    277: #else
    278:   /* Norm correction */
    279:   switch (t) {
    280:     case NORM_2: case NORM_FROBENIUS: *norm = GetNorm2(*norm,s); break;
    281:     case NORM_1_AND_2: norm[1] = GetNorm2(norm[1],s); break;
    282:     default: ;
    283:   }
    284: #endif
    285:   return(0);
    286: }

    290: PetscErrorCode __SUF__(VecDotNorm2_Comp)(Vec v,Vec w,PetscScalar *dp,PetscScalar *nm)
    291: {
    292:   PetscScalar    *vx,*wx,dp0,nm0,dp1,nm1;
    294:   Vec_Comp       *vs = (Vec_Comp*)v->data,*ws = (Vec_Comp*)w->data;
    295:   PetscInt       i,n;
    296:   PetscBool      t0,t1;
    297: #if defined(__WITH_MPI__)
    298:   PetscScalar    work[4];
    299: #endif

    302:   /* Compute recursively the local part */
    303:   dp0 = nm0 = 0.0;
    304:   PetscObjectTypeCompare((PetscObject)v,VECCOMP,&t0);
    305:   PetscObjectTypeCompare((PetscObject)w,VECCOMP,&t1);
    306:   if (t0 && t1) {
    307:     SlepcValidVecComp(v);
    308:     SlepcValidVecComp(w);
    309:     for (i=0;i<vs->n->n;i++) {
    310:       VecDotNorm2_Comp_Seq(vs->x[i],ws->x[i],&dp1,&nm1);
    311:       dp0 += dp1;
    312:       nm0 += nm1;
    313:     }
    314:   } else if (!t0 && !t1) {
    315:     VecGetLocalSize(v,&n);
    316:     VecGetArray(v,&vx);
    317:     VecGetArray(w,&wx);
    318:     for (i=0;i<n;i++) {
    319:       dp0 += vx[i]*PetscConj(wx[i]);
    320:       nm0 += wx[i]*PetscConj(wx[i]);
    321:     }
    322:     VecRestoreArray(v,&vx);
    323:     VecRestoreArray(w,&wx);
    324:   } else SETERRQ(PetscObjectComm((PetscObject)v),PETSC_ERR_ARG_INCOMP,"Incompatible vector types");

    326: #if defined(__WITH_MPI__)
    327:     /* [dp, nm] <- Allreduce([dp0, nm0]) */
    328:     work[0] = dp0; work[1] = nm0;
    329:     MPI_Allreduce(work,&work[2],2,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)v));
    330:     *dp = work[2]; *nm = work[3];
    331: #else
    332:     *dp = dp0; *nm = nm0;
    333: #endif
    334:   return(0);
    335: }