I'm a chemistry student working on a simple bash script to automate HPC density functional theory calculations using Quantum Espresso (pw.x). I am very much a novice at shell scripting and would appreciate some criticism/feedback before I try to implement it on the cluster. The script calls in-gen.py which is a Python script I wrote for generating new input files if certain parameter thresholds in the log file are not met.
#!/bin/bash
#SBATCH --job-name=2x2x6_PbCO3 # job name
#SBATCH --output=slurm.out # Output file name
#SBATCH --error=slurm.err # Error file name
#SBATCH --partition=batch # Partition
#SBATCH --qos=medium+ # Queue
#SBATCH --time=24:00:00 # Time limit
#SBATCH --nodes=3 # Number of nodes
#SBATCH --ntasks-per-node=16 # MPI processes per node
errors='MPI_ABORT|error|aborted|SIGTERM|TIME|CANCELLED|SIGCONT|terminated|fork'
job='2x2x6_PbCO3'
max_runs=5
prefix=PbCO3
#-------------------------------------------------------------------------------
Clear ()
{
# Checks for input/log from a completed batch script
if [[ -f "$prefix.in" && -f "$prefix.log" ]]; then
# If both are found a new input file is generated
python ~/path-to-in-gen.py $prefix.log $prefix.in $job override
if [ -z "$(ls -A ../logs_and_inputs)" ]; then
index=1
else
indices=()
# Old input/log are tagged and stored
for entry in "../logs_and_inputs"/$prefix.in-*; do
indices+=("${entry: -1}")
done
max=${indices[0]}
for n in "${indices[@]}" ; do
((n > max)) && max=$n
done
index=$((max+1))
rm -r *x*x*
mv $prefix.in ../logs_and_inputs/$prefix.in-$index
mv $prefix.log ../logs_and_inputs/$prefix.log-$index
mv $prefix.in-new $prefix.in
fi
fi
}
#-------------------------------------------------------------------------------
# Creates a directory for old logs and inputs to be stored with a numerical tag from 1 to k
Sort ()
{
if [ ! -d "../logs_and_inputs" ]; then
mkdir ../logs_and_inputs
iter=1
else
if [ -z "$(ls -A ../logs_and_inputs)" ]; then
iter=1
else
indices=()
for entry in "../logs_and_inputs"/$prefix.in-*; do
indices+=("${entry: -1}")
done
max=${indices[0]}
for n in "${indices[@]}" ; do
((n > max)) && max=$n
done
iter=$((max+1))
fi
fi
max_iter=$((iter+max_runs))
}
#-------------------------------------------------------------------------------
Automode ()
{
mpirun ~/path-to-pw.x < $prefix.in > $prefix.log
# Runs pw.x job, checks for completion and errors
if grep -E -q -- $errors "slurm.err"; then
exit 1
fi
if grep -q "job DONE." "$prefix.log"; then
# Clear wavefunction files and temp directories
rm -r *x*x*
# Generates new input file
python ~/path-to-in-gen.py $prefix.log $prefix.in $job
# Tags and stores the previous input and log
mv $prefix.in ../logs_and_inputs/$prefix.in-$iter
mv $prefix.log ../logs_and_inputs/$prefix.log-$iter
else
exit 1
fi
# Checks for generation of new input file
if test -f "$prefix.in-new"; then
mv $prefix.in-new $prefix.in
else
exit 1
fi
let "iter=iter+1"
}
#-------------------------------------------------------------------------------
Clear
Sort
while ((iter < max_iter)); do
Automode
done