ENH: foamMonitor: modernise and refactor the script (fixes #2104)
- enhance POSIX compliance - apply distinct colours and dash type for each line - standardize the frame size to 1200x627 - dynamically replace the title with <function-object-name>/<file-name> - address underscore character issues - introduce legend components for tensors - resolve a bug caused by parentheses in tensor files BUG: particleTrackProperties: correct the typo (fixes #3050)
This commit is contained in:
parent
7e0acfa4ed
commit
88b3fb7c2d
@ -14,7 +14,7 @@ FoamFile
|
|||||||
}
|
}
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
cloudName reactingCloud1;
|
cloud reactingCloud1;
|
||||||
|
|
||||||
sampleFrequency 1;
|
sampleFrequency 1;
|
||||||
|
|
||||||
|
125
bin/foamMonitor
125
bin/foamMonitor
@ -7,7 +7,7 @@
|
|||||||
# \\/ M anipulation |
|
# \\/ M anipulation |
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
# Copyright (C) 2015 OpenFOAM Foundation
|
# Copyright (C) 2015 OpenFOAM Foundation
|
||||||
# Copyright (C) 2019-2021 OpenCFD Ltd.
|
# Copyright (C) 2019-2023 OpenCFD Ltd.
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# License
|
# License
|
||||||
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||||
@ -18,7 +18,7 @@
|
|||||||
# Description
|
# Description
|
||||||
# Monitor data with Gnuplot from time-value(s) graphs written by OpenFOAM
|
# Monitor data with Gnuplot from time-value(s) graphs written by OpenFOAM
|
||||||
# e.g. by functionObjects
|
# e.g. by functionObjects
|
||||||
# - requires gnuplot, gnuplot_x11
|
# - requires gnuplot, gnuplot_x11, sed, awk
|
||||||
#
|
#
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
printHelp() {
|
printHelp() {
|
||||||
@ -58,16 +58,35 @@ die()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Count the number of scalars between ( and ) to deduce the field dimensions
|
||||||
|
count_components() {
|
||||||
|
_text="$1"
|
||||||
|
|
||||||
|
# Extract text between the first ( and )
|
||||||
|
_matches="$(echo "$_text" | sed -n 's/^[^(]*(\([^)]*\)).*$/\1/p')"
|
||||||
|
|
||||||
|
# Use grep to find numbers (doubles and 0) between ( and ), then count them
|
||||||
|
_count="$(echo "$_matches" | grep -Eo '\b[0-9]+\.?[0-9]*[eE]?[-+]?[0-9]+\b|\b0\b' | wc -l)"
|
||||||
|
|
||||||
|
echo "$_count"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# Set Gnuplot header
|
# Set Gnuplot header
|
||||||
plotFileHeader() {
|
plotFileHeader() {
|
||||||
|
TITLE="$1"
|
||||||
|
NCOLOURS="$2"
|
||||||
|
SIZE="1200,627"
|
||||||
cat<<EOF
|
cat<<EOF
|
||||||
set term x11 1 font "helvetica,17" linewidth 1.5 persist noraise
|
set term x11 1 font "helvetica,17" linewidth 1.5 persist noraise size $SIZE
|
||||||
$LOGSCALE
|
$LOGSCALE
|
||||||
$XRANGE
|
$XRANGE
|
||||||
$YRANGE
|
$YRANGE
|
||||||
$GRID
|
$GRID
|
||||||
set title "Data Monitoring"
|
set title "$TITLE"
|
||||||
set xlabel "$XLABEL"
|
set xlabel "$XLABEL"
|
||||||
|
set key outside
|
||||||
|
set linetype cycle "$NCOLOURS"
|
||||||
plot \\
|
plot \\
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
@ -97,6 +116,8 @@ YRANGE=""
|
|||||||
GRID=""
|
GRID=""
|
||||||
GNUPLOT=$(which gnuplot)
|
GNUPLOT=$(which gnuplot)
|
||||||
[ ! "$GNUPLOT" = "" ] || die "foamMonitor requires Gnuplot installed"
|
[ ! "$GNUPLOT" = "" ] || die "foamMonitor requires Gnuplot installed"
|
||||||
|
command -v sed >/dev/null || die "foamMonitor requires sed installed"
|
||||||
|
command -v awk >/dev/null || die "foamMonitor requires awk installed"
|
||||||
|
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -154,63 +175,123 @@ do
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
[ "$#" -eq 1 ] || die "Incorrect arguments specified"
|
[ "$#" -eq 1 ] || die "Incorrect arguments specified"
|
||||||
[ -f "$1" ] || die "File $1 does not exit"
|
[ -f "$1" ] || die "File $1 does not exit"
|
||||||
FILE="$1"
|
FILE="$1"
|
||||||
|
|
||||||
|
|
||||||
# Get KEYS from header
|
# Get KEYS from header
|
||||||
KEYS=$(grep -E '^#' "$FILE" | tail -1)
|
KEYS=$(grep -E '^#' "$FILE" | tail -1)
|
||||||
|
|
||||||
[ "$KEYS" = "" ] && KEYS="# Step"
|
[ "$KEYS" = "" ] && KEYS="# Step"
|
||||||
NKEYS=$(howMany "$KEYS")
|
NKEYS=$(howMany "$KEYS")
|
||||||
NCOLS=$(grep -m 1 '^[^#]' "$FILE" | awk '{ print NF }')
|
NCOLS=$(grep -m 1 '^[^#]' "$FILE" | awk '{ print NF }')
|
||||||
|
NCOMPS=$(count_components "$(grep -m 1 '^[^#]' "$FILE")")
|
||||||
|
|
||||||
# With full column labels, NKEYS = NCOLS + 1, since it includes "#"
|
# With full column labels, NKEYS = NCOLS + 1, since it includes "#"
|
||||||
|
|
||||||
# If NKEYS > NCOLS + 1, REMOVE EXCESS KEYS
|
# If NKEYS > NCOLS + 1, REMOVE EXCESS KEYS
|
||||||
NCOLSPONE=$((NCOLS+1))
|
NCOLSPONE=$((NCOLS+1))
|
||||||
[ "$NKEYS" -gt "$NCOLSPONE" ] && KEYS=$(echo $KEYS | cut -d" " -f1-$NCOLSPONE)
|
[ "$NKEYS" -gt "$NCOLSPONE" ] && KEYS=$(echo "$KEYS" | cut -d" " -f1-$NCOLSPONE)
|
||||||
NKEYS=$(howMany "$KEYS")
|
|
||||||
|
|
||||||
i=0
|
|
||||||
while [ "$NKEYS" -le "$NCOLS" ]
|
|
||||||
do
|
|
||||||
i=$((i+1))
|
|
||||||
KEYS="$KEYS data$i"
|
|
||||||
NKEYS=$(howMany "$KEYS")
|
|
||||||
done
|
|
||||||
|
|
||||||
# Remove # and Time keys
|
# Remove # and Time keys
|
||||||
XLABEL=$(echo $KEYS | cut -d " " -f2)
|
XLABEL=$(echo "$KEYS" | cut -d " " -f2)
|
||||||
KEYS=$(echo $KEYS | cut -d " " -f3-)
|
KEYS=$(echo "$KEYS" | cut -d " " -f3-)
|
||||||
|
NKEYS=$(howMany "$KEYS")
|
||||||
|
|
||||||
|
|
||||||
|
# Create the legend items
|
||||||
|
TEMPKEYS=""
|
||||||
|
|
||||||
|
for i in $KEYS
|
||||||
|
do
|
||||||
|
case "$NCOMPS" in
|
||||||
|
0) # scalar
|
||||||
|
TEMPKEYS="$TEMPKEYS $i"
|
||||||
|
;;
|
||||||
|
3) # vector
|
||||||
|
for j in x y z
|
||||||
|
do
|
||||||
|
TEMPKEYS="$TEMPKEYS ${i}_${j}"
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
6) # symmetric tensor
|
||||||
|
for j in xx xy xz yy yz zz
|
||||||
|
do
|
||||||
|
TEMPKEYS="$TEMPKEYS ${i}_${j}"
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
9) # tensor
|
||||||
|
for j in xx xy xz yx yy yz zx zy zz
|
||||||
|
do
|
||||||
|
TEMPKEYS="$TEMPKEYS ${i}_${j}"
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
*) # handle other cases if needed
|
||||||
|
echo "Unsupported number of components: $NCOMPS"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
KEYS=$TEMPKEYS
|
||||||
|
|
||||||
|
|
||||||
|
# Create plots
|
||||||
GPFILE=$(mktemp)
|
GPFILE=$(mktemp)
|
||||||
plotFileHeader > "$GPFILE"
|
PLOT_TITLE="$(echo "$FILE" | awk -F'/' '{print $(NF-2) "/" $NF}')"
|
||||||
|
NUM_ELEMENTS="$((NKEYS * NCOMPS))"
|
||||||
|
|
||||||
|
plotFileHeader "$PLOT_TITLE" "$NUM_ELEMENTS" > "$GPFILE"
|
||||||
|
|
||||||
i=1
|
i=1
|
||||||
|
j=1
|
||||||
for field in $KEYS
|
for field in $KEYS
|
||||||
do
|
do
|
||||||
i=$((i+1))
|
i=$((i+1))
|
||||||
PLOTLINE="\"$FILE\" using 1:${i} with lines title \"$field\""
|
|
||||||
if [ $i -lt $NCOLS ]
|
# Reject any keys consisting of 'iter|converged|solver' words
|
||||||
|
case "$field" in
|
||||||
|
*"iter"*|*"converged"*|*"solver"*)
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# Reject any parentheses, and configure gnuplot for the underscore character
|
||||||
|
PLOTLINE="\"< sed 's/[()]//g' $FILE\" u 1:${i} w l dt ${j} t \"$(echo "$field" | sed 's/_/\\\\_/g')\""
|
||||||
|
if [ "$i" -lt "$NCOLS" ]
|
||||||
then
|
then
|
||||||
PLOTLINE="$PLOTLINE, \\"
|
PLOTLINE="$PLOTLINE, \\"
|
||||||
fi
|
fi
|
||||||
echo $PLOTLINE >> "$GPFILE"
|
echo "$PLOTLINE" >> "$GPFILE"
|
||||||
|
|
||||||
|
# Change the dash type after every 5 non-rejected lines
|
||||||
|
[ $(((i-1) % 5)) -eq 0 ] && j=$((j+1))
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Scrap ', \' characters from the tail of plot command, if necessary
|
||||||
|
if tail -n 1 "$GPFILE" | grep -q ', \\$'; then
|
||||||
|
{ head -n -1 "$GPFILE"; tail -n 1 "$GPFILE" | sed 's/, \\$//'; } > tmp.gp
|
||||||
|
mv -f -- tmp.gp "$GPFILE"
|
||||||
|
fi
|
||||||
|
|
||||||
plotFileFooter >> "$GPFILE"
|
plotFileFooter >> "$GPFILE"
|
||||||
|
|
||||||
|
|
||||||
touch "$FILE"
|
touch "$FILE"
|
||||||
$GNUPLOT "$GPFILE" &
|
$GNUPLOT "$GPFILE" &
|
||||||
PID=$!
|
PID=$!
|
||||||
|
|
||||||
while true
|
while true
|
||||||
do
|
do
|
||||||
MODTIME=$(stat --format=%Y $FILE)
|
MODTIME="$(stat --format=%Y "$FILE")"
|
||||||
IDLEAGO=$(($(date +%s)-IDLE))
|
IDLEAGO=$(($(date +%s)-IDLE))
|
||||||
test "$MODTIME" -gt "$IDLEAGO" || break
|
test "$MODTIME" -gt "$IDLEAGO" || break
|
||||||
sleep $REFRESH
|
sleep "$REFRESH"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
kill -9 $PID
|
kill -9 $PID
|
||||||
rm -f "$GPFILE"
|
rm -f "$GPFILE"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user