Actual source code: vsection.c

  1: /*
  2:    This file contains routines for section object operations on Vecs
  3: */
  4: #include <petsc/private/sectionimpl.h>
  5: #include <petsc/private/vecimpl.h>

  7: static PetscErrorCode PetscSectionVecView_ASCII(PetscSection s, Vec v, PetscViewer viewer)
  8: {
  9:   PetscScalar *array;
 10:   PetscInt     p, i;
 11:   PetscMPIInt  rank;

 13:   PetscFunctionBegin;
 14:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
 15:   PetscCall(VecGetArray(v, &array));
 16:   PetscCall(PetscViewerASCIIPushSynchronized(viewer));
 17:   PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Process %d:\n", rank));
 18:   for (p = 0; p < s->pEnd - s->pStart; ++p) {
 19:     if ((s->bc) && (s->bc->atlasDof[p] > 0)) {
 20:       PetscInt b;

 22:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p + s->pStart, s->atlasDof[p], s->atlasOff[p]));
 23:       for (i = s->atlasOff[p]; i < s->atlasOff[p] + s->atlasDof[p]; ++i) {
 24:         PetscScalar v = array[i];
 25: #if defined(PETSC_USE_COMPLEX)
 26:         if (PetscImaginaryPart(v) > 0.0) {
 27:           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g + %g i", (double)PetscRealPart(v), (double)PetscImaginaryPart(v)));
 28:         } else if (PetscImaginaryPart(v) < 0.0) {
 29:           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g - %g i", (double)PetscRealPart(v), (double)(-PetscImaginaryPart(v))));
 30:         } else {
 31:           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(v)));
 32:         }
 33: #else
 34:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)v));
 35: #endif
 36:       }
 37:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " constrained"));
 38:       for (b = 0; b < s->bc->atlasDof[p]; ++b) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %" PetscInt_FMT, s->bcIndices[s->bc->atlasOff[p] + b]));
 39:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
 40:     } else {
 41:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "  (%4" PetscInt_FMT ") dim %2" PetscInt_FMT " offset %3" PetscInt_FMT, p + s->pStart, s->atlasDof[p], s->atlasOff[p]));
 42:       for (i = s->atlasOff[p]; i < s->atlasOff[p] + s->atlasDof[p]; ++i) {
 43:         PetscScalar v = array[i];
 44: #if defined(PETSC_USE_COMPLEX)
 45:         if (PetscImaginaryPart(v) > 0.0) {
 46:           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g + %g i", (double)PetscRealPart(v), (double)PetscImaginaryPart(v)));
 47:         } else if (PetscImaginaryPart(v) < 0.0) {
 48:           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g - %g i", (double)PetscRealPart(v), (double)(-PetscImaginaryPart(v))));
 49:         } else {
 50:           PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)PetscRealPart(v)));
 51:         }
 52: #else
 53:         PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " %g", (double)v));
 54: #endif
 55:       }
 56:       PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "\n"));
 57:     }
 58:   }
 59:   PetscCall(PetscViewerFlush(viewer));
 60:   PetscCall(PetscViewerASCIIPopSynchronized(viewer));
 61:   PetscCall(VecRestoreArray(v, &array));
 62:   PetscFunctionReturn(PETSC_SUCCESS);
 63: }

 65: /*@
 66:   PetscSectionVecView - View a vector, using the section to structure the values

 68:   Not collective

 70:   Input Parameters:
 71: + s      - the organizing PetscSection
 72: . v      - the Vec
 73: - viewer - the PetscViewer

 75:   Level: developer

 77: .seealso: `PetscSection`, `PetscSectionCreate()`, `VecSetValuesSection()`
 78: @*/
 79: PetscErrorCode PetscSectionVecView(PetscSection s, Vec v, PetscViewer viewer)
 80: {
 81:   PetscBool isascii;
 82:   PetscInt  f;

 84:   PetscFunctionBegin;
 87:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)v), &viewer));
 89:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
 90:   if (isascii) {
 91:     const char *name;

 93:     PetscCall(PetscObjectGetName((PetscObject)v, &name));
 94:     if (s->numFields) {
 95:       PetscCall(PetscViewerASCIIPrintf(viewer, "%s with %" PetscInt_FMT " fields\n", name, s->numFields));
 96:       for (f = 0; f < s->numFields; ++f) {
 97:         PetscCall(PetscViewerASCIIPrintf(viewer, "  field %" PetscInt_FMT " with %" PetscInt_FMT " components\n", f, s->numFieldComponents[f]));
 98:         PetscCall(PetscSectionVecView_ASCII(s->field[f], v, viewer));
 99:       }
100:     } else {
101:       PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", name));
102:       PetscCall(PetscSectionVecView_ASCII(s, v, viewer));
103:     }
104:   }
105:   PetscFunctionReturn(PETSC_SUCCESS);
106: }

