The projection information for one target cell consists of a list of donor cell indices and a list of donor cell levels. The donor cell level stores the relative level between the donor cell and the target cell. With the donor cell index the position of the donor cell on its level relative to the cell is described, i.e. it is a scalar index instead of nDim-indices for all dimensions. Additionally, the non-mapped volumes are identified and added to the donorIds and donorLevels lists. This means that cells that are missing in the FV-solver since they are inside some geometric object are identified such that for these volumes default values for mapping data to a DG element can be used (without implicitly assuming them all to be zero when these volumes are not handled).
331 {
332 TRACE();
333
334
335
336 auto positionOnUnitElement = [](
MFloat pos,
MFloat center,
MFloat width) {
return 2 * (pos - center) / width; };
337
338
340
341 const MFloatTensor donorCellCoords(
const_cast<MFloat*
>(donorCellCoordinates), noDonorCells, nDim);
343 MInt intervals[MAX_SPACE_DIMENSIONS];
344
345 IF_CONSTEXPR(nDim == 2) {
346 intervals[2] = 0;
347 }
348
349
350 const MInt maxDonorLevel =
351 *(std::max_element(&donorCellLevels[0], &donorCellLevels[0] + noDonorCells)) - targetLevel + 1;
352
353
354 std::vector<std::vector<MInt>> mappedVolume(maxDonorLevel);
355 for(
MInt i = 0; i < maxDonorLevel; i++) {
357 mappedVolume[i].resize(noCellsOnLvl);
358 std::fill(mappedVolume[i].begin(), mappedVolume[i].end(), 0);
359 }
360
361
362 for(
MInt l = 0; l < noDonorCells; l++) {
363
364 const MInt donorLevel = donorCellLevels[l] - targetLevel;
365
366 const MInt noCells1D =
IPOW2(donorLevel);
367 const MInt noCells1D3 = (nDim == 3) ? noCells1D : 1;
368
369
370 for(
MInt d = 0; d < nDim; d++) {
371 const MFloat posOnUnitElem = positionOnUnitElement(donorCellCoords(l, d), targetCellCenter[d], cellLength);
372
373 intervals[d] = -1;
374
375 for(
MInt i = 0; i < noCells1D; i++) {
378
379
380
381 if(lowerBound < posOnUnitElem && posOnUnitElem < upperBound
383 intervals[d] = i;
384 break;
385 }
386 }
387
388 if(intervals[d] == -1) {
389 stringstream errorMsg;
390 errorMsg << "Donor cell interval not found! (level = " << donorLevel << "; position = " << std::scientific
391 << posOnUnitElem << ")";
392 TERMM(1, errorMsg.str());
393 }
394 }
395
396
397 const MInt donorIndex =
398 intervals[0] * noCells1D * noCells1D3 + intervals[1] * noCells1D3 + intervals[2] * (nDim == 3);
399
400
401 donorIds[l] = donorIndex;
402 donorLevels[l] = donorLevel;
403
404
405 mappedVolume[donorLevel][donorIndex] = 1;
406
407
408 for(
MInt lvl = donorLevel + 1; lvl < maxDonorLevel; lvl++) {
409 const MInt noCellsRel1D =
IPOW2(lvl - donorLevel);
410 const MInt noCellsRel1D3 = (nDim == 3) ? noCellsRel1D : 1;
411 const MInt sizeFactor =
IPOW2(lvl - donorLevel);
412
414 const MInt noCells1D3_ = (nDim == 3) ? noCells1D_ : 1;
415
416
417 for(
MInt i = 0; i < noCellsRel1D; i++) {
418 for(
MInt j = 0; j < noCellsRel1D; j++) {
419 for(
MInt k = 0; k < noCellsRel1D3; k++) {
420
421 const MInt volumeIndex = (intervals[0] * sizeFactor + i) * noCells1D_ * noCells1D3_
422 + (intervals[1] * sizeFactor + j) * noCells1D3_
423 + (intervals[2] * sizeFactor + k) * (nDim == 3);
424 mappedVolume[lvl][volumeIndex] = 1;
425 }
426 }
427 }
428 }
429
430
431 for(
MInt lvl = donorLevel - 1; lvl >= 0; lvl--) {
433 const MInt noCells1D3_ = (nDim == 3) ? noCells1D_ : 1;
434 const MInt sizeFactor =
IPOW2(donorLevel - lvl);
435
436
437 const MInt volumeIndex = std::floor(intervals[0] / sizeFactor) * noCells1D_ * noCells1D3_
438 + std::floor(intervals[1] / sizeFactor) * noCells1D3_
439 + std::floor(intervals[2] / sizeFactor) * (nDim == 3);
440 mappedVolume[lvl][volumeIndex] = 1;
441 }
442 }
443
444
445
446 for(
MInt lvl = 0; lvl < maxDonorLevel; lvl++) {
448 const MInt noCellsLvl1D3 = (nDim == 3) ? noCellsLvl1D : 1;
449
450
451 for(
MInt i = 0; i < noCellsLvl1D; i++) {
452 for(
MInt j = 0; j < noCellsLvl1D; j++) {
453 for(
MInt k = 0; k < noCellsLvl1D3; k++) {
454
455 const MInt donorIndex = i * noCellsLvl1D * noCellsLvl1D3 + j * noCellsLvl1D3 + k * (nDim == 3);
456
457
458 if(!mappedVolume[lvl][donorIndex]) {
459
460 donorIds.push_back(donorIndex);
461 donorLevels.push_back(lvl);
462
463 std::cerr <<
globalDomainId() <<
" non-mapped " << targetCellCenter[0] <<
" " << lvl <<
" " << donorIndex
464 << std::endl;
465 TERMM(1, "TODO check if this is working correctly");
466
467
468
469 for(
MInt childLvl = lvl + 1; childLvl < maxDonorLevel; childLvl++) {
470 const MInt noCellsRel1D =
IPOW2(childLvl - lvl);
471 const MInt noCellsRel1D3 = (nDim == 3) ? noCellsRel1D : 1;
472
473
474 for(
MInt i2 = 0; i2 < noCellsRel1D; i2++) {
475 for(
MInt j2 = 0; j2 < noCellsRel1D; j2++) {
476 for(
MInt k2 = 0; k2 < noCellsRel1D3; k2++) {
477 const MInt volumeIndex =
478 (i2 + i) * noCellsRel1D * noCellsRel1D3 + (j2 + j) * noCellsRel1D3 + (k2 + k) * (nDim == 3);
479 mappedVolume[childLvl][volumeIndex] = 1;
480 }
481 }
482 }
483 }
484 }
485 }
486 }
487 }
488 }
489
490
492 for(
MUint i = 0; i < donorLevels.size(); i++) {
494 sumVolumes += volume;
495 }
496 if(!
approx(sumVolumes, 1.0, eps)) {
497 stringstream errMsg;
498 errMsg << "calcProjectionInformation: mapped volume " << std::to_string(sumVolumes) << "(target cell coordinates:";
499 for(
MInt d = 0; d < nDim; d++) {
500 errMsg << " " << targetCellCenter[d];
501 }
502 errMsg << ")";
503 TERMM(1, errMsg.str());
504 }
505}
MBool approx(const T &, const U &, const T)
MInt globalDomainId()
Return global domain id.
constexpr MFloat FPOW2(MInt x)
constexpr MFloat FFPOW2(MInt x)