1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 3 #include <petsc/private/petscfeimpl.h> 4 5 /*@ 6 DMPlexGetActivePoint - Get the point on which projection is currently working 7 8 Not collective 9 10 Input Parameter: 11 . dm - the DM 12 13 Output Parameter: 14 . point - The mesh point involved in the current projection 15 16 Level: developer 17 18 .seealso: DMPlexSetActivePoint() 19 @*/ 20 PetscErrorCode DMPlexGetActivePoint(DM dm, PetscInt *point) 21 { 22 PetscFunctionBeginHot; 23 *point = ((DM_Plex *) dm->data)->activePoint; 24 PetscFunctionReturn(0); 25 } 26 27 /*@ 28 DMPlexSetActivePoint - Set the point on which projection is currently working 29 30 Not collective 31 32 Input Parameters: 33 + dm - the DM 34 - point - The mesh point involved in the current projection 35 36 Level: developer 37 38 .seealso: DMPlexGetActivePoint() 39 @*/ 40 PetscErrorCode DMPlexSetActivePoint(DM dm, PetscInt point) 41 { 42 PetscFunctionBeginHot; 43 ((DM_Plex *) dm->data)->activePoint = point; 44 PetscFunctionReturn(0); 45 } 46 47 /* 48 DMProjectPoint_Func_Private - Interpolate the given function in the output basis on the given point 49 50 Input Parameters: 51 + dm - The output DM 52 . ds - The output DS 53 . dmIn - The input DM 54 . dsIn - The input DS 55 . time - The time for this evaluation 56 . fegeom - The FE geometry for this point 57 . fvgeom - The FV geometry for this point 58 . isFE - Flag indicating whether each output field has an FE discretization 59 . sp - The output PetscDualSpace for each field 60 . funcs - The evaluation function for each field 61 - ctxs - The user context for each field 62 63 Output Parameter: 64 . values - The value for each dual basis vector in the output dual space 65 66 Level: developer 67 68 .seealso: DMProjectPoint_Field_Private() 69 */ 70 static PetscErrorCode DMProjectPoint_Func_Private(DM dm, PetscDS ds, DM dmIn, PetscDS dsIn, PetscReal time, PetscFEGeom *fegeom, PetscFVCellGeom *fvgeom, PetscBool isFE[], PetscDualSpace sp[], 71 PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, 72 PetscScalar values[]) 73 { 74 PetscInt coordDim, Nf, *Nc, f, spDim, d, v, tp; 75 PetscBool isAffine, isCohesive, transform; 76 77 PetscFunctionBeginHot; 78 CHKERRQ(DMGetCoordinateDim(dmIn, &coordDim)); 79 CHKERRQ(DMHasBasisTransform(dmIn, &transform)); 80 CHKERRQ(PetscDSGetNumFields(ds, &Nf)); 81 CHKERRQ(PetscDSGetComponents(ds, &Nc)); 82 CHKERRQ(PetscDSIsCohesive(ds, &isCohesive)); 83 /* Get values for closure */ 84 isAffine = fegeom->isAffine; 85 for (f = 0, v = 0, tp = 0; f < Nf; ++f) { 86 void * const ctx = ctxs ? ctxs[f] : NULL; 87 PetscBool cohesive; 88 89 if (!sp[f]) continue; 90 CHKERRQ(PetscDSGetCohesive(ds, f, &cohesive)); 91 CHKERRQ(PetscDualSpaceGetDimension(sp[f], &spDim)); 92 if (funcs[f]) { 93 if (isFE[f]) { 94 PetscQuadrature allPoints; 95 PetscInt q, dim, numPoints; 96 const PetscReal *points; 97 PetscScalar *pointEval; 98 PetscReal *x; 99 DM rdm; 100 101 CHKERRQ(PetscDualSpaceGetDM(sp[f],&rdm)); 102 CHKERRQ(PetscDualSpaceGetAllData(sp[f], &allPoints, NULL)); 103 CHKERRQ(PetscQuadratureGetData(allPoints,&dim,NULL,&numPoints,&points,NULL)); 104 CHKERRQ(DMGetWorkArray(rdm,numPoints*Nc[f],MPIU_SCALAR,&pointEval)); 105 CHKERRQ(DMGetWorkArray(rdm,coordDim,MPIU_REAL,&x)); 106 for (q = 0; q < numPoints; q++, tp++) { 107 const PetscReal *v0; 108 109 if (isAffine) { 110 const PetscReal *refpoint = &points[q*dim]; 111 PetscReal injpoint[3] = {0., 0., 0.}; 112 113 if (dim != fegeom->dim) { 114 if (isCohesive) { 115 /* We just need to inject into the higher dimensional space assuming the last dimension is collapsed */ 116 for (d = 0; d < dim; ++d) injpoint[d] = refpoint[d]; 117 refpoint = injpoint; 118 } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Reference spatial dimension %D != %D dual basis spatial dimension", fegeom->dim, dim); 119 } 120 CoordinatesRefToReal(coordDim, fegeom->dim, fegeom->xi, fegeom->v, fegeom->J, refpoint, x); 121 v0 = x; 122 } else { 123 v0 = &fegeom->v[tp*coordDim]; 124 } 125 if (transform) {CHKERRQ(DMPlexBasisTransformApplyReal_Internal(dmIn, v0, PETSC_TRUE, coordDim, v0, x, dm->transformCtx)); v0 = x;} 126 CHKERRQ((*funcs[f])(coordDim, time, v0, Nc[f], &pointEval[Nc[f]*q], ctx)); 127 } 128 /* Transform point evaluations pointEval[q,c] */ 129 CHKERRQ(PetscDualSpacePullback(sp[f], fegeom, numPoints, Nc[f], pointEval)); 130 CHKERRQ(PetscDualSpaceApplyAll(sp[f], pointEval, &values[v])); 131 CHKERRQ(DMRestoreWorkArray(rdm,coordDim,MPIU_REAL,&x)); 132 CHKERRQ(DMRestoreWorkArray(rdm,numPoints*Nc[f],MPIU_SCALAR,&pointEval)); 133 v += spDim; 134 if (isCohesive && !cohesive) { 135 for (d = 0; d < spDim; d++, v++) values[v] = values[v - spDim]; 136 } 137 } else { 138 for (d = 0; d < spDim; ++d, ++v) { 139 CHKERRQ(PetscDualSpaceApplyFVM(sp[f], d, time, fvgeom, Nc[f], funcs[f], ctx, &values[v])); 140 } 141 } 142 } else { 143 for (d = 0; d < spDim; d++, v++) values[v] = 0.; 144 if (isCohesive && !cohesive) { 145 for (d = 0; d < spDim; d++, v++) values[v] = 0.; 146 } 147 } 148 } 149 PetscFunctionReturn(0); 150 } 151 152 /* 153 DMProjectPoint_Field_Private - Interpolate a function of the given field, in the input basis, using the output basis on the given point 154 155 Input Parameters: 156 + dm - The output DM 157 . ds - The output DS 158 . dmIn - The input DM 159 . dsIn - The input DS 160 . dmAux - The auxiliary DM, which is always for the input space 161 . dsAux - The auxiliary DS, which is always for the input space 162 . time - The time for this evaluation 163 . localU - The local solution 164 . localA - The local auziliary fields 165 . cgeom - The FE geometry for this point 166 . sp - The output PetscDualSpace for each field 167 . p - The point in the output DM 168 . T - Input basis and derivatives for each field tabulated on the quadrature points 169 . TAux - Auxiliary basis and derivatives for each aux field tabulated on the quadrature points 170 . funcs - The evaluation function for each field 171 - ctxs - The user context for each field 172 173 Output Parameter: 174 . values - The value for each dual basis vector in the output dual space 175 176 Note: Not supported for FV 177 178 Level: developer 179 180 .seealso: DMProjectPoint_Field_Private() 181 */ 182 static PetscErrorCode DMProjectPoint_Field_Private(DM dm, PetscDS ds, DM dmIn, DMEnclosureType encIn, PetscDS dsIn, DM dmAux, DMEnclosureType encAux, PetscDS dsAux, PetscReal time, Vec localU, Vec localA, PetscFEGeom *cgeom, PetscDualSpace sp[], PetscInt p, 183 PetscTabulation *T, PetscTabulation *TAux, 184 void (**funcs)(PetscInt, PetscInt, PetscInt, 185 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 186 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 187 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), void **ctxs, 188 PetscScalar values[]) 189 { 190 PetscSection section, sectionAux = NULL; 191 PetscScalar *u, *u_t = NULL, *u_x, *a = NULL, *a_t = NULL, *a_x = NULL, *bc; 192 PetscScalar *coefficients = NULL, *coefficientsAux = NULL; 193 PetscScalar *coefficients_t = NULL, *coefficientsAux_t = NULL; 194 const PetscScalar *constants; 195 PetscReal *x; 196 PetscInt *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL, *Nc; 197 PetscFEGeom fegeom; 198 const PetscInt dE = cgeom->dimEmbed; 199 PetscInt numConstants, Nf, NfIn, NfAux = 0, f, spDim, d, v, inp, tp = 0; 200 PetscBool isAffine, isCohesive, transform; 201 202 PetscFunctionBeginHot; 203 CHKERRQ(PetscDSGetNumFields(ds, &Nf)); 204 CHKERRQ(PetscDSGetComponents(ds, &Nc)); 205 CHKERRQ(PetscDSIsCohesive(ds, &isCohesive)); 206 CHKERRQ(PetscDSGetNumFields(dsIn, &NfIn)); 207 CHKERRQ(PetscDSGetComponentOffsets(dsIn, &uOff)); 208 CHKERRQ(PetscDSGetComponentDerivativeOffsets(dsIn, &uOff_x)); 209 CHKERRQ(PetscDSGetEvaluationArrays(dsIn, &u, &bc /*&u_t*/, &u_x)); 210 CHKERRQ(PetscDSGetWorkspace(dsIn, &x, NULL, NULL, NULL, NULL)); 211 CHKERRQ(PetscDSGetConstants(dsIn, &numConstants, &constants)); 212 CHKERRQ(DMHasBasisTransform(dmIn, &transform)); 213 CHKERRQ(DMGetLocalSection(dmIn, §ion)); 214 CHKERRQ(DMGetEnclosurePoint(dmIn, dm, encIn, p, &inp)); 215 CHKERRQ(DMPlexVecGetClosure(dmIn, section, localU, inp, NULL, &coefficients)); 216 if (dmAux) { 217 PetscInt subp; 218 219 CHKERRQ(DMGetEnclosurePoint(dmAux, dm, encAux, p, &subp)); 220 CHKERRQ(PetscDSGetNumFields(dsAux, &NfAux)); 221 CHKERRQ(DMGetLocalSection(dmAux, §ionAux)); 222 CHKERRQ(PetscDSGetComponentOffsets(dsAux, &aOff)); 223 CHKERRQ(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x)); 224 CHKERRQ(PetscDSGetEvaluationArrays(dsAux, &a, NULL /*&a_t*/, &a_x)); 225 CHKERRQ(DMPlexVecGetClosure(dmAux, sectionAux, localA, subp, NULL, &coefficientsAux)); 226 } 227 /* Get values for closure */ 228 isAffine = cgeom->isAffine; 229 fegeom.dim = cgeom->dim; 230 fegeom.dimEmbed = cgeom->dimEmbed; 231 if (isAffine) { 232 fegeom.v = x; 233 fegeom.xi = cgeom->xi; 234 fegeom.J = cgeom->J; 235 fegeom.invJ = cgeom->invJ; 236 fegeom.detJ = cgeom->detJ; 237 } 238 for (f = 0, v = 0; f < Nf; ++f) { 239 PetscQuadrature allPoints; 240 PetscInt q, dim, numPoints; 241 const PetscReal *points; 242 PetscScalar *pointEval; 243 PetscBool cohesive; 244 DM dm; 245 246 if (!sp[f]) continue; 247 CHKERRQ(PetscDSGetCohesive(ds, f, &cohesive)); 248 CHKERRQ(PetscDualSpaceGetDimension(sp[f], &spDim)); 249 if (!funcs[f]) { 250 for (d = 0; d < spDim; d++, v++) values[v] = 0.; 251 if (isCohesive && !cohesive) { 252 for (d = 0; d < spDim; d++, v++) values[v] = 0.; 253 } 254 continue; 255 } 256 CHKERRQ(PetscDualSpaceGetDM(sp[f],&dm)); 257 CHKERRQ(PetscDualSpaceGetAllData(sp[f], &allPoints, NULL)); 258 CHKERRQ(PetscQuadratureGetData(allPoints,&dim,NULL,&numPoints,&points,NULL)); 259 CHKERRQ(DMGetWorkArray(dm,numPoints*Nc[f],MPIU_SCALAR,&pointEval)); 260 for (q = 0; q < numPoints; ++q, ++tp) { 261 if (isAffine) { 262 CoordinatesRefToReal(dE, cgeom->dim, fegeom.xi, cgeom->v, fegeom.J, &points[q*dim], x); 263 } else { 264 fegeom.v = &cgeom->v[tp*dE]; 265 fegeom.J = &cgeom->J[tp*dE*dE]; 266 fegeom.invJ = &cgeom->invJ[tp*dE*dE]; 267 fegeom.detJ = &cgeom->detJ[tp]; 268 } 269 CHKERRQ(PetscFEEvaluateFieldJets_Internal(dsIn, NfIn, 0, tp, T, &fegeom, coefficients, coefficients_t, u, u_x, u_t)); 270 if (dsAux) CHKERRQ(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, tp, TAux, &fegeom, coefficientsAux, coefficientsAux_t, a, a_x, a_t)); 271 if (transform) CHKERRQ(DMPlexBasisTransformApplyReal_Internal(dmIn, fegeom.v, PETSC_TRUE, dE, fegeom.v, fegeom.v, dm->transformCtx)); 272 (*funcs[f])(dE, NfIn, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, a_t, a_x, time, fegeom.v, numConstants, constants, &pointEval[Nc[f]*q]); 273 } 274 CHKERRQ(PetscDualSpaceApplyAll(sp[f], pointEval, &values[v])); 275 CHKERRQ(DMRestoreWorkArray(dm,numPoints*Nc[f],MPIU_SCALAR,&pointEval)); 276 v += spDim; 277 /* TODO: For now, set both sides equal, but this should use info from other support cell */ 278 if (isCohesive && !cohesive) { 279 for (d = 0; d < spDim; d++, v++) values[v] = values[v - spDim]; 280 } 281 } 282 CHKERRQ(DMPlexVecRestoreClosure(dmIn, section, localU, inp, NULL, &coefficients)); 283 if (dmAux) CHKERRQ(DMPlexVecRestoreClosure(dmAux, sectionAux, localA, p, NULL, &coefficientsAux)); 284 PetscFunctionReturn(0); 285 } 286 287 static PetscErrorCode DMProjectPoint_BdField_Private(DM dm, PetscDS ds, DM dmIn, PetscDS dsIn, DM dmAux, DMEnclosureType encAux, PetscDS dsAux, PetscReal time, Vec localU, Vec localA, PetscFEGeom *fgeom, PetscDualSpace sp[], PetscInt p, 288 PetscTabulation *T, PetscTabulation *TAux, 289 void (**funcs)(PetscInt, PetscInt, PetscInt, 290 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 291 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 292 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), void **ctxs, 293 PetscScalar values[]) 294 { 295 PetscSection section, sectionAux = NULL; 296 PetscScalar *u, *u_t = NULL, *u_x, *a = NULL, *a_t = NULL, *a_x = NULL, *bc; 297 PetscScalar *coefficients = NULL, *coefficientsAux = NULL; 298 PetscScalar *coefficients_t = NULL, *coefficientsAux_t = NULL; 299 const PetscScalar *constants; 300 PetscReal *x; 301 PetscInt *uOff, *uOff_x, *aOff = NULL, *aOff_x = NULL, *Nc; 302 PetscFEGeom fegeom, cgeom; 303 const PetscInt dE = fgeom->dimEmbed; 304 PetscInt numConstants, Nf, NfAux = 0, f, spDim, d, v, tp = 0; 305 PetscBool isAffine; 306 307 PetscFunctionBeginHot; 308 PetscCheckFalse(dm != dmIn,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Not yet upgraded to use different input DM"); 309 CHKERRQ(PetscDSGetNumFields(ds, &Nf)); 310 CHKERRQ(PetscDSGetComponents(ds, &Nc)); 311 CHKERRQ(PetscDSGetComponentOffsets(ds, &uOff)); 312 CHKERRQ(PetscDSGetComponentDerivativeOffsets(ds, &uOff_x)); 313 CHKERRQ(PetscDSGetEvaluationArrays(ds, &u, &bc /*&u_t*/, &u_x)); 314 CHKERRQ(PetscDSGetWorkspace(ds, &x, NULL, NULL, NULL, NULL)); 315 CHKERRQ(PetscDSGetConstants(ds, &numConstants, &constants)); 316 CHKERRQ(DMGetLocalSection(dm, §ion)); 317 CHKERRQ(DMPlexVecGetClosure(dmIn, section, localU, p, NULL, &coefficients)); 318 if (dmAux) { 319 PetscInt subp; 320 321 CHKERRQ(DMGetEnclosurePoint(dmAux, dm, encAux, p, &subp)); 322 CHKERRQ(PetscDSGetNumFields(dsAux, &NfAux)); 323 CHKERRQ(DMGetLocalSection(dmAux, §ionAux)); 324 CHKERRQ(PetscDSGetComponentOffsets(dsAux, &aOff)); 325 CHKERRQ(PetscDSGetComponentDerivativeOffsets(dsAux, &aOff_x)); 326 CHKERRQ(PetscDSGetEvaluationArrays(dsAux, &a, NULL /*&a_t*/, &a_x)); 327 CHKERRQ(DMPlexVecGetClosure(dmAux, sectionAux, localA, subp, NULL, &coefficientsAux)); 328 } 329 /* Get values for closure */ 330 isAffine = fgeom->isAffine; 331 fegeom.n = NULL; 332 fegeom.J = NULL; 333 fegeom.v = NULL; 334 fegeom.xi = NULL; 335 cgeom.dim = fgeom->dim; 336 cgeom.dimEmbed = fgeom->dimEmbed; 337 if (isAffine) { 338 fegeom.v = x; 339 fegeom.xi = fgeom->xi; 340 fegeom.J = fgeom->J; 341 fegeom.invJ = fgeom->invJ; 342 fegeom.detJ = fgeom->detJ; 343 fegeom.n = fgeom->n; 344 345 cgeom.J = fgeom->suppJ[0]; 346 cgeom.invJ = fgeom->suppInvJ[0]; 347 cgeom.detJ = fgeom->suppDetJ[0]; 348 } 349 for (f = 0, v = 0; f < Nf; ++f) { 350 PetscQuadrature allPoints; 351 PetscInt q, dim, numPoints; 352 const PetscReal *points; 353 PetscScalar *pointEval; 354 DM dm; 355 356 if (!sp[f]) continue; 357 CHKERRQ(PetscDualSpaceGetDimension(sp[f], &spDim)); 358 if (!funcs[f]) { 359 for (d = 0; d < spDim; d++, v++) values[v] = 0.; 360 continue; 361 } 362 CHKERRQ(PetscDualSpaceGetDM(sp[f],&dm)); 363 CHKERRQ(PetscDualSpaceGetAllData(sp[f], &allPoints, NULL)); 364 CHKERRQ(PetscQuadratureGetData(allPoints,&dim,NULL,&numPoints,&points,NULL)); 365 CHKERRQ(DMGetWorkArray(dm,numPoints*Nc[f],MPIU_SCALAR,&pointEval)); 366 for (q = 0; q < numPoints; ++q, ++tp) { 367 if (isAffine) { 368 CoordinatesRefToReal(dE, fgeom->dim, fegeom.xi, fgeom->v, fegeom.J, &points[q*dim], x); 369 } else { 370 fegeom.v = &fgeom->v[tp*dE]; 371 fegeom.J = &fgeom->J[tp*dE*dE]; 372 fegeom.invJ = &fgeom->invJ[tp*dE*dE]; 373 fegeom.detJ = &fgeom->detJ[tp]; 374 fegeom.n = &fgeom->n[tp*dE]; 375 376 cgeom.J = &fgeom->suppJ[0][tp*dE*dE]; 377 cgeom.invJ = &fgeom->suppInvJ[0][tp*dE*dE]; 378 cgeom.detJ = &fgeom->suppDetJ[0][tp]; 379 } 380 /* TODO We should use cgeom here, instead of fegeom, however the geometry coming in through fgeom does not have the support cell geometry */ 381 CHKERRQ(PetscFEEvaluateFieldJets_Internal(ds, Nf, 0, tp, T, &cgeom, coefficients, coefficients_t, u, u_x, u_t)); 382 if (dsAux) CHKERRQ(PetscFEEvaluateFieldJets_Internal(dsAux, NfAux, 0, tp, TAux, &cgeom, coefficientsAux, coefficientsAux_t, a, a_x, a_t)); 383 (*funcs[f])(dE, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, a_t, a_x, time, fegeom.v, fegeom.n, numConstants, constants, &pointEval[Nc[f]*q]); 384 } 385 CHKERRQ(PetscDualSpaceApplyAll(sp[f], pointEval, &values[v])); 386 CHKERRQ(DMRestoreWorkArray(dm,numPoints*Nc[f],MPIU_SCALAR,&pointEval)); 387 v += spDim; 388 } 389 CHKERRQ(DMPlexVecRestoreClosure(dmIn, section, localU, p, NULL, &coefficients)); 390 if (dmAux) CHKERRQ(DMPlexVecRestoreClosure(dmAux, sectionAux, localA, p, NULL, &coefficientsAux)); 391 PetscFunctionReturn(0); 392 } 393 394 static PetscErrorCode DMProjectPoint_Private(DM dm, PetscDS ds, DM dmIn, DMEnclosureType encIn, PetscDS dsIn, DM dmAux, DMEnclosureType encAux, PetscDS dsAux, PetscFEGeom *fegeom, PetscInt effectiveHeight, PetscReal time, Vec localU, Vec localA, PetscBool hasFE, PetscBool hasFV, PetscBool isFE[], 395 PetscDualSpace sp[], PetscInt p, PetscTabulation *T, PetscTabulation *TAux, 396 DMBoundaryConditionType type, void (**funcs)(void), void **ctxs, PetscBool fieldActive[], PetscScalar values[]) 397 { 398 PetscFVCellGeom fvgeom; 399 PetscInt dim, dimEmbed; 400 PetscErrorCode ierr; 401 402 PetscFunctionBeginHot; 403 CHKERRQ(DMGetDimension(dm, &dim)); 404 CHKERRQ(DMGetCoordinateDim(dm, &dimEmbed)); 405 if (hasFV) CHKERRQ(DMPlexComputeCellGeometryFVM(dm, p, &fvgeom.volume, fvgeom.centroid, NULL)); 406 switch (type) { 407 case DM_BC_ESSENTIAL: 408 case DM_BC_NATURAL: 409 CHKERRQ(DMProjectPoint_Func_Private(dm, ds, dmIn, dsIn, time, fegeom, &fvgeom, isFE, sp, (PetscErrorCode (**)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *)) funcs, ctxs, values));break; 410 case DM_BC_ESSENTIAL_FIELD: 411 case DM_BC_NATURAL_FIELD: 412 ierr = DMProjectPoint_Field_Private(dm, ds, dmIn, encIn, dsIn, dmAux, encAux, dsAux, time, localU, localA, fegeom, sp, p, T, TAux, 413 (void (**)(PetscInt, PetscInt, PetscInt, 414 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 415 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 416 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[])) funcs, ctxs, values);CHKERRQ(ierr);break; 417 case DM_BC_ESSENTIAL_BD_FIELD: 418 ierr = DMProjectPoint_BdField_Private(dm, ds, dmIn, dsIn, dmAux, encAux, dsAux, time, localU, localA, fegeom, sp, p, T, TAux, 419 (void (**)(PetscInt, PetscInt, PetscInt, 420 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 421 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 422 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[])) funcs, ctxs, values);CHKERRQ(ierr);break; 423 default: SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Unknown boundary condition type: %d", (int) type); 424 } 425 PetscFunctionReturn(0); 426 } 427 428 static PetscErrorCode PetscDualSpaceGetAllPointsUnion(PetscInt Nf, PetscDualSpace *sp, PetscInt dim, void (**funcs)(void), PetscQuadrature *allPoints) 429 { 430 PetscReal *points; 431 PetscInt f, numPoints; 432 433 PetscFunctionBegin; 434 numPoints = 0; 435 for (f = 0; f < Nf; ++f) { 436 if (funcs[f]) { 437 PetscQuadrature fAllPoints; 438 PetscInt fNumPoints; 439 440 CHKERRQ(PetscDualSpaceGetAllData(sp[f],&fAllPoints, NULL)); 441 CHKERRQ(PetscQuadratureGetData(fAllPoints, NULL, NULL, &fNumPoints, NULL, NULL)); 442 numPoints += fNumPoints; 443 } 444 } 445 CHKERRQ(PetscMalloc1(dim*numPoints,&points)); 446 numPoints = 0; 447 for (f = 0; f < Nf; ++f) { 448 if (funcs[f]) { 449 PetscQuadrature fAllPoints; 450 PetscInt qdim, fNumPoints, q; 451 const PetscReal *fPoints; 452 453 CHKERRQ(PetscDualSpaceGetAllData(sp[f],&fAllPoints, NULL)); 454 CHKERRQ(PetscQuadratureGetData(fAllPoints, &qdim, NULL, &fNumPoints, &fPoints, NULL)); 455 PetscCheckFalse(qdim != dim,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Spatial dimension %D for dual basis does not match input dimension %D", qdim, dim); 456 for (q = 0; q < fNumPoints*dim; ++q) points[numPoints*dim+q] = fPoints[q]; 457 numPoints += fNumPoints; 458 } 459 } 460 CHKERRQ(PetscQuadratureCreate(PETSC_COMM_SELF,allPoints)); 461 CHKERRQ(PetscQuadratureSetData(*allPoints,dim,0,numPoints,points,NULL)); 462 PetscFunctionReturn(0); 463 } 464 465 /*@C 466 DMGetFirstLabeledPoint - Find first labeled point p_o in odm such that the corresponding point p in dm has the specified height. Return p and the corresponding ds. 467 468 Input Parameters: 469 dm - the DM 470 odm - the enclosing DM 471 label - label for DM domain, or NULL for whole domain 472 numIds - the number of ids 473 ids - An array of the label ids in sequence for the domain 474 height - Height of target cells in DMPlex topology 475 476 Output Parameters: 477 point - the first labeled point 478 ds - the ds corresponding to the first labeled point 479 480 Level: developer 481 @*/ 482 PetscErrorCode DMGetFirstLabeledPoint(DM dm, DM odm, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt height, PetscInt *point, PetscDS *ds) 483 { 484 DM plex; 485 DMEnclosureType enc; 486 PetscInt ls = -1; 487 488 PetscFunctionBegin; 489 if (point) *point = -1; 490 if (!label) PetscFunctionReturn(0); 491 CHKERRQ(DMGetEnclosureRelation(dm, odm, &enc)); 492 CHKERRQ(DMConvert(dm, DMPLEX, &plex)); 493 for (PetscInt i = 0; i < numIds; ++i) { 494 IS labelIS; 495 PetscInt num_points, pStart, pEnd; 496 CHKERRQ(DMLabelGetStratumIS(label, ids[i], &labelIS)); 497 if (!labelIS) continue; /* No points with that id on this process */ 498 CHKERRQ(DMPlexGetHeightStratum(plex, height, &pStart, &pEnd)); 499 CHKERRQ(ISGetSize(labelIS, &num_points)); 500 if (num_points) { 501 const PetscInt *points; 502 CHKERRQ(ISGetIndices(labelIS, &points)); 503 for (PetscInt i=0; i<num_points; i++) { 504 PetscInt point; 505 CHKERRQ(DMGetEnclosurePoint(dm, odm, enc, points[i], &point)); 506 if (pStart <= point && point < pEnd) { 507 ls = point; 508 if (ds) CHKERRQ(DMGetCellDS(dm, ls, ds)); 509 } 510 } 511 CHKERRQ(ISRestoreIndices(labelIS, &points)); 512 } 513 CHKERRQ(ISDestroy(&labelIS)); 514 if (ls >= 0) break; 515 } 516 if (point) *point = ls; 517 CHKERRQ(DMDestroy(&plex)); 518 PetscFunctionReturn(0); 519 } 520 521 /* 522 This function iterates over a manifold, and interpolates the input function/field using the basis provided by the DS in our DM 523 524 There are several different scenarios: 525 526 1) Volumetric mesh with volumetric auxiliary data 527 528 Here minHeight=0 since we loop over cells. 529 530 2) Boundary mesh with boundary auxiliary data 531 532 Here minHeight=1 since we loop over faces. This normally happens since we hang cells off of our boundary meshes to facilitate computation. 533 534 3) Volumetric mesh with boundary auxiliary data 535 536 Here minHeight=1 and auxbd=PETSC_TRUE since we loop over faces and use data only supported on those faces. This is common when imposing Dirichlet boundary conditions. 537 538 4) Volumetric input mesh with boundary output mesh 539 540 Here we must get a subspace for the input DS 541 542 The maxHeight is used to support enforcement of constraints in DMForest. 543 544 If localU is given and not equal to localX, we call DMPlexInsertBoundaryValues() to complete it. 545 546 If we are using an input field (DM_BC_ESSENTIAL_FIELD or DM_BC_NATURAL_FIELD), we need to evaluate it at all the quadrature points of the dual basis functionals. 547 - We use effectiveHeight to mean the height above our incoming DS. For example, if the DS is for a submesh then the effective height is zero, whereas if the DS 548 is for the volumetric mesh, but we are iterating over a surface, then the effective height is nonzero. When the effective height is nonzero, we need to extract 549 dual spaces for the boundary from our input spaces. 550 - After extracting all quadrature points, we tabulate the input fields and auxiliary fields on them. 551 552 We check that the #dof(closure(p)) == #dual basis functionals(p) for a representative p in the iteration 553 554 If we have a label, we iterate over those points. This will probably break the maxHeight functionality since we do not check the height of those points. 555 */ 556 static PetscErrorCode DMProjectLocal_Generic_Plex(DM dm, PetscReal time, Vec localU, 557 PetscInt Ncc, const PetscInt comps[], DMLabel label, PetscInt numIds, const PetscInt ids[], 558 DMBoundaryConditionType type, void (**funcs)(void), void **ctxs, 559 InsertMode mode, Vec localX) 560 { 561 DM plex, dmIn, plexIn, dmAux = NULL, plexAux = NULL, tdm; 562 DMEnclosureType encIn, encAux; 563 PetscDS ds = NULL, dsIn = NULL, dsAux = NULL; 564 Vec localA = NULL, tv; 565 IS fieldIS; 566 PetscSection section; 567 PetscDualSpace *sp, *cellsp, *spIn, *cellspIn; 568 PetscTabulation *T = NULL, *TAux = NULL; 569 PetscInt *Nc; 570 PetscInt dim, dimEmbed, depth, htInc = 0, htIncIn = 0, htIncAux = 0, minHeight, maxHeight, h, regionNum, Nf, NfIn, NfAux = 0, NfTot, f; 571 PetscBool *isFE, hasFE = PETSC_FALSE, hasFV = PETSC_FALSE, isCohesive = PETSC_FALSE, transform; 572 DMField coordField; 573 DMLabel depthLabel; 574 PetscQuadrature allPoints = NULL; 575 PetscErrorCode ierr; 576 577 PetscFunctionBegin; 578 if (localU) CHKERRQ(VecGetDM(localU, &dmIn)); 579 else {dmIn = dm;} 580 CHKERRQ(DMGetAuxiliaryVec(dm, label, numIds ? ids[0] : 0, 0, &localA)); 581 if (localA) CHKERRQ(VecGetDM(localA, &dmAux)); else {dmAux = NULL;} 582 CHKERRQ(DMConvert(dm, DMPLEX, &plex)); 583 CHKERRQ(DMConvert(dmIn, DMPLEX, &plexIn)); 584 CHKERRQ(DMGetEnclosureRelation(dmIn, dm, &encIn)); 585 CHKERRQ(DMGetEnclosureRelation(dmAux, dm, &encAux)); 586 CHKERRQ(DMGetDimension(dm, &dim)); 587 CHKERRQ(DMPlexGetVTKCellHeight(plex, &minHeight)); 588 CHKERRQ(DMGetBasisTransformDM_Internal(dm, &tdm)); 589 CHKERRQ(DMGetBasisTransformVec_Internal(dm, &tv)); 590 CHKERRQ(DMHasBasisTransform(dm, &transform)); 591 /* Auxiliary information can only be used with interpolation of field functions */ 592 if (dmAux) { 593 CHKERRQ(DMConvert(dmAux, DMPLEX, &plexAux)); 594 if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_ESSENTIAL_BD_FIELD || type == DM_BC_NATURAL_FIELD) { 595 PetscCheck(localA,PETSC_COMM_SELF, PETSC_ERR_USER, "Missing localA vector"); 596 } 597 } 598 /* Determine height for iteration of all meshes */ 599 { 600 DMPolytopeType ct, ctIn, ctAux; 601 PetscInt minHeightIn, minHeightAux, lStart, pStart, pEnd, p, pStartIn, pStartAux; 602 PetscInt dim = -1, dimIn, dimAux; 603 604 CHKERRQ(DMPlexGetSimplexOrBoxCells(plex, minHeight, &pStart, &pEnd)); 605 if (pEnd > pStart) { 606 CHKERRQ(DMGetFirstLabeledPoint(dm, dm, label, numIds, ids, minHeight, &lStart, NULL)); 607 p = lStart < 0 ? pStart : lStart; 608 CHKERRQ(DMPlexGetCellType(plex, p, &ct)); 609 dim = DMPolytopeTypeGetDim(ct); 610 CHKERRQ(DMPlexGetVTKCellHeight(plexIn, &minHeightIn)); 611 CHKERRQ(DMPlexGetSimplexOrBoxCells(plexIn, minHeightIn, &pStartIn, NULL)); 612 CHKERRQ(DMPlexGetCellType(plexIn, pStartIn, &ctIn)); 613 dimIn = DMPolytopeTypeGetDim(ctIn); 614 if (dmAux) { 615 CHKERRQ(DMPlexGetVTKCellHeight(plexAux, &minHeightAux)); 616 CHKERRQ(DMPlexGetSimplexOrBoxCells(plexAux, minHeightAux, &pStartAux, NULL)); 617 CHKERRQ(DMPlexGetCellType(plexAux, pStartAux, &ctAux)); 618 dimAux = DMPolytopeTypeGetDim(ctAux); 619 } else dimAux = dim; 620 } 621 if (dim < 0) { 622 DMLabel spmap = NULL, spmapIn = NULL, spmapAux = NULL; 623 624 /* Fall back to determination based on being a submesh */ 625 CHKERRQ(DMPlexGetSubpointMap(plex, &spmap)); 626 CHKERRQ(DMPlexGetSubpointMap(plexIn, &spmapIn)); 627 if (plexAux) CHKERRQ(DMPlexGetSubpointMap(plexAux, &spmapAux)); 628 dim = spmap ? 1 : 0; 629 dimIn = spmapIn ? 1 : 0; 630 dimAux = spmapAux ? 1 : 0; 631 } 632 { 633 PetscInt dimProj = PetscMin(PetscMin(dim, dimIn), dimAux); 634 635 PetscCheckFalse(PetscAbsInt(dimProj - dim) > 1 || PetscAbsInt(dimProj - dimIn) > 1 || PetscAbsInt(dimProj - dimAux) > 1,PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not currently support differences of more than 1 in dimension"); 636 if (dimProj < dim) minHeight = 1; 637 htInc = dim - dimProj; 638 htIncIn = dimIn - dimProj; 639 htIncAux = dimAux - dimProj; 640 } 641 } 642 CHKERRQ(DMPlexGetDepth(plex, &depth)); 643 CHKERRQ(DMPlexGetDepthLabel(plex, &depthLabel)); 644 CHKERRQ(DMPlexGetMaxProjectionHeight(plex, &maxHeight)); 645 maxHeight = PetscMax(maxHeight, minHeight); 646 PetscCheck(maxHeight >= 0 && maxHeight <= dim,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Maximum projection height %D not in [0, %D)", maxHeight, dim); 647 CHKERRQ(DMGetFirstLabeledPoint(dm, dm, label, numIds, ids, 0, NULL, &ds)); 648 if (!ds) CHKERRQ(DMGetDS(dm, &ds)); 649 CHKERRQ(DMGetFirstLabeledPoint(dmIn, dm, label, numIds, ids, 0, NULL, &dsIn)); 650 if (!dsIn) CHKERRQ(DMGetDS(dmIn, &dsIn)); 651 CHKERRQ(PetscDSGetNumFields(ds, &Nf)); 652 CHKERRQ(PetscDSGetNumFields(dsIn, &NfIn)); 653 CHKERRQ(DMGetNumFields(dm, &NfTot)); 654 CHKERRQ(DMFindRegionNum(dm, ds, ®ionNum)); 655 CHKERRQ(DMGetRegionNumDS(dm, regionNum, NULL, &fieldIS, NULL)); 656 CHKERRQ(PetscDSIsCohesive(ds, &isCohesive)); 657 CHKERRQ(DMGetCoordinateDim(dm, &dimEmbed)); 658 CHKERRQ(DMGetLocalSection(dm, §ion)); 659 if (dmAux) { 660 CHKERRQ(DMGetDS(dmAux, &dsAux)); 661 CHKERRQ(PetscDSGetNumFields(dsAux, &NfAux)); 662 } 663 CHKERRQ(PetscDSGetComponents(ds, &Nc)); 664 CHKERRQ(PetscMalloc3(Nf, &isFE, Nf, &sp, NfIn, &spIn)); 665 if (maxHeight > 0) CHKERRQ(PetscMalloc2(Nf, &cellsp, NfIn, &cellspIn)); 666 else {cellsp = sp; cellspIn = spIn;} 667 if (localU && localU != localX) CHKERRQ(DMPlexInsertBoundaryValues(plex, PETSC_TRUE, localU, time, NULL, NULL, NULL)); 668 /* Get cell dual spaces */ 669 for (f = 0; f < Nf; ++f) { 670 PetscDiscType disctype; 671 672 CHKERRQ(PetscDSGetDiscType_Internal(ds, f, &disctype)); 673 if (disctype == PETSC_DISC_FE) { 674 PetscFE fe; 675 676 isFE[f] = PETSC_TRUE; 677 hasFE = PETSC_TRUE; 678 CHKERRQ(PetscDSGetDiscretization(ds, f, (PetscObject *) &fe)); 679 CHKERRQ(PetscFEGetDualSpace(fe, &cellsp[f])); 680 } else if (disctype == PETSC_DISC_FV) { 681 PetscFV fv; 682 683 isFE[f] = PETSC_FALSE; 684 hasFV = PETSC_TRUE; 685 CHKERRQ(PetscDSGetDiscretization(ds, f, (PetscObject *) &fv)); 686 CHKERRQ(PetscFVGetDualSpace(fv, &cellsp[f])); 687 } else { 688 isFE[f] = PETSC_FALSE; 689 cellsp[f] = NULL; 690 } 691 } 692 for (f = 0; f < NfIn; ++f) { 693 PetscDiscType disctype; 694 695 CHKERRQ(PetscDSGetDiscType_Internal(dsIn, f, &disctype)); 696 if (disctype == PETSC_DISC_FE) { 697 PetscFE fe; 698 699 CHKERRQ(PetscDSGetDiscretization(dsIn, f, (PetscObject *) &fe)); 700 CHKERRQ(PetscFEGetDualSpace(fe, &cellspIn[f])); 701 } else if (disctype == PETSC_DISC_FV) { 702 PetscFV fv; 703 704 CHKERRQ(PetscDSGetDiscretization(dsIn, f, (PetscObject *) &fv)); 705 CHKERRQ(PetscFVGetDualSpace(fv, &cellspIn[f])); 706 } else { 707 cellspIn[f] = NULL; 708 } 709 } 710 CHKERRQ(DMGetCoordinateField(dm,&coordField)); 711 for (f = 0; f < Nf; ++f) { 712 if (!htInc) {sp[f] = cellsp[f];} 713 else CHKERRQ(PetscDualSpaceGetHeightSubspace(cellsp[f], htInc, &sp[f])); 714 } 715 if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_ESSENTIAL_BD_FIELD || type == DM_BC_NATURAL_FIELD) { 716 PetscFE fem, subfem; 717 PetscDiscType disctype; 718 const PetscReal *points; 719 PetscInt numPoints; 720 721 PetscCheckFalse(maxHeight > minHeight,PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Field projection not supported for face interpolation"); 722 CHKERRQ(PetscDualSpaceGetAllPointsUnion(Nf, sp, dim-htInc, funcs, &allPoints)); 723 CHKERRQ(PetscQuadratureGetData(allPoints, NULL, NULL, &numPoints, &points, NULL)); 724 CHKERRQ(PetscMalloc2(NfIn, &T, NfAux, &TAux)); 725 for (f = 0; f < NfIn; ++f) { 726 if (!htIncIn) {spIn[f] = cellspIn[f];} 727 else CHKERRQ(PetscDualSpaceGetHeightSubspace(cellspIn[f], htIncIn, &spIn[f])); 728 729 CHKERRQ(PetscDSGetDiscType_Internal(dsIn, f, &disctype)); 730 if (disctype != PETSC_DISC_FE) continue; 731 CHKERRQ(PetscDSGetDiscretization(dsIn, f, (PetscObject *) &fem)); 732 if (!htIncIn) {subfem = fem;} 733 else CHKERRQ(PetscFEGetHeightSubspace(fem, htIncIn, &subfem)); 734 CHKERRQ(PetscFECreateTabulation(subfem, 1, numPoints, points, 1, &T[f])); 735 } 736 for (f = 0; f < NfAux; ++f) { 737 CHKERRQ(PetscDSGetDiscType_Internal(dsAux, f, &disctype)); 738 if (disctype != PETSC_DISC_FE) continue; 739 CHKERRQ(PetscDSGetDiscretization(dsAux, f, (PetscObject *) &fem)); 740 if (!htIncAux) {subfem = fem;} 741 else CHKERRQ(PetscFEGetHeightSubspace(fem, htIncAux, &subfem)); 742 CHKERRQ(PetscFECreateTabulation(subfem, 1, numPoints, points, 1, &TAux[f])); 743 } 744 } 745 /* Note: We make no attempt to optimize for height. Higher height things just overwrite the lower height results. */ 746 for (h = minHeight; h <= maxHeight; h++) { 747 PetscInt hEff = h - minHeight + htInc; 748 PetscInt hEffIn = h - minHeight + htIncIn; 749 PetscInt hEffAux = h - minHeight + htIncAux; 750 PetscDS dsEff = ds; 751 PetscDS dsEffIn = dsIn; 752 PetscDS dsEffAux = dsAux; 753 PetscScalar *values; 754 PetscBool *fieldActive; 755 PetscInt maxDegree; 756 PetscInt pStart, pEnd, p, lStart, spDim, totDim, numValues; 757 IS heightIS; 758 759 if (h > minHeight) { 760 for (f = 0; f < Nf; ++f) CHKERRQ(PetscDualSpaceGetHeightSubspace(cellsp[f], hEff, &sp[f])); 761 } 762 CHKERRQ(DMPlexGetSimplexOrBoxCells(plex, h, &pStart, &pEnd)); 763 CHKERRQ(DMGetFirstLabeledPoint(dm, dm, label, numIds, ids, h, &lStart, NULL)); 764 CHKERRQ(DMLabelGetStratumIS(depthLabel, depth - h, &heightIS)); 765 if (pEnd <= pStart) { 766 CHKERRQ(ISDestroy(&heightIS)); 767 continue; 768 } 769 /* Compute totDim, the number of dofs in the closure of a point at this height */ 770 totDim = 0; 771 for (f = 0; f < Nf; ++f) { 772 PetscBool cohesive; 773 774 if (!sp[f]) continue; 775 CHKERRQ(PetscDSGetCohesive(ds, f, &cohesive)); 776 CHKERRQ(PetscDualSpaceGetDimension(sp[f], &spDim)); 777 totDim += spDim; 778 if (isCohesive && !cohesive) totDim += spDim; 779 } 780 p = lStart < 0 ? pStart : lStart; 781 CHKERRQ(DMPlexVecGetClosure(plex, section, localX, p, &numValues, NULL)); 782 PetscCheckFalse(numValues != totDim,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The output section point (%D) closure size %D != dual space dimension %D at height %D in [%D, %D]", p, numValues, totDim, h, minHeight, maxHeight); 783 if (!totDim) { 784 CHKERRQ(ISDestroy(&heightIS)); 785 continue; 786 } 787 if (htInc) CHKERRQ(PetscDSGetHeightSubspace(ds, hEff, &dsEff)); 788 /* Compute totDimIn, the number of dofs in the closure of a point at this height */ 789 if (localU) { 790 PetscInt totDimIn, pIn, numValuesIn; 791 792 totDimIn = 0; 793 for (f = 0; f < NfIn; ++f) { 794 PetscBool cohesive; 795 796 if (!spIn[f]) continue; 797 CHKERRQ(PetscDSGetCohesive(dsIn, f, &cohesive)); 798 CHKERRQ(PetscDualSpaceGetDimension(spIn[f], &spDim)); 799 totDimIn += spDim; 800 if (isCohesive && !cohesive) totDimIn += spDim; 801 } 802 CHKERRQ(DMGetEnclosurePoint(dmIn, dm, encIn, lStart < 0 ? pStart : lStart, &pIn)); 803 CHKERRQ(DMPlexVecGetClosure(plexIn, NULL, localU, pIn, &numValuesIn, NULL)); 804 PetscCheckFalse(numValuesIn != totDimIn,PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "The input section point (%D) closure size %D != dual space dimension %D at height %D", pIn, numValuesIn, totDimIn, htIncIn); 805 if (htIncIn) CHKERRQ(PetscDSGetHeightSubspace(dsIn, hEffIn, &dsEffIn)); 806 } 807 if (htIncAux) CHKERRQ(PetscDSGetHeightSubspace(dsAux, hEffAux, &dsEffAux)); 808 /* Loop over points at this height */ 809 CHKERRQ(DMGetWorkArray(dm, numValues, MPIU_SCALAR, &values)); 810 CHKERRQ(DMGetWorkArray(dm, NfTot, MPI_INT, &fieldActive)); 811 { 812 const PetscInt *fields; 813 814 CHKERRQ(ISGetIndices(fieldIS, &fields)); 815 for (f = 0; f < NfTot; ++f) {fieldActive[f] = PETSC_FALSE;} 816 for (f = 0; f < Nf; ++f) {fieldActive[fields[f]] = (funcs[f] && sp[f]) ? PETSC_TRUE : PETSC_FALSE;} 817 CHKERRQ(ISRestoreIndices(fieldIS, &fields)); 818 } 819 if (label) { 820 PetscInt i; 821 822 for (i = 0; i < numIds; ++i) { 823 IS pointIS, isectIS; 824 const PetscInt *points; 825 PetscInt n; 826 PetscFEGeom *fegeom = NULL, *chunkgeom = NULL; 827 PetscQuadrature quad = NULL; 828 829 CHKERRQ(DMLabelGetStratumIS(label, ids[i], &pointIS)); 830 if (!pointIS) continue; /* No points with that id on this process */ 831 CHKERRQ(ISIntersect(pointIS,heightIS,&isectIS)); 832 CHKERRQ(ISDestroy(&pointIS)); 833 if (!isectIS) continue; 834 CHKERRQ(ISGetLocalSize(isectIS, &n)); 835 CHKERRQ(ISGetIndices(isectIS, &points)); 836 CHKERRQ(DMFieldGetDegree(coordField,isectIS,NULL,&maxDegree)); 837 if (maxDegree <= 1) { 838 CHKERRQ(DMFieldCreateDefaultQuadrature(coordField,isectIS,&quad)); 839 } 840 if (!quad) { 841 if (!h && allPoints) { 842 quad = allPoints; 843 allPoints = NULL; 844 } else { 845 CHKERRQ(PetscDualSpaceGetAllPointsUnion(Nf,sp,isCohesive ? dim-htInc-1 : dim-htInc,funcs,&quad)); 846 } 847 } 848 CHKERRQ(DMFieldCreateFEGeom(coordField, isectIS, quad, (htInc && h == minHeight) ? PETSC_TRUE : PETSC_FALSE, &fegeom)); 849 for (p = 0; p < n; ++p) { 850 const PetscInt point = points[p]; 851 852 CHKERRQ(PetscArrayzero(values, numValues)); 853 CHKERRQ(PetscFEGeomGetChunk(fegeom,p,p+1,&chunkgeom)); 854 CHKERRQ(DMPlexSetActivePoint(dm, point)); 855 ierr = DMProjectPoint_Private(dm, dsEff, plexIn, encIn, dsEffIn, plexAux, encAux, dsEffAux, chunkgeom, htInc, time, localU, localA, hasFE, hasFV, isFE, sp, point, T, TAux, type, funcs, ctxs, fieldActive, values); 856 if (ierr) { 857 CHKERRQ(DMRestoreWorkArray(dm, numValues, MPIU_SCALAR, &values)); 858 CHKERRQ(DMRestoreWorkArray(dm, Nf, MPI_INT, &fieldActive)); 859 CHKERRQ(ierr); 860 } 861 if (transform) CHKERRQ(DMPlexBasisTransformPoint_Internal(plex, tdm, tv, point, fieldActive, PETSC_FALSE, values)); 862 CHKERRQ(DMPlexVecSetFieldClosure_Internal(plex, section, localX, fieldActive, point, Ncc, comps, label, ids[i], values, mode)); 863 } 864 CHKERRQ(PetscFEGeomRestoreChunk(fegeom,p,p+1,&chunkgeom)); 865 CHKERRQ(PetscFEGeomDestroy(&fegeom)); 866 CHKERRQ(PetscQuadratureDestroy(&quad)); 867 CHKERRQ(ISRestoreIndices(isectIS, &points)); 868 CHKERRQ(ISDestroy(&isectIS)); 869 } 870 } else { 871 PetscFEGeom *fegeom = NULL, *chunkgeom = NULL; 872 PetscQuadrature quad = NULL; 873 IS pointIS; 874 875 CHKERRQ(ISCreateStride(PETSC_COMM_SELF,pEnd-pStart,pStart,1,&pointIS)); 876 CHKERRQ(DMFieldGetDegree(coordField,pointIS,NULL,&maxDegree)); 877 if (maxDegree <= 1) { 878 CHKERRQ(DMFieldCreateDefaultQuadrature(coordField,pointIS,&quad)); 879 } 880 if (!quad) { 881 if (!h && allPoints) { 882 quad = allPoints; 883 allPoints = NULL; 884 } else { 885 CHKERRQ(PetscDualSpaceGetAllPointsUnion(Nf, sp, dim-htInc, funcs, &quad)); 886 } 887 } 888 CHKERRQ(DMFieldCreateFEGeom(coordField, pointIS, quad, (htInc && h == minHeight) ? PETSC_TRUE : PETSC_FALSE, &fegeom)); 889 for (p = pStart; p < pEnd; ++p) { 890 CHKERRQ(PetscArrayzero(values, numValues)); 891 CHKERRQ(PetscFEGeomGetChunk(fegeom,p-pStart,p-pStart+1,&chunkgeom)); 892 CHKERRQ(DMPlexSetActivePoint(dm, p)); 893 ierr = DMProjectPoint_Private(dm, dsEff, plexIn, encIn, dsEffIn, plexAux, encAux, dsEffAux, chunkgeom, htInc, time, localU, localA, hasFE, hasFV, isFE, sp, p, T, TAux, type, funcs, ctxs, fieldActive, values); 894 if (ierr) { 895 CHKERRQ(DMRestoreWorkArray(dm, numValues, MPIU_SCALAR, &values)); 896 CHKERRQ(DMRestoreWorkArray(dm, Nf, MPI_INT, &fieldActive)); 897 CHKERRQ(ierr); 898 } 899 if (transform) CHKERRQ(DMPlexBasisTransformPoint_Internal(plex, tdm, tv, p, fieldActive, PETSC_FALSE, values)); 900 CHKERRQ(DMPlexVecSetFieldClosure_Internal(plex, section, localX, fieldActive, p, Ncc, comps, NULL, -1, values, mode)); 901 } 902 CHKERRQ(PetscFEGeomRestoreChunk(fegeom,p-pStart,pStart-p+1,&chunkgeom)); 903 CHKERRQ(PetscFEGeomDestroy(&fegeom)); 904 CHKERRQ(PetscQuadratureDestroy(&quad)); 905 CHKERRQ(ISDestroy(&pointIS)); 906 } 907 CHKERRQ(ISDestroy(&heightIS)); 908 CHKERRQ(DMRestoreWorkArray(dm, numValues, MPIU_SCALAR, &values)); 909 CHKERRQ(DMRestoreWorkArray(dm, Nf, MPI_INT, &fieldActive)); 910 } 911 /* Cleanup */ 912 if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_ESSENTIAL_BD_FIELD || type == DM_BC_NATURAL_FIELD) { 913 for (f = 0; f < NfIn; ++f) CHKERRQ(PetscTabulationDestroy(&T[f])); 914 for (f = 0; f < NfAux; ++f) CHKERRQ(PetscTabulationDestroy(&TAux[f])); 915 CHKERRQ(PetscFree2(T, TAux)); 916 } 917 CHKERRQ(PetscQuadratureDestroy(&allPoints)); 918 CHKERRQ(PetscFree3(isFE, sp, spIn)); 919 if (maxHeight > 0) CHKERRQ(PetscFree2(cellsp, cellspIn)); 920 CHKERRQ(DMDestroy(&plex)); 921 CHKERRQ(DMDestroy(&plexIn)); 922 if (dmAux) CHKERRQ(DMDestroy(&plexAux)); 923 PetscFunctionReturn(0); 924 } 925 926 PetscErrorCode DMProjectFunctionLocal_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 927 { 928 PetscFunctionBegin; 929 CHKERRQ(DMProjectLocal_Generic_Plex(dm, time, NULL, 0, NULL, NULL, 0, NULL, DM_BC_ESSENTIAL, (void (**)(void)) funcs, ctxs, mode, localX)); 930 PetscFunctionReturn(0); 931 } 932 933 PetscErrorCode DMProjectFunctionLabelLocal_Plex(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Ncc, const PetscInt comps[], PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 934 { 935 PetscFunctionBegin; 936 CHKERRQ(DMProjectLocal_Generic_Plex(dm, time, NULL, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL, (void (**)(void)) funcs, ctxs, mode, localX)); 937 PetscFunctionReturn(0); 938 } 939 940 PetscErrorCode DMProjectFieldLocal_Plex(DM dm, PetscReal time, Vec localU, 941 void (**funcs)(PetscInt, PetscInt, PetscInt, 942 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 943 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 944 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 945 InsertMode mode, Vec localX) 946 { 947 PetscFunctionBegin; 948 CHKERRQ(DMProjectLocal_Generic_Plex(dm, time, localU, 0, NULL, NULL, 0, NULL, DM_BC_ESSENTIAL_FIELD, (void (**)(void)) funcs, NULL, mode, localX)); 949 PetscFunctionReturn(0); 950 } 951 952 PetscErrorCode DMProjectFieldLabelLocal_Plex(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Ncc, const PetscInt comps[], Vec localU, 953 void (**funcs)(PetscInt, PetscInt, PetscInt, 954 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 955 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 956 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 957 InsertMode mode, Vec localX) 958 { 959 PetscFunctionBegin; 960 CHKERRQ(DMProjectLocal_Generic_Plex(dm, time, localU, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL_FIELD, (void (**)(void)) funcs, NULL, mode, localX)); 961 PetscFunctionReturn(0); 962 } 963 964 PetscErrorCode DMProjectBdFieldLabelLocal_Plex(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Ncc, const PetscInt comps[], Vec localU, 965 void (**funcs)(PetscInt, PetscInt, PetscInt, 966 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 967 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 968 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 969 InsertMode mode, Vec localX) 970 { 971 PetscFunctionBegin; 972 CHKERRQ(DMProjectLocal_Generic_Plex(dm, time, localU, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL_BD_FIELD, (void (**)(void)) funcs, NULL, mode, localX)); 973 PetscFunctionReturn(0); 974 } 975