108: /*@C
109:   VecGetValuesSection - Gets all the values associated with a given point, according to the section, in the given Vec

111:   Not collective

113:   Input Parameters:
114: + v - the Vec
115: . s - the organizing PetscSection
116: - point - the point

118:   Output Parameter:
119: . values - the array of output values

121:   Level: developer

123: .seealso: `PetscSection`, `PetscSectionCreate()`, `VecSetValuesSection()`
124: @*/
125: PetscErrorCode VecGetValuesSection(Vec v, PetscSection s, PetscInt point, PetscScalar **values)
126: {
127:   PetscScalar   *baseArray;
128:   const PetscInt p = point - s->pStart;

130:   PetscFunctionBegin;
133:   PetscCall(VecGetArray(v, &baseArray));
134:   *values = &baseArray[s->atlasOff[p]];
135:   PetscCall(VecRestoreArray(v, &baseArray));
136:   PetscFunctionReturn(PETSC_SUCCESS);
137: }

139: /*@C
140:   VecSetValuesSection - Sets all the values associated with a given point, according to the section, in the given Vec

142:   Not collective

144:   Input Parameters:
145: + v - the Vec
146: . s - the organizing PetscSection
147: . point - the point
148: . values - the array of input values
149: - mode - the insertion mode, either ADD_VALUES or INSERT_VALUES

151:   Level: developer

153:   Note: This is similar to MatSetValuesStencil(). The Fortran binding is
154: $
155: $   VecSetValuesSectionF90(vec, section, point, values, mode, ierr)
156: $

158: .seealso: `PetscSection`, `PetscSectionCreate()`, `VecGetValuesSection()`
159: @*/
160: PetscErrorCode VecSetValuesSection(Vec v, PetscSection s, PetscInt point, PetscScalar values[], InsertMode mode)
161: {
162:   PetscScalar    *baseArray, *array;
163:   const PetscBool doInsert    = mode == INSERT_VALUES || mode == INSERT_ALL_VALUES || mode == INSERT_BC_VALUES ? PETSC_TRUE : PETSC_FALSE;
164:   const PetscBool doInterior  = mode == INSERT_ALL_VALUES || mode == ADD_ALL_VALUES || mode == INSERT_VALUES || mode == ADD_VALUES ? PETSC_TRUE : PETSC_FALSE;
165:   const PetscBool doBC        = mode == INSERT_ALL_VALUES || mode == ADD_ALL_VALUES || mode == INSERT_BC_VALUES || mode == ADD_BC_VALUES ? PETSC_TRUE : PETSC_FALSE;
166:   const PetscInt  p           = point - s->pStart;
167:   const PetscInt  orientation = 0; /* Needs to be included for use in closure operations */
168:   PetscInt        cDim        = 0;

170:   PetscFunctionBegin;
173:   PetscCall(PetscSectionGetConstraintDof(s, point, &cDim));
174:   PetscCall(VecGetArray(v, &baseArray));
175:   array = &baseArray[s->atlasOff[p]];
176:   if (!cDim && doInterior) {
177:     if (orientation >= 0) {
178:       const PetscInt dim = s->atlasDof[p];
179:       PetscInt       i;

181:       if (doInsert) {
182:         for (i = 0; i < dim; ++i) array[i] = values[i];
183:       } else {
184:         for (i = 0; i < dim; ++i) array[i] += values[i];
185:       }
186:     } else {
187:       PetscInt offset = 0;
188:       PetscInt j      = -1, field, i;

190:       for (field = 0; field < s->numFields; ++field) {
191:         const PetscInt dim = s->field[field]->atlasDof[p]; /* PetscSectionGetFieldDof() */

193:         for (i = dim - 1; i >= 0; --i) array[++j] = values[i + offset];
194:         offset += dim;
195:       }
196:     }
197:   } else if (cDim) {
198:     if (orientation >= 0) {
199:       const PetscInt  dim  = s->atlasDof[p];
200:       PetscInt        cInd = 0, i;
201:       const PetscInt *cDof;

203:       PetscCall(PetscSectionGetConstraintIndices(s, point, &cDof));
204:       if (doInsert) {
205:         for (i = 0; i < dim; ++i) {
206:           if ((cInd < cDim) && (i == cDof[cInd])) {
207:             if (doBC) array[i] = values[i]; /* Constrained update */
208:             ++cInd;
209:             continue;
210:           }
211:           if (doInterior) array[i] = values[i]; /* Unconstrained update */
212:         }
213:       } else {
214:         for (i = 0; i < dim; ++i) {
215:           if ((cInd < cDim) && (i == cDof[cInd])) {
216:             if (doBC) array[i] += values[i]; /* Constrained update */
217:             ++cInd;
218:             continue;
219:           }
220:           if (doInterior) array[i] += values[i]; /* Unconstrained update */
221:         }
222:       }
223:     } else {
224:       /* TODO This is broken for add and constrained update */
225:       const PetscInt *cDof;
226:       PetscInt        offset  = 0;
227:       PetscInt        cOffset = 0;
228:       PetscInt        j       = 0, field;

230:       PetscCall(PetscSectionGetConstraintIndices(s, point, &cDof));
231:       for (field = 0; field < s->numFields; ++field) {
232:         const PetscInt dim  = s->field[field]->atlasDof[p];     /* PetscSectionGetFieldDof() */
233:         const PetscInt tDim = s->field[field]->bc->atlasDof[p]; /* PetscSectionGetFieldConstraintDof() */
234:         const PetscInt sDim = dim - tDim;
235:         PetscInt       cInd = 0, i, k;

237:         for (i = 0, k = dim + offset - 1; i < dim; ++i, ++j, --k) {
238:           if ((cInd < sDim) && (j == cDof[cInd + cOffset])) {
239:             ++cInd;
240:             continue;
241:           }
242:           if (doInterior) array[j] = values[k]; /* Unconstrained update */
243:         }
244:         offset += dim;
245:         cOffset += dim - tDim;
246:       }
247:     }
248:   }
249:   PetscCall(VecRestoreArray(v, &baseArray));
250:   PetscFunctionReturn(PETSC_SUCCESS);
251: }

