void Demultiplexer::dataChanged() { if ( hasProperty("numInput") && dataInt("numInput") != -1 ) { int addressSize = int( std::ceil( std::log( (double)dataInt("numInput") ) / std::log(2.0) ) ); property("numInput")->setValue(-1); if ( addressSize < 1 ) addressSize = 1; else if ( addressSize > 8 ) addressSize = 8; // This function will get called again when we set the value of numInput property("addressSize")->setValue(addressSize); return; } if ( hasProperty("numInput") ) { m_variantData["numInput"]->deleteLater(); m_variantData.remove("numInput"); } initPins( unsigned(dataInt("addressSize")) ); }
void MatrixDisplay::dataChanged() { QColor color = dataColor("color"); m_r = double(color.red()) / 0x100; m_g = double(color.green()) / 0x100; m_b = double(color.blue()) / 0x100; int numRows = dataInt("0-rows"); int numCols = dataInt("1-cols"); bool ledsChanged = (numRows != int(m_numRows)) || (numCols != int(m_numCols)); if (ledsChanged) { for (unsigned i = 0; i < m_numCols; i++) for (unsigned j = 0; j < m_numRows; j++) // must remove elements before re-organizing storage. removeElement(&(m_LEDs[i][j].m_pDiode), (i == (m_numCols - 1)) && (j == (m_numRows - 1))); initPins(numRows, numCols); } bool rowCathode = dataString("diode-configuration") == "Row Cathode"; if ((rowCathode != m_bRowCathode) || ledsChanged) { m_bRowCathode = rowCathode; for (unsigned i = 0; i < m_numCols; i++) { for (unsigned j = 0; j < m_numRows; j++) { if (rowCathode) { setup2pinElement(m_LEDs[i][j].m_pDiode, m_pColNodes[i]->pin(), m_pRowNodes[j]->pin()); } else setup2pinElement(m_LEDs[i][j].m_pDiode, m_pRowNodes[j]->pin(), m_pColNodes[i]->pin()); } } } }
void RAM::dataChanged() { m_wordSize = dataInt("wordSize"); m_addressSize = dataInt("addressSize"); int newSize = int(m_wordSize * std::pow(2., m_addressSize)); m_data.resize(newSize); initPins(); }
void BinaryCounter::dataChanged() { initPins( dataInt("bitcount") ); b_triggerHigh = dataString("trig") == "Rising"; setDisplayText( ">", b_triggerHigh ? "^>" : "_>" ); }
void ResistorDIP::initPins() { const int count = dataInt("count"); const double resistance = dataDouble("resistance"); if ( count == m_resistorCount ) return; if ( count < m_resistorCount ) { for ( int i=count; i<m_resistorCount; ++i ) { removeElement( m_resistance[i], false ); m_resistance[i] = 0l; removeNode( "n"+QString::number(i) ); removeNode( "p"+QString::number(i) ); } } else { for ( int i=m_resistorCount; i<count; ++i ) { const QString nid = "n"+QString::number(i); const QString pid = "p"+QString::number(i); m_resistance[i] = createResistance( createPin( -24, 0, 0, nid ), createPin( 24, 0, 180, pid ), resistance ); } } m_resistorCount = count; setSize( -16, -count*8, 32, count*16, true ); updateDIPNodePositions(); }
void LEDBarGraphDisplay::initPins() { unsigned int numRows = dataInt("rows"); if (numRows == m_numRows) return; if (numRows > max_LED_rows) numRows = max_LED_rows; if (numRows < 1) numRows = 1; // Create a list of named pins. // A default setup looks like: // ------- // p_0--|1 14|--n_0 // p_1--|2 13|--n_1 // p_2--|3 12|--n_2 // p_3--|4 11|--n_3 // p_4--|5 10|--n_4 // p_5--|6 9|--n_5 // p_6--|7 8|--n_6 // ------- // And this is the scheme used to create the nodes and diodes. // Create the positive & negative pin names in an anticlockwise fashion // as shown in the pin schematic above. QStringList pins; for (unsigned i = 0; i < numRows; i++) pins += QString("p_" + QString::number(i)); for (int i = numRows - 1; i >= 0; i--) pins += QString("n_" + QString::number(i)); // Set the size of the component *BEFORE* initDIP() is called // as initDIP() uses this data to initialise the pin positions. setSize(-16, -(numRows + 1) * 8, 32, (numRows + 1) * 16, true); // Create the nodes. initDIP(pins); // Create or remove LED parts if (numRows > m_numRows) { // Create the extra LED parts required. for (unsigned i = m_numRows; i < numRows; i++) m_LEDParts[i] = new LEDPart((Component*)this, QString("p_" + QString::number(i)), QString("n_" + QString::number(i))); } else { // Remove excess LED parts. for (unsigned i = numRows; i < m_numRows; i++) { delete m_LEDParts[i]; m_LEDParts[i] = 0; } } m_numRows = numRows; }
void DPLine::dataChanged() { setPen( QPen( dataColor("line-color"), unsigned( dataInt("line-width") ), getDataPenStyle("line-style"), getDataPenCapStyle("cap-style"), Qt::MiterJoin ) ); postResize(); // in case the pen width has changed update(); }
void ECKeyPad::dataChanged() { initPins(dataInt("numCols")); bool useToggle = dataBool("useToggles"); bool bounce = dataBool("bounce"); int bouncePeriod_ms = int(dataDouble("bounce_period") * 1e3); for (unsigned i = 0; i < 4; i++) { for (unsigned j = 0; j < m_numCols; j++) { button(buttonID(i, j))->setToggle(useToggle); m_switch[i][j]->setBounce(bounce, bouncePeriod_ms); } } }
void DPRectangle::dataChanged() { bool displayBackground = dataBool("background"); QColor line_color = dataColor("line-color"); unsigned width = unsigned( dataInt("line-width") ); Qt::PenStyle style = getDataPenStyle("line-style"); setPen( QPen( line_color, width, style ) ); if (displayBackground) setBrush( dataColor("background-color") ); else setBrush( Qt::NoBrush ); postResize(); update(); }
void BusSplitter::dataChanged() { unsigned busSize = dataInt("size"); if ( busSize < 1 ) busSize = 1; else if ( busSize > MAX_BUS_SIZE ) busSize = MAX_BUS_SIZE; if ( busSize == m_busSize ) return; m_pInNode->setNumPins(busSize); if ( busSize > m_busSize ) { m_pWires.resize(busSize); for ( unsigned i = m_busSize; i < unsigned(busSize); i++ ) { Pin * pin = createPin( 16, 0, 180, outNodeID(i) )->pin(); m_pWires[i] = new Wire( m_pInNode->pin(i), pin ); } } else { for ( unsigned i = busSize; i < unsigned(m_busSize); i++ ) { removeNode( outNodeID(i) ); delete m_pWires[i]; } m_pWires.resize(busSize); } m_busSize = busSize; // Position pins setSize( 0, -int(m_busSize+1)*8, 8, int(m_busSize+1)*16, true ); for ( int i = 0; i < int(m_busSize); i++ ) m_nodeMap[ outNodeID(i) ].y = 16*i - int(m_busSize+1)*8 + 24; m_nodeMap["n1"].y = -int(m_busSize+1)*8 + 8; updateAttachedPositioning(); }
void RAM::initPins() { int oldWordSize = m_dataIn.size(); int oldAddressSize = m_address.size(); int newWordSize = dataInt("wordSize"); int newAddressSize = dataInt("addressSize"); if ( newAddressSize == oldAddressSize && newWordSize == oldWordSize ) return; QStringList leftPins; // Pins on left of IC leftPins << "CS" << "OE" << "WE"; for ( int i = 0; i < newAddressSize; ++i ) leftPins << QString("A%1").arg( QString::number(i) ); QStringList rightPins; // Pins on right of IC for ( unsigned i = newWordSize; i > 0; --i ) rightPins << QString("DI%1").arg( QString::number(i-1) ); for ( unsigned i = newWordSize; i > 0; --i ) rightPins << QString("DO%1").arg( QString::number(i-1) ); // Make pin lists of consistent sizes for ( unsigned i = leftPins.size(); i < rightPins.size(); ++i ) leftPins.append(""); for ( unsigned i = rightPins.size(); i < leftPins.size(); ++i ) rightPins.prepend(""); QStringList pins = leftPins + rightPins; initDIPSymbol( pins, 72 ); initDIP(pins); ECNode *node; if (!m_pCS) { node = ecNodeWithID("CS"); m_pCS = createLogicIn(node); m_pCS->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) ); } if (!m_pOE) { node = ecNodeWithID("OE"); m_pOE = createLogicIn(node); m_pOE->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) ); } if (!m_pWE) { node = ecNodeWithID("WE"); m_pWE = createLogicIn(node); m_pWE->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) ); } if ( newWordSize > oldWordSize ) { m_dataIn.resize(newWordSize); m_dataOut.resize(newWordSize); for ( int i = oldWordSize; i < newWordSize; ++i ) { node = ecNodeWithID( QString("DI%1").arg( QString::number(i) ) ); m_dataIn.insert( i, createLogicIn(node) ); m_dataIn[i]->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) ); node = ecNodeWithID( QString("DO%1").arg( QString::number(i) ) ); m_dataOut.insert( i, createLogicOut(node, false) ); } } else if ( newWordSize < oldWordSize ) { for ( int i = newWordSize; i < oldWordSize; ++i ) { QString id = QString("DO%1").arg( QString::number(i) ); removeDisplayText(id); removeElement( m_dataIn[i], false ); removeNode(id); id = QString("DI%1").arg( QString::number(i) ); removeDisplayText(id); removeElement( m_dataOut[i], false ); removeNode(id); } m_dataIn.resize(newWordSize); m_dataOut.resize(newWordSize); } if ( newAddressSize > oldAddressSize ) { m_address.resize(newAddressSize); for ( int i = oldAddressSize; i < newAddressSize; ++i ) { node = ecNodeWithID( QString("A%1").arg( QString::number(i) ) ); m_address.insert( i, createLogicIn(node) ); m_address[i]->setCallback( this, (CallbackPtr)(&RAM::inStateChanged) ); } } else if ( newAddressSize < oldAddressSize ) { for ( int i = newAddressSize; i < oldAddressSize; ++i ) { QString id = QString("A%1").arg( QString::number(i) ); removeDisplayText(id); removeElement( m_address[i], false ); removeNode(id); } m_address.resize(newAddressSize); } }
void MultiInputGate::dataChanged() { updateInputs(QMIN(maxGateInput, dataInt("numInput"))); }
int main(int argc, char ** argv) { MPI_Init(&argc, &argv); NcError error(NcError::silent_nonfatal); try { // Input filename std::string strInputFile; // Output filename std::string strOutputFile; // Separate topography file std::string strTopographyFile; // List of variables to extract std::string strVariables; // Extract geopotential height bool fGeopotentialHeight; // Pressure levels to extract std::string strPressureLevels; // Height levels to extract std::string strHeightLevels; // Extract variables at the surface bool fExtractSurface; // Extract total energy bool fExtractTotalEnergy; // Parse the command line BeginCommandLine() CommandLineString(strInputFile, "in", ""); CommandLineString(strOutputFile, "out", ""); CommandLineString(strVariables, "var", ""); CommandLineBool(fGeopotentialHeight, "output_z"); CommandLineBool(fExtractTotalEnergy, "output_energy"); CommandLineString(strPressureLevels, "p", ""); CommandLineString(strHeightLevels, "z", ""); CommandLineBool(fExtractSurface, "surf"); ParseCommandLine(argc, argv); EndCommandLine(argv) AnnounceBanner(); // Check command line arguments if (strInputFile == "") { _EXCEPTIONT("No input file specified"); } if (strOutputFile == "") { _EXCEPTIONT("No output file specified"); } if (strVariables == "") { _EXCEPTIONT("No variables specified"); } // Parse variable string std::vector< std::string > vecVariableStrings; ParseVariableList(strVariables, vecVariableStrings); // Check variables if (vecVariableStrings.size() == 0) { _EXCEPTIONT("No variables specified"); } // Parse pressure level string std::vector<double> vecPressureLevels; ParseLevelArray(strPressureLevels, vecPressureLevels); int nPressureLevels = (int)(vecPressureLevels.size()); for (int k = 0; k < nPressureLevels; k++) { if (vecPressureLevels[k] <= 0.0) { _EXCEPTIONT("Non-positive pressure values not allowed"); } } // Parse height level string std::vector<double> vecHeightLevels; ParseLevelArray(strHeightLevels, vecHeightLevels); int nHeightLevels = (int)(vecHeightLevels.size()); // Check pressure levels if ((nPressureLevels == 0) && (nHeightLevels == 0) && (!fExtractSurface) ) { _EXCEPTIONT("No pressure / height levels to process"); } // Open input file AnnounceStartBlock("Loading input file"); NcFile ncdf_in(strInputFile.c_str(), NcFile::ReadOnly); if (!ncdf_in.is_valid()) { _EXCEPTION1("Unable to open file \"%s\" for reading", strInputFile.c_str()); } // Load time array Announce("Time"); NcVar * varTime = ncdf_in.get_var("time"); if (varTime == NULL) { _EXCEPTION1("File \"%s\" does not contain variable \"time\"", strInputFile.c_str()); } int nTime = varTime->get_dim(0)->size(); DataArray1D<double> dTime(nTime); varTime->set_cur((long)0); varTime->get(&(dTime[0]), nTime); // Load latitude array Announce("Latitude"); NcVar * varLat = ncdf_in.get_var("lat"); if (varLat == NULL) { _EXCEPTION1("File \"%s\" does not contain variable \"lat\"", strInputFile.c_str()); } int nLat = varLat->get_dim(0)->size(); DataArray1D<double> dLat(nLat); varLat->set_cur((long)0); varLat->get(&(dLat[0]), nLat); // Load longitude array Announce("Longitude"); NcVar * varLon = ncdf_in.get_var("lon"); if (varLon == NULL) { _EXCEPTION1("File \"%s\" does not contain variable \"lon\"", strInputFile.c_str()); } int nLon = varLon->get_dim(0)->size(); DataArray1D<double> dLon(nLon); varLon->set_cur((long)0); varLon->get(&(dLon[0]), nLon); // Load level array Announce("Level"); NcVar * varLev = ncdf_in.get_var("lev"); if (varLev == NULL) { _EXCEPTION1("File \"%s\" does not contain variable \"lev\"", strInputFile.c_str()); } int nLev = varLev->get_dim(0)->size(); DataArray1D<double> dLev(nLev); varLev->set_cur((long)0); varLev->get(&(dLev[0]), nLev); // Load level interface array Announce("Interface"); NcVar * varILev = ncdf_in.get_var("ilev"); int nILev = 0; DataArray1D<double> dILev; if (varILev == NULL) { Announce("Warning: Variable \"ilev\" not found"); } else { nILev = varILev->get_dim(0)->size(); if (nILev != nLev + 1) { _EXCEPTIONT("Variable \"ilev\" must have size lev+1"); } dILev.Allocate(nILev); varILev->set_cur((long)0); varILev->get(&(dILev[0]), nILev); } // Load topography Announce("Topography"); NcVar * varZs = ncdf_in.get_var("Zs"); if (varZs == NULL) { _EXCEPTION1("File \"%s\" does not contain variable \"Zs\"", strInputFile.c_str()); } DataArray2D<double> dZs(nLat, nLon); varZs->set_cur((long)0, (long)0); varZs->get(&(dZs[0][0]), nLat, nLon); AnnounceEndBlock("Done"); // Open output file AnnounceStartBlock("Constructing output file"); NcFile ncdf_out(strOutputFile.c_str(), NcFile::Replace); if (!ncdf_out.is_valid()) { _EXCEPTION1("Unable to open file \"%s\" for writing", strOutputFile.c_str()); } CopyNcFileAttributes(&ncdf_in, &ncdf_out); // Output time array Announce("Time"); NcDim * dimOutTime = ncdf_out.add_dim("time"); NcVar * varOutTime = ncdf_out.add_var("time", ncDouble, dimOutTime); varOutTime->set_cur((long)0); varOutTime->put(&(dTime[0]), nTime); CopyNcVarAttributes(varTime, varOutTime); // Output pressure array NcDim * dimOutP = NULL; NcVar * varOutP = NULL; if (nPressureLevels > 0) { Announce("Pressure"); dimOutP = ncdf_out.add_dim("p", nPressureLevels); varOutP = ncdf_out.add_var("p", ncDouble, dimOutP); varOutP->set_cur((long)0); varOutP->put(&(vecPressureLevels[0]), nPressureLevels); } // Output height array NcDim * dimOutZ = NULL; NcVar * varOutZ = NULL; if (nHeightLevels > 0) { Announce("Height"); dimOutZ = ncdf_out.add_dim("z", nHeightLevels); varOutZ = ncdf_out.add_var("z", ncDouble, dimOutZ); varOutZ->set_cur((long)0); varOutZ->put(&(vecHeightLevels[0]), nHeightLevels); } // Output latitude and longitude array Announce("Latitude"); NcDim * dimOutLat = ncdf_out.add_dim("lat", nLat); NcVar * varOutLat = ncdf_out.add_var("lat", ncDouble, dimOutLat); varOutLat->set_cur((long)0); varOutLat->put(&(dLat[0]), nLat); CopyNcVarAttributes(varLat, varOutLat); Announce("Longitude"); NcDim * dimOutLon = ncdf_out.add_dim("lon", nLon); NcVar * varOutLon = ncdf_out.add_var("lon", ncDouble, dimOutLon); varOutLon->set_cur((long)0); varOutLon->put(&(dLon[0]), nLon); CopyNcVarAttributes(varLon, varOutLon); // Output topography Announce("Topography"); NcVar * varOutZs = ncdf_out.add_var( "Zs", ncDouble, dimOutLat, dimOutLon); varOutZs->set_cur((long)0, (long)0); varOutZs->put(&(dZs[0][0]), nLat, nLon); AnnounceEndBlock("Done"); // Done AnnounceEndBlock("Done"); // Load all variables Announce("Loading variables"); std::vector<NcVar *> vecNcVar; for (int v = 0; v < vecVariableStrings.size(); v++) { vecNcVar.push_back(ncdf_in.get_var(vecVariableStrings[v].c_str())); if (vecNcVar[v] == NULL) { _EXCEPTION1("Unable to load variable \"%s\" from file", vecVariableStrings[v].c_str()); } } // Physical constants Announce("Initializing thermodynamic variables"); NcAtt * attEarthRadius = ncdf_in.get_att("earth_radius"); double dEarthRadius = attEarthRadius->as_double(0); NcAtt * attRd = ncdf_in.get_att("Rd"); double dRd = attRd->as_double(0); NcAtt * attCp = ncdf_in.get_att("Cp"); double dCp = attCp->as_double(0); double dGamma = dCp / (dCp - dRd); NcAtt * attP0 = ncdf_in.get_att("P0"); double dP0 = attP0->as_double(0); double dPressureScaling = dP0 * std::pow(dRd / dP0, dGamma); NcAtt * attZtop = ncdf_in.get_att("Ztop"); double dZtop = attZtop->as_double(0); // Input data DataArray3D<double> dataIn(nLev, nLat, nLon); DataArray3D<double> dataInt(nILev, nLat, nLon); // Output data DataArray2D<double> dataOut(nLat, nLon); // Pressure in column DataArray1D<double> dataColumnP(nLev); // Height in column DataArray1D<double> dataColumnZ(nLev); DataArray1D<double> dataColumnIZ(nILev); // Column weights DataArray1D<double> dW(nLev); DataArray1D<double> dIW(nILev); // Loop through all times, pressure levels and variables AnnounceStartBlock("Interpolating"); // Add energy variable NcVar * varEnergy; if (fExtractTotalEnergy) { varEnergy = ncdf_out.add_var("TE", ncDouble, dimOutTime); } // Create output pressure variables std::vector<NcVar *> vecOutNcVarP; if (nPressureLevels > 0) { for (int v = 0; v < vecVariableStrings.size(); v++) { vecOutNcVarP.push_back( ncdf_out.add_var( vecVariableStrings[v].c_str(), ncDouble, dimOutTime, dimOutP, dimOutLat, dimOutLon)); // Copy attributes CopyNcVarAttributes(vecNcVar[v], vecOutNcVarP[v]); } } // Create output height variables std::vector<NcVar *> vecOutNcVarZ; if (nHeightLevels > 0) { for (int v = 0; v < vecVariableStrings.size(); v++) { std::string strVarName = vecVariableStrings[v]; if (nPressureLevels > 0) { strVarName += "z"; } vecOutNcVarZ.push_back( ncdf_out.add_var( strVarName.c_str(), ncDouble, dimOutTime, dimOutZ, dimOutLat, dimOutLon)); // Copy attributes CopyNcVarAttributes(vecNcVar[v], vecOutNcVarZ[v]); } } // Create output surface variable std::vector<NcVar *> vecOutNcVarS; if (fExtractSurface) { for (int v = 0; v < vecVariableStrings.size(); v++) { std::string strVarName = vecVariableStrings[v]; strVarName += "S"; vecOutNcVarS.push_back( ncdf_out.add_var( strVarName.c_str(), ncDouble, dimOutTime, dimOutLat, dimOutLon)); // Copy attributes CopyNcVarAttributes(vecNcVar[v], vecOutNcVarS[v]); } } // Loop over all times for (int t = 0; t < nTime; t++) { char szAnnounce[256]; sprintf(szAnnounce, "Time %i", t); AnnounceStartBlock(szAnnounce); // Rho DataArray3D<double> dataRho(nLev, nLat, nLon); NcVar * varRho = ncdf_in.get_var("Rho"); if (varRho == NULL) { _EXCEPTIONT("Unable to load variable \"Rho\" from file"); } varRho->set_cur(t, 0, 0, 0); varRho->get(&(dataRho[0][0][0]), 1, nLev, nLat, nLon); // Pressure DataArray3D<double> dataP(nLev, nLat, nLon); if (nPressureLevels != 0) { NcVar * varP = ncdf_in.get_var("P"); if (varP == NULL) { _EXCEPTIONT("Unable to load variable \"P\" from file"); } varP->set_cur(t, 0, 0, 0); varP->get(&(dataP[0][0][0]), 1, nLev, nLat, nLon); } /* // Populate pressure array if (nPressureLevels > 0) { // Calculate pointwise pressure for (int k = 0; k < nLev; k++) { for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { dataP[k][i][j] = dPressureScaling * exp(log(dataRho[k][i][j] * dataP[k][i][j]) * dGamma); } } } } */ // Height everywhere DataArray3D<double> dataZ(nLev, nLat, nLon); DataArray3D<double> dataIZ; if (nILev != 0) { dataIZ.Allocate(nILev, nLat, nLon); } // Populate height array if ((nHeightLevels > 0) || (fGeopotentialHeight)) { for (int k = 0; k < nLev; k++) { for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { dataZ[k][i][j] = dZs[i][j] + dLev[k] * (dZtop - dZs[i][j]); } } } for (int k = 0; k < nILev; k++) { for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { dataIZ[k][i][j] = dZs[i][j] + dILev[k] * (dZtop - dZs[i][j]); } } } } // Loop through all pressure levels and variables for (int v = 0; v < vecNcVar.size(); v++) { bool fOnInterfaces = false; // Load in the data array vecNcVar[v]->set_cur(t, 0, 0, 0); if (vecNcVar[v]->get_dim(1)->size() == nLev) { vecNcVar[v]->get(&(dataIn[0][0][0]), 1, nLev, nLat, nLon); Announce("%s (n)", vecVariableStrings[v].c_str()); } else if (vecNcVar[v]->get_dim(1)->size() == nILev) { vecNcVar[v]->get(&(dataInt[0][0][0]), 1, nILev, nLat, nLon); fOnInterfaces = true; Announce("%s (i)", vecVariableStrings[v].c_str()); } else { _EXCEPTION1("Variable \"%s\" has invalid level dimension", vecVariableStrings[v].c_str()); } // At the physical surface if (fExtractSurface) { if (fOnInterfaces) { for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { dataOut[i][j] = dataInt[0][i][j]; } } } else { int kBegin = 0; int kEnd = 3; PolynomialInterp::LagrangianPolynomialCoeffs( 3, dLev, dW, 0.0); // Loop thorugh all latlon indices for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { // Interpolate in the vertical dataOut[i][j] = 0.0; for (int k = kBegin; k < kEnd; k++) { dataOut[i][j] += dW[k] * dataIn[k][i][j]; } } } } // Write variable vecOutNcVarS[v]->set_cur(t, 0, 0); vecOutNcVarS[v]->put(&(dataOut[0][0]), 1, nLat, nLon); } // Loop through all pressure levels for (int p = 0; p < nPressureLevels; p++) { // Loop thorugh all latlon indices for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { // Store column pressure for (int k = 0; k < nLev; k++) { dataColumnP[k] = dataP[k][i][j]; } // Find weights int kBegin = 0; int kEnd = 0; // On a pressure surface InterpolationWeightsLinear( vecPressureLevels[p], dataColumnP, kBegin, kEnd, dW); // Interpolate in the vertical dataOut[i][j] = 0.0; for (int k = kBegin; k < kEnd; k++) { dataOut[i][j] += dW[k] * dataIn[k][i][j]; } } } // Write variable vecOutNcVarP[v]->set_cur(t, p, 0, 0); vecOutNcVarP[v]->put(&(dataOut[0][0]), 1, 1, nLat, nLon); } // Loop through all height levels for (int z = 0; z < nHeightLevels; z++) { // Loop thorugh all latlon indices for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { // Find weights int kBegin = 0; int kEnd = 0; // Interpolate from levels to z surfaces if (!fOnInterfaces) { for (int k = 0; k < nLev; k++) { dataColumnZ[k] = dataZ[k][i][j]; } InterpolationWeightsLinear( vecHeightLevels[z], dataColumnZ, kBegin, kEnd, dW); dataOut[i][j] = 0.0; for (int k = kBegin; k < kEnd; k++) { dataOut[i][j] += dW[k] * dataIn[k][i][j]; } // Interpolate from interfaces to z surfaces } else { for (int k = 0; k < nILev; k++) { dataColumnIZ[k] = dataIZ[k][i][j]; } InterpolationWeightsLinear( vecHeightLevels[z], dataColumnIZ, kBegin, kEnd, dIW); dataOut[i][j] = 0.0; for (int k = kBegin; k < kEnd; k++) { dataOut[i][j] += dIW[k] * dataInt[k][i][j]; } } } } // Write variable vecOutNcVarZ[v]->set_cur(t, z, 0, 0); vecOutNcVarZ[v]->put(&(dataOut[0][0]), 1, 1, nLat, nLon); } } // Output geopotential height if (fGeopotentialHeight) { Announce("Geopotential height"); // Output variables NcVar * varOutZ; NcVar * varOutZs; if (nPressureLevels > 0) { varOutZ = ncdf_out.add_var( "PHIZ", ncDouble, dimOutTime, dimOutP, dimOutLat, dimOutLon); } if (fExtractSurface) { varOutZs = ncdf_out.add_var( "PHIZS", ncDouble, dimOutTime, dimOutLat, dimOutLon); } // Interpolate onto pressure levels for (int p = 0; p < nPressureLevels; p++) { // Loop thorugh all latlon indices for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { int kBegin = 0; int kEnd = 0; for (int k = 0; k < nLev; k++) { dataColumnP[k] = dataP[k][i][j]; } InterpolationWeightsLinear( vecPressureLevels[p], dataColumnP, kBegin, kEnd, dW); // Interpolate in the vertical dataOut[i][j] = 0.0; for (int k = kBegin; k < kEnd; k++) { dataOut[i][j] += dW[k] * dataZ[k][i][j]; } } } // Write variable varOutZ->set_cur(t, p, 0, 0); varOutZ->put(&(dataOut[0][0]), 1, 1, nLat, nLon); } // Interpolate onto the physical surface if (fExtractSurface) { int kBegin = 0; int kEnd = 3; PolynomialInterp::LagrangianPolynomialCoeffs( 3, dLev, dW, 0.0); // Loop thorugh all latlon indices for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { // Interpolate in the vertical dataOut[i][j] = 0.0; for (int k = kBegin; k < kEnd; k++) { dataOut[i][j] += dW[k] * dataZ[k][i][j]; } } } // Write variable varOutZs->set_cur(t, 0, 0); varOutZs->put(&(dataOut[0][0]), 1, nLat, nLon); } } // Extract total energy if (fExtractTotalEnergy) { Announce("Total Energy"); // Zonal velocity DataArray3D<double> dataU(nLev, nLat, nLon); NcVar * varU = ncdf_in.get_var("U"); varU->set_cur(t, 0, 0, 0); varU->get(&(dataU[0][0][0]), 1, nLev, nLat, nLon); // Meridional velocity DataArray3D<double> dataV(nLev, nLat, nLon); NcVar * varV = ncdf_in.get_var("V"); varV->set_cur(t, 0, 0, 0); varV->get(&(dataV[0][0][0]), 1, nLev, nLat, nLon); // Vertical velocity DataArray3D<double> dataW(nLev, nLat, nLon); NcVar * varW = ncdf_in.get_var("W"); varW->set_cur(t, 0, 0, 0); varW->get(&(dataW[0][0][0]), 1, nLev, nLat, nLon); // Calculate total energy double dTotalEnergy = 0.0; double dElementRefArea = dEarthRadius * dEarthRadius * M_PI / static_cast<double>(nLat) * 2.0 * M_PI / static_cast<double>(nLon); for (int k = 0; k < nLev; k++) { for (int i = 0; i < nLat; i++) { for (int j = 0; j < nLon; j++) { double dKineticEnergy = 0.5 * dataRho[k][i][j] * ( dataU[k][i][j] * dataU[k][i][j] + dataV[k][i][j] * dataV[k][i][j] + dataW[k][i][j] * dataW[k][i][j]); double dInternalEnergy = dataP[k][i][j] / (dGamma - 1.0); dTotalEnergy += (dKineticEnergy + dInternalEnergy) * std::cos(M_PI * dLat[i] / 180.0) * dElementRefArea * (dZtop - dZs[i][j]) / static_cast<double>(nLev); } } } // Put total energy into file varEnergy->set_cur(t); varEnergy->put(&dTotalEnergy, 1); } AnnounceEndBlock("Done"); } AnnounceEndBlock("Done"); } catch(Exception & e) { Announce(e.ToString().c_str()); } // Finalize MPI MPI_Finalize(); }