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