void ConstantSet::netcdf_define(NcFile &nc, std::string const &vname) { // Create the variable to store our constants NcVar *ncvar = giss::get_var_safe(nc, vname.c_str(), false); if (!ncvar) { auto oneDim = giss::get_or_add_dim(nc, "one", 1); ncvar = nc.add_var(vname.c_str(), ncDouble, oneDim); } // Store the constants as attributes for (int i=0; i<fields.size_withunit(); ++i) { CoupledField const &field(fields.field(i)); ncvar->add_att(field.name.c_str(), vals[i]); ncvar->add_att((field.name + "_units").c_str(), field.units.c_str()); ncvar->add_att((field.name + "_description").c_str(), field.description.c_str()); } }
void PointCounter::output(const string &fileName) const { NcFile file(fileName.c_str(), NcFile::Replace); if (!file.is_valid()) { string message = "Failed to open file "+fileName+"."; REPORT_ERROR(message.c_str()); } NcDim *numLonDim = file.add_dim("lon", counters.extent(0)); NcDim *numLatDim = file.add_dim("lat", counters.extent(1)); NcDim *numBndsDim = file.add_dim("bnds", 2); //NcDim *numLevDim = file.add_dim("lev", counters.extent(2)); NcVar *lonBndsVar = file.add_var("lon_bnds", ncDouble, numLonDim, numBndsDim); NcVar *latBndsVar = file.add_var("lat_bnds", ncDouble, numLatDim, numBndsDim); //NcVar *levVar = file.add_var("lev", ncDouble, numLevDim); lonBndsVar->add_att("long_name", "longitude bounds"); lonBndsVar->add_att("units", "degree_east"); latBndsVar->add_att("long_name", "latitude bounds"); latBndsVar->add_att("units", "degree_north"); int numLonBnds = mesh[0].getNumLon()-2, numLatBnds = mesh[0].getNumLat()-1; double lonBnds[numLonBnds][2], latBnds[numLatBnds][2]; for (int i = 0; i < numLonBnds; ++i) { lonBnds[i][0] = mesh[0].lon(i)*Rad2Deg; lonBnds[i][1] = mesh[0].lon(i+1)*Rad2Deg; } for (int j = 0; j < numLatBnds; ++j) { latBnds[j][0] = mesh[0].lat(j)*Rad2Deg; latBnds[j][1] = mesh[0].lat(j+1)*Rad2Deg; } lonBndsVar->put(&lonBnds[0][0], numLonBnds, 2); latBndsVar->put(&latBnds[0][0], numLatBnds, 2); NcVar *countersVar = file.add_var("counters", ncInt, numLatDim, numLonDim); countersVar->add_att("long_name", "contained point numbers in grid boxes"); int counters[this->counters.extent(1)][this->counters.extent(0)]; for (int j = 0; j < this->counters.extent(1); ++j) for (int i = 0; i < this->counters.extent(0); ++i) counters[j][i] = this->counters(i, j, 0); countersVar->put(&counters[0][0], this->counters.extent(1), this->counters.extent(0)); }
bool OutputClusters(const string &filename, const vector<Cluster> &theClusters, const RadarData_t &radarInfo, const ClustParams_t &clustParam) { NcFile clusterFile(filename.c_str(), NcFile::Replace); if (!clusterFile.is_valid()) { cerr << "Could not create file: " << filename << "\n"; return(false); } size_t pixelCnt = 0; for (vector<Cluster>::const_iterator aClust = theClusters.begin(); aClust != theClusters.end(); aClust++) { pixelCnt += aClust->size(); } NcDim* pixelDim = clusterFile.add_dim("pixel_index", pixelCnt); NcDim* latDim = clusterFile.add_dim("lat", radarInfo.dataEdges[1]); NcDim* lonDim = clusterFile.add_dim("lon", radarInfo.dataEdges[2]); NcVar* clustMember = clusterFile.add_var("clusterIndex", ncInt, pixelDim); clustMember->add_att("Description", "pixel cluster membership"); NcVar* xLoc = clusterFile.add_var("pixel_xLoc", ncInt, pixelDim); xLoc->add_att("Description", "x-index of pixel in domain (lat,lon)"); NcVar* yLoc = clusterFile.add_var("pixel_yLoc", ncInt, pixelDim); yLoc->add_att("Description", "y-index of pixel in domain (lat,lon)"); NcVar* lats = clusterFile.add_var("lat", ncDouble, latDim); lats->add_att("units", radarInfo.latUnits.c_str()); lats->add_att("spacing", radarInfo.latSpacing); NcVar* lons = clusterFile.add_var("lon", ncDouble, lonDim); lons->add_att("units", radarInfo.lonUnits.c_str()); lons->add_att("spacing", radarInfo.lonSpacing); clusterFile.add_att("title", "SPA Cluster Results of Radar Reflectivities"); clusterFile.add_att("data_source", radarInfo.inputFilename.c_str()); clusterFile.add_att("time", radarInfo.scanTime); // Need to do type-casting to double because the netcdf libraries can't seem to properly save a float. // Also, the truncf() is used to -- somewhat -- handle mantisa issues. clusterFile.add_att("Upper_Sensitivity", (double) (truncf(100.0 * clustParam.upperSensitivity)/100.0)); clusterFile.add_att("Lower_Sensitivity", (double) (truncf(100.0 * clustParam.lowerSensitivity)/100.0)); clusterFile.add_att("Padding_Level", (double) (truncf(100.0 * clustParam.paddingLevel)/100.0)); clusterFile.add_att("Reach", (double) (truncf(100.0 * clustParam.reach)/100.0)); clusterFile.add_att("Subcluster_Depth", clustParam.subClustDepth); int* clustIndicies = new int[pixelCnt]; int* xPixels = new int[pixelCnt]; int* yPixels = new int[pixelCnt]; size_t pixelIndex = 0; for (size_t clustIndex = 0; clustIndex < theClusters.size(); clustIndex++) { for (Cluster::const_iterator aMember = theClusters[clustIndex].begin(); aMember != theClusters[clustIndex].end(); aMember++, pixelIndex++) { clustIndicies[pixelIndex] = clustIndex; xPixels[pixelIndex] = aMember->XLoc; yPixels[pixelIndex] = aMember->YLoc; } } clustMember->put(clustIndicies, pixelCnt); xLoc->put(xPixels, pixelCnt); yLoc->put(yPixels, pixelCnt); lats->put(radarInfo.latVals, radarInfo.dataEdges[1]); lons->put(radarInfo.lonVals, radarInfo.dataEdges[2]); clusterFile.close(); delete [] clustIndicies; delete [] xPixels; delete [] yPixels; return(true); }
void PolygonManager::output(const string &fileName) { // ------------------------------------------------------------------------- NcFile file(fileName.c_str(), NcFile::Replace); if (!file.is_valid()) { string message = "Failed to open file "+fileName+"."; REPORT_ERROR(message.c_str()); } // ------------------------------------------------------------------------- // time information if (TimeManager::onLine()) { file.add_att("time", TimeManager::getSeconds()); file.add_att("time_step", TimeManager::getTimeStep()); file.add_att("steps", TimeManager::getSteps()); } // ------------------------------------------------------------------------- // dimensions NcDim *numVertexDim = file.add_dim("num_total_vertex", vertices.size()); NcDim *numEdgeDim = file.add_dim("num_total_edge", edges.size()); NcDim *numPolygonDim = file.add_dim("num_total_polygon", polygons.size()); // ------------------------------------------------------------------------- // vertices part NcVar *oldVtxLonVar = file.add_var("old_vertex_lon", ncDouble, numVertexDim); NcVar *oldVtxLatVar = file.add_var("old_vertex_lat", ncDouble, numVertexDim); NcVar *newVtxLonVar = file.add_var("new_vertex_lon", ncDouble, numVertexDim); NcVar *newVtxLatVar = file.add_var("new_vertex_lat", ncDouble, numVertexDim); oldVtxLonVar->add_att("long_name", "old vertex longitude"); oldVtxLonVar->add_att("units", "degree_east"); oldVtxLatVar->add_att("long_name", "old vertex latitude"); oldVtxLatVar->add_att("units", "degree_north"); newVtxLonVar->add_att("long_name", "new vertex longitude"); newVtxLonVar->add_att("units", "degree_east"); newVtxLatVar->add_att("long_name", "new vertex latitude"); newVtxLatVar->add_att("units", "degree_north"); double *oldVtxLon = new double[vertices.size()]; double *oldVtxLat = new double[vertices.size()]; double *newVtxLon = new double[vertices.size()]; double *newVtxLat = new double[vertices.size()]; Vertex *vertex = vertices.front(); for (int i = 0; i < vertices.size(); ++i) { oldVtxLon[i] = vertex->getCoordinate(OldTimeLevel).getLon()*Rad2Deg; oldVtxLat[i] = vertex->getCoordinate(OldTimeLevel).getLat()*Rad2Deg; newVtxLon[i] = vertex->getCoordinate(NewTimeLevel).getLon()*Rad2Deg; newVtxLat[i] = vertex->getCoordinate(NewTimeLevel).getLat()*Rad2Deg; vertex = vertex->next; } oldVtxLonVar->put(oldVtxLon, vertices.size()); oldVtxLatVar->put(oldVtxLat, vertices.size()); newVtxLonVar->put(newVtxLon, vertices.size()); newVtxLatVar->put(newVtxLat, vertices.size()); delete [] oldVtxLon; delete [] oldVtxLat; delete [] newVtxLon; delete [] newVtxLat; // ------------------------------------------------------------------------- // edges part NcVar *firstPointVar = file.add_var("first_point_idx", ncInt, numEdgeDim); NcVar *secondPointVar = file.add_var("second_point_idx", ncInt, numEdgeDim); firstPointVar->add_att("long_name", "first point index of edge"); secondPointVar->add_att("long_name", "second point index of edge"); int *idx1 = new int[edges.size()]; int *idx2 = new int[edges.size()]; Edge *edge = edges.front(); for (int i = 0; i < edges.size(); ++i) { idx1[i] = edge->getEndPoint(FirstPoint)->getID(); idx2[i] = edge->getEndPoint(SecondPoint)->getID(); edge = edge->next; } firstPointVar->put(idx1, edges.size()); secondPointVar->put(idx2, edges.size()); delete [] idx1; delete [] idx2; // test point NcVar *oldTestLonVar = file.add_var("old_testpoint_lon", ncDouble, numEdgeDim); NcVar *oldTestLatVar = file.add_var("old_testpoint_lat", ncDouble, numEdgeDim); NcVar *newTestLonVar = file.add_var("new_testpoint_lon", ncDouble, numEdgeDim); NcVar *newTestLatVar = file.add_var("new_testpoint_lat", ncDouble, numEdgeDim); oldTestLonVar->add_att("long_name", "old test point longitude"); oldTestLonVar->add_att("units", "degree_east"); oldTestLatVar->add_att("long_name", "old test point latitude"); oldTestLatVar->add_att("units", "degree_north"); newTestLonVar->add_att("long_name", "new test point longitude"); newTestLonVar->add_att("units", "degree_east"); newTestLatVar->add_att("long_name", "new test point latitude"); newTestLatVar->add_att("units", "degree_north"); #if defined TTS_ONLINE || PREPROCESS double *oldTestLon = new double[edges.size()]; double *oldTestLat = new double[edges.size()]; double *newTestLon = new double[edges.size()]; double *newTestLat = new double[edges.size()]; edge = edges.front(); for (int i = 0; i < edges.size(); ++i) { Vertex *testPoint = edge->getTestPoint(); oldTestLon[i] = testPoint->getCoordinate(OldTimeLevel).getLon()*Rad2Deg; oldTestLat[i] = testPoint->getCoordinate(OldTimeLevel).getLat()*Rad2Deg; newTestLon[i] = testPoint->getCoordinate(NewTimeLevel).getLon()*Rad2Deg; newTestLat[i] = testPoint->getCoordinate(NewTimeLevel).getLat()*Rad2Deg; edge = edge->next; } oldTestLonVar->put(oldTestLon, edges.size()); oldTestLatVar->put(oldTestLat, edges.size()); newTestLonVar->put(newTestLon, edges.size()); newTestLatVar->put(newTestLat, edges.size()); delete [] oldTestLon; delete [] oldTestLat; delete [] newTestLon; delete [] newTestLat; #endif // ------------------------------------------------------------------------- // polygons part NcVar *edgeNumVar = file.add_var("edge_num", ncInt, numPolygonDim); NcVar *areaVar = file.add_var("area", ncDouble, numPolygonDim); edgeNumVar->add_att("long_name", "edge number of polygon"); areaVar->add_att("long_name", "polygon area"); int edgeNum[polygons.size()]; double area[polygons.size()]; int counter = 0; Polygon *polygon = polygons.front(); for (int i = 0; i < polygons.size(); ++i) { edgeNum[i] = polygon->edgePointers.size(); area[i] = polygon->getArea(); counter += edgeNum[i]; polygon = polygon->next; } int numEdgeIdx = counter; NcDim *numEdgeIdxDim = file.add_dim("num_edge_idx", numEdgeIdx); NcVar *edgeIdxVar = file.add_var("edge_idx", ncInt, numEdgeIdxDim); NcVar *edgeOntVar = file.add_var("edge_ont", ncInt, numEdgeIdxDim); edgeIdxVar->add_att("long_name", "edge index of polygon"); edgeOntVar->add_att("long_name", "edge orientation of polygon"); int *edgeIdx = new int[counter]; int *edgeOnt = new int[counter]; counter = 0; polygon = polygons.front(); for (int i = 0; i < polygons.size(); ++i) { EdgePointer *edgePointer = polygon->edgePointers.front(); for (int j = 0; j < polygon->edgePointers.size(); ++j) { edgeIdx[counter] = edgePointer->edge->getID(); edgeOnt[counter] = edgePointer->orient; counter++; edgePointer = edgePointer->next; } polygon = polygon->next; } edgeNumVar->put(edgeNum, polygons.size()); areaVar->put(area, polygons.size()); edgeIdxVar->put(edgeIdx, numEdgeIdx); edgeOntVar->put(edgeOnt, numEdgeIdx); delete [] edgeIdx; delete [] edgeOnt; // ------------------------------------------------------------------------- file.close(); }
// // Creates NetCDF product // bool NetCDFProduct(MSG_header *PRO_head, MSG_data* PRO_data, int totalsegs, int *segsindexes, MSG_header *header, MSG_data *msgdat) { struct tm *tmtime; char NcName[1024]; char reftime[64]; char projname[16]; int wd, hg; int bpp; int ncal; float *cal; NcVar *ivar; NcVar *tvar; NcDim *tdim; NcDim *ldim; NcDim *cdim; NcDim *caldim; int npix = header[0].image_structure->number_of_columns; int nlin = header[0].image_structure->number_of_lines; size_t npixperseg = npix*nlin; size_t total_size = totalsegs*npixperseg; MSG_SAMPLE *pixels = new MSG_SAMPLE[total_size]; memset(pixels, 0, total_size*sizeof(MSG_SAMPLE)); size_t pos = 0; for (int i = 0; i < totalsegs; i ++) { if (segsindexes[i] >= 0) memcpy(pixels+pos, msgdat[segsindexes[i]].image->data, npixperseg*sizeof(MSG_SAMPLE)); pos += npixperseg; } nlin = nlin*totalsegs; // Manage subarea if (is_subarea) { if (AreaLinStart < 0 || AreaLinStart > nlin - AreaNlin || AreaNlin > nlin - AreaLinStart) { std::cerr << "Wrong Subarea in lines...." << std::endl; throw; } if (AreaPixStart < 0 || AreaPixStart > npix - AreaNpix || AreaNpix > npix - AreaPixStart) { std::cerr << "Wrong Subarea in Pixels...." << std::endl; throw; } size_t newsize = AreaNpix * AreaNlin; MSG_SAMPLE *newpix = new MSG_SAMPLE[newsize]; memset(newpix, 0, newsize*sizeof(MSG_SAMPLE)); for (int i = 0; i < AreaNlin; i ++) memcpy(newpix + i * AreaNpix, pixels + (AreaLinStart + i) * npix + AreaPixStart, AreaNpix * sizeof(MSG_SAMPLE)); delete [ ] pixels; pixels = newpix; total_size = newsize; } else { AreaNpix = npix; AreaNlin = nlin; } tmtime = PRO_data->prologue->image_acquisition.PlannedAquisitionTime.TrueRepeatCycleStart.get_timestruct( ); t_enum_MSG_spacecraft spc = header[0].segment_id->spacecraft_id; uint_1 chn = header[0].segment_id->spectral_channel_id; float sublon = header[0].image_navigation->subsatellite_longitude; int cfac = header[0].image_navigation->column_scaling_factor; int lfac = header[0].image_navigation->line_scaling_factor; int coff = header[0].image_navigation->column_offset; int loff = header[0].image_navigation->line_offset; float sh = header[0].image_navigation->satellite_h; char *channelstring = strdup(MSG_channel_name(spc, chn).c_str( )); char *channel = chname(channelstring, strlen(channelstring) + 1); // Build up output NetCDF file name and open it sprintf( NcName, "%s_%4d%02d%02d_%02d%02d.nc", channel, tmtime->tm_year + 1900, tmtime->tm_mon + 1, tmtime->tm_mday, tmtime->tm_hour, tmtime->tm_min ); NcFile ncf ( NcName , NcFile::Replace ); if (! ncf.is_valid()) return false; // Fill arrays on creation ncf.set_fill(NcFile::Fill); // Add Global Attributes if (! ncf.add_att("Satellite", MSG_spacecraft_name(spc).c_str())) return false; sprintf(reftime, "%04d-%02d-%02d %02d:%02d:00 UTC", tmtime->tm_year + 1900, tmtime->tm_mon + 1, tmtime->tm_mday, tmtime->tm_hour, tmtime->tm_min); if (! ncf.add_att("Antenna", "Fixed") ) return false; if (! ncf.add_att("Receiver", "HIMET") ) return false; if (! ncf.add_att("Time", reftime) ) return false; if (! ncf.add_att("Area_Name", "SpaceView" ) ) return false; sprintf(projname, "GEOS(%3.1f)", sublon); if (! ncf.add_att("Projection", projname) ) return false; if (! ncf.add_att("Columns", AreaNpix ) ) return false; if (! ncf.add_att("Lines", AreaNlin ) ) return false; if (! ncf.add_att("SampleX", 1.0 ) ) return false; if (! ncf.add_att("SampleY", 1.0 ) ) return false; if (! ncf.add_att("AreaStartPix", AreaPixStart ) ) return false; if (! ncf.add_att("AreaStartLin", AreaLinStart ) ) return false; if (! ncf.add_att("Column_Scale_Factor", cfac) ) return false; if (! ncf.add_att("Line_Scale_Factor", lfac) ) return false; if (! ncf.add_att("Column_Offset", coff) ) return false; if (! ncf.add_att("Line_Offset", loff) ) return false; if (! ncf.add_att("Orbit_Radius", sh) ) return false; if (! ncf.add_att("Longitude", sublon) ) return false; if (! ncf.add_att("NortPolar", 1) ) return false; if (! ncf.add_att("NorthSouth", 1) ) return false; if (! ncf.add_att("title", TITLE) ) return false; if (! ncf.add_att("Institution", INSTITUTION) ) return false; if (! ncf.add_att("Type", TYPE) ) return false; if (! ncf.add_att("Version", HIMET_VERSION) ) return false; if (! ncf.add_att("Conventions", "COARDS") ) return false; if (! ncf.add_att("history", "Created from raw data") ) return false; // Dimensions wd = AreaNpix; hg = AreaNlin; bpp = header[0].image_structure->number_of_bits_per_pixel; ncal = (int) pow(2.0, bpp); tdim = ncf.add_dim("time"); if (!tdim->is_valid()) return false; ldim = ncf.add_dim("line", hg); if (!ldim->is_valid()) return false; cdim = ncf.add_dim("column", wd); if (!cdim->is_valid()) return false; caldim = ncf.add_dim("calibration", ncal); if (!caldim->is_valid()) return false; // Get calibration values cal = PRO_data->prologue->radiometric_proc.get_calibration((int) chn, bpp); // Add Calibration values NcVar *cvar = ncf.add_var("calibration", ncFloat, caldim); if (!cvar->is_valid()) return false; cvar->add_att("long_name", "Calibration coefficients"); cvar->add_att("variable", channel); if (chn > 3 && chn < 12) cvar->add_att("units", "K"); else cvar->add_att("units", "mW m^-2 sr^-1 (cm^-1)^-1"); if (!cvar->put(cal, ncal)) return false; tvar = ncf.add_var("time", ncDouble, tdim); if (!tvar->is_valid()) return false; tvar->add_att("long_name", "Time"); tvar->add_att("units", "seconds since 2000-01-01 00:00:00 UTC"); double atime; time_t ttime; extern long timezone; ttime = mktime(tmtime); atime = ttime - 946684800 - timezone; if (!tvar->put(&atime, 1)) return false; ivar = ncf.add_var(channel, ncShort, tdim, ldim, cdim); if (!ivar->is_valid()) return false; if (!ivar->add_att("add_offset", 0.0)) return false; if (!ivar->add_att("scale_factor", 1.0)) return false; if (!ivar->add_att("chnum", chn)) return false; // Write output values if (!ivar->put((const short int *) pixels, 1, hg, wd)) return false; // Close NetCDF output (void) ncf.close( ); delete [ ] pixels; delete [ ] cal; return( true ); }
void TracerManager::output(const string &fileName) { // ------------------------------------------------------------------------- // output polygon stuffs polygonManager.output(fileName); #ifdef TTS_REMAP // ------------------------------------------------------------------------- NcFile file(fileName.c_str(), NcFile::Write); if (!file.is_valid()) { Message message; message << "Failed to open tracer output file \""; message << fileName << "\" for appending meshed density field!"; REPORT_ERROR(message.str()); } // ------------------------------------------------------------------------- // output tracer densities on the polygons NcDim *numPolygonDim = file.get_dim("num_total_polygon"); double q0[polygonManager.polygons.size()]; for (int l = 0; l < tracerNames.size(); ++l) { char varName[30]; sprintf(varName, "q%d", l); NcVar *qVar = file.add_var(varName, ncDouble, numPolygonDim); Polygon *polygon = polygonManager.polygons.front(); for (int i = 0; i < polygonManager.polygons.size(); ++i) { q0[i] = polygon->tracers[l].getDensity(); polygon = polygon->next; } qVar->put(q0, polygonManager.polygons.size()); } // ------------------------------------------------------------------------- // output tracer densities on the mesh const RLLMesh &mesh = tracerDensities[0].getMesh(); int numLon = mesh.getNumLon()-2; int numLat = mesh.getNumLat(); double lon[numLon], lat[numLat]; for (int i = 0; i < numLon; ++i) lon[i] = mesh.lon(i+1)*Rad2Deg; for (int j = 0; j < numLat; ++j) lat[j] = mesh.lat(j)*Rad2Deg; NcDim *lonDim = file.add_dim("lon", numLon); NcDim *latDim = file.add_dim("lat", numLat); NcVar *lonVar = file.add_var("lon", ncDouble, lonDim); lonVar->add_att("long_name", "longitude"); lonVar->add_att("units", "degrees_east"); lonVar->put(lon, numLon); NcVar *latVar = file.add_var("lat", ncDouble, latDim); latVar->add_att("long_name", "latitude"); latVar->add_att("units", "degrees_north"); latVar->put(lat, numLat); NcVar *areaVar = file.add_var("area_mesh", ncDouble, latDim, lonDim); areaVar->add_att("long_name", "area of fixed mesh cell"); areaVar->add_att("units", "m2"); double area[numLat][numLon]; for (int i = 0; i < numLon; ++i) for (int j = 0; j < numLat; ++j) area[j][i] = tracerDensities[0].getMesh(Field::Bound).area(i, j); areaVar->put(&area[0][0], numLat, numLon); double q[numLat][numLon]; for (int l = 0; l < tracerNames.size(); ++l) { char varName[30]; sprintf(varName, "q%d_mesh", l); NcVar *qVar = file.add_var(varName, ncDouble, latDim, lonDim); qVar->add_att("long_name", tracerNames[l].c_str()); for (int i = 0; i < numLon; ++i) for (int j = 0; j < numLat; ++j) q[j][i] = tracerDensities[l].values(i+1, j, 0).getNew(); qVar->put(&q[0][0], numLat, numLon); } // ------------------------------------------------------------------------- file.close(); #endif NOTICE("TracerManager", fileName+" is generated."); }
bool OutputManagerReference::OpenFile( const std::string & strFileName ) { #ifdef TEMPEST_NETCDF // Determine processor rank; only proceed if root node int nRank = 0; #ifdef TEMPEST_MPIOMP MPI_Comm_rank(MPI_COMM_WORLD, &nRank); #endif // The active model const Model & model = m_grid.GetModel(); // Open NetCDF file on root process if (nRank == 0) { // Check for existing NetCDF file if (m_pActiveNcOutput != NULL) { _EXCEPTIONT("NetCDF file already open"); } // Append .nc extension to file std::string strNcFileName = strFileName + ".nc"; // Open new NetCDF file m_pActiveNcOutput = new NcFile(strNcFileName.c_str(), NcFile::Replace); if (m_pActiveNcOutput == NULL) { _EXCEPTION1("Error opening NetCDF file \"%s\"", strNcFileName.c_str()); } if (!m_pActiveNcOutput->is_valid()) { _EXCEPTION1("Error opening NetCDF file \"%s\"", strNcFileName.c_str()); } // Create nodal time dimension NcDim * dimTime = m_pActiveNcOutput->add_dim("time"); if (dimTime == NULL) { _EXCEPTIONT("Error creating \"time\" dimension"); } m_varTime = m_pActiveNcOutput->add_var("time", ncDouble, dimTime); if (m_varTime == NULL) { _EXCEPTIONT("Error creating \"time\" variable"); } std::string strUnits = "days since " + model.GetStartTime().ToDateString(); std::string strCalendarName = model.GetStartTime().GetCalendarName(); m_varTime->add_att("long_name", "time"); m_varTime->add_att("units", strUnits.c_str()); m_varTime->add_att("calendar", strCalendarName.c_str()); m_varTime->add_att("bounds", "time_bnds"); // Create levels dimension NcDim * dimLev = m_pActiveNcOutput->add_dim("lev", m_dREtaCoord.GetRows()); // Create interfaces dimension NcDim * dimILev = m_pActiveNcOutput->add_dim("ilev", m_grid.GetRElements()+1); // Create latitude dimension NcDim * dimLat = m_pActiveNcOutput->add_dim("lat", m_nYReference); // Create longitude dimension NcDim * dimLon = m_pActiveNcOutput->add_dim("lon", m_nXReference); // Output physical constants const PhysicalConstants & phys = model.GetPhysicalConstants(); m_pActiveNcOutput->add_att("earth_radius", phys.GetEarthRadius()); m_pActiveNcOutput->add_att("g", phys.GetG()); m_pActiveNcOutput->add_att("omega", phys.GetOmega()); m_pActiveNcOutput->add_att("alpha", phys.GetAlpha()); m_pActiveNcOutput->add_att("Rd", phys.GetR()); m_pActiveNcOutput->add_att("Cp", phys.GetCp()); m_pActiveNcOutput->add_att("T0", phys.GetT0()); m_pActiveNcOutput->add_att("P0", phys.GetP0()); m_pActiveNcOutput->add_att("rho_water", phys.GetRhoWater()); m_pActiveNcOutput->add_att("Rvap", phys.GetRvap()); m_pActiveNcOutput->add_att("Mvap", phys.GetMvap()); m_pActiveNcOutput->add_att("Lvap", phys.GetLvap()); // Output grid parameters m_pActiveNcOutput->add_att("Ztop", m_grid.GetZtop()); // Output equation set const EquationSet & eqn = model.GetEquationSet(); m_pActiveNcOutput->add_att("equation_set", eqn.GetName().c_str()); // Create variables for (int c = 0; c < eqn.GetComponents(); c++) { if ((m_fOutputAllVarsOnNodes) || (m_grid.GetVarLocation(c) == DataLocation_Node) ) { m_vecComponentVar.push_back( m_pActiveNcOutput->add_var( eqn.GetComponentShortName(c).c_str(), ncDouble, dimTime, dimLev, dimLat, dimLon)); } else { m_vecComponentVar.push_back( m_pActiveNcOutput->add_var( eqn.GetComponentShortName(c).c_str(), ncDouble, dimTime, dimILev, dimLat, dimLon)); } } for (int c = 0; c < eqn.GetTracers(); c++) { m_vecTracersVar.push_back( m_pActiveNcOutput->add_var( eqn.GetTracerShortName(c).c_str(), ncDouble, dimTime, dimLev, dimLat, dimLon)); } // Vorticity variable if (m_fOutputVorticity) { m_varVorticity = m_pActiveNcOutput->add_var( "ZETA", ncDouble, dimTime, dimLev, dimLat, dimLon); } // Divergence variable if (m_fOutputDivergence) { m_varDivergence = m_pActiveNcOutput->add_var( "DELTA", ncDouble, dimTime, dimLev, dimLat, dimLon); } // Temperature variable if (m_fOutputTemperature) { m_varTemperature = m_pActiveNcOutput->add_var( "T", ncDouble, dimTime, dimLev, dimLat, dimLon); } // Surface pressure variable if (m_fOutputSurfacePressure) { m_varSurfacePressure = m_pActiveNcOutput->add_var( "PS", ncDouble, dimTime, dimLat, dimLon); } // Richardson number variable if (m_fOutputRichardson) { m_varRichardson = m_pActiveNcOutput->add_var( "Ri", ncDouble, dimTime, dimLev, dimLat, dimLon); } // User data variables const UserDataMeta & metaUserData = model.GetUserDataMeta(); m_vecUserData2DVar.resize(metaUserData.GetUserData2DItemCount()); for (int i = 0; i < metaUserData.GetUserData2DItemCount(); i++) { m_vecUserData2DVar[i] = m_pActiveNcOutput->add_var( metaUserData.GetUserData2DItemName(i).c_str(), ncDouble, dimTime, dimLat, dimLon); } // Output longitudes and latitudes NcVar * varLon = m_pActiveNcOutput->add_var("lon", ncDouble, dimLon); NcVar * varLat = m_pActiveNcOutput->add_var("lat", ncDouble, dimLat); varLon->put(m_dXCoord, m_dXCoord.GetRows()); varLat->put(m_dYCoord, m_dYCoord.GetRows()); varLon->add_att("long_name", "longitude"); varLon->add_att("units", "degrees_east"); varLat->add_att("long_name", "latitude"); varLat->add_att("units", "degrees_north"); // Output levels NcVar * varLev = m_pActiveNcOutput->add_var("lev", ncDouble, dimLev); varLev->put( m_dREtaCoord, m_dREtaCoord.GetRows()); varLev->add_att("long_name", "level"); varLev->add_att("units", "level"); // Output interface levels NcVar * varILev = m_pActiveNcOutput->add_var("ilev", ncDouble, dimILev); varILev->put( m_grid.GetREtaStretchInterfaces(), m_grid.GetREtaStretchInterfaces().GetRows()); varILev->add_att("long_name", "interface level"); varILev->add_att("units", "level"); // Topography variable m_varTopography = m_pActiveNcOutput->add_var("Zs", ncDouble, dimLat, dimLon); // Fresh output file m_fFreshOutputFile = true; } #ifdef TEMPEST_MPIOMP // Wait for all processes to complete MPI_Barrier(MPI_COMM_WORLD); #endif #endif return true; }
int main(int argc, char** argv) { NcError error(NcError::verbose_nonfatal); try { // Input file std::string strInputFile; // Input file list std::string strInputFileList; // Input file format std::string strInputFormat; // NetCDF file containing latitude and longitude arrays std::string strLatLonFile; // Output file (NetCDF) std::string strOutputFile; // Output variable name std::string strOutputVariable; // Column in which the longitude index appears int iLonIxCol; // Column in which the latitude index appears int iLatIxCol; // Begin latitude double dLatBegin; // End latitude double dLatEnd; // Begin longitude double dLonBegin; // End longitude double dLonEnd; // Number of latitudes in output int nLat; // Number of longitudes in output int nLon; // Parse the command line BeginCommandLine() CommandLineString(strInputFile, "in", ""); CommandLineString(strInputFileList, "inlist", ""); CommandLineStringD(strInputFormat, "in_format", "std", "(std|visit)"); CommandLineString(strOutputFile, "out", ""); CommandLineString(strOutputVariable, "outvar", "density"); CommandLineInt(iLonIxCol, "iloncol", 8); CommandLineInt(iLatIxCol, "ilatcol", 9); CommandLineDouble(dLatBegin, "lat_begin", -90.0); CommandLineDouble(dLatEnd, "lat_end", 90.0); CommandLineDouble(dLonBegin, "lon_begin", 0.0); CommandLineDouble(dLonEnd, "lon_end", 360.0); CommandLineInt(nLat, "nlat", 180); CommandLineInt(nLon, "nlon", 360); ParseCommandLine(argc, argv); EndCommandLine(argv) AnnounceBanner(); // Check input if ((strInputFile == "") && (strInputFileList == "")) { _EXCEPTIONT("No input file (--in) or (--inlist) specified"); } if ((strInputFile != "") && (strInputFileList != "")) { _EXCEPTIONT("Only one input file (--in) or (--inlist) allowed"); } if (strInputFormat != "std") { _EXCEPTIONT("UNIMPLEMENTED: Only \"--in_format std\" supported"); } // Check output if (strOutputFile == "") { _EXCEPTIONT("No output file (--out) specified"); } // Check output variable if (strOutputVariable == "") { _EXCEPTIONT("No output variable name (--outvar) specified"); } // Number of latitudes and longitudes if (nLat == 0) { _EXCEPTIONT("UNIMPLEMENTED: --nlat must be specified currently"); } if (nLon == 0) { _EXCEPTIONT("UNIMPLEMENTED: --nlon must be specified currently"); } // Input file list std::vector<std::string> vecInputFiles; if (strInputFile != "") { vecInputFiles.push_back(strInputFile); } if (strInputFileList != "") { GetInputFileList(strInputFileList, vecInputFiles); } int nFiles = vecInputFiles.size(); // Density DataMatrix<int> nCounts; nCounts.Initialize(nLat, nLon); // Loop through all files in list AnnounceStartBlock("Processing files"); std::string strBuffer; strBuffer.reserve(1024); for (int f = 0; f < nFiles; f++) { Announce("File \"%s\"", vecInputFiles[f].c_str()); FILE * fp = fopen(vecInputFiles[f].c_str(), "r"); if (fp == NULL) { _EXCEPTION1("Unable to open input file \"%s\"", vecInputFiles[f].c_str()); } for (;;) { // Read in the next line fgets(&(strBuffer[0]), 1024, fp); int nLength = strlen(&(strBuffer[0])); // Check for end of file if (feof(fp)) { break; } // Check for comment line if (strBuffer[0] == '#') { continue; } // Check for new storm if (strncmp(&(strBuffer[0]), "start", 5) == 0) { continue; } // Parse line double dLon; double dLat; int iCol = 0; int iLast = 0; bool fWhitespace = true; for (int i = 0; i <= nLength; i++) { if ((strBuffer[i] == ' ') || (strBuffer[i] == ',') || (strBuffer[i] == '\t') || (strBuffer[i] == '\0') ) { if (!fWhitespace) { if (iCol == iLonIxCol) { strBuffer[i] = '\0'; dLon = atof(&(strBuffer[iLast])); } if (iCol == iLatIxCol) { strBuffer[i] = '\0'; dLat = atof(&(strBuffer[iLast])); } } fWhitespace = true; } else { if (fWhitespace) { iLast = i; iCol++; } fWhitespace = false; } } // Latitude and longitude index int iLon = static_cast<int>(static_cast<double>(nLon) * (dLon - dLonBegin) / (dLonEnd - dLonBegin)); int iLat = static_cast<int>(static_cast<double>(nLat) * (dLat - dLatBegin) / (dLatEnd - dLatBegin)); if (iLon == (-1)) { iLon = 0; } if (iLon == nLon) { iLon = nLon - 1; } if (iLat == (-1)) { iLat = 0; } if (iLat == nLat) { iLat = nLat - 1; } if ((iLat < 0) || (iLat >= nLat)) { _EXCEPTION1("Latitude index (%i) out of range", iLat); } if ((iLon < 0) || (iLon >= nLon)) { _EXCEPTION1("Longitude index (%i) out of range", iLon); } nCounts[iLat][iLon]++; } fclose(fp); } AnnounceEndBlock("Done"); // Output results AnnounceStartBlock("Output results"); // Load the netcdf output file NcFile ncOutput(strOutputFile.c_str(), NcFile::Replace); if (!ncOutput.is_valid()) { _EXCEPTION1("Unable to open output file \"%s\"", strOutputFile.c_str()); } // Create output NcDim * dimLat = ncOutput.add_dim("lat", nLat); NcDim * dimLon = ncOutput.add_dim("lon", nLon); NcVar * varLat = ncOutput.add_var("lat", ncDouble, dimLat); NcVar * varLon = ncOutput.add_var("lon", ncDouble, dimLon); varLat->add_att("units", "degrees_north"); varLon->add_att("units", "degrees_east"); DataVector<double> dLat(nLat); DataVector<double> dLon(nLon); for (int j = 0; j < nLat; j++) { dLat[j] = dLatBegin + (dLatEnd - dLatBegin) * (static_cast<double>(j) + 0.5) / static_cast<double>(nLat); } for (int i = 0; i < nLon; i++) { dLon[i] = dLonBegin + (dLonEnd - dLonBegin) * (static_cast<double>(i) + 0.5) / static_cast<double>(nLon); } varLat->put(&(dLat[0]), nLat); varLon->put(&(dLon[0]), nLon); // Output counts NcVar * varCount = ncOutput.add_var( strOutputVariable.c_str(), ncInt, dimLat, dimLon); varCount->put(&(nCounts[0][0]), nLat, nLon); ncOutput.close(); AnnounceEndBlock("Done"); AnnounceBanner(); } catch(Exception & e) { Announce(e.ToString().c_str()); } }
void gen(const char* path, NcFile::FileFormat format) // Generate a netCDF file { NcFile nc(path, NcFile::Replace, NULL, 0, format); // Create, leave in define mode // Check if the file was opened successfully if (! nc.is_valid()) { cerr << "can't create netCDF file " << path << "\n"; return; } // Create dimensions const int NLATS = 4; const int NLONS = 3; const int NFRTIMES = 2; const int TIMESTRINGLEN = 20; NcDim* latd = nc.add_dim("lat", NLATS); NcDim* lond = nc.add_dim("lon", NLONS); NcDim* frtimed = nc.add_dim("frtime"); // unlimited dimension NcDim* timelend = nc.add_dim("timelen", TIMESTRINGLEN); // Create variables and their attributes NcVar* P = nc.add_var("P", ncFloat, frtimed, latd, lond); P->add_att("long_name", "pressure at maximum wind"); P->add_att("units", "hectopascals"); static float range[] = {0., 1500.}; P->add_att("valid_range", 2, range); P->add_att("_FillValue", -9999.0f); NcVar* lat = nc.add_var("lat", ncFloat, latd); lat->add_att("long_name", "latitude"); lat->add_att("units", "degrees_north"); NcVar* lon = nc.add_var("lon", ncFloat, lond); lon->add_att("long_name", "longitude"); lon->add_att("units", "degrees_east"); NcVar* frtime = nc.add_var("frtime", ncLong, frtimed); frtime->add_att("long_name", "forecast time"); frtime->add_att("units", "hours"); NcVar* reftime = nc.add_var("reftime",ncChar,timelend); reftime->add_att("long_name", "reference time"); reftime->add_att("units", "text_time"); NcVar* scalar = nc.add_var("scalarv", ncInt); scalar->add_att("scalar_att", 1); // Global attributes nc.add_att("history", "created by Unidata LDM from NPS broadcast"); nc.add_att("title", "NMC Global Product Set: Pressure at Maximum Wind"); // Start writing data, implictly leaves define mode static float lats[NLATS] = {-90, -87.5, -85, -82.5}; lat->put(lats, NLATS); static float lons[NLONS] = {-180, -175, -170}; lon->put(lons, NLONS); static int frtimes[NFRTIMES] = {12, 18}; frtime->put(frtimes, NFRTIMES); static const char* s = "1992-3-21 12:00" ; reftime->put(s, strlen(s)); static float P_data[2][4][3] = { {{950, 951, 952}, {953, 954, 955}, {956, 957, 958}, {959, 960, 961}}, {{962, 963, 964}, {965, 966, 967}, {968, 969, 970}, {971, 972, 973}} }; // We could write all P data at once with P->put(&P_data[0][0][0], P->edges()), // but instead we write one record at a time, to show use of setcur(). long rec = 0; // start at zero-th const long nrecs = 1; // # records to write P->put(&P_data[0][0][0], nrecs, NLATS, NLONS); // write zero-th record P->set_cur(++rec); // set to next record P->put(&P_data[1][0][0], nrecs, NLATS, NLONS); // write next record // close of nc takes place in destructor }