7#ifndef DGGALERKINPROJECTION_H_
8#define DGGALERKINPROJECTION_H_
40 const MInt* donorCellLvls,
41 const MFloat* donorCellCoordinates,
43 const MFloat* targetElementCenter,
44 std::vector<MInt>& donorIds,
45 std::vector<MInt>& donorLvls)
const;
47 void apply(
const MInt noDonorCells,
const MInt noNonMappedCells,
const MInt* donorCellIds,
const MInt* donorCellLvls,
48 const MInt* donorCellPos,
const MFloat*
const donorField,
const MFloat*
const defaultValues,
49 const MInt noVars,
MFloat*
const targetField)
const;
56 const MInt* donorCellPos,
const MFloat* donorField,
const MInt noVars,
const MFloat targetLength,
84 std::vector<MFloatTensor>
m_MTD{};
113 const MInt noNonMappedCells,
114 const MInt* donorCellIds,
115 const MInt* donorCellLevels,
116 const MInt* donorCellPos,
117 const MFloat*
const donorField,
118 const MFloat*
const defaultValues,
120 MFloat*
const targetField)
const {
123 std::fill_n(&targetField[0], m_noNodesXD * noVars, 0.0);
127 for(
MInt l = 0; l < noDonorCells; l++) {
131 const MFloat*
const weight = &m_MTD[donorCellLevels[l]](donorCellPos[l], 0);
133 const MFloat*
const donorVars = &donorField[donorCellIds[l] * noVars];
136 for(
MInt i = 0; i < m_noNodesXD; i++) {
138 for(
MInt v = 0; v < noVars; v++) {
139 target(i, v) += weight[i] * donorVars[v];
145 for(
MInt l = noDonorCells; l < noDonorCells + noNonMappedCells; l++) {
146 const MFloat*
const weight = &m_MTD[donorCellLevels[l]](donorCellPos[l], 0);
148 for(
MInt i = 0; i < m_noNodesXD; i++) {
150 for(
MInt v = 0; v < noVars; v++) {
151 target(i, v) += weight[i] * defaultValues[v];
180 const MInt* donorCellLevels,
const MFloat* donorField,
185 const MInt noNodes1D = m_polyDeg + 1;
186 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
188 const MFloatTensor target(
const_cast<MFloat*
>(targetField), noNodes1D, noNodes1D, noNodes1D3, noVars);
191 const MFloat elementJacobian = (nDim == 2) ?
POW2(F1B2 * targetLength) :
POW3(F1B2 * targetLength);
194 std::fill(donorIntegral.
begin(), donorIntegral.
end(), 0.0);
196 std::fill(targetIntegral.
begin(), targetIntegral.
end(), 0.0);
199 for(
MInt l = 0; l < noDonorCells; l++) {
200 const MInt dLevel = donorCellLevels[l];
201 const MInt nCellsOnLevel =
IPOW2(dLevel);
203 const MFloat donorLength = targetLength / nCellsOnLevel;
204 const MFloat volume = (nDim == 2) ?
POW2(donorLength) :
POW3(donorLength);
206 const MInt donorCellOffset = donorCellIds[l] * noVars;
208 for(
MInt varId = 0; varId < noVars; varId++) {
209 donorIntegral[varId] += volume * donorField[donorCellOffset + varId];
214 IF_CONSTEXPR(nDim == 2) {
215 for(
MInt i = 0; i < noNodes1D; i++) {
216 for(
MInt j = 0; j < noNodes1D; j++) {
217 const MFloat weight = m_wInt(i) * m_wInt(j);
218 for(
MInt varId = 0; varId < noVars; varId++) {
219 targetIntegral[varId] += weight * target(i, j, 0, varId);
225 for(
MInt i = 0; i < noNodes1D; i++) {
226 for(
MInt j = 0; j < noNodes1D; j++) {
227 for(
MInt k = 0; k < noNodes1D; k++) {
228 const MFloat weight = m_wInt(i) * m_wInt(j) * m_wInt(k);
229 for(
MInt varId = 0; varId < noVars; varId++) {
230 targetIntegral[varId] += weight * target(i, j, k, varId);
238 for(
MInt varId = 0; varId < noVars; varId++) {
239 targetIntegral[varId] *= elementJacobian;
243 for(
MInt varId = 0; varId < noVars; varId++) {
244 errors[varId] =
ABS(donorIntegral[varId] - targetIntegral[varId]);
247 if(errors[varId] > m_tolerance) {
248 std::stringstream errorMsg;
249 errorMsg <<
"targetIntegral doesn't match donorIntegral! (donorIntegral = " << std::scientific
250 << donorIntegral[varId] <<
"; targetIntegral = " << targetIntegral[varId]
251 <<
"; error = " << errors[varId] <<
"; m_tolerance = " << m_tolerance <<
")";
253 TERMM(1, errorMsg.str());
281 const MInt* donorCellLevels,
const MInt* donorCellPos,
288 const MInt noNodes1D = m_polyDeg + 1;
289 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
292 const MFloat elementJacobian = (nDim == 2) ?
POW2(F1B2 * targetLength) :
POW3(F1B2 * targetLength);
294 MInt intervals[3], index[3];
296 std::fill_n(&errors[0], noVars, 0.0);
299 for(
MInt l = 0; l < noDonorCells; l++) {
300 const MInt dLevel = donorCellLevels[l];
301 const MInt nCellsOnLevel =
IPOW2(dLevel);
303 const MFloat donorXiLength = m_cellLengths[dLevel];
304 const MFloat donorCellJacobian = (nDim == 2) ?
POW2(F1B2 * donorXiLength) :
POW3(F1B2 * donorXiLength);
306 const MInt donorCellOffset = donorCellIds[l] * noVars;
309 indices<nDim>(donorCellPos[l], nCellsOnLevel, intervals);
312 for(
MInt u = 0; u < noNodes1D; u++) {
313 for(
MInt k = 0; k < noNodes1D; k++) {
314 for(
MInt j = 0; j < noNodes1D3; j++) {
315 std::vector<MFloat> sum(noVars, 0.0);
318 for(
MInt i = 0; i < m_noNodesXD; i++) {
319 indices<nDim>(i, noNodes1D, index);
323 m_polynomials[dLevel](intervals[0], u, index[0]) * m_polynomials[dLevel](intervals[1], k, index[1]);
324 IF_CONSTEXPR(nDim == 3) { tmp *= m_polynomials[dLevel](intervals[2], j, index[2]); }
327 for(
MInt varId = 0; varId < noVars; varId++) {
328 sum[varId] += tmp * target(i, varId);
332 MFloat factor = m_wInt(u) * m_wInt(k) * elementJacobian * donorCellJacobian;
333 IF_CONSTEXPR(nDim == 3) { factor *= m_wInt(j); }
336 for(
MInt varId = 0; varId < noVars; varId++) {
337 const MFloat square =
POW2(donorField[donorCellOffset + varId] - sum[varId]);
338 errors[varId] += factor * square;
349namespace projection {
365 const MInt f1 = i / n;
367 IF_CONSTEXPR(nDim == 2) {
372 const MInt f2 = i / (n * n);
375 ids[1] = f1 - f2 * n;
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 calcL2Error(const MInt noDonorCells, const MInt *donorCellIds, const MInt *donorCellLvls, const MInt *donorCellPos, const MFloat *donorField, const MInt noVars, const MFloat targetLength, const MFloat *targetField, MFloat *errors) const
Calculate the L2 projection error.
void apply(const MInt noDonorCells, const MInt noNonMappedCells, const MInt *donorCellIds, const MInt *donorCellLvls, const MInt *donorCellPos, const MFloat *const donorField, const MFloat *const defaultValues, const MInt noVars, MFloat *const targetField) const
Apply the Galerkin projection using the provided information.
void init(MInt polyDeg, const MInt noLevels, const MFloat lengthLevel0, const MInt solverId)
Initialize the member variables and calculate the interpolation matrices.
std::vector< MFloatTensor > m_MTD
DgGalerkinProjection()=default
MFloatTensor m_cellCenters
void calcConservationError(const MInt noDonorCells, const MInt *donorCellIds, const MInt *donorCellLvls, const MFloat *donorField, const MInt noVars, const MFloat targetLength, const MFloat *targetField, MFloat *errors) const
Calculate the Galerkin projection conservation error and check against tolerance.
void calcInterpolationMatrices()
Calculate and store the needed interpolation matrices.
MFloatTensor m_cellLengths
std::vector< MFloatTensor > m_polynomials
This class is a ScratchSpace.
constexpr Real POW3(const Real x)
constexpr Real POW2(const Real x)
constexpr MLong IPOW2(MInt x)
void indices(const MInt i, const MInt n, MInt *const ids)
Calculate the 2D/3D indices for a given scalar id for accessing a field of n^nDim points.
Namespace for auxiliary functions/classes.