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

      2:  #include <petsc/private/dmdaimpl.h>

      4: static PetscErrorCode DMDAGetElements_1D(DM dm,PetscInt *nel,PetscInt *nen,const PetscInt *e[])
      5: {
      7:   DM_DA          *da = (DM_DA*)dm->data;
      8:   PetscInt       i,xs,xe,Xs,Xe;
      9:   PetscInt       cnt=0;

     12:   if (!da->e) {
     13:     PetscInt corners[2];

     15:     if (!da->s) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Cannot get elements for DMDA with zero stencil width");
     16:     DMDAGetCorners(dm,&xs,0,0,&xe,0,0);
     17:     DMDAGetGhostCorners(dm,&Xs,0,0,&Xe,0,0);
     18:     xe    += xs; Xe += Xs; if (xs != Xs) xs -= 1;
     19:     da->ne = 1*(xe - xs - 1);
     20:     PetscMalloc1(1 + 2*da->ne,&da->e);
     21:     for (i=xs; i<xe-1; i++) {
     22:       da->e[cnt++] = (i-Xs);
     23:       da->e[cnt++] = (i-Xs+1);
     24:     }
     25:     da->nen = 2;

     27:     corners[0] = (xs  -Xs);
     28:     corners[1] = (xe-1-Xs);
     29:     ISCreateGeneral(PETSC_COMM_SELF,2,corners,PETSC_COPY_VALUES,&da->ecorners);
     30:   }
     31:   *nel = da->ne;
     32:   *nen = da->nen;
     33:   *e   = da->e;
     34:   return(0);
     35: }

     37: static PetscErrorCode DMDAGetElements_2D(DM dm,PetscInt *nel,PetscInt *nen,const PetscInt *e[])
     38: {
     40:   DM_DA          *da = (DM_DA*)dm->data;
     41:   PetscInt       i,xs,xe,Xs,Xe;
     42:   PetscInt       j,ys,ye,Ys,Ye;
     43:   PetscInt       cnt=0, cell[4], ns=2;
     44:   PetscInt       c, split[] = {0,1,3,
     45:                                2,3,1};

     48:   if (!da->e) {
     49:     PetscInt corners[4],nn = 0;

     51:     if (!da->s) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Cannot get elements for DMDA with zero stencil width");

     53:     switch (da->elementtype) {
     54:     case DMDA_ELEMENT_Q1:
     55:       da->nen = 4;
     56:       break;
     57:     case DMDA_ELEMENT_P1:
     58:       da->nen = 3;
     59:       break;
     60:     default:
     61:       SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Unknown element type %d",da->elementtype);
     62:       break;
     63:     }
     64:     nn = da->nen;

     66:     if (da->elementtype == DMDA_ELEMENT_P1) {ns=2;}
     67:     if (da->elementtype == DMDA_ELEMENT_Q1) {ns=1;}
     68:     DMDAGetCorners(dm,&xs,&ys,0,&xe,&ye,0);
     69:     DMDAGetGhostCorners(dm,&Xs,&Ys,0,&Xe,&Ye,0);
     70:     xe    += xs; Xe += Xs; if (xs != Xs) xs -= 1;
     71:     ye    += ys; Ye += Ys; if (ys != Ys) ys -= 1;
     72:     da->ne = ns*(xe - xs - 1)*(ye - ys - 1);
     73:     PetscMalloc1(1 + nn*da->ne,&da->e);
     74:     for (j=ys; j<ye-1; j++) {
     75:       for (i=xs; i<xe-1; i++) {
     76:         cell[0] = (i-Xs  ) + (j-Ys  )*(Xe-Xs);
     77:         cell[1] = (i-Xs+1) + (j-Ys  )*(Xe-Xs);
     78:         cell[2] = (i-Xs+1) + (j-Ys+1)*(Xe-Xs);
     79:         cell[3] = (i-Xs  ) + (j-Ys+1)*(Xe-Xs);
     80:         if (da->elementtype == DMDA_ELEMENT_P1) {
     81:           for (c=0; c<ns*nn; c++) da->e[cnt++] = cell[split[c]];
     82:         }
     83:         if (da->elementtype == DMDA_ELEMENT_Q1) {
     84:           for (c=0; c<ns*nn; c++) da->e[cnt++] = cell[c];
     85:         }
     86:       }
     87:     }

     89:     corners[0] = (xs  -Xs) + (ys  -Ys)*(Xe-Xs);
     90:     corners[1] = (xe-1-Xs) + (ys  -Ys)*(Xe-Xs);
     91:     corners[2] = (xs  -Xs) + (ye-1-Ys)*(Xe-Xs);
     92:     corners[3] = (xe-1-Xs) + (ye-1-Ys)*(Xe-Xs);
     93:     ISCreateGeneral(PETSC_COMM_SELF,4,corners,PETSC_COPY_VALUES,&da->ecorners);
     94:   }
     95:   *nel = da->ne;
     96:   *nen = da->nen;
     97:   *e   = da->e;
     98:   return(0);
     99: }

    101: static PetscErrorCode DMDAGetElements_3D(DM dm,PetscInt *nel,PetscInt *nen,const PetscInt *e[])
    102: {
    104:   DM_DA          *da = (DM_DA*)dm->data;
    105:   PetscInt       i,xs,xe,Xs,Xe;
    106:   PetscInt       j,ys,ye,Ys,Ye;
    107:   PetscInt       k,zs,ze,Zs,Ze;
    108:   PetscInt       cnt=0, cell[8], ns=6;
    109:   PetscInt       c, split[] = {0,1,3,7,
    110:                                0,1,7,4,
    111:                                1,2,3,7,
    112:                                1,2,7,6,
    113:                                1,4,5,7,
    114:                                1,5,6,7};

    117:   if (!da->e) {
    118:     PetscInt corners[8],nn = 0;

    120:     if (!da->s) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Cannot get elements for DMDA with zero stencil width");

    122:     switch (da->elementtype) {
    123:     case DMDA_ELEMENT_Q1:
    124:       da->nen = 8;
    125:       break;
    126:     case DMDA_ELEMENT_P1:
    127:       da->nen = 4;
    128:       break;
    129:     default:
    130:       SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Unknown element type %d",da->elementtype);
    131:       break;
    132:     }
    133:     nn = da->nen;

    135:     if (da->elementtype == DMDA_ELEMENT_P1) {ns=6;}
    136:     if (da->elementtype == DMDA_ELEMENT_Q1) {ns=1;}
    137:     DMDAGetCorners(dm,&xs,&ys,&zs,&xe,&ye,&ze);
    138:     DMDAGetGhostCorners(dm,&Xs,&Ys,&Zs,&Xe,&Ye,&Ze);
    139:     xe    += xs; Xe += Xs; if (xs != Xs) xs -= 1;
    140:     ye    += ys; Ye += Ys; if (ys != Ys) ys -= 1;
    141:     ze    += zs; Ze += Zs; if (zs != Zs) zs -= 1;
    142:     da->ne = ns*(xe - xs - 1)*(ye - ys - 1)*(ze - zs - 1);
    143:     PetscMalloc1(1 + nn*da->ne,&da->e);
    144:     for (k=zs; k<ze-1; k++) {
    145:       for (j=ys; j<ye-1; j++) {
    146:         for (i=xs; i<xe-1; i++) {
    147:           cell[0] = (i-Xs  ) + (j-Ys  )*(Xe-Xs) + (k-Zs  )*(Xe-Xs)*(Ye-Ys);
    148:           cell[1] = (i-Xs+1) + (j-Ys  )*(Xe-Xs) + (k-Zs  )*(Xe-Xs)*(Ye-Ys);
    149:           cell[2] = (i-Xs+1) + (j-Ys+1)*(Xe-Xs) + (k-Zs  )*(Xe-Xs)*(Ye-Ys);
    150:           cell[3] = (i-Xs  ) + (j-Ys+1)*(Xe-Xs) + (k-Zs  )*(Xe-Xs)*(Ye-Ys);
    151:           cell[4] = (i-Xs  ) + (j-Ys  )*(Xe-Xs) + (k-Zs+1)*(Xe-Xs)*(Ye-Ys);
    152:           cell[5] = (i-Xs+1) + (j-Ys  )*(Xe-Xs) + (k-Zs+1)*(Xe-Xs)*(Ye-Ys);
    153:           cell[6] = (i-Xs+1) + (j-Ys+1)*(Xe-Xs) + (k-Zs+1)*(Xe-Xs)*(Ye-Ys);
    154:           cell[7] = (i-Xs  ) + (j-Ys+1)*(Xe-Xs) + (k-Zs+1)*(Xe-Xs)*(Ye-Ys);
    155:           if (da->elementtype == DMDA_ELEMENT_P1) {
    156:             for (c=0; c<ns*nn; c++) da->e[cnt++] = cell[split[c]];
    157:           }
    158:           if (da->elementtype == DMDA_ELEMENT_Q1) {
    159:             for (c=0; c<ns*nn; c++) da->e[cnt++] = cell[c];
    160:           }
    161:         }
    162:       }
    163:     }

    165:     corners[0] = (xs  -Xs) + (ys  -Ys)*(Xe-Xs) + (zs-Zs  )*(Xe-Xs)*(Ye-Ys);
    166:     corners[1] = (xe-1-Xs) + (ys  -Ys)*(Xe-Xs) + (zs-Zs  )*(Xe-Xs)*(Ye-Ys);
    167:     corners[2] = (xs  -Xs) + (ye-1-Ys)*(Xe-Xs) + (zs-Zs  )*(Xe-Xs)*(Ye-Ys);
    168:     corners[3] = (xe-1-Xs) + (ye-1-Ys)*(Xe-Xs) + (zs-Zs  )*(Xe-Xs)*(Ye-Ys);
    169:     corners[4] = (xs  -Xs) + (ys  -Ys)*(Xe-Xs) + (ze-1-Zs)*(Xe-Xs)*(Ye-Ys);
    170:     corners[5] = (xe-1-Xs) + (ys  -Ys)*(Xe-Xs) + (ze-1-Zs)*(Xe-Xs)*(Ye-Ys);
    171:     corners[6] = (xs  -Xs) + (ye-1-Ys)*(Xe-Xs) + (ze-1-Zs)*(Xe-Xs)*(Ye-Ys);
    172:     corners[7] = (xe-1-Xs) + (ye-1-Ys)*(Xe-Xs) + (ze-1-Zs)*(Xe-Xs)*(Ye-Ys);
    173:     ISCreateGeneral(PETSC_COMM_SELF,8,corners,PETSC_COPY_VALUES,&da->ecorners);
    174:   }
    175:   *nel = da->ne;
    176:   *nen = da->nen;
    177:   *e   = da->e;
    178:   return(0);
    179: }

    181: /*@
    182:    DMDAGetElementsCorners - Returns the global (x,y,z) indices of the lower left
    183:    corner of the non-overlapping decomposition identified by DMDAGetElements()

    185:     Not Collective

    187:    Input Parameter:
    188: .     da - the DM object

    190:    Output Parameters:
    191: +     gx - the x index
    192: .     gy - the y index
    193: -     gz - the z index

    195:    Level: intermediate

    197:    Notes:

    199: .seealso: DMDAElementType, DMDASetElementType(), DMDAGetElements()
    200: @*/
    201: PetscErrorCode  DMDAGetElementsCorners(DM da, PetscInt *gx, PetscInt *gy, PetscInt *gz)
    202: {
    203:   PetscInt       xs,Xs;
    204:   PetscInt       ys,Ys;
    205:   PetscInt       zs,Zs;
    206:   PetscBool      isda;

    214:   PetscObjectTypeCompare((PetscObject)da,DMDA,&isda);
    215:   if (!isda) SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_USER,"Not for DM type %s",((PetscObject)da)->type_name);
    216:   DMDAGetCorners(da,&xs,&ys,&zs,NULL,NULL,NULL);
    217:   DMDAGetGhostCorners(da,&Xs,&Ys,&Zs,NULL,NULL,NULL);
    218:   if (xs != Xs) xs -= 1;
    219:   if (ys != Ys) ys -= 1;
    220:   if (zs != Zs) zs -= 1;
    221:   if (gx) *gx  = xs;
    222:   if (gy) *gy  = ys;
    223:   if (gz) *gz  = zs;
    224:   return(0);
    225: }

    227: /*@
    228:       DMDAGetElementsSizes - Gets the local number of elements per direction for the non-overlapping decomposition identified by DMDAGetElements()

    230:     Not Collective

    232:    Input Parameter:
    233: .     da - the DM object

    235:    Output Parameters:
    236: +     mx - number of local elements in x-direction
    237: .     my - number of local elements in y-direction
    238: -     mz - number of local elements in z-direction

    240:    Level: intermediate

    242:    Notes:
    243:     It returns the same number of elements, irrespective of the DMDAElementType

    245: .seealso: DMDAElementType, DMDASetElementType(), DMDAGetElements
    246: @*/
    247: PetscErrorCode  DMDAGetElementsSizes(DM da, PetscInt *mx, PetscInt *my, PetscInt *mz)
    248: {
    249:   PetscInt       xs,xe,Xs;
    250:   PetscInt       ys,ye,Ys;
    251:   PetscInt       zs,ze,Zs;
    252:   PetscInt       dim;
    253:   PetscBool      isda;

    261:   PetscObjectTypeCompare((PetscObject)da,DMDA,&isda);
    262:   if (!isda) SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_USER,"Not for DM type %s",((PetscObject)da)->type_name);
    263:   DMDAGetCorners(da,&xs,&ys,&zs,&xe,&ye,&ze);
    264:   DMDAGetGhostCorners(da,&Xs,&Ys,&Zs,NULL,NULL,NULL);
    265:   xe  += xs; if (xs != Xs) xs -= 1;
    266:   ye  += ys; if (ys != Ys) ys -= 1;
    267:   ze  += zs; if (zs != Zs) zs -= 1;
    268:   if (mx) *mx  = 0;
    269:   if (my) *my  = 0;
    270:   if (mz) *mz  = 0;
    271:   DMGetDimension(da,&dim);
    272:   switch (dim) {
    273:   case 3:
    274:     if (mz) *mz = ze - zs - 1;
    275:   case 2:
    276:     if (my) *my = ye - ys - 1;
    277:   case 1:
    278:     if (mx) *mx = xe - xs - 1;
    279:     break;
    280:   }
    281:   return(0);
    282: }

    284: /*@
    285:       DMDASetElementType - Sets the element type to be returned by DMDAGetElements()

    287:     Not Collective

    289:    Input Parameter:
    290: .     da - the DMDA object

    292:    Output Parameters:
    293: .     etype - the element type, currently either DMDA_ELEMENT_P1 or DMDA_ELEMENT_Q1

    295:    Level: intermediate

    297: .seealso: DMDAElementType, DMDAGetElementType(), DMDAGetElements(), DMDARestoreElements()
    298: @*/
    299: PetscErrorCode  DMDASetElementType(DM da, DMDAElementType etype)
    300: {
    301:   DM_DA          *dd = (DM_DA*)da->data;
    303:   PetscBool      isda;

    308:   PetscObjectTypeCompare((PetscObject)da,DMDA,&isda);
    309:   if (!isda) return(0);
    310:   if (dd->elementtype != etype) {
    311:     PetscFree(dd->e);
    312:     ISDestroy(&dd->ecorners);

    314:     dd->elementtype = etype;
    315:     dd->ne          = 0;
    316:     dd->nen         = 0;
    317:     dd->e           = NULL;
    318:   }
    319:   return(0);
    320: }

    322: /*@
    323:       DMDAGetElementType - Gets the element type to be returned by DMDAGetElements()

    325:     Not Collective

    327:    Input Parameter:
    328: .     da - the DMDA object

    330:    Output Parameters:
    331: .     etype - the element type, currently either DMDA_ELEMENT_P1 or DMDA_ELEMENT_Q1

    333:    Level: intermediate

    335: .seealso: DMDAElementType, DMDASetElementType(), DMDAGetElements(), DMDARestoreElements()
    336: @*/
    337: PetscErrorCode  DMDAGetElementType(DM da, DMDAElementType *etype)
    338: {
    339:   DM_DA          *dd = (DM_DA*)da->data;
    341:   PetscBool      isda;

    346:   PetscObjectTypeCompare((PetscObject)da,DMDA,&isda);
    347:   if (!isda) SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_USER,"Not for DM type %s",((PetscObject)da)->type_name);
    348:   *etype = dd->elementtype;
    349:   return(0);
    350: }

    352: /*@C
    353:       DMDAGetElements - Gets an array containing the indices (in local coordinates)
    354:                  of all the local elements

    356:     Not Collective

    358:    Input Parameter:
    359: .     dm - the DM object

    361:    Output Parameters:
    362: +     nel - number of local elements
    363: .     nen - number of element nodes
    364: -     e - the local indices of the elements' vertices

    366:    Level: intermediate

    368:    Notes:
    369:      Call DMDARestoreElements() once you have finished accessing the elements.

    371:      Each process uniquely owns a subset of the elements. That is no element is owned by two or more processes.

    373:      If on each process you integrate over its owned elements and use ADD_VALUES in Vec/MatSetValuesLocal() then you'll obtain the correct result.

    375:      Not supported in Fortran

    377: .seealso: DMDAElementType, DMDASetElementType(), VecSetValuesLocal(), MatSetValuesLocal(), DMGlobalToLocalBegin(), DMLocalToGlobalBegin()
    378: @*/
    379: PetscErrorCode  DMDAGetElements(DM dm,PetscInt *nel,PetscInt *nen,const PetscInt *e[])
    380: {
    381:   PetscInt       dim;
    383:   DM_DA          *dd = (DM_DA*)dm->data;
    384:   PetscBool      isda;

    391:   PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda);
    392:   if (!isda) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for DM type %s",((PetscObject)dm)->type_name);
    393:   if (dd->stencil_type == DMDA_STENCIL_STAR) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DMDAGetElements() requires you use a stencil type of DMDA_STENCIL_BOX");
    394:   DMGetDimension(dm, &dim);
    395:   if (dd->e) {
    396:     *nel = dd->ne;
    397:     *nen = dd->nen;
    398:     *e   = dd->e;
    399:     return(0);
    400:   }
    401:   if (dim==-1) {
    402:     *nel = 0; *nen = 0; *e = NULL;
    403:   } else if (dim==1) {
    404:     DMDAGetElements_1D(dm,nel,nen,e);
    405:   } else if (dim==2) {
    406:     DMDAGetElements_2D(dm,nel,nen,e);
    407:   } else if (dim==3) {
    408:     DMDAGetElements_3D(dm,nel,nen,e);
    409:   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT,"DMDA dimension not 1, 2, or 3, it is %D\n",dim);
    410:   return(0);
    411: }

    413: /*@
    414:       DMDAGetSubdomainCornersIS - Gets an index set containing the corner indices (in local coordinates)
    415:                                  of the non-overlapping decomposition identified by DMDAGetElements

    417:     Not Collective

    419:    Input Parameter:
    420: .     dm - the DM object

    422:    Output Parameters:
    423: .     is - the index set

    425:    Level: intermediate

    427:    Notes:
    428:     Call DMDARestoreSubdomainCornersIS() once you have finished accessing the index set.

    430: .seealso: DMDAElementType, DMDASetElementType(), DMDAGetElements(), DMDARestoreElementsCornersIS()
    431: @*/
    432: PetscErrorCode  DMDAGetSubdomainCornersIS(DM dm,IS *is)
    433: {
    435:   DM_DA          *dd = (DM_DA*)dm->data;
    436:   PetscBool      isda;

    441:   PetscObjectTypeCompare((PetscObject)dm,DMDA,&isda);
    442:   if (!isda) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Not for DM type %s",((PetscObject)dm)->type_name);
    443:   if (dd->stencil_type == DMDA_STENCIL_STAR) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"DMDAGetElement() requires you use a stencil type of DMDA_STENCIL_BOX");
    444:   if (!dd->ecorners) { /* compute elements if not yet done */
    445:     const PetscInt *e;
    446:     PetscInt       nel,nen;

    448:     DMDAGetElements(dm,&nel,&nen,&e);
    449:     DMDARestoreElements(dm,&nel,&nen,&e);
    450:   }
    451:   *is = dd->ecorners;
    452:   return(0);
    453: }

    455: /*@C
    456:       DMDARestoreElements - Restores the array obtained with DMDAGetElements()

    458:     Not Collective

    460:    Input Parameter:
    461: +     dm - the DM object
    462: .     nel - number of local elements
    463: .     nen - number of element nodes
    464: -     e - the local indices of the elements' vertices

    466:    Level: intermediate

    468:    Note: You should not access these values after you have called this routine.

    470:          This restore signals the DMDA object that you no longer need access to the array information.

    472:          Not supported in Fortran

    474: .seealso: DMDAElementType, DMDASetElementType(), DMDAGetElements()
    475: @*/
    476: PetscErrorCode  DMDARestoreElements(DM dm,PetscInt *nel,PetscInt *nen,const PetscInt *e[])
    477: {
    483:   *nel = 0;
    484:   *nen = -1;
    485:   *e = NULL;
    486:   return(0);
    487: }

    489: /*@
    490:       DMDARestoreSubdomainCornersIS - Restores the IS obtained with DMDAGetSubdomainCornersIS()

    492:     Not Collective

    494:    Input Parameter:
    495: +     dm - the DM object
    496: -     is - the index set

    498:    Level: intermediate

    500:    Note:

    502: .seealso: DMDAElementType, DMDASetElementType(), DMDAGetSubdomainCornersIS()
    503: @*/
    504: PetscErrorCode  DMDARestoreSubdomainCornersIS(DM dm,IS *is)
    505: {
    509:   *is = NULL;
    510:   return(0);
    511: }