Newer
Older
set -o pipefail #abort if left command on a pipe fails
#This script:
# - compiles the PHYEX package using a specific commit
# - runs the different test progs and checks if results are identical to a given version
#ice_adjust: the ice adjust test case
#ref is commit 855b8f8 for ice_adjust, rain_ice
#ref is commit ??????? for turb
#ref is commit 7e44ab1 for shallow
#ref is commit e070d16 for rain_ice_old
#Commit e070d16 can be used for rain_ice_old (ref commit for this testprogs), and for
#turb, shallow, rain_ice and ice_adjust (as it gives the same results for these test cases).
#Some modifications have been introduced and new reference commit is 00148b1
#Data generation:
# - The last commit of the testprogs_data branch (based on 46t1) is able to produce the data
# for the turb, shallow, rain_ice and ice_adjust testprogs. The code is present but must be
# activated in the corresponding aro_* routine (as only one set of data can be produced during
# a single execution).
# - The last commit of the testprogs_data2 branch (based on 48t3) is able to produce the data
# for the rain_ice_old testprog.

RIETTE Sébastien
committed
#######################
#### CONFIGURATION ####
#######################
#Special pack names:
# - ref: symbolic name to the commit to use as a reference
# useless for the commits containing a json file

RIETTE Sébastien
committed
#About the tests:
# - ALLTests is a list of tests to be done when '-t ALL' is used. This list is filled here
# in case there is no ial_version.json file containig a 'testing' section. If this 'testing'
# section exists, this list is overridden.
# - allowedTests is the list of allowed tests which can depend on platform, if we ask to perform an action
# with a test not in the allowedTests list, the action is ignored
# - defaultTest is the list of tests to perform when no '-t' option is provided on the command line.
ALLTests="ice_adjust,rain_ice,rain_ice_old,turb,shallow"
defaultTest=${ALLTests}
allowedTests=${ALLTests}
separator='_' #- seprator must be in sync with prep_code.sh separator
PHYEXTOOLSDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

RIETTE Sébastien
committed
TESTDIR=${TESTPROGSDIR:=$HOME/TESTPROGS}
dirdata=$PHYEXTOOLSDIR/testprogs_data
if [ $(hostname | cut -c 1-7) == 'belenos' -o $(hostname | cut -c 1-7) == 'taranis' ]; then
defaultarchfile=MIMPIIFC1805.EPONA
elif [ $(hostname) == 'aurora01' ]; then
defaultarchfile=ECMWF_NEC440MPI225SP.AU.x
#Options to have longer simulations, tag is used to build the directory name of the result
declare -A conf_extra_tag
declare -A conf_extra_opts
i=-1
i=$((i+1)); conf_extra_tag[$i]=""
conf_extra_opts[$i]=""
i=$((i+1)); conf_extra_tag[$i]="_Z120_NPRO32_BLK1024"
conf_extra_opts[$i]="--nflevg 120 --nproma 32 --blocks 1024"
i=$((i+1)); conf_extra_tag[$i]="_Z120_NPRO32_BLK256_TIMES4"
conf_extra_opts[$i]="--nflevg 120 --nproma 32 --blocks 256 --times 4"
i=$((i+1)); conf_extra_tag[$i]="_Z120_NPRO32_BLK64_TIMES16"
conf_extra_opts[$i]="--nflevg 120 --nproma 32 --blocks 64 --times 16"
i=$((i+1)); conf_extra_tag[$i]='_Z120_NPRO${NPROMA}_BLK${NBLOCKS}'
conf_extra_opts[$i]='--nflevg 120 --nproma ${NPROMA} --blocks ${NBLOCKS}'

RIETTE Sébastien
committed
################################
#### COMMAND LINE ARGUMENTS ####
################################
echo "Usage: $0 [-h] [-p] [-c] [-r] [-C] [-s] [--noexpand] [-t TEST] [--repo-user USER] [--repo-protocol PROTOCOL] [-a ARCH] [-A ARCH] [--remove] [--onlyIfNeeded] [--computeRefIfNeeded] [--no-perf] [--no-check] [-e EXTRAPOLATION] commit [reference]"
echo "commit commit hash (or a directory, or among $specialName) to test"
echo "reference commit hash (or a directory, or among $specialName) REF to use as a reference"
echo "-s suppress compilation directory"

