void GridPatchCartesianGLL::InterpolateData( const DataVector<double> & dAlpha, const DataVector<double> & dBeta, const DataVector<int> & iPatch, DataType eDataType, DataLocation eDataLocation, bool fInterpAllVariables, DataMatrix3D<double> & dInterpData, bool fIncludeReferenceState, bool fConvertToPrimitive ) { if (dAlpha.GetRows() != dBeta.GetRows()) { _EXCEPTIONT("Point vectors must have equivalent length."); } // Vector for storage interpolated points DataVector<double> dAInterpCoeffs; dAInterpCoeffs.Initialize(m_nHorizontalOrder); DataVector<double> dBInterpCoeffs; dBInterpCoeffs.Initialize(m_nHorizontalOrder); DataVector<double> dADiffCoeffs; dADiffCoeffs.Initialize(m_nHorizontalOrder); DataVector<double> dBDiffCoeffs; dBDiffCoeffs.Initialize(m_nHorizontalOrder); DataVector<double> dAInterpPt; dAInterpPt.Initialize(m_nHorizontalOrder); // Element-wise grid spacing double dDeltaA = GetElementDeltaA(); double dDeltaB = GetElementDeltaB(); // Physical constants const PhysicalConstants & phys = m_grid.GetModel().GetPhysicalConstants(); // Loop throught all points for (int i = 0; i < dAlpha.GetRows(); i++) { // Element index if (iPatch[i] != GetPatchIndex()) { continue; } // Verify point lies within domain of patch const double Eps = 1.0e-10; if ((dAlpha[i] < m_box.GetAEdge(m_box.GetAInteriorBegin()) - Eps) || (dAlpha[i] > m_box.GetAEdge(m_box.GetAInteriorEnd()) + Eps) || (dBeta[i] < m_box.GetBEdge(m_box.GetBInteriorBegin()) - Eps) || (dBeta[i] > m_box.GetBEdge(m_box.GetBInteriorEnd()) + Eps) ) { _EXCEPTIONT("Point out of range"); } // Determine finite element index int iA = (dAlpha[i] - m_box.GetAEdge(m_box.GetAInteriorBegin())) / dDeltaA; int iB = (dBeta[i] - m_box.GetBEdge(m_box.GetBInteriorBegin())) / dDeltaB; // Bound the index within the element if (iA < 0) { iA = 0; } if (iA >= (m_box.GetAInteriorWidth() / m_nHorizontalOrder)) { iA = m_box.GetAInteriorWidth() / m_nHorizontalOrder - 1; } if (iB < 0) { iB = 0; } if (iB >= (m_box.GetBInteriorWidth() / m_nHorizontalOrder)) { iB = m_box.GetBInteriorWidth() / m_nHorizontalOrder - 1; } iA = m_box.GetHaloElements() + iA * m_nHorizontalOrder; iB = m_box.GetHaloElements() + iB * m_nHorizontalOrder; // Compute interpolation coefficients PolynomialInterp::LagrangianPolynomialCoeffs( m_nHorizontalOrder, &(m_box.GetAEdges()[iA]), dAInterpCoeffs, dAlpha[i]); PolynomialInterp::LagrangianPolynomialCoeffs( m_nHorizontalOrder, &(m_box.GetBEdges()[iB]), dBInterpCoeffs, dBeta[i]); int nComponents; int nRElements = m_grid.GetRElements(); double ** pData2D; // State Data: Perform interpolation on all variables if (eDataType == DataType_State) { if (eDataLocation == DataLocation_Node) { nComponents = m_datavecStateNode[0].GetComponents(); } else { nComponents = m_datavecStateREdge[0].GetComponents(); nRElements = m_grid.GetRElements() + 1; } // Tracer Data: Perform interpolation on all variables } else if (eDataType == DataType_Tracers) { nComponents = m_datavecTracers[0].GetComponents(); // Topography Data: Special handling due to 2D nature of data } else if (eDataType == DataType_Topography) { nComponents = 1; pData2D = (double**)(m_dataTopography); // Vorticity Data } else if (eDataType == DataType_Vorticity) { nComponents = 1; // Divergence Data } else if (eDataType == DataType_Divergence) { nComponents = 1; // Temperature Data } else if (eDataType == DataType_Temperature) { nComponents = 1; } else { _EXCEPTIONT("Invalid DataType"); } // Number of radial elements for (int c = 0; c < nComponents; c++) { const double *** pData; if (eDataType == DataType_State) { if (eDataLocation == DataLocation_Node) { pData = (const double ***)(m_datavecStateNode[0][c]); } else { pData = (const double ***)(m_datavecStateREdge[0][c]); } } else if (eDataType == DataType_Topography) { pData = (const double ***)(&pData2D); nRElements = 1; } else if (eDataType == DataType_Tracers) { pData = (const double ***)(m_datavecTracers[0][c]); } else if (eDataType == DataType_Vorticity) { pData = (const double ***)(double ***)(m_dataVorticity); } else if (eDataType == DataType_Divergence) { pData = (const double ***)(double ***)(m_dataDivergence); } else if (eDataType == DataType_Temperature) { pData = (const double ***)(double ***)(m_dataTemperature); } // Perform interpolation on all levels for (int k = 0; k < nRElements; k++) { dInterpData[c][k][i] = 0.0; for (int m = 0; m < m_nHorizontalOrder; m++) { for (int n = 0; n < m_nHorizontalOrder; n++) { dInterpData[c][k][i] += dAInterpCoeffs[m] * dBInterpCoeffs[n] * pData[k][iA+m][iB+n]; } } // Do not include the reference state if ((eDataType == DataType_State) && (!fIncludeReferenceState) ) { if (eDataLocation == DataLocation_Node) { for (int m = 0; m < m_nHorizontalOrder; m++) { for (int n = 0; n < m_nHorizontalOrder; n++) { dInterpData[c][k][i] -= dAInterpCoeffs[m] * dBInterpCoeffs[n] * m_dataRefStateNode[c][k][iA+m][iB+n]; } } } else { for (int m = 0; m < m_nHorizontalOrder; m++) { for (int n = 0; n < m_nHorizontalOrder; n++) { dInterpData[c][k][i] -= dAInterpCoeffs[m] * dBInterpCoeffs[n] * m_dataRefStateREdge[c][k][iA+m][iB+n]; } } } } } } } }
void GridPatchCSGLL::InterpolateData( DataType eDataType, const DataArray1D<double> & dREta, const DataArray1D<double> & dAlpha, const DataArray1D<double> & dBeta, const DataArray1D<int> & iPatch, DataArray3D<double> & dInterpData, DataLocation eOnlyVariablesAt, bool fIncludeReferenceState, bool fConvertToPrimitive ) { if ((dAlpha.GetRows() != dBeta.GetRows()) || (dAlpha.GetRows() != iPatch.GetRows()) ) { _EXCEPTIONT("Point vectors must have equivalent length."); } // Vector for storage interpolated points DataArray1D<double> dAInterpCoeffs(m_nHorizontalOrder); DataArray1D<double> dBInterpCoeffs(m_nHorizontalOrder); DataArray1D<double> dADiffCoeffs(m_nHorizontalOrder); DataArray1D<double> dBDiffCoeffs(m_nHorizontalOrder); DataArray1D<double> dAInterpPt(m_nHorizontalOrder); // Physical constants const PhysicalConstants & phys = m_grid.GetModel().GetPhysicalConstants(); // Perform interpolation on all variables int nComponents = 0; int nRElements = m_grid.GetRElements(); // Discretization type Grid::VerticalDiscretization eVerticalDiscType = m_grid.GetVerticalDiscretization(); // State Data: Perform interpolation on all variables if (eDataType == DataType_State) { nComponents = m_datavecStateNode[0].GetSize(0); nRElements = m_grid.GetRElements() + 1; // Tracer Data: Perform interpolation on all variables } else if (eDataType == DataType_Tracers) { nComponents = m_datavecTracers[0].GetSize(0); // Topography Data } else if (eDataType == DataType_Topography) { nComponents = 1; nRElements = 1; // Vorticity Data } else if (eDataType == DataType_Vorticity) { nComponents = 1; // Divergence Data } else if (eDataType == DataType_Divergence) { nComponents = 1; // Temperature Data } else if (eDataType == DataType_Temperature) { nComponents = 1; // Surface Pressure Data } else if (eDataType == DataType_SurfacePressure) { nComponents = 1; nRElements = 1; // 2D User Data } else if (eDataType == DataType_Auxiliary2D) { nComponents = m_dataUserData2D.GetSize(0); nRElements = 1; } else { _EXCEPTIONT("Invalid DataType"); } // Buffer storage in column DataArray1D<double> dColumnDataOut(dREta.GetRows()); // Loop through all components for (int c = 0; c < nComponents; c++) { DataLocation eDataLocation = DataLocation_Node; if (eDataType == DataType_State) { eDataLocation = m_grid.GetVarLocation(c); // Exclude variables not at the specified DataLocation if ((eOnlyVariablesAt != DataLocation_None) && (eOnlyVariablesAt != eDataLocation) ) { continue; } // Adjust RElements depending on state data location if (eDataLocation == DataLocation_Node) { nRElements = m_grid.GetRElements(); } else if (eDataLocation == DataLocation_REdge) { nRElements = m_grid.GetRElements() + 1; } else { _EXCEPTIONT("Invalid DataLocation"); } } // Vertical interpolation operator LinearColumnInterpFEM opInterp; if (nRElements != 1) { // Finite element interpolation if (eVerticalDiscType == Grid::VerticalDiscretization_FiniteElement ) { if (eDataLocation == DataLocation_Node) { opInterp.Initialize( LinearColumnInterpFEM::InterpSource_Levels, m_nVerticalOrder, m_grid.GetREtaLevels(), m_grid.GetREtaInterfaces(), dREta); } else if (eDataLocation == DataLocation_REdge) { opInterp.Initialize( LinearColumnInterpFEM::InterpSource_Interfaces, m_nVerticalOrder, m_grid.GetREtaLevels(), m_grid.GetREtaInterfaces(), dREta); } else { _EXCEPTIONT("Invalid DataLocation"); } // Finite volume interpolation } else if ( eVerticalDiscType == Grid::VerticalDiscretization_FiniteVolume ) { if (eDataLocation == DataLocation_Node) { opInterp.Initialize( LinearColumnInterpFEM::InterpSource_Levels, 1, m_grid.GetREtaLevels(), m_grid.GetREtaInterfaces(), dREta); } else if (eDataLocation == DataLocation_REdge) { opInterp.Initialize( LinearColumnInterpFEM::InterpSource_Interfaces, 1, m_grid.GetREtaLevels(), m_grid.GetREtaInterfaces(), dREta); } else { _EXCEPTIONT("Invalid DataLocation"); } // Invalid vertical discretization type } else { _EXCEPTIONT("Invalid VerticalDiscretization"); } } else { opInterp.InitializeIdentity(1); } // Buffer storage in column DataArray1D<double> dColumnData(nRElements); // Get a pointer to the 3D data structure DataArray3D<double> pData; DataArray3D<double> pDataRef; pData.SetSize( nRElements, m_box.GetATotalWidth(), m_box.GetBTotalWidth()); pDataRef.SetSize( nRElements, m_box.GetATotalWidth(), m_box.GetBTotalWidth()); if (eDataType == DataType_State) { if (eDataLocation == DataLocation_Node) { pData.AttachToData(&(m_datavecStateNode[0][c][0][0][0])); pDataRef.AttachToData(&(m_dataRefStateNode[c][0][0][0])); } else if (eDataLocation == DataLocation_REdge) { pData.AttachToData(&(m_datavecStateREdge[0][c][0][0][0])); pDataRef.AttachToData(&(m_dataRefStateREdge[c][0][0][0])); } else { _EXCEPTIONT("Invalid DataLocation"); } } else if (eDataType == DataType_Tracers) { pData.AttachToData(&(m_datavecTracers[0][c][0][0][0])); } else if (eDataType == DataType_Topography) { pData.AttachToData(&(m_dataTopography[0][0])); } else if (eDataType == DataType_Vorticity) { pData.AttachToData(&(m_dataVorticity[0][0][0])); } else if (eDataType == DataType_Divergence) { pData.AttachToData(&(m_dataDivergence[0][0][0])); } else if (eDataType == DataType_Temperature) { pData.AttachToData(&(m_dataTemperature[0][0][0])); } else if (eDataType == DataType_SurfacePressure) { pData.AttachToData(&(m_dataSurfacePressure[0][0])); } else if (eDataType == DataType_Auxiliary2D) { pData.AttachToData(&(m_dataUserData2D[c][0][0])); } // Loop throught all points for (int i = 0; i < dAlpha.GetRows(); i++) { // Element index if (iPatch[i] != GetPatchIndex()) { continue; } // Verify point lies within domain of patch const double Eps = 1.0e-10; if ((dAlpha[i] < m_dAEdge[m_box.GetAInteriorBegin()] - Eps) || (dAlpha[i] > m_dAEdge[m_box.GetAInteriorEnd()] + Eps) || (dBeta[i] < m_dBEdge[m_box.GetBInteriorBegin()] - Eps) || (dBeta[i] > m_dBEdge[m_box.GetBInteriorEnd()] + Eps) ) { _EXCEPTIONT("Point out of range"); } // Determine finite element index int iA = (dAlpha[i] - m_dAEdge[m_box.GetAInteriorBegin()]) / GetElementDeltaA(); int iB = (dBeta[i] - m_dBEdge[m_box.GetBInteriorBegin()]) / GetElementDeltaB(); // Bound the index within the element if (iA < 0) { iA = 0; } if (iA >= (m_box.GetAInteriorWidth() / m_nHorizontalOrder)) { iA = m_box.GetAInteriorWidth() / m_nHorizontalOrder - 1; } if (iB < 0) { iB = 0; } if (iB >= (m_box.GetBInteriorWidth() / m_nHorizontalOrder)) { iB = m_box.GetBInteriorWidth() / m_nHorizontalOrder - 1; } iA = m_box.GetHaloElements() + iA * m_nHorizontalOrder; iB = m_box.GetHaloElements() + iB * m_nHorizontalOrder; // Compute interpolation coefficients PolynomialInterp::LagrangianPolynomialCoeffs( m_nHorizontalOrder, &(m_dAEdge[iA]), dAInterpCoeffs, dAlpha[i]); PolynomialInterp::LagrangianPolynomialCoeffs( m_nHorizontalOrder, &(m_dBEdge[iB]), dBInterpCoeffs, dBeta[i]); // Perform interpolation on all levels for (int k = 0; k < nRElements; k++) { dColumnData[k] = 0.0; // Rescale vertical velocity const int WIx = 3; if ((c == WIx) && (fConvertToPrimitive)) { if (m_grid.GetVarLocation(WIx) == DataLocation_REdge) { for (int m = 0; m < m_nHorizontalOrder; m++) { for (int n = 0; n < m_nHorizontalOrder; n++) { dColumnData[k] += dAInterpCoeffs[m] * dBInterpCoeffs[n] * pData[k][iA+m][iB+n] / m_dataDerivRREdge[k][iA][iB][2]; } } } else { for (int m = 0; m < m_nHorizontalOrder; m++) { for (int n = 0; n < m_nHorizontalOrder; n++) { dColumnData[k] += dAInterpCoeffs[m] * dBInterpCoeffs[n] * pData[k][iA+m][iB+n] / m_dataDerivRNode[k][iA][iB][2]; } } } } else { for (int m = 0; m < m_nHorizontalOrder; m++) { for (int n = 0; n < m_nHorizontalOrder; n++) { dColumnData[k] += dAInterpCoeffs[m] * dBInterpCoeffs[n] * pData[k][iA+m][iB+n]; } } } // Do not include the reference state if ((eDataType == DataType_State) && (!fIncludeReferenceState) ) { for (int m = 0; m < m_nHorizontalOrder; m++) { for (int n = 0; n < m_nHorizontalOrder; n++) { dColumnData[k] -= dAInterpCoeffs[m] * dBInterpCoeffs[n] * pDataRef[k][iA+m][iB+n]; } } } } // Interpolate vertically opInterp.Apply( &(dColumnData[0]), &(dColumnDataOut[0])); // Store data for (int k = 0; k < dREta.GetRows(); k++) { dInterpData[c][k][i] = dColumnDataOut[k]; } } } // Convert to primitive variables if ((eDataType == DataType_State) && (fConvertToPrimitive)) { for (int i = 0; i < dAlpha.GetRows(); i++) { if (iPatch[i] != GetPatchIndex()) { continue; } for (int k = 0; k < dREta.GetRows(); k++) { double dUalpha = dInterpData[0][k][i] / phys.GetEarthRadius(); double dUbeta = dInterpData[1][k][i] / phys.GetEarthRadius(); CubedSphereTrans::CoVecTransRLLFromABP( tan(dAlpha[i]), tan(dBeta[i]), GetPatchBox().GetPanel(), dUalpha, dUbeta, dInterpData[0][k][i], dInterpData[1][k][i]); } } } }