Newer
Older
Mark Olesen
committed
#---------------------------------*- sh -*-------------------------------------
# ========= |
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
# \\ / O peration |
# \\/ M anipulation |
#------------------------------------------------------------------------------
# Copyright (C) 2015-2024 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Script
# RunFunctions
#
# Description
# Miscellaneous functions for running tutorial cases
#------------------------------------------------------------------------------
[ -n "$FOAM_TUTORIALS" ] || export FOAM_TUTORIALS="$WM_PROJECT_DIR"/tutorials
# Basic sanity checks
[ -d "$FOAM_TUTORIALS" ] || echo "No OpenFOAM tutorials? : $FOAM_TUTORIALS" 1>&2
# Darwin workaround - SIP clearing DYLD_LIBRARY_PATH variable
if [ -n "$FOAM_LD_LIBRARY_PATH" ] && [ -z "$DYLD_LIBRARY_PATH" ]
then
export DYLD_LIBRARY_PATH="$FOAM_LD_LIBRARY_PATH"
fi
#------------------------------------------------------------------------------
# Check presence of '-parallel' in the argument list.
#
isParallel()
{
for i; do [ "$i" = "-parallel" ] && return 0; done
return 1
}
# Check presence of '-test' in the argument list.
isTest()
{
for i; do [ "$i" = "-test" ] && return 0; done
return 1
}
#
# Check absence of '-test' in the argument list.
#
notTest()
{
for i; do [ "$i" = "-test" ] && return 1; done
return 0
}
# Test for make/wmake, compiler suite or emit warning
# system
if ! command -v make >/dev/null
then
echo "No system 'make' command found ... cannot compile" 1>&2
return 1
fi
# OpenFOAM-specific
if ! command -v wmake >/dev/null
then
echo "No openfoam 'wmake' command found ... cannot compile" 1>&2
return 1
fi
local cxx_compiler
cxx_compiler="$(wmake -show-cxx 2>/dev/null)"
if [ -z "$cxx_compiler" ]
then
echo "No wmake rule for C++ compiler ... cannot compile" 1>&2
return 1
elif ! command -v "$cxx_compiler" >/dev/null
then
echo "No path to C++ compiler ($cxx_compiler) ... cannot compile" 1>&2
return 1
fi
return 0
}
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#
# Check if '$1' corresponds to an OpenFOAM value for 'true' (see Switch.H)
# - does not handle integers very much, although Switch does
#
# Handles -dict as first argument to relay the balance to foamDictionary
# Eg,
# isTrue -dict controls -entry coupling
# ->
# value=$(foamDictionary controls -entry coupling -value)
# if value ...
#
isTrue()
{
local value="$1"
if [ "$value" = "-dict" ]
then
shift
value="$(foamDictionary -value $@ 2>/dev/null)" || return 2
fi
case "$value" in
(t | y | true | yes | on) return 0 ;;
(f | n | false | no | off) return 1 ;;
esac
return 2
}
#
# Extract 'nFaces' for given patchName from constant/polyMesh/boundary
# or constant/{region}/polyMesh/boundary
#
# On failure:
# return '1'
# exit status 1
#
getNumberOfPatchFaces()
{
local patch="${1:-}"
local file="${2:-}"
file="constant/$file${file:+/}polyMesh/boundary"
[ -n "$patch" ] || {
echo "No patch name given" 1>&2
return 1
}
[ -f "$file" ] || {
echo "No such file: $file" 1>&2
return 2
}
local nFaces
nFaces=$(sed -ne \
'/^ *'"$patch"' *$/,/}/{s/^ *nFaces *\([0-9][0-9]*\) *;.*$/\1/p}' \
"$file")
if [ -n "$nFaces" ]
then
echo "$nFaces"
else
echo "No patch entry found for '$patch' in $file" 1>&2
echo 0 # Report as 0
return 2
fi
}
#
# Extract 'numberOfSubdomains' from system/decomposeParDict
# (or alternative location).
#
# On failure:
# return '1'
# exit status 1
#
getNumberOfProcessors()
{
local dict="${1:-system/decomposeParDict}"
case "$dict" in
(system/*) # Already qualified
;;
(*)
# If it does not exist, assume it refers to location in system/
[ -f "$dict" ] || dict="system/$dict"
;;
esac
# Re-use positional parameters for automatic whitespace elimination
set -- $(foamDictionary -entry numberOfSubdomains -value "$dict" 2>/dev/null)
if [ "$#" -eq 1 ]
then
echo "$1"
else
echo "Error getting 'numberOfSubdomains' from '$dict'" 1>&2
echo 1 # Fallback is 1 proc (serial)
return 1
fi
#
# Extract 'application' from system/controlDict
#
# On failure:
# return 'false' which is also a command (ie, shell builtin or /bin/false)
# exit status 1
#
getApplication()
# Re-use positional parameters for automatic whitespace elimination
set -- $(foamDictionary -entry application -value system/controlDict 2>/dev/null)
if [ "$#" -eq 1 ]
then
echo "$1"
else
echo "Error getting 'application' from system/controlDict" 1>&2
echo false # Fallback
return 1
fi
#
# Run given application in serial with logfile output.
# The preexistence of the log file prevents rerunning.
#
runApplication()
local appName appRun optValue logFile logMode
# Any additional parsed arguments (eg, decomposeParDict)
local appArgs
# Parse options until executable is encountered
while [ "$#" -gt 0 ] && [ -z "$appRun" ]
do
case "$1" in
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
('') ;; # Ignore junk
(-a | -append)
logMode=append
;;
(-o | -overwrite)
logMode=overwrite
;;
(-s | -suffix)
logFile=".$2"
shift
;;
(-decompose-dict=*)
optValue="${1#*=}"
case "$optValue" in
('' | none | false) ;; ## Ignore
(*) appArgs="$appArgs -decomposeParDict $optValue" ;;
esac
;;
(-decomposeParDict)
optValue="$2"
shift
case "$optValue" in
('' | none | false) ;; ## Ignore
(*) appArgs="$appArgs -decomposeParDict $optValue" ;;
esac
;;
(*)
appRun="$1"
;;
appName="${appRun##*/}"
logFile="log.$appName$logFile"
if [ -f "$logFile" ] && [ -z "$logMode" ]
echo "$appName already run on $PWD:" \
"remove log file '$logFile' to re-run"
echo "Running $appRun on $PWD"
if [ "$logMode" = append ]
then
$appRun $appArgs "$@" >> $logFile 2>&1
$appRun $appArgs "$@" > $logFile 2>&1
#
# Run given application in parallel with logfile output.
# The preexistence of the log file prevents rerunning.
#
runParallel()
local appName appRun optValue logFile logMode
local mpiopts nProcs
# Any additional parsed arguments (eg, decomposeParDict)
local appArgs="-parallel"
local mpirun="mpirun"
case "$FOAM_MPI" in
(msmpi*)
mpirun="mpiexec"
;;
(*openmpi*)
mpiopts="--oversubscribe"
;;
esac
# Parse options until executable is encountered
while [ "$#" -gt 0 ] && [ -z "$appRun" ]
do
case "$1" in
('') ;; # Ignore junk
(-a | -append)
logMode=append
;;
(-o | -overwrite)
logMode=overwrite
;;
(-s | -suffix)
logFile=".$2"
shift
;;
(-n | -np)
nProcs="$2"
shift
;;
(-decompose-dict=*)
optValue="${1#*=}"
case "$optValue" in
('' | none | false) ;; ## Ignore
(*)
appArgs="$appArgs -decomposeParDict $optValue"
nProcs="$(getNumberOfProcessors "$optValue")"
esac
;;
(-decomposeParDict)
optValue="$2"
shift
case "$optValue" in
('' | none | false) ;; ## Ignore
(*)
appArgs="$appArgs -decomposeParDict $optValue"
nProcs="$(getNumberOfProcessors "$optValue")"
esac
;;
(*)
appRun="$1"
;;
shift
[ -n "$nProcs" ] || nProcs=$(getNumberOfProcessors system/decomposeParDict)
Andrew Heather
committed
appName="${appRun##*/}"
logFile="log.$appName$logFile"
if [ -f "$logFile" ] && [ -z "$logMode" ]
echo "$appName already run on $PWD:" \
"remove log file '$logFile' to re-run"
echo "Running $appRun ($nProcs processes) on $PWD "
# Options '-n' and '-np' are synonymous, but msmpi only supports '-n'
if [ "$logMode" = append ]
then
(
"$mpirun" $mpiopts -n "${nProcs:?}" $appRun $appArgs "$@" </dev/null >> $logFile 2>&1
"$mpirun" $mpiopts -n "${nProcs:?}" $appRun $appArgs "$@" </dev/null > $logFile 2>&1
compileApplication()
{
echo "Compiling $1 application"
wmake $1
}
#
# cloneCase srcDir dstDir
#
cloneCase()
local src=$1
local dst=$2
shift 2
if [ -e "$dst" ]
echo "Case already cloned: remove case directory $dst prior to cloning"
return 1
elif [ ! -d "$src" ]
echo "Error: no directory to clone: $src"
return 1
fi
echo "Cloning $dst case from $src"
mkdir $dst
# These must exist, so do not hide error messages
for f in constant system
do
\cp -r $src/$f $dst
done
# Either (or both) may exist, so error messages may be spurious
for f in 0 0.orig
do
\cp -r $src/$f $dst 2>/dev/null
done
return 0
}
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
#
# cloneParallelCase srcDir dstDir [...times]
#
# If any times are specified, they will be used for the cloning.
# Otherwise the entire processor* directories are cloned
cloneParallelCase()
{
local src=$1
local dst=$2
shift 2
if [ -e "$dst" ]
then
echo "Case already cloned: remove case directory $dst prior to cloning"
return 1
fi
[ -d "$src" ] || {
echo "Error: no directory to clone: $src"
return 1
}
echo "Cloning $dst parallel case from $src"
mkdir $dst
# These must exist, so do not hide error messages
for f in constant system
do
\cp -r $src/$f $dst
done
[ -d $src/processor0 ] || {
echo "Does not appear to be a parallel case"
return 1
}
if [ "$#" -eq 0 ]
then
# Copy all processor directories
echo " clone processor* directories"
\cp -r $src/processor* $dst
else
# Only copy some time directories
echo " clone processor directories with $# times: $@"
for proc in $(\cd $src && \ls -d processor*)
srcProc=$src/$proc
dstProc=$dst/$proc
mkdir $dstProc
\cp -r $srcProc/constant $dstProc/
for time
do
[ -d $srcProc/$time ] && \cp -r $srcProc/$time $dstProc/
return 0
# If 0.orig/ exists, copy (overwrite) into 0/ [ie, serial case]
# * -processor : copy into processor directories instead
# * -all : copy into serial and processor directories
if [ ! -d 0.orig ]
then
echo "No 0.orig/ to restore..." 1>&2
return 0
fi
case "$1" in
(-all | -proc | -processor*)
if [ "$1" = "-all" ]
then
echo "Restore 0/ from 0.orig/ [serial/processor dirs]" 1>&2
\rm -rf 0
\cp -r 0.orig 0 2>/dev/null
else
echo "Restore 0/ from 0.orig/ [processor dirs]" 1>&2
fi
\ls -d processor* | xargs -I {} \rm -rf ./{}/0
\ls -d processor* | xargs -I {} \cp -r 0.orig ./{}/0 > /dev/null 2>&1
(*)
echo "Restore 0/ from 0.orig/" 1>&2
\rm -rf 0
\cp -r 0.orig 0 2>/dev/null
;;
esac
#------------------------------------------------------------------------------