RIETTE Sébastien
committed
echo "-p creates pack"
echo "-c performs compilation"
echo "-r runs the tests"
echo "-C checks the result against the reference"

RIETTE Sébastien
committed
echo "-t TEST comma separated list of tests to execute"
echo " or ALL to execute all tests"
echo "--noexpand do not expand mnh_expand blocks (code will be in array-syntax)"

RIETTE Sébastien
committed
echo "--repo-user USER"
echo " user hosting the PHYEX repository on github,"

RIETTE Sébastien
committed
echo " defaults to the env variable PHYEXREOuser (=$PHYEXREOuser)"

RIETTE Sébastien
committed
echo "--repo-protocol PROTOCOL"
echo " protocol (https or ssh) to reach the PHYEX repository on github,"

RIETTE Sébastien
committed
echo " defaults to the env variable PHYEXREOprotocol (=$PHYEXREOprotocol)"
echo "--remove removes the pack"
echo "--onlyIfNeeded do not rerun already run steps"
echo "--computeRefIfNeeded"
echo " compute the reference if not already present"
echo "--no-perf deactivate DR_HOOK"
echo "--no-check suppress value printing (comparison will be impossible)"
echo " this option can reduce drastically the running time but only allow"
echo " to access performance statistics."

RIETTE Sébastien
committed
echo "-a arch ARCH architecture name to use to build and run the commit (=$defaultarchfile)"
echo "-A arch ARCH architecture name to use for the reference simulation (=$defaultarchfile)"
echo "-e EXTRAPOLATION"
echo " extrapolate data. EXTRAPOLATION corresponds to a configuration:"
for i in $(seq 1 $((${#conf_extra_tag[@]}-1))); do
echo " - '$i': ${conf_extra_opts[$i]} (${conf_extra_tag[$i]})"
done

RIETTE Sébastien
committed
echo "If nothing is asked (pack creation compilation, running, check, removing) everything"
echo "except the removing is done"
echo
echo "If no test is aked for, the default one ($defaultTest) is executed"
echo
echo "With the special reference REF commit, a suitable reference is guessed"
echo
echo "The directory (for commit only, not ref) can take the form server:directory"
echo
echo "If using a directory (for commit or reference) it must contain at least one '/'"
echo "The commit can be a tag, written with syntagx tags/<TAG>"

RIETTE Sébastien
committed
packcreation=0
compilation=0
run=0
check=0
commit=""
reference=""
tests=""
suppress=0
useexpand=""
archfile=$defaultarchfile
refarchfile=$defaultarchfile

RIETTE Sébastien
committed
onlyIfNeeded=0
computeRefIfNeeded=0
extrapolation=0
checkOpt="--check"
while [ -n "$1" ]; do
case "$1" in

RIETTE Sébastien
committed
'-p') packcreation=1;;
'-c') compilation=1;;
'-r') run=$(($run+1));;
'-C') check=1;;
'-t') tests="$2"; shift;;
'--noexpand') useexpand=$1;;

RIETTE Sébastien
committed
'--repo-user') export PHYEXREPOuser=$2; shift;;
'--repo-protocol') export PHYEXREPOprotocol=$2; shift;;
'--remove') remove=1;;
'-a') archfile="$2"; shift;;
'-A') refarchfile="$2"; shift;;

RIETTE Sébastien
committed
'--onlyIfNeeded') onlyIfNeeded=1;;
'--computeRefIfNeeded') computeRefIfNeeded=1;;
'--no-perf') perf=0;;
'--no-check') checkOpt="";;
'-e') extrapolation=$2; shift;;

RIETTE Sébastien
committed
#--) shift; break ;;
*) if [ -z "${commit-}" ]; then
commit=$1
else
if [ -z "${reference-}" ]; then
reference=$1
else
echo "Only two commit hash allowed on command line"
exit 1
fi
fi;;
esac
shift
done

RIETTE Sébastien
committed
if [ $packcreation -eq 0 -a \
$compilation -eq 0 -a \
$check -eq 0 -a \
$remove -eq 0 ]; then

