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