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