RIETTE Sébastien
committed
packcreation=1
compilation=1
run=1
check=1
fi
if [ -z "${commit-}" ]; then
echo "At least one commit hash must be provided on command line"
exit 2
fi
if [ $check -eq 1 -a -z "${reference-}" ]; then
echo "To perform a comparison two commit hashes are mandatory on the command line"
exit 3
fi
if [[ ! -z "${conf_extra_tag[$extrapolation]+unset}" ]]; then
extrapolation_tag=$(eval echo ${conf_extra_tag[$extrapolation]})
else
echo "The extrapolation option ($extrapolation) doesn't have associated tag"
fi
if [[ ! -z "${conf_extra_opts[$extrapolation]+unset}" ]]; then
extrapolation_opts=$(eval echo ${conf_extra_opts[$extrapolation]})
else
echo "The extrapolation option ($extrapolation) doesn't have associated options"
fi

RIETTE Sébastien
committed
##############################
#### FUNCTION DEFINITIONS ####
##############################
function json_dictkey2value {
# $1 must contain the json string
# $2 must be the key name
# $3 is the default value
json_content="$1" python3 -c "import json; import os; result=json.loads(os.environ['json_content']).get('$2', '$3'); print(json.dumps(result) if isinstance(result, dict) else result)"
}
###########################
#### COMMIT ADAPTATION ####
###########################
#Name and directory for compiling and executing user pack
declare -A refByTest
if echo $commit | grep '/' | grep -v '^tags/' > /dev/null; then

RIETTE Sébastien
committed
#The git repository is a directory
name=$(echo $commit | sed 's/\//'${separator}'/g' | sed 's/:/'${separator}'/g' | sed 's/\./'${separator}'/g')

RIETTE Sébastien
committed
content_testprogs_version=$(scp $commit/src/testprogs/testprogs_version.json /dev/stdout 2>/dev/null || echo "")
[ $suppress -eq 1 -a -d $TESTDIR/$name ] && rm -rf $TESTDIR/$name
elif echo $specialName | grep -w $commit > /dev/null; then
name="$commit"
else

