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: }