1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petscsf.h> 3 4 #include <petsc-private/petscfeimpl.h> 5 #include <petsc-private/petscfvimpl.h> 6 7 #undef __FUNCT__ 8 #define __FUNCT__ "DMPlexGetScale" 9 PetscErrorCode DMPlexGetScale(DM dm, PetscUnit unit, PetscReal *scale) 10 { 11 DM_Plex *mesh = (DM_Plex*) dm->data; 12 13 PetscFunctionBegin; 14 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 15 PetscValidPointer(scale, 3); 16 *scale = mesh->scale[unit]; 17 PetscFunctionReturn(0); 18 } 19 20 #undef __FUNCT__ 21 #define __FUNCT__ "DMPlexSetScale" 22 PetscErrorCode DMPlexSetScale(DM dm, PetscUnit unit, PetscReal scale) 23 { 24 DM_Plex *mesh = (DM_Plex*) dm->data; 25 26 PetscFunctionBegin; 27 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 28 mesh->scale[unit] = scale; 29 PetscFunctionReturn(0); 30 } 31 32 PETSC_STATIC_INLINE PetscInt epsilon(PetscInt i, PetscInt j, PetscInt k) 33 { 34 switch (i) { 35 case 0: 36 switch (j) { 37 case 0: return 0; 38 case 1: 39 switch (k) { 40 case 0: return 0; 41 case 1: return 0; 42 case 2: return 1; 43 } 44 case 2: 45 switch (k) { 46 case 0: return 0; 47 case 1: return -1; 48 case 2: return 0; 49 } 50 } 51 case 1: 52 switch (j) { 53 case 0: 54 switch (k) { 55 case 0: return 0; 56 case 1: return 0; 57 case 2: return -1; 58 } 59 case 1: return 0; 60 case 2: 61 switch (k) { 62 case 0: return 1; 63 case 1: return 0; 64 case 2: return 0; 65 } 66 } 67 case 2: 68 switch (j) { 69 case 0: 70 switch (k) { 71 case 0: return 0; 72 case 1: return 1; 73 case 2: return 0; 74 } 75 case 1: 76 switch (k) { 77 case 0: return -1; 78 case 1: return 0; 79 case 2: return 0; 80 } 81 case 2: return 0; 82 } 83 } 84 return 0; 85 } 86 87 #undef __FUNCT__ 88 #define __FUNCT__ "DMPlexCreateRigidBody" 89 /*@C 90 DMPlexCreateRigidBody - create rigid body modes from coordinates 91 92 Collective on DM 93 94 Input Arguments: 95 + dm - the DM 96 . section - the local section associated with the rigid field, or NULL for the default section 97 - globalSection - the global section associated with the rigid field, or NULL for the default section 98 99 Output Argument: 100 . sp - the null space 101 102 Note: This is necessary to take account of Dirichlet conditions on the displacements 103 104 Level: advanced 105 106 .seealso: MatNullSpaceCreate() 107 @*/ 108 PetscErrorCode DMPlexCreateRigidBody(DM dm, PetscSection section, PetscSection globalSection, MatNullSpace *sp) 109 { 110 MPI_Comm comm; 111 Vec coordinates, localMode, mode[6]; 112 PetscSection coordSection; 113 PetscScalar *coords; 114 PetscInt dim, vStart, vEnd, v, n, m, d, i, j; 115 PetscErrorCode ierr; 116 117 PetscFunctionBegin; 118 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 119 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 120 if (dim == 1) { 121 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 122 PetscFunctionReturn(0); 123 } 124 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 125 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 126 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 127 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 128 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 129 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 130 m = (dim*(dim+1))/2; 131 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 132 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 133 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 134 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 135 /* Assume P1 */ 136 ierr = DMGetLocalVector(dm, &localMode);CHKERRQ(ierr); 137 for (d = 0; d < dim; ++d) { 138 PetscScalar values[3] = {0.0, 0.0, 0.0}; 139 140 values[d] = 1.0; 141 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 142 for (v = vStart; v < vEnd; ++v) { 143 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 144 } 145 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 146 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 147 } 148 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 149 for (d = dim; d < dim*(dim+1)/2; ++d) { 150 PetscInt i, j, k = dim > 2 ? d - dim : d; 151 152 ierr = VecSet(localMode, 0.0);CHKERRQ(ierr); 153 for (v = vStart; v < vEnd; ++v) { 154 PetscScalar values[3] = {0.0, 0.0, 0.0}; 155 PetscInt off; 156 157 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 158 for (i = 0; i < dim; ++i) { 159 for (j = 0; j < dim; ++j) { 160 values[j] += epsilon(i, j, k)*PetscRealPart(coords[off+i]); 161 } 162 } 163 ierr = DMPlexVecSetClosure(dm, section, localMode, v, values, INSERT_VALUES);CHKERRQ(ierr); 164 } 165 ierr = DMLocalToGlobalBegin(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 166 ierr = DMLocalToGlobalEnd(dm, localMode, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 167 } 168 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 169 ierr = DMRestoreLocalVector(dm, &localMode);CHKERRQ(ierr); 170 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 171 /* Orthonormalize system */ 172 for (i = dim; i < m; ++i) { 173 PetscScalar dots[6]; 174 175 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 176 for (j = 0; j < i; ++j) dots[j] *= -1.0; 177 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 178 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 179 } 180 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 181 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 182 PetscFunctionReturn(0); 183 } 184 185 #undef __FUNCT__ 186 #define __FUNCT__ "DMPlexSetMaxProjectionHeight" 187 /*@ 188 DMPlexSetMaxProjectionHeight - In DMPlexProjectXXXLocal() functions, the projected values of a basis function's dofs 189 are computed by associating the basis function with one of the mesh points in its transitively-closed support, and 190 evaluating the dual space basis of that point. A basis function is associated with the point in its 191 transitively-closed support whose mesh height is highest (w.r.t. DAG height), but not greater than the maximum 192 projection height, which is set with this function. By default, the maximum projection height is zero, which means 193 that only mesh cells are used to project basis functions. A height of one, for example, evaluates a cell-interior 194 basis functions using its cells dual space basis, but all other basis functions with the dual space basis of a face. 195 196 Input Parameters: 197 + dm - the DMPlex object 198 - height - the maximum projection height >= 0 199 200 Level: advanced 201 202 .seealso: DMPlexGetMaxProjectionHeight(), DMPlexProjectFunctionLocal(), DMPlexProjectFunctionLabelLocal() 203 @*/ 204 PetscErrorCode DMPlexSetMaxProjectionHeight(DM dm, PetscInt height) 205 { 206 DM_Plex *plex = (DM_Plex *) dm->data; 207 208 PetscFunctionBegin; 209 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 210 plex->maxProjectionHeight = height; 211 PetscFunctionReturn(0); 212 } 213 214 #undef __FUNCT__ 215 #define __FUNCT__ "DMPlexGetMaxProjectionHeight" 216 /*@ 217 DMPlexGetMaxProjectionHeight - Get the maximum height (w.r.t. DAG) of mesh points used to evaluate dual bases in 218 DMPlexProjectXXXLocal() functions. 219 220 Input Parameters: 221 . dm - the DMPlex object 222 223 Output Parameters: 224 . height - the maximum projection height 225 226 Level: intermediate 227 228 .seealso: DMPlexSetMaxProjectionHeight(), DMPlexProjectFunctionLocal(), DMPlexProjectFunctionLabelLocal() 229 @*/ 230 PetscErrorCode DMPlexGetMaxProjectionHeight(DM dm, PetscInt *height) 231 { 232 DM_Plex *plex = (DM_Plex *) dm->data; 233 234 PetscFunctionBegin; 235 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 236 *height = plex->maxProjectionHeight; 237 PetscFunctionReturn(0); 238 } 239 240 #undef __FUNCT__ 241 #define __FUNCT__ "DMPlexProjectFunctionLabelLocal" 242 PetscErrorCode DMPlexProjectFunctionLabelLocal(DM dm, DMLabel label, PetscInt numIds, const PetscInt ids[], void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 243 { 244 PetscDualSpace *sp, *cellsp; 245 PetscInt *numComp; 246 PetscSection section; 247 PetscScalar *values; 248 PetscBool *fieldActive; 249 PetscInt numFields, dim, dimEmbed, spDim, totDim = 0, numValues, pStart, pEnd, cStart, cEnd, cEndInterior, f, d, v, i, comp, maxHeight, h; 250 PetscErrorCode ierr; 251 252 PetscFunctionBegin; 253 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 254 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 255 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 256 if (cEnd <= cStart) PetscFunctionReturn(0); 257 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 258 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 259 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 260 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 261 ierr = PetscMalloc2(numFields,&sp,numFields,&numComp);CHKERRQ(ierr); 262 ierr = DMPlexGetMaxProjectionHeight(dm,&maxHeight);CHKERRQ(ierr); 263 if (maxHeight < 0 || maxHeight > dim) {SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"maximum projection height %d not in [0, %d)\n", maxHeight,dim);} 264 if (maxHeight > 0) {ierr = PetscMalloc1(numFields,&cellsp);CHKERRQ(ierr);} 265 else {cellsp = sp;} 266 for (h = 0; h <= maxHeight; h++) { 267 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 268 if (!h) {pStart = cStart; pEnd = cEnd;} 269 if (pEnd <= pStart) continue; 270 totDim = 0; 271 for (f = 0; f < numFields; ++f) { 272 PetscObject obj; 273 PetscClassId id; 274 275 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 276 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 277 if (id == PETSCFE_CLASSID) { 278 PetscFE fe = (PetscFE) obj; 279 280 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 281 if (!h) { 282 ierr = PetscFEGetDualSpace(fe, &cellsp[f]);CHKERRQ(ierr); 283 sp[f] = cellsp[f]; 284 ierr = PetscObjectReference((PetscObject) sp[f]);CHKERRQ(ierr); 285 } else { 286 ierr = PetscDualSpaceGetHeightSubspace(cellsp[f], h, &sp[f]);CHKERRQ(ierr); 287 if (!sp[f]) continue; 288 } 289 } else if (id == PETSCFV_CLASSID) { 290 PetscFV fv = (PetscFV) obj; 291 PetscQuadrature q; 292 293 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 294 ierr = PetscFVGetQuadrature(fv, &q);CHKERRQ(ierr); 295 ierr = PetscDualSpaceCreate(PetscObjectComm((PetscObject) fv), &sp[f]);CHKERRQ(ierr); 296 ierr = PetscDualSpaceSetDM(sp[f], dm);CHKERRQ(ierr); 297 ierr = PetscDualSpaceSetType(sp[f], PETSCDUALSPACESIMPLE);CHKERRQ(ierr); 298 ierr = PetscDualSpaceSimpleSetDimension(sp[f], 1);CHKERRQ(ierr); 299 ierr = PetscDualSpaceSimpleSetFunctional(sp[f], 0, q);CHKERRQ(ierr); 300 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 301 ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 302 totDim += spDim*numComp[f]; 303 } 304 ierr = DMPlexVecGetClosure(dm, section, localX, pStart, &numValues, NULL);CHKERRQ(ierr); 305 if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section point closure size %d != dual space dimension %d", numValues, totDim); 306 if (!totDim) continue; 307 ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 308 ierr = DMGetWorkArray(dm, numFields, PETSC_BOOL, &fieldActive);CHKERRQ(ierr); 309 for (f = 0; f < numFields; ++f) fieldActive[f] = (funcs[f] && sp[f]) ? PETSC_TRUE : PETSC_FALSE; 310 for (i = 0; i < numIds; ++i) { 311 IS pointIS; 312 const PetscInt *points; 313 PetscInt n, p; 314 315 ierr = DMLabelGetStratumIS(label, ids[i], &pointIS);CHKERRQ(ierr); 316 ierr = ISGetLocalSize(pointIS, &n);CHKERRQ(ierr); 317 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 318 for (p = 0; p < n; ++p) { 319 const PetscInt point = points[p]; 320 PetscFECellGeom geom; 321 322 if ((point < pStart) || (point >= pEnd)) continue; 323 ierr = DMPlexComputeCellGeometryFEM(dm, point, NULL, geom.v0, geom.J, NULL, &geom.detJ);CHKERRQ(ierr); 324 geom.dim = dim - h; 325 geom.dimEmbed = dimEmbed; 326 for (f = 0, v = 0; f < numFields; ++f) { 327 void * const ctx = ctxs ? ctxs[f] : NULL; 328 329 if (!sp[f]) continue; 330 ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 331 for (d = 0; d < spDim; ++d) { 332 if (funcs[f]) { 333 ierr = PetscDualSpaceApply(sp[f], d, &geom, numComp[f], funcs[f], ctx, &values[v]);CHKERRQ(ierr); 334 } else { 335 for (comp = 0; comp < numComp[f]; ++comp) values[v+comp] = 0.0; 336 } 337 v += numComp[f]; 338 } 339 } 340 ierr = DMPlexVecSetFieldClosure_Internal(dm, section, localX, fieldActive, point, values, mode);CHKERRQ(ierr); 341 } 342 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 343 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 344 } 345 if (h) { 346 for (f = 0; f < numFields; ++f) {ierr = PetscDualSpaceDestroy(&sp[f]);CHKERRQ(ierr);} 347 } 348 } 349 ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 350 ierr = DMRestoreWorkArray(dm, numFields, PETSC_BOOL, &fieldActive);CHKERRQ(ierr); 351 for (f = 0; f < numFields; ++f) {ierr = PetscDualSpaceDestroy(&sp[f]);CHKERRQ(ierr);} 352 ierr = PetscFree2(sp, numComp);CHKERRQ(ierr); 353 if (maxHeight > 0) { 354 ierr = PetscFree(cellsp);CHKERRQ(ierr); 355 } 356 PetscFunctionReturn(0); 357 } 358 359 #undef __FUNCT__ 360 #define __FUNCT__ "DMPlexProjectFunctionLocal" 361 PetscErrorCode DMPlexProjectFunctionLocal(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 362 { 363 PetscDualSpace *sp, *cellsp; 364 PetscInt *numComp; 365 PetscSection section; 366 PetscScalar *values; 367 PetscInt numFields, dim, dimEmbed, spDim, totDim = 0, numValues, pStart, pEnd, p, cStart, cEnd, cEndInterior, f, d, v, comp, h, maxHeight; 368 PetscErrorCode ierr; 369 370 PetscFunctionBegin; 371 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 372 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 373 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 374 if (cEnd <= cStart) PetscFunctionReturn(0); 375 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 376 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 377 ierr = PetscMalloc2(numFields, &sp, numFields, &numComp);CHKERRQ(ierr); 378 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 379 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 380 ierr = DMPlexGetMaxProjectionHeight(dm,&maxHeight);CHKERRQ(ierr); 381 if (maxHeight < 0 || maxHeight > dim) {SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"maximum projection height %d not in [0, %d)\n", maxHeight,dim);} 382 if (maxHeight > 0) { 383 ierr = PetscMalloc1(numFields,&cellsp);CHKERRQ(ierr); 384 } 385 else { 386 cellsp = sp; 387 } 388 for (h = 0; h <= maxHeight; h++) { 389 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 390 if (!h) {pStart = cStart; pEnd = cEnd;} 391 if (pEnd <= pStart) continue; 392 totDim = 0; 393 for (f = 0; f < numFields; ++f) { 394 PetscObject obj; 395 PetscClassId id; 396 397 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 398 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 399 if (id == PETSCFE_CLASSID) { 400 PetscFE fe = (PetscFE) obj; 401 402 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 403 if (!h) { 404 ierr = PetscFEGetDualSpace(fe, &cellsp[f]);CHKERRQ(ierr); 405 sp[f] = cellsp[f]; 406 ierr = PetscObjectReference((PetscObject) sp[f]);CHKERRQ(ierr); 407 } 408 else { 409 ierr = PetscDualSpaceGetHeightSubspace(cellsp[f], h, &sp[f]);CHKERRQ(ierr); 410 if (!sp[f]) { 411 continue; 412 } 413 } 414 } else if (id == PETSCFV_CLASSID) { 415 PetscFV fv = (PetscFV) obj; 416 PetscQuadrature q; 417 418 if (h) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP, "Projection height > 0 not supported for finite volume"); 419 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 420 ierr = PetscFVGetQuadrature(fv, &q);CHKERRQ(ierr); 421 ierr = PetscDualSpaceCreate(PetscObjectComm((PetscObject) fv), &sp[f]);CHKERRQ(ierr); 422 ierr = PetscDualSpaceSetDM(sp[f], dm);CHKERRQ(ierr); 423 ierr = PetscDualSpaceSetType(sp[f], PETSCDUALSPACESIMPLE);CHKERRQ(ierr); 424 ierr = PetscDualSpaceSimpleSetDimension(sp[f], 1);CHKERRQ(ierr); 425 ierr = PetscDualSpaceSimpleSetFunctional(sp[f], 0, q);CHKERRQ(ierr); 426 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 427 ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 428 totDim += spDim*numComp[f]; 429 } 430 ierr = DMPlexVecGetClosure(dm, section, localX, pStart, &numValues, NULL);CHKERRQ(ierr); 431 if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section point closure size %d != dual space dimension %d", numValues, totDim); 432 if (!totDim) continue; 433 ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 434 for (p = pStart; p < pEnd; ++p) { 435 PetscFECellGeom geom; 436 437 ierr = DMPlexComputeCellGeometryFEM(dm, p, NULL, geom.v0, geom.J, NULL, &geom.detJ);CHKERRQ(ierr); 438 geom.dim = dim - h; 439 geom.dimEmbed = dimEmbed; 440 for (f = 0, v = 0; f < numFields; ++f) { 441 void * const ctx = ctxs ? ctxs[f] : NULL; 442 443 if (!sp[f]) continue; 444 ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 445 for (d = 0; d < spDim; ++d) { 446 if (funcs[f]) { 447 ierr = PetscDualSpaceApply(sp[f], d, &geom, numComp[f], funcs[f], ctx, &values[v]);CHKERRQ(ierr); 448 } else { 449 for (comp = 0; comp < numComp[f]; ++comp) values[v+comp] = 0.0; 450 } 451 v += numComp[f]; 452 } 453 } 454 ierr = DMPlexVecSetClosure(dm, section, localX, p, values, mode);CHKERRQ(ierr); 455 } 456 ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 457 if (h || !maxHeight) { 458 for (f = 0; f < numFields; f++) {ierr = PetscDualSpaceDestroy(&sp[f]);CHKERRQ(ierr);} 459 } 460 } 461 ierr = PetscFree2(sp, numComp);CHKERRQ(ierr); 462 if (maxHeight > 0) { 463 for (f = 0; f < numFields; f++) {ierr = PetscDualSpaceDestroy(&cellsp[f]);CHKERRQ(ierr);} 464 ierr = PetscFree(cellsp);CHKERRQ(ierr); 465 } 466 PetscFunctionReturn(0); 467 } 468 469 #undef __FUNCT__ 470 #define __FUNCT__ "DMPlexProjectFunction" 471 /*@C 472 DMPlexProjectFunction - This projects the given function into the function space provided. 473 474 Input Parameters: 475 + dm - The DM 476 . funcs - The coordinate functions to evaluate, one per field 477 . ctxs - Optional array of contexts to pass to each coordinate function. ctxs itself may be null. 478 - mode - The insertion mode for values 479 480 Output Parameter: 481 . X - vector 482 483 Level: developer 484 485 .seealso: DMPlexComputeL2Diff() 486 @*/ 487 PetscErrorCode DMPlexProjectFunction(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, InsertMode mode, Vec X) 488 { 489 Vec localX; 490 PetscErrorCode ierr; 491 492 PetscFunctionBegin; 493 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 494 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 495 ierr = DMPlexProjectFunctionLocal(dm, funcs, ctxs, mode, localX);CHKERRQ(ierr); 496 ierr = DMLocalToGlobalBegin(dm, localX, mode, X);CHKERRQ(ierr); 497 ierr = DMLocalToGlobalEnd(dm, localX, mode, X);CHKERRQ(ierr); 498 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 499 PetscFunctionReturn(0); 500 } 501 502 #undef __FUNCT__ 503 #define __FUNCT__ "DMPlexProjectFieldLocal" 504 PetscErrorCode DMPlexProjectFieldLocal(DM dm, Vec localU, void (**funcs)(const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscScalar[], const PetscReal [], PetscScalar []), InsertMode mode, Vec localX) 505 { 506 DM dmAux; 507 PetscDS prob, probAux; 508 Vec A; 509 PetscSection section, sectionAux; 510 PetscScalar *values, *u, *u_x, *a, *a_x; 511 PetscReal *x, *v0, *J, *invJ, detJ, **basisField, **basisFieldDer, **basisFieldAux, **basisFieldDerAux; 512 PetscInt Nf, dim, spDim, totDim, numValues, cStart, cEnd, cEndInterior, c, f, d, v, comp, maxHeight; 513 PetscErrorCode ierr; 514 515 PetscFunctionBegin; 516 ierr = DMPlexGetMaxProjectionHeight(dm,&maxHeight);CHKERRQ(ierr); 517 if (maxHeight > 0) {SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Field projection for height > 0 not supported yet");} 518 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 519 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 520 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 521 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 522 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 523 ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 524 ierr = PetscDSGetTabulation(prob, &basisField, &basisFieldDer);CHKERRQ(ierr); 525 ierr = PetscDSGetEvaluationArrays(prob, &u, NULL, &u_x);CHKERRQ(ierr); 526 ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr); 527 ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 528 ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 529 if (dmAux) { 530 ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 531 ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 532 ierr = PetscDSGetTabulation(prob, &basisFieldAux, &basisFieldDerAux);CHKERRQ(ierr); 533 ierr = PetscDSGetEvaluationArrays(probAux, &a, NULL, &a_x);CHKERRQ(ierr); 534 } 535 ierr = DMPlexInsertBoundaryValues(dm, localU, 0.0, NULL, NULL, NULL);CHKERRQ(ierr); 536 ierr = DMPlexVecGetClosure(dm, section, localX, cStart, &numValues, NULL);CHKERRQ(ierr); 537 if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section cell closure size %d != dual space dimension %d", numValues, totDim); 538 ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 539 ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 540 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 541 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 542 for (c = cStart; c < cEnd; ++c) { 543 PetscScalar *coefficients = NULL, *coefficientsAux = NULL; 544 545 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 546 ierr = DMPlexVecGetClosure(dm, section, localU, c, NULL, &coefficients);CHKERRQ(ierr); 547 if (dmAux) {ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &coefficientsAux);CHKERRQ(ierr);} 548 for (f = 0, v = 0; f < Nf; ++f) { 549 PetscFE fe; 550 PetscDualSpace sp; 551 PetscInt Ncf; 552 553 ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 554 ierr = PetscFEGetDualSpace(fe, &sp);CHKERRQ(ierr); 555 ierr = PetscFEGetNumComponents(fe, &Ncf);CHKERRQ(ierr); 556 ierr = PetscDualSpaceGetDimension(sp, &spDim);CHKERRQ(ierr); 557 for (d = 0; d < spDim; ++d) { 558 PetscQuadrature quad; 559 const PetscReal *points, *weights; 560 PetscInt numPoints, q; 561 562 if (funcs[f]) { 563 ierr = PetscDualSpaceGetFunctional(sp, d, &quad);CHKERRQ(ierr); 564 ierr = PetscQuadratureGetData(quad, NULL, &numPoints, &points, &weights);CHKERRQ(ierr); 565 ierr = PetscFEGetTabulation(fe, numPoints, points, &basisField[f], &basisFieldDer[f], NULL);CHKERRQ(ierr); 566 for (q = 0; q < numPoints; ++q) { 567 CoordinatesRefToReal(dim, dim, v0, J, &points[q*dim], x); 568 ierr = EvaluateFieldJets(prob, PETSC_FALSE, q, invJ, coefficients, NULL, u, u_x, NULL);CHKERRQ(ierr); 569 ierr = EvaluateFieldJets(probAux, PETSC_FALSE, q, invJ, coefficientsAux, NULL, a, a_x, NULL);CHKERRQ(ierr); 570 (*funcs[f])(u, NULL, u_x, a, NULL, a_x, x, &values[v]); 571 } 572 ierr = PetscFERestoreTabulation(fe, numPoints, points, &basisField[f], &basisFieldDer[f], NULL);CHKERRQ(ierr); 573 } else { 574 for (comp = 0; comp < Ncf; ++comp) values[v+comp] = 0.0; 575 } 576 v += Ncf; 577 } 578 } 579 ierr = DMPlexVecRestoreClosure(dm, section, localU, c, NULL, &coefficients);CHKERRQ(ierr); 580 if (dmAux) {ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &coefficientsAux);CHKERRQ(ierr);} 581 ierr = DMPlexVecSetClosure(dm, section, localX, c, values, mode);CHKERRQ(ierr); 582 } 583 ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 584 ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr); 585 PetscFunctionReturn(0); 586 } 587 588 #undef __FUNCT__ 589 #define __FUNCT__ "DMPlexInsertBoundaryValues_FEM_Internal" 590 static PetscErrorCode DMPlexInsertBoundaryValues_FEM_Internal(DM dm, PetscInt field, DMLabel label, PetscInt numids, const PetscInt ids[], void (*func)(const PetscReal[], PetscScalar *, void *), void *ctx, Vec locX) 591 { 592 void (**funcs)(const PetscReal x[], PetscScalar *u, void *ctx); 593 void **ctxs; 594 PetscInt numFields; 595 PetscErrorCode ierr; 596 597 PetscFunctionBegin; 598 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 599 ierr = PetscCalloc2(numFields,&funcs,numFields,&ctxs);CHKERRQ(ierr); 600 funcs[field] = func; 601 ctxs[field] = ctx; 602 ierr = DMPlexProjectFunctionLabelLocal(dm, label, numids, ids, funcs, ctxs, INSERT_BC_VALUES, locX);CHKERRQ(ierr); 603 ierr = PetscFree2(funcs,ctxs);CHKERRQ(ierr); 604 PetscFunctionReturn(0); 605 } 606 607 #undef __FUNCT__ 608 #define __FUNCT__ "DMPlexInsertBoundaryValues_FVM_Internal" 609 static PetscErrorCode DMPlexInsertBoundaryValues_FVM_Internal(DM dm, PetscReal time, Vec faceGeometry, Vec cellGeometry, Vec Grad, 610 PetscInt field, DMLabel label, PetscInt numids, const PetscInt ids[], PetscErrorCode (*func)(PetscReal,const PetscReal*,const PetscReal*,const PetscScalar*,PetscScalar*,void*), void *ctx, Vec locX) 611 { 612 PetscDS prob; 613 PetscSF sf; 614 DM dmFace, dmCell, dmGrad; 615 const PetscScalar *facegeom, *cellgeom, *grad; 616 const PetscInt *leaves; 617 PetscScalar *x, *fx; 618 PetscInt dim, nleaves, loc, fStart, fEnd, pdim, i; 619 PetscErrorCode ierr; 620 621 PetscFunctionBegin; 622 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 623 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, NULL);CHKERRQ(ierr); 624 nleaves = PetscMax(0, nleaves); 625 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 626 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 627 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 628 ierr = VecGetDM(faceGeometry, &dmFace);CHKERRQ(ierr); 629 ierr = VecGetArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); 630 ierr = VecGetDM(cellGeometry, &dmCell);CHKERRQ(ierr); 631 ierr = VecGetArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); 632 if (Grad) { 633 PetscFV fv; 634 635 ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fv);CHKERRQ(ierr); 636 ierr = VecGetDM(Grad, &dmGrad);CHKERRQ(ierr); 637 ierr = VecGetArrayRead(Grad, &grad);CHKERRQ(ierr); 638 ierr = PetscFVGetNumComponents(fv, &pdim);CHKERRQ(ierr); 639 ierr = DMGetWorkArray(dm, pdim, PETSC_SCALAR, &fx);CHKERRQ(ierr); 640 } 641 ierr = VecGetArray(locX, &x);CHKERRQ(ierr); 642 for (i = 0; i < numids; ++i) { 643 IS faceIS; 644 const PetscInt *faces; 645 PetscInt numFaces, f; 646 647 ierr = DMLabelGetStratumIS(label, ids[i], &faceIS);CHKERRQ(ierr); 648 if (!faceIS) continue; /* No points with that id on this process */ 649 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 650 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 651 for (f = 0; f < numFaces; ++f) { 652 const PetscInt face = faces[f], *cells; 653 const PetscFVFaceGeom *fg; 654 655 if ((face < fStart) || (face >= fEnd)) continue; /* Refinement adds non-faces to labels */ 656 ierr = PetscFindInt(face, nleaves, (PetscInt *) leaves, &loc);CHKERRQ(ierr); 657 if (loc >= 0) continue; 658 ierr = DMPlexPointLocalRead(dmFace, face, facegeom, &fg);CHKERRQ(ierr); 659 ierr = DMPlexGetSupport(dm, face, &cells);CHKERRQ(ierr); 660 if (Grad) { 661 const PetscFVCellGeom *cg; 662 const PetscScalar *cx, *cgrad; 663 PetscScalar *xG; 664 PetscReal dx[3]; 665 PetscInt d; 666 667 ierr = DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cg);CHKERRQ(ierr); 668 ierr = DMPlexPointLocalRead(dm, cells[0], x, &cx);CHKERRQ(ierr); 669 ierr = DMPlexPointLocalRead(dmGrad, cells[0], grad, &cgrad);CHKERRQ(ierr); 670 ierr = DMPlexPointLocalFieldRef(dm, cells[1], field, x, &xG);CHKERRQ(ierr); 671 DMPlex_WaxpyD_Internal(dim, -1, cg->centroid, fg->centroid, dx); 672 for (d = 0; d < pdim; ++d) fx[d] = cx[d] + DMPlex_DotD_Internal(dim, &cgrad[d*dim], dx); 673 ierr = (*func)(time, fg->centroid, fg->normal, fx, xG, ctx);CHKERRQ(ierr); 674 } else { 675 const PetscScalar *xI; 676 PetscScalar *xG; 677 678 ierr = DMPlexPointLocalRead(dm, cells[0], x, &xI);CHKERRQ(ierr); 679 ierr = DMPlexPointLocalFieldRef(dm, cells[1], field, x, &xG);CHKERRQ(ierr); 680 ierr = (*func)(time, fg->centroid, fg->normal, xI, xG, ctx);CHKERRQ(ierr); 681 } 682 } 683 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 684 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 685 } 686 ierr = VecRestoreArray(locX, &x);CHKERRQ(ierr); 687 if (Grad) { 688 ierr = DMRestoreWorkArray(dm, pdim, PETSC_SCALAR, &fx);CHKERRQ(ierr); 689 ierr = VecRestoreArrayRead(Grad, &grad);CHKERRQ(ierr); 690 } 691 ierr = VecRestoreArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); 692 ierr = VecRestoreArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); 693 PetscFunctionReturn(0); 694 } 695 696 #undef __FUNCT__ 697 #define __FUNCT__ "DMPlexInsertBoundaryValues" 698 PetscErrorCode DMPlexInsertBoundaryValues(DM dm, Vec locX, PetscReal time, Vec faceGeomFVM, Vec cellGeomFVM, Vec gradFVM) 699 { 700 PetscInt numBd, b; 701 PetscErrorCode ierr; 702 703 PetscFunctionBegin; 704 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 705 PetscValidHeaderSpecific(locX, VEC_CLASSID, 2); 706 if (faceGeomFVM) {PetscValidHeaderSpecific(faceGeomFVM, VEC_CLASSID, 4);} 707 if (cellGeomFVM) {PetscValidHeaderSpecific(cellGeomFVM, VEC_CLASSID, 5);} 708 if (gradFVM) {PetscValidHeaderSpecific(gradFVM, VEC_CLASSID, 6);} 709 ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 710 for (b = 0; b < numBd; ++b) { 711 PetscBool isEssential; 712 const char *labelname; 713 DMLabel label; 714 PetscInt field; 715 PetscObject obj; 716 PetscClassId id; 717 void (*func)(); 718 PetscInt numids; 719 const PetscInt *ids; 720 void *ctx; 721 722 ierr = DMPlexGetBoundary(dm, b, &isEssential, NULL, &labelname, &field, &func, &numids, &ids, &ctx);CHKERRQ(ierr); 723 if (!isEssential) continue; 724 ierr = DMPlexGetLabel(dm, labelname, &label);CHKERRQ(ierr); 725 ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 726 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 727 if (id == PETSCFE_CLASSID) { 728 ierr = DMPlexInsertBoundaryValues_FEM_Internal(dm, field, label, numids, ids, (void (*)(const PetscReal[], PetscScalar *, void *)) func, ctx, locX);CHKERRQ(ierr); 729 } else if (id == PETSCFV_CLASSID) { 730 if (!faceGeomFVM) continue; 731 ierr = DMPlexInsertBoundaryValues_FVM_Internal(dm, time, faceGeomFVM, cellGeomFVM, gradFVM, 732 field, label, numids, ids, (PetscErrorCode (*)(PetscReal,const PetscReal*,const PetscReal*,const PetscScalar*,PetscScalar*,void*)) func, ctx, locX);CHKERRQ(ierr); 733 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 734 } 735 PetscFunctionReturn(0); 736 } 737 738 #undef __FUNCT__ 739 #define __FUNCT__ "DMPlexComputeL2Diff" 740 /*@C 741 DMPlexComputeL2Diff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h. 742 743 Input Parameters: 744 + dm - The DM 745 . funcs - The functions to evaluate for each field component 746 . ctxs - Optional array of contexts to pass to each function, or NULL. 747 - X - The coefficient vector u_h 748 749 Output Parameter: 750 . diff - The diff ||u - u_h||_2 751 752 Level: developer 753 754 .seealso: DMPlexProjectFunction(), DMPlexComputeL2FieldDiff(), DMPlexComputeL2GradientDiff() 755 @*/ 756 PetscErrorCode DMPlexComputeL2Diff(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 757 { 758 const PetscInt debug = 0; 759 PetscSection section; 760 PetscQuadrature quad; 761 Vec localX; 762 PetscScalar *funcVal, *interpolant; 763 PetscReal *coords, *v0, *J, *invJ, detJ; 764 PetscReal localDiff = 0.0; 765 const PetscReal *quadPoints, *quadWeights; 766 PetscInt dim, numFields, numComponents = 0, numQuadPoints, cStart, cEnd, cEndInterior, c, field, fieldOffset; 767 PetscErrorCode ierr; 768 769 PetscFunctionBegin; 770 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 771 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 772 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 773 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 774 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 775 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 776 for (field = 0; field < numFields; ++field) { 777 PetscObject obj; 778 PetscClassId id; 779 PetscInt Nc; 780 781 ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 782 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 783 if (id == PETSCFE_CLASSID) { 784 PetscFE fe = (PetscFE) obj; 785 786 ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 787 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 788 } else if (id == PETSCFV_CLASSID) { 789 PetscFV fv = (PetscFV) obj; 790 791 ierr = PetscFVGetQuadrature(fv, &quad);CHKERRQ(ierr); 792 ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 793 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 794 numComponents += Nc; 795 } 796 ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 797 ierr = DMPlexProjectFunctionLocal(dm, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 798 ierr = PetscMalloc6(numComponents,&funcVal,numComponents,&interpolant,dim,&coords,dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 799 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 800 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 801 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 802 for (c = cStart; c < cEnd; ++c) { 803 PetscScalar *x = NULL; 804 PetscReal elemDiff = 0.0; 805 806 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 807 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 808 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 809 810 for (field = 0, fieldOffset = 0; field < numFields; ++field) { 811 PetscObject obj; 812 PetscClassId id; 813 void * const ctx = ctxs ? ctxs[field] : NULL; 814 PetscInt Nb, Nc, q, fc; 815 816 ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 817 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 818 if (id == PETSCFE_CLASSID) {ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);ierr = PetscFEGetDimension((PetscFE) obj, &Nb);CHKERRQ(ierr);} 819 else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);Nb = 1;} 820 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 821 if (debug) { 822 char title[1024]; 823 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 824 ierr = DMPrintCellVector(c, title, Nb*Nc, &x[fieldOffset]);CHKERRQ(ierr); 825 } 826 for (q = 0; q < numQuadPoints; ++q) { 827 CoordinatesRefToReal(dim, dim, v0, J, &quadPoints[q*dim], coords); 828 (*funcs[field])(coords, funcVal, ctx); 829 if (id == PETSCFE_CLASSID) {ierr = PetscFEInterpolate_Static((PetscFE) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 830 else if (id == PETSCFV_CLASSID) {ierr = PetscFVInterpolate_Static((PetscFV) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 831 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 832 for (fc = 0; fc < Nc; ++fc) { 833 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*quadWeights[q]*detJ);CHKERRQ(ierr);} 834 elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*quadWeights[q]*detJ; 835 } 836 } 837 fieldOffset += Nb*Nc; 838 } 839 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 840 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 841 localDiff += elemDiff; 842 } 843 ierr = PetscFree6(funcVal,interpolant,coords,v0,J,invJ);CHKERRQ(ierr); 844 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 845 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 846 *diff = PetscSqrtReal(*diff); 847 PetscFunctionReturn(0); 848 } 849 850 #undef __FUNCT__ 851 #define __FUNCT__ "DMPlexComputeL2GradientDiff" 852 /*@C 853 DMPlexComputeL2GradientDiff - This function computes the L_2 difference between the gradient of a function u and an FEM interpolant solution grad u_h. 854 855 Input Parameters: 856 + dm - The DM 857 . funcs - The gradient functions to evaluate for each field component 858 . ctxs - Optional array of contexts to pass to each function, or NULL. 859 . X - The coefficient vector u_h 860 - n - The vector to project along 861 862 Output Parameter: 863 . diff - The diff ||(grad u - grad u_h) . n||_2 864 865 Level: developer 866 867 .seealso: DMPlexProjectFunction(), DMPlexComputeL2Diff() 868 @*/ 869 PetscErrorCode DMPlexComputeL2GradientDiff(DM dm, void (**funcs)(const PetscReal [], const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff) 870 { 871 const PetscInt debug = 0; 872 PetscSection section; 873 PetscQuadrature quad; 874 Vec localX; 875 PetscScalar *funcVal, *interpolantVec; 876 PetscReal *coords, *realSpaceDer, *v0, *J, *invJ, detJ; 877 PetscReal localDiff = 0.0; 878 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, cEndInterior, c, field, fieldOffset, comp; 879 PetscErrorCode ierr; 880 881 PetscFunctionBegin; 882 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 883 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 884 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 885 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 886 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 887 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 888 for (field = 0; field < numFields; ++field) { 889 PetscFE fe; 890 PetscInt Nc; 891 892 ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 893 ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 894 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 895 numComponents += Nc; 896 } 897 /* ierr = DMPlexProjectFunctionLocal(dm, fe, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); */ 898 ierr = PetscMalloc7(numComponents,&funcVal,dim,&coords,dim,&realSpaceDer,dim,&v0,dim*dim,&J,dim*dim,&invJ,dim,&interpolantVec);CHKERRQ(ierr); 899 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 900 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 901 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 902 for (c = cStart; c < cEnd; ++c) { 903 PetscScalar *x = NULL; 904 PetscReal elemDiff = 0.0; 905 906 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 907 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 908 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 909 910 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 911 PetscFE fe; 912 void * const ctx = ctxs ? ctxs[field] : NULL; 913 const PetscReal *quadPoints, *quadWeights; 914 PetscReal *basisDer; 915 PetscInt numQuadPoints, Nb, Ncomp, q, d, e, fc, f, g; 916 917 ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 918 ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 919 ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 920 ierr = PetscFEGetNumComponents(fe, &Ncomp);CHKERRQ(ierr); 921 ierr = PetscFEGetDefaultTabulation(fe, NULL, &basisDer, NULL);CHKERRQ(ierr); 922 if (debug) { 923 char title[1024]; 924 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 925 ierr = DMPrintCellVector(c, title, Nb*Ncomp, &x[fieldOffset]);CHKERRQ(ierr); 926 } 927 for (q = 0; q < numQuadPoints; ++q) { 928 for (d = 0; d < dim; d++) { 929 coords[d] = v0[d]; 930 for (e = 0; e < dim; e++) { 931 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 932 } 933 } 934 (*funcs[field])(coords, n, funcVal, ctx); 935 for (fc = 0; fc < Ncomp; ++fc) { 936 PetscScalar interpolant = 0.0; 937 938 for (d = 0; d < dim; ++d) interpolantVec[d] = 0.0; 939 for (f = 0; f < Nb; ++f) { 940 const PetscInt fidx = f*Ncomp+fc; 941 942 for (d = 0; d < dim; ++d) { 943 realSpaceDer[d] = 0.0; 944 for (g = 0; g < dim; ++g) { 945 realSpaceDer[d] += invJ[g*dim+d]*basisDer[(q*Nb*Ncomp+fidx)*dim+g]; 946 } 947 interpolantVec[d] += x[fieldOffset+fidx]*realSpaceDer[d]; 948 } 949 } 950 for (d = 0; d < dim; ++d) interpolant += interpolantVec[d]*n[d]; 951 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d fieldDer %d diff %g\n", c, field, PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ);CHKERRQ(ierr);} 952 elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ; 953 } 954 } 955 comp += Ncomp; 956 fieldOffset += Nb*Ncomp; 957 } 958 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 959 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 960 localDiff += elemDiff; 961 } 962 ierr = PetscFree7(funcVal,coords,realSpaceDer,v0,J,invJ,interpolantVec);CHKERRQ(ierr); 963 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 964 ierr = MPI_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 965 *diff = PetscSqrtReal(*diff); 966 PetscFunctionReturn(0); 967 } 968 969 #undef __FUNCT__ 970 #define __FUNCT__ "DMPlexComputeL2FieldDiff" 971 /*@C 972 DMPlexComputeL2FieldDiff - This function computes the L_2 difference between a function u and an FEM interpolant solution u_h, separated into field components. 973 974 Input Parameters: 975 + dm - The DM 976 . funcs - The functions to evaluate for each field component 977 . ctxs - Optional array of contexts to pass to each function, or NULL. 978 - X - The coefficient vector u_h 979 980 Output Parameter: 981 . diff - The array of differences, ||u^f - u^f_h||_2 982 983 Level: developer 984 985 .seealso: DMPlexProjectFunction(), DMPlexComputeL2Diff(), DMPlexComputeL2GradientDiff() 986 @*/ 987 PetscErrorCode DMPlexComputeL2FieldDiff(DM dm, void (**funcs)(const PetscReal [], PetscScalar *, void *), void **ctxs, Vec X, PetscReal diff[]) 988 { 989 const PetscInt debug = 0; 990 PetscSection section; 991 PetscQuadrature quad; 992 Vec localX; 993 PetscScalar *funcVal, *interpolant; 994 PetscReal *coords, *v0, *J, *invJ, detJ; 995 PetscReal *localDiff; 996 const PetscReal *quadPoints, *quadWeights; 997 PetscInt dim, numFields, numComponents = 0, numQuadPoints, cStart, cEnd, cEndInterior, c, field, fieldOffset; 998 PetscErrorCode ierr; 999 1000 PetscFunctionBegin; 1001 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1002 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1003 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 1004 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 1005 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 1006 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 1007 for (field = 0; field < numFields; ++field) { 1008 PetscObject obj; 1009 PetscClassId id; 1010 PetscInt Nc; 1011 1012 ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 1013 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1014 if (id == PETSCFE_CLASSID) { 1015 PetscFE fe = (PetscFE) obj; 1016 1017 ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 1018 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 1019 } else if (id == PETSCFV_CLASSID) { 1020 PetscFV fv = (PetscFV) obj; 1021 1022 ierr = PetscFVGetQuadrature(fv, &quad);CHKERRQ(ierr); 1023 ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 1024 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 1025 numComponents += Nc; 1026 } 1027 ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 1028 ierr = DMPlexProjectFunctionLocal(dm, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 1029 ierr = PetscCalloc7(numFields,&localDiff,numComponents,&funcVal,numComponents,&interpolant,dim,&coords,dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 1030 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1031 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 1032 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 1033 for (c = cStart; c < cEnd; ++c) { 1034 PetscScalar *x = NULL; 1035 1036 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 1037 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 1038 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 1039 1040 for (field = 0, fieldOffset = 0; field < numFields; ++field) { 1041 PetscObject obj; 1042 PetscClassId id; 1043 void * const ctx = ctxs ? ctxs[field] : NULL; 1044 PetscInt Nb, Nc, q, fc; 1045 1046 PetscReal elemDiff = 0.0; 1047 1048 ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 1049 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1050 if (id == PETSCFE_CLASSID) {ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);ierr = PetscFEGetDimension((PetscFE) obj, &Nb);CHKERRQ(ierr);} 1051 else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);Nb = 1;} 1052 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 1053 if (debug) { 1054 char title[1024]; 1055 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 1056 ierr = DMPrintCellVector(c, title, Nb*Nc, &x[fieldOffset]);CHKERRQ(ierr); 1057 } 1058 for (q = 0; q < numQuadPoints; ++q) { 1059 CoordinatesRefToReal(dim, dim, v0, J, &quadPoints[q*dim], coords); 1060 (*funcs[field])(coords, funcVal, ctx); 1061 if (id == PETSCFE_CLASSID) {ierr = PetscFEInterpolate_Static((PetscFE) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 1062 else if (id == PETSCFV_CLASSID) {ierr = PetscFVInterpolate_Static((PetscFV) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 1063 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 1064 for (fc = 0; fc < Nc; ++fc) { 1065 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d field %d diff %g\n", c, field, PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*quadWeights[q]*detJ);CHKERRQ(ierr);} 1066 elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*quadWeights[q]*detJ; 1067 } 1068 } 1069 fieldOffset += Nb*Nc; 1070 localDiff[field] += elemDiff; 1071 } 1072 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 1073 } 1074 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 1075 ierr = MPI_Allreduce(localDiff, diff, numFields, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1076 for (field = 0; field < numFields; ++field) diff[field] = PetscSqrtReal(diff[field]); 1077 ierr = PetscFree7(localDiff,funcVal,interpolant,coords,v0,J,invJ);CHKERRQ(ierr); 1078 PetscFunctionReturn(0); 1079 } 1080 1081 #undef __FUNCT__ 1082 #define __FUNCT__ "DMPlexComputeIntegralFEM" 1083 /*@ 1084 DMPlexComputeIntegralFEM - Form the local integral F from the local input X using pointwise functions specified by the user 1085 1086 Input Parameters: 1087 + dm - The mesh 1088 . X - Local input vector 1089 - user - The user context 1090 1091 Output Parameter: 1092 . integral - Local integral for each field 1093 1094 Level: developer 1095 1096 .seealso: DMPlexComputeResidualFEM() 1097 @*/ 1098 PetscErrorCode DMPlexComputeIntegralFEM(DM dm, Vec X, PetscReal *integral, void *user) 1099 { 1100 DM_Plex *mesh = (DM_Plex *) dm->data; 1101 DM dmAux; 1102 Vec localX, A; 1103 PetscDS prob, probAux = NULL; 1104 PetscQuadrature q; 1105 PetscSection section, sectionAux; 1106 PetscFECellGeom *cgeom; 1107 PetscScalar *u, *a = NULL; 1108 PetscReal *lintegral, *vol; 1109 PetscInt dim, Nf, f, numCells, cStart, cEnd, cEndInterior, c; 1110 PetscInt totDim, totDimAux; 1111 PetscErrorCode ierr; 1112 1113 PetscFunctionBegin; 1114 ierr = PetscLogEventBegin(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr); 1115 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 1116 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 1117 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 1118 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1119 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1120 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 1121 ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 1122 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 1123 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1124 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 1125 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 1126 numCells = cEnd - cStart; 1127 ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 1128 ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 1129 if (dmAux) { 1130 ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 1131 ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 1132 ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 1133 } 1134 ierr = DMPlexInsertBoundaryValues(dm, localX, 0.0, NULL, NULL, NULL);CHKERRQ(ierr); 1135 ierr = PetscMalloc4(Nf,&lintegral,numCells*totDim,&u,numCells,&cgeom,numCells,&vol);CHKERRQ(ierr); 1136 if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 1137 for (f = 0; f < Nf; ++f) {lintegral[f] = 0.0;} 1138 for (c = cStart; c < cEnd; ++c) { 1139 PetscScalar *x = NULL; 1140 PetscInt i; 1141 1142 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, cgeom[c].v0, cgeom[c].J, cgeom[c].invJ, &cgeom[c].detJ);CHKERRQ(ierr); 1143 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol[c], NULL, NULL);CHKERRQ(ierr); 1144 if (cgeom[c].detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", cgeom[c].detJ, c); 1145 ierr = DMPlexVecGetClosure(dm, section, localX, c, NULL, &x);CHKERRQ(ierr); 1146 for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 1147 ierr = DMPlexVecRestoreClosure(dm, section, localX, c, NULL, &x);CHKERRQ(ierr); 1148 if (dmAux) { 1149 ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 1150 for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 1151 ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 1152 } 1153 } 1154 for (f = 0; f < Nf; ++f) { 1155 PetscObject obj; 1156 PetscClassId id; 1157 PetscInt numChunks, numBatches, batchSize, numBlocks, blockSize, Ne, Nr, offset; 1158 1159 ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 1160 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1161 if (id == PETSCFE_CLASSID) { 1162 PetscFE fe = (PetscFE) obj; 1163 PetscQuadrature q; 1164 PetscInt Nq, Nb; 1165 1166 ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 1167 ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 1168 ierr = PetscQuadratureGetData(q, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 1169 ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 1170 blockSize = Nb*Nq; 1171 batchSize = numBlocks * blockSize; 1172 ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 1173 numChunks = numCells / (numBatches*batchSize); 1174 Ne = numChunks*numBatches*batchSize; 1175 Nr = numCells % (numBatches*batchSize); 1176 offset = numCells - Nr; 1177 ierr = PetscFEIntegrate(fe, prob, f, Ne, cgeom, u, probAux, a, lintegral);CHKERRQ(ierr); 1178 ierr = PetscFEIntegrate(fe, prob, f, Nr, &cgeom[offset], &u[offset*totDim], probAux, &a[offset*totDimAux], lintegral);CHKERRQ(ierr); 1179 } else if (id == PETSCFV_CLASSID) { 1180 PetscFV fv = (PetscFV) obj; 1181 PetscInt foff; 1182 void (*obj_func)(const PetscScalar u[], const PetscScalar u_x[], const PetscScalar u_t[], const PetscScalar a[], const PetscScalar a_x[], const PetscScalar a_t[], const PetscReal x[], PetscScalar obj[]); 1183 1184 ierr = PetscDSGetObjective(prob, f, &obj_func);CHKERRQ(ierr); 1185 ierr = PetscDSGetFieldOffset(prob, f, &foff);CHKERRQ(ierr); 1186 if (obj_func) { 1187 for (c = 0; c < numCells; ++c) { 1188 /* TODO: Need full pointwise interpolation and get centroid for x argument */ 1189 obj_func(&u[totDim*c+foff], NULL, NULL, NULL, NULL, NULL, NULL, &lintegral[f]); 1190 lintegral[f] *= vol[c]; 1191 } 1192 } 1193 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 1194 } 1195 if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 1196 if (mesh->printFEM) { 1197 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "Local integral:");CHKERRQ(ierr); 1198 for (f = 0; f < Nf; ++f) {ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), " %g", lintegral[f]);CHKERRQ(ierr);} 1199 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "\n");CHKERRQ(ierr); 1200 } 1201 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 1202 ierr = MPI_Allreduce(lintegral, integral, Nf, MPIU_REAL, MPI_SUM, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 1203 ierr = PetscFree4(lintegral,u,cgeom,vol);CHKERRQ(ierr); 1204 ierr = PetscLogEventEnd(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr); 1205 PetscFunctionReturn(0); 1206 } 1207 1208 #undef __FUNCT__ 1209 #define __FUNCT__ "DMPlexComputeInterpolatorFEM" 1210 /*@ 1211 DMPlexComputeInterpolatorFEM - Form the local portion of the interpolation matrix I from the coarse DM to the uniformly refined DM. 1212 1213 Input Parameters: 1214 + dmf - The fine mesh 1215 . dmc - The coarse mesh 1216 - user - The user context 1217 1218 Output Parameter: 1219 . In - The interpolation matrix 1220 1221 Note: 1222 The first member of the user context must be an FEMContext. 1223 1224 We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, 1225 like a GPU, or vectorize on a multicore machine. 1226 1227 Level: developer 1228 1229 .seealso: DMPlexComputeJacobianFEM() 1230 @*/ 1231 PetscErrorCode DMPlexComputeInterpolatorFEM(DM dmc, DM dmf, Mat In, void *user) 1232 { 1233 DM_Plex *mesh = (DM_Plex *) dmc->data; 1234 const char *name = "Interpolator"; 1235 PetscDS prob; 1236 PetscFE *feRef; 1237 PetscSection fsection, fglobalSection; 1238 PetscSection csection, cglobalSection; 1239 PetscScalar *elemMat; 1240 PetscInt dim, Nf, f, fieldI, fieldJ, offsetI, offsetJ, cStart, cEnd, cEndInterior, c; 1241 PetscInt cTotDim, rTotDim = 0; 1242 PetscErrorCode ierr; 1243 1244 PetscFunctionBegin; 1245 ierr = PetscLogEventBegin(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1246 ierr = DMGetDimension(dmf, &dim);CHKERRQ(ierr); 1247 ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 1248 ierr = DMGetDefaultGlobalSection(dmf, &fglobalSection);CHKERRQ(ierr); 1249 ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 1250 ierr = DMGetDefaultGlobalSection(dmc, &cglobalSection);CHKERRQ(ierr); 1251 ierr = PetscSectionGetNumFields(fsection, &Nf);CHKERRQ(ierr); 1252 ierr = DMPlexGetHeightStratum(dmc, 0, &cStart, &cEnd);CHKERRQ(ierr); 1253 ierr = DMPlexGetHybridBounds(dmc, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 1254 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 1255 ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr); 1256 ierr = PetscMalloc1(Nf,&feRef);CHKERRQ(ierr); 1257 for (f = 0; f < Nf; ++f) { 1258 PetscFE fe; 1259 PetscInt rNb, Nc; 1260 1261 ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 1262 ierr = PetscFERefine(fe, &feRef[f]);CHKERRQ(ierr); 1263 ierr = PetscFEGetDimension(feRef[f], &rNb);CHKERRQ(ierr); 1264 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 1265 rTotDim += rNb*Nc; 1266 } 1267 ierr = PetscDSGetTotalDimension(prob, &cTotDim);CHKERRQ(ierr); 1268 ierr = PetscMalloc1(rTotDim*cTotDim,&elemMat);CHKERRQ(ierr); 1269 ierr = PetscMemzero(elemMat, rTotDim*cTotDim * sizeof(PetscScalar));CHKERRQ(ierr); 1270 for (fieldI = 0, offsetI = 0; fieldI < Nf; ++fieldI) { 1271 PetscDualSpace Qref; 1272 PetscQuadrature f; 1273 const PetscReal *qpoints, *qweights; 1274 PetscReal *points; 1275 PetscInt npoints = 0, Nc, Np, fpdim, i, k, p, d; 1276 1277 /* Compose points from all dual basis functionals */ 1278 ierr = PetscFEGetDualSpace(feRef[fieldI], &Qref);CHKERRQ(ierr); 1279 ierr = PetscFEGetNumComponents(feRef[fieldI], &Nc);CHKERRQ(ierr); 1280 ierr = PetscDualSpaceGetDimension(Qref, &fpdim);CHKERRQ(ierr); 1281 for (i = 0; i < fpdim; ++i) { 1282 ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1283 ierr = PetscQuadratureGetData(f, NULL, &Np, NULL, NULL);CHKERRQ(ierr); 1284 npoints += Np; 1285 } 1286 ierr = PetscMalloc1(npoints*dim,&points);CHKERRQ(ierr); 1287 for (i = 0, k = 0; i < fpdim; ++i) { 1288 ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1289 ierr = PetscQuadratureGetData(f, NULL, &Np, &qpoints, NULL);CHKERRQ(ierr); 1290 for (p = 0; p < Np; ++p, ++k) for (d = 0; d < dim; ++d) points[k*dim+d] = qpoints[p*dim+d]; 1291 } 1292 1293 for (fieldJ = 0, offsetJ = 0; fieldJ < Nf; ++fieldJ) { 1294 PetscFE fe; 1295 PetscReal *B; 1296 PetscInt NcJ, cpdim, j; 1297 1298 /* Evaluate basis at points */ 1299 ierr = PetscDSGetDiscretization(prob, fieldJ, (PetscObject *) &fe);CHKERRQ(ierr); 1300 ierr = PetscFEGetNumComponents(fe, &NcJ);CHKERRQ(ierr); 1301 ierr = PetscFEGetDimension(fe, &cpdim);CHKERRQ(ierr); 1302 /* For now, fields only interpolate themselves */ 1303 if (fieldI == fieldJ) { 1304 if (Nc != NcJ) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in fine space field %d does not match coarse field %d", Nc, NcJ); 1305 ierr = PetscFEGetTabulation(fe, npoints, points, &B, NULL, NULL);CHKERRQ(ierr); 1306 for (i = 0, k = 0; i < fpdim; ++i) { 1307 ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1308 ierr = PetscQuadratureGetData(f, NULL, &Np, NULL, &qweights);CHKERRQ(ierr); 1309 for (p = 0; p < Np; ++p, ++k) { 1310 for (j = 0; j < cpdim; ++j) { 1311 for (c = 0; c < Nc; ++c) elemMat[(offsetI + i*Nc + c)*cTotDim + offsetJ + j*NcJ + c] += B[k*cpdim*NcJ+j*Nc+c]*qweights[p]; 1312 } 1313 } 1314 } 1315 ierr = PetscFERestoreTabulation(fe, npoints, points, &B, NULL, NULL);CHKERRQ(ierr);CHKERRQ(ierr); 1316 } 1317 offsetJ += cpdim*NcJ; 1318 } 1319 offsetI += fpdim*Nc; 1320 ierr = PetscFree(points);CHKERRQ(ierr); 1321 } 1322 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(0, name, rTotDim, cTotDim, elemMat);CHKERRQ(ierr);} 1323 /* Preallocate matrix */ 1324 { 1325 PetscHashJK ht; 1326 PetscLayout rLayout; 1327 PetscInt *dnz, *onz, *cellCIndices, *cellFIndices; 1328 PetscInt locRows, rStart, rEnd, cell, r; 1329 1330 ierr = MatGetLocalSize(In, &locRows, NULL);CHKERRQ(ierr); 1331 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) In), &rLayout);CHKERRQ(ierr); 1332 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 1333 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 1334 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 1335 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 1336 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 1337 ierr = PetscCalloc4(locRows,&dnz,locRows,&onz,cTotDim,&cellCIndices,rTotDim,&cellFIndices);CHKERRQ(ierr); 1338 ierr = PetscHashJKCreate(&ht);CHKERRQ(ierr); 1339 for (cell = cStart; cell < cEnd; ++cell) { 1340 ierr = DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, cell, cellCIndices, cellFIndices);CHKERRQ(ierr); 1341 for (r = 0; r < rTotDim; ++r) { 1342 PetscHashJKKey key; 1343 PetscHashJKIter missing, iter; 1344 1345 key.j = cellFIndices[r]; 1346 if (key.j < 0) continue; 1347 for (c = 0; c < cTotDim; ++c) { 1348 key.k = cellCIndices[c]; 1349 if (key.k < 0) continue; 1350 ierr = PetscHashJKPut(ht, key, &missing, &iter);CHKERRQ(ierr); 1351 if (missing) { 1352 ierr = PetscHashJKSet(ht, iter, 1);CHKERRQ(ierr); 1353 if ((key.k >= rStart) && (key.k < rEnd)) ++dnz[key.j-rStart]; 1354 else ++onz[key.j-rStart]; 1355 } 1356 } 1357 } 1358 } 1359 ierr = PetscHashJKDestroy(&ht);CHKERRQ(ierr); 1360 ierr = MatXAIJSetPreallocation(In, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr); 1361 ierr = MatSetOption(In, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1362 ierr = PetscFree4(dnz,onz,cellCIndices,cellFIndices);CHKERRQ(ierr); 1363 } 1364 /* Fill matrix */ 1365 ierr = MatZeroEntries(In);CHKERRQ(ierr); 1366 for (c = cStart; c < cEnd; ++c) { 1367 ierr = DMPlexMatSetClosureRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, In, c, elemMat, INSERT_VALUES);CHKERRQ(ierr); 1368 } 1369 for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&feRef[f]);CHKERRQ(ierr);} 1370 ierr = PetscFree(feRef);CHKERRQ(ierr); 1371 ierr = PetscFree(elemMat);CHKERRQ(ierr); 1372 ierr = MatAssemblyBegin(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1373 ierr = MatAssemblyEnd(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1374 if (mesh->printFEM) { 1375 ierr = PetscPrintf(PETSC_COMM_WORLD, "%s:\n", name);CHKERRQ(ierr); 1376 ierr = MatChop(In, 1.0e-10);CHKERRQ(ierr); 1377 ierr = MatView(In, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1378 } 1379 ierr = PetscLogEventEnd(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1380 PetscFunctionReturn(0); 1381 } 1382 1383 #undef __FUNCT__ 1384 #define __FUNCT__ "DMPlexComputeInjectorFEM" 1385 PetscErrorCode DMPlexComputeInjectorFEM(DM dmc, DM dmf, VecScatter *sc, void *user) 1386 { 1387 PetscDS prob; 1388 PetscFE *feRef; 1389 Vec fv, cv; 1390 IS fis, cis; 1391 PetscSection fsection, fglobalSection, csection, cglobalSection; 1392 PetscInt *cmap, *cellCIndices, *cellFIndices, *cindices, *findices; 1393 PetscInt cTotDim, fTotDim = 0, Nf, f, field, cStart, cEnd, cEndInterior, c, dim, d, startC, offsetC, offsetF, m; 1394 PetscErrorCode ierr; 1395 1396 PetscFunctionBegin; 1397 ierr = PetscLogEventBegin(DMPLEX_InjectorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1398 ierr = DMGetDimension(dmf, &dim);CHKERRQ(ierr); 1399 ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 1400 ierr = DMGetDefaultGlobalSection(dmf, &fglobalSection);CHKERRQ(ierr); 1401 ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 1402 ierr = DMGetDefaultGlobalSection(dmc, &cglobalSection);CHKERRQ(ierr); 1403 ierr = PetscSectionGetNumFields(fsection, &Nf);CHKERRQ(ierr); 1404 ierr = DMPlexGetHeightStratum(dmc, 0, &cStart, &cEnd);CHKERRQ(ierr); 1405 ierr = DMPlexGetHybridBounds(dmc, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 1406 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 1407 ierr = DMGetDS(dmc, &prob);CHKERRQ(ierr); 1408 ierr = PetscMalloc1(Nf,&feRef);CHKERRQ(ierr); 1409 for (f = 0; f < Nf; ++f) { 1410 PetscFE fe; 1411 PetscInt fNb, Nc; 1412 1413 ierr = PetscDSGetDiscretization(prob, f, (PetscObject *) &fe);CHKERRQ(ierr); 1414 ierr = PetscFERefine(fe, &feRef[f]);CHKERRQ(ierr); 1415 ierr = PetscFEGetDimension(feRef[f], &fNb);CHKERRQ(ierr); 1416 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 1417 fTotDim += fNb*Nc; 1418 } 1419 ierr = PetscDSGetTotalDimension(prob, &cTotDim);CHKERRQ(ierr); 1420 ierr = PetscMalloc1(cTotDim,&cmap);CHKERRQ(ierr); 1421 for (field = 0, offsetC = 0, offsetF = 0; field < Nf; ++field) { 1422 PetscFE feC; 1423 PetscDualSpace QF, QC; 1424 PetscInt NcF, NcC, fpdim, cpdim; 1425 1426 ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &feC);CHKERRQ(ierr); 1427 ierr = PetscFEGetNumComponents(feC, &NcC);CHKERRQ(ierr); 1428 ierr = PetscFEGetNumComponents(feRef[field], &NcF);CHKERRQ(ierr); 1429 if (NcF != NcC) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of components in fine space field %d does not match coarse field %d", NcF, NcC); 1430 ierr = PetscFEGetDualSpace(feRef[field], &QF);CHKERRQ(ierr); 1431 ierr = PetscDualSpaceGetDimension(QF, &fpdim);CHKERRQ(ierr); 1432 ierr = PetscFEGetDualSpace(feC, &QC);CHKERRQ(ierr); 1433 ierr = PetscDualSpaceGetDimension(QC, &cpdim);CHKERRQ(ierr); 1434 for (c = 0; c < cpdim; ++c) { 1435 PetscQuadrature cfunc; 1436 const PetscReal *cqpoints; 1437 PetscInt NpC; 1438 1439 ierr = PetscDualSpaceGetFunctional(QC, c, &cfunc);CHKERRQ(ierr); 1440 ierr = PetscQuadratureGetData(cfunc, NULL, &NpC, &cqpoints, NULL);CHKERRQ(ierr); 1441 if (NpC != 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not know how to do injection for moments"); 1442 for (f = 0; f < fpdim; ++f) { 1443 PetscQuadrature ffunc; 1444 const PetscReal *fqpoints; 1445 PetscReal sum = 0.0; 1446 PetscInt NpF, comp; 1447 1448 ierr = PetscDualSpaceGetFunctional(QF, f, &ffunc);CHKERRQ(ierr); 1449 ierr = PetscQuadratureGetData(ffunc, NULL, &NpF, &fqpoints, NULL);CHKERRQ(ierr); 1450 if (NpC != NpF) continue; 1451 for (d = 0; d < dim; ++d) sum += PetscAbsReal(cqpoints[d] - fqpoints[d]); 1452 if (sum > 1.0e-9) continue; 1453 for (comp = 0; comp < NcC; ++comp) { 1454 cmap[(offsetC+c)*NcC+comp] = (offsetF+f)*NcF+comp; 1455 } 1456 break; 1457 } 1458 } 1459 offsetC += cpdim*NcC; 1460 offsetF += fpdim*NcF; 1461 } 1462 for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&feRef[f]);CHKERRQ(ierr);} 1463 ierr = PetscFree(feRef);CHKERRQ(ierr); 1464 1465 ierr = DMGetGlobalVector(dmf, &fv);CHKERRQ(ierr); 1466 ierr = DMGetGlobalVector(dmc, &cv);CHKERRQ(ierr); 1467 ierr = VecGetOwnershipRange(cv, &startC, NULL);CHKERRQ(ierr); 1468 ierr = PetscSectionGetConstrainedStorageSize(cglobalSection, &m);CHKERRQ(ierr); 1469 ierr = PetscMalloc2(cTotDim,&cellCIndices,fTotDim,&cellFIndices);CHKERRQ(ierr); 1470 ierr = PetscMalloc1(m,&cindices);CHKERRQ(ierr); 1471 ierr = PetscMalloc1(m,&findices);CHKERRQ(ierr); 1472 for (d = 0; d < m; ++d) cindices[d] = findices[d] = -1; 1473 for (c = cStart; c < cEnd; ++c) { 1474 ierr = DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, c, cellCIndices, cellFIndices);CHKERRQ(ierr); 1475 for (d = 0; d < cTotDim; ++d) { 1476 if (cellCIndices[d] < 0) continue; 1477 if ((findices[cellCIndices[d]-startC] >= 0) && (findices[cellCIndices[d]-startC] != cellFIndices[cmap[d]])) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Coarse dof %d maps to both %d and %d", cindices[cellCIndices[d]-startC], findices[cellCIndices[d]-startC], cellFIndices[cmap[d]]); 1478 cindices[cellCIndices[d]-startC] = cellCIndices[d]; 1479 findices[cellCIndices[d]-startC] = cellFIndices[cmap[d]]; 1480 } 1481 } 1482 ierr = PetscFree(cmap);CHKERRQ(ierr); 1483 ierr = PetscFree2(cellCIndices,cellFIndices);CHKERRQ(ierr); 1484 1485 ierr = ISCreateGeneral(PETSC_COMM_SELF, m, cindices, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr); 1486 ierr = ISCreateGeneral(PETSC_COMM_SELF, m, findices, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr); 1487 ierr = VecScatterCreate(cv, cis, fv, fis, sc);CHKERRQ(ierr); 1488 ierr = ISDestroy(&cis);CHKERRQ(ierr); 1489 ierr = ISDestroy(&fis);CHKERRQ(ierr); 1490 ierr = DMRestoreGlobalVector(dmf, &fv);CHKERRQ(ierr); 1491 ierr = DMRestoreGlobalVector(dmc, &cv);CHKERRQ(ierr); 1492 ierr = PetscLogEventEnd(DMPLEX_InjectorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1493 PetscFunctionReturn(0); 1494 } 1495