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 SETERRQ2(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 if (dm != dmIn) SETERRQ(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: SETERRQ1(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 if (qdim != dim) SETERRQ2(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 static PetscErrorCode DMGetFirstLabelEntry_Private(DM dm, DM odm, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt height, PetscInt *lStart, PetscDS *ds) 470 { 471 DM plex; 472 DMEnclosureType enc; 473 DMLabel depthLabel; 474 PetscInt dim, cdepth, ls = -1, i; 475 PetscErrorCode ierr; 476 477 PetscFunctionBegin; 478 if (lStart) *lStart = -1; 479 if (!label) PetscFunctionReturn(0); 480 ierr = DMGetEnclosureRelation(dm, odm, &enc);CHKERRQ(ierr); 481 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 482 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 483 ierr = DMPlexGetDepthLabel(plex, &depthLabel);CHKERRQ(ierr); 484 cdepth = dim - height; 485 for (i = 0; i < numIds; ++i) { 486 IS pointIS; 487 const PetscInt *points; 488 PetscInt pdepth, point; 489 490 ierr = DMLabelGetStratumIS(label, ids[i], &pointIS);CHKERRQ(ierr); 491 if (!pointIS) continue; /* No points with that id on this process */ 492 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 493 ierr = DMGetEnclosurePoint(dm, odm, enc, points[0], &point);CHKERRQ(ierr); 494 ierr = DMLabelGetValue(depthLabel, point, &pdepth);CHKERRQ(ierr); 495 if (pdepth == cdepth) { 496 ls = point; 497 if (ds) {ierr = DMGetCellDS(dm, ls, ds);CHKERRQ(ierr);} 498 } 499 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 500 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 501 if (ls >= 0) break; 502 } 503 if (lStart) *lStart = ls; 504 ierr = DMDestroy(&plex);CHKERRQ(ierr); 505 PetscFunctionReturn(0); 506 } 507 508 /* 509 This function iterates over a manifold, and interpolates the input function/field using the basis provided by the DS in our DM 510 511 There are several different scenarios: 512 513 1) Volumetric mesh with volumetric auxiliary data 514 515 Here minHeight=0 since we loop over cells. 516 517 2) Boundary mesh with boundary auxiliary data 518 519 Here minHeight=1 since we loop over faces. This normally happens since we hang cells off of our boundary meshes to facilitate computation. 520 521 3) Volumetric mesh with boundary auxiliary data 522 523 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. 524 525 4) Volumetric input mesh with boundary output mesh 526 527 Here we must get a subspace for the input DS 528 529 The maxHeight is used to support enforcement of constraints in DMForest. 530 531 If localU is given and not equal to localX, we call DMPlexInsertBoundaryValues() to complete it. 532 533 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. 534 - 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 535 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 536 dual spaces for the boundary from our input spaces. 537 - After extracting all quadrature points, we tabulate the input fields and auxiliary fields on them. 538 539 We check that the #dof(closure(p)) == #dual basis functionals(p) for a representative p in the iteration 540 541 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. 542 */ 543 static PetscErrorCode DMProjectLocal_Generic_Plex(DM dm, PetscReal time, Vec localU, 544 PetscInt Ncc, const PetscInt comps[], DMLabel label, PetscInt numIds, const PetscInt ids[], 545 DMBoundaryConditionType type, void (**funcs)(void), void **ctxs, 546 InsertMode mode, Vec localX) 547 { 548 DM plex, dmIn, plexIn, dmAux = NULL, plexAux = NULL, tdm; 549 DMEnclosureType encIn, encAux; 550 PetscDS ds = NULL, dsIn = NULL, dsAux = NULL; 551 Vec localA = NULL, tv; 552 IS fieldIS; 553 PetscSection section; 554 PetscDualSpace *sp, *cellsp, *spIn, *cellspIn; 555 PetscTabulation *T = NULL, *TAux = NULL; 556 PetscInt *Nc; 557 PetscInt dim, dimEmbed, depth, htInc = 0, htIncIn = 0, htIncAux = 0, minHeight, maxHeight, h, regionNum, Nf, NfIn, NfAux = 0, NfTot, f; 558 PetscBool *isFE, hasFE = PETSC_FALSE, hasFV = PETSC_FALSE, isCohesive = PETSC_FALSE, transform; 559 DMField coordField; 560 DMLabel depthLabel; 561 PetscQuadrature allPoints = NULL; 562 PetscErrorCode ierr; 563 564 PetscFunctionBegin; 565 if (localU) {ierr = VecGetDM(localU, &dmIn);CHKERRQ(ierr);} 566 else {dmIn = dm;} 567 ierr = DMGetAuxiliaryVec(dm, label, numIds ? ids[0] : 0, &localA);CHKERRQ(ierr); 568 if (localA) {ierr = VecGetDM(localA, &dmAux);CHKERRQ(ierr);} else {dmAux = NULL;} 569 ierr = DMConvert(dm, DMPLEX, &plex);CHKERRQ(ierr); 570 ierr = DMConvert(dmIn, DMPLEX, &plexIn);CHKERRQ(ierr); 571 ierr = DMGetEnclosureRelation(dmIn, dm, &encIn);CHKERRQ(ierr); 572 ierr = DMGetEnclosureRelation(dmAux, dm, &encAux);CHKERRQ(ierr); 573 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 574 ierr = DMPlexGetVTKCellHeight(plex, &minHeight);CHKERRQ(ierr); 575 ierr = DMGetBasisTransformDM_Internal(dm, &tdm);CHKERRQ(ierr); 576 ierr = DMGetBasisTransformVec_Internal(dm, &tv);CHKERRQ(ierr); 577 ierr = DMHasBasisTransform(dm, &transform);CHKERRQ(ierr); 578 /* Auxiliary information can only be used with interpolation of field functions */ 579 if (dmAux) { 580 ierr = DMConvert(dmAux, DMPLEX, &plexAux);CHKERRQ(ierr); 581 if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_ESSENTIAL_BD_FIELD || type == DM_BC_NATURAL_FIELD) { 582 if (!localA) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Missing localA vector"); 583 } 584 } 585 /* Determine height for iteration of all meshes */ 586 { 587 DMPolytopeType ct, ctIn, ctAux; 588 PetscInt minHeightIn, minHeightAux, lStart, pStart, pEnd, p, pStartIn, pStartAux; 589 PetscInt dim = -1, dimIn, dimAux; 590 591 ierr = DMPlexGetSimplexOrBoxCells(plex, minHeight, &pStart, &pEnd);CHKERRQ(ierr); 592 if (pEnd > pStart) { 593 ierr = DMGetFirstLabelEntry_Private(dm, dm, label, numIds, ids, minHeight, &lStart, NULL);CHKERRQ(ierr); 594 p = lStart < 0 ? pStart : lStart; 595 ierr = DMPlexGetCellType(plex, p, &ct);CHKERRQ(ierr); 596 dim = DMPolytopeTypeGetDim(ct); 597 ierr = DMPlexGetVTKCellHeight(plexIn, &minHeightIn);CHKERRQ(ierr); 598 ierr = DMPlexGetSimplexOrBoxCells(plexIn, minHeightIn, &pStartIn, NULL);CHKERRQ(ierr); 599 ierr = DMPlexGetCellType(plexIn, pStartIn, &ctIn);CHKERRQ(ierr); 600 dimIn = DMPolytopeTypeGetDim(ctIn); 601 if (dmAux) { 602 ierr = DMPlexGetVTKCellHeight(plexAux, &minHeightAux);CHKERRQ(ierr); 603 ierr = DMPlexGetSimplexOrBoxCells(plexAux, minHeightAux, &pStartAux, NULL);CHKERRQ(ierr); 604 ierr = DMPlexGetCellType(plexAux, pStartAux, &ctAux);CHKERRQ(ierr); 605 dimAux = DMPolytopeTypeGetDim(ctAux); 606 } else dimAux = dim; 607 } 608 if (dim < 0) { 609 DMLabel spmap = NULL, spmapIn = NULL, spmapAux = NULL; 610 611 /* Fall back to determination based on being a submesh */ 612 ierr = DMPlexGetSubpointMap(plex, &spmap);CHKERRQ(ierr); 613 ierr = DMPlexGetSubpointMap(plexIn, &spmapIn);CHKERRQ(ierr); 614 if (plexAux) {ierr = DMPlexGetSubpointMap(plexAux, &spmapAux);CHKERRQ(ierr);} 615 dim = spmap ? 1 : 0; 616 dimIn = spmapIn ? 1 : 0; 617 dimAux = spmapAux ? 1 : 0; 618 } 619 { 620 PetscInt dimProj = PetscMin(PetscMin(dim, dimIn), dimAux); 621 622 if (PetscAbsInt(dimProj - dim) > 1 || PetscAbsInt(dimProj - dimIn) > 1 || PetscAbsInt(dimProj - dimAux) > 1) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Do not currently support differences of more than 1 in dimension"); 623 if (dimProj < dim) minHeight = 1; 624 htInc = dim - dimProj; 625 htIncIn = dimIn - dimProj; 626 htIncAux = dimAux - dimProj; 627 } 628 } 629 ierr = DMPlexGetDepth(plex, &depth);CHKERRQ(ierr); 630 ierr = DMPlexGetDepthLabel(plex, &depthLabel);CHKERRQ(ierr); 631 ierr = DMPlexGetMaxProjectionHeight(plex, &maxHeight);CHKERRQ(ierr); 632 maxHeight = PetscMax(maxHeight, minHeight); 633 if (maxHeight < 0 || maxHeight > dim) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Maximum projection height %D not in [0, %D)", maxHeight, dim); 634 ierr = DMGetFirstLabelEntry_Private(dm, dm, label, numIds, ids, 0, NULL, &ds);CHKERRQ(ierr); 635 if (!ds) {ierr = DMGetDS(dm, &ds);CHKERRQ(ierr);} 636 ierr = DMGetFirstLabelEntry_Private(dmIn, dm, label, numIds, ids, 0, NULL, &dsIn);CHKERRQ(ierr); 637 if (!dsIn) {ierr = DMGetDS(dmIn, &dsIn);CHKERRQ(ierr);} 638 ierr = PetscDSGetNumFields(ds, &Nf);CHKERRQ(ierr); 639 ierr = PetscDSGetNumFields(dsIn, &NfIn);CHKERRQ(ierr); 640 ierr = DMGetNumFields(dm, &NfTot);CHKERRQ(ierr); 641 ierr = DMFindRegionNum(dm, ds, ®ionNum);CHKERRQ(ierr); 642 ierr = DMGetRegionNumDS(dm, regionNum, NULL, &fieldIS, NULL);CHKERRQ(ierr); 643 ierr = PetscDSIsCohesive(ds, &isCohesive);CHKERRQ(ierr); 644 ierr = DMGetCoordinateDim(dm, &dimEmbed);CHKERRQ(ierr); 645 ierr = DMGetLocalSection(dm, §ion);CHKERRQ(ierr); 646 if (dmAux) { 647 ierr = DMGetDS(dmAux, &dsAux);CHKERRQ(ierr); 648 ierr = PetscDSGetNumFields(dsAux, &NfAux);CHKERRQ(ierr); 649 } 650 ierr = PetscDSGetComponents(ds, &Nc);CHKERRQ(ierr); 651 ierr = PetscMalloc3(Nf, &isFE, Nf, &sp, NfIn, &spIn);CHKERRQ(ierr); 652 if (maxHeight > 0) {ierr = PetscMalloc2(Nf, &cellsp, NfIn, &cellspIn);CHKERRQ(ierr);} 653 else {cellsp = sp; cellspIn = spIn;} 654 if (localU && localU != localX) {ierr = DMPlexInsertBoundaryValues(plex, PETSC_TRUE, localU, time, NULL, NULL, NULL);CHKERRQ(ierr);} 655 /* Get cell dual spaces */ 656 for (f = 0; f < Nf; ++f) { 657 PetscDiscType disctype; 658 659 ierr = PetscDSGetDiscType_Internal(ds, f, &disctype);CHKERRQ(ierr); 660 if (disctype == PETSC_DISC_FE) { 661 PetscFE fe; 662 663 isFE[f] = PETSC_TRUE; 664 hasFE = PETSC_TRUE; 665 ierr = PetscDSGetDiscretization(ds, f, (PetscObject *) &fe);CHKERRQ(ierr); 666 ierr = PetscFEGetDualSpace(fe, &cellsp[f]);CHKERRQ(ierr); 667 } else if (disctype == PETSC_DISC_FV) { 668 PetscFV fv; 669 670 isFE[f] = PETSC_FALSE; 671 hasFV = PETSC_TRUE; 672 ierr = PetscDSGetDiscretization(ds, f, (PetscObject *) &fv);CHKERRQ(ierr); 673 ierr = PetscFVGetDualSpace(fv, &cellsp[f]);CHKERRQ(ierr); 674 } else { 675 isFE[f] = PETSC_FALSE; 676 cellsp[f] = NULL; 677 } 678 } 679 for (f = 0; f < NfIn; ++f) { 680 PetscDiscType disctype; 681 682 ierr = PetscDSGetDiscType_Internal(dsIn, f, &disctype);CHKERRQ(ierr); 683 if (disctype == PETSC_DISC_FE) { 684 PetscFE fe; 685 686 ierr = PetscDSGetDiscretization(dsIn, f, (PetscObject *) &fe);CHKERRQ(ierr); 687 ierr = PetscFEGetDualSpace(fe, &cellspIn[f]);CHKERRQ(ierr); 688 } else if (disctype == PETSC_DISC_FV) { 689 PetscFV fv; 690 691 ierr = PetscDSGetDiscretization(dsIn, f, (PetscObject *) &fv);CHKERRQ(ierr); 692 ierr = PetscFVGetDualSpace(fv, &cellspIn[f]);CHKERRQ(ierr); 693 } else { 694 cellspIn[f] = NULL; 695 } 696 } 697 ierr = DMGetCoordinateField(dm,&coordField);CHKERRQ(ierr); 698 for (f = 0; f < Nf; ++f) { 699 if (!htInc) {sp[f] = cellsp[f];} 700 else {ierr = PetscDualSpaceGetHeightSubspace(cellsp[f], htInc, &sp[f]);CHKERRQ(ierr);} 701 } 702 if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_ESSENTIAL_BD_FIELD || type == DM_BC_NATURAL_FIELD) { 703 PetscFE fem, subfem; 704 PetscDiscType disctype; 705 const PetscReal *points; 706 PetscInt numPoints; 707 708 if (maxHeight > minHeight) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Field projection not supported for face interpolation"); 709 ierr = PetscDualSpaceGetAllPointsUnion(Nf, sp, dim-htInc, funcs, &allPoints);CHKERRQ(ierr); 710 ierr = PetscQuadratureGetData(allPoints, NULL, NULL, &numPoints, &points, NULL);CHKERRQ(ierr); 711 ierr = PetscMalloc2(NfIn, &T, NfAux, &TAux);CHKERRQ(ierr); 712 for (f = 0; f < NfIn; ++f) { 713 if (!htIncIn) {spIn[f] = cellspIn[f];} 714 else {ierr = PetscDualSpaceGetHeightSubspace(cellspIn[f], htIncIn, &spIn[f]);CHKERRQ(ierr);} 715 716 ierr = PetscDSGetDiscType_Internal(dsIn, f, &disctype);CHKERRQ(ierr); 717 if (disctype != PETSC_DISC_FE) continue; 718 ierr = PetscDSGetDiscretization(dsIn, f, (PetscObject *) &fem);CHKERRQ(ierr); 719 if (!htIncIn) {subfem = fem;} 720 else {ierr = PetscFEGetHeightSubspace(fem, htIncIn, &subfem);CHKERRQ(ierr);} 721 ierr = PetscFECreateTabulation(subfem, 1, numPoints, points, 1, &T[f]);CHKERRQ(ierr); 722 } 723 for (f = 0; f < NfAux; ++f) { 724 ierr = PetscDSGetDiscType_Internal(dsAux, f, &disctype);CHKERRQ(ierr); 725 if (disctype != PETSC_DISC_FE) continue; 726 ierr = PetscDSGetDiscretization(dsAux, f, (PetscObject *) &fem);CHKERRQ(ierr); 727 if (!htIncAux) {subfem = fem;} 728 else {ierr = PetscFEGetHeightSubspace(fem, htIncAux, &subfem);CHKERRQ(ierr);} 729 ierr = PetscFECreateTabulation(subfem, 1, numPoints, points, 1, &TAux[f]);CHKERRQ(ierr); 730 } 731 } 732 /* Note: We make no attempt to optimize for height. Higher height things just overwrite the lower height results. */ 733 for (h = minHeight; h <= maxHeight; h++) { 734 PetscInt hEff = h - minHeight + htInc; 735 PetscInt hEffIn = h - minHeight + htIncIn; 736 PetscInt hEffAux = h - minHeight + htIncAux; 737 PetscDS dsEff = ds; 738 PetscDS dsEffIn = dsIn; 739 PetscDS dsEffAux = dsAux; 740 PetscScalar *values; 741 PetscBool *fieldActive; 742 PetscInt maxDegree; 743 PetscInt pStart, pEnd, p, lStart, spDim, totDim, numValues; 744 IS heightIS; 745 746 if (h > minHeight) { 747 for (f = 0; f < Nf; ++f) {ierr = PetscDualSpaceGetHeightSubspace(cellsp[f], hEff, &sp[f]);CHKERRQ(ierr);} 748 } 749 ierr = DMPlexGetSimplexOrBoxCells(plex, h, &pStart, &pEnd);CHKERRQ(ierr); 750 ierr = DMGetFirstLabelEntry_Private(dm, dm, label, numIds, ids, h, &lStart, NULL);CHKERRQ(ierr); 751 ierr = DMLabelGetStratumIS(depthLabel, depth - h, &heightIS);CHKERRQ(ierr); 752 if (pEnd <= pStart) { 753 ierr = ISDestroy(&heightIS);CHKERRQ(ierr); 754 continue; 755 } 756 /* Compute totDim, the number of dofs in the closure of a point at this height */ 757 totDim = 0; 758 for (f = 0; f < Nf; ++f) { 759 PetscBool cohesive; 760 761 if (!sp[f]) continue; 762 ierr = PetscDSGetCohesive(ds, f, &cohesive);CHKERRQ(ierr); 763 ierr = PetscDualSpaceGetDimension(sp[f], &spDim);CHKERRQ(ierr); 764 totDim += spDim; 765 if (isCohesive && !cohesive) totDim += spDim; 766 } 767 p = lStart < 0 ? pStart : lStart; 768 ierr = DMPlexVecGetClosure(plex, section, localX, p, &numValues, NULL);CHKERRQ(ierr); 769 if (numValues != totDim) SETERRQ6(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); 770 if (!totDim) { 771 ierr = ISDestroy(&heightIS);CHKERRQ(ierr); 772 continue; 773 } 774 if (htInc) {ierr = PetscDSGetHeightSubspace(ds, hEff, &dsEff);CHKERRQ(ierr);} 775 /* Compute totDimIn, the number of dofs in the closure of a point at this height */ 776 if (localU) { 777 PetscInt totDimIn, pIn, numValuesIn; 778 779 totDimIn = 0; 780 for (f = 0; f < NfIn; ++f) { 781 PetscBool cohesive; 782 783 if (!spIn[f]) continue; 784 ierr = PetscDSGetCohesive(dsIn, f, &cohesive);CHKERRQ(ierr); 785 ierr = PetscDualSpaceGetDimension(spIn[f], &spDim);CHKERRQ(ierr); 786 totDimIn += spDim; 787 if (isCohesive && !cohesive) totDimIn += spDim; 788 } 789 ierr = DMGetEnclosurePoint(dmIn, dm, encIn, lStart < 0 ? pStart : lStart, &pIn);CHKERRQ(ierr); 790 ierr = DMPlexVecGetClosure(plexIn, NULL, localU, pIn, &numValuesIn, NULL);CHKERRQ(ierr); 791 if (numValuesIn != totDimIn) SETERRQ4(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); 792 if (htIncIn) {ierr = PetscDSGetHeightSubspace(dsIn, hEffIn, &dsEffIn);CHKERRQ(ierr);} 793 } 794 if (htIncAux) {ierr = PetscDSGetHeightSubspace(dsAux, hEffAux, &dsEffAux);CHKERRQ(ierr);} 795 /* Loop over points at this height */ 796 ierr = DMGetWorkArray(dm, numValues, MPIU_SCALAR, &values);CHKERRQ(ierr); 797 ierr = DMGetWorkArray(dm, NfTot, MPI_INT, &fieldActive);CHKERRQ(ierr); 798 { 799 const PetscInt *fields; 800 801 ierr = ISGetIndices(fieldIS, &fields);CHKERRQ(ierr); 802 for (f = 0; f < NfTot; ++f) {fieldActive[f] = PETSC_FALSE;} 803 for (f = 0; f < Nf; ++f) {fieldActive[fields[f]] = (funcs[f] && sp[f]) ? PETSC_TRUE : PETSC_FALSE;} 804 ierr = ISRestoreIndices(fieldIS, &fields);CHKERRQ(ierr); 805 } 806 if (label) { 807 PetscInt i; 808 809 for (i = 0; i < numIds; ++i) { 810 IS pointIS, isectIS; 811 const PetscInt *points; 812 PetscInt n; 813 PetscFEGeom *fegeom = NULL, *chunkgeom = NULL; 814 PetscQuadrature quad = NULL; 815 816 ierr = DMLabelGetStratumIS(label, ids[i], &pointIS);CHKERRQ(ierr); 817 if (!pointIS) continue; /* No points with that id on this process */ 818 ierr = ISIntersect(pointIS,heightIS,&isectIS);CHKERRQ(ierr); 819 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 820 if (!isectIS) continue; 821 ierr = ISGetLocalSize(isectIS, &n);CHKERRQ(ierr); 822 ierr = ISGetIndices(isectIS, &points);CHKERRQ(ierr); 823 ierr = DMFieldGetDegree(coordField,isectIS,NULL,&maxDegree);CHKERRQ(ierr); 824 if (maxDegree <= 1) { 825 ierr = DMFieldCreateDefaultQuadrature(coordField,isectIS,&quad);CHKERRQ(ierr); 826 } 827 if (!quad) { 828 if (!h && allPoints) { 829 quad = allPoints; 830 allPoints = NULL; 831 } else { 832 ierr = PetscDualSpaceGetAllPointsUnion(Nf,sp,isCohesive ? dim-htInc-1 : dim-htInc,funcs,&quad);CHKERRQ(ierr); 833 } 834 } 835 ierr = DMFieldCreateFEGeom(coordField, isectIS, quad, (htInc && h == minHeight) ? PETSC_TRUE : PETSC_FALSE, &fegeom);CHKERRQ(ierr); 836 for (p = 0; p < n; ++p) { 837 const PetscInt point = points[p]; 838 839 ierr = PetscArrayzero(values, numValues);CHKERRQ(ierr); 840 ierr = PetscFEGeomGetChunk(fegeom,p,p+1,&chunkgeom);CHKERRQ(ierr); 841 ierr = DMPlexSetActivePoint(dm, point);CHKERRQ(ierr); 842 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); 843 if (ierr) { 844 PetscErrorCode ierr2; 845 ierr2 = DMRestoreWorkArray(dm, numValues, MPIU_SCALAR, &values);CHKERRQ(ierr2); 846 ierr2 = DMRestoreWorkArray(dm, Nf, MPI_INT, &fieldActive);CHKERRQ(ierr2); 847 CHKERRQ(ierr); 848 } 849 if (transform) {ierr = DMPlexBasisTransformPoint_Internal(plex, tdm, tv, point, fieldActive, PETSC_FALSE, values);CHKERRQ(ierr);} 850 ierr = DMPlexVecSetFieldClosure_Internal(plex, section, localX, fieldActive, point, Ncc, comps, label, ids[i], values, mode);CHKERRQ(ierr); 851 } 852 ierr = PetscFEGeomRestoreChunk(fegeom,p,p+1,&chunkgeom);CHKERRQ(ierr); 853 ierr = PetscFEGeomDestroy(&fegeom);CHKERRQ(ierr); 854 ierr = PetscQuadratureDestroy(&quad);CHKERRQ(ierr); 855 ierr = ISRestoreIndices(isectIS, &points);CHKERRQ(ierr); 856 ierr = ISDestroy(&isectIS);CHKERRQ(ierr); 857 } 858 } else { 859 PetscFEGeom *fegeom = NULL, *chunkgeom = NULL; 860 PetscQuadrature quad = NULL; 861 IS pointIS; 862 863 ierr = ISCreateStride(PETSC_COMM_SELF,pEnd-pStart,pStart,1,&pointIS);CHKERRQ(ierr); 864 ierr = DMFieldGetDegree(coordField,pointIS,NULL,&maxDegree);CHKERRQ(ierr); 865 if (maxDegree <= 1) { 866 ierr = DMFieldCreateDefaultQuadrature(coordField,pointIS,&quad);CHKERRQ(ierr); 867 } 868 if (!quad) { 869 if (!h && allPoints) { 870 quad = allPoints; 871 allPoints = NULL; 872 } else { 873 ierr = PetscDualSpaceGetAllPointsUnion(Nf, sp, dim-htInc, funcs, &quad);CHKERRQ(ierr); 874 } 875 } 876 ierr = DMFieldCreateFEGeom(coordField, pointIS, quad, (htInc && h == minHeight) ? PETSC_TRUE : PETSC_FALSE, &fegeom);CHKERRQ(ierr); 877 for (p = pStart; p < pEnd; ++p) { 878 ierr = PetscArrayzero(values, numValues);CHKERRQ(ierr); 879 ierr = PetscFEGeomGetChunk(fegeom,p-pStart,p-pStart+1,&chunkgeom);CHKERRQ(ierr); 880 ierr = DMPlexSetActivePoint(dm, p);CHKERRQ(ierr); 881 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); 882 if (ierr) { 883 PetscErrorCode ierr2; 884 ierr2 = DMRestoreWorkArray(dm, numValues, MPIU_SCALAR, &values);CHKERRQ(ierr2); 885 ierr2 = DMRestoreWorkArray(dm, Nf, MPI_INT, &fieldActive);CHKERRQ(ierr2); 886 CHKERRQ(ierr); 887 } 888 if (transform) {ierr = DMPlexBasisTransformPoint_Internal(plex, tdm, tv, p, fieldActive, PETSC_FALSE, values);CHKERRQ(ierr);} 889 ierr = DMPlexVecSetFieldClosure_Internal(plex, section, localX, fieldActive, p, Ncc, comps, NULL, -1, values, mode);CHKERRQ(ierr); 890 } 891 ierr = PetscFEGeomRestoreChunk(fegeom,p-pStart,pStart-p+1,&chunkgeom);CHKERRQ(ierr); 892 ierr = PetscFEGeomDestroy(&fegeom);CHKERRQ(ierr); 893 ierr = PetscQuadratureDestroy(&quad);CHKERRQ(ierr); 894 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 895 } 896 ierr = ISDestroy(&heightIS);CHKERRQ(ierr); 897 ierr = DMRestoreWorkArray(dm, numValues, MPIU_SCALAR, &values);CHKERRQ(ierr); 898 ierr = DMRestoreWorkArray(dm, Nf, MPI_INT, &fieldActive);CHKERRQ(ierr); 899 } 900 /* Cleanup */ 901 if (type == DM_BC_ESSENTIAL_FIELD || type == DM_BC_ESSENTIAL_BD_FIELD || type == DM_BC_NATURAL_FIELD) { 902 for (f = 0; f < NfIn; ++f) {ierr = PetscTabulationDestroy(&T[f]);CHKERRQ(ierr);} 903 for (f = 0; f < NfAux; ++f) {ierr = PetscTabulationDestroy(&TAux[f]);CHKERRQ(ierr);} 904 ierr = PetscFree2(T, TAux);CHKERRQ(ierr); 905 } 906 ierr = PetscQuadratureDestroy(&allPoints);CHKERRQ(ierr); 907 ierr = PetscFree3(isFE, sp, spIn);CHKERRQ(ierr); 908 if (maxHeight > 0) {ierr = PetscFree2(cellsp, cellspIn);CHKERRQ(ierr);} 909 ierr = DMDestroy(&plex);CHKERRQ(ierr); 910 ierr = DMDestroy(&plexIn);CHKERRQ(ierr); 911 if (dmAux) {ierr = DMDestroy(&plexAux);CHKERRQ(ierr);} 912 PetscFunctionReturn(0); 913 } 914 915 PetscErrorCode DMProjectFunctionLocal_Plex(DM dm, PetscReal time, PetscErrorCode (**funcs)(PetscInt, PetscReal, const PetscReal [], PetscInt, PetscScalar *, void *), void **ctxs, InsertMode mode, Vec localX) 916 { 917 PetscErrorCode ierr; 918 919 PetscFunctionBegin; 920 ierr = DMProjectLocal_Generic_Plex(dm, time, NULL, 0, NULL, NULL, 0, NULL, DM_BC_ESSENTIAL, (void (**)(void)) funcs, ctxs, mode, localX);CHKERRQ(ierr); 921 PetscFunctionReturn(0); 922 } 923 924 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) 925 { 926 PetscErrorCode ierr; 927 928 PetscFunctionBegin; 929 ierr = DMProjectLocal_Generic_Plex(dm, time, NULL, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL, (void (**)(void)) funcs, ctxs, mode, localX);CHKERRQ(ierr); 930 PetscFunctionReturn(0); 931 } 932 933 PetscErrorCode DMProjectFieldLocal_Plex(DM dm, PetscReal time, Vec localU, 934 void (**funcs)(PetscInt, PetscInt, PetscInt, 935 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 936 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 937 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 938 InsertMode mode, Vec localX) 939 { 940 PetscErrorCode ierr; 941 942 PetscFunctionBegin; 943 ierr = DMProjectLocal_Generic_Plex(dm, time, localU, 0, NULL, NULL, 0, NULL, DM_BC_ESSENTIAL_FIELD, (void (**)(void)) funcs, NULL, mode, localX);CHKERRQ(ierr); 944 PetscFunctionReturn(0); 945 } 946 947 PetscErrorCode DMProjectFieldLabelLocal_Plex(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Ncc, const PetscInt comps[], Vec localU, 948 void (**funcs)(PetscInt, PetscInt, PetscInt, 949 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 950 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 951 PetscReal, const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 952 InsertMode mode, Vec localX) 953 { 954 PetscErrorCode ierr; 955 956 PetscFunctionBegin; 957 ierr = DMProjectLocal_Generic_Plex(dm, time, localU, Ncc, comps, label, numIds, ids, DM_BC_ESSENTIAL_FIELD, (void (**)(void)) funcs, NULL, mode, localX);CHKERRQ(ierr); 958 PetscFunctionReturn(0); 959 } 960 961 PetscErrorCode DMProjectBdFieldLabelLocal_Plex(DM dm, PetscReal time, DMLabel label, PetscInt numIds, const PetscInt ids[], PetscInt Ncc, const PetscInt comps[], Vec localU, 962 void (**funcs)(PetscInt, PetscInt, PetscInt, 963 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 964 const PetscInt[], const PetscInt[], const PetscScalar[], const PetscScalar[], const PetscScalar[], 965 PetscReal, const PetscReal[], const PetscReal[], PetscInt, const PetscScalar[], PetscScalar[]), 966 InsertMode mode, Vec localX) 967 { 968 PetscErrorCode ierr; 969 970 PetscFunctionBegin; 971 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); 972 PetscFunctionReturn(0); 973 } 974