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 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 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::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; } } } } }