diff --git a/bin/foamLog b/bin/foamLog index 8b7d6587e75377982c6fa7d62c9a458f41beee0d..e784bf435cd27b5a34c77dfc0c5c7001999c5149 100755 --- a/bin/foamLog +++ b/bin/foamLog @@ -26,7 +26,7 @@ # foamLog # # Description -# Script extract data for each time-step from a log file for graphing. +# Extract data for each time-step from a log file for graphing. # #------------------------------------------------------------------------------ Script=${0##*/} @@ -40,11 +40,12 @@ usage() { cat <<USAGE Usage: $Script [OPTIONS] <log> - -list lists but does not extract - -n create single column files with the extracted data only - -quiet quiet operation - -localDB only use the local database file - -help print the usage + -case <dir> specify alternate case directory, default is the cwd + -list | -l lists but does not extract + -n create single column files with extracted data only + -quiet | -q quiet operation + -local | -localDB only use the local database file + -help print the usage $Script - extracts xy files from OpenFOAM logs. @@ -57,43 +58,42 @@ USAGE printHelp() { cat <<HELP ----------------------------------------------------------------------------- -The default is to extract for all the 'Solved for' variables the initial -residual, the final residual and the number of iterations. Additionally, a -(user editable) database is used to extract data for standard non-solved for -variables like Courant number, and execution time. - -$Script -l lists all the possible variables without extracting them. - -The program will generate and run an awk script which writes a set of files, -logs/<var>_<subIter>, for every <var> specified, for every occurrence inside -a time step. - -For variables that are 'Solved for', the initial residual name will be -<var>, the final residual receive the name <var>FinalRes, - -The files are output in a simple xy format with the first column Time (default) -and the second the extracted values. Option -n creates single column -files with the extracted data only. - - -The query database is a simple text format with three entries per line, -separated with '/' : - Column 1 is the name of the variable (cannot contain spaces). - Column 2 is the extended regular expression (egrep) to select the line. - Column 3 is the string (fgrep) to select the column inside the line. -The value taken will be the first (non-space)word after this column. -The database ($Script.db) will taken from these locations: - - . - $userDir/$WM_PROJECT_VERSION - $userDir - $siteDir/$WM_PROJECT_VERSION - $siteDir - $WM_PROJECT_DIR/etc - $toolsDir - -Option -q suppresses the default information and only prints the extracted -variables. + The default is to extract the initial residual, the final residual and + the number of iterations for all 'Solved for' variables. + Additionally, a (user editable) database is used to extract data for + standard non-solved for variables like Courant number, and execution time. + + option -list : lists the possible variables without extracting them. + + The program will generate and run an awk script that writes a set of files, + logs/<var>_<subIter>, for every <var> specified, for every occurrence inside + a time step. + + For variables that are 'Solved for', the initial residual name will be + <var>, the final residual receive the name <var>FinalRes, + + The files are output in a simple xy format with the first column Time + (default) and the second the extracted values. + Option -n creates single column files with the extracted data only. + + The query database is a simple text format with three entries per line, + separated by '/' : + Column 1 is the name of the variable (cannot contain spaces). + Column 2 is the extended regular expression (egrep) to select the line. + Column 3 is the string (fgrep) to select the column inside the line. + The value taken will be the first (non-space)word after this column. + + The database ($Script.db) will taken from these locations: + . + $userDir/$WM_PROJECT_VERSION + $userDir + $siteDir/$WM_PROJECT_VERSION + $siteDir + $WM_PROJECT_DIR/etc + $toolsDir + + option -quiet : suppresses the default information and only prints the + extracted variables. ----------------------------------------------------------------------------- HELP @@ -101,8 +101,9 @@ usage } +caseDir=. timeName=Time -unset listOpt quietOpt localDB +unset optList optQuiet localDB # Parse options while [ "$#" -gt 0 ] @@ -112,85 +113,93 @@ do printHelp exit 0 ;; + -case) + caseDir="$2" + shift + ;; -n) unset timeName - shift ;; -l | -list) - listOpt=true - shift + optList=true ;; -q | -quiet | -s | -silent) - quietOpt=true - shift + optQuiet=true ;; - -localDB) + -local | -localDB) localDB=true - shift ;; -*) - usage "unknown option: '$*'" + usage "unknown option: '$1'" ;; *) break ;; esac + shift done -# Find the database file +# Requires a single logFile +[ $# -eq 1 ] || usage + +logFile=$1 + +# Change to case directory +cd "$caseDir" 2>/dev/null || { + echo "$Script: No such case directory '$caseDir'" 1>&2 + exit 1 +} + +# Find the database file: case-local, from etc dirs, or tools-dir DBFILE=$Script.db -[ -f $DBFILE ] || DBFILE=`foamEtcFile $Script.db` || DBFILE=$toolsDir/$Script.db +[ -f "$DBFILE" ] || \ + DBFILE=$(foamEtcFile $Script.db) || \ + DBFILE=$toolsDir/$Script.db -# Heed the database file -[ -f $DBFILE ] || { - echo "$Script: Cannot read database $DBFILE" +# Need the database file +[ -f "$DBFILE" ] || { + echo "$Script: Cannot read database $DBFILE" 1>&2 exit 1 } -# Single logFile -if [ $# -eq 1 ] -then - LOG=$1 - [ -r "$LOG" ] && [ -f "$LOG" ] || usage "Cannot read log $LOG" -else - usage -fi +# Verify that logFile is readable +[ -r "$logFile" -a -f "$logFile" ] || usage "Cannot read log $logFile" -myEcho() +# Say is like echo, but -quiet turns it off +say() { - [ "$quietOpt" = true ] || echo "$*" + [ "$optQuiet" = true ] || echo "$*" } # getSolvedVars logFile -# Prints names of all 'solved for' variables in the log file. +# Prints names of all 'Solving for ...' variables in the log file. getSolvedVars() { - fgrep ' Solving for ' $1 | fgrep ',' | sed -e 's/.* Solving for \([^,]*\)[,:].*/\1/' | sed -e 's/\./_/g' | sort -u + [ -f "$1" ] && \ + sed -n -e 's/.* Solving for \([^,]*\)[,:].*/\1/p' "$1" | \ + sed -e 's/\./_/g' | \ + sort -u } # getQueries dbFile queryName # Gets regular expressions for a certain queryName from the database +# +# Sets LINEQ, NUMQ getQueries() { - dbFile=$1 - queryName=$2 + local dbFile=$1 + local queryName=$2 [ -f "$dbFile" ] || { - echo "Cannot find dbFile $dbFile" + echo "Cannot find dbFile $dbFile" 1>&2 exit 1 } - LINEQ=`grep -v '^#' $dbFile | awk -F '/' "/$queryName/ {if (\"$queryName\" "'!= $1) next; print $2}'` - NUMQ=`grep -v '^#' $dbFile | awk -F '/' "/$queryName/ {if (\"$queryName\" "'!= $1) next; print $3}'` - - #echo "For $queryName found line selection /$LINEQ/ , column selection /$NUMQ/" 1>&2 - #if [ ! "$LINEQ" -o ! "$NUMQ" ] - #then - # echo "Did not find query for $2 in database $1" 1>&2 - #fi + LINEQ=$(grep -v '^#' $dbFile | awk -F '/' "/$queryName/ {if (\"$queryName\" "'!= $1) next; print $2}') + NUMQ=$(grep -v '^#' $dbFile | awk -F '/' "/$queryName/ {if (\"$queryName\" "'!= $1) next; print $3}') } @@ -198,7 +207,8 @@ getQueries() # Echoes list of possible queries getDbQueryList() { - grep -v '^#' $1 | grep '[^ \t]' | awk -F '/' '{print $1}' + local dbFile=$1 + grep -v '^#' $dbFile | grep '[^ \t]' | awk -F '/' '{print $1}' } @@ -206,7 +216,7 @@ getDbQueryList() # Echoes list of queries from "solved for" variables in log file getSolveQueryList() { - solvedVars=`getSolvedVars $1` + solvedVars=$(getSolvedVars $1) for var in $solvedVars do @@ -221,31 +231,28 @@ getSolveQueryList() # Gets all queries from database and from logfile getAllQueries() { + local db=$1 + local log=$2 + local q queries + #-- All solved for queries from log file - [ "$localDB" = true ] || queries=`getSolveQueryList $2` + [ "$localDB" = true ] || queries=$(getSolveQueryList $log) #-- Add ones from database, present in log file # Note: just like awk, line selected with regular expression, # column with string. - dbQueries=`getDbQueryList $1` + local dbQueries=$(getDbQueryList $db) for var in $dbQueries do - getQueries $1 "$var" - line=`egrep "$LINEQ" $2` - if [ "$line" ] - then - column=`echo "$line" | fgrep "$NUMQ"` - if [ "$column" ] - then - queries="$queries $var" - fi - fi + getQueries $db "$var" + q=$(egrep "$LINEQ" "$log" | fgrep "$NUMQ") + [ -n "$q" ] && queries="$queries $var" done for q in $queries do - echo "$q" + echo $q done | sort -u } @@ -254,21 +261,14 @@ getAllQueries() # Main #----------------------------- -if [ "$listOpt" = true ] +if [ "$optList" = true ] then - getAllQueries $DBFILE $LOG + getAllQueries $DBFILE $logFile exit 0 fi -caseDir=. -outputDir=$caseDir/logs - -[ -d "$caseDir" ] || { - echo "$Script: Cannot read $caseDir" - exit 1 -} - -QUERYNAMES=`getAllQueries $DBFILE $LOG` +outputDir=logs +QUERYNAMES=$(getAllQueries $DBFILE $logFile) # # Make logs dir in case directory and place awk file there @@ -276,12 +276,13 @@ QUERYNAMES=`getAllQueries $DBFILE $LOG` mkdir -p $outputDir AWKFILE=$outputDir/$Script.awk -myEcho "Using:" -myEcho " log : $LOG" -myEcho " database : $DBFILE" -myEcho " awk file : $AWKFILE" -myEcho " files to : $outputDir" -myEcho "" +say "Using:" +say " case : $(pwd -L)" +say " log : $logFile" +say " database : $DBFILE" +say " awk file : $AWKFILE" +say " files to : $outputDir" +say #----------------------------- @@ -290,33 +291,30 @@ myEcho "" rm -f $AWKFILE 2> /dev/null cat << AWK_CONTENTS > $AWKFILE -# header +# Awk script for OpenFOAM log file extraction BEGIN { Iteration=0 resetCounters() } -# reset counters used for variable postfix +# Reset counters used for variable postfix function resetCounters() { AWK_CONTENTS # ---------- for queryName in $QUERYNAMES do - varName=${queryName}Cnt - echo " ${varName}=0" >> $AWKFILE -done - -echo " # Reset counters for general Solving for extraction" >> $AWKFILE -echo " for (varName in subIter)" >> $AWKFILE -echo " {" >> $AWKFILE -echo " subIter[varName]=0" >> $AWKFILE -echo " }" >> $AWKFILE -echo "}" >> $AWKFILE -echo "" >> $AWKFILE - + echo " ${queryName}Cnt=0" +done >> $AWKFILE cat << AWK_CONTENTS >> $AWKFILE + # Reset counters for 'Solving for ...' + for (varName in subIter) + { + subIter[varName]=0 + } +} + # Extract value after columnSel function extract(inLine,columnSel,outVar,a,b) { @@ -332,7 +330,7 @@ AWK_CONTENTS # # Code for iteration separator (increments 'Iteration') # -getQueries $DBFILE 'Separator' +getQueries $DBFILE Separator cat << AWK_CONTENTS >> $AWKFILE # Iteration separator (increments 'Iteration') /$LINEQ/ { @@ -346,7 +344,7 @@ AWK_CONTENTS # # Code for extracting Time # -getQueries $DBFILE 'Time' +getQueries $DBFILE Time cat << AWK_CONTENTS >> $AWKFILE # Time extraction (sets 'Time') /$LINEQ/ { @@ -371,31 +369,30 @@ AWK_CONTENTS # # Code for extracting solved for quantities -# -[ "$localDB" = true ] || - cat << AWK_CONTENTS >> $AWKFILE - # Extraction of any solved for variable - /Solving for/ { - extract(\$0, "Solving for ", varNameVal) - - varName=varNameVal[1] - file=varName "_" subIter[varName]++ - file="$outputDir/" file - extract(\$0, "Initial residual = ", val) - print $timeName "\t" val[1] > file - - varName=varNameVal[1] "FinalRes" - file=varName "_" subIter[varName]++ - file="$outputDir/" file - extract(\$0, "Final residual = ", val) - print $timeName "\t" val[1] > file - - varName=varNameVal[1] "Iters" - file=varName "_" subIter[varName]++ - file="$outputDir/" file - extract(\$0, "No Iterations ", val) - print $timeName "\t" val[1] > file - } +# - note leading tabs for alignment are intentional +[ "$localDB" = true ] || cat <<- AWK_CONTENTS >> $AWKFILE + # Extract: 'Solving for ...' + /Solving for/ { + extract(\$0, "Solving for ", varNameVal) + + varName=varNameVal[1] + file=varName "_" subIter[varName]++ + file="$outputDir/" file + extract(\$0, "Initial residual = ", val) + print $timeName "\t" val[1] > file + + varName=varNameVal[1] "FinalRes" + file=varName "_" subIter[varName]++ + file="$outputDir/" file + extract(\$0, "Final residual = ", val) + print $timeName "\t" val[1] > file + + varName=varNameVal[1] "Iters" + file=varName "_" subIter[varName]++ + file="$outputDir/" file + extract(\$0, "No Iterations ", val) + print $timeName "\t" val[1] > file + } AWK_CONTENTS # ---------- @@ -405,38 +402,45 @@ AWK_CONTENTS # for queryName in $QUERYNAMES do + counter=${queryName}Cnt getQueries $DBFILE $queryName - if [ "$LINEQ" -a "$NUMQ" ] - then - counter=${queryName}Cnt - - echo "# Extraction of $queryName" >> $AWKFILE - echo "/$LINEQ/ {" >> $AWKFILE - echo " extract(\$0, \"$NUMQ\", val)" >> $AWKFILE - echo " file=\"$outputDir/${queryName}_\" ${counter}" >> $AWKFILE - echo " print $timeName \"\\t\" val[1] > file" >> $AWKFILE - echo " ${counter}++" >> $AWKFILE - echo "}" >> $AWKFILE - echo "" >> $AWKFILE - fi -done + # note leading tabs for alignment are intentional + [ -n "$LINEQ" -a -n "$NUMQ" ] && cat<<- AWK_CONTENTS + # Extract: '$queryName' + /$LINEQ/ { + extract(\$0, "$NUMQ", val) + file="$outputDir/${queryName}_" ${counter} + print $timeName "\\t" val[1] > file + ${counter}++ + } + +AWK_CONTENTS +# ---------- +done >> $AWKFILE + +echo "# End" >> $AWKFILE #----------------------------- # Run awk program on log #----------------------------- -( - cmd="awk -f $AWKFILE $LOG" - myEcho "Executing: $cmd" - $cmd - myEcho "" -) +say "Executing: awk -f $AWKFILE $logFile" +awk -f $AWKFILE $logFile +say + #----------------------------- # Print found #----------------------------- -myEcho "Generated XY files for:" -[ "$quietOpt" = true ] || getAllQueries $DBFILE $LOG -myEcho "End" +if [ -z "$optQuiet" ] +then + echo "Generated XY files for:" + + for queryName in $QUERYNAMES + do + echo " ${queryName}" + done + echo "End" +fi #------------------------------------------------------------------------------