33 const MInt solverId) {
36 init(polyDeg, noLevels, lengthLevel0, solverId);
51 m_lengthLevel0 = -1.0;
53 m_wInt.clear(), m_MTD.clear();
54 m_polynomials.clear();
55 m_cellCenters.clear();
56 m_cellLengths.clear();
75 const MInt solverId) {
80 m_noLevels = noLevels;
81 m_lengthLevel0 = lengthLevel0;
82 m_noNodesXD =
ipow(polyDeg + 1, nDim);
83 m_solverId = solverId;
85 const MInt noNodes1D = polyDeg + 1;
86 const MInt maxNoCellsOnLevel =
IPOW2(noLevels - 1);
89 m_MTD.resize(m_noLevels);
90 m_polynomials.resize(m_noLevels);
91 for(
MInt level = 0; level < m_noLevels; level++) {
93 const MInt noCellsOnLevel =
ipow(noCells1D, nDim);
95 m_MTD[level].resize(noCellsOnLevel, m_noNodesXD);
96 m_polynomials[level].resize(noCells1D, noNodes1D, noNodes1D);
99 m_cellCenters.resize(noLevels, maxNoCellsOnLevel);
100 m_cellLengths.resize(noLevels);
103 for(
MInt l = 0; l < noLevels; l++) {
106 const MFloat cellLength = 2.0 / noCellsOnLevel;
107 m_cellLengths[l] = cellLength;
110 for(
MInt c = 0; c < noCellsOnLevel; c++) {
111 m_cellCenters(l, c) = -1.0 + 0.5 * cellLength + c * cellLength;
116 calcInterpolationMatrices();
152 const MBool defaultSbpMode =
false;
153 const MBool sbpMode = Context::getSolverProperty<MBool>(
"sbpMode", m_solverId, AT_, &defaultSbpMode);
156 const MString defaultSbpOperator =
"";
157 const MString sbpOperator = Context::getSolverProperty<MString>(
"sbpOperator", m_solverId, AT_, &defaultSbpOperator);
159 MInt initNoNodes1D = -1;
160 initNoNodes1D = Context::getSolverProperty<MInt>(
"initNoNodes", m_solverId, AT_, &initNoNodes1D);
162 const MInt noNodes1D = sbpMode ? initNoNodes1D : (m_polyDeg + 1);
163 const MInt maxNoCellsOnLevel =
IPOW2(m_noLevels - 1);
166 MString defaultDgIntegrationMethod =
"DG_INTEGRATE_GAUSS";
168 Context::getSolverProperty<MString>(
"dgIntegrationMethod", m_solverId, AT_, &defaultDgIntegrationMethod));
171 MString defaultDgPolynomialType =
"DG_POLY_LEGENDRE";
172 const MInt dgPolynomialType =
173 string2enum(Context::getSolverProperty<MString>(
"dgPolynomialType", m_solverId, AT_, &defaultDgPolynomialType));
180 DgInterpolation interpolation(m_polyDeg, polyType, noNodes1D, intMethod, sbpMode, sbpOperator);
197 std::array<MInt, nDim> index;
199 IF_CONSTEXPR(nDim == 2) {
200 for(
MInt i = 0; i < m_noNodesXD; i++) {
201 indices<nDim>(i, noNodes1D, &index[0]);
202 MT_inverse[i] = 1.0 / (wInt(index[0]) * wInt(index[1]));
206 for(
MInt i = 0; i < m_noNodesXD; i++) {
207 indices<nDim>(i, noNodes1D, &index[0]);
208 MT_inverse[i] = 1.0 / (wInt(index[0]) * wInt(index[1]) * wInt(index[2]));
216 for(
MInt level = m_noLevels - 1; level >= 0; level--) {
217 const MInt noCellsOnLevel =
IPOW2(level);
218 const MFloat lengthOnLevel = m_cellLengths[level];
221 for(
MInt l = 0; l < noCellsOnLevel; l++) {
223 for(
MInt j = 0; j < noNodes1D; j++) {
226 if(level == m_noLevels - 1) {
228 for(
MInt k = 0; k < noNodes1D; k++) {
230 const MFloat xiPos = m_cellCenters(level, l) + 0.5 * lengthOnLevel * nodes[k];
239 const MFloat weight = 0.5 * lengthOnLevel * wInt[k];
240 sumXi += weight * polynomials[j];
244 sumXi = vector1D(level + 1, 2 * l, j) + vector1D(level + 1, 2 * l + 1, j);
248 vector1D(level, l, j) = sumXi;
254 MInt cellIndex[MAX_SPACE_DIMENSIONS];
257 for(
MInt level = 0; level < m_noLevels; level++) {
259 const MInt noCellsOnLevel =
ipow(noCells1D, nDim);
262 for(
MInt nodeId = 0; nodeId < m_noNodesXD; nodeId++) {
264 indices<nDim>(nodeId, noNodes1D, &index[0]);
267 for(
MInt i = 0; i < noCellsOnLevel; i++) {
269 indices<nDim>(i, noCells1D, cellIndex);
272 m_MTD[level](i, nodeId) = 1.0;
273 for(
MInt d = 0; d < nDim; d++) {
274 m_MTD[level](i, nodeId) *= vector1D(level, cellIndex[d], index[d]);
277 m_MTD[level](i, nodeId) *= MT_inverse[nodeId];
283 for(
MInt level = 0; level < m_noLevels; level++) {
284 const MInt noCellsOnLevel =
IPOW2(level);
285 const MFloat lengthOnLevel = m_cellLengths[level];
288 for(
MInt l = 0; l < noCellsOnLevel; l++) {
290 for(
MInt k = 0; k < noNodes1D; k++) {
292 const MFloat xiPos = m_cellCenters(level, l) + 0.5 * lengthOnLevel * nodes[k];
329 const MFloat* donorCellCoordinates,
const MInt targetLevel,
330 const MFloat* targetCellCenter, std::vector<MInt>& donorIds,
331 std::vector<MInt>& donorLevels)
const {
336 auto positionOnUnitElement = [](
MFloat pos,
MFloat center,
MFloat width) {
return 2 * (pos - center) / width; };
339 const MFloat eps = 1.0 /
FPOW2(30) * m_lengthLevel0;
341 const MFloatTensor donorCellCoords(
const_cast<MFloat*
>(donorCellCoordinates), noDonorCells, nDim);
342 const MFloat cellLength = m_lengthLevel0 *
FFPOW2(targetLevel);
343 MInt intervals[MAX_SPACE_DIMENSIONS];
345 IF_CONSTEXPR(nDim == 2) {
350 const MInt maxDonorLevel =
351 *(std::max_element(&donorCellLevels[0], &donorCellLevels[0] + noDonorCells)) - targetLevel + 1;
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);
362 for(
MInt l = 0; l < noDonorCells; l++) {
364 const MInt donorLevel = donorCellLevels[l] - targetLevel;
366 const MInt noCells1D =
IPOW2(donorLevel);
367 const MInt noCells1D3 = (nDim == 3) ? noCells1D : 1;
370 for(
MInt d = 0; d < nDim; d++) {
371 const MFloat posOnUnitElem = positionOnUnitElement(donorCellCoords(l, d), targetCellCenter[d], cellLength);
375 for(
MInt i = 0; i < noCells1D; i++) {
376 const MFloat lowerBound = m_cellCenters(donorLevel, i) - 0.5 * m_cellLengths[donorLevel];
377 const MFloat upperBound = m_cellCenters(donorLevel, i) + 0.5 * m_cellLengths[donorLevel];
381 if(lowerBound < posOnUnitElem && posOnUnitElem < upperBound
382 &&
approx(posOnUnitElem, m_cellCenters(donorLevel, i), eps)) {
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());
397 const MInt donorIndex =
398 intervals[0] * noCells1D * noCells1D3 + intervals[1] * noCells1D3 + intervals[2] * (nDim == 3);
401 donorIds[l] = donorIndex;
402 donorLevels[l] = donorLevel;
405 mappedVolume[donorLevel][donorIndex] = 1;
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);
414 const MInt noCells1D3_ = (nDim == 3) ? noCells1D_ : 1;
417 for(
MInt i = 0; i < noCellsRel1D; i++) {
418 for(
MInt j = 0; j < noCellsRel1D; j++) {
419 for(
MInt k = 0; k < noCellsRel1D3; k++) {
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;
431 for(
MInt lvl = donorLevel - 1; lvl >= 0; lvl--) {
433 const MInt noCells1D3_ = (nDim == 3) ? noCells1D_ : 1;
434 const MInt sizeFactor =
IPOW2(donorLevel - lvl);
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;
446 for(
MInt lvl = 0; lvl < maxDonorLevel; lvl++) {
448 const MInt noCellsLvl1D3 = (nDim == 3) ? noCellsLvl1D : 1;
451 for(
MInt i = 0; i < noCellsLvl1D; i++) {
452 for(
MInt j = 0; j < noCellsLvl1D; j++) {
453 for(
MInt k = 0; k < noCellsLvl1D3; k++) {
455 const MInt donorIndex = i * noCellsLvl1D * noCellsLvl1D3 + j * noCellsLvl1D3 + k * (nDim == 3);
458 if(!mappedVolume[lvl][donorIndex]) {
460 donorIds.push_back(donorIndex);
461 donorLevels.push_back(lvl);
463 std::cerr <<
globalDomainId() <<
" non-mapped " << targetCellCenter[0] <<
" " << lvl <<
" " << donorIndex
465 TERMM(1,
"TODO check if this is working correctly");
469 for(
MInt childLvl = lvl + 1; childLvl < maxDonorLevel; childLvl++) {
470 const MInt noCellsRel1D =
IPOW2(childLvl - lvl);
471 const MInt noCellsRel1D3 = (nDim == 3) ? noCellsRel1D : 1;
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;
492 for(
MUint i = 0; i < donorLevels.size(); i++) {
494 sumVolumes += volume;
496 if(!
approx(sumVolumes, 1.0, eps)) {
498 errMsg <<
"calcProjectionInformation: mapped volume " << std::to_string(sumVolumes) <<
"(target cell coordinates:";
499 for(
MInt d = 0; d < nDim; d++) {
500 errMsg <<
" " << targetCellCenter[d];
503 TERMM(1, errMsg.str());
Performs the Galerkin projection for a given polynomial degree.
void calcProjectionInformation(const MInt noDonorCells, const MInt *donorCellLvls, const MFloat *donorCellCoordinates, const MInt targetLvl, const MFloat *targetElementCenter, std::vector< MInt > &donorIds, std::vector< MInt > &donorLvls) const
Compute the projection information for one target cell.
~DgGalerkinProjection()
Destructor clears all member variables.
void init(MInt polyDeg, const MInt noLevels, const MFloat lengthLevel0, const MInt solverId)
Initialize the member variables and calculate the interpolation matrices.
DgGalerkinProjection()=default
void calcInterpolationMatrices()
Calculate and store the needed interpolation matrices.
Class stores precalculated values for interpolation & integration on the reference interval [-1,...
This class is a ScratchSpace.
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
MBool approx(const T &, const U &, const T)
MInt ipow(MInt base, MInt exp)
Integer exponent function for non-negative exponents.
MInt globalDomainId()
Return global domain id.
constexpr MLong IPOW2(MInt x)
constexpr MFloat FPOW2(MInt x)
constexpr MFloat FFPOW2(MInt x)
std::basic_string< char > MString
Holds helper functions for the interpolation.
void calcLinearInterpolationBase(const MFloat x, const MInt noNodes, const MFloat *nodes, MFloat *const polynomials)
Calculates linear interpolation base for point (1D).
void calcLagrangeInterpolatingPolynomials(const MFloat x, const MInt polyDeg, const MFloat *nodes, const MFloat *wBary, MFloat *polynomials)
Calculates the values of the Lagrangian polynomials l_j for a given point x in [-1,...