866 lines
23 KiB
Bash
Executable File
866 lines
23 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
|
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
|
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
|
#
|
|
# This file is part of the MFEM library. For more information and source code
|
|
# availability visit https://mfem.org.
|
|
#
|
|
# MFEM is free software; you can redistribute it and/or modify it under the
|
|
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
|
# CONTRIBUTING.md for details.
|
|
|
|
make="${MAKE:-make}"
|
|
mpiexec="${MPIEXEC:-mpirun}"
|
|
mpiexec_np="${MPIEXEC_NP:--np}"
|
|
run_prefix=""
|
|
run_vg="valgrind --leak-check=full --show-reachable=yes --track-origins=yes"
|
|
run_suffix="-no-vis"
|
|
skip_gen_meshes="yes"
|
|
# filter-out device runs ("no") or non-device runs ("yes"):
|
|
device_runs="no"
|
|
cur_dir="${PWD}"
|
|
mfem_dir="$(cd "$(dirname "$0")"/.. && pwd)"
|
|
mfem_build_dir=""
|
|
build_log=""
|
|
output_dir=""
|
|
output_sfx=".out"
|
|
# The group format is: '"group-name" "group-summary-title" "group-directory"
|
|
# "group-source-patterns"'
|
|
groups_serial=(
|
|
'"examples"
|
|
"Examples:"
|
|
"examples"
|
|
"ex{,[1-9]}[0-9].cpp"'
|
|
# "ex1.cpp"'
|
|
'"sundials"
|
|
"SUNDIALS examples:"
|
|
"examples/sundials"
|
|
"ex{9,10,16}.cpp"'
|
|
'"performance"
|
|
"Performance miniapps:"
|
|
"miniapps/performance"
|
|
"ex1.cpp"'
|
|
'"amgx"
|
|
"AmgX examples:"
|
|
"examples/amgx"
|
|
"ex1.cpp"'
|
|
'"caliper"
|
|
"Caliper examples:"
|
|
"examples/caliper"
|
|
"ex1.cpp"'
|
|
'"ginkgo"
|
|
"Ginkgo examples:"
|
|
"examples/ginkgo"
|
|
"ex1.cpp"'
|
|
'"hiop"
|
|
"HiOp examples:"
|
|
"examples/hiop"
|
|
"ex9.cpp"'
|
|
'"moonolith"
|
|
"Moonolith examples:"
|
|
"examples/moonolith"
|
|
"ex1.cpp"'
|
|
'"pumi"
|
|
"PUMI examples:"
|
|
"examples/pumi"
|
|
"ex1.cpp ex2.cpp"'
|
|
# ""'
|
|
'"meshing"
|
|
"Meshing miniapps:"
|
|
"miniapps/meshing"
|
|
"mobius-strip.cpp klein-bottle.cpp extruder.cpp toroid.cpp mesh-quality.cpp
|
|
polar-nc.cpp reflector.cpp shaper.cpp trimmer.cpp twist.cpp
|
|
mesh-optimizer.cpp minimal-surface.cpp"'
|
|
'"adjoint"
|
|
"Adjoint miniapps:"
|
|
"miniapps/adjoint"
|
|
"cvsRoberts_ASAi_dns.cpp"'
|
|
'"autodiff"
|
|
"Autodiff miniapps:"
|
|
"miniapps/autodiff"
|
|
"seq_example.cpp seq_test.cpp"' # 'seq_test.cpp' has no sample runs
|
|
'"dpg"
|
|
"DPG miniapps:"
|
|
"miniapps/dpg"
|
|
"{acoustics,convection-diffusion,diffusion,maxwell}.cpp"'
|
|
'"isf"
|
|
"Schrodinger flow miniapps:"
|
|
"miniapps/fluids/schrodinger-flow"
|
|
"schrodinger_flow.cpp"'
|
|
'"gslib"
|
|
"GSLIB miniapps:"
|
|
"miniapps/gslib"
|
|
"field-diff.cpp field-interp.cpp findpts.cpp schwarz_ex1.cpp "'
|
|
# todo: miniapps/mtop
|
|
'"nurbs"
|
|
"NURBS miniapps:"
|
|
"miniapps/nurbs"
|
|
"nurbs_ex1.cpp"'
|
|
# todo: add other nurbs miniapps
|
|
# todo: miniapps/solvers (serial)
|
|
'"tools"
|
|
"Tools miniapps:"
|
|
"miniapps/tools"
|
|
"convert-dc.cpp display-basis.cpp get-values.cpp load-dc.cpp
|
|
lor-transfer.cpp"'
|
|
# todo: add other tools miniapps
|
|
'"toys"
|
|
"Toys miniapps:"
|
|
"miniapps/toys"
|
|
"automata.cpp life.cpp lissajous.cpp mandel.cpp mondrian.cpp rubik.cpp
|
|
snake.cpp"'
|
|
'"convergence"
|
|
"Convergence tests:"
|
|
"tests/convergence"
|
|
"rates.cpp"'
|
|
)
|
|
# Parallel groups
|
|
groups_parallel=(
|
|
'"examples"
|
|
"Examples:"
|
|
"examples"
|
|
"ex{,[1-9]}[0-9]p.cpp"'
|
|
# "ex1p.cpp"'
|
|
'"sundials"
|
|
"SUNDIALS examples:"
|
|
"examples/sundials"
|
|
"ex{9,10,16}p.cpp"'
|
|
'"petsc"
|
|
"PETSc examples:"
|
|
"examples/petsc"
|
|
"ex{,1}[0-9]p.cpp"'
|
|
'"performance"
|
|
"Performance miniapps:"
|
|
"miniapps/performance"
|
|
"ex1p.cpp"'
|
|
'"amgx"
|
|
"AmgX examples:"
|
|
"examples/amgx"
|
|
"ex1p.cpp"'
|
|
'"caliper"
|
|
"Caliper examples:"
|
|
"examples/caliper"
|
|
"ex1p.cpp"'
|
|
'"hiop"
|
|
"HiOp examples:"
|
|
"examples/hiop"
|
|
"ex9p.cpp"'
|
|
'"moonolith"
|
|
"Moonolith examples:"
|
|
"examples/moonolith"
|
|
"ex{1,2}p.cpp"'
|
|
'"pumi"
|
|
"PUMI examples:"
|
|
"examples/pumi"
|
|
"ex1p.cpp ex6p.cpp"'
|
|
'"superlu"
|
|
"Superlu examples:"
|
|
"examples/superlu"
|
|
"ex1p.cpp"'
|
|
# ""'
|
|
'"meshing"
|
|
"Meshing miniapps:"
|
|
"miniapps/meshing"
|
|
"pmesh-optimizer.cpp pmesh-fitting.cpp pminimal-surface.cpp
|
|
fit-node-position.cpp"'
|
|
'"electromagnetics"
|
|
"Electromagnetics miniapps:"
|
|
"miniapps/electromagnetics"
|
|
"joule.cpp"'
|
|
# "{joule,maxwell,tesla,volta}.cpp"' # todo: multiline sample runs
|
|
'"isf"
|
|
"Schrodinger flow miniapps:"
|
|
"miniapps/fluids/schrodinger-flow"
|
|
"pschrodinger_flow.cpp"'
|
|
'"adjoint"
|
|
"Adjoint miniapps:"
|
|
"miniapps/adjoint"
|
|
"adjoint_advection_diffusion.cpp"'
|
|
'"autodiff"
|
|
"Autodiff miniapps:"
|
|
"miniapps/autodiff"
|
|
"par_example.cpp"'
|
|
'"dpg"
|
|
"DPG miniapps:"
|
|
"miniapps/dpg"
|
|
"p{acoustics,convection-diffusion,diffusion,maxwell}.cpp"'
|
|
'"gslib"
|
|
"GSLIB miniapps:"
|
|
"miniapps/gslib"
|
|
"pfindpts.cpp schwarz_ex1p.cpp"'
|
|
'"hdiv-linear-solver"
|
|
"H(div) linear solver miniapps:"
|
|
"miniapps/hdiv-linear-solver"
|
|
"grad_div.cpp darcy.cpp"'
|
|
# 'miniapps/hooke/hooke.cpp' has no sample runs
|
|
# todo: miniapps/mtop
|
|
# todo: miniapps/multidomain
|
|
'"navier"
|
|
"Navier miniapps:"
|
|
"miniapps/fluids/navier"
|
|
"navier_cht.cpp"'
|
|
# todo: add other navier miniapps
|
|
'"nurbs"
|
|
"NURBS miniapps:"
|
|
"miniapps/nurbs"
|
|
"nurbs_ex1p.cpp nurbs_ex11p.cpp"'
|
|
'"shifted"
|
|
"Shifted miniapps:"
|
|
"miniapps/shifted"
|
|
"distance.cpp"'
|
|
# todo: add other shifted miniapps
|
|
'"solvers"
|
|
"Solvers miniapps:"
|
|
"miniapps/solvers"
|
|
"block-solvers.cpp"'
|
|
# todo: add other solvers miniapps
|
|
# todo: miniapps/spde
|
|
'"tools"
|
|
"Tools miniapps:"
|
|
"miniapps/tools"
|
|
"convert-dc.cpp get-values.cpp load-dc.cpp"'
|
|
# todo: add other tools miniapps
|
|
'"convergence"
|
|
"Convergence tests:"
|
|
"tests/convergence"
|
|
"prates.cpp"'
|
|
'"par-mesh-format"
|
|
"Parallel mesh tests:"
|
|
"tests/par-mesh-format"
|
|
"ex1p.cpp"'
|
|
)
|
|
# All groups serial + parallel runs mixed in the same group:
|
|
groups_all=(
|
|
'"examples"
|
|
"Examples:"
|
|
"examples"
|
|
"ex\"{,[1-9]}[0-9]\"{,p}.cpp"'
|
|
'"sundials"
|
|
"SUNDIALS examples:"
|
|
"examples/sundials"
|
|
"ex\"{9,10,16}\"{,p}.cpp"'
|
|
'"petsc"
|
|
"PETSc examples:"
|
|
"examples/petsc"
|
|
"ex{,1}[0-9]p.cpp"'
|
|
'"performance"
|
|
"Performance miniapps:"
|
|
"miniapps/performance"
|
|
"ex1{,p}.cpp"'
|
|
'"amgx"
|
|
"AmgX examples:"
|
|
"examples/amgx"
|
|
"ex1.cpp ex1p.cpp"'
|
|
'"caliper"
|
|
"Caliper examples:"
|
|
"examples/caliper"
|
|
"ex1.cpp ex1p.cpp"'
|
|
'"ginkgo"
|
|
"Ginkgo examples:"
|
|
"examples/ginkgo"
|
|
"ex1.cpp"'
|
|
'"hiop"
|
|
"HiOp examples:"
|
|
"examples/hiop"
|
|
"ex9.cpp ex9p.cpp"'
|
|
'"moonolith"
|
|
"Moonolith examples:"
|
|
"examples/moonolith"
|
|
"ex1.cpp ex{1,2}p.cpp"'
|
|
'"pumi"
|
|
"PUMI examples:"
|
|
"examples/pumi"
|
|
"ex1.cpp ex2.cpp ex1p.cpp ex6p.cpp"'
|
|
'"superlu"
|
|
"Superlu examples:"
|
|
"examples/superlu"
|
|
"ex1p.cpp"'
|
|
'"meshing"
|
|
"Meshing miniapps:"
|
|
"miniapps/meshing"
|
|
"mobius-strip.cpp klein-bottle.cpp extruder.cpp toroid.cpp mesh-quality.cpp
|
|
polar-nc.cpp reflector.cpp shaper.cpp trimmer.cpp twist.cpp
|
|
{,p}mesh-optimizer.cpp pmesh-fitting.cpp {,p}minimal-surface.cpp
|
|
fit-node-position.cpp"'
|
|
'"electromagnetics"
|
|
"Electromagnetics miniapps:"
|
|
"miniapps/electromagnetics"
|
|
"joule.cpp"'
|
|
# "{joule,maxwell,tesla,volta}.cpp"' # todo: multiline sample runs
|
|
'"isf"
|
|
"Schrodinger flow miniapps:"
|
|
"miniapps/fluids/schrodinger-flow"
|
|
"{,p}schrodinger_flow.cpp"'
|
|
'"adjoint"
|
|
"Adjoint miniapps:"
|
|
"miniapps/adjoint"
|
|
"cvsRoberts_ASAi_dns.cpp adjoint_advection_diffusion.cpp"'
|
|
'"autodiff"
|
|
"Autodiff miniapps:"
|
|
"miniapps/autodiff"
|
|
"seq_example.cpp seq_test.cpp par_example.cpp"'
|
|
# 'seq_test.cpp' has no sample runs
|
|
'"dpg"
|
|
"DPG miniapps:"
|
|
"miniapps/dpg"
|
|
"{,p}{acoustics,convection-diffusion,diffusion,maxwell}.cpp"'
|
|
'"gslib"
|
|
"GSLIB miniapps:"
|
|
"miniapps/gslib"
|
|
"field-diff.cpp field-interp.cpp findpts.cpp schwarz_ex1.cpp pfindpts.cpp
|
|
schwarz_ex1p.cpp"'
|
|
'"hdiv-linear-solver"
|
|
"H(div) linear solver miniapps:"
|
|
"miniapps/hdiv-linear-solver"
|
|
"grad_div.cpp darcy.cpp"'
|
|
# 'miniapps/hooke/hooke.cpp' has no sample runs
|
|
# todo: miniapps/mtop
|
|
# todo: miniapps/multidomain
|
|
'"navier"
|
|
"Navier miniapps:"
|
|
"miniapps/fluids/navier"
|
|
"navier_cht.cpp"'
|
|
# todo: add other navier miniapps
|
|
'"nurbs"
|
|
"NURBS miniapps:"
|
|
"miniapps/nurbs"
|
|
"nurbs_ex1.cpp nurbs_ex1p.cpp nurbs_ex11p.cpp"'
|
|
# todo: add other nurbs miniapps
|
|
'"shifted"
|
|
"Shifted miniapps:"
|
|
"miniapps/shifted"
|
|
"distance.cpp"'
|
|
# todo: add other shifted miniapps
|
|
'"solvers"
|
|
"Solvers miniapps:"
|
|
"miniapps/solvers"
|
|
"block-solvers.cpp"'
|
|
# todo: add other solvers miniapps
|
|
# todo: miniapps/spde
|
|
'"tools"
|
|
"Tools miniapps:"
|
|
"miniapps/tools"
|
|
"convert-dc.cpp display-basis.cpp get-values.cpp load-dc.cpp
|
|
lor-transfer.cpp"'
|
|
# todo: add other tools miniapps
|
|
'"toys"
|
|
"Toys miniapps:"
|
|
"miniapps/toys"
|
|
"automata.cpp life.cpp lissajous.cpp mandel.cpp mondrian.cpp rubik.cpp
|
|
snake.cpp"'
|
|
'"convergence"
|
|
"Convergence tests:"
|
|
"tests/convergence"
|
|
"{,p}rates.cpp"'
|
|
'"par-mesh-format"
|
|
"Parallel mesh tests:"
|
|
"tests/par-mesh-format"
|
|
"ex1p.cpp"'
|
|
)
|
|
make_all="all"
|
|
base_timeformat=$'real: %3Rs user: %3Us sys: %3Ss %%cpu: %P'
|
|
# separator
|
|
sep='----------------------------------------------------------------'
|
|
|
|
# Command line parameters:
|
|
opt_help="no"
|
|
opt_show="no"
|
|
mfem_config="MFEM_USE_MPI=NO MFEM_DEBUG=NO"
|
|
groups=()
|
|
group_name=""
|
|
group_title=""
|
|
valgrind="no"
|
|
make_j="-j $(getconf _NPROCESSORS_ONLN)"
|
|
color="no"
|
|
built="no"
|
|
timing="no"
|
|
|
|
# Read the sample runs from the source "$1" and put them in the array variable
|
|
# "runs".
|
|
function extract_sample_runs()
|
|
{
|
|
local old_IFS="${IFS}" sruns="" pruns=""
|
|
local src="$1"
|
|
if [ "${src}" == "" ]; then runs=(); return 1; fi
|
|
local app=${src%.cpp}
|
|
local vg_app="${app}"
|
|
if [ "${valgrind}" == "yes" ]; then vg_app="${run_vg} ${app}"; fi
|
|
# parallel sample runs are lines matching "^//.* mpirun .* ${app}" with
|
|
# everything in front of "mpirun" removed:
|
|
pruns=`grep "^//.* mpirun .* ${app}" "${src}" |
|
|
sed -e "s/.* mpirun \(.*\) ${app}/${mpiexec} \1 ${app}/g" \
|
|
-e "s/ -np\(.*\) ${app}/ ${mpiexec_np}\1 ${vg_app}/g"`
|
|
# serial sample runs are lines that are not parallel sample runs and matching
|
|
# "^//.* ${app}" with everything in front of "${app}" removed:
|
|
sruns=`grep -v "^//.* mpirun .* ${app}" "${src}" |
|
|
grep "^//.* ${app}" |
|
|
sed -e "s/.* ${app}/${vg_app}/g"`
|
|
runs="${sruns}"$'\n'"${pruns}"
|
|
if [ "$skip_gen_meshes" == "yes" ]; then
|
|
runs=`printf "%s" "$runs" | grep -v ".* -m .*\.gen"`
|
|
fi
|
|
if [ "$device_runs" == "yes" ]; then
|
|
runs=`printf "%s" "$runs" | grep ".* -d .*"`
|
|
if [ "$have_occa" == "no" ]; then
|
|
runs=`printf "%s" "$runs" | grep -v ".* -d occa-.*"`
|
|
fi
|
|
if [ "$have_raja" == "no" ]; then
|
|
runs=`printf "%s" "$runs" | grep -v ".* -d raja-.*"`
|
|
fi
|
|
if [ "$have_ceed" == "no" ]; then
|
|
runs=`printf "%s" "$runs" | grep -v ".* -d ceed-.*"`
|
|
fi
|
|
else
|
|
runs=`printf "%s" "$runs" | grep -v ".* -d .*"`
|
|
fi
|
|
IFS=$'\n'
|
|
runs=(${runs})
|
|
IFS="${old_IFS}"
|
|
}
|
|
|
|
# Echo usage information
|
|
function help_message()
|
|
{
|
|
cat <<EOF
|
|
|
|
$0 [options]
|
|
|
|
Options:
|
|
-h|-help Print this usage information and exit
|
|
-p|-par Build the parallel MFEM library + examples + miniapps.
|
|
The default is to build the serial MFEM library + examples +
|
|
miniapps. The build can be customized by setting the variable
|
|
'mfem_config' or by building separately and using '-b'
|
|
-g <dir> <pattern>
|
|
Specify explicitly a group (dir + file pattern) to run; This
|
|
option can be used multiple times to define multiple groups
|
|
-dev configure only sample runs using devices.
|
|
To test with a parallel build, the parallel (-p|-par) option
|
|
should be set first on the command line.
|
|
-v Enable valgrind
|
|
-o <dir> [${output_dir:-"<empty>: output goes to stdout"}]
|
|
If not empty, save output to files inside <dir>
|
|
-d <dir> [${mfem_build_dir}]
|
|
If <dir> is different from <mfem_dir> then use an
|
|
out-of-source build in <dir>
|
|
-j <np> [${make_j}] Specify the number of jobs to use for building
|
|
-c|-color Always use colors for the status messages: OK, FAILED, etc
|
|
-b|-built Do NOT rebuild the library and the executables
|
|
-t|-time Measure and print execution time for each sample run
|
|
-s|-show Show all configured sample runs and exit
|
|
-n Dry run: replace "\$sample_run" with "echo \$sample_run"
|
|
<var>=<value>
|
|
Set a shell script variable; see below for valid variables
|
|
* Any other parameter is treated as <mfem_dir>
|
|
<mfem_dir> [${mfem_dir}] is the MFEM source directory
|
|
|
|
This script tests all the sample runs listed in the beginning comments of
|
|
MFEM's serial or parallel example and miniapp codes. The list of sample runs
|
|
is auto-generated and can be viewed with the -s|-show option.
|
|
|
|
The following shell script variables can be set with <var>=<value>:
|
|
output_dir [${output_dir}]
|
|
Same as '-o': if not empty, save output to files in that directory
|
|
output_sfx [${output_sfx}]
|
|
Suffix to append to the output files
|
|
mfem_config [${mfem_config}]
|
|
Set MFEM configuration options
|
|
make [${make}], mpiexec [${mpiexec}], mpiexec_np [${mpiexec_np}]
|
|
Their values can also be set using the respective uppercase environment
|
|
variable
|
|
mfem_build_dir [${mfem_build_dir}]
|
|
Same as '-d': set this variable to something different from <mfem_dir>
|
|
to use an out-of-source build
|
|
|
|
For other valid variables, see the script source.
|
|
|
|
The following environment variables, if non-empty, are used:
|
|
MAKE, MPIEXEC, MPIEXEC_NP
|
|
|
|
Example usage:
|
|
$0 -s [ Show all configured sample runs ]
|
|
$0 -o baseline [ Serial build; run and save all built sample runs ]
|
|
$0 -p -o baseline [ Parallel build; run and save all sample runs ]
|
|
$0 -b -g examples ex8.cpp [ Use the existing build; run ex8 sample runs ]
|
|
|
|
EOF
|
|
}
|
|
|
|
function show_runs()
|
|
{
|
|
echo "${sep}"
|
|
for group_params in "${groups[@]}"; do
|
|
eval params=(${group_params})
|
|
name="${params[0]}"
|
|
title="${params[1]}"
|
|
group_dir="${mfem_dir}/${params[2]}"
|
|
pattern="${params[3]}"
|
|
printf "group name: [%s]\n" "${name}"
|
|
printf "summary title: [%s]\n" "${title}"
|
|
printf "directory: [%s]\n" "${group_dir}"
|
|
printf "pattern: [%s]\n" "${pattern}"
|
|
cd "${cur_dir}"; cd "${group_dir}" || exit 1
|
|
eval sources=(${pattern})
|
|
eval sources=("${sources[@]}")
|
|
printf "sources: (%s)\n" "${sources[*]}"
|
|
printf "sample runs:\n"
|
|
for src in "${sources[@]}"; do
|
|
extract_sample_runs "${src}"
|
|
for run in "${runs[@]}"; do
|
|
printf " %s\n" "${run}"
|
|
done
|
|
done
|
|
echo "${sep}"
|
|
done
|
|
}
|
|
|
|
# Process command line parameters
|
|
while [ $# -gt 0 ]; do
|
|
|
|
case "$1" in
|
|
-h|-help)
|
|
opt_help="yes"
|
|
;;
|
|
-p|-par)
|
|
mfem_config="MFEM_USE_MPI=YES MFEM_DEBUG=NO"
|
|
;;
|
|
-g)
|
|
gbasename="$(basename "$2")"
|
|
gname="${group_name:-${gbasename}}"
|
|
gtitle="${group_title:-"Group <${gbasename}>:"}"
|
|
test_group="\"${gname}\" \"${gtitle}\" \"$2\" \"$3\""
|
|
groups=("${groups[@]}" "${test_group}")
|
|
shift 2
|
|
;;
|
|
-dev)
|
|
device_runs="yes"
|
|
mfem_config+=" MFEM_USE_CUDA=YES MFEM_USE_OPENMP=YES"
|
|
# OCCA, RAJA, libCEED are enabled below, if available
|
|
;;
|
|
-v)
|
|
valgrind="yes"
|
|
;;
|
|
-o)
|
|
shift
|
|
output_dir="$1"
|
|
;;
|
|
-d)
|
|
shift
|
|
mfem_build_dir="$1"
|
|
;;
|
|
-j)
|
|
shift
|
|
make_j="-j $1"
|
|
;;
|
|
-c|-color)
|
|
color="yes"
|
|
;;
|
|
-b|-built)
|
|
built="yes"
|
|
;;
|
|
-t|-time)
|
|
timing="yes"
|
|
;;
|
|
-s|-show)
|
|
opt_show="yes"
|
|
;;
|
|
-n)
|
|
run_prefix="echo"
|
|
;;
|
|
-*)
|
|
echo "unknown option: '$1'"
|
|
exit 1
|
|
;;
|
|
*=*)
|
|
eval $1
|
|
;;
|
|
*)
|
|
mfem_dir="$1"
|
|
;;
|
|
esac
|
|
|
|
shift
|
|
done # while ...
|
|
|
|
mfem_build_dir="${mfem_build_dir:-${mfem_dir}}"
|
|
|
|
build_log="${build_log:-${mfem_build_dir}/config/sample-runs-build.log}"
|
|
|
|
if [ 0 -eq ${#groups[*]} ]; then
|
|
groups=("${groups_all[@]}")
|
|
# These can be used as command line arguments:
|
|
# 'groups=("${groups_serial[@]}")'
|
|
# 'groups=("${groups_parallel[@]}")'
|
|
fi
|
|
|
|
if [ "${opt_help}" == "yes" ]; then
|
|
help_message
|
|
exit
|
|
fi
|
|
|
|
if [ "${opt_show}" == "yes" ]; then
|
|
show_runs
|
|
exit
|
|
fi
|
|
|
|
# Setup colors
|
|
if [ -t 1 ] && [ -z "${output_dir}" ] || [ "${color}" == "yes" ]; then
|
|
red='\033[0;31m'
|
|
green='\033[0;32m'
|
|
yellow='\033[0;33m'
|
|
magenta='\033[0;35m'
|
|
cyan='\033[0;36m'
|
|
none='\033[0m'
|
|
else
|
|
red=
|
|
green=
|
|
yellow=
|
|
magenta=
|
|
cyan=
|
|
none=
|
|
fi
|
|
|
|
# Run the given command, saving the rune time in the variable "timer".
|
|
function timed_run()
|
|
{
|
|
timer="$({ time "$@" 1>&3 2>&4; } 2>&1)"
|
|
} 3>&1 4>&2
|
|
|
|
# This function is used to execute the sample runs
|
|
function go()
|
|
{
|
|
# Strip leading and trailing spaces from $1 and store the result in cmd_line
|
|
shopt -s extglob
|
|
local cmd_line="${1##+( )}"
|
|
cmd_line="${cmd_line%%+( )}"
|
|
shopt -u extglob
|
|
local res=""
|
|
echo $sep
|
|
echo "<${group}>" "${cmd_line}"
|
|
echo $sep
|
|
if [ "${timing}" == "yes" ]; then
|
|
timed_run eval "${cmd_line}"
|
|
else
|
|
eval "${cmd_line}"
|
|
fi
|
|
if [ "$?" -eq 0 ]; then
|
|
res="${green} OK ${none}"
|
|
else
|
|
res="${red}FAILED${none}"
|
|
fi
|
|
printf "[${res}] <${group}> ${cmd_line}\n"
|
|
if [ "${timing}" == "yes" ]; then
|
|
printf "Run time: %s\n" "${timer}"
|
|
timer=(${timer})
|
|
timer="${timer[1]}"
|
|
printf -v line "[$res](%8s) ${cmd_line}" "$timer"
|
|
summary=("${summary[@]}" "$line")
|
|
else
|
|
summary=("${summary[@]}" "[${res}] ${cmd_line}")
|
|
fi
|
|
echo $sep
|
|
}
|
|
|
|
# This function is used to run a group of sample runs (in the same directory)
|
|
function go_group()
|
|
{
|
|
local res=""
|
|
if [ $# -eq 0 ]; then return 0; fi
|
|
local group_output_dir="" output_file="" output=""
|
|
if [ ! -z "$output_dir" ]; then
|
|
group_output_dir="${output_dir}/${group_dir}"
|
|
mkdir -p "${group_output_dir}" || exit 1
|
|
fi
|
|
for src in "$@"; do
|
|
ex_run_suffix=${run_suffix} && [[ $src =~ ex0p?\.cpp ]] \
|
|
&& ex_run_suffix=""
|
|
cd "${mfem_dir}/${group_dir}" || exit 1
|
|
extract_sample_runs "${src}" || continue
|
|
[ "${#runs[@]}" -eq 0 ] && continue
|
|
cd "${mfem_build_dir}/${group_dir}" || exit 1
|
|
if [ ! -x "${src%.cpp}" ]; then
|
|
res="${magenta} SKIP ${none}"
|
|
echo $sep
|
|
printf "[${res}] <${group}> <${src}>\n"
|
|
echo $sep
|
|
summary=("${summary[@]}" "[${res}] <${src}>")
|
|
continue
|
|
fi
|
|
if [ ! -z "$output_dir" ]; then
|
|
output_file="${group_output_dir}/${src}${output_sfx}"
|
|
: > "${output_file}"
|
|
output=">> \"${output_file}\" 2>&1"
|
|
fi
|
|
for run in "${runs[@]}"; do
|
|
if [ "${run}" == "" ]; then continue; fi
|
|
eval go \"\${run_prefix} \${run} \${ex_run_suffix}\" $output
|
|
done
|
|
done
|
|
${make} clean-exec
|
|
}
|
|
|
|
# Make sure $mfem_dir exists and we can cd into it
|
|
cd "$mfem_dir" || exit 1
|
|
# Make sure $mfem_dir is an absolute path
|
|
mfem_dir="$PWD"
|
|
cd "${cur_dir}"
|
|
if [ "${built}" == "no" ]; then
|
|
mkdir -p "${mfem_build_dir}" || exit 1
|
|
fi
|
|
# Make sure $mfem_build_dir exists and we can cd into it
|
|
cd "${mfem_build_dir}" || exit 1
|
|
# Make sure $mfem_build_dir is an absolute path
|
|
mfem_build_dir="$PWD"
|
|
# Setup 'output_dir'
|
|
if [ ! -z "$output_dir" ]; then
|
|
cd "${cur_dir}"
|
|
mkdir -p "${output_dir}" && cd "${output_dir}" || exit 1
|
|
output_dir="$PWD"
|
|
echo "Sending output to files in: [${output_dir}]"
|
|
echo "Using suffix: [${output_sfx}]"
|
|
fi
|
|
|
|
TIMEFORMAT="${base_timeformat}"
|
|
|
|
# Setup optional libraries when not using externally built MFEM:
|
|
if [ "${built}" == "no" ]; then
|
|
have_occa="no"
|
|
have_raja="no"
|
|
have_ceed="no"
|
|
if [ "${device_runs}" == "yes" ]; then
|
|
if [ -n "${CUDA_ARCH}" ]; then
|
|
mfem_config+=" CUDA_ARCH=${CUDA_ARCH}"
|
|
fi
|
|
if [ -d "${mfem_dir}/../occa" ]; then
|
|
mfem_config+=" MFEM_USE_OCCA=YES"
|
|
have_occa="yes"
|
|
fi
|
|
if [ -d "${mfem_dir}/../raja" ]; then
|
|
mfem_config+=" MFEM_USE_RAJA=YES"
|
|
have_raja="yes"
|
|
fi
|
|
if [ -d "${mfem_dir}/../libCEED" ]; then
|
|
mfem_config+=" MFEM_USE_CEED=YES"
|
|
have_ceed="yes"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
function set_echo_log()
|
|
{
|
|
local dirname=`dirname "$1"`
|
|
cd "${cur_dir}"
|
|
mkdir -p "${dirname}" && cd "${dirname}" || exit 1
|
|
echo_log="$PWD"/`basename "$1"`
|
|
}
|
|
|
|
# Echo the given command line; then run it sending all output to $echo_log
|
|
function echo_run()
|
|
{
|
|
echo " $@"
|
|
{ echo " $@"; echo "$sep";
|
|
eval "$@"
|
|
echo "$sep"; } >> "$echo_log" 2>&1
|
|
}
|
|
|
|
# Function that builds the mfem library, examples and miniapps
|
|
function build_all()
|
|
{
|
|
printf "Building MFEM with all examples and miniapps:\n"
|
|
set_echo_log "${build_log}"
|
|
echo " ### build log: [$echo_log]"
|
|
{ echo "$sep"; echo " MFEM build log"; echo "$sep"; } > "$echo_log"
|
|
echo_run cd "${mfem_build_dir}"
|
|
if [ "${mfem_dir}" != "${mfem_build_dir}" ]; then
|
|
echo_run ${make} -f "${mfem_dir}"/makefile config
|
|
fi
|
|
# Don't use 'make distclean' as it will delete the default $build_log
|
|
echo_run ${make} clean || exit 1
|
|
echo_run ${make} config ${mfem_config} || exit 1
|
|
echo_run ${make} ${make_j} || exit 1
|
|
echo_run ${make} ${make_all} ${make_j} || exit 1
|
|
# Build groups in directories other than the directories built by 'make all':
|
|
for group_params in "${groups[@]}"; do
|
|
eval params=(${group_params})
|
|
group_dir="${params[2]}"
|
|
case "$group_dir" in
|
|
(examples*|miniapps*)
|
|
# Built by 'make all'
|
|
;;
|
|
(*)
|
|
if [ "${mfem_dir}" != "${mfem_build_dir}" ]; then
|
|
echo_run mkdir -p "${group_dir}" || exit 1
|
|
echo_run cd "${group_dir}" || exit 1
|
|
echo_run cp -af "${mfem_dir}/${group_dir}/makefile" . || exit 1
|
|
else
|
|
echo_run cd "${group_dir}" || exit 1
|
|
fi
|
|
echo_run ${make} clean || exit 1
|
|
echo_run ${make} MFEM_DIR="${mfem_dir}" ${make_j} || exit 1
|
|
echo_run cd "${mfem_build_dir}" || exit 1
|
|
;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
# Function that runs all sample runs, given by the array variable "groups".
|
|
function all_go()
|
|
{
|
|
for group_params in "${groups[@]}"; do
|
|
eval params=(${group_params})
|
|
group="${params[0]}"
|
|
group_dir="${params[2]}"
|
|
cd "${mfem_dir}/${group_dir}" || exit 1
|
|
eval sources=(${params[3]})
|
|
eval sources=("${sources[@]}")
|
|
summary=("${summary[@]}" "${params[1]}")
|
|
go_group "${sources[@]}"
|
|
done
|
|
|
|
printf "Summary:\n--------\n"
|
|
for line in "${summary[@]}"; do
|
|
printf "${line}\n"
|
|
done
|
|
}
|
|
|
|
function main()
|
|
{
|
|
# Build all mfem examples and miniapps
|
|
if [ "${built}" == "no" ]; then
|
|
if [ "${timing}" == "yes" ]; then
|
|
timed_run build_all
|
|
printf "Build time: %s\n" "${timer}"
|
|
else
|
|
build_all
|
|
fi
|
|
fi
|
|
|
|
summary=()
|
|
PATH=.:$PATH
|
|
|
|
# Print the MFEM configuration info
|
|
cd "${mfem_build_dir}"
|
|
echo "$sep"
|
|
echo "MFEM configuration"
|
|
echo "$sep"
|
|
${make} info
|
|
echo "$sep"
|
|
|
|
# Run all sample runs.
|
|
if [ "${timing}" == "yes" ]; then
|
|
timed_run all_go
|
|
printf "Total run time: %s\n" "${timer}"
|
|
else
|
|
all_go
|
|
fi
|
|
echo
|
|
}
|
|
|
|
output=""
|
|
if [ ! -z "$output_dir" ]; then
|
|
output=">> \"${output_dir}/main${output_sfx}\" 2>&1"
|
|
fi
|
|
eval main $output
|