diff --git a/applications/utilities/postProcessing/lagrangian/particleTracks/particleTrackProperties b/applications/utilities/postProcessing/lagrangian/particleTracks/particleTrackProperties index e258f47597..2f04084402 100644 --- a/applications/utilities/postProcessing/lagrangian/particleTracks/particleTrackProperties +++ b/applications/utilities/postProcessing/lagrangian/particleTracks/particleTrackProperties @@ -14,7 +14,7 @@ FoamFile } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // -cloudName reactingCloud1; +cloud reactingCloud1; sampleFrequency 1; diff --git a/bin/foamMonitor b/bin/foamMonitor index 3998fa3a4c..28923708f1 100755 --- a/bin/foamMonitor +++ b/bin/foamMonitor @@ -7,7 +7,7 @@ # \\/ M anipulation | #------------------------------------------------------------------------------- # Copyright (C) 2015 OpenFOAM Foundation -# Copyright (C) 2019-2021 OpenCFD Ltd. +# Copyright (C) 2019-2023 OpenCFD Ltd. #------------------------------------------------------------------------------ # License # This file is part of OpenFOAM, distributed under GPL-3.0-or-later. @@ -18,7 +18,7 @@ # Description # Monitor data with Gnuplot from time-value(s) graphs written by OpenFOAM # e.g. by functionObjects -# - requires gnuplot, gnuplot_x11 +# - requires gnuplot, gnuplot_x11, sed, awk # #------------------------------------------------------------------------------ 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 plotFileHeader() { + TITLE="$1" + NCOLOURS="$2" + SIZE="1200,627" cat</dev/null || die "foamMonitor requires sed installed" +command -v awk >/dev/null || die "foamMonitor requires awk installed" #------------------------------------------------------------------------------- @@ -154,63 +175,123 @@ do esac done + [ "$#" -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" = "" ] && KEYS="# Step" NKEYS=$(howMany "$KEYS") 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 "#" # If NKEYS > NCOLS + 1, REMOVE EXCESS KEYS NCOLSPONE=$((NCOLS+1)) -[ "$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 +[ "$NKEYS" -gt "$NCOLSPONE" ] && KEYS=$(echo "$KEYS" | cut -d" " -f1-$NCOLSPONE) # Remove # and Time keys -XLABEL=$(echo $KEYS | cut -d " " -f2) -KEYS=$(echo $KEYS | cut -d " " -f3-) +XLABEL=$(echo "$KEYS" | cut -d " " -f2) +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) -plotFileHeader > "$GPFILE" +PLOT_TITLE="$(echo "$FILE" | awk -F'/' '{print $(NF-2) "/" $NF}')" +NUM_ELEMENTS="$((NKEYS * NCOMPS))" + +plotFileHeader "$PLOT_TITLE" "$NUM_ELEMENTS" > "$GPFILE" + i=1 +j=1 for field in $KEYS do 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 PLOTLINE="$PLOTLINE, \\" 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 + +# 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" + touch "$FILE" $GNUPLOT "$GPFILE" & PID=$! while true do - MODTIME=$(stat --format=%Y $FILE) + MODTIME="$(stat --format=%Y "$FILE")" IDLEAGO=$(($(date +%s)-IDLE)) test "$MODTIME" -gt "$IDLEAGO" || break - sleep $REFRESH + sleep "$REFRESH" done + kill -9 $PID rm -f "$GPFILE"