#!/bin/sh #------------------------------------------------------------------------------ # ========= | # \\ / F ield | OpenFOAM: The Open Source CFD Toolbox # \\ / O peration | Website: https://openfoam.org # \\ / A nd | Copyright (C) 2018-2024 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 . # # Script # foamInfo # # Description # Prints description and usage of an application, a script, or a model # (including boundary conditions, function objects and fvModels). # #------------------------------------------------------------------------------ usage() { cat< options: -all | -a list all tutorials that use (otherwise maximum 10) and all models of the same family (otherwise maximum 25) -browser | -b output C++ source guide web page with specified browser, e.g. foamInfo -browser "firefox" -help | -h print the usage -keyword | -k uses as a keyword, rather than an exact match -web | -w output C++ source guide web page with the browser specified in the global controlDict file Prints the following for an application, a script, or a model (including boundary conditions, function objects and fvModels). - File: the location of the relevant source code header file. - Description details from the header file. - Usage details from the header file. - Models: lists other models belonging to the same family, where applicable. - Examples: a list of relevant cases from the tutorials directory. By default, finds an exact match with or something beginning with , which is case-insensitive on the first character. Otherwise the user can try a broader keyword match with "-keyword | -k" option. Examples foamInfo incompressibleFluid foamInfo interFoam foamInfo fixedValue foamInfo -k fixedValue foamInfo -a turbulentIntensityKineticEnergyInlet foamInfo symmetry foamInfo -k wallFunction foamInfo kEpsilon foamInfo -k kEpsilon foamInfo RAS foamInfo hPolynomial foamInfo -k contactAngle foamInfo Function1 foamInfo square foamInfo fixedTemperatureConstraint foamInfo foamNewBC USAGE } error() { exec 1>&2 while [ "$#" -ge 1 ]; do echo "$1"; shift; done usage exit 1 } capitaliseWord () { echo "$1" | awk '{$1=toupper(substr($1,0,1))substr($1,2)}1' } # (1) case-sensitive match; (2) case-insensitive match; (3) keyword match findModelFiles() { find "$FOAM_SRC" "$FOAM_APP" \ -name "$1" \ -iname "$2" \ ! -iname "$3" \ ! -name "*Fwd.H" \ ! -name "*Fields.H" \ ! -name "*I.H" -type f } findFiles() { _pre="$1" # Application _out="$(find "$FOAM_APP" -name "${_pre}.C" -type f)" # If same file with .H extension exists, then .C is not an application [ "$_out" ] && \ [ "$(find "$FOAM_APP" -name "${_pre}.H" -type f | wc -c)" -ne 0 ] && unset _out # Script _out="$(find "$FOAM_APP/../bin" -name "${_pre}" -type f | \ sed 's@applications/../@@g' ) $_out" # Model # case-sensitive match _models="$(findModelFiles "${_pre}*.H" "*" "") \ $(findModelFiles "$(capitaliseWord "$_pre")*.H" "*" "")" # case-insensitive match [ "$_models" ] || \ _models="$(findModelFiles "*" "${_pre}*.H" "")" # keyword match [ "$_models" ] && ! [ "$KEYWORD" ] || \ _models="$_models $(findModelFiles "*" "*${_pre}*.H" "${_pre}*.H")" _out="$_models $_out" for _t in scalar vector tensor do echo "$_pre" | grep -oq "$_t" && \ _mod="$(echo "$_pre" | sed "s/${_t}//g")" && \ _out="$(find "$FOAM_SRC" -name "${_mod}*.H" -type f) $_out" done # Function _out="$(find "$FOAM_ETC" -name "${_pre}" -type f) $_out" # Remove whitespace echo "$_out" | xargs -n 1 | sort -u | awk 'NF' } nArgs() { ! [ "$1" ] && echo 0 && return 0 echo "$1" | xargs -n 1 | wc -l return 0 } listArgs() { _i=0 _suggest="" _pri=100 for _a in $1 do _i=$(( _i + 1)) echo "${_i}) $_a" >&2 # Prioritise suggestion locations _tests="\ fields/fvPatchFields/ \ fvMesh/fvPatches/ \ caseDicts/functions/" _n=0 for _t in $_tests do _n=$(( _n + 1)) [ "$_n" -lt "$_pri" ] && \ echo "$_a" | grep -q "$_t" && _suggest="$_i" && _pri="$_n" done done echo "$_suggest" } setFile() { _files="$1" _n="$2" echo "$_files" | xargs -n 1 | awk -v n="${_n}" 'NR==n' } # (1) model family directory (2) depth (optional, default 1) findModelDirs () { _familyDir="$1" _depth=1 [ "$2" ] && _depth="$2" _dirs="" while [ "$_depth" -ge 1 ] do _dirs="$(find "$1" -maxdepth "$_depth" -mindepth "$_depth" -type d | \ sed 's/\/Make//g' | sed 's/\/lnInclude//g')" [ "$_dirs" ] && break _depth=$((_depth - 1)) done echo "$_dirs" | sort -u } fvModelDirs () { for d in \ $(find "$FOAM_APP" -name fvModels) \ $(find "$FOAM_SRC" -name fvModels) do findModelDirs "$d" 2 done } modelsInFamily () { _familyDir="$1" _family="${_familyDir##*/}" ! [ -d "$_familyDir" ] && return 0 _modelDirs="$(findModelDirs "$_familyDir")" ### special handling of fvModels [ "$_family" = fvModels ] && _modelDirs="$(fvModelDirs)" [ "$_modelDirs" ] || return 0 _hasTypeName="" grep -rqw TypeName "$_familyDir" && _hasTypeName="yes" for _mDir in $_modelDirs do # Exclude base class _mName="${_mDir##*/}" echo "$_family" | grep -q "$_mName" && continue # Model family with TypeName defined [ "$_hasTypeName" ] && \ _files="$(find "$_mDir" -maxdepth 1 -name "*.H" -exec \ grep -l TypeName {} \;)" && \ for _f in $_files ; do TypeName "$_f" ; done [ "$_hasTypeName" ] && continue # Model family without TypeName defined # Exclusions echo "Make lnInclude" | \ grep -w "$_mName" && continue echo "$_mName" # Remove model names ending "Base" as they are base classes done | sort -u | sed '/Base$/d' } # Argument: .H file TypeName () { # First sed captures FvPatch, PolyPatch, PointPatch _model="$(grep -Es "TypeName\(\"*[[:alnum:]:_()]*\"*\);" "$1" | \ sed 's@[FP][[:lower:]]*Patch::typeName_()@@g' | \ sed 's@[\t ]*TypeName("*\([[:alnum:]:]*\)"*);@\1@')" [ "$_model" ] && echo "$_model" && return 0 return 1 } modelName () { _file="$1" # Get model from TypeName in file TypeName "$_file" && return 0 # Otherwise use the directory name _modelDir="${_file%/*}" echo "${_modelDir##*/}" return 0 } printInfo() { _file="$1" _all="$2" echo "File" printf " %s\n\n" "$_file" # Description sed -e "s/^#.//g" -e "s/^#$//g" "$_file" | \ sed -n '/^Description/,/^[^ ]/p' | sed \$d # Usage sed -n '/^Usage/,/^[^ ]/p' "$_file" | sed \$d # Model echo "$_file" | grep -q "$FOAM_SRC" || return 0 _model="$(modelName "$_file")" || return 0 _familyDir="$(dirname "$(dirname "$_file")")" ### special handling of fvModels echo "$_familyDir" | grep -q fvModels && \ _familyDir="$FOAM_SRC/fvModels" ### special handling of fvConstraints echo "$_familyDir" | grep -q fvConstraints && \ _familyDir="$FOAM_SRC/fvConstraints" _family="${_familyDir##*/}" _models="$(modelsInFamily "$_familyDir")" _nMo="$(nArgs "$_models")" [ "$_nMo" -eq 0 ] && return 0 printf "Model\n" echo "$_family" | grep -q "$_model" && \ printf " This appears to be the '%s' family of models.\n" \ "$_family" || \ printf " This appears to be the '%s' model of the '%s' family.\n" \ "$_model" "$_family" printf " The models in the '%s' family are:\n" "$_family" _nMoD=25 [ "$_all" = "yes" ] && _nMoD=1000 [ "$_nMo" -gt "$_nMoD" ] && [ "$_all" = "no" ] && \ echo " *** Listing $_nMoD out of $_nMo;" \ "run with \"-a\" option to list all ***" echo "$_models" | awk -v nMoD="$_nMoD" 'FNR <= nMoD {print " + " $1}' printf "\n" return 0 } webInfo() { # basename of file _file="$(basename "$1")" echo "$_file" | grep -q ".[CH]" || error "No web documentation for file \"$_file\"" _pre="$(echo "$_file" | sed 's/\./_8/g')" _url="https://cpp.openfoam.org/${VER}/${_pre}.html" echo "Running \"$BROWSER $_url\"" $BROWSER "$_url" return 0 } showInfo() { _file="$1" _all="$2" _web="$3" # Return 1 for web so examples are not printed [ -n "$_web" ] && webInfo "$_file" && return 1 printInfo "$_file" "$_all" } findSolverExamples() { _pre="$1" _out="" # Solvers _app="$(find "$FOAM_TUTORIALS" -name "$_pre")" _dirs="$(find "$_app" -name "system" -type d)" for _d in $_dirs do _out="${_d%/*} $_out" done # Remove whitespace echo "$_out" | xargs -n 1 } findUtilityExamples() { _pre="$1" _out="" # Applications _scripts="$(find "$FOAM_TUTORIALS" -type f -name "All*")" for _f in $_scripts do grep -rq "$_pre" "$_f" && _out="${_f%/*} $_out" done # Remove whitespace echo "$_out" | xargs -n 1 | sort -u } findModelExamples() { _pre="$1" _out="" # Field files _dirs="$(find "$FOAM_TUTORIALS" \ -type d -name "0*" -o -name "constant" -o -name "system")" for _d in $_dirs do # Space and semicolon pick up exact matches grep -rq " ${_pre};" "$_d" && _out="${_d%/*} $_out" done # Remove whitespace echo "$_out" | xargs -n 1 | sort -u } findAllExamples() { _pre="$1" _type="$2" case "$_type" in model) findModelExamples "$_pre" ;; utility|script) findUtilityExamples "$_pre" ;; solver) findSolverExamples "$_pre" ;; esac } showTypeExamples() { _pre="$1" _type="$2" _all="$3" _examples="" [ -z "$_pre" ] && echo "Examples: none found" && return 1 _nExD=10 [ "$_all" = "yes" ] && _nExD=1000 _examples="$(findAllExamples "$_pre" "$_type")" [ -z "$_examples" ] && \ echo "Examples: cannot find any tutorials using \"$_pre\"" && \ return 1 _nEx="$(nArgs "$_examples")" echo "Examples using \"$_pre\"" [ "$_nEx" -gt "$_nExD" ] && ! [ "$_all" = "yes" ] && \ echo " *** Listing $_nExD out of $_nEx;" \ "run with \"-a\" option to list all ***" echo "$_examples" | awk -v nExD="$_nExD" 'FNR <= nExD {print " " $1}' } showExamples() { _pre="$1" _file="$2" _all="$3" echo "$_file" | grep -q ".H" && _type=model && \ _pre="$(basename "${file%/*}")" && \ echo "$_pre" | grep -iq include && _pre="" ! [ "$_type" ] && echo "$_file" | grep -q "$FOAM_SRC/../bin" && _type=script ! [ "$_type" ] && echo "$_file" | grep -q "$FOAM_UTILITIES" && _type=utility ! [ "$_type" ] && echo "$_file" | grep -q "$FOAM_SOLVERS" && _type=solver [ -n "$_type" ] && showTypeExamples "$_pre" "$_type" "$_all" && return 0 return 0 } web="" all="no" # Global controlDict file controlDict="$(foamEtcFile controlDict 2> /dev/null)" BROWSER="$(grep docBrowser "$controlDict" 2> /dev/null | cut -d "\"" -f2)" KEYWORD="" while [ "$#" -gt 0 ] do case "$1" in -a | -all) all="yes" shift ;; -b | -browser) [ "$#" -ge 2 ] || error "'$1' option requires an argument" BROWSER="$2" web="yes" shift 2 ;; -h | -help) usage && exit 0 ;; -k | -keyword) KEYWORD="yes" shift ;; -w | -web) web="yes" shift ;; -*) error "invalid option '$1'" ;; *) break ;; esac done # Check if browsing is possible VER="${WM_PROJECT_VERSION%%.*}" [ -n "$web" ] && \ ! command -v "$BROWSER" >/dev/null 2>&1 && \ error "Cannot run browser application: $BROWSER" [ -n "$web" ] && [ -z "$VER" ] && \ error "Cannot establish OpenFOAM version: \$WM_PROJECT_VERSION not set" [ "$VER" = "dev" ] || VER="v${VER}" [ $# -gt 1 ] && error "$# arguments \"$*\" specified: only 1 permitted" [ $# -eq 1 ] || error "Missing argument: no application, model, script, etc provided" prefix="$1" files="$(findFiles "$prefix")" [ -z "$files" ] && error "Nothing found with \"$prefix\" in the name" nFiles="$(nArgs "$files")" nFile="" if [ "$nFiles" -eq 1 ] then nFile=1 else echo "Multiple items with \"$prefix\" found:" suggest="$(listArgs "$files")" printf "\n%s" "Enter file number (1-$nFiles) to obtain description " [ -n "$suggest" ] && printf "%s" "(suggest $suggest) " printf "%s" ": " read -r nFile [ -z "$nFile" ] && [ -n "$suggest" ] && nFile="$suggest" [ -z "$nFile" ] && \ echo "Cannot specify nothing; re-run and enter a file number" && exit 1 ! [ "$nFile" -eq "$nFile" ] 2>/dev/null && \ echo "\"$nFile\" is not a number between 1 and $nFiles" && exit 1 { [ "$nFile" -lt 1 ] || [ "$nFile" -gt "$nFiles" ] ; } && \ echo "\"$nFile\" is not a number between 1 and $nFiles" && exit 1 fi file="$(setFile "$files" "$nFile")" showInfo "$file" "$all" "$web" && showExamples "$prefix" "$file" "$all"