diff --git a/bin/foamMonitor b/bin/foamMonitor index a15bd5b168ffc43c125cf7ca03c5082e77e47e0f..5a4f736a0bab73eefcd1302784b1c34325e97fad 100755 --- a/bin/foamMonitor +++ b/bin/foamMonitor @@ -7,7 +7,7 @@ # \\/ M anipulation | #------------------------------------------------------------------------------- # Copyright (C) 2015 OpenFOAM Foundation -# Copyright (C) 2019 OpenCFD Ltd. +# Copyright (C) 2019-2021 OpenCFD Ltd. #------------------------------------------------------------------------------ # License # This file is part of OpenFOAM. @@ -34,35 +34,49 @@ # - requires gnuplot, gnuplot_x11 # #------------------------------------------------------------------------------ -usage() { - exec 1>&2 - while [ "$#" -ge 1 ]; do echo "$1"; shift; done +printHelp() { cat<<USAGE -Usage: ${0##*/} [OPTION] <file> -options: - -h | -help prints the usage - -i | -idle <time> stops if <file> unchanging for <time> sec (default = 60) - -l | -logscale plots data (y-axis) on log scale, e.g. for residuals - -r | -refresh <time> refreshes display every <time> sec (default = 10) - -y | -yrange <range> sets data (y-axis) <range>, format "[0:1]" - -g | -grid draws grid lines on the plot +Usage: ${0##*/} [OPTIONS] <file> +Options: + -g | -grid Draw grid lines + -i | -idle <time> Stop if <file> unchanging for <time> sec (default = 60) + -l | -logscale Plot y-axis data on log scale + -r | -refresh <time> Refresh display every <time> sec (default = 10) + -x | -xrange <range> Set <range> of x-axis data, format "[0:1]" + -y | -yrange <range> Set <range> of y-axis data, format "[0:1]" + -h | -help Display short help and exit Monitor data with Gnuplot from time-value(s) graphs written by OpenFOAM -e.g. by functionObjects -- requires gnuplot, gnuplot_x11 +e.g. by functionObjects. For example, -Example: - foamMonitor -l postProcessing/residuals/0/residuals.dat + foamMonitor -l postProcessing/residuals/0/residuals.dat USAGE + exit 0 # A clean exit +} + + +# Report error and exit +die() +{ + exec 1>&2 + echo + echo "Error encountered:" + while [ "$#" -ge 1 ]; do echo " $1"; shift; done + echo + echo "See '${0##*/} -help' for usage" + echo exit 1 } + +# Set Gnuplot header plotFileHeader() { cat<<EOF set term x11 1 font "helvetica,17" linewidth 1.5 persist noraise $LOGSCALE +$XRANGE $YRANGE $GRID set title "Data Monitoring" @@ -71,34 +85,49 @@ plot \\ EOF } + +# Set Gnuplot footer plotFileFooter() { cat<<EOF - pause $REFRESH reread EOF } -howMany() ( set -f; set -- $1; echo $# ) +# Count number of tokens in a variable +howMany() { + ( set -f; set -- $1; echo $# ) +} + + +#------------------------------------------------------------------------------- IDLE=60 REFRESH=10 LOGSCALE="" +XRANGE="" YRANGE="" GRID="" GNUPLOT=$(which gnuplot) -! [ "x$GNUPLOT" = "x" ] || usage "Gnuplot not installed" +[ ! "$GNUPLOT" = "" ] || die "foamMonitor requires Gnuplot installed" -# parse options +#------------------------------------------------------------------------------- + +# Parse options while [ "$#" -gt 0 ] do case "$1" in -h | -help*) - usage + printHelp ;; -i | -idle) - [ "$#" -ge 2 ] || usage "'$1' option requires an argument" - [ ! -z "${2##*[!0-9]*}" ] && IDLE=$2 || usage "Argument of '$1' is not an integer: '$2'" + [ "$#" -ge 2 ] || die "'$1' option requires an argument" + if [ -n "${2##*[!0-9]*}" ] + then + IDLE=$2 + else + die "Argument of '$1' is not an integer: '$2'" + fi shift 2 ;; -l | -logscale) @@ -106,12 +135,22 @@ do shift 1 ;; -r | -refresh) - [ "$#" -ge 2 ] || usage "'$1' option requires an argument" - [ ! -z "${2##*[!0-9]*}" ] && REFRESH=$2 || usage "Argument of '$1' is not an integer: '$2'" + [ "$#" -ge 2 ] || die "'$1' option requires an argument" + if [ -n "${2##*[!0-9]*}" ] + then + REFRESH=$2 + else + die "Argument of '$1' is not an integer: '$2'" + fi + shift 2 + ;; + -x | -xrange) + [ "$#" -ge 2 ] || die "'$1' option requires an argument" + XRANGE="set xrange $2" shift 2 ;; -y | -yrange) - [ "$#" -ge 2 ] || usage "'$1' option requires an argument" + [ "$#" -ge 2 ] || die "'$1' option requires an argument" YRANGE="set yrange $2" shift 2 ;; @@ -120,7 +159,7 @@ do shift 1 ;; -*) - usage "unknown option: '$*'" + die "unknown option: '$*'" ;; *) break @@ -128,28 +167,28 @@ do esac done -[ $# -eq 1 ] || usage "Incorrect arguments specified" -[ -f $1 ] || usage "File $1 does not exit" -FILE=$1 +[ "$#" -eq 1 ] || die "Incorrect arguments specified" +[ -f "$1" ] || die "File $1 does not exit" +FILE="$1" # Get KEYS from header -KEYS=$(grep -E '^#' $FILE | tail -1) +KEYS=$(grep -E '^#' "$FILE" | tail -1) -[ "x$KEYS" = "x" ] && KEYS="# Step" +[ "$KEYS" = "" ] && KEYS="# Step" NKEYS=$(howMany "$KEYS") -NCOLS=$(tail -1 $FILE | awk '{ print NF}') +NCOLS=$(grep -m 1 '^[^#]' "$FILE" | awk '{ print NF }') # With full column labels, NKEYS = NCOLS + 1, since it includes "#" # If NKEYS > NCOLS + 1, REMOVE EXCESS KEYS -NCOLSPONE=$(expr $NCOLS + 1) +NCOLSPONE=$((NCOLS+1)) [ "$NKEYS" -gt "$NCOLSPONE" ] && KEYS=$(echo $KEYS | cut -d" " -f1-$NCOLSPONE) NKEYS=$(howMany "$KEYS") i=0 while [ "$NKEYS" -le "$NCOLS" ] do - i=$(expr $i + 1) + i=$((i+1)) KEYS="$KEYS data$i" NKEYS=$(howMany "$KEYS") done @@ -159,33 +198,33 @@ XLABEL=$(echo $KEYS | cut -d " " -f2) KEYS=$(echo $KEYS | cut -d " " -f3-) GPFILE=$(mktemp) -plotFileHeader > $GPFILE +plotFileHeader > "$GPFILE" i=1 for field in $KEYS do - i=$(expr $i + 1) + i=$((i+1)) PLOTLINE="\"$FILE\" using 1:${i} with lines title \"$field\"" if [ $i -lt $NCOLS ] then PLOTLINE="$PLOTLINE, \\" fi - echo $PLOTLINE >> $GPFILE + echo $PLOTLINE >> "$GPFILE" done -plotFileFooter >> $GPFILE +plotFileFooter >> "$GPFILE" -touch $FILE -$GNUPLOT $GPFILE & +touch "$FILE" +$GNUPLOT "$GPFILE" & PID=$! while true do MODTIME=$(stat --format=%Y $FILE) - IDLEAGO=$(expr $(date +%s) - $IDLE) + IDLEAGO=$(($(date +%s)-IDLE)) test "$MODTIME" -gt "$IDLEAGO" || break sleep $REFRESH done kill -9 $PID -rm $GPFILE +rm -f "$GPFILE" #------------------------------------------------------------------------------