253: PetscErrorCode PetscSectionGetField_Internal(PetscSection section, PetscSection sectionGlobal, Vec v, PetscInt field, PetscInt pStart, PetscInt pEnd, IS *is, Vec *subv)
254: {
255:   PetscInt *subIndices;
256:   PetscInt  Nc, subSize = 0, subOff = 0, p;

258:   PetscFunctionBegin;
259:   PetscCall(PetscSectionGetFieldComponents(section, field, &Nc));
260:   for (p = pStart; p < pEnd; ++p) {
261:     PetscInt gdof, fdof = 0;

263:     PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
264:     if (gdof > 0) PetscCall(PetscSectionGetFieldDof(section, p, field, &fdof));
265:     subSize += fdof;
266:   }
267:   PetscCall(PetscMalloc1(subSize, &subIndices));
268:   for (p = pStart; p < pEnd; ++p) {
269:     PetscInt gdof, goff;

271:     PetscCall(PetscSectionGetDof(sectionGlobal, p, &gdof));
272:     if (gdof > 0) {
273:       PetscInt fdof, fc, f2, poff = 0;

275:       PetscCall(PetscSectionGetOffset(sectionGlobal, p, &goff));
276:       /* Can get rid of this loop by storing field information in the global section */
277:       for (f2 = 0; f2 < field; ++f2) {
278:         PetscCall(PetscSectionGetFieldDof(section, p, f2, &fdof));
279:         poff += fdof;
280:       }
281:       PetscCall(PetscSectionGetFieldDof(section, p, field, &fdof));
282:       for (fc = 0; fc < fdof; ++fc, ++subOff) subIndices[subOff] = goff + poff + fc;
283:     }
284:   }
285:   PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)v), subSize, subIndices, PETSC_OWN_POINTER, is));
286:   PetscCall(VecGetSubVector(v, *is, subv));
287:   PetscCall(VecSetBlockSize(*subv, Nc));
288:   PetscFunctionReturn(PETSC_SUCCESS);
289: }

291: PetscErrorCode PetscSectionRestoreField_Internal(PetscSection section, PetscSection sectionGlobal, Vec v, PetscInt field, PetscInt pStart, PetscInt pEnd, IS *is, Vec *subv)
292: {
293:   PetscFunctionBegin;
294:   PetscCall(VecRestoreSubVector(v, *is, subv));
295:   PetscCall(ISDestroy(is));
296:   PetscFunctionReturn(PETSC_SUCCESS);
297: }

299: /*@C
300:   PetscSectionVecNorm - Computes the vector norm, separated into field components.

302:   Input Parameters:
303: + s    - the local Section
304: . gs   - the global section
305: . x    - the vector
306: - type - one of NORM_1, NORM_2, NORM_INFINITY.

308:   Output Parameter:
309: . val  - the array of norms

311:   Level: intermediate

313: .seealso: `VecNorm()`, `PetscSectionCreate()`
314: @*/
315: PetscErrorCode PetscSectionVecNorm(PetscSection s, PetscSection gs, Vec x, NormType type, PetscReal val[])
316: {
317:   PetscInt Nf, f, pStart, pEnd;

319:   PetscFunctionBegin;
324:   PetscCall(PetscSectionGetNumFields(s, &Nf));
325:   if (Nf < 2) PetscCall(VecNorm(x, type, val));
326:   else {
327:     PetscCall(PetscSectionGetChart(s, &pStart, &pEnd));
328:     for (f = 0; f < Nf; ++f) {
329:       Vec subv;
330:       IS  is;

332:       PetscCall(PetscSectionGetField_Internal(s, gs, x, f, pStart, pEnd, &is, &subv));
333:       PetscCall(VecNorm(subv, type, &val[f]));
334:       PetscCall(PetscSectionRestoreField_Internal(s, gs, x, f, pStart, pEnd, &is, &subv));
335:     }
336:   }
337:   PetscFunctionReturn(PETSC_SUCCESS);
338: }