Skip to content
Snippets Groups Projects
foamLog 10.4 KiB
Newer Older
#!/bin/sh
#------------------------------------------------------------------------------
# =========                 |
# \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
#  \\    /   O peration     |
#   \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
#    \\/     M anipulation  |
#-------------------------------------------------------------------------------
# License
#     This file is part of OpenFOAM.
#
#     OpenFOAM is free software: you can redistribute it and/or modify it
#     under the terms of the GNU General Public License as published by
#     the Free Software Foundation, either version 3 of the License, or
#     (at your option) any later version.
#
#     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
#     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
#     for more details.
#
#     You should have received a copy of the GNU General Public License
#     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
#
# Script
#     foamLog
#
# Description
#     extracts info from log file
#
# Bugs
#     -solution singularity not handled
#------------------------------------------------------------------------------
Script=${0##*/}
toolsDir=${0%/*}/tools
siteDir=${WM_PROJECT_SITE:-${WM_PROJECT_INST_DIR:-<unknown>}/site}
userDir=$HOME/.OpenFOAM
    while [ "$#" -ge 1 ]; do echo "$1"; shift; done
    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
$Script - extracts xy files from OpenFOAM logs.
#------------------------------------------------------------------------------
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
Andrew Heather's avatar
Andrew Heather committed
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,
Andrew Heather's avatar
Andrew Heather committed
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
Option -q suppresses the default information and only prints the extracted
-----------------------------------------------------------------------------
HELP
unset listOpt quietOpt localDB

# parse options
while [ "$#" -gt 0 ]
    case "$1" in
    -h | -help)
        printHelp
        exit 0
        ;;
    -n)
        unset timeName
        shift
        ;;
    -l | -list)
        listOpt=true
        shift
        ;;
    -q | -quiet | -s | -silent)
        quietOpt=true
        shift
        ;;
    -*)
        usage "unknown option: '$*'"
        ;;
    *)
# find the database file
DBFILE=$Script.db
[ -f $DBFILE ] || DBFILE=`foamEtcFile $Script.db` || DBFILE=$toolsDir/$Script.db
# need the database file
[ -f $DBFILE ] || {
    echo "$Script: Cannot read database $DBFILE"
    exit 1
# single logFile
if [ $# -eq 1 ]
then
    LOG=$1
    [ -r "$LOG" ] && [ -f "$LOG" ] || usage "Cannot read log $LOG"
else
    usage
fi


myEcho()
{
   [ "$quietOpt" = true ] || echo "$*"
}


# getSolvedVars logFile
# Prints names of all 'solved for' variables in the log file.
Mattijs Janssens's avatar
Mattijs Janssens committed
    fgrep ' Solving for ' $1 | fgrep ',' | sed -e 's/.* Solving for \([^,]*\)[,:].*/\1/' | sort -u
}


# getQueries dbFile queryName
# Gets regular expressions for a certain queryName from the database
    [ -f "$dbFile" ] || {
        echo "Cannot find dbFile $dbFile"
        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
}


# getDbQueryList dbFile
# Echoes list of possible queries
    grep -v '^#' $1 | grep '[^ \t]' | awk -F '/' '{print $1}'
}


# getSolveQueryList logFile
# Echoes list of queries from "solved for" variables in log file
    solvedVars=`getSolvedVars $1`

    for var in $solvedVars
    do
        echo "${var}"
        echo "${var}FinalRes"
        echo "${var}Iters"
    done
}

# getAllQueries dbFile logFile
# Gets all queries from database and from logfile
    #-- All solved for queries from log file
    [ "$localDB" = true ] || queries=`getSolveQueryList $2`

    #-- Add ones from database, present in log file
    # Note: just like awk, line selected with regular expression,
    #       column with string.
    dbQueries=`getDbQueryList $1`

    for var in $dbQueries
    do
        getQueries $1 "$var"
Mattijs Janssens's avatar
Mattijs Janssens committed
        line=`egrep "$LINEQ" $2`
            column=`echo "$line" | fgrep "$NUMQ"`
                queries="$queries $var"
            fi
        fi
    done

    for q in $queries
    do
        echo "$q"
    done | sort -u
}

#-----------------------------
# Main
#-----------------------------

    getAllQueries $DBFILE $LOG
    exit 0
fi

caseDir=.
outputDir=$caseDir/logs
[ -d "$caseDir" ] || {
    echo "$Script: Cannot read $caseDir"

QUERYNAMES=`getAllQueries $DBFILE $LOG`

#
# Make logs dir in case directory and place awk file there
#
mkdir -p $outputDir
AWKFILE=$outputDir/$Script.awk

myEcho "Using:"
myEcho "  log      : $LOG"
myEcho "  database : $DBFILE"
myEcho "  awk file : $AWKFILE"
myEcho "  files to : $outputDir"
myEcho ""


#-----------------------------
# Generate Awk program
#-----------------------------

rm -f $AWKFILE 2> /dev/null
cat << AWK_CONTENTS > $AWKFILE
# header
BEGIN {
    Iteration=0
    resetCounters()
}
# 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


cat << AWK_CONTENTS >> $AWKFILE
# Extract value after columnSel
function extract(inLine,columnSel,outVar,a,b)
{
    a=index(inLine, columnSel)
    b=length(columnSel)
    split(substr(inLine, a+b),outVar)
    gsub("[,:]","",outVar[1])
}

#
# Code for iteration separator (increments 'Iteration')
#
getQueries $DBFILE 'Separator'
cat << AWK_CONTENTS >> $AWKFILE
# Iteration separator (increments 'Iteration')
/$LINEQ/ {
    Iteration++
    resetCounters()
}

getQueries $DBFILE 'Time'
cat << AWK_CONTENTS >> $AWKFILE
# Time extraction (sets 'Time')
/$LINEQ/ {
    extract(\$0, "$NUMQ", val)
    Time=val[1]
}

#
# Code for singularity handling.
#
cat << AWK_CONTENTS >> $AWKFILE
# Skip whole line with singularity variable
/solution singularity/ {
    next;
}

#
# 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
    }
for queryName in $QUERYNAMES
do
    getQueries $DBFILE $queryName
        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


#-----------------------------
# Run awk program on log
#-----------------------------
(
    cmd="awk -f $AWKFILE $LOG"
    myEcho "Executing: $cmd"
    $cmd
    myEcho ""
)

#-----------------------------
# Print found
#-----------------------------
myEcho "Generated XY files for:"
[ "$quietOpt" = true ] || getAllQueries $DBFILE $LOG
henry's avatar
henry committed
myEcho "End"

#------------------------------------------------------------------------------