Actual source code: dacorn.c

      1: #define PETSCDM_DLL

      3: /*
      4:   Code for manipulating distributed regular arrays in parallel.
      5: */

     7:  #include src/dm/da/daimpl.h

     11: /*@
     12:    DASetCoordinates - Sets into the DA a vector that indicates the
     13:       coordinates of the local nodes (NOT including ghost nodes).

     15:    Not Collective

     17:    Input Parameter:
     18: +  da - the distributed array
     19: -  c - coordinate vector

     21:    Note:
     22:     The coordinates should NOT include those for all ghost points

     24:      Does NOT increase the reference count of this vector, so caller should NOT
     25:   destroy the vector.

     27:   Level: intermediate

     29: .keywords: distributed array, get, corners, nodes, local indices, coordinates

     31: .seealso: DAGetGhostCorners(), DAGetCoordinates(), DASetUniformCoordinates(). DAGetGhostCoordinates(), DAGetCoordinateDA()
     32: @*/
     33: PetscErrorCode PETSCDM_DLLEXPORT DASetCoordinates(DA da,Vec c)
     34: {

     40:   da->coordinates = c;
     41:   VecSetBlockSize(c,da->dim);
     42:   return(0);
     43: }

     47: /*@
     48:    DAGetCoordinates - Gets the node coordinates associated with a DA.

     50:    Not Collective

     52:    Input Parameter:
     53: .  da - the distributed array

     55:    Output Parameter:
     56: .  c - coordinate vector

     58:    Note:
     59:     Each process has only the coordinates for its local nodes (does NOT have the
     60:   coordinates for the ghost nodes).

     62:     For two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
     63:     and (x_0,y_0,z_0,x_1,y_1,z_1...)

     65:     You should not destroy or keep around this vector after the DA is destroyed.

     67:   Level: intermediate

     69: .keywords: distributed array, get, corners, nodes, local indices, coordinates

     71: .seealso: DAGetGhostCorners(), DASetCoordinates(), DASetUniformCoordinates(), DAGetCoordinates(), DAGetCoordinateDA()
     72: @*/
     73: PetscErrorCode PETSCDM_DLLEXPORT DAGetCoordinates(DA da,Vec *c)
     74: {
     76:
     79:   *c = da->coordinates;
     80:   return(0);
     81: }

     85: /*@
     86:    DAGetCoordinateDA - Gets the DA that scatters between global and local DA coordinates

     88:    Collective on DA

     90:    Input Parameter:
     91: .  da - the distributed array

     93:    Output Parameter:
     94: .  dac - coordinate DA

     96:    Note: You should not destroy or keep around this vector after the DA is destroyed.

     98:   Level: intermediate

    100: .keywords: distributed array, get, corners, nodes, local indices, coordinates

    102: .seealso: DAGetGhostCorners(), DASetCoordinates(), DASetUniformCoordinates(), DAGetCoordinates(), DAGetGhostedCoordinates()
    103: @*/
    104: PetscErrorCode PETSCDM_DLLEXPORT DAGetCoordinateDA(DA da,DA *cda)
    105: {
    106:   DAStencilType  st;
    108:   PetscMPIInt    size;

    111:   if (da->da_coordinates) {
    112:     *cda = da->da_coordinates;
    113:     return(0);
    114:   }
    115:   MPI_Comm_size(da->comm,&size);
    116:   if (da->dim == 1) {
    117:     if (da->w == 1) {
    118:       da->da_coordinates = da;
    119:     } else {
    120:       PetscInt            s,m,*lc,l;
    121:       DAPeriodicType pt;
    122:       DAGetInfo(da,0,&m,0,0,0,0,0,0,&s,&pt,0);
    123:       DAGetCorners(da,0,0,0,&l,0,0);
    124:       PetscMalloc(size*sizeof(PetscInt),&lc);
    125:       MPI_Allgather(&l,1,MPIU_INT,lc,1,MPIU_INT,da->comm);
    126:       DACreate1d(da->comm,pt,m,1,s,lc,&da->da_coordinates);
    127:       PetscFree(lc);
    128:     }
    129:   } else if (da->dim == 2) {
    130:     DAGetInfo(da,0,0,0,0,0,0,0,0,0,0,&st);
    131:     if (da->w == 2 && st == DA_STENCIL_BOX) {
    132:       da->da_coordinates = da;
    133:     } else {
    134:       PetscInt            i,s,m,*lc,*ld,l,k,n,M,N;
    135:       DAPeriodicType pt;
    136:       DAGetInfo(da,0,&m,&n,0,&M,&N,0,0,&s,&pt,0);
    137:       DAGetCorners(da,0,0,0,&l,&k,0);
    138:       PetscMalloc(size*sizeof(PetscInt),&lc);
    139:       PetscMalloc(size*sizeof(PetscInt),&ld);
    140:       /* only first M values in lc matter */
    141:       MPI_Allgather(&l,1,MPIU_INT,lc,1,MPIU_INT,da->comm);
    142:       /* every Mth value in ld matters */
    143:       MPI_Allgather(&k,1,MPIU_INT,ld,1,MPIU_INT,da->comm);
    144:       for ( i=0; i<N; i++) {
    145:         ld[i] = ld[M*i];
    146:       }
    147:       DACreate2d(da->comm,pt,DA_STENCIL_BOX,m,n,M,N,2,s,lc,ld,&da->da_coordinates);
    148:       PetscFree(lc);
    149:       PetscFree(ld);
    150:     }
    151:   } else if (da->dim == 3) {
    152:     DAGetInfo(da,0,0,0,0,0,0,0,0,0,0,&st);
    153:     if (da->w == 3 && st == DA_STENCIL_BOX) {
    154:       da->da_coordinates = da;
    155:     } else {
    156:       PetscInt            i,s,m,*lc,*ld,*le,l,k,q,n,M,N,P,p;
    157:       DAPeriodicType pt;
    158:       DAGetInfo(da,0,&m,&n,&p,&M,&N,&P,0,&s,&pt,0);
    159:       DAGetCorners(da,0,0,0,&l,&k,&q);
    160:       PetscMalloc(size*sizeof(PetscInt),&lc);
    161:       PetscMalloc(size*sizeof(PetscInt),&ld);
    162:       PetscMalloc(size*sizeof(PetscInt),&le);
    163:       /* only first M values in lc matter */
    164:       MPI_Allgather(&l,1,MPIU_INT,lc,1,MPIU_INT,da->comm);
    165:       /* every Mth value in ld matters */
    166:       MPI_Allgather(&k,1,MPIU_INT,ld,1,MPIU_INT,da->comm);
    167:       for ( i=0; i<N; i++) {
    168:         ld[i] = ld[M*i];
    169:       }
    170:       MPI_Allgather(&q,1,MPIU_INT,le,1,MPIU_INT,da->comm);
    171:       for ( i=0; i<P; i++) {
    172:         le[i] = le[M*N*i];
    173:       }
    174:       DACreate3d(da->comm,pt,DA_STENCIL_BOX,m,n,p,M,N,P,3,s,lc,ld,le,&da->da_coordinates);
    175:       PetscFree(lc);
    176:       PetscFree(ld);
    177:       PetscFree(le);
    178:     }
    179:   }
    180:   *cda = da->da_coordinates;
    181:   return(0);
    182: }

    187: /*@
    188:    DAGetGhostedCoordinates - Gets the node coordinates associated with a DA.

    190:    Collective on DA the first time it is called

    192:    Input Parameter:
    193: .  da - the distributed array

    195:    Output Parameter:
    196: .  c - coordinate vector

    198:    Note:
    199:     Each process has only the coordinates for its local AND ghost nodes

    201:     For two and three dimensions coordinates are interlaced (x_0,y_0,x_1,y_1,...)
    202:     and (x_0,y_0,z_0,x_1,y_1,z_1...)

    204:     You should not destroy or keep around this vector after the DA is destroyed.

    206:   Level: intermediate

    208: .keywords: distributed array, get, corners, nodes, local indices, coordinates

    210: .seealso: DAGetGhostCorners(), DASetCoordinates(), DASetUniformCoordinates(), DAGetCoordinates(), DAGetCoordinateDA()
    211: @*/
    212: PetscErrorCode PETSCDM_DLLEXPORT DAGetGhostedCoordinates(DA da,Vec *c)
    213: {
    215:
    218:   if (!da->coordinates) SETERRQ(PETSC_ERR_ORDER,"You must call DASetCoordinates() before this call");
    219:   if (!da->ghosted_coordinates) {
    220:     DA  dac;
    222:     DAGetCoordinateDA(da,&dac);
    223:     DACreateLocalVector(dac,&da->ghosted_coordinates);
    224:     if (dac == da) {PetscObjectDereference((PetscObject)dac);}
    225:     DAGlobalToLocalBegin(dac,da->coordinates,INSERT_VALUES,da->ghosted_coordinates);
    226:     DAGlobalToLocalEnd(dac,da->coordinates,INSERT_VALUES,da->ghosted_coordinates);
    227:   }
    228:   *c = da->ghosted_coordinates;
    229:   return(0);
    230: }

    234: /*@C
    235:    DASetFieldName - Sets the names of individual field components in multicomponent
    236:    vectors associated with a DA.

    238:    Not Collective

    240:    Input Parameters:
    241: +  da - the distributed array
    242: .  nf - field number for the DA (0, 1, ... dof-1), where dof indicates the
    243:         number of degrees of freedom per node within the DA
    244: -  names - the name of the field (component)

    246:   Level: intermediate

    248: .keywords: distributed array, get, component name

    250: .seealso: DAGetFieldName()
    251: @*/
    252: PetscErrorCode PETSCDM_DLLEXPORT DASetFieldName(DA da,PetscInt nf,const char name[])
    253: {

    257:
    259:   if (nf < 0 || nf >= da->w) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Invalid field number: %D",nf);
    260:   if (da->fieldname[nf]) {PetscFree(da->fieldname[nf]);}
    261:
    262:   PetscStrallocpy(name,&da->fieldname[nf]);
    263:   return(0);
    264: }

    268: /*@C
    269:    DAGetFieldName - Gets the names of individual field components in multicomponent
    270:    vectors associated with a DA.

    272:    Not Collective

    274:    Input Parameter:
    275: +  da - the distributed array
    276: -  nf - field number for the DA (0, 1, ... dof-1), where dof indicates the
    277:         number of degrees of freedom per node within the DA

    279:    Output Parameter:
    280: .  names - the name of the field (component)

    282:   Level: intermediate

    284: .keywords: distributed array, get, component name

    286: .seealso: DASetFieldName()
    287: @*/
    288: PetscErrorCode PETSCDM_DLLEXPORT DAGetFieldName(DA da,PetscInt nf,char **name)
    289: {
    291:
    294:   if (nf < 0 || nf >= da->w) SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Invalid field number: %D",nf);
    295:   *name = da->fieldname[nf];
    296:   return(0);
    297: }

    301: /*@
    302:    DAGetCorners - Returns the global (x,y,z) indices of the lower left
    303:    corner of the local region, excluding ghost points.

    305:    Not Collective

    307:    Input Parameter:
    308: .  da - the distributed array

    310:    Output Parameters:
    311: +  x,y,z - the corner indices (where y and z are optional; these are used
    312:            for 2D and 3D problems)
    313: -  m,n,p - widths in the corresponding directions (where n and p are optional;
    314:            these are used for 2D and 3D problems)

    316:    Note:
    317:    The corner information is independent of the number of degrees of
    318:    freedom per node set with the DACreateXX() routine. Thus the x, y, z, and
    319:    m, n, p can be thought of as coordinates on a logical grid, where each
    320:    grid point has (potentially) several degrees of freedom.
    321:    Any of y, z, n, and p can be passed in as PETSC_NULL if not needed.

    323:   Level: beginner

    325: .keywords: distributed array, get, corners, nodes, local indices

    327: .seealso: DAGetGhostCorners()
    328: @*/
    329: PetscErrorCode PETSCDM_DLLEXPORT DAGetCorners(DA da,PetscInt *x,PetscInt *y,PetscInt *z,PetscInt *m,PetscInt *n,PetscInt *p)
    330: {
    331:   PetscInt w;

    335:   /* since the xs, xe ... have all been multiplied by the number of degrees
    336:      of freedom per cell, w = da->w, we divide that out before returning.*/
    337:   w = da->w;
    338:   if (x) *x = da->xs/w; if(m) *m = (da->xe - da->xs)/w;
    339:   /* the y and z have NOT been multiplied by w */
    340:   if (y) *y = da->ys;   if (n) *n = (da->ye - da->ys);
    341:   if (z) *z = da->zs;   if (p) *p = (da->ze - da->zs);
    342:   return(0);
    343: }