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 GridPatchCartesianGLL::EvaluateGeometricTerms() { // Physical constants const PhysicalConstants & phys = m_grid.GetModel().GetPhysicalConstants(); // Obtain Gauss Lobatto quadrature nodes and weights DataVector<double> dGL; DataVector<double> dWL; GaussLobattoQuadrature::GetPoints(m_nHorizontalOrder, 0.0, 1.0, dGL, dWL); // Obtain normalized areas in the vertical const DataVector<double> & dWNode = m_grid.GetREtaLevelsNormArea(); const DataVector<double> & dWREdge = m_grid.GetREtaInterfacesNormArea(); // Verify that normalized areas are correct double dWNodeSum = 0.0; for (int k = 0; k < dWNode.GetRows(); k++) { dWNodeSum += dWNode[k]; } if (fabs(dWNodeSum - 1.0) > 1.0e-13) { _EXCEPTION1("Error in normalized areas (%1.15e)", dWNodeSum); } if (m_grid.GetVerticalStaggering() != Grid::VerticalStaggering_Interfaces ) { double dWREdgeSum = 0.0; for (int k = 0; k < dWREdge.GetRows(); k++) { dWREdgeSum += dWREdge[k]; } if (fabs(dWREdgeSum - 1.0) > 1.0e-13) { _EXCEPTION1("Error in normalized areas (%1.15e)", dWREdgeSum); } } // Derivatives of basis functions GridCartesianGLL & gridCartesianGLL = dynamic_cast<GridCartesianGLL &>(m_grid); const DataMatrix<double> & dDxBasis1D = gridCartesianGLL.GetDxBasis1D(); double dy0 = 0.5 * fabs(m_dGDim[3] - m_dGDim[2]); double dfp = 2.0 * phys.GetOmega() * sin(m_dRefLat); double dbetap = 2.0 * phys.GetOmega() * cos(m_dRefLat) / phys.GetEarthRadius(); // Initialize the Coriolis force at each node for (int i = 0; i < m_box.GetATotalWidth(); i++) { for (int j = 0; j < m_box.GetBTotalWidth(); j++) { // Coriolis force by beta approximation //m_dataCoriolisF[i][j] = dfp + dbetap * (m_dataLat[i][j] - dy0); //m_dataCoriolisF[i][j] = dfp; //m_dataCoriolisF[i][j] = 0.0; } } // Initialize metric and Christoffel symbols in terrain-following coords for (int a = 0; a < GetElementCountA(); a++) { for (int b = 0; b < GetElementCountB(); b++) { for (int i = 0; i < m_nHorizontalOrder; i++) { for (int j = 0; j < m_nHorizontalOrder; j++) { // Nodal points int iElementA = m_box.GetAInteriorBegin() + a * m_nHorizontalOrder; int iElementB = m_box.GetBInteriorBegin() + b * m_nHorizontalOrder; int iA = iElementA + i; int iB = iElementB + j; // Topography height and its derivatives double dZs = m_dataTopography[iA][iB]; double dDaZs = m_dataTopographyDeriv[0][iA][iB]; double dDbZs = m_dataTopographyDeriv[1][iA][iB]; // Initialize 2D Jacobian m_dataJacobian2D[iA][iB] = 1.0; // Initialize 2D contravariant metric m_dataContraMetric2DA[iA][iB][0] = 1.0; m_dataContraMetric2DA[iA][iB][1] = 0.0; m_dataContraMetric2DB[iA][iB][0] = 0.0; m_dataContraMetric2DB[iA][iB][1] = 1.0; // Initialize 2D covariant metric m_dataCovMetric2DA[iA][iB][0] = 1.0; m_dataCovMetric2DA[iA][iB][1] = 0.0; m_dataCovMetric2DB[iA][iB][0] = 0.0; m_dataCovMetric2DB[iA][iB][1] = 1.0; // Vertical coordinate transform and its derivatives for (int k = 0; k < m_grid.GetRElements(); k++) { // Gal-Chen and Somerville (1975) terrain following coord // Schar Exponential Decay terrain following coord double dREta = m_grid.GetREtaLevel(k); double dREtaStretch; double dDxREtaStretch; m_grid.EvaluateVerticalStretchF( dREta, dREtaStretch, dDxREtaStretch); //double dZ = dZs + (m_grid.GetZtop() - dZs) * dREtaStretch; //double dbZ = sinh(m_grid.GetZtop() * (1.0 - dREtaStretch) / m_dSL) // / sinh(m_grid.GetZtop() / m_dSL); //double dZ = m_grid.GetZtop() * dREtaStretch + dZs; // * dbZ; double dZ = dZs + (m_grid.GetZtop() - dZs) * dREtaStretch; double dDaZ = (1.0 - dREtaStretch) * dDaZs; double dDbZ = (1.0 - dREtaStretch) * dDbZs; double dDxZ = (m_grid.GetZtop() - dZs) * dDxREtaStretch; /* double dDaZ = dbZ * dDaZs; double dDbZ = dbZ * dDbZs; double dDxZ = m_grid.GetZtop() - dZs * m_grid.GetZtop() * cosh(m_grid.GetZtop() * (1.0 - dREtaStretch) / m_dSL) / (m_dSL * sinh(m_grid.GetZtop() / m_dSL)); dDxZ *= dDxREtaStretch; */ // Calculate pointwise Jacobian m_dataJacobian[k][iA][iB] = dDxZ * m_dataJacobian2D[iA][iB]; // Element area associated with each model level GLL node m_dataElementArea[k][iA][iB] = m_dataJacobian[k][iA][iB] * dWL[i] * GetElementDeltaA() * dWL[j] * GetElementDeltaB() * dWNode[k]; // Contravariant metric components m_dataContraMetricA[k][iA][iB][0] = m_dataContraMetric2DA[iA][iB][0]; m_dataContraMetricA[k][iA][iB][1] = m_dataContraMetric2DA[iA][iB][1]; m_dataContraMetricA[k][iA][iB][2] = - dDaZ / dDxZ; m_dataContraMetricB[k][iA][iB][0] = m_dataContraMetric2DB[iA][iB][0]; m_dataContraMetricB[k][iA][iB][1] = m_dataContraMetric2DB[iA][iB][1]; m_dataContraMetricB[k][iA][iB][2] = - dDbZ / dDxZ; m_dataContraMetricXi[k][iA][iB][0] = m_dataContraMetricA[k][iA][iB][2]; m_dataContraMetricXi[k][iA][iB][1] = m_dataContraMetricB[k][iA][iB][2]; m_dataContraMetricXi[k][iA][iB][2] = (1.0 + dDaZ * dDaZ + dDbZ * dDbZ) / (dDxZ * dDxZ); // Covariant metric components m_dataCovMetricA[k][iA][iB][0] = m_dataCovMetric2DA[iA][iB][0] + dDaZ * dDaZ; m_dataCovMetricA[k][iA][iB][1] = m_dataCovMetric2DA[iA][iB][1] + dDaZ * dDbZ; m_dataCovMetricA[k][iA][iB][2] = dDaZ * dDxZ; m_dataCovMetricB[k][iA][iB][0] = m_dataCovMetric2DB[iA][iB][0] + dDbZ * dDaZ; m_dataCovMetricB[k][iA][iB][1] = m_dataCovMetric2DB[iA][iB][1] + dDbZ * dDbZ; m_dataCovMetricB[k][iA][iB][2] = dDbZ * dDxZ; m_dataCovMetricXi[k][iA][iB][0] = dDaZ * dDxZ; m_dataCovMetricXi[k][iA][iB][1] = dDbZ * dDxZ; m_dataCovMetricXi[k][iA][iB][2] = dDxZ * dDxZ; // Derivatives of the vertical coordinate transform m_dataDerivRNode[k][iA][iB][0] = dDaZ; m_dataDerivRNode[k][iA][iB][1] = dDbZ; m_dataDerivRNode[k][iA][iB][2] = dDxZ; } // Metric terms at vertical interfaces for (int k = 0; k <= m_grid.GetRElements(); k++) { // Gal-Chen and Somerville (1975) terrain following coord // Schar Exponential decay terrain following coord double dREta = m_grid.GetREtaInterface(k); /* double dREtaStretch; double dDxREtaStretch; m_grid.EvaluateVerticalStretchF( dREta, dREtaStretch, dDxREtaStretch); double dZ = dZs + (m_grid.GetZtop() - dZs) * dREtaStretch; double dDaZ = (1.0 - dREtaStretch) * dDaZs; double dDbZ = (1.0 - dREtaStretch) * dDbZs; double dDxZ = (m_grid.GetZtop() - dZs) * dDxREtaStretch; */ double dREtaStretch; double dDxREtaStretch; m_grid.EvaluateVerticalStretchF( dREta, dREtaStretch, dDxREtaStretch); /* //double dZ = dZs + (m_grid.GetZtop() - dZs) * dREtaStretch; double dbZ = sinh(m_grid.GetZtop() * (1.0 - dREtaStretch) / m_dSL) / sinh(m_grid.GetZtop() / m_dSL); double dZ = m_grid.GetZtop() * dREtaStretch + dZs * dbZ; */ double dDaZ = (1.0 - dREtaStretch) * dDaZs; double dDbZ = (1.0 - dREtaStretch) * dDbZs; double dDxZ = (m_grid.GetZtop() - dZs) * dDxREtaStretch; /* double dDaZ = dbZ * dDaZs; double dDbZ = dbZ * dDbZs; double dDxZ = m_grid.GetZtop() - dZs * m_grid.GetZtop() * cosh(m_grid.GetZtop() * (1.0 - dREtaStretch) / m_dSL) / (m_dSL * sinh(m_grid.GetZtop() / m_dSL)); dDxZ *= dDxREtaStretch; */ // Calculate pointwise Jacobian m_dataJacobianREdge[k][iA][iB] = dDxZ * m_dataJacobian2D[iA][iB]; // Element area associated with each model interface GLL node m_dataElementAreaREdge[k][iA][iB] = m_dataJacobianREdge[k][iA][iB] * dWL[i] * GetElementDeltaA() * dWL[j] * GetElementDeltaB() * dWREdge[k]; // Components of the contravariant metric m_dataContraMetricAREdge[k][iA][iB][0] = m_dataContraMetric2DA[iA][iB][0]; m_dataContraMetricAREdge[k][iA][iB][1] = m_dataContraMetric2DA[iA][iB][1]; m_dataContraMetricAREdge[k][iA][iB][2] = - dDaZ / dDxZ; m_dataContraMetricBREdge[k][iA][iB][0] = m_dataContraMetric2DB[iA][iB][0]; m_dataContraMetricBREdge[k][iA][iB][1] = m_dataContraMetric2DB[iA][iB][1]; m_dataContraMetricBREdge[k][iA][iB][2] = - dDbZ / dDxZ; m_dataContraMetricXiREdge[k][iA][iB][0] = - dDaZ / dDxZ; m_dataContraMetricXiREdge[k][iA][iB][1] = - dDbZ / dDxZ; m_dataContraMetricXiREdge[k][iA][iB][2] = (1.0 + dDaZ * dDaZ + dDbZ * dDbZ) / (dDxZ * dDxZ); // Derivatives of the vertical coordinate transform m_dataDerivRREdge[k][iA][iB][0] = dDaZ; m_dataDerivRREdge[k][iA][iB][1] = dDbZ; m_dataDerivRREdge[k][iA][iB][2] = dDxZ; } } } } } }
void GridPatchCartesianGLL::ComputeCurlAndDiv( const GridData3D & dataUa, const GridData3D & dataUb ) const { // Parent grid const GridCartesianGLL & gridCSGLL = dynamic_cast<const GridCartesianGLL &>(m_grid); // Compute derivatives of the field const DataMatrix<double> & dDxBasis1D = gridCSGLL.GetDxBasis1D(); // Number of finite elements in each direction int nAFiniteElements = m_box.GetAInteriorWidth() / m_nHorizontalOrder; int nBFiniteElements = m_box.GetBInteriorWidth() / m_nHorizontalOrder; // Contravariant velocity within an element DataMatrix<double> dConUa(m_nHorizontalOrder, m_nHorizontalOrder); DataMatrix<double> dConUb(m_nHorizontalOrder, m_nHorizontalOrder); // Loop over all elements in the box for (int k = 0; k < gridCSGLL.GetRElements(); k++) { for (int a = 0; a < nAFiniteElements; a++) { for (int b = 0; b < nBFiniteElements; b++) { // Index of lower-left corner node int iA = a * m_nHorizontalOrder + m_box.GetHaloElements(); int iB = b * m_nHorizontalOrder + m_box.GetHaloElements(); // Calculate contravariant velocity at each node within the element for (int i = 0; i < m_nHorizontalOrder; i++) { for (int j = 0; j < m_nHorizontalOrder; j++) { dConUa[i][j] = m_dataContraMetric2DA[iA+i][iB+j][0] * dataUa[k][iA+i][iB+j] + m_dataContraMetric2DA[iA+i][iB+j][1] * dataUb[k][iA+i][iB+j]; dConUb[i][j] = m_dataContraMetric2DB[iA+i][iB+j][0] * dataUa[k][iA+i][iB+j] + m_dataContraMetric2DB[iA+i][iB+j][1] * dataUb[k][iA+i][iB+j]; } } // Calculate divergance and curl for (int i = 0; i < m_nHorizontalOrder; i++) { for (int j = 0; j < m_nHorizontalOrder; j++) { // Compute derivatives at each node double dDaJUa = 0.0; double dDbJUb = 0.0; double dCovDaUb = 0.0; double dCovDbUa = 0.0; for (int s = 0; s < m_nHorizontalOrder; s++) { dDaJUa += dDxBasis1D[s][i] * m_dataJacobian2D[iA+s][iB+j] * dConUa[s][j]; dDbJUb += dDxBasis1D[s][j] * m_dataJacobian2D[iA+i][iB+s] * dConUb[i][s]; dCovDaUb += dDxBasis1D[s][i] * dataUb[k][iA+s][iB+j]; //( m_dataCovMetric2DB[iA+s][iB+j][0] * dataUa[k][iA+s][iB+j] //+ m_dataCovMetric2DB[iA+s][iB+j][1] * dataUb[k][iA+s][iB+j]); dCovDbUa += dDxBasis1D[s][j] * dataUa[k][iA+i][iB+s]; //( m_dataCovMetric2DA[iA+i][iB+s][0] * dataUa[k][iA+i][iB+s] //+ m_dataCovMetric2DA[iA+i][iB+s][1] * dataUb[k][iA+i][iB+s]); } dDaJUa /= GetElementDeltaA(); dDbJUb /= GetElementDeltaB(); dCovDaUb /= GetElementDeltaA(); dCovDbUa /= GetElementDeltaB(); m_dataVorticity[k][iA+i][iB+j] = (dCovDaUb - dCovDbUa) / m_dataJacobian2D[iA+i][iB+j]; // Compute the divergence at node m_dataDivergence[k][iA+i][iB+j] = (dDaJUa + dDbJUb) / m_dataJacobian2D[iA+i][iB+j]; /* // Compute covariant derivatives at node double dCovDaUa = dDaUa + m_dataChristoffelA[iA+i][iB+j][0] * dUa + m_dataChristoffelA[iA+i][iB+j][1] * 0.5 * dUb; double dCovDaUb = dDaUb + m_dataChristoffelB[iA+i][iB+j][0] * dUa + m_dataChristoffelB[iA+i][iB+j][1] * 0.5 * dUb; double dCovDbUa = dDbUa + m_dataChristoffelA[iA+i][iB+j][1] * 0.5 * dUa + m_dataChristoffelA[iA+i][iB+j][2] * dUb; double dCovDbUb = dDbUb + m_dataChristoffelB[iA+i][iB+j][1] * 0.5 * dUa + m_dataChristoffelB[iA+i][iB+j][2] * dUb; // Compute curl at node m_dataVorticity[k][iA+i][iB+j] = m_dataJacobian2D[iA+i][iB+j] * ( + m_dataContraMetric2DA[iA+i][iB+j][0] * dDaUb + m_dataContraMetric2DA[iA+i][iB+j][1] * dDbUb - m_dataContraMetric2DB[iA+i][iB+j][0] * dDaUa - m_dataContraMetric2DB[iA+i][iB+j][1] * dDbUa); // Compute the divergence at node m_dataDivergence[k][iA+i][iB+j] = dDaUa + dDbUb; */ } } } } } }
void GridPatchCartesianGLL::EvaluateTopography( const TestCase & test ) { const PhysicalConstants & phys = m_grid.GetModel().GetPhysicalConstants(); // Compute values of topography for (int i = 0; i < m_box.GetATotalWidth(); i++) { for (int j = 0; j < m_box.GetBTotalWidth(); j++) { double dX = m_box.GetANode(i); double dY = m_box.GetBNode(j); m_dataTopography[i][j] = test.EvaluateTopography(phys, dX, dY); if (m_dataTopography[i][j] >= m_grid.GetZtop()) { _EXCEPTIONT("TestCase topography exceeds model top."); } } } // Get derivatves from basis GridCartesianGLL & gridCartesianGLL = dynamic_cast<GridCartesianGLL &>(m_grid); const DataMatrix<double> & dDxBasis1D = gridCartesianGLL.GetDxBasis1D(); // Compute derivatives of topography for (int a = 0; a < GetElementCountA(); a++) { for (int b = 0; b < GetElementCountB(); b++) { for (int i = 0; i < m_nHorizontalOrder; i++) { for (int j = 0; j < m_nHorizontalOrder; j++) { // Nodal points int iElementA = m_box.GetAInteriorBegin() + a * m_nHorizontalOrder; int iElementB = m_box.GetBInteriorBegin() + b * m_nHorizontalOrder; int iA = iElementA + i; int iB = iElementB + j; // Topography height and its derivatives double dZs = m_dataTopography[iA][iB]; double dDaZs = 0.0; double dDbZs = 0.0; for (int s = 0; s < m_nHorizontalOrder; s++) { dDaZs += dDxBasis1D[s][i] * m_dataTopography[iElementA+s][iB]; dDbZs += dDxBasis1D[s][j] * m_dataTopography[iA][iElementB+s]; } dDaZs /= GetElementDeltaA(); dDbZs /= GetElementDeltaB(); m_dataTopographyDeriv[0][iA][iB] = dDaZs; m_dataTopographyDeriv[1][iA][iB] = dDbZs; } } } } }
void GridPatchCSGLL::ComputeCurlAndDiv( const DataArray3D<double> & dataUa, const DataArray3D<double> & dataUb ) { // Parent grid const GridCSGLL & gridCSGLL = dynamic_cast<const GridCSGLL &>(m_grid); // If SpectralElement dynamics are used, apply direct stiffness summation bool fDiscontinuous = false; // Get derivatives of the basis functions const DataArray2D<double> & dDxBasis1D = gridCSGLL.GetDxBasis1D(); // Get derivatives of the flux reconstruction function const DataArray1D<double> & dFluxDeriv1D = gridCSGLL.GetFluxDeriv1D(); // Number of finite elements in each direction int nAFiniteElements = m_box.GetAInteriorWidth() / m_nHorizontalOrder; int nBFiniteElements = m_box.GetBInteriorWidth() / m_nHorizontalOrder; /* // Allocate temporary data for contravariant velocities DataArray2D<double> dConUa(m_nHorizontalOrder, m_nHorizontalOrder); DataArray2D<double> dConUb(m_nHorizontalOrder, m_nHorizontalOrder); */ // Inverse grid spacings const double dInvElementDeltaA = 1.0 / GetElementDeltaA(); const double dInvElementDeltaB = 1.0 / GetElementDeltaB(); // Loop over all elements in the box for (int k = 0; k < gridCSGLL.GetRElements(); k++) { for (int a = 0; a < nAFiniteElements; a++) { for (int b = 0; b < nBFiniteElements; b++) { // Index of lower-left corner node int iElementA = a * m_nHorizontalOrder + m_box.GetHaloElements(); int iElementB = b * m_nHorizontalOrder + m_box.GetHaloElements(); // Calculate contravariant velocities in element for (int i = 0; i < m_nHorizontalOrder; i++) { for (int j = 0; j < m_nHorizontalOrder; j++) { int iA = iElementA + i; int iB = iElementB + j; m_dBufferConU[0][i][j] = + m_dataContraMetric2DA[iA][iB][0] * dataUa[k][iA][iB] + m_dataContraMetric2DA[iA][iB][1] * dataUb[k][iA][iB]; m_dBufferConU[1][i][j] = + m_dataContraMetric2DB[iA][iB][0] * dataUa[k][iA][iB] + m_dataContraMetric2DB[iA][iB][1] * dataUb[k][iA][iB]; } } // Calculate curl and div for (int i = 0; i < m_nHorizontalOrder; i++) { for (int j = 0; j < m_nHorizontalOrder; j++) { int iA = iElementA + i; int iB = iElementB + j; // Pointwise field values double dUa = dataUa[k][iA][iB]; double dUb = dataUb[k][iA][iB]; // Compute derivatives at each node //double dDaUa = 0.0; double dDaUb = 0.0; double dDbUa = 0.0; //double dDbUb = 0.0; double dDaJUa = 0.0; double dDbJUb = 0.0; for (int s = 0; s < m_nHorizontalOrder; s++) { //dDaUa += dataUa[k][iElementA+s][iB] * dDxBasis1D[s][i]; dDaUb += dataUb[k][iElementA+s][iB] * dDxBasis1D[s][i]; dDbUa += dataUa[k][iA][iElementB+s] * dDxBasis1D[s][j]; //dDbUb += dataUb[k][iA][iElementB+s] * dDxBasis1D[s][j]; dDaJUa += m_dataJacobian2D[iElementA+s][iB] * m_dBufferConU[0][s][j] * dDxBasis1D[s][i]; dDbJUb += m_dataJacobian2D[iA][iElementB+s] * m_dBufferConU[1][i][s] * dDxBasis1D[s][j]; } dDaUb *= dInvElementDeltaA; dDbUa *= dInvElementDeltaB; dDaJUa *= dInvElementDeltaA; dDbJUb *= dInvElementDeltaB; /* if (fDiscontinuous) { _EXCEPTIONT("This needs to be updated for covariant indices"); double dUpdateDerivA = dFluxDeriv1D[m_nHorizontalOrder-1] / GetElementDeltaA(); double dUpdateDerivB = dFluxDeriv1D[m_nHorizontalOrder-1] / GetElementDeltaB(); if (i == 0) { double dUaL = dataUa[k][iA-1][iB]; double dUaR = dataUa[k][iA ][iB]; double dUbL = dataUb[k][iA-1][iB]; double dUbR = dataUb[k][iA ][iB]; dDaUa += 0.5 * dUpdateDerivA * (dUaR - dUaL); dDaUb += 0.5 * dUpdateDerivA * (dUbR - dUbL); } if (i == m_nHorizontalOrder-1) { double dUaL = dataUa[k][iA ][iB]; double dUaR = dataUa[k][iA+1][iB]; double dUbL = dataUb[k][iA ][iB]; double dUbR = dataUb[k][iA+1][iB]; dDaUa += 0.5 * dUpdateDerivA * (dUaR - dUaL); dDaUb += 0.5 * dUpdateDerivA * (dUbR - dUbL); } if (j == 0) { double dUaL = dataUa[k][iA][iB-1]; double dUaR = dataUa[k][iA][iB ]; double dUbL = dataUb[k][iA][iB-1]; double dUbR = dataUb[k][iA][iB ]; dDbUa += 0.5 * dUpdateDerivB * (dUaR - dUaL); dDbUb += 0.5 * dUpdateDerivB * (dUbR - dUbL); } if (j == m_nHorizontalOrder-1) { double dUaL = dataUa[k][iA][iB ]; double dUaR = dataUa[k][iA][iB+1]; double dUbL = dataUb[k][iA][iB ]; double dUbR = dataUb[k][iA][iB+1]; dDbUa += 0.5 * dUpdateDerivB * (dUaR - dUaL); dDbUb += 0.5 * dUpdateDerivB * (dUbR - dUbL); } } */ m_dataDivergence[k][iA][iB] = (dDaJUa + dDbJUb) / m_dataJacobian2D[iA][iB]; m_dataVorticity[k][iA][iB] = (dDaUb - dDbUa) / m_dataJacobian2D[iA][iB]; /* // Compute covariant derivatives at node double dCovDaUa = dDaUa + m_dataChristoffelA[iA][iB][0] * dUa + m_dataChristoffelA[iA][iB][1] * 0.5 * dUb; double dCovDaUb = dDaUb + m_dataChristoffelB[iA][iB][0] * dUa + m_dataChristoffelB[iA][iB][1] * 0.5 * dUb; double dCovDbUa = dDbUa + m_dataChristoffelA[iA][iB][1] * 0.5 * dUa + m_dataChristoffelA[iA][iB][2] * dUb; double dCovDbUb = dDbUb + m_dataChristoffelB[iA][iB][1] * 0.5 * dUa + m_dataChristoffelB[iA][iB][2] * dUb; // Compute curl at node m_dataVorticity[k][iA][iB] = m_dataJacobian2D[iA][iB] * ( + m_dataContraMetric2DA[iA][iB][0] * dCovDaUb + m_dataContraMetric2DA[iA][iB][1] * dCovDbUb - m_dataContraMetric2DB[iA][iB][0] * dCovDaUa - m_dataContraMetric2DB[iA][iB][1] * dCovDbUa); // Compute the divergence at node m_dataDivergence[k][iA][iB] = dCovDaUa + dCovDbUb; //double dInvJacobian = 1.0 / m_dataJacobian2D[iA][iB]; //m_dataDivergence[k][iA][iB] = // dInvJacobian * (dDaJUa + dDbJUb); */ } } } } } }
void GridPatchCSGLL::EvaluateGeometricTerms() { // Physical constants const PhysicalConstants & phys = m_grid.GetModel().GetPhysicalConstants(); // 2D equation set bool fIs2DEquationSet = false; if (m_grid.GetModel().GetEquationSet().GetDimensionality() == 2) { fIs2DEquationSet = true; } if ((fIs2DEquationSet) && (m_grid.GetZtop() != 1.0)) { _EXCEPTIONT("Ztop must be 1.0 for 2D equation sets"); } // Obtain Gauss Lobatto quadrature nodes and weights DataArray1D<double> dGL; DataArray1D<double> dWL; GaussLobattoQuadrature::GetPoints(m_nHorizontalOrder, 0.0, 1.0, dGL, dWL); // Obtain normalized areas in the vertical const DataArray1D<double> & dWNode = m_grid.GetREtaLevelsNormArea(); const DataArray1D<double> & dWREdge = m_grid.GetREtaInterfacesNormArea(); // Verify that normalized areas are correct double dWNodeSum = 0.0; for (int k = 0; k < dWNode.GetRows(); k++) { dWNodeSum += dWNode[k]; } if (fabs(dWNodeSum - 1.0) > 1.0e-13) { _EXCEPTION1("Error in normalized areas (%1.15e)", dWNodeSum); } if (m_grid.GetVerticalStaggering() != Grid::VerticalStaggering_Interfaces ) { double dWREdgeSum = 0.0; for (int k = 0; k < dWREdge.GetRows(); k++) { dWREdgeSum += dWREdge[k]; } if (fabs(dWREdgeSum - 1.0) > 1.0e-13) { _EXCEPTION1("Error in normalized areas (%1.15e)", dWREdgeSum); } } // Derivatives of basis functions GridCSGLL & gridCSGLL = dynamic_cast<GridCSGLL &>(m_grid); const DataArray2D<double> & dDxBasis1D = gridCSGLL.GetDxBasis1D(); // Initialize the Coriolis force at each node for (int i = 0; i < m_box.GetATotalWidth(); i++) { for (int j = 0; j < m_box.GetBTotalWidth(); j++) { m_dataCoriolisF[i][j] = 2.0 * phys.GetOmega() * sin(m_dataLat[i][j]); } } // Initialize metric in terrain-following coords for (int a = 0; a < GetElementCountA(); a++) { for (int b = 0; b < GetElementCountB(); b++) { for (int i = 0; i < m_nHorizontalOrder; i++) { for (int j = 0; j < m_nHorizontalOrder; j++) { // Nodal points int iElementA = m_box.GetAInteriorBegin() + a * m_nHorizontalOrder; int iElementB = m_box.GetBInteriorBegin() + b * m_nHorizontalOrder; int iA = iElementA + i; int iB = iElementB + j; // Gnomonic coordinates double dX = tan(m_dANode[iA]); double dY = tan(m_dBNode[iB]); double dDelta2 = (1.0 + dX * dX + dY * dY); double dDelta = sqrt(dDelta2); // Topography height and its derivatives double dZs = m_dataTopography[iA][iB]; double dDaZs = m_dataTopographyDeriv[0][iA][iB]; double dDbZs = m_dataTopographyDeriv[1][iA][iB]; // 2D equations if (fIs2DEquationSet) { dZs = 0.0; dDaZs = 0.0; dDbZs = 0.0; } // Initialize 2D Jacobian m_dataJacobian2D[iA][iB] = (1.0 + dX * dX) * (1.0 + dY * dY) / (dDelta * dDelta * dDelta); m_dataJacobian2D[iA][iB] *= phys.GetEarthRadius() * phys.GetEarthRadius(); // Initialize 2D contravariant metric double dContraMetricScale = dDelta2 / (1.0 + dX * dX) / (1.0 + dY * dY) / (phys.GetEarthRadius() * phys.GetEarthRadius()); m_dataContraMetric2DA[iA][iB][0] = dContraMetricScale * (1.0 + dY * dY); m_dataContraMetric2DA[iA][iB][1] = dContraMetricScale * dX * dY; m_dataContraMetric2DB[iA][iB][0] = dContraMetricScale * dX * dY; m_dataContraMetric2DB[iA][iB][1] = dContraMetricScale * (1.0 + dX * dX); // Initialize 2D covariant metric double dCovMetricScale = phys.GetEarthRadius() * phys.GetEarthRadius() * (1.0 + dX * dX) * (1.0 + dY * dY) / (dDelta2 * dDelta2); m_dataCovMetric2DA[iA][iB][0] = dCovMetricScale * (1.0 + dX * dX); m_dataCovMetric2DA[iA][iB][1] = dCovMetricScale * (- dX * dY); m_dataCovMetric2DB[iA][iB][0] = dCovMetricScale * (- dX * dY); m_dataCovMetric2DB[iA][iB][1] = dCovMetricScale * (1.0 + dY * dY); // Vertical coordinate transform and its derivatives for (int k = 0; k < m_grid.GetRElements(); k++) { // Gal-Chen and Somerville (1975) linear terrain-following coord double dREta = m_grid.GetREtaLevel(k); /* double dREtaStretch; double dDxREtaStretch; m_grid.EvaluateVerticalStretchF( dREta, dREtaStretch, dDxREtaStretch); double dZ = dZs + (m_grid.GetZtop() - dZs) * dREtaStretch; double dDaR = (1.0 - dREtaStretch) * dDaZs; double dDbR = (1.0 - dREtaStretch) * dDbZs; double dDxR = (m_grid.GetZtop() - dZs) * dDxREtaStretch; */ double dZ = dZs + (m_grid.GetZtop() - dZs) * dREta; double dDaR = (1.0 - dREta) * dDaZs; double dDbR = (1.0 - dREta) * dDbZs; double dDxR = (m_grid.GetZtop() - dZs); // Calculate pointwise Jacobian m_dataJacobian[k][iA][iB] = dDxR * m_dataJacobian2D[iA][iB]; // Element area associated with each model level GLL node m_dataElementAreaNode[k][iA][iB] = m_dataJacobian[k][iA][iB] * dWL[i] * GetElementDeltaA() * dWL[j] * GetElementDeltaB() * dWNode[k]; // Contravariant metric components m_dataContraMetricA[k][iA][iB][0] = m_dataContraMetric2DA[iA][iB][0]; m_dataContraMetricA[k][iA][iB][1] = m_dataContraMetric2DA[iA][iB][1]; m_dataContraMetricA[k][iA][iB][2] = - dContraMetricScale / dDxR * ( (1.0 + dY * dY) * dDaR + dX * dY * dDbR); m_dataContraMetricB[k][iA][iB][0] = m_dataContraMetric2DB[iA][iB][0]; m_dataContraMetricB[k][iA][iB][1] = m_dataContraMetric2DB[iA][iB][1]; m_dataContraMetricB[k][iA][iB][2] = - dContraMetricScale / dDxR * ( dX * dY * dDaR + (1.0 + dX * dX) * dDbR); m_dataContraMetricXi[k][iA][iB][0] = m_dataContraMetricA[k][iA][iB][2]; m_dataContraMetricXi[k][iA][iB][1] = m_dataContraMetricB[k][iA][iB][2]; m_dataContraMetricXi[k][iA][iB][2] = 1.0 / (dDxR * dDxR) - 1.0 / dDxR * ( m_dataContraMetricXi[k][iA][iB][0] * dDaR + m_dataContraMetricXi[k][iA][iB][1] * dDbR); // Derivatives of the vertical coordinate transform m_dataDerivRNode[k][iA][iB][0] = dDaR; m_dataDerivRNode[k][iA][iB][1] = dDbR; m_dataDerivRNode[k][iA][iB][2] = dDxR; } // Metric terms at vertical interfaces for (int k = 0; k <= m_grid.GetRElements(); k++) { // Gal-Chen and Somerville (1975) linear terrain-following coord double dREta = m_grid.GetREtaInterface(k); /* double dREtaStretch; double dDxREtaStretch; m_grid.EvaluateVerticalStretchF( dREta, dREtaStretch, dDxREtaStretch); double dZ = dZs + (m_grid.GetZtop() - dZs) * dREtaStretch; double dDaR = (1.0 - dREtaStretch) * dDaZs; double dDbR = (1.0 - dREtaStretch) * dDbZs; double dDxR = (m_grid.GetZtop() - dZs) * dDxREtaStretch; */ double dZ = dZs + (m_grid.GetZtop() - dZs) * dREta; double dDaR = (1.0 - dREta) * dDaZs; double dDbR = (1.0 - dREta) * dDbZs; double dDxR = (m_grid.GetZtop() - dZs); // Calculate pointwise Jacobian m_dataJacobianREdge[k][iA][iB] = (1.0 + dX * dX) * (1.0 + dY * dY) / (dDelta * dDelta * dDelta); m_dataJacobianREdge[k][iA][iB] *= dDxR * phys.GetEarthRadius() * phys.GetEarthRadius(); // Element area associated with each model interface GLL node m_dataElementAreaREdge[k][iA][iB] = m_dataJacobianREdge[k][iA][iB] * dWL[i] * GetElementDeltaA() * dWL[j] * GetElementDeltaB() * dWREdge[k]; // Contravariant metric (alpha) m_dataContraMetricAREdge[k][iA][iB][0] = m_dataContraMetric2DA[iA][iB][0]; m_dataContraMetricAREdge[k][iA][iB][1] = m_dataContraMetric2DA[iA][iB][1]; m_dataContraMetricAREdge[k][iA][iB][2] = - dContraMetricScale / dDxR * ( (1.0 + dY * dY) * dDaR + dX * dY * dDbR); // Contravariant metric (beta) m_dataContraMetricBREdge[k][iA][iB][0] = m_dataContraMetric2DB[iA][iB][0]; m_dataContraMetricBREdge[k][iA][iB][1] = m_dataContraMetric2DB[iA][iB][1]; m_dataContraMetricBREdge[k][iA][iB][2] = - dContraMetricScale / dDxR * ( dX * dY * dDaR + (1.0 + dX * dX) * dDbR); // Contravariant metric (xi) m_dataContraMetricXiREdge[k][iA][iB][0] = - dContraMetricScale / dDxR * ( (1.0 + dY * dY) * dDaR + dX * dY * dDbR); m_dataContraMetricXiREdge[k][iA][iB][1] = - dContraMetricScale / dDxR * ( dX * dY * dDaR + (1.0 + dX * dX) * dDbR); m_dataContraMetricXiREdge[k][iA][iB][2] = 1.0 / (dDxR * dDxR) - 1.0 / dDxR * ( m_dataContraMetricXiREdge[k][iA][iB][0] * dDaR + m_dataContraMetricXiREdge[k][iA][iB][1] * dDbR); // Derivatives of the vertical coordinate transform m_dataDerivRREdge[k][iA][iB][0] = dDaR; m_dataDerivRREdge[k][iA][iB][1] = dDbR; m_dataDerivRREdge[k][iA][iB][2] = dDxR; } } } } } }
void GridPatchCSGLL::EvaluateTopography( const TestCase & test ) { const PhysicalConstants & phys = m_grid.GetModel().GetPhysicalConstants(); // Compute values of topography for (int i = 0; i < m_box.GetATotalWidth(); i++) { for (int j = 0; j < m_box.GetBTotalWidth(); j++) { double dLon; double dLat; CubedSphereTrans::RLLFromABP( m_dANode[i], m_dBNode[j], m_box.GetPanel(), dLon, dLat); m_dataTopography[i][j] = test.EvaluateTopography(phys, dLon, dLat); } } // Get derivatves from basis GridCSGLL & gridCSGLL = dynamic_cast<GridCSGLL &>(m_grid); const DataArray2D<double> & dDxBasis1D = gridCSGLL.GetDxBasis1D(); // Compute derivatives of topography for (int a = 0; a < GetElementCountA(); a++) { for (int b = 0; b < GetElementCountB(); b++) { for (int i = 0; i < m_nHorizontalOrder; i++) { for (int j = 0; j < m_nHorizontalOrder; j++) { // Nodal points int iElementA = m_box.GetAInteriorBegin() + a * m_nHorizontalOrder; int iElementB = m_box.GetBInteriorBegin() + b * m_nHorizontalOrder; int iA = iElementA + i; int iB = iElementB + j; // Topography height and its derivatives double dZs = m_dataTopography[iA][iB]; double dDaZs = 0.0; double dDbZs = 0.0; for (int s = 0; s < m_nHorizontalOrder; s++) { dDaZs += dDxBasis1D[s][i] * m_dataTopography[iElementA+s][iB]; dDbZs += dDxBasis1D[s][j] * m_dataTopography[iA][iElementB+s]; } dDaZs /= GetElementDeltaA(); dDbZs /= GetElementDeltaB(); m_dataTopographyDeriv[0][iA][iB] = dDaZs; m_dataTopographyDeriv[1][iA][iB] = dDbZs; } } } } }
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]); } } } }