Actual source code: vinv.c
petsc-3.10.5 2019-03-28
Report Typos and Errors

      2: /*
      3:      Some useful vector utility functions.
      4: */
      5:  #include <../src/vec/vec/impls/mpi/pvecimpl.h>
      6: extern MPI_Op MPIU_MAXINDEX_OP;
      7: extern MPI_Op MPIU_MININDEX_OP;

      9: /*@
     10:    VecStrideSet - Sets a subvector of a vector defined
     11:    by a starting point and a stride with a given value

     13:    Logically Collective on Vec

     15:    Input Parameter:
     16: +  v - the vector
     17: .  start - starting point of the subvector (defined by a stride)
     18: -  s - value to set for each entry in that subvector

     20:    Notes:
     21:    One must call VecSetBlockSize() before this routine to set the stride
     22:    information, or use a vector created from a multicomponent DMDA.

     24:    This will only work if the desire subvector is a stride subvector

     26:    Level: advanced

     28:    Concepts: scale^on stride of vector
     29:    Concepts: stride^scale

     31: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideScale()
     32: @*/
     33: PetscErrorCode  VecStrideSet(Vec v,PetscInt start,PetscScalar s)
     34: {
     36:   PetscInt       i,n,bs;
     37:   PetscScalar    *x;

     43:   VecLocked(v,1);
     44:
     45:   VecGetLocalSize(v,&n);
     46:   VecGetArray(v,&x);
     47:   VecGetBlockSize(v,&bs);
     48:   if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
     49:   else if (start >= bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n  Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
     50:   x += start;

     52:   for (i=0; i<n; i+=bs) x[i] = s;
     53:   x -= start;

     55:   VecRestoreArray(v,&x);
     56:   return(0);
     57: }

     59: /*@
     60:    VecStrideScale - Scales a subvector of a vector defined
     61:    by a starting point and a stride.

     63:    Logically Collective on Vec

     65:    Input Parameter:
     66: +  v - the vector
     67: .  start - starting point of the subvector (defined by a stride)
     68: -  scale - value to multiply each subvector entry by

     70:    Notes:
     71:    One must call VecSetBlockSize() before this routine to set the stride
     72:    information, or use a vector created from a multicomponent DMDA.

     74:    This will only work if the desire subvector is a stride subvector

     76:    Level: advanced

     78:    Concepts: scale^on stride of vector
     79:    Concepts: stride^scale

     81: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideScale()
     82: @*/
     83: PetscErrorCode  VecStrideScale(Vec v,PetscInt start,PetscScalar scale)
     84: {
     86:   PetscInt       i,n,bs;
     87:   PetscScalar    *x;

     93:   VecLocked(v,1);
     94:
     95:   VecGetLocalSize(v,&n);
     96:   VecGetArray(v,&x);
     97:   VecGetBlockSize(v,&bs);
     98:   if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
     99:   else if (start >= bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n  Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
    100:   x += start;

    102:   for (i=0; i<n; i+=bs) x[i] *= scale;
    103:   x -= start;

    105:   VecRestoreArray(v,&x);
    106:   return(0);
    107: }

    109: /*@
    110:    VecStrideNorm - Computes the norm of subvector of a vector defined
    111:    by a starting point and a stride.

    113:    Collective on Vec

    115:    Input Parameter:
    116: +  v - the vector
    117: .  start - starting point of the subvector (defined by a stride)
    118: -  ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY

    120:    Output Parameter:
    121: .  norm - the norm

    123:    Notes:
    124:    One must call VecSetBlockSize() before this routine to set the stride
    125:    information, or use a vector created from a multicomponent DMDA.

    127:    If x is the array representing the vector x then this computes the norm
    128:    of the array (x[start],x[start+stride],x[start+2*stride], ....)

    130:    This is useful for computing, say the norm of the pressure variable when
    131:    the pressure is stored (interlaced) with other variables, say density etc.

    133:    This will only work if the desire subvector is a stride subvector

    135:    Level: advanced

    137:    Concepts: norm^on stride of vector
    138:    Concepts: stride^norm

    140: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
    141: @*/
    142: PetscErrorCode  VecStrideNorm(Vec v,PetscInt start,NormType ntype,PetscReal *nrm)
    143: {
    144:   PetscErrorCode    ierr;
    145:   PetscInt          i,n,bs;
    146:   const PetscScalar *x;
    147:   PetscReal         tnorm;
    148:   MPI_Comm          comm;

    153:   VecGetLocalSize(v,&n);
    154:   VecGetArrayRead(v,&x);
    155:   PetscObjectGetComm((PetscObject)v,&comm);

    157:   VecGetBlockSize(v,&bs);
    158:   if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
    159:   else if (start >= bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
    160:   x += start;

    162:   if (ntype == NORM_2) {
    163:     PetscScalar sum = 0.0;
    164:     for (i=0; i<n; i+=bs) sum += x[i]*(PetscConj(x[i]));
    165:     tnorm = PetscRealPart(sum);
    166:     MPIU_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPIU_SUM,comm);
    167:     *nrm  = PetscSqrtReal(*nrm);
    168:   } else if (ntype == NORM_1) {
    169:     tnorm = 0.0;
    170:     for (i=0; i<n; i+=bs) tnorm += PetscAbsScalar(x[i]);
    171:     MPIU_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPIU_SUM,comm);
    172:   } else if (ntype == NORM_INFINITY) {
    173:     PetscReal tmp;
    174:     tnorm = 0.0;

    176:     for (i=0; i<n; i+=bs) {
    177:       if ((tmp = PetscAbsScalar(x[i])) > tnorm) tnorm = tmp;
    178:       /* check special case of tmp == NaN */
    179:       if (tmp != tmp) {tnorm = tmp; break;}
    180:     }
    181:     MPIU_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPIU_MAX,comm);
    182:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
    183:   VecRestoreArrayRead(v,&x);
    184:   return(0);
    185: }

    187: /*@
    188:    VecStrideMax - Computes the maximum of subvector of a vector defined
    189:    by a starting point and a stride and optionally its location.

    191:    Collective on Vec

    193:    Input Parameter:
    194: +  v - the vector
    195: -  start - starting point of the subvector (defined by a stride)

    197:    Output Parameter:
    198: +  index - the location where the maximum occurred  (pass NULL if not required)
    199: -  nrm - the maximum value in the subvector

    201:    Notes:
    202:    One must call VecSetBlockSize() before this routine to set the stride
    203:    information, or use a vector created from a multicomponent DMDA.

    205:    If xa is the array representing the vector x, then this computes the max
    206:    of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)

    208:    This is useful for computing, say the maximum of the pressure variable when
    209:    the pressure is stored (interlaced) with other variables, e.g., density, etc.
    210:    This will only work if the desire subvector is a stride subvector.

    212:    Level: advanced

    214:    Concepts: maximum^on stride of vector
    215:    Concepts: stride^maximum

    217: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
    218: @*/
    219: PetscErrorCode  VecStrideMax(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
    220: {
    221:   PetscErrorCode    ierr;
    222:   PetscInt          i,n,bs,id;
    223:   const PetscScalar *x;
    224:   PetscReal         max,tmp;
    225:   MPI_Comm          comm;

    231:   VecGetLocalSize(v,&n);
    232:   VecGetArrayRead(v,&x);
    233:   PetscObjectGetComm((PetscObject)v,&comm);

    235:   VecGetBlockSize(v,&bs);
    236:   if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
    237:   else if (start >= bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
    238:   x += start;

    240:   id = -1;
    241:   if (!n) max = PETSC_MIN_REAL;
    242:   else {
    243:     id  = 0;
    244:     max = PetscRealPart(x[0]);
    245:     for (i=bs; i<n; i+=bs) {
    246:       if ((tmp = PetscRealPart(x[i])) > max) { max = tmp; id = i;}
    247:     }
    248:   }
    249:   VecRestoreArrayRead(v,&x);

    251:   if (!idex) {
    252:     MPIU_Allreduce(&max,nrm,1,MPIU_REAL,MPIU_MAX,comm);
    253:   } else {
    254:     PetscReal in[2],out[2];
    255:     PetscInt  rstart;

    257:     VecGetOwnershipRange(v,&rstart,NULL);
    258:     in[0] = max;
    259:     in[1] = rstart+id+start;
    260:     MPIU_Allreduce(in,out,2,MPIU_REAL,MPIU_MAXINDEX_OP,PetscObjectComm((PetscObject)v));
    261:     *nrm  = out[0];
    262:     *idex = (PetscInt)out[1];
    263:   }
    264:   return(0);
    265: }

    267: /*@
    268:    VecStrideMin - Computes the minimum of subvector of a vector defined
    269:    by a starting point and a stride and optionally its location.

    271:    Collective on Vec

    273:    Input Parameter:
    274: +  v - the vector
    275: -  start - starting point of the subvector (defined by a stride)

    277:    Output Parameter:
    278: +  idex - the location where the minimum occurred. (pass NULL if not required)
    279: -  nrm - the minimum value in the subvector

    281:    Level: advanced

    283:    Notes:
    284:    One must call VecSetBlockSize() before this routine to set the stride
    285:    information, or use a vector created from a multicomponent DMDA.

    287:    If xa is the array representing the vector x, then this computes the min
    288:    of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)

    290:    This is useful for computing, say the minimum of the pressure variable when
    291:    the pressure is stored (interlaced) with other variables, e.g., density, etc.
    292:    This will only work if the desire subvector is a stride subvector.

    294:    Concepts: minimum^on stride of vector
    295:    Concepts: stride^minimum

    297: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
    298: @*/
    299: PetscErrorCode  VecStrideMin(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
    300: {
    301:   PetscErrorCode    ierr;
    302:   PetscInt          i,n,bs,id;
    303:   const PetscScalar *x;
    304:   PetscReal         min,tmp;
    305:   MPI_Comm          comm;

    311:   VecGetLocalSize(v,&n);
    312:   VecGetArrayRead(v,&x);
    313:   PetscObjectGetComm((PetscObject)v,&comm);

    315:   VecGetBlockSize(v,&bs);
    316:   if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
    317:   else if (start >= bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\nHave you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
    318:   x += start;

    320:   id = -1;
    321:   if (!n) min = PETSC_MAX_REAL;
    322:   else {
    323:     id = 0;
    324:     min = PetscRealPart(x[0]);
    325:     for (i=bs; i<n; i+=bs) {
    326:       if ((tmp = PetscRealPart(x[i])) < min) { min = tmp; id = i;}
    327:     }
    328:   }
    329:   VecRestoreArrayRead(v,&x);

    331:   if (!idex) {
    332:     MPIU_Allreduce(&min,nrm,1,MPIU_REAL,MPIU_MIN,comm);
    333:   } else {
    334:     PetscReal in[2],out[2];
    335:     PetscInt  rstart;

    337:     VecGetOwnershipRange(v,&rstart,NULL);
    338:     in[0] = min;
    339:     in[1] = rstart+id;
    340:     MPIU_Allreduce(in,out,2,MPIU_REAL,MPIU_MININDEX_OP,PetscObjectComm((PetscObject)v));
    341:     *nrm  = out[0];
    342:     *idex = (PetscInt)out[1];
    343:   }
    344:   return(0);
    345: }

    347: /*@
    348:    VecStrideScaleAll - Scales the subvectors of a vector defined
    349:    by a starting point and a stride.

    351:    Logically Collective on Vec

    353:    Input Parameter:
    354: +  v - the vector
    355: -  scales - values to multiply each subvector entry by

    357:    Notes:
    358:    One must call VecSetBlockSize() before this routine to set the stride
    359:    information, or use a vector created from a multicomponent DMDA.

    361:    The dimension of scales must be the same as the vector block size

    364:    Level: advanced

    366:    Concepts: scale^on stride of vector
    367:    Concepts: stride^scale

    369: .seealso: VecNorm(), VecStrideScale(), VecScale(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
    370: @*/
    371: PetscErrorCode  VecStrideScaleAll(Vec v,const PetscScalar *scales)
    372: {
    374:   PetscInt       i,j,n,bs;
    375:   PetscScalar    *x;

    380:   VecLocked(v,1);
    381:
    382:   VecGetLocalSize(v,&n);
    383:   VecGetArray(v,&x);
    384:   VecGetBlockSize(v,&bs);

    386:   /* need to provide optimized code for each bs */
    387:   for (i=0; i<n; i+=bs) {
    388:     for (j=0; j<bs; j++) x[i+j] *= scales[j];
    389:   }
    390:   VecRestoreArray(v,&x);
    391:   return(0);
    392: }

    394: /*@
    395:    VecStrideNormAll - Computes the norms of subvectors of a vector defined
    396:    by a starting point and a stride.

    398:    Collective on Vec

    400:    Input Parameter:
    401: +  v - the vector
    402: -  ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY

    404:    Output Parameter:
    405: .  nrm - the norms

    407:    Notes:
    408:    One must call VecSetBlockSize() before this routine to set the stride
    409:    information, or use a vector created from a multicomponent DMDA.

    411:    If x is the array representing the vector x then this computes the norm
    412:    of the array (x[start],x[start+stride],x[start+2*stride], ....) for each start < stride

    414:    The dimension of nrm must be the same as the vector block size

    416:    This will only work if the desire subvector is a stride subvector

    418:    Level: advanced

    420:    Concepts: norm^on stride of vector
    421:    Concepts: stride^norm

    423: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
    424: @*/
    425: PetscErrorCode  VecStrideNormAll(Vec v,NormType ntype,PetscReal nrm[])
    426: {
    427:   PetscErrorCode    ierr;
    428:   PetscInt          i,j,n,bs;
    429:   const PetscScalar *x;
    430:   PetscReal         tnorm[128];
    431:   MPI_Comm          comm;

    436:   VecGetLocalSize(v,&n);
    437:   VecGetArrayRead(v,&x);
    438:   PetscObjectGetComm((PetscObject)v,&comm);

    440:   VecGetBlockSize(v,&bs);
    441:   if (bs > 128) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently supports only blocksize up to 128");

    443:   if (ntype == NORM_2) {
    444:     PetscScalar sum[128];
    445:     for (j=0; j<bs; j++) sum[j] = 0.0;
    446:     for (i=0; i<n; i+=bs) {
    447:       for (j=0; j<bs; j++) sum[j] += x[i+j]*(PetscConj(x[i+j]));
    448:     }
    449:     for (j=0; j<bs; j++) tnorm[j]  = PetscRealPart(sum[j]);

    451:     MPIU_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPIU_SUM,comm);
    452:     for (j=0; j<bs; j++) nrm[j] = PetscSqrtReal(nrm[j]);
    453:   } else if (ntype == NORM_1) {
    454:     for (j=0; j<bs; j++) tnorm[j] = 0.0;

    456:     for (i=0; i<n; i+=bs) {
    457:       for (j=0; j<bs; j++) tnorm[j] += PetscAbsScalar(x[i+j]);
    458:     }

    460:     MPIU_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPIU_SUM,comm);
    461:   } else if (ntype == NORM_INFINITY) {
    462:     PetscReal tmp;
    463:     for (j=0; j<bs; j++) tnorm[j] = 0.0;

    465:     for (i=0; i<n; i+=bs) {
    466:       for (j=0; j<bs; j++) {
    467:         if ((tmp = PetscAbsScalar(x[i+j])) > tnorm[j]) tnorm[j] = tmp;
    468:         /* check special case of tmp == NaN */
    469:         if (tmp != tmp) {tnorm[j] = tmp; break;}
    470:       }
    471:     }
    472:     MPIU_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPIU_MAX,comm);
    473:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
    474:   VecRestoreArrayRead(v,&x);
    475:   return(0);
    476: }

    478: /*@
    479:    VecStrideMaxAll - Computes the maximums of subvectors of a vector defined
    480:    by a starting point and a stride and optionally its location.

    482:    Collective on Vec

    484:    Input Parameter:
    485: .  v - the vector

    487:    Output Parameter:
    488: +  index - the location where the maximum occurred (not supported, pass NULL,
    489:            if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
    490: -  nrm - the maximum values of each subvector

    492:    Notes:
    493:    One must call VecSetBlockSize() before this routine to set the stride
    494:    information, or use a vector created from a multicomponent DMDA.

    496:    The dimension of nrm must be the same as the vector block size

    498:    Level: advanced

    500:    Concepts: maximum^on stride of vector
    501:    Concepts: stride^maximum

    503: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
    504: @*/
    505: PetscErrorCode  VecStrideMaxAll(Vec v,PetscInt idex[],PetscReal nrm[])
    506: {
    507:   PetscErrorCode    ierr;
    508:   PetscInt          i,j,n,bs;
    509:   const PetscScalar *x;
    510:   PetscReal         max[128],tmp;
    511:   MPI_Comm          comm;

    516:   if (idex) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
    517:   VecGetLocalSize(v,&n);
    518:   VecGetArrayRead(v,&x);
    519:   PetscObjectGetComm((PetscObject)v,&comm);

    521:   VecGetBlockSize(v,&bs);
    522:   if (bs > 128) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently supports only blocksize up to 128");

    524:   if (!n) {
    525:     for (j=0; j<bs; j++) max[j] = PETSC_MIN_REAL;
    526:   } else {
    527:     for (j=0; j<bs; j++) max[j] = PetscRealPart(x[j]);

    529:     for (i=bs; i<n; i+=bs) {
    530:       for (j=0; j<bs; j++) {
    531:         if ((tmp = PetscRealPart(x[i+j])) > max[j]) max[j] = tmp;
    532:       }
    533:     }
    534:   }
    535:   MPIU_Allreduce(max,nrm,bs,MPIU_REAL,MPIU_MAX,comm);

    537:   VecRestoreArrayRead(v,&x);
    538:   return(0);
    539: }

    541: /*@
    542:    VecStrideMinAll - Computes the minimum of subvector of a vector defined
    543:    by a starting point and a stride and optionally its location.

    545:    Collective on Vec

    547:    Input Parameter:
    548: .  v - the vector

    550:    Output Parameter:
    551: +  idex - the location where the minimum occurred (not supported, pass NULL,
    552:            if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
    553: -  nrm - the minimums of each subvector

    555:    Level: advanced

    557:    Notes:
    558:    One must call VecSetBlockSize() before this routine to set the stride
    559:    information, or use a vector created from a multicomponent DMDA.

    561:    The dimension of nrm must be the same as the vector block size

    563:    Concepts: minimum^on stride of vector
    564:    Concepts: stride^minimum

    566: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
    567: @*/
    568: PetscErrorCode  VecStrideMinAll(Vec v,PetscInt idex[],PetscReal nrm[])
    569: {
    570:   PetscErrorCode    ierr;
    571:   PetscInt          i,n,bs,j;
    572:   const PetscScalar *x;
    573:   PetscReal         min[128],tmp;
    574:   MPI_Comm          comm;

    579:   if (idex) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
    580:   VecGetLocalSize(v,&n);
    581:   VecGetArrayRead(v,&x);
    582:   PetscObjectGetComm((PetscObject)v,&comm);

    584:   VecGetBlockSize(v,&bs);
    585:   if (bs > 128) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently supports only blocksize up to 128");

    587:   if (!n) {
    588:     for (j=0; j<bs; j++) min[j] = PETSC_MAX_REAL;
    589:   } else {
    590:     for (j=0; j<bs; j++) min[j] = PetscRealPart(x[j]);

    592:     for (i=bs; i<n; i+=bs) {
    593:       for (j=0; j<bs; j++) {
    594:         if ((tmp = PetscRealPart(x[i+j])) < min[j]) min[j] = tmp;
    595:       }
    596:     }
    597:   }
    598:   MPIU_Allreduce(min,nrm,bs,MPIU_REAL,MPIU_MIN,comm);

    600:   VecRestoreArrayRead(v,&x);
    601:   return(0);
    602: }

    604: /*----------------------------------------------------------------------------------------------*/
    605: /*@
    606:    VecStrideGatherAll - Gathers all the single components from a multi-component vector into
    607:    separate vectors.

    609:    Collective on Vec

    611:    Input Parameter:
    612: +  v - the vector
    613: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

    615:    Output Parameter:
    616: .  s - the location where the subvectors are stored

    618:    Notes:
    619:    One must call VecSetBlockSize() before this routine to set the stride
    620:    information, or use a vector created from a multicomponent DMDA.

    622:    If x is the array representing the vector x then this gathers
    623:    the arrays (x[start],x[start+stride],x[start+2*stride], ....)
    624:    for start=0,1,2,...bs-1

    626:    The parallel layout of the vector and the subvector must be the same;
    627:    i.e., nlocal of v = stride*(nlocal of s)

    629:    Not optimized; could be easily

    631:    Level: advanced

    633:    Concepts: gather^into strided vector

    635: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
    636:           VecStrideScatterAll()
    637: @*/
    638: PetscErrorCode  VecStrideGatherAll(Vec v,Vec s[],InsertMode addv)
    639: {
    640:   PetscErrorCode    ierr;
    641:   PetscInt          i,n,n2,bs,j,k,*bss = NULL,nv,jj,nvc;
    642:   PetscScalar       **y;
    643:   const PetscScalar *x;

    649:   VecGetLocalSize(v,&n);
    650:   VecGetLocalSize(s[0],&n2);
    651:   VecGetArrayRead(v,&x);
    652:   VecGetBlockSize(v,&bs);
    653:   if (bs <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");

    655:   PetscMalloc2(bs,&y,bs,&bss);
    656:   nv   = 0;
    657:   nvc  = 0;
    658:   for (i=0; i<bs; i++) {
    659:     VecGetBlockSize(s[i],&bss[i]);
    660:     if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1  Re: [PETSC #8241] VecStrideGatherAll */
    661:     VecGetArray(s[i],&y[i]);
    662:     nvc += bss[i];
    663:     nv++;
    664:     if (nvc > bs)  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
    665:     if (nvc == bs) break;
    666:   }

    668:   n =  n/bs;

    670:   jj = 0;
    671:   if (addv == INSERT_VALUES) {
    672:     for (j=0; j<nv; j++) {
    673:       for (k=0; k<bss[j]; k++) {
    674:         for (i=0; i<n; i++) y[j][i*bss[j] + k] = x[bs*i+jj+k];
    675:       }
    676:       jj += bss[j];
    677:     }
    678:   } else if (addv == ADD_VALUES) {
    679:     for (j=0; j<nv; j++) {
    680:       for (k=0; k<bss[j]; k++) {
    681:         for (i=0; i<n; i++) y[j][i*bss[j] + k] += x[bs*i+jj+k];
    682:       }
    683:       jj += bss[j];
    684:     }
    685: #if !defined(PETSC_USE_COMPLEX)
    686:   } else if (addv == MAX_VALUES) {
    687:     for (j=0; j<nv; j++) {
    688:       for (k=0; k<bss[j]; k++) {
    689:         for (i=0; i<n; i++) y[j][i*bss[j] + k] = PetscMax(y[j][i*bss[j] + k],x[bs*i+jj+k]);
    690:       }
    691:       jj += bss[j];
    692:     }
    693: #endif
    694:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");

    696:   VecRestoreArrayRead(v,&x);
    697:   for (i=0; i<nv; i++) {
    698:     VecRestoreArray(s[i],&y[i]);
    699:   }

    701:   PetscFree2(y,bss);
    702:   return(0);
    703: }

    705: /*@
    706:    VecStrideScatterAll - Scatters all the single components from separate vectors into
    707:      a multi-component vector.

    709:    Collective on Vec

    711:    Input Parameter:
    712: +  s - the location where the subvectors are stored
    713: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

    715:    Output Parameter:
    716: .  v - the multicomponent vector

    718:    Notes:
    719:    One must call VecSetBlockSize() before this routine to set the stride
    720:    information, or use a vector created from a multicomponent DMDA.

    722:    The parallel layout of the vector and the subvector must be the same;
    723:    i.e., nlocal of v = stride*(nlocal of s)

    725:    Not optimized; could be easily

    727:    Level: advanced

    729:    Concepts:  scatter^into strided vector

    731: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
    732:           VecStrideScatterAll()
    733: @*/
    734: PetscErrorCode  VecStrideScatterAll(Vec s[],Vec v,InsertMode addv)
    735: {
    736:   PetscErrorCode    ierr;
    737:   PetscInt          i,n,n2,bs,j,jj,k,*bss = NULL,nv,nvc;
    738:   PetscScalar       *x,**y;

    744:   VecGetLocalSize(v,&n);
    745:   VecGetLocalSize(s[0],&n2);
    746:   VecGetArray(v,&x);
    747:   VecGetBlockSize(v,&bs);
    748:   if (bs <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");

    750:   PetscMalloc2(bs,&y,bs,&bss);
    751:   nv   = 0;
    752:   nvc  = 0;
    753:   for (i=0; i<bs; i++) {
    754:     VecGetBlockSize(s[i],&bss[i]);
    755:     if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1  Re: [PETSC #8241] VecStrideGatherAll */
    756:     VecGetArray(s[i],&y[i]);
    757:     nvc += bss[i];
    758:     nv++;
    759:     if (nvc > bs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
    760:     if (nvc == bs) break;
    761:   }

    763:   n =  n/bs;

    765:   jj = 0;
    766:   if (addv == INSERT_VALUES) {
    767:     for (j=0; j<nv; j++) {
    768:       for (k=0; k<bss[j]; k++) {
    769:         for (i=0; i<n; i++) x[bs*i+jj+k] = y[j][i*bss[j] + k];
    770:       }
    771:       jj += bss[j];
    772:     }
    773:   } else if (addv == ADD_VALUES) {
    774:     for (j=0; j<nv; j++) {
    775:       for (k=0; k<bss[j]; k++) {
    776:         for (i=0; i<n; i++) x[bs*i+jj+k] += y[j][i*bss[j] + k];
    777:       }
    778:       jj += bss[j];
    779:     }
    780: #if !defined(PETSC_USE_COMPLEX)
    781:   } else if (addv == MAX_VALUES) {
    782:     for (j=0; j<nv; j++) {
    783:       for (k=0; k<bss[j]; k++) {
    784:         for (i=0; i<n; i++) x[bs*i+jj+k] = PetscMax(x[bs*i+jj+k],y[j][i*bss[j] + k]);
    785:       }
    786:       jj += bss[j];
    787:     }
    788: #endif
    789:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");

    791:   VecRestoreArray(v,&x);
    792:   for (i=0; i<nv; i++) {
    793:     VecRestoreArray(s[i],&y[i]);
    794:   }
    795:   PetscFree2(y,bss);
    796:   return(0);
    797: }

    799: /*@
    800:    VecStrideGather - Gathers a single component from a multi-component vector into
    801:    another vector.

    803:    Collective on Vec

    805:    Input Parameter:
    806: +  v - the vector
    807: .  start - starting point of the subvector (defined by a stride)
    808: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

    810:    Output Parameter:
    811: .  s - the location where the subvector is stored

    813:    Notes:
    814:    One must call VecSetBlockSize() before this routine to set the stride
    815:    information, or use a vector created from a multicomponent DMDA.

    817:    If x is the array representing the vector x then this gathers
    818:    the array (x[start],x[start+stride],x[start+2*stride], ....)

    820:    The parallel layout of the vector and the subvector must be the same;
    821:    i.e., nlocal of v = stride*(nlocal of s)

    823:    Not optimized; could be easily

    825:    Level: advanced

    827:    Concepts: gather^into strided vector

    829: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
    830:           VecStrideScatterAll()
    831: @*/
    832: PetscErrorCode  VecStrideGather(Vec v,PetscInt start,Vec s,InsertMode addv)
    833: {

    839:   if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
    840:   if (start >= v->map->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,v->map->bs);
    841:   if (!v->ops->stridegather) SETERRQ(PetscObjectComm((PetscObject)s),PETSC_ERR_SUP,"Not implemented for this Vec class");
    842:   (*v->ops->stridegather)(v,start,s,addv);
    843:   return(0);
    844: }

    846: /*@
    847:    VecStrideScatter - Scatters a single component from a vector into a multi-component vector.

    849:    Collective on Vec

    851:    Input Parameter:
    852: +  s - the single-component vector
    853: .  start - starting point of the subvector (defined by a stride)
    854: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

    856:    Output Parameter:
    857: .  v - the location where the subvector is scattered (the multi-component vector)

    859:    Notes:
    860:    One must call VecSetBlockSize() on the multi-component vector before this
    861:    routine to set the stride  information, or use a vector created from a multicomponent DMDA.

    863:    The parallel layout of the vector and the subvector must be the same;
    864:    i.e., nlocal of v = stride*(nlocal of s)

    866:    Not optimized; could be easily

    868:    Level: advanced

    870:    Concepts: scatter^into strided vector

    872: .seealso: VecStrideNorm(), VecStrideGather(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
    873:           VecStrideScatterAll(), VecStrideSubSetScatter(), VecStrideSubSetGather()
    874: @*/
    875: PetscErrorCode  VecStrideScatter(Vec s,PetscInt start,Vec v,InsertMode addv)
    876: {

    882:   if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
    883:   if (start >= v->map->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,v->map->bs);
    884:   if (!v->ops->stridescatter) SETERRQ(PetscObjectComm((PetscObject)s),PETSC_ERR_SUP,"Not implemented for this Vec class");
    885:   (*v->ops->stridescatter)(s,start,v,addv);
    886:   return(0);
    887: }

    889: /*@
    890:    VecStrideSubSetGather - Gathers a subset of components from a multi-component vector into
    891:    another vector.

    893:    Collective on Vec

    895:    Input Parameter:
    896: +  v - the vector
    897: .  nidx - the number of indices
    898: .  idxv - the indices of the components 0 <= idxv[0] ...idxv[nidx-1] < bs(v), they need not be sorted
    899: .  idxs - the indices of the components 0 <= idxs[0] ...idxs[nidx-1] < bs(s), they need not be sorted, may be null if nidx == bs(s) or is PETSC_DETERMINE
    900: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

    902:    Output Parameter:
    903: .  s - the location where the subvector is stored

    905:    Notes:
    906:    One must call VecSetBlockSize() on both vectors before this routine to set the stride
    907:    information, or use a vector created from a multicomponent DMDA.

    910:    The parallel layout of the vector and the subvector must be the same;

    912:    Not optimized; could be easily

    914:    Level: advanced

    916:    Concepts: gather^into strided vector

    918: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideGather(), VecStrideSubSetScatter(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
    919:           VecStrideScatterAll()
    920: @*/
    921: PetscErrorCode  VecStrideSubSetGather(Vec v,PetscInt nidx,const PetscInt idxv[],const PetscInt idxs[],Vec s,InsertMode addv)
    922: {

    928:   if (nidx == PETSC_DETERMINE) nidx = s->map->bs;
    929:   if (!v->ops->stridesubsetgather) SETERRQ(PetscObjectComm((PetscObject)s),PETSC_ERR_SUP,"Not implemented for this Vec class");
    930:   (*v->ops->stridesubsetgather)(v,nidx,idxv,idxs,s,addv);
    931:   return(0);
    932: }

    934: /*@
    935:    VecStrideSubSetScatter - Scatters components from a vector into a subset of components of a multi-component vector.

    937:    Collective on Vec

    939:    Input Parameter:
    940: +  s - the smaller-component vector
    941: .  nidx - the number of indices in idx
    942: .  idxs - the indices of the components in the smaller-component vector, 0 <= idxs[0] ...idxs[nidx-1] < bs(s) they need not be sorted, may be null if nidx == bs(s) or is PETSC_DETERMINE
    943: .  idxv - the indices of the components in the larger-component vector, 0 <= idx[0] ...idx[nidx-1] < bs(v) they need not be sorted
    944: -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES

    946:    Output Parameter:
    947: .  v - the location where the subvector is into scattered (the multi-component vector)

    949:    Notes:
    950:    One must call VecSetBlockSize() on the vectors before this
    951:    routine to set the stride  information, or use a vector created from a multicomponent DMDA.

    953:    The parallel layout of the vector and the subvector must be the same;

    955:    Not optimized; could be easily

    957:    Level: advanced

    959:    Concepts: scatter^into strided vector

    961: .seealso: VecStrideNorm(), VecStrideGather(), VecStrideGather(), VecStrideSubSetGather(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
    962:           VecStrideScatterAll()
    963: @*/
    964: PetscErrorCode  VecStrideSubSetScatter(Vec s,PetscInt nidx,const PetscInt idxs[],const PetscInt idxv[],Vec v,InsertMode addv)
    965: {

    971:   if (nidx == PETSC_DETERMINE) nidx = s->map->bs;
    972:   if (!v->ops->stridesubsetscatter) SETERRQ(PetscObjectComm((PetscObject)s),PETSC_ERR_SUP,"Not implemented for this Vec class");
    973:   (*v->ops->stridesubsetscatter)(s,nidx,idxs,idxv,v,addv);
    974:   return(0);
    975: }

    977: PetscErrorCode  VecStrideGather_Default(Vec v,PetscInt start,Vec s,InsertMode addv)
    978: {
    980:   PetscInt       i,n,bs,ns;
    981:   const PetscScalar *x;
    982:   PetscScalar       *y;

    985:   VecGetLocalSize(v,&n);
    986:   VecGetLocalSize(s,&ns);
    987:   VecGetArrayRead(v,&x);
    988:   VecGetArray(s,&y);

    990:   bs = v->map->bs;
    991:   if (n != ns*bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for gather from original vector %D",ns*bs,n);
    992:   x += start;
    993:   n  =  n/bs;

    995:   if (addv == INSERT_VALUES) {
    996:     for (i=0; i<n; i++) y[i] = x[bs*i];
    997:   } else if (addv == ADD_VALUES) {
    998:     for (i=0; i<n; i++) y[i] += x[bs*i];
    999: #if !defined(PETSC_USE_COMPLEX)
    1000:   } else if (addv == MAX_VALUES) {
    1001:     for (i=0; i<n; i++) y[i] = PetscMax(y[i],x[bs*i]);
    1002: #endif
    1003:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");

    1005:   VecRestoreArrayRead(v,&x);
    1006:   VecRestoreArray(s,&y);
    1007:   return(0);
    1008: }

    1010: PetscErrorCode  VecStrideScatter_Default(Vec s,PetscInt start,Vec v,InsertMode addv)
    1011: {
    1012:   PetscErrorCode    ierr;
    1013:   PetscInt          i,n,bs,ns;
    1014:   PetscScalar       *x;
    1015:   const PetscScalar *y;

    1018:   VecGetLocalSize(v,&n);
    1019:   VecGetLocalSize(s,&ns);
    1020:   VecGetArray(v,&x);
    1021:   VecGetArrayRead(s,&y);

    1023:   bs = v->map->bs;
    1024:   if (n != ns*bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for scatter to multicomponent vector %D",ns*bs,n);
    1025:   x += start;
    1026:   n  =  n/bs;

    1028:   if (addv == INSERT_VALUES) {
    1029:     for (i=0; i<n; i++) x[bs*i] = y[i];
    1030:   } else if (addv == ADD_VALUES) {
    1031:     for (i=0; i<n; i++) x[bs*i] += y[i];
    1032: #if !defined(PETSC_USE_COMPLEX)
    1033:   } else if (addv == MAX_VALUES) {
    1034:     for (i=0; i<n; i++) x[bs*i] = PetscMax(y[i],x[bs*i]);
    1035: #endif
    1036:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");

    1038:   VecRestoreArray(v,&x);
    1039:   VecRestoreArrayRead(s,&y);
    1040:   return(0);
    1041: }

    1043: PetscErrorCode  VecStrideSubSetGather_Default(Vec v,PetscInt nidx,const PetscInt idxv[],const PetscInt idxs[],Vec s,InsertMode addv)
    1044: {
    1045:   PetscErrorCode    ierr;
    1046:   PetscInt          i,j,n,bs,bss,ns;
    1047:   const PetscScalar *x;
    1048:   PetscScalar       *y;

    1051:   VecGetLocalSize(v,&n);
    1052:   VecGetLocalSize(s,&ns);
    1053:   VecGetArrayRead(v,&x);
    1054:   VecGetArray(s,&y);

    1056:   bs  = v->map->bs;
    1057:   bss = s->map->bs;
    1058:   n  =  n/bs;

    1060: #if defined(PETSC_DEBUG)
    1061:   if (n != ns/bss) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Incompatible layout of vectors");
    1062:   for (j=0; j<nidx; j++) {
    1063:     if (idxv[j] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"idx[%D] %D is negative",j,idxv[j]);
    1064:     if (idxv[j] >= bs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"idx[%D] %D is greater than or equal to vector blocksize %D",j,idxv[j],bs);
    1065:   }
    1066:   if (!idxs && bss != nidx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must provide idxs when not gathering into all locations");
    1067: #endif

    1069:   if (addv == INSERT_VALUES) {
    1070:     if (!idxs) {
    1071:       for (i=0; i<n; i++) {
    1072:         for (j=0; j<bss; j++) y[bss*i+j] = x[bs*i+idxv[j]];
    1073:       }
    1074:     } else {
    1075:       for (i=0; i<n; i++) {
    1076:         for (j=0; j<bss; j++) y[bss*i+idxs[j]] = x[bs*i+idxv[j]];
    1077:       }
    1078:     }
    1079:   } else if (addv == ADD_VALUES) {
    1080:     if (!idxs) {
    1081:       for (i=0; i<n; i++) {
    1082:         for (j=0; j<bss; j++) y[bss*i+j] += x[bs*i+idxv[j]];
    1083:       }
    1084:     } else {
    1085:       for (i=0; i<n; i++) {
    1086:         for (j=0; j<bss; j++) y[bss*i+idxs[j]] += x[bs*i+idxv[j]];
    1087:       }
    1088:     }
    1089: #if !defined(PETSC_USE_COMPLEX)
    1090:   } else if (addv == MAX_VALUES) {
    1091:     if (!idxs) {
    1092:       for (i=0; i<n; i++) {
    1093:         for (j=0; j<bss; j++) y[bss*i+j] = PetscMax(y[bss*i+j],x[bs*i+idxv[j]]);
    1094:       }
    1095:     } else {
    1096:       for (i=0; i<n; i++) {
    1097:         for (j=0; j<bss; j++) y[bss*i+idxs[j]] = PetscMax(y[bss*i+idxs[j]],x[bs*i+idxv[j]]);
    1098:       }
    1099:     }
    1100: #endif
    1101:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");

    1103:   VecRestoreArrayRead(v,&x);
    1104:   VecRestoreArray(s,&y);
    1105:   return(0);
    1106: }

    1108: PetscErrorCode  VecStrideSubSetScatter_Default(Vec s,PetscInt nidx,const PetscInt idxs[],const PetscInt idxv[],Vec v,InsertMode addv)
    1109: {
    1110:   PetscErrorCode    ierr;
    1111:   PetscInt          j,i,n,bs,ns,bss;
    1112:   PetscScalar       *x;
    1113:   const PetscScalar *y;

    1116:   VecGetLocalSize(v,&n);
    1117:   VecGetLocalSize(s,&ns);
    1118:   VecGetArray(v,&x);
    1119:   VecGetArrayRead(s,&y);

    1121:   bs  = v->map->bs;
    1122:   bss = s->map->bs;
    1123:   n  =  n/bs;

    1125: #if defined(PETSC_DEBUG)
    1126:   if (n != ns/bss) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Incompatible layout of vectors");
    1127:   for (j=0; j<bss; j++) {
    1128:     if (idx[j] < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"idx[%D] %D is negative",j,idx[j]);
    1129:     if (idx[j] >= bs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"idx[%D] %D is greater than or equal to vector blocksize %D",j,idx[j],bs);
    1130:   }
    1131:   if (!idxs && bss != nidx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must provide idxs when not scattering from all locations");
    1132: #endif

    1134:   if (addv == INSERT_VALUES) {
    1135:     if (!idxs) {
    1136:       for (i=0; i<n; i++) {
    1137:         for (j=0; j<bss; j++) x[bs*i + idxv[j]] = y[bss*i+j];
    1138:       }
    1139:     } else {
    1140:       for (i=0; i<n; i++) {
    1141:         for (j=0; j<bss; j++) x[bs*i + idxv[j]] = y[bss*i+idxs[j]];
    1142:       }
    1143:     }
    1144:   } else if (addv == ADD_VALUES) {
    1145:     if (!idxs) {
    1146:       for (i=0; i<n; i++) {
    1147:         for (j=0; j<bss; j++) x[bs*i + idxv[j]] += y[bss*i+j];
    1148:       }
    1149:     } else {
    1150:       for (i=0; i<n; i++) {
    1151:         for (j=0; j<bss; j++) x[bs*i + idxv[j]] += y[bss*i+idxs[j]];
    1152:       }
    1153:     }
    1154: #if !defined(PETSC_USE_COMPLEX)
    1155:   } else if (addv == MAX_VALUES) {
    1156:     if (!idxs) {
    1157:       for (i=0; i<n; i++) {
    1158:         for (j=0; j<bss; j++) x[bs*i + idxv[j]] = PetscMax(y[bss*i+j],x[bs*i + idxv[j]]);
    1159:       }
    1160:     } else {
    1161:       for (i=0; i<n; i++) {
    1162:         for (j=0; j<bss; j++) x[bs*i + idxv[j]] = PetscMax(y[bss*i+idxs[j]],x[bs*i + idxv[j]]);
    1163:       }
    1164:     }
    1165: #endif
    1166:   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");

    1168:   VecRestoreArray(v,&x);
    1169:   VecRestoreArrayRead(s,&y);
    1170:   return(0);
    1171: }

    1173: PetscErrorCode VecReciprocal_Default(Vec v)
    1174: {
    1176:   PetscInt       i,n;
    1177:   PetscScalar    *x;

    1180:   VecGetLocalSize(v,&n);
    1181:   VecGetArray(v,&x);
    1182:   for (i=0; i<n; i++) {
    1183:     if (x[i] != (PetscScalar)0.0) x[i] = (PetscScalar)1.0/x[i];
    1184:   }
    1185:   VecRestoreArray(v,&x);
    1186:   return(0);
    1187: }

    1189: /*@
    1190:   VecExp - Replaces each component of a vector by e^x_i

    1192:   Not collective

    1194:   Input Parameter:
    1195: . v - The vector

    1197:   Output Parameter:
    1198: . v - The vector of exponents

    1200:   Level: beginner

    1202: .seealso:  VecLog(), VecAbs(), VecSqrtAbs(), VecReciprocal()

    1204: .keywords: vector, sqrt, square root
    1205: @*/
    1206: PetscErrorCode  VecExp(Vec v)
    1207: {
    1208:   PetscScalar    *x;
    1209:   PetscInt       i, n;

    1214:   if (v->ops->exp) {
    1215:     (*v->ops->exp)(v);
    1216:   } else {
    1217:     VecGetLocalSize(v, &n);
    1218:     VecGetArray(v, &x);
    1219:     for (i = 0; i < n; i++) x[i] = PetscExpScalar(x[i]);
    1220:     VecRestoreArray(v, &x);
    1221:   }
    1222:   return(0);
    1223: }

    1225: /*@
    1226:   VecLog - Replaces each component of a vector by log(x_i), the natural logarithm

    1228:   Not collective

    1230:   Input Parameter:
    1231: . v - The vector

    1233:   Output Parameter:
    1234: . v - The vector of logs

    1236:   Level: beginner

    1238: .seealso:  VecExp(), VecAbs(), VecSqrtAbs(), VecReciprocal()

    1240: .keywords: vector, sqrt, square root
    1241: @*/
    1242: PetscErrorCode  VecLog(Vec v)
    1243: {
    1244:   PetscScalar    *x;
    1245:   PetscInt       i, n;

    1250:   if (v->ops->log) {
    1251:     (*v->ops->log)(v);
    1252:   } else {
    1253:     VecGetLocalSize(v, &n);
    1254:     VecGetArray(v, &x);
    1255:     for (i = 0; i < n; i++) x[i] = PetscLogScalar(x[i]);
    1256:     VecRestoreArray(v, &x);
    1257:   }
    1258:   return(0);
    1259: }

    1261: /*@
    1262:   VecSqrtAbs - Replaces each component of a vector by the square root of its magnitude.

    1264:   Not collective

    1266:   Input Parameter:
    1267: . v - The vector

    1269:   Output Parameter:
    1270: . v - The vector square root

    1272:   Level: beginner

    1274:   Note: The actual function is sqrt(|x_i|)

    1276: .seealso: VecLog(), VecExp(), VecReciprocal(), VecAbs()

    1278: .keywords: vector, sqrt, square root
    1279: @*/
    1280: PetscErrorCode  VecSqrtAbs(Vec v)
    1281: {
    1282:   PetscScalar    *x;
    1283:   PetscInt       i, n;

    1288:   if (v->ops->sqrt) {
    1289:     (*v->ops->sqrt)(v);
    1290:   } else {
    1291:     VecGetLocalSize(v, &n);
    1292:     VecGetArray(v, &x);
    1293:     for (i = 0; i < n; i++) x[i] = PetscSqrtReal(PetscAbsScalar(x[i]));
    1294:     VecRestoreArray(v, &x);
    1295:   }
    1296:   return(0);
    1297: }

    1299: /*@
    1300:   VecDotNorm2 - computes the inner product of two vectors and the 2-norm squared of the second vector

    1302:   Collective on Vec

    1304:   Input Parameter:
    1305: + s - first vector
    1306: - t - second vector

    1308:   Output Parameter:
    1309: + dp - s'conj(t)
    1310: - nm - t'conj(t)

    1312:   Level: advanced

    1314:   Notes:
    1315:     conj(x) is the complex conjugate of x when x is complex

    1318: .seealso:   VecDot(), VecNorm(), VecDotBegin(), VecNormBegin(), VecDotEnd(), VecNormEnd()

    1320: .keywords: vector, sqrt, square root
    1321: @*/
    1322: PetscErrorCode  VecDotNorm2(Vec s,Vec t,PetscScalar *dp, PetscReal *nm)
    1323: {
    1324:   const PetscScalar *sx, *tx;
    1325:   PetscScalar       dpx = 0.0, nmx = 0.0,work[2],sum[2];
    1326:   PetscInt          i, n;
    1327:   PetscErrorCode    ierr;

    1337:   if (s->map->N != t->map->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector global lengths");
    1338:   if (s->map->n != t->map->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector local lengths");

    1340:   PetscLogEventBegin(VEC_DotNorm2,s,t,0,0);
    1341:   if (s->ops->dotnorm2) {
    1342:     (*s->ops->dotnorm2)(s,t,dp,&dpx);
    1343:     *nm  = PetscRealPart(dpx);
    1344:   } else {
    1345:     VecGetLocalSize(s, &n);
    1346:     VecGetArrayRead(s, &sx);
    1347:     VecGetArrayRead(t, &tx);

    1349:     for (i = 0; i<n; i++) {
    1350:       dpx += sx[i]*PetscConj(tx[i]);
    1351:       nmx += tx[i]*PetscConj(tx[i]);
    1352:     }
    1353:     work[0] = dpx;
    1354:     work[1] = nmx;

    1356:     MPIU_Allreduce(work,sum,2,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)s));
    1357:     *dp  = sum[0];
    1358:     *nm  = PetscRealPart(sum[1]);

    1360:     VecRestoreArrayRead(t, &tx);
    1361:     VecRestoreArrayRead(s, &sx);
    1362:     PetscLogFlops(4.0*n);
    1363:   }
    1364:   PetscLogEventEnd(VEC_DotNorm2,s,t,0,0);
    1365:   return(0);
    1366: }

    1368: /*@
    1369:    VecSum - Computes the sum of all the components of a vector.

    1371:    Collective on Vec

    1373:    Input Parameter:
    1374: .  v - the vector

    1376:    Output Parameter:
    1377: .  sum - the result

    1379:    Level: beginner

    1381:    Concepts: sum^of vector entries

    1383: .seealso: VecNorm()
    1384: @*/
    1385: PetscErrorCode  VecSum(Vec v,PetscScalar *sum)
    1386: {
    1387:   PetscErrorCode    ierr;
    1388:   PetscInt          i,n;
    1389:   const PetscScalar *x;
    1390:   PetscScalar       lsum = 0.0;

    1395:   VecGetLocalSize(v,&n);
    1396:   VecGetArrayRead(v,&x);
    1397:   for (i=0; i<n; i++) lsum += x[i];
    1398:   MPIU_Allreduce(&lsum,sum,1,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)v));
    1399:   VecRestoreArrayRead(v,&x);
    1400:   return(0);
    1401: }

    1403: /*@
    1404:    VecShift - Shifts all of the components of a vector by computing
    1405:    x[i] = x[i] + shift.

    1407:    Logically Collective on Vec

    1409:    Input Parameters:
    1410: +  v - the vector
    1411: -  shift - the shift

    1413:    Output Parameter:
    1414: .  v - the shifted vector

    1416:    Level: intermediate

    1418:    Concepts: vector^adding constant

    1420: @*/
    1421: PetscErrorCode  VecShift(Vec v,PetscScalar shift)
    1422: {
    1424:   PetscInt       i,n;
    1425:   PetscScalar    *x;

    1430:   VecLocked(v,1);

    1432:   if (v->ops->shift) {
    1433:     (*v->ops->shift)(v,shift);
    1434:   } else {
    1435:     VecGetLocalSize(v,&n);
    1436:     VecGetArray(v,&x);
    1437:     for (i=0; i<n; i++) x[i] += shift;
    1438:     VecRestoreArray(v,&x);
    1439:   }
    1440:   return(0);
    1441: }

    1443: /*@
    1444:    VecAbs - Replaces every element in a vector with its absolute value.

    1446:    Logically Collective on Vec

    1448:    Input Parameters:
    1449: .  v - the vector

    1451:    Level: intermediate

    1453:    Concepts: vector^absolute value

    1455: @*/
    1456: PetscErrorCode  VecAbs(Vec v)
    1457: {
    1459:   PetscInt       i,n;
    1460:   PetscScalar    *x;

    1464:   VecLocked(v,1);
    1465:
    1466:   if (v->ops->abs) {
    1467:     (*v->ops->abs)(v);
    1468:   } else {
    1469:     VecGetLocalSize(v,&n);
    1470:     VecGetArray(v,&x);
    1471:     for (i=0; i<n; i++) x[i] = PetscAbsScalar(x[i]);
    1472:     VecRestoreArray(v,&x);
    1473:   }
    1474:   return(0);
    1475: }

    1477: /*@
    1478:   VecPermute - Permutes a vector in place using the given ordering.

    1480:   Input Parameters:
    1481: + vec   - The vector
    1482: . order - The ordering
    1483: - inv   - The flag for inverting the permutation

    1485:   Level: beginner

    1487:   Note: This function does not yet support parallel Index Sets with non-local permutations

    1489: .seealso: MatPermute()
    1490: .keywords: vec, permute
    1491: @*/
    1492: PetscErrorCode  VecPermute(Vec x, IS row, PetscBool inv)
    1493: {
    1494:   PetscScalar    *array, *newArray;
    1495:   const PetscInt *idx;
    1496:   PetscInt       i,rstart,rend;

    1500:   VecLocked(x,1);
    1501:
    1502:   VecGetOwnershipRange(x,&rstart,&rend);
    1503:   ISGetIndices(row, &idx);
    1504:   VecGetArray(x, &array);
    1505:   PetscMalloc1(x->map->n, &newArray);
    1506: #if defined(PETSC_USE_DEBUG)
    1507:   for (i = 0; i < x->map->n; i++) {
    1508:     if ((idx[i] < rstart) || (idx[i] >= rend)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT, "Permutation index %D is out of bounds: %D", i, idx[i]);
    1509:   }
    1510: #endif
    1511:   if (!inv) {
    1512:     for (i = 0; i < x->map->n; i++) newArray[i] = array[idx[i]-rstart];
    1513:   } else {
    1514:     for (i = 0; i < x->map->n; i++) newArray[idx[i]-rstart] = array[i];
    1515:   }
    1516:   VecRestoreArray(x, &array);
    1517:   ISRestoreIndices(row, &idx);
    1518:   VecReplaceArray(x, newArray);
    1519:   return(0);
    1520: }

    1522: /*@
    1523:    VecEqual - Compares two vectors. Returns true if the two vectors are either pointing to the same memory buffer,
    1524:    or if the two vectors have the same local and global layout as well as bitwise equality of all entries.
    1525:    Does NOT take round-off errors into account.

    1527:    Collective on Vec

    1529:    Input Parameters:
    1530: +  vec1 - the first vector
    1531: -  vec2 - the second vector

    1533:    Output Parameter:
    1534: .  flg - PETSC_TRUE if the vectors are equal; PETSC_FALSE otherwise.

    1536:    Level: intermediate

    1538:    Concepts: equal^two vectors
    1539:    Concepts: vector^equality

    1541: @*/
    1542: PetscErrorCode  VecEqual(Vec vec1,Vec vec2,PetscBool  *flg)
    1543: {
    1544:   const PetscScalar  *v1,*v2;
    1545:   PetscErrorCode     ierr;
    1546:   PetscInt           n1,n2,N1,N2;
    1547:   PetscBool          flg1;

    1553:   if (vec1 == vec2) *flg = PETSC_TRUE;
    1554:   else {
    1555:     VecGetSize(vec1,&N1);
    1556:     VecGetSize(vec2,&N2);
    1557:     if (N1 != N2) flg1 = PETSC_FALSE;
    1558:     else {
    1559:       VecGetLocalSize(vec1,&n1);
    1560:       VecGetLocalSize(vec2,&n2);
    1561:       if (n1 != n2) flg1 = PETSC_FALSE;
    1562:       else {
    1563:         VecGetArrayRead(vec1,&v1);
    1564:         VecGetArrayRead(vec2,&v2);
    1565:         PetscMemcmp(v1,v2,n1*sizeof(PetscScalar),&flg1);
    1566:         VecRestoreArrayRead(vec1,&v1);
    1567:         VecRestoreArrayRead(vec2,&v2);
    1568:       }
    1569:     }
    1570:     /* combine results from all processors */
    1571:     MPIU_Allreduce(&flg1,flg,1,MPIU_BOOL,MPI_MIN,PetscObjectComm((PetscObject)vec1));
    1572:   }
    1573:   return(0);
    1574: }

    1576: /*@
    1577:    VecUniqueEntries - Compute the number of unique entries, and those entries

    1579:    Collective on Vec

    1581:    Input Parameter:
    1582: .  vec - the vector

    1584:    Output Parameters:
    1585: +  n - The number of unique entries
    1586: -  e - The entries

    1588:    Level: intermediate

    1590: @*/
    1591: PetscErrorCode  VecUniqueEntries(Vec vec, PetscInt *n, PetscScalar **e)
    1592: {
    1593:   const PetscScalar *v;
    1594:   PetscScalar       *tmp, *vals;
    1595:   PetscMPIInt       *N, *displs, l;
    1596:   PetscInt          ng, m, i, j, p;
    1597:   PetscMPIInt       size;
    1598:   PetscErrorCode    ierr;

    1603:   MPI_Comm_size(PetscObjectComm((PetscObject) vec), &size);
    1604:   VecGetLocalSize(vec, &m);
    1605:   VecGetArrayRead(vec, &v);
    1606:   PetscMalloc2(m,&tmp,size,&N);
    1607:   for (i = 0, j = 0, l = 0; i < m; ++i) {
    1608:     /* Can speed this up with sorting */
    1609:     for (j = 0; j < l; ++j) {
    1610:       if (v[i] == tmp[j]) break;
    1611:     }
    1612:     if (j == l) {
    1613:       tmp[j] = v[i];
    1614:       ++l;
    1615:     }
    1616:   }
    1617:   VecRestoreArrayRead(vec, &v);
    1618:   /* Gather serial results */
    1619:   MPI_Allgather(&l, 1, MPI_INT, N, 1, MPI_INT, PetscObjectComm((PetscObject) vec));
    1620:   for (p = 0, ng = 0; p < size; ++p) {
    1621:     ng += N[p];
    1622:   }
    1623:   PetscMalloc2(ng,&vals,size+1,&displs);
    1624:   for (p = 1, displs[0] = 0; p <= size; ++p) {
    1625:     displs[p] = displs[p-1] + N[p-1];
    1626:   }
    1627:   MPI_Allgatherv(tmp, l, MPIU_SCALAR, vals, N, displs, MPIU_SCALAR, PetscObjectComm((PetscObject) vec));
    1628:   /* Find unique entries */
    1629: #ifdef PETSC_USE_COMPLEX
    1630:   SETERRQ(PetscObjectComm((PetscObject) vec), PETSC_ERR_SUP, "Does not work with complex numbers");
    1631: #else
    1632:   *n = displs[size];
    1633:   PetscSortRemoveDupsReal(n, (PetscReal *) vals);
    1634:   if (e) {
    1636:     PetscMalloc1(*n, e);
    1637:     for (i = 0; i < *n; ++i) {
    1638:       (*e)[i] = vals[i];
    1639:     }
    1640:   }
    1641:   PetscFree2(vals,displs);
    1642:   PetscFree2(tmp,N);
    1643:   return(0);
    1644: #endif
    1645: }