RIETTE Sébastien
committed
#The git repository is on github
if [[ $commit == testprogs${separator}* ]]; then
testprogs_version_file="testprogs_version.json"
else
testprogs_version_file="src/testprogs/testprogs_version.json"
fi
if echo $commit | grep '^tags/' > /dev/null; then
urlcommit=$(echo $commit | cut -d / -f 2-)
else
urlcommit=$commit
fi
content_testprogs_version=$(wget --no-check-certificate https://raw.githubusercontent.com/$PHYEXREPOuser/PHYEX/${urlcommit}/$testprogs_version_file -O - 2>/dev/null || echo "")
name="COMMIT$(echo $commit | sed 's/\//'${separator}'/g' | sed 's/:/'${separator}'/g' | sed 's/\./'${separator}'/g')"
[ $suppress -eq 1 -a -d $TESTDIR/$name ] && rm -rf $TESTDIR/$name
fi

RIETTE Sébastien
committed
if [ ! "${content_testprogs_version}" == "" ]; then
testing=$(json_dictkey2value "$content_testprogs_version" 'testing' '')
refALL=$(json_dictkey2value "$testing" "ALL" '')
if [ ! "$testing" == "" ]; then
ALLTests='' #We reset the list of tests
for t in $(echo $allowedTests | sed 's/,/ /g'); do
ref=$(json_dictkey2value "$testing" "$t" "$refALL")
if [ ! "$ref" == "" ]; then
ALLTests="${ALLTests},$t"
refByTest[$t]=$ref
fi
done
ALLTests="${ALLTests:1}" #Remove first character (',')

RIETTE Sébastien
committed
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
#Name and directory for the reference version
if [ ! -z "${reference-}" ]; then
declare -A refnameByTest
#Reference to use for each test
for t in $(echo $ALLTests | sed 's/,/ /g'); do
#Name of the reference
if [ "$reference" == "REF" ]; then
if [[ ! -z "${refByTest[$t]+unset}" ]]; then #the -v test is valid only with bash > 4.3
#The json file contained the references to use on a per test case basis
caseref=${refByTest[$t]}
else
caseref=$defaultRef
fi
refByTest[$t]=$caseref
else
#The exact reference to use was given on the command line
caseref=$reference
fi
refByTest[$t]=$caseref
#Conversion into directory name
if echo $caseref | grep '/' > /dev/null; then
refname=$(echo $reference | sed 's/\//'${separator}'/g' | sed 's/:/'${separator}'/g' | sed 's/\./'${separator}'/g')
elif echo $specialName | grep -w $caseref > /dev/null; then
refname="$caseref"
else
refname="COMMIT${caseref}"
fi
refnameByTest[$t]=$refname
done
fi

RIETTE Sébastien
committed
if [ -z "${tests-}" ]; then
tests=$defaultTest
elif echo "$tests" | grep -w 'ALL' > /dev/null; then
tests=$(echo "$tests" | sed "s/\bALL\b/$ALLTests/g")
fi
#######################
#### PACK CREATION ####
#######################

RIETTE Sébastien
committed
if [ $packcreation -eq 1 ]; then

RIETTE Sébastien
committed
if [ -d $TESTDIR/$name/build/with_fcm/arch_${archfile} ]; then

RIETTE Sébastien
committed
if [ $onlyIfNeeded -eq 0 ]; then

RIETTE Sébastien
committed
echo "Directory already exists ($TESTDIR/$name/build/with_fcm/arch_${archfile}),"
echo "suppress it to be able to compile it again (or use the -s option to automatically suppress it)"

RIETTE Sébastien
committed
exit 5
fi
else
echo "### Pack creation for commit $commit"
if echo $specialName | grep -w $commit > /dev/null; then
echo "Special commit '$commit' cannot be compiled with this script"
exit 4
fi
mkdir -p $TESTDIR/$name

RIETTE Sébastien
committed
cd $TESTDIR/$name/

RIETTE Sébastien
committed
if [ ! -d build ]; then
cp -r $PHYEXTOOLSDIR/../build . #We use the compilation system from the same commit as the current script
rm -rf build/with_fcm/arch_*
else
echo "WARNING: the compilation system is already there, we use it but it could be outdated"
fi

RIETTE Sébastien
committed
cd $TESTDIR/$name/build/with_fcm/
./make_fcm.sh -p $useexpand --commit $commit --arch $archfile 2>&1 | tee Output_compilation_step1

RIETTE Sébastien
committed
fi

RIETTE Sébastien
committed
#####################
#### COMPILATION ####
#####################
if [ $compilation -eq 1 ]; then
if [ $onlyIfNeeded -eq 0 -o ! -f $TESTDIR/$name/build/with_fcm/arch_${archfile}/build/bin/libphyex.so ]; then
echo "### Compilation of commit $commit"

RIETTE Sébastien
committed
cd $TESTDIR/$name/build/with_fcm/
./make_fcm.sh -c $useexpand --commit $commit --arch $archfile 2>&1 | tee Output_compilation_step2
fi

RIETTE Sébastien
committed
###################
#### EXECUTION ####
###################
if [ $run -ge 1 ]; then
cd $TESTDIR/$name
#Cleaning to suppress old results that may be confusing in case of a crash during the run

RIETTE Sébastien
committed
if [ $onlyIfNeeded -eq 0 ]; then
for t in $(echo $tests | sed 's/,/ /g'); do
if [ -d tests/with_fcm/arch_${archfile}/${t}${extrapolation_tag} ]; then
rm -rf tests/with_fcm/arch_${archfile}/${t}${extrapolation_tag}

RIETTE Sébastien
committed
fi
done
fi
#Run the tests one after the other

RIETTE Sébastien
committed
firstrun=1
for t in $(echo $tests | sed 's/,/ /g'); do

RIETTE Sébastien
committed
if echo $allowedTests | grep -w $t > /dev/null; then #test is allowed on this plateform
if [ ! -d tests/with_fcm/arch_${archfile}/${t}${extrapolation_tag} ]; then #We do not enter systematically this part if onlyIfNeeded=1

RIETTE Sébastien
committed
if [ $firstrun -eq 1 ]; then
echo "### Running of commit $commit"
firstrun=0
fi
if [ ! -f $TESTDIR/$name/build/with_fcm/arch_${archfile}/build/bin/main_${t}.exe ]; then
echo "Directory does not exist ($TESTDIR/$name) or compilation has failed, please check"
exit 6
fi
#execution
cd $TESTDIR/$name
mkdir -p tests/with_fcm/arch_${archfile}/${t}${extrapolation_tag}
cd tests/with_fcm/arch_${archfile}/${t}${extrapolation_tag}

RIETTE Sébastien
committed
ln -s $dirdata/$t data
if [ $perf -eq 1 ]; then
export DR_HOOK_OPT=prof
export DR_HOOK=1
export DR_HOOK_IGNORE_SIGNALS=-1
. $TESTDIR/$name/build/with_fcm/arch_${archfile}/arch.env
set +e
$TESTDIR/$name/build/with_fcm/arch_${archfile}/build/bin/main_${t}.exe $checkOpt $extrapolation_opts > Output_run 2> Stderr_run
stat=$?
set -e
if [ $stat -ne 0 ]; then
cat Stderr_run
exit $stat
fi
if [ $perf -eq 1 ]; then
firstLine=$(grep -m 1 -n "^ *1" drhook.prof.0 | cut -d: -f1)
python3 -c "import numpy, pandas
d = {'time': ('<f4', ('mean', )), 'self': ('<f4', ('mean', 'max', 'min', 'std', 'sum')),
'total': ('<f4', ('mean', 'max', 'min', 'std', 'sum')), 'calls': ('<i4', ('sum', )),
'self_per_call': ('<f4', ('mean', )), 'total_per_call': ('<f4', ('mean', )), 'routine': ('U256', '')}
arraynp = numpy.loadtxt('drhook.prof.0', dtype=[(k, v[0]) for (k, v) in d.items()],
converters={8: lambda s: s.split(b'@')[0].lstrip(b'*')},
skiprows=$firstLine - 1, usecols=[1, 3, 4, 5, 6, 7, 8])
df = pandas.DataFrame(arraynp).groupby('routine').agg(
**{k + '_' + agg:pandas.NamedAgg(column=k, aggfunc=agg)
for (k, agg) in [(k, agg) for k in d.keys() for agg in d[k][1]]
if k != 'routine'}).sort_values('self_sum', ascending=False)
df.index.name += ' ordered by self_sum'
with open('drhook.prof.agg', 'w') as f: f.write(df.to_string())
"
fi

RIETTE Sébastien
committed
fi
fi

RIETTE Sébastien
committed
####################
#### COMPARISON ####
####################
if [ $check -eq 1 ]; then
echo "### Check commit $commit against commit $reference"
alltests=0
message=""
for t in $(echo $tests | sed 's/,/ /g'); do

RIETTE Sébastien
committed
if echo $allowedTests | grep -w $t > /dev/null; then
#Run the reference if needed
if [ $computeRefIfNeeded -eq 1 ]; then
$0 -p -c -r -t $t -a ${refarchfile} --onlyIfNeeded -e $extrapolation ${refByTest[$t]}

RIETTE Sébastien
committed
#File comparison
file1=$TESTDIR/$name/tests/with_fcm/arch_${archfile}/${t}${extrapolation_tag}/Output_run
file2=$TESTDIR/${refnameByTest[$t]}/tests/with_fcm/arch_${refarchfile}/${t}${extrapolation_tag}/Output_run

RIETTE Sébastien
committed
mess=""
te=0
if [ ! -f "$file1" ]; then
mess="Result ($file1) for commit $commit does not exist, please run the simulation"
te=1
fi
if [ ! -f "$file2" ]; then
mess2="Result ($file2) for commit ${refByTest[$t]} does not exist, please run the simulation"
te=1
if [ "$mess" = "" ]; then
mess=$mess2
else
mess="$mess and $mess2"
fi
fi
if [ $te -eq 0 ]; then
set +e
mess=$($PHYEXTOOLSDIR/compare.py --testprogs $file1 $file2)

RIETTE Sébastien
committed
te=$?
set -e
fi
[ $te -ne 0 ] && message="$message $mess \n"
alltests=$(($alltests+$te))
fi
done
if [ $alltests -eq 0 ]; then
echo "SUCCESS, files are identical"
else
echo "*************** Files are different *******************"
echo -e "$message"

RIETTE Sébastien
committed
##################
#### CLEANING ####
##################
if [ $remove -eq 1 ]; then
echo "### Remove model directory for commit $commit"
[ -d $TESTDIR/$name ] && rm -rf $TESTDIR/$name
fi
exit $cmpstatus