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__ "DMPlexProjectRigidBody" 89 static PetscErrorCode DMPlexProjectRigidBody(PetscInt dim, PetscReal t, const PetscReal X[], PetscInt Nf, PetscScalar *mode, void *ctx) 90 { 91 PetscInt *ctxInt = (PetscInt *) ctx; 92 PetscInt dim2 = ctxInt[0]; 93 PetscInt d = ctxInt[1]; 94 PetscInt i, j, k = dim > 2 ? d - dim : d; 95 96 PetscFunctionBegin; 97 if (dim != dim2) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Input dimension %d does not match context dimension %d", dim, dim2); 98 for (i = 0; i < dim; i++) mode[i] = 0.; 99 if (d < dim) { 100 mode[d] = 1.; 101 } else { 102 for (i = 0; i < dim; i++) { 103 for (j = 0; j < dim; j++) { 104 mode[j] += epsilon(i, j, k)*X[i]; 105 } 106 } 107 } 108 PetscFunctionReturn(0); 109 } 110 111 #undef __FUNCT__ 112 #define __FUNCT__ "DMPlexCreateRigidBody" 113 /*@C 114 DMPlexCreateRigidBody - for the default global section, create rigid body modes from coordinates 115 116 Collective on DM 117 118 Input Arguments: 119 . dm - the DM 120 121 Output Argument: 122 . sp - the null space 123 124 Note: This is necessary to take account of Dirichlet conditions on the displacements 125 126 Level: advanced 127 128 .seealso: MatNullSpaceCreate() 129 @*/ 130 PetscErrorCode DMPlexCreateRigidBody(DM dm, MatNullSpace *sp) 131 { 132 MPI_Comm comm; 133 Vec mode[6]; 134 PetscSection section, globalSection; 135 PetscInt dim, dimEmbed, n, m, d, i, j; 136 PetscErrorCode ierr; 137 138 PetscFunctionBegin; 139 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 140 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 141 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 142 if (dim == 1) { 143 ierr = MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, sp);CHKERRQ(ierr); 144 PetscFunctionReturn(0); 145 } 146 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 147 ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr); 148 ierr = PetscSectionGetConstrainedStorageSize(globalSection, &n);CHKERRQ(ierr); 149 m = (dim*(dim+1))/2; 150 ierr = VecCreate(comm, &mode[0]);CHKERRQ(ierr); 151 ierr = VecSetSizes(mode[0], n, PETSC_DETERMINE);CHKERRQ(ierr); 152 ierr = VecSetUp(mode[0]);CHKERRQ(ierr); 153 for (i = 1; i < m; ++i) {ierr = VecDuplicate(mode[0], &mode[i]);CHKERRQ(ierr);} 154 for (d = 0; d < m; d++) { 155 PetscInt ctx[2]; 156 void *voidctx = (void *) (&ctx[0]); 157 PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal *, PetscInt, PetscScalar *, void *) = DMPlexProjectRigidBody; 158 159 ctx[0] = dimEmbed; 160 ctx[1] = d; 161 ierr = DMProjectFunction(dm, 0.0, &func, &voidctx, INSERT_VALUES, mode[d]);CHKERRQ(ierr); 162 } 163 for (i = 0; i < dim; ++i) {ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr);} 164 /* Orthonormalize system */ 165 for (i = dim; i < m; ++i) { 166 PetscScalar dots[6]; 167 168 ierr = VecMDot(mode[i], i, mode, dots);CHKERRQ(ierr); 169 for (j = 0; j < i; ++j) dots[j] *= -1.0; 170 ierr = VecMAXPY(mode[i], i, dots, mode);CHKERRQ(ierr); 171 ierr = VecNormalize(mode[i], NULL);CHKERRQ(ierr); 172 } 173 ierr = MatNullSpaceCreate(comm, PETSC_FALSE, m, mode, sp);CHKERRQ(ierr); 174 for (i = 0; i< m; ++i) {ierr = VecDestroy(&mode[i]);CHKERRQ(ierr);} 175 PetscFunctionReturn(0); 176 } 177 178 #undef __FUNCT__ 179 #define __FUNCT__ "DMPlexSetMaxProjectionHeight" 180 /*@ 181 DMPlexSetMaxProjectionHeight - In DMPlexProjectXXXLocal() functions, the projected values of a basis function's dofs 182 are computed by associating the basis function with one of the mesh points in its transitively-closed support, and 183 evaluating the dual space basis of that point. A basis function is associated with the point in its 184 transitively-closed support whose mesh height is highest (w.r.t. DAG height), but not greater than the maximum 185 projection height, which is set with this function. By default, the maximum projection height is zero, which means 186 that only mesh cells are used to project basis functions. A height of one, for example, evaluates a cell-interior 187 basis functions using its cells dual space basis, but all other basis functions with the dual space basis of a face. 188 189 Input Parameters: 190 + dm - the DMPlex object 191 - height - the maximum projection height >= 0 192 193 Level: advanced 194 195 .seealso: DMPlexGetMaxProjectionHeight(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal() 196 @*/ 197 PetscErrorCode DMPlexSetMaxProjectionHeight(DM dm, PetscInt height) 198 { 199 DM_Plex *plex = (DM_Plex *) dm->data; 200 201 PetscFunctionBegin; 202 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 203 plex->maxProjectionHeight = height; 204 PetscFunctionReturn(0); 205 } 206 207 #undef __FUNCT__ 208 #define __FUNCT__ "DMPlexGetMaxProjectionHeight" 209 /*@ 210 DMPlexGetMaxProjectionHeight - Get the maximum height (w.r.t. DAG) of mesh points used to evaluate dual bases in 211 DMPlexProjectXXXLocal() functions. 212 213 Input Parameters: 214 . dm - the DMPlex object 215 216 Output Parameters: 217 . height - the maximum projection height 218 219 Level: intermediate 220 221 .seealso: DMPlexSetMaxProjectionHeight(), DMProjectFunctionLocal(), DMProjectFunctionLabelLocal() 222 @*/ 223 PetscErrorCode DMPlexGetMaxProjectionHeight(DM dm, PetscInt *height) 224 { 225 DM_Plex *plex = (DM_Plex *) dm->data; 226 227 PetscFunctionBegin; 228 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 229 *height = plex->maxProjectionHeight; 230 PetscFunctionReturn(0); 231 } 232 233 #undef __FUNCT__ 234 #define __FUNCT__ "DMProjectFunctionLabelLocal_Plex" 235 PetscErrorCode DMProjectFunctionLabelLocal_Plex(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 236 { 237 PetscDualSpace *sp, *cellsp; 238 PetscInt *numComp; 239 PetscSection section; 240 PetscScalar *values; 241 PetscBool *fieldActive; 242 PetscInt numFields, dim, dimEmbed, spDim, totDim = 0, numValues, pStart, pEnd, cStart, cEnd, cEndInterior, f, d, v, i, comp, maxHeight, h; 243 PetscErrorCode ierr; 244 245 PetscFunctionBegin; 246 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 247 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 248 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 249 if (cEnd <= cStart) PetscFunctionReturn(0); 250 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 251 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 252 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 253 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 254 ierr = PetscMalloc2(numFields,&sp,numFields,&numComp);CHKERRQ(ierr); 255 ierr = DMPlexGetMaxProjectionHeight(dm,&maxHeight);CHKERRQ(ierr); 256 if (maxHeight < 0 || maxHeight > dim) {SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"maximum projection height %d not in [0, %d)\n", maxHeight,dim);} 257 if (maxHeight > 0) {ierr = PetscMalloc1(numFields,&cellsp);CHKERRQ(ierr);} 258 else {cellsp = sp;} 259 for (h = 0; h <= maxHeight; h++) { 260 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 261 if (!h) {pStart = cStart; pEnd = cEnd;} 262 if (pEnd <= pStart) continue; 263 totDim = 0; 264 for (f = 0; f < numFields; ++f) { 265 PetscObject obj; 266 PetscClassId id; 267 268 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 269 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 270 if (id == PETSCFE_CLASSID) { 271 PetscFE fe = (PetscFE) obj; 272 273 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 274 if (!h) { 275 ierr = PetscFEGetDualSpace(fe, &cellsp[f]);CHKERRQ(ierr); 276 sp[f] = cellsp[f]; 277 ierr = PetscObjectReference((PetscObject) sp[f]);CHKERRQ(ierr); 278 } else { 279 ierr = PetscDualSpaceGetHeightSubspace(cellsp[f], h, &sp[f]);CHKERRQ(ierr); 280 if (!sp[f]) continue; 281 } 282 } else if (id == PETSCFV_CLASSID) { 283 PetscFV fv = (PetscFV) obj; 284 285 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 286 ierr = PetscFVGetDualSpace(fv, &sp[f]);CHKERRQ(ierr); 287 ierr = PetscObjectReference((PetscObject) sp[f]);CHKERRQ(ierr); 288 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 289 ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 290 totDim += spDim*numComp[f]; 291 } 292 ierr = DMPlexVecGetClosure(dm, section, localX, pStart, &numValues, NULL);CHKERRQ(ierr); 293 if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section point closure size %d != dual space dimension %d", numValues, totDim); 294 if (!totDim) continue; 295 ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 296 ierr = DMGetWorkArray(dm, numFields, PETSC_BOOL, &fieldActive);CHKERRQ(ierr); 297 for (f = 0; f < numFields; ++f) fieldActive[f] = (funcs[f] && sp[f]) ? PETSC_TRUE : PETSC_FALSE; 298 for (i = 0; i < numIds; ++i) { 299 IS pointIS; 300 const PetscInt *points; 301 PetscInt n, p; 302 303 ierr = DMLabelGetStratumIS(label, ids[i], &pointIS);CHKERRQ(ierr); 304 ierr = ISGetLocalSize(pointIS, &n);CHKERRQ(ierr); 305 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 306 for (p = 0; p < n; ++p) { 307 const PetscInt point = points[p]; 308 PetscFECellGeom geom; 309 310 if ((point < pStart) || (point >= pEnd)) continue; 311 ierr = DMPlexComputeCellGeometryFEM(dm, point, NULL, geom.v0, geom.J, NULL, &geom.detJ);CHKERRQ(ierr); 312 geom.dim = dim - h; 313 geom.dimEmbed = dimEmbed; 314 for (f = 0, v = 0; f < numFields; ++f) { 315 void * const ctx = ctxs ? ctxs[f] : NULL; 316 317 if (!sp[f]) continue; 318 ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 319 for (d = 0; d < spDim; ++d) { 320 if (funcs[f]) { 321 ierr = PetscDualSpaceApply(sp[f], d, time, &geom, numComp[f], funcs[f], ctx, &values[v]);CHKERRQ(ierr); 322 } else { 323 for (comp = 0; comp < numComp[f]; ++comp) values[v+comp] = 0.0; 324 } 325 v += numComp[f]; 326 } 327 } 328 ierr = DMPlexVecSetFieldClosure_Internal(dm, section, localX, fieldActive, point, values, mode);CHKERRQ(ierr); 329 } 330 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 331 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 332 } 333 if (h) { 334 for (f = 0; f < numFields; ++f) {ierr = PetscDualSpaceDestroy(&sp[f]);CHKERRQ(ierr);} 335 } 336 } 337 ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 338 ierr = DMRestoreWorkArray(dm, numFields, PETSC_BOOL, &fieldActive);CHKERRQ(ierr); 339 for (f = 0; f < numFields; ++f) {ierr = PetscDualSpaceDestroy(&sp[f]);CHKERRQ(ierr);} 340 ierr = PetscFree2(sp, numComp);CHKERRQ(ierr); 341 if (maxHeight > 0) { 342 ierr = PetscFree(cellsp);CHKERRQ(ierr); 343 } 344 PetscFunctionReturn(0); 345 } 346 347 #undef __FUNCT__ 348 #define __FUNCT__ "DMProjectFunctionLocal_Plex" 349 PetscErrorCode DMProjectFunctionLocal_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 350 { 351 PetscDualSpace *sp, *cellsp; 352 PetscInt *numComp; 353 PetscSection section; 354 PetscScalar *values; 355 PetscInt Nf, dim, dimEmbed, spDim, totDim = 0, numValues, pStart, pEnd, p, cStart, cEnd, cEndInterior, f, d, v, comp, h, maxHeight; 356 PetscBool *isFE, hasFE = PETSC_FALSE, hasFV = PETSC_FALSE; 357 PetscErrorCode ierr; 358 359 PetscFunctionBegin; 360 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 361 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 362 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 363 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 364 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 365 ierr = PetscMalloc3(Nf, &isFE, Nf, &sp, Nf, &numComp);CHKERRQ(ierr); 366 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 367 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 368 ierr = DMPlexGetMaxProjectionHeight(dm,&maxHeight);CHKERRQ(ierr); 369 if (maxHeight < 0 || maxHeight > dim) {SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_USER,"maximum projection height %d not in [0, %d)\n", maxHeight,dim);} 370 if (maxHeight > 0) { 371 ierr = PetscMalloc1(Nf,&cellsp);CHKERRQ(ierr); 372 } 373 else { 374 cellsp = sp; 375 } 376 for (f = 0; f < Nf; ++f) { 377 PetscObject obj; 378 PetscClassId id; 379 380 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 381 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 382 if (id == PETSCFE_CLASSID) { 383 PetscFE fe = (PetscFE) obj; 384 385 hasFE = PETSC_TRUE; 386 isFE[f] = PETSC_TRUE; 387 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 388 ierr = PetscFEGetDualSpace(fe, &cellsp[f]);CHKERRQ(ierr); 389 } else if (id == PETSCFV_CLASSID) { 390 PetscFV fv = (PetscFV) obj; 391 392 hasFV = PETSC_TRUE; 393 isFE[f] = PETSC_FALSE; 394 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 395 ierr = PetscFVGetDualSpace(fv, &cellsp[f]);CHKERRQ(ierr); 396 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 397 } 398 for (h = 0; h <= maxHeight; h++) { 399 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 400 if (!h) {pStart = cStart; pEnd = cEnd;} 401 if (pEnd <= pStart) continue; 402 totDim = 0; 403 for (f = 0; f < Nf; ++f) { 404 if (!h) { 405 sp[f] = cellsp[f]; 406 } 407 else { 408 ierr = PetscDualSpaceGetHeightSubspace(cellsp[f], h, &sp[f]);CHKERRQ(ierr); 409 if (!sp[f]) { 410 continue; 411 } 412 } 413 ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 414 totDim += spDim*numComp[f]; 415 } 416 ierr = DMPlexVecGetClosure(dm, section, localX, pStart, &numValues, NULL);CHKERRQ(ierr); 417 if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section point closure size %d != dual space dimension %d", numValues, totDim); 418 if (!totDim) continue; 419 ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 420 for (p = pStart; p < pEnd; ++p) { 421 PetscFECellGeom fegeom; 422 PetscFVCellGeom fvgeom; 423 424 if (hasFE) { 425 ierr = DMPlexComputeCellGeometryFEM(dm, p, NULL, fegeom.v0, fegeom.J, NULL, &fegeom.detJ);CHKERRQ(ierr); 426 fegeom.dim = dim - h; 427 fegeom.dimEmbed = dimEmbed; 428 } 429 if (hasFV) {ierr = DMPlexComputeCellGeometryFVM(dm, p, &fvgeom.volume, fvgeom.centroid, NULL);CHKERRQ(ierr);} 430 for (f = 0, v = 0; f < Nf; ++f) { 431 void * const ctx = ctxs ? ctxs[f] : NULL; 432 433 if (!sp[f]) continue; 434 ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 435 for (d = 0; d < spDim; ++d) { 436 if (funcs[f]) { 437 if (isFE[f]) {ierr = PetscDualSpaceApply(sp[f], d, time, &fegeom, numComp[f], funcs[f], ctx, &values[v]);CHKERRQ(ierr);} 438 else {ierr = PetscDualSpaceApplyFVM(sp[f], d, time, &fvgeom, numComp[f], funcs[f], ctx, &values[v]);CHKERRQ(ierr);} 439 } else { 440 for (comp = 0; comp < numComp[f]; ++comp) values[v+comp] = 0.0; 441 } 442 v += numComp[f]; 443 } 444 } 445 ierr = DMPlexVecSetClosure(dm, section, localX, p, values, mode);CHKERRQ(ierr); 446 } 447 ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 448 if (h) { 449 for (f = 0; f < Nf; f++) {ierr = PetscDualSpaceDestroy(&sp[f]);CHKERRQ(ierr);} 450 } 451 } 452 ierr = PetscFree3(isFE, sp, numComp);CHKERRQ(ierr); 453 if (maxHeight > 0) { 454 ierr = PetscFree(cellsp);CHKERRQ(ierr); 455 } 456 PetscFunctionReturn(0); 457 } 458 459 #undef __FUNCT__ 460 #define __FUNCT__ "DMProjectFieldLocal_Plex" 461 PetscErrorCode DMProjectFieldLocal_Plex(DM dm, Vec localU, 462 void (**funcs)(PetscInt, PetscInt, PetscInt, 463 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 464 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 465 PetscReal, const PetscReal[], PetscScalar[]), 466 InsertMode mode, Vec localX) 467 { 468 DM dmAux; 469 PetscDS prob, probAux = NULL; 470 Vec A; 471 PetscSection section, sectionAux = NULL; 472 PetscDualSpace *sp; 473 PetscInt *Ncf; 474 PetscScalar *values, *u, *u_x, *a, *a_x; 475 PetscReal *x, *v0, *J, *invJ, detJ; 476 PetscInt *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL; 477 PetscInt Nf, NfAux = 0, dim, spDim, totDim, numValues, cStart, cEnd, cEndInterior, c, f, d, v, comp, maxHeight; 478 PetscErrorCode ierr; 479 480 PetscFunctionBegin; 481 ierr = DMPlexGetMaxProjectionHeight(dm,&maxHeight);CHKERRQ(ierr); 482 if (maxHeight > 0) {SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Field projection for height > 0 not supported yet");} 483 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 484 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 485 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 486 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 487 ierr = PetscMalloc2(Nf, &sp, Nf, &Ncf);CHKERRQ(ierr); 488 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 489 ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 490 ierr = PetscDSGetComponentOffsets(prob, &uOff);CHKERRQ(ierr); 491 ierr = PetscDSGetComponentDerivativeOffsets(prob, &uOff_x);CHKERRQ(ierr); 492 ierr = PetscDSGetEvaluationArrays(prob, &u, NULL, &u_x);CHKERRQ(ierr); 493 ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr); 494 ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 495 ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 496 if (dmAux) { 497 ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 498 ierr = PetscDSGetNumFields(probAux, &NfAux);CHKERRQ(ierr); 499 ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 500 ierr = PetscDSGetComponentOffsets(probAux, &aOff);CHKERRQ(ierr); 501 ierr = PetscDSGetComponentDerivativeOffsets(probAux, &aOff_x);CHKERRQ(ierr); 502 ierr = PetscDSGetEvaluationArrays(probAux, &a, NULL, &a_x);CHKERRQ(ierr); 503 } 504 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, localU, 0.0, NULL, NULL, NULL);CHKERRQ(ierr); 505 ierr = DMPlexVecGetClosure(dm, section, localX, cStart, &numValues, NULL);CHKERRQ(ierr); 506 if (numValues != totDim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "The section cell closure size %d != dual space dimension %d", numValues, totDim); 507 ierr = DMGetWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 508 ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 509 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 510 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 511 for (c = cStart; c < cEnd; ++c) { 512 PetscScalar *coefficients = NULL, *coefficientsAux = NULL; 513 514 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 515 ierr = DMPlexVecGetClosure(dm, section, localU, c, NULL, &coefficients);CHKERRQ(ierr); 516 if (dmAux) {ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &coefficientsAux);CHKERRQ(ierr);} 517 for (f = 0, v = 0; f < Nf; ++f) { 518 PetscObject obj; 519 PetscClassId id; 520 521 ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 522 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 523 if (id == PETSCFE_CLASSID) { 524 PetscFE fe = (PetscFE) obj; 525 526 ierr = PetscFEGetDualSpace(fe, &sp[f]);CHKERRQ(ierr); 527 ierr = PetscFEGetNumComponents(fe, &Ncf[f]);CHKERRQ(ierr); 528 } else if (id == PETSCFV_CLASSID) { 529 PetscFV fv = (PetscFV) obj; 530 531 ierr = PetscFVGetNumComponents(fv, &Ncf[f]);CHKERRQ(ierr); 532 ierr = PetscObjectReference((PetscObject) sp[f]);CHKERRQ(ierr); 533 } 534 ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 535 for (d = 0; d < spDim; ++d) { 536 PetscQuadrature quad; 537 const PetscReal *points, *weights; 538 PetscInt numPoints, q; 539 540 if (funcs[f]) { 541 ierr = PetscDualSpaceGetFunctional(sp[f], d, &quad);CHKERRQ(ierr); 542 ierr = PetscQuadratureGetData(quad, NULL, &numPoints, &points, &weights);CHKERRQ(ierr); 543 for (q = 0; q < numPoints; ++q) { 544 CoordinatesRefToReal(dim, dim, v0, J, &points[q*dim], x); 545 ierr = EvaluateFieldJets(prob, PETSC_FALSE, q, invJ, coefficients, NULL, u, u_x, NULL);CHKERRQ(ierr); 546 ierr = EvaluateFieldJets(probAux, PETSC_FALSE, q, invJ, coefficientsAux, NULL, a, a_x, NULL);CHKERRQ(ierr); 547 (*funcs[f])(dim, Nf, NfAux, uOff, uOff_x, u, NULL, u_x, aOff, aOff_x, a, NULL, a_x, 0.0, x, &values[v]); 548 } 549 } else { 550 for (comp = 0; comp < Ncf[f]; ++comp) values[v+comp] = 0.0; 551 } 552 v += Ncf[f]; 553 } 554 } 555 ierr = DMPlexVecRestoreClosure(dm, section, localU, c, NULL, &coefficients);CHKERRQ(ierr); 556 if (dmAux) {ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &coefficientsAux);CHKERRQ(ierr);} 557 ierr = DMPlexVecSetClosure(dm, section, localX, c, values, mode);CHKERRQ(ierr); 558 } 559 ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr); 560 ierr = DMRestoreWorkArray(dm, numValues, PETSC_SCALAR, &values);CHKERRQ(ierr); 561 ierr = PetscFree2(sp, Ncf);CHKERRQ(ierr); 562 PetscFunctionReturn(0); 563 } 564 565 #undef __FUNCT__ 566 #define __FUNCT__ "DMPlexInsertBoundaryValues_FEM_Internal" 567 static PetscErrorCode DMPlexInsertBoundaryValues_FEM_Internal(DM dm, PetscReal time, PetscInt field, DMLabel label, PetscInt numids, const PetscInt ids[], PetscErrorCode (*func)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *), void *ctx, Vec locX) 568 { 569 PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal x[], PetscInt, PetscScalar *u, void *ctx); 570 void **ctxs; 571 PetscInt numFields; 572 PetscErrorCode ierr; 573 574 PetscFunctionBegin; 575 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 576 ierr = PetscCalloc2(numFields,&funcs,numFields,&ctxs);CHKERRQ(ierr); 577 funcs[field] = func; 578 ctxs[field] = ctx; 579 ierr = DMProjectFunctionLabelLocal(dm, time, label, numids, ids, funcs, ctxs, INSERT_BC_VALUES, locX);CHKERRQ(ierr); 580 ierr = PetscFree2(funcs,ctxs);CHKERRQ(ierr); 581 PetscFunctionReturn(0); 582 } 583 584 #undef __FUNCT__ 585 #define __FUNCT__ "DMPlexInsertBoundaryValues_FVM_Internal" 586 /* This ignores numcomps/comps */ 587 static PetscErrorCode DMPlexInsertBoundaryValues_FVM_Internal(DM dm, PetscReal time, Vec faceGeometry, Vec cellGeometry, Vec Grad, 588 PetscInt field, DMLabel label, PetscInt numids, const PetscInt ids[], PetscErrorCode (*func)(PetscReal,const PetscReal*,const PetscReal*,const PetscScalar*,PetscScalar*,void*), void *ctx, Vec locX) 589 { 590 PetscDS prob; 591 PetscSF sf; 592 DM dmFace, dmCell, dmGrad; 593 const PetscScalar *facegeom, *cellgeom = NULL, *grad; 594 const PetscInt *leaves; 595 PetscScalar *x, *fx; 596 PetscInt dim, nleaves, loc, fStart, fEnd, pdim, i; 597 PetscErrorCode ierr; 598 599 PetscFunctionBegin; 600 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 601 ierr = PetscSFGetGraph(sf, NULL, &nleaves, &leaves, NULL);CHKERRQ(ierr); 602 nleaves = PetscMax(0, nleaves); 603 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 604 ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 605 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 606 ierr = VecGetDM(faceGeometry, &dmFace);CHKERRQ(ierr); 607 ierr = VecGetArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); 608 if (cellGeometry) { 609 ierr = VecGetDM(cellGeometry, &dmCell);CHKERRQ(ierr); 610 ierr = VecGetArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); 611 } 612 if (Grad) { 613 PetscFV fv; 614 615 ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fv);CHKERRQ(ierr); 616 ierr = VecGetDM(Grad, &dmGrad);CHKERRQ(ierr); 617 ierr = VecGetArrayRead(Grad, &grad);CHKERRQ(ierr); 618 ierr = PetscFVGetNumComponents(fv, &pdim);CHKERRQ(ierr); 619 ierr = DMGetWorkArray(dm, pdim, PETSC_SCALAR, &fx);CHKERRQ(ierr); 620 } 621 ierr = VecGetArray(locX, &x);CHKERRQ(ierr); 622 for (i = 0; i < numids; ++i) { 623 IS faceIS; 624 const PetscInt *faces; 625 PetscInt numFaces, f; 626 627 ierr = DMLabelGetStratumIS(label, ids[i], &faceIS);CHKERRQ(ierr); 628 if (!faceIS) continue; /* No points with that id on this process */ 629 ierr = ISGetLocalSize(faceIS, &numFaces);CHKERRQ(ierr); 630 ierr = ISGetIndices(faceIS, &faces);CHKERRQ(ierr); 631 for (f = 0; f < numFaces; ++f) { 632 const PetscInt face = faces[f], *cells; 633 PetscFVFaceGeom *fg; 634 635 if ((face < fStart) || (face >= fEnd)) continue; /* Refinement adds non-faces to labels */ 636 ierr = PetscFindInt(face, nleaves, (PetscInt *) leaves, &loc);CHKERRQ(ierr); 637 if (loc >= 0) continue; 638 ierr = DMPlexPointLocalRead(dmFace, face, facegeom, &fg);CHKERRQ(ierr); 639 ierr = DMPlexGetSupport(dm, face, &cells);CHKERRQ(ierr); 640 if (Grad) { 641 PetscFVCellGeom *cg; 642 PetscScalar *cx, *cgrad; 643 PetscScalar *xG; 644 PetscReal dx[3]; 645 PetscInt d; 646 647 ierr = DMPlexPointLocalRead(dmCell, cells[0], cellgeom, &cg);CHKERRQ(ierr); 648 ierr = DMPlexPointLocalRead(dm, cells[0], x, &cx);CHKERRQ(ierr); 649 ierr = DMPlexPointLocalRead(dmGrad, cells[0], grad, &cgrad);CHKERRQ(ierr); 650 ierr = DMPlexPointLocalFieldRef(dm, cells[1], field, x, &xG);CHKERRQ(ierr); 651 DMPlex_WaxpyD_Internal(dim, -1, cg->centroid, fg->centroid, dx); 652 for (d = 0; d < pdim; ++d) fx[d] = cx[d] + DMPlex_DotD_Internal(dim, &cgrad[d*dim], dx); 653 ierr = (*func)(time, fg->centroid, fg->normal, fx, xG, ctx);CHKERRQ(ierr); 654 } else { 655 PetscScalar *xI; 656 PetscScalar *xG; 657 658 ierr = DMPlexPointLocalRead(dm, cells[0], x, &xI);CHKERRQ(ierr); 659 ierr = DMPlexPointLocalFieldRef(dm, cells[1], field, x, &xG);CHKERRQ(ierr); 660 ierr = (*func)(time, fg->centroid, fg->normal, xI, xG, ctx);CHKERRQ(ierr); 661 } 662 } 663 ierr = ISRestoreIndices(faceIS, &faces);CHKERRQ(ierr); 664 ierr = ISDestroy(&faceIS);CHKERRQ(ierr); 665 } 666 ierr = VecRestoreArray(locX, &x);CHKERRQ(ierr); 667 if (Grad) { 668 ierr = DMRestoreWorkArray(dm, pdim, PETSC_SCALAR, &fx);CHKERRQ(ierr); 669 ierr = VecRestoreArrayRead(Grad, &grad);CHKERRQ(ierr); 670 } 671 if (cellGeometry) { 672 ierr = VecRestoreArrayRead(cellGeometry, &cellgeom);CHKERRQ(ierr); 673 } 674 ierr = VecRestoreArrayRead(faceGeometry, &facegeom);CHKERRQ(ierr); 675 PetscFunctionReturn(0); 676 } 677 678 #undef __FUNCT__ 679 #define __FUNCT__ "DMPlexInsertBoundaryValues" 680 PetscErrorCode DMPlexInsertBoundaryValues(DM dm, PetscBool insertEssential, Vec locX, PetscReal time, Vec faceGeomFVM, Vec cellGeomFVM, Vec gradFVM) 681 { 682 PetscInt numBd, b; 683 PetscErrorCode ierr; 684 685 PetscFunctionBegin; 686 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 687 PetscValidHeaderSpecific(locX, VEC_CLASSID, 2); 688 if (faceGeomFVM) {PetscValidHeaderSpecific(faceGeomFVM, VEC_CLASSID, 4);} 689 if (cellGeomFVM) {PetscValidHeaderSpecific(cellGeomFVM, VEC_CLASSID, 5);} 690 if (gradFVM) {PetscValidHeaderSpecific(gradFVM, VEC_CLASSID, 6);} 691 ierr = DMGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 692 for (b = 0; b < numBd; ++b) { 693 PetscBool isEssential; 694 const char *labelname; 695 DMLabel label; 696 PetscInt field; 697 PetscObject obj; 698 PetscClassId id; 699 void (*func)(); 700 PetscInt numids; 701 const PetscInt *ids; 702 void *ctx; 703 704 ierr = DMGetBoundary(dm, b, &isEssential, NULL, &labelname, &field, NULL, NULL, &func, &numids, &ids, &ctx);CHKERRQ(ierr); 705 if (insertEssential != isEssential) continue; 706 ierr = DMGetLabel(dm, labelname, &label);CHKERRQ(ierr); 707 ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 708 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 709 if (id == PETSCFE_CLASSID) { 710 if (!isEssential) continue; /* for FEM, there is no insertion to be done for non-essential boundary conditions */ 711 ierr = DMPlexLabelAddCells(dm,label);CHKERRQ(ierr); 712 ierr = DMPlexInsertBoundaryValues_FEM_Internal(dm, time, field, label, numids, ids, (PetscErrorCode (*)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *)) func, ctx, locX);CHKERRQ(ierr); 713 ierr = DMPlexLabelClearCells(dm,label);CHKERRQ(ierr); 714 } else if (id == PETSCFV_CLASSID) { 715 if (!faceGeomFVM) continue; 716 ierr = DMPlexInsertBoundaryValues_FVM_Internal(dm, time, faceGeomFVM, cellGeomFVM, gradFVM, 717 field, label, numids, ids, (PetscErrorCode (*)(PetscReal,const PetscReal*,const PetscReal*,const PetscScalar*,PetscScalar*,void*)) func, ctx, locX);CHKERRQ(ierr); 718 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 719 } 720 PetscFunctionReturn(0); 721 } 722 723 #undef __FUNCT__ 724 #define __FUNCT__ "DMComputeL2Diff_Plex" 725 PetscErrorCode DMComputeL2Diff_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 726 { 727 const PetscInt debug = 0; 728 PetscSection section; 729 PetscQuadrature quad; 730 Vec localX; 731 PetscScalar *funcVal, *interpolant; 732 PetscReal *coords, *v0, *J, *invJ, detJ; 733 PetscReal localDiff = 0.0; 734 const PetscReal *quadPoints, *quadWeights; 735 PetscInt dim, numFields, numComponents = 0, numQuadPoints, cStart, cEnd, cEndInterior, c, field, fieldOffset; 736 PetscErrorCode ierr; 737 738 PetscFunctionBegin; 739 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 740 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 741 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 742 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 743 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 744 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 745 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 746 for (field = 0; field < numFields; ++field) { 747 PetscObject obj; 748 PetscClassId id; 749 PetscInt Nc; 750 751 ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 752 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 753 if (id == PETSCFE_CLASSID) { 754 PetscFE fe = (PetscFE) obj; 755 756 ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 757 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 758 } else if (id == PETSCFV_CLASSID) { 759 PetscFV fv = (PetscFV) obj; 760 761 ierr = PetscFVGetQuadrature(fv, &quad);CHKERRQ(ierr); 762 ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 763 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 764 numComponents += Nc; 765 } 766 ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 767 ierr = PetscMalloc6(numComponents,&funcVal,numComponents,&interpolant,dim,&coords,dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 768 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 769 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 770 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 771 for (c = cStart; c < cEnd; ++c) { 772 PetscScalar *x = NULL; 773 PetscReal elemDiff = 0.0; 774 775 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 776 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 777 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 778 779 for (field = 0, fieldOffset = 0; field < numFields; ++field) { 780 PetscObject obj; 781 PetscClassId id; 782 void * const ctx = ctxs ? ctxs[field] : NULL; 783 PetscInt Nb, Nc, q, fc; 784 785 ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 786 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 787 if (id == PETSCFE_CLASSID) {ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);ierr = PetscFEGetDimension((PetscFE) obj, &Nb);CHKERRQ(ierr);} 788 else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);Nb = 1;} 789 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 790 if (debug) { 791 char title[1024]; 792 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 793 ierr = DMPrintCellVector(c, title, Nb*Nc, &x[fieldOffset]);CHKERRQ(ierr); 794 } 795 for (q = 0; q < numQuadPoints; ++q) { 796 CoordinatesRefToReal(dim, dim, v0, J, &quadPoints[q*dim], coords); 797 ierr = (*funcs[field])(dim, time, coords, Nc, funcVal, ctx);CHKERRQ(ierr); 798 if (id == PETSCFE_CLASSID) {ierr = PetscFEInterpolate_Static((PetscFE) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 799 else if (id == PETSCFV_CLASSID) {ierr = PetscFVInterpolate_Static((PetscFV) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 800 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 801 for (fc = 0; fc < Nc; ++fc) { 802 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);} 803 elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*quadWeights[q]*detJ; 804 } 805 } 806 fieldOffset += Nb*Nc; 807 } 808 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 809 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 810 localDiff += elemDiff; 811 } 812 ierr = PetscFree6(funcVal,interpolant,coords,v0,J,invJ);CHKERRQ(ierr); 813 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 814 ierr = MPIU_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 815 *diff = PetscSqrtReal(*diff); 816 PetscFunctionReturn(0); 817 } 818 819 #undef __FUNCT__ 820 #define __FUNCT__ "DMComputeL2GradientDiff_Plex" 821 PetscErrorCode DMComputeL2GradientDiff_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, const PetscReal n[], PetscReal *diff) 822 { 823 const PetscInt debug = 0; 824 PetscSection section; 825 PetscQuadrature quad; 826 Vec localX; 827 PetscScalar *funcVal, *interpolantVec; 828 PetscReal *coords, *realSpaceDer, *v0, *J, *invJ, detJ; 829 PetscReal localDiff = 0.0; 830 PetscInt dim, numFields, numComponents = 0, cStart, cEnd, cEndInterior, c, field, fieldOffset, comp; 831 PetscErrorCode ierr; 832 833 PetscFunctionBegin; 834 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 835 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 836 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 837 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 838 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 839 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 840 for (field = 0; field < numFields; ++field) { 841 PetscFE fe; 842 PetscInt Nc; 843 844 ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 845 ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 846 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 847 numComponents += Nc; 848 } 849 /* ierr = DMProjectFunctionLocal(dm, fe, funcs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); */ 850 ierr = PetscMalloc7(numComponents,&funcVal,dim,&coords,dim,&realSpaceDer,dim,&v0,dim*dim,&J,dim*dim,&invJ,dim,&interpolantVec);CHKERRQ(ierr); 851 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 852 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 853 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 854 for (c = cStart; c < cEnd; ++c) { 855 PetscScalar *x = NULL; 856 PetscReal elemDiff = 0.0; 857 858 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 859 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 860 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 861 862 for (field = 0, comp = 0, fieldOffset = 0; field < numFields; ++field) { 863 PetscFE fe; 864 void * const ctx = ctxs ? ctxs[field] : NULL; 865 const PetscReal *quadPoints, *quadWeights; 866 PetscReal *basisDer; 867 PetscInt numQuadPoints, Nb, Ncomp, q, d, e, fc, f, g; 868 869 ierr = DMGetField(dm, field, (PetscObject *) &fe);CHKERRQ(ierr); 870 ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 871 ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 872 ierr = PetscFEGetNumComponents(fe, &Ncomp);CHKERRQ(ierr); 873 ierr = PetscFEGetDefaultTabulation(fe, NULL, &basisDer, NULL);CHKERRQ(ierr); 874 if (debug) { 875 char title[1024]; 876 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 877 ierr = DMPrintCellVector(c, title, Nb*Ncomp, &x[fieldOffset]);CHKERRQ(ierr); 878 } 879 for (q = 0; q < numQuadPoints; ++q) { 880 for (d = 0; d < dim; d++) { 881 coords[d] = v0[d]; 882 for (e = 0; e < dim; e++) { 883 coords[d] += J[d*dim+e]*(quadPoints[q*dim+e] + 1.0); 884 } 885 } 886 ierr = (*funcs[field])(dim, time, coords, n, numFields, funcVal, ctx);CHKERRQ(ierr); 887 for (fc = 0; fc < Ncomp; ++fc) { 888 PetscScalar interpolant = 0.0; 889 890 for (d = 0; d < dim; ++d) interpolantVec[d] = 0.0; 891 for (f = 0; f < Nb; ++f) { 892 const PetscInt fidx = f*Ncomp+fc; 893 894 for (d = 0; d < dim; ++d) { 895 realSpaceDer[d] = 0.0; 896 for (g = 0; g < dim; ++g) { 897 realSpaceDer[d] += invJ[g*dim+d]*basisDer[(q*Nb*Ncomp+fidx)*dim+g]; 898 } 899 interpolantVec[d] += x[fieldOffset+fidx]*realSpaceDer[d]; 900 } 901 } 902 for (d = 0; d < dim; ++d) interpolant += interpolantVec[d]*n[d]; 903 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);} 904 elemDiff += PetscSqr(PetscRealPart(interpolant - funcVal[fc]))*quadWeights[q]*detJ; 905 } 906 } 907 comp += Ncomp; 908 fieldOffset += Nb*Ncomp; 909 } 910 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 911 if (debug) {ierr = PetscPrintf(PETSC_COMM_SELF, " elem %d diff %g\n", c, elemDiff);CHKERRQ(ierr);} 912 localDiff += elemDiff; 913 } 914 ierr = PetscFree7(funcVal,coords,realSpaceDer,v0,J,invJ,interpolantVec);CHKERRQ(ierr); 915 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 916 ierr = MPIU_Allreduce(&localDiff, diff, 1, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 917 *diff = PetscSqrtReal(*diff); 918 PetscFunctionReturn(0); 919 } 920 921 #undef __FUNCT__ 922 #define __FUNCT__ "DMComputeL2FieldDiff_Plex" 923 PetscErrorCode DMComputeL2FieldDiff_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, PetscReal *diff) 924 { 925 const PetscInt debug = 0; 926 PetscSection section; 927 PetscQuadrature quad; 928 Vec localX; 929 PetscScalar *funcVal, *interpolant; 930 PetscReal *coords, *v0, *J, *invJ, detJ; 931 PetscReal *localDiff; 932 const PetscReal *quadPoints, *quadWeights; 933 PetscInt dim, numFields, numComponents = 0, numQuadPoints, cStart, cEnd, cEndInterior, c, field, fieldOffset; 934 PetscErrorCode ierr; 935 936 PetscFunctionBegin; 937 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 938 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 939 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 940 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 941 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 942 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 943 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 944 for (field = 0; field < numFields; ++field) { 945 PetscObject obj; 946 PetscClassId id; 947 PetscInt Nc; 948 949 ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 950 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 951 if (id == PETSCFE_CLASSID) { 952 PetscFE fe = (PetscFE) obj; 953 954 ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 955 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 956 } else if (id == PETSCFV_CLASSID) { 957 PetscFV fv = (PetscFV) obj; 958 959 ierr = PetscFVGetQuadrature(fv, &quad);CHKERRQ(ierr); 960 ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 961 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 962 numComponents += Nc; 963 } 964 ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 965 ierr = PetscCalloc7(numFields,&localDiff,numComponents,&funcVal,numComponents,&interpolant,dim,&coords,dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 966 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 967 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 968 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 969 for (c = cStart; c < cEnd; ++c) { 970 PetscScalar *x = NULL; 971 972 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 973 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 974 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 975 976 for (field = 0, fieldOffset = 0; field < numFields; ++field) { 977 PetscObject obj; 978 PetscClassId id; 979 void * const ctx = ctxs ? ctxs[field] : NULL; 980 PetscInt Nb, Nc, q, fc; 981 982 PetscReal elemDiff = 0.0; 983 984 ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 985 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 986 if (id == PETSCFE_CLASSID) {ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);ierr = PetscFEGetDimension((PetscFE) obj, &Nb);CHKERRQ(ierr);} 987 else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);Nb = 1;} 988 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 989 if (debug) { 990 char title[1024]; 991 ierr = PetscSNPrintf(title, 1023, "Solution for Field %d", field);CHKERRQ(ierr); 992 ierr = DMPrintCellVector(c, title, Nb*Nc, &x[fieldOffset]);CHKERRQ(ierr); 993 } 994 for (q = 0; q < numQuadPoints; ++q) { 995 CoordinatesRefToReal(dim, dim, v0, J, &quadPoints[q*dim], coords); 996 ierr = (*funcs[field])(dim, time, coords, numFields, funcVal, ctx);CHKERRQ(ierr); 997 if (id == PETSCFE_CLASSID) {ierr = PetscFEInterpolate_Static((PetscFE) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 998 else if (id == PETSCFV_CLASSID) {ierr = PetscFVInterpolate_Static((PetscFV) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 999 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 1000 for (fc = 0; fc < Nc; ++fc) { 1001 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);} 1002 elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*quadWeights[q]*detJ; 1003 } 1004 } 1005 fieldOffset += Nb*Nc; 1006 localDiff[field] += elemDiff; 1007 } 1008 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 1009 } 1010 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 1011 ierr = MPIU_Allreduce(localDiff, diff, numFields, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 1012 for (field = 0; field < numFields; ++field) diff[field] = PetscSqrtReal(diff[field]); 1013 ierr = PetscFree7(localDiff,funcVal,interpolant,coords,v0,J,invJ);CHKERRQ(ierr); 1014 PetscFunctionReturn(0); 1015 } 1016 1017 #undef __FUNCT__ 1018 #define __FUNCT__ "DMPlexComputeL2DiffVec" 1019 /*@C 1020 DMPlexComputeL2DiffVec - This function computes the cellwise L_2 difference between a function u and an FEM interpolant solution u_h, and stores it in a Vec. 1021 1022 Input Parameters: 1023 + dm - The DM 1024 . time - The time 1025 . funcs - The functions to evaluate for each field component: NULL means that component does not contribute to error calculation 1026 . ctxs - Optional array of contexts to pass to each function, or NULL. 1027 - X - The coefficient vector u_h 1028 1029 Output Parameter: 1030 . D - A Vec which holds the difference ||u - u_h||_2 for each cell 1031 1032 Level: developer 1033 1034 .seealso: DMProjectFunction(), DMComputeL2Diff(), DMPlexComputeL2FieldDiff(), DMComputeL2GradientDiff() 1035 @*/ 1036 PetscErrorCode DMPlexComputeL2DiffVec(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, Vec X, Vec D) 1037 { 1038 PetscSection section; 1039 PetscQuadrature quad; 1040 Vec localX; 1041 PetscScalar *funcVal, *interpolant; 1042 PetscReal *coords, *v0, *J, *invJ, detJ; 1043 const PetscReal *quadPoints, *quadWeights; 1044 PetscInt dim, numFields, numComponents = 0, numQuadPoints, cStart, cEnd, cEndInterior, c, field, fieldOffset; 1045 PetscErrorCode ierr; 1046 1047 PetscFunctionBegin; 1048 ierr = VecSet(D, 0.0);CHKERRQ(ierr); 1049 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1050 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1051 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 1052 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 1053 ierr = DMProjectFunctionLocal(dm, time, funcs, ctxs, INSERT_BC_VALUES, localX);CHKERRQ(ierr); 1054 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 1055 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 1056 for (field = 0; field < numFields; ++field) { 1057 PetscObject obj; 1058 PetscClassId id; 1059 PetscInt Nc; 1060 1061 ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 1062 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1063 if (id == PETSCFE_CLASSID) { 1064 PetscFE fe = (PetscFE) obj; 1065 1066 ierr = PetscFEGetQuadrature(fe, &quad);CHKERRQ(ierr); 1067 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 1068 } else if (id == PETSCFV_CLASSID) { 1069 PetscFV fv = (PetscFV) obj; 1070 1071 ierr = PetscFVGetQuadrature(fv, &quad);CHKERRQ(ierr); 1072 ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 1073 } else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 1074 numComponents += Nc; 1075 } 1076 ierr = PetscQuadratureGetData(quad, NULL, &numQuadPoints, &quadPoints, &quadWeights);CHKERRQ(ierr); 1077 ierr = PetscMalloc6(numComponents,&funcVal,numComponents,&interpolant,dim,&coords,dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 1078 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1079 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 1080 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 1081 for (c = cStart; c < cEnd; ++c) { 1082 PetscScalar *x = NULL; 1083 PetscScalar elemDiff = 0.0; 1084 1085 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 1086 if (detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ, c); 1087 ierr = DMPlexVecGetClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 1088 1089 for (field = 0, fieldOffset = 0; field < numFields; ++field) { 1090 PetscObject obj; 1091 PetscClassId id; 1092 void * const ctx = ctxs ? ctxs[field] : NULL; 1093 PetscInt Nb, Nc, q, fc; 1094 1095 ierr = DMGetField(dm, field, &obj);CHKERRQ(ierr); 1096 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1097 if (id == PETSCFE_CLASSID) {ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);ierr = PetscFEGetDimension((PetscFE) obj, &Nb);CHKERRQ(ierr);} 1098 else if (id == PETSCFV_CLASSID) {ierr = PetscFVGetNumComponents((PetscFV) obj, &Nc);CHKERRQ(ierr);Nb = 1;} 1099 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 1100 if (funcs[field]) { 1101 for (q = 0; q < numQuadPoints; ++q) { 1102 CoordinatesRefToReal(dim, dim, v0, J, &quadPoints[q*dim], coords); 1103 ierr = (*funcs[field])(dim, time, coords, Nc, funcVal, ctx);CHKERRQ(ierr); 1104 if (id == PETSCFE_CLASSID) {ierr = PetscFEInterpolate_Static((PetscFE) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 1105 else if (id == PETSCFV_CLASSID) {ierr = PetscFVInterpolate_Static((PetscFV) obj, &x[fieldOffset], q, interpolant);CHKERRQ(ierr);} 1106 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", field); 1107 for (fc = 0; fc < Nc; ++fc) { 1108 elemDiff += PetscSqr(PetscRealPart(interpolant[fc] - funcVal[fc]))*quadWeights[q]*detJ; 1109 } 1110 } 1111 } 1112 fieldOffset += Nb*Nc; 1113 } 1114 ierr = DMPlexVecRestoreClosure(dm, NULL, localX, c, NULL, &x);CHKERRQ(ierr); 1115 ierr = VecSetValue(D, c - cStart, elemDiff, INSERT_VALUES);CHKERRQ(ierr); 1116 } 1117 ierr = PetscFree6(funcVal,interpolant,coords,v0,J,invJ);CHKERRQ(ierr); 1118 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 1119 ierr = VecSqrtAbs(D);CHKERRQ(ierr); 1120 PetscFunctionReturn(0); 1121 } 1122 1123 #undef __FUNCT__ 1124 #define __FUNCT__ "DMPlexComputeIntegralFEM" 1125 /*@ 1126 DMPlexComputeIntegralFEM - Form the local integral F from the local input X using pointwise functions specified by the user 1127 1128 Input Parameters: 1129 + dm - The mesh 1130 . X - Local input vector 1131 - user - The user context 1132 1133 Output Parameter: 1134 . integral - Local integral for each field 1135 1136 Level: developer 1137 1138 .seealso: DMPlexComputeResidualFEM() 1139 @*/ 1140 PetscErrorCode DMPlexComputeIntegralFEM(DM dm, Vec X, PetscReal *integral, void *user) 1141 { 1142 DM_Plex *mesh = (DM_Plex *) dm->data; 1143 DM dmAux; 1144 Vec localX, A; 1145 PetscDS prob, probAux = NULL; 1146 PetscSection section, sectionAux; 1147 PetscFECellGeom *cgeom; 1148 PetscScalar *u, *a = NULL; 1149 PetscReal *lintegral, *vol; 1150 PetscInt dim, Nf, f, numCells, cStart, cEnd, cEndInterior, c; 1151 PetscInt totDim, totDimAux; 1152 PetscErrorCode ierr; 1153 1154 PetscFunctionBegin; 1155 ierr = PetscLogEventBegin(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr); 1156 ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr); 1157 ierr = DMPlexInsertBoundaryValues(dm, PETSC_TRUE, localX, 0.0, NULL, NULL, NULL);CHKERRQ(ierr); 1158 ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 1159 ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr); 1160 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1161 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 1162 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 1163 ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 1164 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 1165 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 1166 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 1167 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 1168 numCells = cEnd - cStart; 1169 ierr = PetscObjectQuery((PetscObject) dm, "dmAux", (PetscObject *) &dmAux);CHKERRQ(ierr); 1170 ierr = PetscObjectQuery((PetscObject) dm, "A", (PetscObject *) &A);CHKERRQ(ierr); 1171 if (dmAux) { 1172 ierr = DMGetDefaultSection(dmAux, §ionAux);CHKERRQ(ierr); 1173 ierr = DMGetDS(dmAux, &probAux);CHKERRQ(ierr); 1174 ierr = PetscDSGetTotalDimension(probAux, &totDimAux);CHKERRQ(ierr); 1175 } 1176 ierr = PetscMalloc4(Nf,&lintegral,numCells*totDim,&u,numCells,&cgeom,numCells,&vol);CHKERRQ(ierr); 1177 if (dmAux) {ierr = PetscMalloc1(numCells*totDimAux, &a);CHKERRQ(ierr);} 1178 for (f = 0; f < Nf; ++f) {lintegral[f] = 0.0;} 1179 for (c = cStart; c < cEnd; ++c) { 1180 PetscScalar *x = NULL; 1181 PetscInt i; 1182 1183 ierr = DMPlexComputeCellGeometryFEM(dm, c, NULL, cgeom[c].v0, cgeom[c].J, cgeom[c].invJ, &cgeom[c].detJ);CHKERRQ(ierr); 1184 ierr = DMPlexComputeCellGeometryFVM(dm, c, &vol[c], NULL, NULL);CHKERRQ(ierr); 1185 if (cgeom[c].detJ <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", cgeom[c].detJ, c); 1186 ierr = DMPlexVecGetClosure(dm, section, localX, c, NULL, &x);CHKERRQ(ierr); 1187 for (i = 0; i < totDim; ++i) u[c*totDim+i] = x[i]; 1188 ierr = DMPlexVecRestoreClosure(dm, section, localX, c, NULL, &x);CHKERRQ(ierr); 1189 if (dmAux) { 1190 ierr = DMPlexVecGetClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 1191 for (i = 0; i < totDimAux; ++i) a[c*totDimAux+i] = x[i]; 1192 ierr = DMPlexVecRestoreClosure(dmAux, sectionAux, A, c, NULL, &x);CHKERRQ(ierr); 1193 } 1194 } 1195 for (f = 0; f < Nf; ++f) { 1196 PetscObject obj; 1197 PetscClassId id; 1198 PetscInt numChunks, numBatches, batchSize, numBlocks, blockSize, Ne, Nr, offset; 1199 1200 ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 1201 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1202 if (id == PETSCFE_CLASSID) { 1203 PetscFE fe = (PetscFE) obj; 1204 PetscQuadrature q; 1205 PetscInt Nq, Nb; 1206 1207 ierr = PetscFEGetTileSizes(fe, NULL, &numBlocks, NULL, &numBatches);CHKERRQ(ierr); 1208 ierr = PetscFEGetQuadrature(fe, &q);CHKERRQ(ierr); 1209 ierr = PetscQuadratureGetData(q, NULL, &Nq, NULL, NULL);CHKERRQ(ierr); 1210 ierr = PetscFEGetDimension(fe, &Nb);CHKERRQ(ierr); 1211 blockSize = Nb*Nq; 1212 batchSize = numBlocks * blockSize; 1213 ierr = PetscFESetTileSizes(fe, blockSize, numBlocks, batchSize, numBatches);CHKERRQ(ierr); 1214 numChunks = numCells / (numBatches*batchSize); 1215 Ne = numChunks*numBatches*batchSize; 1216 Nr = numCells % (numBatches*batchSize); 1217 offset = numCells - Nr; 1218 ierr = PetscFEIntegrate(fe, prob, f, Ne, cgeom, u, probAux, a, lintegral);CHKERRQ(ierr); 1219 ierr = PetscFEIntegrate(fe, prob, f, Nr, &cgeom[offset], &u[offset*totDim], probAux, &a[offset*totDimAux], lintegral);CHKERRQ(ierr); 1220 } else if (id == PETSCFV_CLASSID) { 1221 /* PetscFV fv = (PetscFV) obj; */ 1222 PetscInt foff; 1223 PetscPointFunc obj_func; 1224 PetscScalar lint; 1225 1226 ierr = PetscDSGetObjective(prob, f, &obj_func);CHKERRQ(ierr); 1227 ierr = PetscDSGetFieldOffset(prob, f, &foff);CHKERRQ(ierr); 1228 if (obj_func) { 1229 for (c = 0; c < numCells; ++c) { 1230 /* TODO: Need full pointwise interpolation and get centroid for x argument */ 1231 obj_func(dim, Nf, 0, NULL, NULL, &u[totDim*c+foff], NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0.0, NULL, &lint); 1232 lintegral[f] = PetscRealPart(lint)*vol[c]; 1233 } 1234 } 1235 } else SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 1236 } 1237 if (dmAux) {ierr = PetscFree(a);CHKERRQ(ierr);} 1238 if (mesh->printFEM) { 1239 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "Local integral:");CHKERRQ(ierr); 1240 for (f = 0; f < Nf; ++f) {ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), " %g", lintegral[f]);CHKERRQ(ierr);} 1241 ierr = PetscPrintf(PetscObjectComm((PetscObject) dm), "\n");CHKERRQ(ierr); 1242 } 1243 ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr); 1244 ierr = MPIU_Allreduce(lintegral, integral, Nf, MPIU_REAL, MPIU_SUM, PetscObjectComm((PetscObject) dm));CHKERRQ(ierr); 1245 ierr = PetscFree4(lintegral,u,cgeom,vol);CHKERRQ(ierr); 1246 ierr = PetscLogEventEnd(DMPLEX_IntegralFEM,dm,0,0,0);CHKERRQ(ierr); 1247 PetscFunctionReturn(0); 1248 } 1249 1250 #undef __FUNCT__ 1251 #define __FUNCT__ "DMPlexComputeInterpolatorNested" 1252 /*@ 1253 DMPlexComputeInterpolatorNested - Form the local portion of the interpolation matrix I from the coarse DM to the uniformly refined DM. 1254 1255 Input Parameters: 1256 + dmf - The fine mesh 1257 . dmc - The coarse mesh 1258 - user - The user context 1259 1260 Output Parameter: 1261 . In - The interpolation matrix 1262 1263 Level: developer 1264 1265 .seealso: DMPlexComputeInterpolatorGeneral(), DMPlexComputeJacobianFEM() 1266 @*/ 1267 PetscErrorCode DMPlexComputeInterpolatorNested(DM dmc, DM dmf, Mat In, void *user) 1268 { 1269 DM_Plex *mesh = (DM_Plex *) dmc->data; 1270 const char *name = "Interpolator"; 1271 PetscDS prob; 1272 PetscFE *feRef; 1273 PetscFV *fvRef; 1274 PetscSection fsection, fglobalSection; 1275 PetscSection csection, cglobalSection; 1276 PetscScalar *elemMat; 1277 PetscInt dim, Nf, f, fieldI, fieldJ, offsetI, offsetJ, cStart, cEnd, cEndInterior, c; 1278 PetscInt cTotDim, rTotDim = 0; 1279 PetscErrorCode ierr; 1280 1281 PetscFunctionBegin; 1282 ierr = PetscLogEventBegin(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1283 ierr = DMGetDimension(dmf, &dim);CHKERRQ(ierr); 1284 ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 1285 ierr = DMGetDefaultGlobalSection(dmf, &fglobalSection);CHKERRQ(ierr); 1286 ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 1287 ierr = DMGetDefaultGlobalSection(dmc, &cglobalSection);CHKERRQ(ierr); 1288 ierr = PetscSectionGetNumFields(fsection, &Nf);CHKERRQ(ierr); 1289 ierr = DMPlexGetHeightStratum(dmc, 0, &cStart, &cEnd);CHKERRQ(ierr); 1290 ierr = DMPlexGetHybridBounds(dmc, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 1291 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 1292 ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr); 1293 ierr = PetscCalloc2(Nf,&feRef,Nf,&fvRef);CHKERRQ(ierr); 1294 for (f = 0; f < Nf; ++f) { 1295 PetscObject obj; 1296 PetscClassId id; 1297 PetscInt rNb = 0, Nc = 0; 1298 1299 ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 1300 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1301 if (id == PETSCFE_CLASSID) { 1302 PetscFE fe = (PetscFE) obj; 1303 1304 ierr = PetscFERefine(fe, &feRef[f]);CHKERRQ(ierr); 1305 ierr = PetscFEGetDimension(feRef[f], &rNb);CHKERRQ(ierr); 1306 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 1307 } else if (id == PETSCFV_CLASSID) { 1308 PetscFV fv = (PetscFV) obj; 1309 PetscDualSpace Q; 1310 1311 ierr = PetscFVRefine(fv, &fvRef[f]);CHKERRQ(ierr); 1312 ierr = PetscFVGetDualSpace(fvRef[f], &Q);CHKERRQ(ierr); 1313 ierr = PetscDualSpaceGetDimension(Q, &rNb);CHKERRQ(ierr); 1314 ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 1315 } 1316 rTotDim += rNb*Nc; 1317 } 1318 ierr = PetscDSGetTotalDimension(prob, &cTotDim);CHKERRQ(ierr); 1319 ierr = PetscMalloc1(rTotDim*cTotDim,&elemMat);CHKERRQ(ierr); 1320 ierr = PetscMemzero(elemMat, rTotDim*cTotDim * sizeof(PetscScalar));CHKERRQ(ierr); 1321 for (fieldI = 0, offsetI = 0; fieldI < Nf; ++fieldI) { 1322 PetscDualSpace Qref; 1323 PetscQuadrature f; 1324 const PetscReal *qpoints, *qweights; 1325 PetscReal *points; 1326 PetscInt npoints = 0, Nc, Np, fpdim, i, k, p, d; 1327 1328 /* Compose points from all dual basis functionals */ 1329 if (feRef[fieldI]) { 1330 ierr = PetscFEGetDualSpace(feRef[fieldI], &Qref);CHKERRQ(ierr); 1331 ierr = PetscFEGetNumComponents(feRef[fieldI], &Nc);CHKERRQ(ierr); 1332 } else { 1333 ierr = PetscFVGetDualSpace(fvRef[fieldI], &Qref);CHKERRQ(ierr); 1334 ierr = PetscFVGetNumComponents(fvRef[fieldI], &Nc);CHKERRQ(ierr); 1335 } 1336 ierr = PetscDualSpaceGetDimension(Qref, &fpdim);CHKERRQ(ierr); 1337 for (i = 0; i < fpdim; ++i) { 1338 ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1339 ierr = PetscQuadratureGetData(f, NULL, &Np, NULL, NULL);CHKERRQ(ierr); 1340 npoints += Np; 1341 } 1342 ierr = PetscMalloc1(npoints*dim,&points);CHKERRQ(ierr); 1343 for (i = 0, k = 0; i < fpdim; ++i) { 1344 ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1345 ierr = PetscQuadratureGetData(f, NULL, &Np, &qpoints, NULL);CHKERRQ(ierr); 1346 for (p = 0; p < Np; ++p, ++k) for (d = 0; d < dim; ++d) points[k*dim+d] = qpoints[p*dim+d]; 1347 } 1348 1349 for (fieldJ = 0, offsetJ = 0; fieldJ < Nf; ++fieldJ) { 1350 PetscObject obj; 1351 PetscClassId id; 1352 PetscReal *B; 1353 PetscInt NcJ = 0, cpdim = 0, j; 1354 1355 ierr = PetscDSGetDiscretization(prob, fieldJ, &obj);CHKERRQ(ierr); 1356 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1357 if (id == PETSCFE_CLASSID) { 1358 PetscFE fe = (PetscFE) obj; 1359 1360 /* Evaluate basis at points */ 1361 ierr = PetscFEGetNumComponents(fe, &NcJ);CHKERRQ(ierr); 1362 ierr = PetscFEGetDimension(fe, &cpdim);CHKERRQ(ierr); 1363 /* For now, fields only interpolate themselves */ 1364 if (fieldI == fieldJ) { 1365 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); 1366 ierr = PetscFEGetTabulation(fe, npoints, points, &B, NULL, NULL);CHKERRQ(ierr); 1367 for (i = 0, k = 0; i < fpdim; ++i) { 1368 ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1369 ierr = PetscQuadratureGetData(f, NULL, &Np, NULL, &qweights);CHKERRQ(ierr); 1370 for (p = 0; p < Np; ++p, ++k) { 1371 for (j = 0; j < cpdim; ++j) { 1372 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]; 1373 } 1374 } 1375 } 1376 ierr = PetscFERestoreTabulation(fe, npoints, points, &B, NULL, NULL);CHKERRQ(ierr);CHKERRQ(ierr); 1377 } 1378 } else if (id == PETSCFV_CLASSID) { 1379 PetscFV fv = (PetscFV) obj; 1380 1381 /* Evaluate constant function at points */ 1382 ierr = PetscFVGetNumComponents(fv, &NcJ);CHKERRQ(ierr); 1383 cpdim = 1; 1384 /* For now, fields only interpolate themselves */ 1385 if (fieldI == fieldJ) { 1386 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); 1387 for (i = 0, k = 0; i < fpdim; ++i) { 1388 ierr = PetscDualSpaceGetFunctional(Qref, i, &f);CHKERRQ(ierr); 1389 ierr = PetscQuadratureGetData(f, NULL, &Np, NULL, &qweights);CHKERRQ(ierr); 1390 for (p = 0; p < Np; ++p, ++k) { 1391 for (j = 0; j < cpdim; ++j) { 1392 for (c = 0; c < Nc; ++c) elemMat[(offsetI + i*Nc + c)*cTotDim + offsetJ + j*NcJ + c] += 1.0*qweights[p]; 1393 } 1394 } 1395 } 1396 } 1397 } 1398 offsetJ += cpdim*NcJ; 1399 } 1400 offsetI += fpdim*Nc; 1401 ierr = PetscFree(points);CHKERRQ(ierr); 1402 } 1403 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(0, name, rTotDim, cTotDim, elemMat);CHKERRQ(ierr);} 1404 /* Preallocate matrix */ 1405 { 1406 Mat preallocator; 1407 PetscScalar *vals; 1408 PetscInt *cellCIndices, *cellFIndices; 1409 PetscInt locRows, locCols, cell; 1410 1411 ierr = MatGetLocalSize(In, &locRows, &locCols);CHKERRQ(ierr); 1412 ierr = MatCreate(PetscObjectComm((PetscObject) In), &preallocator);CHKERRQ(ierr); 1413 ierr = MatSetType(preallocator, MATPREALLOCATOR);CHKERRQ(ierr); 1414 ierr = MatSetSizes(preallocator, locRows, locCols, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 1415 ierr = MatSetUp(preallocator);CHKERRQ(ierr); 1416 ierr = PetscCalloc3(rTotDim*cTotDim, &vals,cTotDim,&cellCIndices,rTotDim,&cellFIndices);CHKERRQ(ierr); 1417 for (cell = cStart; cell < cEnd; ++cell) { 1418 ierr = DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, cell, cellCIndices, cellFIndices);CHKERRQ(ierr); 1419 ierr = MatSetValues(preallocator, rTotDim, cellFIndices, cTotDim, cellCIndices, vals, INSERT_VALUES);CHKERRQ(ierr); 1420 } 1421 ierr = PetscFree3(vals,cellCIndices,cellFIndices);CHKERRQ(ierr); 1422 ierr = MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1423 ierr = MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1424 ierr = MatPreallocatorPreallocate(preallocator, PETSC_TRUE, In);CHKERRQ(ierr); 1425 ierr = MatDestroy(&preallocator);CHKERRQ(ierr); 1426 } 1427 /* Fill matrix */ 1428 ierr = MatZeroEntries(In);CHKERRQ(ierr); 1429 for (c = cStart; c < cEnd; ++c) { 1430 ierr = DMPlexMatSetClosureRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, In, c, elemMat, INSERT_VALUES);CHKERRQ(ierr); 1431 } 1432 for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&feRef[f]);CHKERRQ(ierr);} 1433 ierr = PetscFree2(feRef,fvRef);CHKERRQ(ierr); 1434 ierr = PetscFree(elemMat);CHKERRQ(ierr); 1435 ierr = MatAssemblyBegin(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1436 ierr = MatAssemblyEnd(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1437 if (mesh->printFEM) { 1438 ierr = PetscPrintf(PETSC_COMM_WORLD, "%s:\n", name);CHKERRQ(ierr); 1439 ierr = MatChop(In, 1.0e-10);CHKERRQ(ierr); 1440 ierr = MatView(In, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1441 } 1442 ierr = PetscLogEventEnd(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1443 PetscFunctionReturn(0); 1444 } 1445 1446 #undef __FUNCT__ 1447 #define __FUNCT__ "DMPlexComputeInterpolatorGeneral" 1448 /*@ 1449 DMPlexComputeInterpolatorGeneral - Form the local portion of the interpolation matrix I from the coarse DM to a non-nested fine DM. 1450 1451 Input Parameters: 1452 + dmf - The fine mesh 1453 . dmc - The coarse mesh 1454 - user - The user context 1455 1456 Output Parameter: 1457 . In - The interpolation matrix 1458 1459 Level: developer 1460 1461 .seealso: DMPlexComputeInterpolatorNested(), DMPlexComputeJacobianFEM() 1462 @*/ 1463 PetscErrorCode DMPlexComputeInterpolatorGeneral(DM dmc, DM dmf, Mat In, void *user) 1464 { 1465 DM_Plex *mesh = (DM_Plex *) dmf->data; 1466 const char *name = "Interpolator"; 1467 PetscDS prob; 1468 PetscSection fsection, csection, globalFSection, globalCSection; 1469 PetscHashJK ht; 1470 PetscLayout rLayout; 1471 PetscInt *dnz, *onz; 1472 PetscInt locRows, rStart, rEnd; 1473 PetscReal *x, *v0, *J, *invJ, detJ; 1474 PetscReal *v0c, *Jc, *invJc, detJc; 1475 PetscScalar *elemMat; 1476 PetscInt dim, Nf, field, totDim, cStart, cEnd, cell, ccell; 1477 PetscErrorCode ierr; 1478 1479 PetscFunctionBegin; 1480 ierr = PetscLogEventBegin(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1481 ierr = DMGetCoordinateDim(dmc, &dim);CHKERRQ(ierr); 1482 ierr = DMGetDS(dmc, &prob);CHKERRQ(ierr); 1483 ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr); 1484 ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 1485 ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr); 1486 ierr = PetscMalloc3(dim,&v0c,dim*dim,&Jc,dim*dim,&invJc);CHKERRQ(ierr); 1487 ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 1488 ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr); 1489 ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 1490 ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr); 1491 ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr); 1492 ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr); 1493 ierr = PetscMalloc1(totDim*totDim, &elemMat);CHKERRQ(ierr); 1494 1495 ierr = MatGetLocalSize(In, &locRows, NULL);CHKERRQ(ierr); 1496 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) In), &rLayout);CHKERRQ(ierr); 1497 ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr); 1498 ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr); 1499 ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr); 1500 ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr); 1501 ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr); 1502 ierr = PetscCalloc2(locRows,&dnz,locRows,&onz);CHKERRQ(ierr); 1503 ierr = PetscHashJKCreate(&ht);CHKERRQ(ierr); 1504 for (field = 0; field < Nf; ++field) { 1505 PetscObject obj; 1506 PetscClassId id; 1507 PetscDualSpace Q = NULL; 1508 PetscQuadrature f; 1509 const PetscReal *qpoints; 1510 PetscInt Nc, Np, fpdim, i, d; 1511 1512 ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr); 1513 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1514 if (id == PETSCFE_CLASSID) { 1515 PetscFE fe = (PetscFE) obj; 1516 1517 ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr); 1518 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 1519 } else if (id == PETSCFV_CLASSID) { 1520 PetscFV fv = (PetscFV) obj; 1521 1522 ierr = PetscFVGetDualSpace(fv, &Q);CHKERRQ(ierr); 1523 Nc = 1; 1524 } 1525 ierr = PetscDualSpaceGetDimension(Q, &fpdim);CHKERRQ(ierr); 1526 /* For each fine grid cell */ 1527 for (cell = cStart; cell < cEnd; ++cell) { 1528 PetscInt *findices, *cindices; 1529 PetscInt numFIndices, numCIndices; 1530 1531 ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 1532 ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 1533 if (numFIndices != fpdim*Nc) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of fine indices %d != %d dual basis vecs", numFIndices, fpdim*Nc); 1534 for (i = 0; i < fpdim; ++i) { 1535 Vec pointVec; 1536 PetscScalar *pV; 1537 IS coarseCellIS; 1538 const PetscInt *coarseCells; 1539 PetscInt numCoarseCells, q, r, c; 1540 1541 /* Get points from the dual basis functional quadrature */ 1542 ierr = PetscDualSpaceGetFunctional(Q, i, &f);CHKERRQ(ierr); 1543 ierr = PetscQuadratureGetData(f, NULL, &Np, &qpoints, NULL);CHKERRQ(ierr); 1544 ierr = VecCreateSeq(PETSC_COMM_SELF, Np*dim, &pointVec);CHKERRQ(ierr); 1545 ierr = VecSetBlockSize(pointVec, dim);CHKERRQ(ierr); 1546 ierr = VecGetArray(pointVec, &pV);CHKERRQ(ierr); 1547 for (q = 0; q < Np; ++q) { 1548 /* Transform point to real space */ 1549 CoordinatesRefToReal(dim, dim, v0, J, &qpoints[q*dim], x); 1550 for (d = 0; d < dim; ++d) pV[q*dim+d] = x[d]; 1551 } 1552 ierr = VecRestoreArray(pointVec, &pV);CHKERRQ(ierr); 1553 /* Get set of coarse cells that overlap points (would like to group points by coarse cell) */ 1554 ierr = DMLocatePoints(dmc, pointVec, &coarseCellIS);CHKERRQ(ierr); 1555 ierr = ISViewFromOptions(coarseCellIS, NULL, "-interp_is_view");CHKERRQ(ierr); 1556 /* Update preallocation info */ 1557 ierr = ISGetLocalSize(coarseCellIS, &numCoarseCells);CHKERRQ(ierr); 1558 ierr = ISGetIndices(coarseCellIS, &coarseCells);CHKERRQ(ierr); 1559 for (r = 0; r < Nc; ++r) { 1560 PetscHashJKKey key; 1561 PetscHashJKIter missing, iter; 1562 1563 key.j = findices[i*Nc+r]; 1564 if (key.j < 0) continue; 1565 /* Get indices for coarse elements */ 1566 for (ccell = 0; ccell < numCoarseCells; ++ccell) { 1567 ierr = DMPlexGetClosureIndices(dmc, csection, globalCSection, coarseCells[ccell], &numCIndices, &cindices, NULL);CHKERRQ(ierr); 1568 for (c = 0; c < numCIndices; ++c) { 1569 key.k = cindices[c]; 1570 if (key.k < 0) continue; 1571 ierr = PetscHashJKPut(ht, key, &missing, &iter);CHKERRQ(ierr); 1572 if (missing) { 1573 ierr = PetscHashJKSet(ht, iter, 1);CHKERRQ(ierr); 1574 if ((key.k >= rStart) && (key.k < rEnd)) ++dnz[key.j-rStart]; 1575 else ++onz[key.j-rStart]; 1576 } 1577 } 1578 ierr = DMPlexRestoreClosureIndices(dmc, csection, globalCSection, coarseCells[ccell], &numCIndices, &cindices, NULL);CHKERRQ(ierr); 1579 } 1580 } 1581 ierr = ISRestoreIndices(coarseCellIS, &coarseCells);CHKERRQ(ierr); 1582 ierr = ISDestroy(&coarseCellIS);CHKERRQ(ierr); 1583 ierr = VecDestroy(&pointVec);CHKERRQ(ierr); 1584 } 1585 ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 1586 } 1587 } 1588 ierr = PetscHashJKDestroy(&ht);CHKERRQ(ierr); 1589 ierr = MatXAIJSetPreallocation(In, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr); 1590 ierr = MatSetOption(In, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr); 1591 ierr = PetscFree2(dnz,onz);CHKERRQ(ierr); 1592 for (field = 0; field < Nf; ++field) { 1593 PetscObject obj; 1594 PetscClassId id; 1595 PetscDualSpace Q = NULL; 1596 PetscQuadrature f; 1597 const PetscReal *qpoints, *qweights; 1598 PetscInt Nc, Np, fpdim, i, d; 1599 1600 ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr); 1601 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1602 if (id == PETSCFE_CLASSID) { 1603 PetscFE fe = (PetscFE) obj; 1604 1605 ierr = PetscFEGetDualSpace(fe, &Q);CHKERRQ(ierr); 1606 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 1607 } else if (id == PETSCFV_CLASSID) { 1608 PetscFV fv = (PetscFV) obj; 1609 1610 ierr = PetscFVGetDualSpace(fv, &Q);CHKERRQ(ierr); 1611 Nc = 1; 1612 } 1613 ierr = PetscDualSpaceGetDimension(Q, &fpdim);CHKERRQ(ierr); 1614 /* For each fine grid cell */ 1615 for (cell = cStart; cell < cEnd; ++cell) { 1616 PetscInt *findices, *cindices; 1617 PetscInt numFIndices, numCIndices; 1618 1619 ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 1620 ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); 1621 if (numFIndices != fpdim*Nc) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Number of fine indices %d != %d dual basis vecs", numFIndices, fpdim*Nc); 1622 for (i = 0; i < fpdim; ++i) { 1623 Vec pointVec; 1624 PetscScalar *pV; 1625 IS coarseCellIS; 1626 const PetscInt *coarseCells; 1627 PetscInt numCoarseCells, cpdim, q, c, j; 1628 1629 /* Get points from the dual basis functional quadrature */ 1630 ierr = PetscDualSpaceGetFunctional(Q, i, &f);CHKERRQ(ierr); 1631 ierr = PetscQuadratureGetData(f, NULL, &Np, &qpoints, &qweights);CHKERRQ(ierr); 1632 ierr = VecCreateSeq(PETSC_COMM_SELF, Np*dim, &pointVec);CHKERRQ(ierr); 1633 ierr = VecSetBlockSize(pointVec, dim);CHKERRQ(ierr); 1634 ierr = VecGetArray(pointVec, &pV);CHKERRQ(ierr); 1635 for (q = 0; q < Np; ++q) { 1636 /* Transform point to real space */ 1637 CoordinatesRefToReal(dim, dim, v0, J, &qpoints[q*dim], x); 1638 for (d = 0; d < dim; ++d) pV[q*dim+d] = x[d]; 1639 } 1640 ierr = VecRestoreArray(pointVec, &pV);CHKERRQ(ierr); 1641 /* Get set of coarse cells that overlap points (would like to group points by coarse cell) */ 1642 ierr = DMLocatePoints(dmc, pointVec, &coarseCellIS);CHKERRQ(ierr); 1643 /* Update preallocation info */ 1644 ierr = ISGetLocalSize(coarseCellIS, &numCoarseCells);CHKERRQ(ierr); 1645 ierr = ISGetIndices(coarseCellIS, &coarseCells);CHKERRQ(ierr); 1646 ierr = VecGetArray(pointVec, &pV);CHKERRQ(ierr); 1647 for (ccell = 0; ccell < numCoarseCells; ++ccell) { 1648 PetscReal pVReal[3]; 1649 1650 ierr = DMPlexGetClosureIndices(dmc, csection, globalCSection, coarseCells[ccell], &numCIndices, &cindices, NULL);CHKERRQ(ierr); 1651 /* Transform points from real space to coarse reference space */ 1652 ierr = DMPlexComputeCellGeometryFEM(dmc, coarseCells[ccell], NULL, v0c, Jc, invJc, &detJc);CHKERRQ(ierr); 1653 for (d = 0; d < dim; ++d) pVReal[d] = PetscRealPart(pV[ccell*dim+d]); 1654 CoordinatesRealToRef(dim, dim, v0c, invJc, pVReal, x); 1655 1656 if (id == PETSCFE_CLASSID) { 1657 PetscFE fe = (PetscFE) obj; 1658 PetscReal *B; 1659 1660 /* Evaluate coarse basis on contained point */ 1661 ierr = PetscFEGetDimension(fe, &cpdim);CHKERRQ(ierr); 1662 ierr = PetscFEGetTabulation(fe, 1, x, &B, NULL, NULL);CHKERRQ(ierr); 1663 /* Get elemMat entries by multiplying by weight */ 1664 for (j = 0; j < cpdim; ++j) { 1665 for (c = 0; c < Nc; ++c) elemMat[(c*cpdim + j)*Nc + c] = B[j*Nc + c]*qweights[ccell]; 1666 } 1667 ierr = PetscFERestoreTabulation(fe, 1, x, &B, NULL, NULL);CHKERRQ(ierr);CHKERRQ(ierr); 1668 } else { 1669 cpdim = 1; 1670 for (j = 0; j < cpdim; ++j) { 1671 for (c = 0; c < Nc; ++c) elemMat[(c*cpdim + j)*Nc + c] = 1.0*qweights[ccell]; 1672 } 1673 } 1674 /* Update interpolator */ 1675 if (mesh->printFEM > 1) {ierr = DMPrintCellMatrix(cell, name, Nc, numCIndices, elemMat);CHKERRQ(ierr);} 1676 ierr = MatSetValues(In, Nc, &findices[i*Nc], numCIndices, cindices, elemMat, INSERT_VALUES);CHKERRQ(ierr); 1677 ierr = DMPlexRestoreClosureIndices(dmc, csection, globalCSection, coarseCells[ccell], &numCIndices, &cindices, NULL);CHKERRQ(ierr); 1678 } 1679 ierr = VecRestoreArray(pointVec, &pV);CHKERRQ(ierr); 1680 ierr = ISRestoreIndices(coarseCellIS, &coarseCells);CHKERRQ(ierr); 1681 ierr = ISDestroy(&coarseCellIS);CHKERRQ(ierr); 1682 ierr = VecDestroy(&pointVec);CHKERRQ(ierr); 1683 } 1684 ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr); 1685 } 1686 } 1687 ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr); 1688 ierr = PetscFree3(v0c,Jc,invJc);CHKERRQ(ierr); 1689 ierr = PetscFree(elemMat);CHKERRQ(ierr); 1690 ierr = MatAssemblyBegin(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1691 ierr = MatAssemblyEnd(In, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 1692 ierr = PetscLogEventEnd(DMPLEX_InterpolatorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1693 PetscFunctionReturn(0); 1694 } 1695 1696 #undef __FUNCT__ 1697 #define __FUNCT__ "DMPlexComputeInjectorFEM" 1698 PetscErrorCode DMPlexComputeInjectorFEM(DM dmc, DM dmf, VecScatter *sc, void *user) 1699 { 1700 PetscDS prob; 1701 PetscFE *feRef; 1702 PetscFV *fvRef; 1703 Vec fv, cv; 1704 IS fis, cis; 1705 PetscSection fsection, fglobalSection, csection, cglobalSection; 1706 PetscInt *cmap, *cellCIndices, *cellFIndices, *cindices, *findices; 1707 PetscInt cTotDim, fTotDim = 0, Nf, f, field, cStart, cEnd, cEndInterior, c, dim, d, startC, endC, offsetC, offsetF, m; 1708 PetscErrorCode ierr; 1709 1710 PetscFunctionBegin; 1711 ierr = PetscLogEventBegin(DMPLEX_InjectorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1712 ierr = DMGetDimension(dmf, &dim);CHKERRQ(ierr); 1713 ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr); 1714 ierr = DMGetDefaultGlobalSection(dmf, &fglobalSection);CHKERRQ(ierr); 1715 ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr); 1716 ierr = DMGetDefaultGlobalSection(dmc, &cglobalSection);CHKERRQ(ierr); 1717 ierr = PetscSectionGetNumFields(fsection, &Nf);CHKERRQ(ierr); 1718 ierr = DMPlexGetHeightStratum(dmc, 0, &cStart, &cEnd);CHKERRQ(ierr); 1719 ierr = DMPlexGetHybridBounds(dmc, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 1720 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 1721 ierr = DMGetDS(dmc, &prob);CHKERRQ(ierr); 1722 ierr = PetscCalloc2(Nf,&feRef,Nf,&fvRef);CHKERRQ(ierr); 1723 for (f = 0; f < Nf; ++f) { 1724 PetscObject obj; 1725 PetscClassId id; 1726 PetscInt fNb = 0, Nc = 0; 1727 1728 ierr = PetscDSGetDiscretization(prob, f, &obj);CHKERRQ(ierr); 1729 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 1730 if (id == PETSCFE_CLASSID) { 1731 PetscFE fe = (PetscFE) obj; 1732 1733 ierr = PetscFERefine(fe, &feRef[f]);CHKERRQ(ierr); 1734 ierr = PetscFEGetDimension(feRef[f], &fNb);CHKERRQ(ierr); 1735 ierr = PetscFEGetNumComponents(fe, &Nc);CHKERRQ(ierr); 1736 } else if (id == PETSCFV_CLASSID) { 1737 PetscFV fv = (PetscFV) obj; 1738 PetscDualSpace Q; 1739 1740 ierr = PetscFVRefine(fv, &fvRef[f]);CHKERRQ(ierr); 1741 ierr = PetscFVGetDualSpace(fvRef[f], &Q);CHKERRQ(ierr); 1742 ierr = PetscDualSpaceGetDimension(Q, &fNb);CHKERRQ(ierr); 1743 ierr = PetscFVGetNumComponents(fv, &Nc);CHKERRQ(ierr); 1744 } 1745 fTotDim += fNb*Nc; 1746 } 1747 ierr = PetscDSGetTotalDimension(prob, &cTotDim);CHKERRQ(ierr); 1748 ierr = PetscMalloc1(cTotDim,&cmap);CHKERRQ(ierr); 1749 for (field = 0, offsetC = 0, offsetF = 0; field < Nf; ++field) { 1750 PetscFE feC; 1751 PetscFV fvC; 1752 PetscDualSpace QF, QC; 1753 PetscInt NcF, NcC, fpdim, cpdim; 1754 1755 if (feRef[field]) { 1756 ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &feC);CHKERRQ(ierr); 1757 ierr = PetscFEGetNumComponents(feC, &NcC);CHKERRQ(ierr); 1758 ierr = PetscFEGetNumComponents(feRef[field], &NcF);CHKERRQ(ierr); 1759 ierr = PetscFEGetDualSpace(feRef[field], &QF);CHKERRQ(ierr); 1760 ierr = PetscDualSpaceGetDimension(QF, &fpdim);CHKERRQ(ierr); 1761 ierr = PetscFEGetDualSpace(feC, &QC);CHKERRQ(ierr); 1762 ierr = PetscDualSpaceGetDimension(QC, &cpdim);CHKERRQ(ierr); 1763 } else { 1764 ierr = PetscDSGetDiscretization(prob, field, (PetscObject *) &fvC);CHKERRQ(ierr); 1765 ierr = PetscFVGetNumComponents(fvC, &NcC);CHKERRQ(ierr); 1766 ierr = PetscFVGetNumComponents(fvRef[field], &NcF);CHKERRQ(ierr); 1767 ierr = PetscFVGetDualSpace(fvRef[field], &QF);CHKERRQ(ierr); 1768 ierr = PetscDualSpaceGetDimension(QF, &fpdim);CHKERRQ(ierr); 1769 ierr = PetscFVGetDualSpace(fvC, &QC);CHKERRQ(ierr); 1770 ierr = PetscDualSpaceGetDimension(QC, &cpdim);CHKERRQ(ierr); 1771 } 1772 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); 1773 for (c = 0; c < cpdim; ++c) { 1774 PetscQuadrature cfunc; 1775 const PetscReal *cqpoints; 1776 PetscInt NpC; 1777 PetscBool found = PETSC_FALSE; 1778 1779 ierr = PetscDualSpaceGetFunctional(QC, c, &cfunc);CHKERRQ(ierr); 1780 ierr = PetscQuadratureGetData(cfunc, NULL, &NpC, &cqpoints, NULL);CHKERRQ(ierr); 1781 if (NpC != 1 && feRef[field]) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Do not know how to do injection for moments"); 1782 for (f = 0; f < fpdim; ++f) { 1783 PetscQuadrature ffunc; 1784 const PetscReal *fqpoints; 1785 PetscReal sum = 0.0; 1786 PetscInt NpF, comp; 1787 1788 ierr = PetscDualSpaceGetFunctional(QF, f, &ffunc);CHKERRQ(ierr); 1789 ierr = PetscQuadratureGetData(ffunc, NULL, &NpF, &fqpoints, NULL);CHKERRQ(ierr); 1790 if (NpC != NpF) continue; 1791 for (d = 0; d < dim; ++d) sum += PetscAbsReal(cqpoints[d] - fqpoints[d]); 1792 if (sum > 1.0e-9) continue; 1793 for (comp = 0; comp < NcC; ++comp) { 1794 cmap[(offsetC+c)*NcC+comp] = (offsetF+f)*NcF+comp; 1795 } 1796 found = PETSC_TRUE; 1797 break; 1798 } 1799 if (!found) { 1800 /* TODO We really want the average here, but some asshole put VecScatter in the interface */ 1801 if (fvRef[field]) { 1802 PetscInt comp; 1803 for (comp = 0; comp < NcC; ++comp) { 1804 cmap[(offsetC+c)*NcC+comp] = (offsetF+0)*NcF+comp; 1805 } 1806 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Could not locate matching functional for injection"); 1807 } 1808 } 1809 offsetC += cpdim*NcC; 1810 offsetF += fpdim*NcF; 1811 } 1812 for (f = 0; f < Nf; ++f) {ierr = PetscFEDestroy(&feRef[f]);CHKERRQ(ierr);ierr = PetscFVDestroy(&fvRef[f]);CHKERRQ(ierr);} 1813 ierr = PetscFree2(feRef,fvRef);CHKERRQ(ierr); 1814 1815 ierr = DMGetGlobalVector(dmf, &fv);CHKERRQ(ierr); 1816 ierr = DMGetGlobalVector(dmc, &cv);CHKERRQ(ierr); 1817 ierr = VecGetOwnershipRange(cv, &startC, &endC);CHKERRQ(ierr); 1818 ierr = PetscSectionGetConstrainedStorageSize(cglobalSection, &m);CHKERRQ(ierr); 1819 ierr = PetscMalloc2(cTotDim,&cellCIndices,fTotDim,&cellFIndices);CHKERRQ(ierr); 1820 ierr = PetscMalloc1(m,&cindices);CHKERRQ(ierr); 1821 ierr = PetscMalloc1(m,&findices);CHKERRQ(ierr); 1822 for (d = 0; d < m; ++d) cindices[d] = findices[d] = -1; 1823 for (c = cStart; c < cEnd; ++c) { 1824 ierr = DMPlexMatGetClosureIndicesRefined(dmf, fsection, fglobalSection, dmc, csection, cglobalSection, c, cellCIndices, cellFIndices);CHKERRQ(ierr); 1825 for (d = 0; d < cTotDim; ++d) { 1826 if ((cellCIndices[d] < startC) || (cellCIndices[d] >= endC)) continue; 1827 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]]); 1828 cindices[cellCIndices[d]-startC] = cellCIndices[d]; 1829 findices[cellCIndices[d]-startC] = cellFIndices[cmap[d]]; 1830 } 1831 } 1832 ierr = PetscFree(cmap);CHKERRQ(ierr); 1833 ierr = PetscFree2(cellCIndices,cellFIndices);CHKERRQ(ierr); 1834 1835 ierr = ISCreateGeneral(PETSC_COMM_SELF, m, cindices, PETSC_OWN_POINTER, &cis);CHKERRQ(ierr); 1836 ierr = ISCreateGeneral(PETSC_COMM_SELF, m, findices, PETSC_OWN_POINTER, &fis);CHKERRQ(ierr); 1837 ierr = VecScatterCreate(cv, cis, fv, fis, sc);CHKERRQ(ierr); 1838 ierr = ISDestroy(&cis);CHKERRQ(ierr); 1839 ierr = ISDestroy(&fis);CHKERRQ(ierr); 1840 ierr = DMRestoreGlobalVector(dmf, &fv);CHKERRQ(ierr); 1841 ierr = DMRestoreGlobalVector(dmc, &cv);CHKERRQ(ierr); 1842 ierr = PetscLogEventEnd(DMPLEX_InjectorFEM,dmc,dmf,0,0);CHKERRQ(ierr); 1843 PetscFunctionReturn(0); 1844 } 1845