Gaussian 16 software
Gaussian 16 (G16) is the world’s most widely used quantum chemistry software. It calculates the electronic structure of molecules using methods ranging from Hartree-Fock to coupled cluster, DFT, and multireference methods. On duhpc (High Performance Computing Cluster commissioned in HPCC Lab, Department of Chemistry, University of Delhi), Gaussian 16 is installed on the compute nodes and is accessed through the SLURM batch system.
Template for Gaussian Job Script:
#!/bin/bash
#==============================================================
# Gaussian16 Job Script — duhpc Cluster
# Version: 3.0 | May 2026
# Department of Chemistry, University of Delhi
#
# FEATURES:
# ✓ Auto-restart from checkpoint after power failure
# ✓ Walltime warning — saves checkpoint 5 min before kill
# ✓ Auto-injects %Chk if user forgets
# ✓ NProcShared mismatch detection and fix
# ✓ Smart failure diagnosis with recovery hints
# ✓ Scratch preserved on failure for debugging
#
# USAGE:
# 1. Copy this file to your job directory
# 2. Edit JobFile= line with your input filename
# 3. Adjust --cpus-per-task and --mem to match your .com file
# 4. sbatch gaussian_job.sh
#
# PARTITION GUIDE:
# compute → Gaussian, single-node, up to 5 days, max 16 CPUs ← USE THIS
# mpi → GROMACS, NAMD, Amber MPI — multi-node jobs ONLY
# short → Test jobs, max 4 hours, max 8 CPUs
# gpu → Amber CUDA, GROMACS GPU — GPU jobs only
#==============================================================
#SBATCH --job-name=Gaussian
#SBATCH --partition=compute # Always use compute for Gaussian
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=8 # Recommended: 4-16 (see guide below)
#SBATCH --mem=32G # Match %Mem in .com file + 4G buffer
#SBATCH --time=5-00:00:00 # Max 5 days on compute partition
#SBATCH --output=%x_%j.out # Stdout (%x=jobname, %j=jobid)
#SBATCH --error=%x_%j.err # Stderr
#SBATCH --mail-type=BEGIN,END,FAIL # Email notifications
#SBATCH --mail-user=your@email.com # ← Change to your email address
#SBATCH --signal=B:USR1@300 # Save checkpoint 5 min before walltime
# ══════════════════════════════════════════════════════════
# USER SETTINGS — Edit only this section
# ══════════════════════════════════════════════════════════
JobFile=molecule # Input filename WITHOUT .com extension
# ══════════════════════════════════════════════════════════
# CPU SELECTION GUIDE:
# Geometry optimisation: 4-8 CPUs --mem=20-32G
# Single point (DFT): 8-12 CPUs --mem=32-48G
# Frequency calculation: 8-12 CPUs --mem=32-48G
# TD-DFT / NMR: 4-8 CPUs --mem=32-48G
# MP2 / CCSD(T): 8-16 CPUs --mem=48-60G
# Large molecule >100 at: 12-16 CPUs --mem=48-60G
#
# IMPORTANT: %NProcShared in .com file MUST match --cpus-per-task
# IMPORTANT: %Mem in .com file must be ~4G LESS than --mem here
#==============================================================
# SETUP — do not edit below unless you know what you are doing
#==============================================================
SUBMIT_DIR=$SLURM_SUBMIT_DIR
CHK_PATH="$SUBMIT_DIR/${JobFile}.chk"
LOG_PATH="$SUBMIT_DIR/${JobFile}.log"
export GAUSS_SCRDIR=/scratch/gaussian/$USER/$SLURM_JOBID
#──────────────────────────────────────────────────────────
# WALLTIME TRAP — fires 5 minutes before SLURM kills job
# Saves checkpoint so job can be restarted
#──────────────────────────────────────────────────────────
walltime_handler() {
echo ""
echo "╔══════════════════════════════════════════════════════╗"
echo "║ ⚠ WALLTIME LIMIT APPROACHING — 5 minutes left! ║"
echo "╚══════════════════════════════════════════════════════╝"
# Save checkpoint from scratch to job directory
SAVED=0
for chk in "$GAUSS_SCRDIR"/*.chk; do
[ -f "$chk" ] && cp "$chk" "$SUBMIT_DIR/" && \
echo "✓ Checkpoint saved: $SUBMIT_DIR/$(basename $chk)" && \
SAVED=1
done
[ -f "$CHK_PATH" ] && \
echo "✓ Checkpoint in submit dir: $CHK_PATH" && SAVED=1
[ $SAVED -eq 0 ] && \
echo "✗ No checkpoint found — add %Chk=${JobFile}.chk to .com file"
echo ""
echo "TO RESTART THIS JOB:"
echo " 1. Increase --time in this script (e.g. 5-00:00:00)"
echo " 2. Resubmit: sbatch gaussian_job.sh"
echo " (script auto-detects checkpoint and restarts)"
echo ""
echo "OR ask admin for walltime extension:"
echo " Contact: ighani@ducc.du.ac.in with Job ID $SLURM_JOB_ID"
}
trap 'walltime_handler' USR1
#──────────────────────────────────────────────────────────
# PRINT JOB HEADER
#──────────────────────────────────────────────────────────
echo "╔══════════════════════════════════════════════╗"
echo "║ Gaussian16 Job — duhpc Cluster ║"
echo "╚══════════════════════════════════════════════╝"
echo "Job ID : $SLURM_JOB_ID"
echo "Job Name : $SLURM_JOB_NAME"
echo "User : $USER"
echo "Node : $SLURMD_NODENAME"
echo "CPUs : $SLURM_CPUS_PER_TASK"
echo "Memory : $SLURM_MEM_PER_NODE MB"
echo "Submit Dir : $SUBMIT_DIR"
echo "Input file : ${JobFile}.com"
echo "Log file : ${JobFile}.log"
echo "Checkpoint : $CHK_PATH"
echo "Scratch : $GAUSS_SCRDIR"
echo "Started : $(date)"
echo "══════════════════════════════════════════════"
#──────────────────────────────────────────────────────────
# LOAD GAUSSIAN
#──────────────────────────────────────────────────────────
export g16root=/scratch/apps/gaussian
export PATH=$g16root/g16:$PATH
export LD_LIBRARY_PATH=$g16root/g16:$LD_LIBRARY_PATH
source $g16root/g16/bsd/g16.profile
ulimit -s unlimited
#──────────────────────────────────────────────────────────
# SETUP SCRATCH DIRECTORY
#──────────────────────────────────────────────────────────
mkdir -p $GAUSS_SCRDIR
#──────────────────────────────────────────────────────────
# VALIDATE INPUT FILE
#──────────────────────────────────────────────────────────
cd $SUBMIT_DIR
if [ ! -f "${JobFile}.com" ]; then
echo "ERROR: Input file '${JobFile}.com' not found in:"
echo " $SUBMIT_DIR"
echo ""
echo "Available .com files:"
ls *.com 2>/dev/null || echo " (none found)"
exit 1
fi
# Fix Windows line endings silently
sed -i 's/\r//g' ${JobFile}.com
# Show key settings from input file
echo ""
echo "--- Input file settings ---"
grep -i "^%NProcShared\|^%Mem\|^%Chk\|^%nproc\|^%mem\|^%chk" ${JobFile}.com
#──────────────────────────────────────────────────────────
# CHECK AND FIX NPROC MISMATCH
#──────────────────────────────────────────────────────────
NPROC=$(grep -i "^%NProcShared\|^%nproc" ${JobFile}.com | \
grep -o '[0-9]*' | head -1)
if [ -n "$NPROC" ] && [ "$NPROC" != "$SLURM_CPUS_PER_TASK" ]; then
echo ""
echo "⚠ WARNING: %NProcShared=$NPROC in .com file"
echo " but --cpus-per-task=$SLURM_CPUS_PER_TASK in job script"
echo " Fixing .com file to match SLURM allocation..."
sed -i "s/NProcShared=$NPROC/NProcShared=$SLURM_CPUS_PER_TASK/Ig" \
${JobFile}.com
sed -i "s/%nproc=$NPROC/%nproc=$SLURM_CPUS_PER_TASK/Ig" \
${JobFile}.com
echo " ✓ %NProcShared updated to $SLURM_CPUS_PER_TASK"
fi
#──────────────────────────────────────────────────────────
# AUTO-INJECT %Chk IF MISSING
#──────────────────────────────────────────────────────────
if ! grep -qi "^%chk" ${JobFile}.com; then
echo ""
echo "⚠ No %Chk found — auto-adding checkpoint line"
TMPFILE=$(mktemp)
echo "%Chk=${CHK_PATH}" > $TMPFILE
cat ${JobFile}.com >> $TMPFILE
cp $TMPFILE ${JobFile}.com
rm -f $TMPFILE
echo " ✓ Added: %Chk=${CHK_PATH}"
fi
#──────────────────────────────────────────────────────────
# AUTO-DETECT RESTART FROM CHECKPOINT
#──────────────────────────────────────────────────────────
RESTART_MODE=0
ACTUAL_INPUT="${JobFile}.com"
if [ -f "$CHK_PATH" ]; then
CHK_SIZE=$(ls -lh "$CHK_PATH" | awk '{print $5}')
CHK_DATE=$(ls -l "$CHK_PATH" | awk '{print $6,$7,$8}')
echo ""
echo "╔══════════════════════════════════════════════╗"
echo "║ ✓ RESTART MODE: Checkpoint found! ║"
echo "╚══════════════════════════════════════════════╝"
echo "Checkpoint : $CHK_PATH"
echo "Size : $CHK_SIZE | Modified: $CHK_DATE"
# Build restart input file
ROUTE=$(grep -i "^#" "${JobFile}.com" | head -1)
MEM_LINE=$(grep -i "^%mem" "${JobFile}.com" | head -1)
NPROC_LINE=$(grep -i "^%nproc\|^%cpu" "${JobFile}.com" | head -1)
CHK_LINE=$(grep -i "^%chk" "${JobFile}.com" | head -1)
# Add Restart keyword to route
if echo "$ROUTE" | grep -qi "Opt=("; then
NEW_ROUTE=$(echo "$ROUTE" | sed 's/Opt=(\([^)]*\))/Opt=(Restart,\1/I')
elif echo "$ROUTE" | grep -qi "\bOpt\b"; then
NEW_ROUTE=$(echo "$ROUTE" | sed 's/\bOpt\b/Opt=Restart/I')
elif echo "$ROUTE" | grep -qi "IRC"; then
NEW_ROUTE=$(echo "$ROUTE" | sed 's/IRC/IRC=Restart/I')
else
NEW_ROUTE="$ROUTE Restart"
fi
RESTART_INPUT="${JobFile}_restart_${SLURM_JOB_ID}.com"
# Extract charge and multiplicity from original input
# Format: "0 1" on the line after the first blank line after route
CHARGE_MULT=$(awk '
/^#/{found_route=1; next}
found_route && /^$/{blank++; next}
found_route && blank==1 && /^$/{blank++; next}
found_route && blank>=1 && NF>0 && !/^$/{
if (blank>=2) {print; exit}
}
' "${JobFile}.com" | head -1)
# If not found try simpler approach
[ -z "$CHARGE_MULT" ] && \
CHARGE_MULT=$(grep -A99 "^$" "${JobFile}.com" | \
grep -E "^[0-9-]+ [0-9]+$" | head -1)
# Default to "0 1" if still not found
[ -z "$CHARGE_MULT" ] && CHARGE_MULT="0 1"
{
# Link0 section
echo "$CHK_LINE"
[ -n "$MEM_LINE" ] && echo "$MEM_LINE"
[ -n "$NPROC_LINE" ] && echo "$NPROC_LINE"
# Route card
echo "$NEW_ROUTE"
# Blank line
echo ""
# Title line
echo "Restart from checkpoint — Job $SLURM_JOB_ID — $(date)"
# Blank line
echo ""
# Charge and multiplicity
echo "$CHARGE_MULT"
# Two final blank lines — Gaussian requires this
echo ""
echo ""
} > "$RESTART_INPUT"
# Verify restart file looks correct
echo "--- Restart input file ---"
cat "$RESTART_INPUT"
echo "--- End restart input ---"
echo ""
ACTUAL_INPUT="$RESTART_INPUT"
RESTART_MODE=1
echo "Restart input : $RESTART_INPUT"
echo "Route : $NEW_ROUTE"
else
echo ""
echo "--- Fresh start — no checkpoint found ---"
fi
echo ""
#──────────────────────────────────────────────────────────
# RUN GAUSSIAN
#──────────────────────────────────────────────────────────
echo "--- Starting Gaussian16 ---"
echo "Mode : $([ $RESTART_MODE -eq 1 ] && \
echo 'RESTART from checkpoint' || echo 'FRESH START')"
echo ""
START=$(date +%s)
# Run Gaussian directly (not background) for reliable output capture
# The USR1 trap will still fire correctly
g16 < "$ACTUAL_INPUT" > "$LOG_PATH" 2>&1
EXIT=$?
END=$(date +%s)
ELAPSED=$((END-START))
HOURS=$((ELAPSED/3600))
MINS=$(( (ELAPSED%3600)/60 ))
SECS=$((ELAPSED%60))
#──────────────────────────────────────────────────────────
# SAVE CHECKPOINT BEFORE CLEANUP
#──────────────────────────────────────────────────────────
echo ""
echo "--- Saving checkpoint ---"
CHK_SAVED=0
for chk in "$GAUSS_SCRDIR"/*.chk; do
[ -f "$chk" ] && \
cp "$chk" "$SUBMIT_DIR/" && \
echo "✓ Saved: $SUBMIT_DIR/$(basename $chk)" && \
CHK_SAVED=1
done
[ -f "$CHK_PATH" ] && \
echo "✓ Checkpoint: $CHK_PATH ($(ls -lh $CHK_PATH | awk '{print $5}'))" && \
CHK_SAVED=1
[ $CHK_SAVED -eq 0 ] && \
echo "✗ No checkpoint found"
#──────────────────────────────────────────────────────────
# JOB RESULT SUMMARY
#──────────────────────────────────────────────────────────
echo ""
echo "╔══════════════════════════════════════════════╗"
echo "║ JOB SUMMARY ║"
echo "╚══════════════════════════════════════════════╝"
echo "Job ID : $SLURM_JOB_ID"
echo "Node : $SLURMD_NODENAME"
echo "Wall time : ${HOURS}h ${MINS}m ${SECS}s"
echo "Exit code : $EXIT"
# Check if log file is empty — Gaussian never started
if [ ! -s "$LOG_PATH" ]; then
echo "Status : ✗ FAILED — Gaussian did not start"
echo ""
echo "Log file is empty — possible causes:"
echo " 1. Input file format error"
echo " 2. Gaussian binary not found"
echo " 3. Memory or scratch issue"
echo ""
echo "Check input file:"
echo " cat $ACTUAL_INPUT"
echo "Scratch preserved: $GAUSS_SCRDIR"
echo ""
echo "Finished : $(date)"
echo "══════════════════════════════════════════════"
exit 1
fi
if [ $EXIT -eq 0 ] && \
[ -s "$LOG_PATH" ] && \
grep -q "Normal termination" "$LOG_PATH" 2>/dev/null; then
echo "Status : ✓ COMPLETED SUCCESSFULLY"
echo ""
echo "--- Key results ---"
grep -E "SCF Done|CCSD\(T\)|MP2|Zero-point|Thermal correction|\
Dipole moment|Frequencies|Stationary point|Optimized Parameters|\
Normal termination|Job cpu time" \
"$LOG_PATH" 2>/dev/null | \
grep -v "^$" | tail -10
# Clean scratch on success
rm -rf $GAUSS_SCRDIR
echo ""
echo "Scratch : Cleaned"
elif grep -q "Erroneous write\|galloc\|Out of memory\|sbrk" \
"$LOG_PATH" 2>/dev/null; then
echo "Status : ✗ FAILED — Memory error"
echo ""
MEM_GB=$((SLURM_MEM_PER_NODE/1024))
NEW_MEM=$((MEM_GB+16))
echo "SOLUTION: Increase memory in job script:"
echo " Change: #SBATCH --mem=${MEM_GB}G"
echo " To: #SBATCH --mem=${NEW_MEM}G"
echo " And in .com file: %Mem=$((NEW_MEM-4))GB"
echo ""
echo "Scratch preserved: $GAUSS_SCRDIR"
elif grep -q "Convergence failure\|SCF has not converged" \
"$LOG_PATH" 2>/dev/null; then
echo "Status : ✗ FAILED — SCF convergence failure"
echo ""
echo "SOLUTION: Add to route card:"
echo " SCF=(MaxCycles=512,XQC)"
echo ""
echo "Scratch preserved: $GAUSS_SCRDIR"
elif grep -q "Optimization stopped\|Berny optimization" \
"$LOG_PATH" 2>/dev/null && \
! grep -q "Stationary point found" "$LOG_PATH" 2>/dev/null; then
echo "Status : ✗ INCOMPLETE — Geometry optimisation not converged"
echo ""
if [ $CHK_SAVED -eq 1 ]; then
echo "SOLUTION: Checkpoint saved — resubmit to continue:"
echo " sbatch gaussian_job.sh"
echo " (script auto-detects checkpoint and restarts)"
fi
echo ""
echo "Scratch preserved: $GAUSS_SCRDIR"
else
echo "Status : ✗ FAILED"
echo ""
echo "Last 15 lines of log:"
tail -15 "$LOG_PATH" 2>/dev/null
echo ""
[ $CHK_SAVED -eq 1 ] && \
echo "Checkpoint saved — resubmit with: sbatch gaussian_job.sh"
echo "Scratch preserved: $GAUSS_SCRDIR"
fi
echo ""
echo "Finished : $(date)"
echo "══════════════════════════════════════════════"
echo ""
echo "--- Gaussian log: $LOG_PATH ---"
echo "--- For help: ighani@ducc.du.ac.in ---"Useful SLURM Commands for Gaussian Jobs
| Task | Command |
|---|---|
| Submit job | sbatch gaussian_job.sh |
| Check job status | squeue -u $USER |
| Cancel job | scancel JOBID |
| Live output | tail -f molecule.log |
