diff --git a/bin/mpirunDebug b/bin/mpirunDebug
index a2c7d75f60..d8d3f74501 100755
--- a/bin/mpirunDebug
+++ b/bin/mpirunDebug
@@ -7,34 +7,21 @@
# \\/ M anipulation |
#------------------------------------------------------------------------------
# Copyright (C) 2011-2015 OpenFOAM Foundation
-# Copyright (C) 2017-2018 OpenCFD Ltd.
+# Copyright (C) 2017-2021 OpenCFD Ltd.
#------------------------------------------------------------------------------
# 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 .
+# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Script
# mpirunDebug
#
# Description
-# Driver script to run mpi jobs with the processes in a separate XTerm
-# or to separate log files.
+# Invoke mpirun with separate per-processor log files
+# or running in separate XTerms.
# Requires bash on all processors.
#
#------------------------------------------------------------------------------
-. $WM_PROJECT_DIR/bin/tools/RunFunctions # Run functions
+. "${WM_PROJECT_DIR:?}"/bin/tools/RunFunctions # Run functions
usage() {
exec 1>&2
@@ -44,28 +31,76 @@ usage() {
Usage: ${0##*/} [OPTION] -np
options:
- -method=MODE Run mode
- (0) normal
- (1) gdb+xterm
- (2) gdb
- (3) log
- (4) log + xterm
- (5) valgrind + xterm
- (5l) valgrind + log
- (6) gperftools(callgrind)
+ -method=MODE The run mode
+ (0) normal
+ (1) gdb+xterm
+ (2) gdb
+ (3) log
+ (4) log + xterm
+ (5) valgrind + xterm
+ (5l) valgrind + log
+ (6) gperftools(callgrind)
-spawn=TYPE Spawn type: (1) local (2) remote
- -log Alias for -method=3
- -valgrind Alias for -method=5l (valgrind + log)
- -local Alias for -spawn=1
- -yes Start without additional prompt
+ -yes Start without additional prompting
+ -local Same as -spawn=1
+ -remote Same as -spawn=2
+ -clean Remove old processor*.{log,sh} files, mpirun.schema etc
-help Print the usage
-Invoke mpirun but with each process in a separate XTerm, or to separate logfile
+Invoke mpirun with separate per-processor log files or running in
+separate XTerms.
+
+Common shortcuts. Sets default spawn to -local, add -yes.
+ -normal = -method=0
+ -log = -method=3
+ -xlog = -method=4 (log + xterm)
+ -valgrind = -method=5l (valgrind + log)
+ -xvalgrind = -method=5 (valgrind + xterm)
+
+Also detects some OpenFOAM options:
+ -decomposeParDict Use specified file for decomposePar dictionary
USAGE
+ exit 0 # A clean exit
+}
+
+# Report error and exit
+die()
+{
+ exec 1>&2
+ echo
+ echo "Error encountered:"
+ while [ "$#" -ge 1 ]; do echo " $1"; shift; done
+ echo
+ echo "See '${0##*/} -help' for usage"
+ echo
exit 1
}
+#-------------------------------------------------------------------------------
+
+# Method naming/numbering correspondence
+methodPrompt="0)normal 1)gdb+xterm 2)gdb 3)log 4)log+xterm 5)valgrind+xterm 5l)valgrind+log 6)gperftools(callgrind)"
+
+methodNumberToName()
+{
+ case "$1" in
+ 0 | norm* ) echo "normal" ;;
+ 1) echo "gdb-xterm" ;;
+ 2) echo "gdb" ;;
+ 3 | log ) echo "log" ;;
+ 4 | xterm ) echo "log-xterm" ;;
+ 5) echo "valgrind-xterm" ;;
+ 5l | valgr*) echo "valgrind" ;;
+ 6) echo "gperf" ;;
+ *) return 1 ;;
+ esac
+}
+
+
+#-------------------------------------------------------------------------------
+# Basic settings
+
case "$(uname -s)" in
Linux)
ECHO='echo -e'
@@ -75,52 +110,102 @@ Linux)
;;
esac
-unset nProcs appName appArgs
-unset method spawn optNoAsk
+unset appName appArgs nProcs
+unset method spawn optClean
+optConfirm=true
decompDict="system/decomposeParDict"
-# parse options
+# Parse options
while [ "$#" -gt 0 ]
do
# echo "$1" 1>&2
+
+ # Our own options (before the application is specified)
+ if [ -z "$appName" ]
+ then
+ knownOption=true # Assume success
+ case "$1" in
+ '') ;; # ignore junk
+
+ -clean) optClean=true ;;
+ -yes) unset optConfirm ;;
+
+ -local | -remote)
+ spawn="${1#-}"
+ ;;
+
+ -spawn=1) spawn="local" ;;
+ -spawn=2) spawn="remote" ;;
+
+ -method=[0-9]*)
+ knownOption="${1#*=}" # Reuse for input
+ method="$(methodNumberToName "$knownOption")" || \
+ die "Unknown run method \"$knownOption\""
+ ;;
+
+ -normal | -log)
+ method="${1#*-}"
+ unset optConfirm
+ : "${spawn:=local}"
+ ;;
+
+ -xlog | -xterm)
+ method="log-xterm"
+ unset optConfirm
+ : "${spawn:=local}"
+ ;;
+
+ -valgr*)
+ method="valgrind"
+ unset optConfirm
+ : "${spawn:=local}"
+ ;;
+
+ -xvalgr*)
+ method="valgrind-xterm"
+ unset optConfirm
+ : "${spawn:=local}"
+ ;;
+
+ -np)
+ nProcs="$2"
+ shift
+ ;;
+
+ -decomposeParDict)
+ # Grab values and add to args immediately
+ decompDict="$2"
+ appArgs="${appArgs}${appArgs:+ }$1 \"$2\""
+ shift
+ ;;
+
+ *)
+ knownOption=false # Fallthrough to regular processing
+ ;;
+ esac
+
+ if [ "$knownOption" = true ]
+ then
+ shift
+ continue
+ fi
+ fi
+
case "$1" in
- -help*)
- usage
- ;;
-
- -method=[0-6]* | -method=5l)
- method="${1#*=}"
- ;;
-
- -spawn=[1-2])
- spawn="${1#*=}"
- ;;
-
- -log)
- method=3
- ;;
-
- -valgrind)
- method=5l
- ;;
-
- -local)
- spawn=1
- ;;
-
- -yes)
- optNoAsk=true
- ;;
+ -help* | --help*) usage ;;
+ '') ;; # ignore junk
-np)
- nProcs=$2
+ nProcs="$2"
shift
;;
-decomposeParDict)
- decompDict=$2
- appArgs="${appArgs}${appArgs:+ }\"$1\""
+ # Grab values and add to args immediately
+ decompDict="$2"
+ appArgs="${appArgs}${appArgs:+ }$1 \"$2\""
+ shift
;;
*)
@@ -135,65 +220,83 @@ do
shift
done
+#-------------------------------------------------------------------------------
-# No -np specified?
-# Try guess from system/decomposeParDict or command-line -decomposeParDict
-if [ -z "$nProcs" -a -f "$decompDict" ]
+# Cleanup only
+if [ -n "$optClean" ]
then
- nProcs=$(getNumberOfProcessors $decompDict) || unset nProcs
+ echo "Cleanup old mpirunDebug files..." 1>&2
+ rm -f gdbCommands mpirun.schema
+ rm -f processor*.log processor*.sh
+ echo " gdbCommands mpirun.schema" 1>&2
+ echo " processor*.log processor*.sh" 1>&2
+ echo "Done" 1>&2
+ exit 0
fi
-echo "nProcs=$nProcs"
-echo "exec=$appName"
-echo "args=$appArgs"
+#-------------------------------------------------------------------------------
+
+# No -np specified?
+# Try guess from system/decomposeParDict or command-line -decomposeParDict
+if [ -z "$nProcs" ] && [ -f "$decompDict" ]
+then
+ nProcs=$(getNumberOfProcessors "$decompDict") || unset nProcs
+fi
+
+
+cat << REPORT_SETTINGS 1>&2
+Run parameters:
+ procs : ${nProcs:-[]}
+ exec : ${appName:-[]}
+ args : ${appArgs:-[]}
+REPORT_SETTINGS
+
+[ -n "$nProcs" ] || die "Number of processors not specified or not detected"
+[ -n "$appName" ] || die "No application specified"
+[ -n "$appArgs" ] || die "No application arguments"
-[ -n "$nProcs" ] || usage
-[ -n "$appArgs" ] || usage
-[ -n "$appName" ] || usage
exec=$(command -v $appName)
-[ -x "$exec" ] || {
- echo "Cannot find executable $appName or is not executable"
- usage
-}
-
-[ -n "$PWD" ] || PWD=$(pwd)
-
-echo "run $appArgs" > $PWD/gdbCommands
-echo "where" >> $PWD/gdbCommands
-echo "Constructed gdb initialization file $PWD/gdbCommands"
+[ -x "$exec" ] || die "Command not found or not executable: $appName"
+[ -n "$PWD" ] || PWD="$(pwd)"
# Choose method
if [ -z "$method" ]
then
- $ECHO "Choose running method: 0)normal 1)gdb+xterm 2)gdb 3)log 4)log+xterm 5)valgrind+xterm 5l)valgrind+log 6)gperftools(callgrind): \c"
- read method
- case "$method" in
- 0 | 1 | 2 | 3 | 4 | 5 | 5l | 6)
- # okay
- ;;
- *)
- usage
- ;;
- esac
+ echo "Choose running method: ${methodPrompt}"
+ $ECHO "[normal] > \c"
+ read input
+ : "${input:=0}" # Default (0) normal
+
+ method="$(methodNumberToName "$input")" || \
+ die "Unknown run method \"$input\""
fi
# Choose spawn
if [ -z "$spawn" ]
then
- $ECHO "Run all processes local or distributed? 1)local 2)remote: \c"
- read spawn
- case "$spawn" in
- 1 | 2)
- # okay
- ;;
- *)
- usage
- ;;
+ echo "Run all processes local or distributed? 1)local 2)remote"
+ $ECHO "[local] > \c"
+ read input
+ : "${input:=1}" # Default (1) local
+
+ case "$input" in
+ (1) spawn="local" ;;
+ (2) spawn="remote" ;;
+ (*) die "Unknown spawn type \"$input\""
esac
fi
+# Methods with gdb:
+case "$method" in
+(*gdb*)
+ echo "run $appArgs" > "$PWD"/gdbCommands
+ echo "where" >> "$PWD"/gdbCommands
+ echo "Constructed gdb initialization file $PWD/gdbCommands" 1>&2
+ ;;
+esac
+
sourceFoam=false # Fallback command
@@ -227,10 +330,10 @@ case "$sourceFoam" in
;;
esac
-echo "**sourceFoam: $sourceFoam"
+echo "**sourceFoam: $sourceFoam" 1>&2
-rm -f $PWD/mpirun.schema
-touch $PWD/mpirun.schema
+rm -f "$PWD"/mpirun.schema
+touch "$PWD"/mpirun.schema
proc=0
xpos=0
@@ -248,50 +351,50 @@ do
;;
esac
- echo "#!/bin/bash" > $procCmdFile
- echo "$sourceFoam" >> $procCmdFile
- echo "cd $PWD" >> $procCmdFile
+cat << COMMANDS > "$procCmdFile"
+#!/bin/bash
+$sourceFoam
+cd "${PWD}" || exit
+COMMANDS
+
+ # Add to the mpirun.schema
+ case "$method" in
+ (*xterm*) echo "${node}${xterm} -e ${procCmdFile}" >> "$PWD"/mpirun.schema ;;
+ (*) echo "${node}${procCmdFile}" >> "$PWD"/mpirun.schema ;;
+ esac
case "$method" in
- 0)
- echo "${node}$procCmdFile" >> $PWD/mpirun.schema
- echo "$exec $appArgs | tee $procLog" >> $procCmdFile
+ (normal)
+ echo "$exec $appArgs | tee $procLog"
;;
- 1)
- echo "${node}$xterm -e $procCmdFile" >> $PWD/mpirun.schema
- echo "gdb -command $PWD/gdbCommands $exec 2>&1 | tee $procLog"
- echo "read dummy"
- ;;
- 2)
- echo "${node}$procCmdFile" >> $PWD/mpirun.schema
- echo "gdb -command $PWD/gdbCommands $exec > $procLog 2>&1"
- ;;
- 3)
- echo "${node}$procCmdFile" >> $PWD/mpirun.schema
+ (log)
echo "$exec $appArgs > $procLog 2>&1"
;;
- 4)
- echo "${node}$xterm -e $procCmdFile" >> $PWD/mpirun.schema
+ (log-xterm)
echo "$exec $appArgs 2>&1 | tee $procLog"
- echo "read dummy"
+ echo "read input"
;;
- 5)
- echo "${node}$xterm -e $procCmdFile" >> $PWD/mpirun.schema
- echo "valgrind --leak-check=full --show-reachable=yes $exec $appArgs 2>&1 | tee $procLog"
- echo "read dummy"
+ (gdb)
+ echo "gdb -command $PWD/gdbCommands $exec > $procLog 2>&1"
;;
- 5l)
- echo "${node}$procCmdFile" >> $PWD/mpirun.schema
+ (gdb-xterm)
+ echo "gdb -command $PWD/gdbCommands $exec 2>&1 | tee $procLog"
+ echo "read input"
+ ;;
+ (valgrind | valgrind-log)
echo "valgrind --leak-check=full --show-reachable=yes $exec $appArgs > $procLog 2>&1"
;;
- 6)
- echo "${node}$procCmdFile" >> $PWD/mpirun.schema
+ (valgrind-xterm)
+ echo "valgrind --leak-check=full --show-reachable=yes $exec $appArgs 2>&1 | tee $procLog"
+ echo "read input"
+ ;;
+ (gperf)
echo "CPUPROFILE=log.profiler_$proc $exec $appArgs"
echo "pprof --callgrind $exec log.profiler_$proc > log.profiler_$proc.callgrind"
;;
- esac >> $procCmdFile
+ esac >> "$procCmdFile"
- chmod +x $procCmdFile
+ chmod +x "$procCmdFile"
let column=proc%6
if [ $proc -ne 0 -a $column -eq 0 ]
@@ -306,7 +409,7 @@ done
for ((proc=0; proc<$nProcs; proc++))
do
procLog="processor${proc}.log"
- echo " tail -f $procLog"
+ echo " tail -f $procLog" 1>&2
done
unset cmd
@@ -330,28 +433,27 @@ MPICH)
cmd="${cmd} :"
fi
cmd="${cmd} -n 1 ${procXtermCmdFile}"
- done < $PWD/mpirun.schema
+ done < "$PWD"/mpirun.schema
;;
*)
- echo
- echo "Unsupported WM_MPLIB setting : $WM_MPLIB"
- usage
- exit 1
+ die "Unsupported WM_MPLIB setting : $WM_MPLIB"
+ ;;
esac
-echo "Constructed $PWD/mpirun.schema file."
-echo
-echo " $cmd"
-echo
+echo 1>&2
+echo "Constructed $PWD/mpirun.schema file:" 1>&2
+echo 1>&2
+echo " $cmd" 1>&2
+echo 1>&2
-if [ -n "$optNoAsk" ]
+if [ -n "$optConfirm" ]
then
- echo "starting: " $(date '+%Y-%m-%d %H:%M:%S %z' 2>/dev/null)
- echo
-else
# Pause before running
$ECHO "Press return to execute.\c"
- read dummy
+ read input
+else
+ echo "starting: $(date '+%Y-%m-%d %H:%M:%S %z' 2>/dev/null)" 1>&2
+ echo 1>&2
fi
exec $cmd