/****************************************************************************** * Write the outflow data file with WQ variables. * ******************************************************************************/ void write_outflow(int of_idx, int jday, AED_REAL vol) { char ts[64]; int i, lvl; AED_REAL DrawHeight; extern int csv_outlet_allinone, csv_outfl_nvars; extern int ofl_wq_idx[]; static AED_REAL vol_tot, state_of_v[MaxCSVOutVars]; //# work out which level the outflow is at now. if (Outflows[of_idx].FloatOff) { DrawHeight = Lake[surfLayer].Height - Outflows[of_idx].OLev; //# Let it sit on the bottom if the lake has drained if (DrawHeight < 0.) DrawHeight = 0.; } else DrawHeight = Outflows[of_idx].OLev; //# Fixed height offtake for (lvl = botmLayer; lvl <= surfLayer; lvl++) if (Lake[lvl].Height >= DrawHeight) break; if ( csv_outlet_allinone ) { if ( of_idx == 0 ) // initialize vol_tot = 0; for (i = 0; i < csv_outfl_nvars; i++) { state_of_v[i] *= vol_tot; state_of_v[i] += (vol * _WQ_Vars(ofl_wq_idx[i], lvl)); } vol_tot += vol; for (i = 0; i < csv_outfl_nvars; i++) state_of_v[i] /= vol_tot; if ( of_idx != MaxOut ) return; of_idx = 0; } else if (wq_calc) { for (i = 0; i < csv_outfl_nvars; i++) state_of_v[i] = _WQ_Vars(ofl_wq_idx[i], lvl); } write_time_string(ts, jday, 0); write_csv_outfl(of_idx, "time", 0.0, ts, FALSE); write_csv_outfl(of_idx, "flow", vol, NULL, FALSE); write_csv_outfl(of_idx, "Temp", Lake[lvl].Temp, NULL, FALSE); write_csv_outfl(of_idx, "Salt", Lake[lvl].Salinity, NULL, FALSE); if (wq_calc) { //# must do each of the WQ vars // # the first 3 vars are flow, temp and salt for (i = 3; i < csv_outfl_nvars; i++) write_csv_outfl_idx(of_idx, i, state_of_v[i], NULL, FALSE); } //# force a newline write_csv_outfl(of_idx, "", 0.0, NULL, TRUE); }
/****************************************************************************** * Write the various output files and/or plots. * ******************************************************************************/ void write_output(int jday, int iclock, int nsave, int stepnum) { int i, n, lvl[MaxPointCSV]; char ts[20]; if ( csv_point_nlevs > 0 ) { for (i = 0; i < MaxPointCSV; i++) lvl[i] = -1; //# Output at end of time step so add noSecs to time string write_time_string(ts, jday, iclock + noSecs); for (i = 0; i < csv_point_nlevs; i++) { write_csv_point(i, "time", 0.0, ts, FALSE); //# find which level csv_at is in if (csv_point_frombot[i]) { //Measure as height from bottom layer for (n = 0; n < NumLayers; n++) { if ( Lake[n].Height >= csv_point_at[i] ) { lvl[i] = n; break; } } } else { //Measure as depth from surface for (n = NumLayers-1; n >= botmLayer; n--) { if ( (Lake[surfLayer].Height - Lake[n].Height) >= csv_point_at[i] ) { lvl[i] = n + 1; break; } //If reached bottom layer if (lvl[i] == -1) lvl[i] = botmLayer; } } write_csv_point(i, "temp", Lake[lvl[i]].Temp, NULL, FALSE); write_csv_point(i, "salt", Lake[lvl[i]].Salinity, NULL, FALSE); } } #ifdef PLOTS if ( do_plots ) do_internal_plots(plot_id); #endif write_glm_ncdf(ncid, NumLayers, MaxLayers, stepnum, timestep); //# outputs WQ vars to NetCDF if (wq_calc) wq_write_glm(ncid, NumLayers, MaxLayers, lvl, csv_point_nlevs); if (csv_point_nlevs > 0) { for (i = 0; i < csv_point_nlevs; i++) write_csv_point(i, "", 0.0, NULL, TRUE); } }
/****************************************************************************** * Write the various output files and/or plots. * ******************************************************************************/ void write_diags(int jday, AED_REAL LakeNum) { char ts[20]; extern AED_REAL Hs, L, T; if ( csv_lake_file < 0 ) return; //# Output at end of day write_time_string(ts, jday, SecsPerDay); write_csv_lake("time", 0.0, ts, FALSE); write_csv_lake("Volume", sum_lake_layervol(), NULL, FALSE); write_csv_lake("Vol Snow", SurfData.HeightSnow * Lake[surfLayer].LayerArea * SurfData.RhoSnow/1000.0, NULL, FALSE); //Magic numbers for ice density are from glm_surface.c write_csv_lake("Vol Black Ice", SurfData.HeightBlackIce * Lake[surfLayer].LayerArea * 917.0/1000.0, NULL, FALSE); write_csv_lake("Vol White Ice", SurfData.HeightWhiteIce * Lake[surfLayer].LayerArea * 890.0/1000.0, NULL, FALSE); write_csv_lake("Tot Inflow Vol", SurfData.dailyInflow, NULL, FALSE); write_csv_lake("Tot Outflow Vol", SurfData.dailyOutflow, NULL, FALSE); write_csv_lake("Overflow Vol", SurfData.dailyOverflow, NULL, FALSE); write_csv_lake("Evaporation", SurfData.dailyEvap, NULL, FALSE); write_csv_lake("Rain", SurfData.dailyRain, NULL, FALSE); write_csv_lake("Snowfall", SurfData.dailySnow, NULL, FALSE); write_csv_lake("Lake Level", Lake[surfLayer].Height, NULL, FALSE); write_csv_lake("Surface Area", Lake[surfLayer].LayerArea, NULL, FALSE); write_csv_lake("Black Ice", SurfData.HeightBlackIce, NULL, FALSE); write_csv_lake("Snow Height", SurfData.HeightSnow, NULL, FALSE); write_csv_lake("Snow Density", SurfData.RhoSnow, NULL, FALSE); write_csv_lake("White Ice", SurfData.HeightWhiteIce, NULL, FALSE); write_csv_lake("Albedo", SurfData.albedo, NULL, FALSE); write_csv_lake("Max Temp", max_temp(Lake, NumLayers), NULL, FALSE); write_csv_lake("Min Temp", min_temp(Lake, NumLayers), NULL, FALSE); write_csv_lake("Surface Temp", Lake[surfLayer].Temp, NULL, FALSE); write_csv_lake("Daily Qsw", SurfData.dailyQsw, NULL, FALSE); write_csv_lake("Daily Qe", SurfData.dailyQe, NULL, FALSE); write_csv_lake("Daily Qh", SurfData.dailyQh, NULL, FALSE); write_csv_lake("Daily Qlw", SurfData.dailyQlw, NULL, FALSE); write_csv_lake("Light", Lake[surfLayer].Light, NULL, FALSE); write_csv_lake("Benthic Light", Benthic_Light_pcArea, NULL, FALSE); write_csv_lake("H_s", Hs, NULL, FALSE); write_csv_lake("L", L, NULL, FALSE); write_csv_lake("T", T, NULL, FALSE); write_csv_lake("LakeNumber", LakeNum, NULL, FALSE); write_csv_lake("Max dT/dz", max_dtdz_at(Lake, NumLayers), NULL, FALSE); write_csv_lake("coef_wind_drag", coef_wind_drag, NULL, TRUE); }
/****************************************************************************** * Initialise output streams * ******************************************************************************/ void init_output(int jstart, const char *out_dir, const char *out_fn, int oMaxLayers, AED_REAL Longitude, AED_REAL Latitude) { char ts[20]; char path[1024]; struct stat sb; if ( out_dir != NULL && stat(out_dir, &sb) ) { fprintf(stderr, "Directory \"%s\" does not exist - attempting to create it\n", out_dir); if ( mkdir(out_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) ) { fprintf(stderr, "mkdir failed\n"); exit(1); } } else { if ( ! S_ISDIR(sb.st_mode) ) { fprintf(stderr, "Name given in out_dir (%s) is not a directory\n", out_dir); exit(1); } } MaxLayers = oMaxLayers; write_time_string(ts,jstart,0); snprintf(path, 1024, "%s/%s.nc", out_dir, out_fn); ncid = init_glm_ncdf(path, "glm run", Latitude, Longitude, MaxLayers, ts); init_csv_output(out_dir); //# Initialize WQ output (creates NetCDF variables) if (wq_calc) wq_init_glm_output(&ncid, &x_dim, &y_dim, &z_dim, &time_dim); #ifdef PLOTS if ( do_plots ) { int i; for (i = 0; i < 10; i++) plot_id[i] = -1; init_plots(jstart,nDays,CrestLevel); } #endif }
void status_print_statistics (stat_format_t *stats, buffer_stats_t *audio_statistics, data_source_stats_t *transport_statistics, decoder_stats_t *decoder_statistics) { pthread_cleanup_push(unlock_output_lock, NULL); /* Updating statistics is not critical. If another thread is already doing output, we skip it. */ if (pthread_mutex_trylock(&output_lock) == 0) { if (decoder_statistics != NULL) { /* Current playback time */ write_time_string(stats[1].arg.stringarg, decoder_statistics->current_time); /* Remaining playback time */ write_time_string(stats[2].arg.stringarg, decoder_statistics->total_time - decoder_statistics->current_time); /* Total playback time */ write_time_string(stats[3].arg.stringarg, decoder_statistics->total_time); /* Instantaneous bitrate */ stats[4].arg.doublearg = decoder_statistics->instant_bitrate / 1000.0f; /* Instantaneous bitrate */ stats[5].arg.doublearg = decoder_statistics->avg_bitrate / 1000.0f; } if (transport_statistics != NULL && transport_statistics->input_buffer_used) { /* Input buffer fill % */ stats[6].arg.doublearg = transport_statistics->input_buffer.fill; /* Input buffer state */ write_buffer_state_string(stats[7].arg.stringarg, &transport_statistics->input_buffer); } if (audio_statistics != NULL) { /* Output buffer fill % */ stats[8].arg.doublearg = audio_statistics->fill; /* Output buffer state */ write_buffer_state_string(stats[9].arg.stringarg, audio_statistics); } last_line_len = print_statistics_line(stats); pthread_mutex_unlock(&output_lock); } pthread_cleanup_pop(0); }
stat_format_t *stat_format_create () { stat_format_t *stats; stat_format_t *cur; stats = calloc(NUM_STATS + 1, sizeof(stat_format_t)); /* One extra for end flag */ if (stats == NULL) { fprintf(stderr, _("Memory allocation error in stats_init()\n")); exit(1); } cur = stats + 0; /* currently playing file / stream */ cur->verbosity = 3; cur->enabled = 0; cur->formatstr = _("File: %s"); cur->type = stat_stringarg; cur = stats + 1; /* current playback time (preformatted) */ cur->verbosity = 1; cur->enabled = 1; cur->formatstr = _("Time: %s"); cur->type = stat_stringarg; cur->arg.stringarg = calloc(TIME_STR_SIZE, sizeof(char)); if (cur->arg.stringarg == NULL) { fprintf(stderr, _("Memory allocation error in stats_init()\n")); exit(1); } write_time_string(cur->arg.stringarg, 0.0); cur = stats + 2; /* remaining playback time (preformatted) */ cur->verbosity = 1; cur->enabled = 1; cur->formatstr = "[%s]"; cur->type = stat_stringarg; cur->arg.stringarg = calloc(TIME_STR_SIZE, sizeof(char)); if (cur->arg.stringarg == NULL) { fprintf(stderr, _("Memory allocation error in stats_init()\n")); exit(1); } write_time_string(cur->arg.stringarg, 0.0); cur = stats + 3; /* total playback time (preformatted) */ cur->verbosity = 1; cur->enabled = 1; cur->formatstr = _("of %s"); cur->type = stat_stringarg; cur->arg.stringarg = calloc(TIME_STR_SIZE, sizeof(char)); if (cur->arg.stringarg == NULL) { fprintf(stderr, _("Memory allocation error in stats_init()\n")); exit(1); } write_time_string(cur->arg.stringarg, 0.0); cur = stats + 4; /* instantaneous bitrate */ cur->verbosity = 2; cur->enabled = 1; cur->formatstr = " (%5.1f kbps)"; cur->type = stat_doublearg; cur = stats + 5; /* average bitrate (not yet implemented) */ cur->verbosity = 2; cur->enabled = 0; cur->formatstr = _("Avg bitrate: %5.1f"); cur->type = stat_doublearg; cur = stats + 6; /* input buffer fill % */ cur->verbosity = 2; cur->enabled = 0; cur->formatstr = _(" Input Buffer %5.1f%%"); cur->type = stat_doublearg; cur = stats + 7; /* input buffer status */ cur->verbosity = 2; cur->enabled = 0; cur->formatstr = "%s"; cur->type = stat_stringarg; cur->arg.stringarg = calloc(STATE_STR_SIZE, sizeof(char)); if (cur->arg.stringarg == NULL) { fprintf(stderr, _("Memory allocation error in stats_init()\n")); exit(1); } cur = stats + 8; /* output buffer fill % */ cur->verbosity = 2; cur->enabled = 0; cur->formatstr = _(" Output Buffer %5.1f%%"); cur->type = stat_doublearg; cur = stats + 9; /* output buffer status */ cur->verbosity = 1; cur->enabled = 0; cur->formatstr = "%s"; cur->type = stat_stringarg; cur->arg.stringarg = calloc(STATE_STR_SIZE, sizeof(char)); if (cur->arg.stringarg == NULL) { fprintf(stderr, _("Memory allocation error in stats_init()\n")); exit(1); } cur = stats + 10; /* End flag */ cur->formatstr = NULL; return stats; }
int write_log_data(obj_t *log, const void *src, int len) { /* Writes a potentially modified version of the buffer (src) of length (len) * into the logfile obj (log); the original (src) buffer is not modified. * This routine is intended for writing data that was read from a console, * not informational messages. * If sanitized logs are enabled, data is stripped to 7-bit ASCII and * control/binary characters are displayed as two-character printable * sequences. * If newline timestamping is enabled, the current timestamp is appended * after each newline. * Returns the number of bytes written into the logfile obj's buffer. */ const int minbuf = 25; /* cr/lf + timestamp + meta/char */ unsigned char buf[MAX_BUF_SIZE - 1]; const unsigned char *p; unsigned char *q; const unsigned char * const qLast = buf + sizeof(buf); int n = 0; assert(is_logfile_obj(log)); assert(sizeof(buf) >= minbuf); /* If no additional processing is needed, listen to Biff Tannen: * "make like a tree and get outta here". */ if (!log->aux.logfile.gotProcessing) { return(write_obj_data(log, src, len, 0)); } DPRINTF((15, "Processing %d bytes for [%s] log \"%s\".\n", len, log->aux.logfile.console->name, log->name)); for (p=src, q=buf; len>0; p++, len--) { /* * A newline state machine is used to properly sanitize CR/LF line * terminations. This is responsible for coalescing multiple CRs, * swapping LF/CR to CR/LF, transcribing CR/NUL to CR/LF, * prepending a CR to a lonely LF, and appending a LF to a * lonely CR to prevent characters from being overwritten. */ if (*p == '\r') { if (log->aux.logfile.lineState == CONMAN_LOG_LINE_DATA) { log->aux.logfile.lineState = CONMAN_LOG_LINE_CR; } else if (log->aux.logfile.lineState == CONMAN_LOG_LINE_INIT) { if (log->aux.logfile.opts.enableTimestamp) q += write_time_string(0, (char *) q, qLast - q); log->aux.logfile.lineState = CONMAN_LOG_LINE_CR; } else { ; /* ignore */ } } else if (*p == '\n') { if ( (log->aux.logfile.lineState == CONMAN_LOG_LINE_INIT) || (log->aux.logfile.lineState == CONMAN_LOG_LINE_LF) ) { if (log->aux.logfile.opts.enableTimestamp) q += write_time_string(0, (char *) q, qLast - q); } *q++ = '\r'; *q++ = '\n'; log->aux.logfile.lineState = CONMAN_LOG_LINE_LF; } else if ( (*p == '\0') && ( (log->aux.logfile.lineState == CONMAN_LOG_LINE_CR) || (log->aux.logfile.lineState == CONMAN_LOG_LINE_LF) ) ) { ; /* ignore */ } else { if (log->aux.logfile.lineState == CONMAN_LOG_LINE_CR) { *q++ = '\r'; *q++ = '\n'; } if (log->aux.logfile.lineState != CONMAN_LOG_LINE_DATA) { if (log->aux.logfile.opts.enableTimestamp) q += write_time_string(0, (char *) q, qLast - q); } log->aux.logfile.lineState = CONMAN_LOG_LINE_DATA; if (log->aux.logfile.opts.enableSanitize) { int c = *p & 0x7F; /* strip data to 7-bit ASCII */ if (c < 0x20) { /* ASCII ctrl-chars */ *q++ = (*p & 0x80) ? '~' : '^'; *q++ = c + '@'; } else if (c == 0x7F) { /* ASCII DEL char */ *q++ = (*p & 0x80) ? '~' : '^'; *q++ = '?'; } else { if (*p & 0x80) *q++ = '`'; *q++ = c; } } else { *q++ = *p; } } /* Flush internal buffer before it overruns. */ if ((qLast - q) < minbuf) { assert((q >= buf) && (q <= qLast)); n += write_obj_data(log, buf, q - buf, 0); q = buf; } } assert((q >= buf) && (q <= qLast)); n += write_obj_data(log, buf, q - buf, 0); return(n); }