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

      1:  #include <petsc/private/dmimpl.h>
      2:  #include <petscds.h>

      4: PetscErrorCode DMCreateGlobalVector_Section_Private(DM dm,Vec *vec)
      5: {
      6:   PetscSection   gSection;
      7:   PetscInt       localSize, bs, blockSize = -1, pStart, pEnd, p;
      9:   PetscInt       in[2],out[2];

     12:   DMGetGlobalSection(dm, &gSection);
     13:   PetscSectionGetChart(gSection, &pStart, &pEnd);
     14:   for (p = pStart; p < pEnd; ++p) {
     15:     PetscInt dof, cdof;

     17:     PetscSectionGetDof(gSection, p, &dof);
     18:     PetscSectionGetConstraintDof(gSection, p, &cdof);

     20:     if (dof > 0) {
     21:       if (blockSize < 0 && dof-cdof > 0) {
     22:         /* set blockSize */
     23:         blockSize = dof-cdof;
     24:       } else if (dof-cdof != blockSize) {
     25:         /* non-identical blockSize, set it as 1 */
     26:         blockSize = 1;
     27:         break;
     28:       }
     29:     }
     30:   }

     32:   in[0] = blockSize < 0 ? PETSC_MIN_INT : -blockSize;
     33:   in[1] = blockSize;
     34:   MPIU_Allreduce(in,out,2,MPIU_INT,MPI_MAX,PetscObjectComm((PetscObject)dm));
     35:   /* -out[0] = min(blockSize), out[1] = max(blockSize) */
     36:   if (-out[0] == out[1]) {
     37:     bs = out[1];
     38:   } else bs = 1;

     40:   if (bs < 0) { /* Everyone was empty */
     41:     blockSize = 1;
     42:     bs        = 1;
     43:   }

     45:   PetscSectionGetConstrainedStorageSize(gSection, &localSize);
     46:   if (localSize%blockSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mismatch between blocksize %d and local storage size %d", blockSize, localSize);
     47:   VecCreate(PetscObjectComm((PetscObject)dm), vec);
     48:   VecSetSizes(*vec, localSize, PETSC_DETERMINE);
     49:   VecSetBlockSize(*vec, bs);
     50:   VecSetType(*vec,dm->vectype);
     51:   VecSetDM(*vec, dm);
     52:   /* VecSetLocalToGlobalMapping(*vec, dm->ltogmap); */
     53:   return(0);
     54: }

     56: PetscErrorCode DMCreateLocalVector_Section_Private(DM dm,Vec *vec)
     57: {
     58:   PetscSection   section;
     59:   PetscInt       localSize, blockSize = -1, pStart, pEnd, p;

     63:   DMGetSection(dm, &section);
     64:   PetscSectionGetChart(section, &pStart, &pEnd);
     65:   for (p = pStart; p < pEnd; ++p) {
     66:     PetscInt dof;

     68:     PetscSectionGetDof(section, p, &dof);
     69:     if ((blockSize < 0) && (dof > 0)) blockSize = dof;
     70:     if ((dof > 0) && (dof != blockSize)) {
     71:       blockSize = 1;
     72:       break;
     73:     }
     74:   }
     75:   PetscSectionGetStorageSize(section, &localSize);
     76:   VecCreate(PETSC_COMM_SELF, vec);
     77:   VecSetSizes(*vec, localSize, localSize);
     78:   VecSetBlockSize(*vec, blockSize);
     79:   VecSetType(*vec,dm->vectype);
     80:   VecSetDM(*vec, dm);
     81:   return(0);
     82: }

     84: /* This assumes that the DM has been cloned prior to the call */
     85: PetscErrorCode DMCreateSubDM_Section_Private(DM dm, PetscInt numFields, const PetscInt fields[], IS *is, DM *subdm)
     86: {
     87:   PetscSection   section, sectionGlobal;
     88:   PetscInt      *subIndices;
     89:   PetscInt       subSize = 0, subOff = 0, nF, f, pStart, pEnd, p;

     93:   if (!numFields) return(0);
     94:   DMGetSection(dm, &section);
     95:   DMGetGlobalSection(dm, &sectionGlobal);
     96:   if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting fields");
     97:   if (!sectionGlobal) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Must set default global section for DM before splitting fields");
     98:   PetscSectionGetNumFields(section, &nF);
     99:   if (numFields > nF) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Number of requested fields %d greater than number of DM fields %d", numFields, nF);
    100:   if (is) {
    101:     PetscInt bs = -1, bsLocal[2], bsMinMax[2];
    102:     PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);
    103:     for (p = pStart; p < pEnd; ++p) {
    104:       PetscInt gdof, pSubSize  = 0;

    106:       PetscSectionGetDof(sectionGlobal, p, &gdof);
    107:       if (gdof > 0) {
    108:         for (f = 0; f < numFields; ++f) {
    109:           PetscInt fdof, fcdof;

    111:           PetscSectionGetFieldDof(section, p, fields[f], &fdof);
    112:           PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);
    113:           pSubSize += fdof-fcdof;
    114:         }
    115:         subSize += pSubSize;
    116:         if (pSubSize) {
    117:           if (bs < 0) {
    118:             bs = pSubSize;
    119:           } else if (bs != pSubSize) {
    120:             /* Layout does not admit a pointwise block size */
    121:             bs = 1;
    122:           }
    123:         }
    124:       }
    125:     }
    126:     /* Must have same blocksize on all procs (some might have no points) */
    127:     bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
    128:     PetscGlobalMinMaxInt(PetscObjectComm((PetscObject) dm), bsLocal, bsMinMax);
    129:     if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
    130:     else                            {bs = bsMinMax[0];}
    131:     PetscMalloc1(subSize, &subIndices);
    132:     for (p = pStart; p < pEnd; ++p) {
    133:       PetscInt gdof, goff;

    135:       PetscSectionGetDof(sectionGlobal, p, &gdof);
    136:       if (gdof > 0) {
    137:         PetscSectionGetOffset(sectionGlobal, p, &goff);
    138:         for (f = 0; f < numFields; ++f) {
    139:           PetscInt fdof, fcdof, fc, f2, poff = 0;

    141:           /* Can get rid of this loop by storing field information in the global section */
    142:           for (f2 = 0; f2 < fields[f]; ++f2) {
    143:             PetscSectionGetFieldDof(section, p, f2, &fdof);
    144:             PetscSectionGetFieldConstraintDof(section, p, f2, &fcdof);
    145:             poff += fdof-fcdof;
    146:           }
    147:           PetscSectionGetFieldDof(section, p, fields[f], &fdof);
    148:           PetscSectionGetFieldConstraintDof(section, p, fields[f], &fcdof);
    149:           for (fc = 0; fc < fdof-fcdof; ++fc, ++subOff) {
    150:             subIndices[subOff] = goff+poff+fc;
    151:           }
    152:         }
    153:       }
    154:     }
    155:     ISCreateGeneral(PetscObjectComm((PetscObject)dm), subSize, subIndices, PETSC_OWN_POINTER, is);
    156:     if (bs > 1) {
    157:       /* We need to check that the block size does not come from non-contiguous fields */
    158:       PetscInt i, j, set = 1;
    159:       for (i = 0; i < subSize; i += bs) {
    160:         for (j = 0; j < bs; ++j) {
    161:           if (subIndices[i+j] != subIndices[i]+j) {set = 0; break;}
    162:         }
    163:       }
    164:       if (set) {ISSetBlockSize(*is, bs);}
    165:     }
    166:   }
    167:   if (subdm) {
    168:     PetscSection subsection;
    169:     PetscBool    haveNull = PETSC_FALSE;
    170:     PetscInt     f, nf = 0;

    172:     PetscSectionCreateSubsection(section, numFields, fields, &subsection);
    173:     DMSetSection(*subdm, subsection);
    174:     PetscSectionDestroy(&subsection);
    175:     for (f = 0; f < numFields; ++f) {
    176:       (*subdm)->nullspaceConstructors[f] = dm->nullspaceConstructors[fields[f]];
    177:       if ((*subdm)->nullspaceConstructors[f]) {
    178:         haveNull = PETSC_TRUE;
    179:         nf       = f;
    180:       }
    181:     }
    182:     if (haveNull && is) {
    183:       MatNullSpace nullSpace;

    185:       (*(*subdm)->nullspaceConstructors[nf])(*subdm, nf, &nullSpace);
    186:       PetscObjectCompose((PetscObject) *is, "nullspace", (PetscObject) nullSpace);
    187:       MatNullSpaceDestroy(&nullSpace);
    188:     }
    189:     if (dm->prob) {
    190:       PetscInt Nf;

    192:       PetscDSGetNumFields(dm->prob, &Nf);
    193:       if (nF != Nf) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "The number of DM fields %d does not match the number of Section fields %d", Nf, nF);
    194:       DMSetNumFields(*subdm, numFields);
    195:       for (f = 0; f < numFields; ++f) {
    196:         PetscObject disc;

    198:         DMGetField(dm, fields[f], &disc);
    199:         DMSetField(*subdm, f, disc);
    200:       }
    201:       if (numFields == 1 && is) {
    202:         PetscObject disc, space, pmat;

    204:         DMGetField(*subdm, 0, &disc);
    205:         PetscObjectQuery(disc, "nullspace", &space);
    206:         if (space) {PetscObjectCompose((PetscObject) *is, "nullspace", space);}
    207:         PetscObjectQuery(disc, "nearnullspace", &space);
    208:         if (space) {PetscObjectCompose((PetscObject) *is, "nearnullspace", space);}
    209:         PetscObjectQuery(disc, "pmat", &pmat);
    210:         if (pmat) {PetscObjectCompose((PetscObject) *is, "pmat", pmat);}
    211:       }
    212:       PetscDSCopyConstants(dm->prob, (*subdm)->prob);
    213:       PetscDSCopyBoundary(dm->prob, (*subdm)->prob);
    214:       PetscDSSelectEquations(dm->prob, numFields, fields, (*subdm)->prob);
    215:     }
    216:     if (dm->coarseMesh) {
    217:       DMCreateSubDM(dm->coarseMesh, numFields, fields, NULL, &(*subdm)->coarseMesh);
    218:     }
    219:   }
    220:   return(0);
    221: }

    223: /* This assumes that the DM has been cloned prior to the call */
    224: PetscErrorCode DMCreateSuperDM_Section_Private(DM dms[], PetscInt len, IS **is, DM *superdm)
    225: {
    226:   MPI_Comm       comm;
    227:   PetscSection   supersection, *sections, *sectionGlobals;
    228:   PetscInt      *Nfs, Nf = 0, f, supf, nullf = -1, i;
    229:   PetscBool      haveNull = PETSC_FALSE;

    233:   PetscObjectGetComm((PetscObject)dms[0], &comm);
    234:   /* Pull out local and global sections */
    235:   PetscMalloc3(len, &Nfs, len, &sections, len, &sectionGlobals);
    236:   for (i = 0 ; i < len; ++i) {
    237:     DMGetSection(dms[i], &sections[i]);
    238:     DMGetGlobalSection(dms[i], &sectionGlobals[i]);
    239:     if (!sections[i]) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Must set default section for DM before splitting fields");
    240:     if (!sectionGlobals[i]) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Must set default global section for DM before splitting fields");
    241:     PetscSectionGetNumFields(sections[i], &Nfs[i]);
    242:     Nf += Nfs[i];
    243:   }
    244:   /* Create the supersection */
    245:   PetscSectionCreateSupersection(sections, len, &supersection);
    246:   DMSetSection(*superdm, supersection);
    247:   /* Create ISes */
    248:   if (is) {
    249:     PetscSection supersectionGlobal;
    250:     PetscInt     bs = -1, startf = 0;

    252:     PetscMalloc1(len, is);
    253:     DMGetDefaultGlobalSection(*superdm, &supersectionGlobal);
    254:     for (i = 0 ; i < len; startf += Nfs[i], ++i) {
    255:       PetscInt *subIndices;
    256:       PetscInt  subSize, subOff, pStart, pEnd, p, start, end, dummy;

    258:       PetscSectionGetChart(sectionGlobals[i], &pStart, &pEnd);
    259:       PetscSectionGetConstrainedStorageSize(sectionGlobals[i], &subSize);
    260:       PetscMalloc1(subSize, &subIndices);
    261:       for (p = pStart, subOff = 0; p < pEnd; ++p) {
    262:         PetscInt gdof, gcdof, gtdof, d;

    264:         PetscSectionGetDof(sectionGlobals[i], p, &gdof);
    265:         PetscSectionGetConstraintDof(sections[i], p, &gcdof);
    266:         gtdof = gdof - gcdof;
    267:         if (gdof > 0 && gtdof) {
    268:           if (bs < 0)           {bs = gtdof;}
    269:           else if (bs != gtdof) {bs = 1;}
    270:           DMGetGlobalFieldOffset_Private(*superdm, p, startf, &start, &dummy);
    271:           DMGetGlobalFieldOffset_Private(*superdm, p, startf+Nfs[i]-1, &dummy, &end);
    272:           if (end-start != gtdof) SETERRQ4(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Invalid number of global dofs %D != %D for dm %D on point %D", end-start, gtdof, i, p);
    273:           for (d = start; d < end; ++d, ++subOff) subIndices[subOff] = d;
    274:         }
    275:       }
    276:       ISCreateGeneral(comm, subSize, subIndices, PETSC_OWN_POINTER, &(*is)[i]);
    277:       /* Must have same blocksize on all procs (some might have no points) */
    278:       {
    279:         PetscInt bs = -1, bsLocal[2], bsMinMax[2];

    281:         bsLocal[0] = bs < 0 ? PETSC_MAX_INT : bs; bsLocal[1] = bs;
    282:         PetscGlobalMinMaxInt(comm, bsLocal, bsMinMax);
    283:         if (bsMinMax[0] != bsMinMax[1]) {bs = 1;}
    284:         else                            {bs = bsMinMax[0];}
    285:         ISSetBlockSize((*is)[i], bs);
    286:       }
    287:     }
    288:   }
    289:   /* Preserve discretizations */
    290:   if (len && dms[0]->prob) {
    291:     DMSetNumFields(*superdm, Nf);
    292:     for (i = 0, supf = 0; i < len; ++i) {
    293:       for (f = 0; f < Nfs[i]; ++f, ++supf) {
    294:         PetscObject disc;

    296:         DMGetField(dms[i], f, &disc);
    297:         DMSetField(*superdm, supf, disc);
    298:       }
    299:     }
    300:   }
    301:   /* Preserve nullspaces */
    302:   for (i = 0, supf = 0; i < len; ++i) {
    303:     for (f = 0; f < Nfs[i]; ++f, ++supf) {
    304:       (*superdm)->nullspaceConstructors[supf] = dms[i]->nullspaceConstructors[f];
    305:       if ((*superdm)->nullspaceConstructors[supf]) {
    306:         haveNull = PETSC_TRUE;
    307:         nullf    = supf;
    308:       }
    309:     }
    310:   }
    311:   /* Attach nullspace to IS */
    312:   if (haveNull && is) {
    313:     MatNullSpace nullSpace;

    315:     (*(*superdm)->nullspaceConstructors[nullf])(*superdm, nullf, &nullSpace);
    316:     PetscObjectCompose((PetscObject) (*is)[nullf], "nullspace", (PetscObject) nullSpace);
    317:     MatNullSpaceDestroy(&nullSpace);
    318:   }
    319:   PetscSectionDestroy(&supersection);
    320:   PetscFree3(Nfs, sections, sectionGlobals);
    321:   return(0);
    322: }