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