void GridPatchCSGLL::ComputeVorticityDivergence( int iDataIndex ) { // Physical constants const PhysicalConstants & phys = m_grid.GetModel().GetPhysicalConstants(); // Working data DataArray4D<double> & dataState = GetDataState(iDataIndex, DataLocation_Node); if (dataState.GetSize(0) < 2) { _EXCEPTIONT( "Insufficient components for vorticity calculation"); } // Get the alpha and beta components of vorticity DataArray3D<double> dataUa; dataUa.SetSize( dataState.GetSize(1), dataState.GetSize(2), dataState.GetSize(3)); DataArray3D<double> dataUb; dataUb.SetSize( dataState.GetSize(1), dataState.GetSize(2), dataState.GetSize(3)); dataUa.AttachToData(&(dataState[0][0][0][0])); dataUb.AttachToData(&(dataState[1][0][0][0])); // Compute the radial component of the curl of the velocity field ComputeCurlAndDiv(dataUa, dataUb); }
void GridCartesianGLL::ApplyDSS( int iDataUpdate, DataType eDataType ) { // Exchange data between nodes Exchange(eDataType, iDataUpdate); // Post-process velocities across panel edges and // perform direct stiffness summation (DSS) for (int n = 0; n < GetActivePatchCount(); n++) { GridPatchCartesianGLL * pPatch = dynamic_cast<GridPatchCartesianGLL*>(GetActivePatch(n)); const PatchBox & box = pPatch->GetPatchBox(); // Patch-specific quantities int nElementCountA = pPatch->GetElementCountA(); int nElementCountB = pPatch->GetElementCountB(); // Apply panel transforms to velocity data if (eDataType == DataType_State) { pPatch->TransformHaloVelocities(iDataUpdate); } if (eDataType == DataType_TopographyDeriv) { pPatch->TransformTopographyDeriv(); } // Loop through all components associated with this DataType int nComponents; if (eDataType == DataType_State) { nComponents = m_model.GetEquationSet().GetComponents(); } else if (eDataType == DataType_Tracers) { nComponents = m_model.GetEquationSet().GetTracers(); } else if (eDataType == DataType_Vorticity) { nComponents = 1; } else if (eDataType == DataType_Divergence) { nComponents = 1; } else if (eDataType == DataType_TopographyDeriv) { nComponents = 2; } else { _EXCEPTIONT("Invalid DataType"); } // Apply BC only to state DSS if (eDataType == DataType_State) { pPatch->ApplyBoundaryConditions(iDataUpdate, DataType_State, n); } // Perform Direct Stiffness Summation (DSS) for (int c = 0; c < nComponents; c++) { // Obtain the array of working data int nRElements = GetRElements(); DataArray3D<double> pDataUpdate; if ((eDataType == DataType_State) && (GetVarLocation(c) == DataLocation_REdge) ) { nRElements++; } if (eDataType == DataType_TopographyDeriv) { nRElements = 2; } pDataUpdate.SetSize( nRElements, box.GetATotalWidth(), box.GetBTotalWidth()); // State data if (eDataType == DataType_State) { DataArray4D<double> & dState = pPatch->GetDataState(iDataUpdate, GetVarLocation(c)); pDataUpdate.AttachToData(&(dState[c][0][0][0])); // Tracer data } else if (eDataType == DataType_Tracers) { DataArray4D<double> & dTracers = pPatch->GetDataTracers(iDataUpdate); pDataUpdate.AttachToData(&(dTracers[c][0][0][0])); // Vorticity data } else if (eDataType == DataType_Vorticity) { DataArray3D<double> & dVorticity = pPatch->GetDataVorticity(); pDataUpdate.AttachToData(&(dVorticity[0][0][0])); // Divergence data } else if (eDataType == DataType_Divergence) { DataArray3D<double> & dDivergence = pPatch->GetDataDivergence(); pDataUpdate.AttachToData(&(dDivergence[0][0][0])); // Topographic derivative data } else if (eDataType == DataType_TopographyDeriv) { DataArray3D<double> & dTopographyDeriv = pPatch->GetTopographyDeriv(); pDataUpdate.AttachToData(&(dTopographyDeriv[0][0][0])); } // Averaging DSS across patch boundaries for (int k = 0; k < nRElements; k++) { // Average in the alpha direction for (int a = 0; a <= nElementCountA; a++) { int iA = a * m_nHorizontalOrder + box.GetHaloElements(); // Averaging done at the corners of the panel int jBegin = box.GetBInteriorBegin()-1; int jEnd = box.GetBInteriorEnd()+1; // Perform averaging across edge of patch for (int j = jBegin; j < jEnd; j++) { pDataUpdate[k][iA][j] = 0.5 * ( + pDataUpdate[k][iA ][j] + pDataUpdate[k][iA-1][j]); pDataUpdate[k][iA-1][j] = pDataUpdate[k][iA][j]; } } // Average in the beta direction for (int b = 0; b <= nElementCountB; b++) { int iB = b * m_nHorizontalOrder + box.GetHaloElements(); // Averaging done at the corners of the panel int iBegin = box.GetAInteriorBegin()-1; int iEnd = box.GetAInteriorEnd()+1; for (int i = iBegin; i < iEnd; i++) { pDataUpdate[k][i][iB] = 0.5 * ( + pDataUpdate[k][i][iB ] + pDataUpdate[k][i][iB-1]); pDataUpdate[k][i][iB-1] = pDataUpdate[k][i][iB]; } } } } } }
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]); } } } }