Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: zpasesopts problem



Hello,

Stephane Chazelas writes:

> 2021-06-02 13:44:44 -0230, Roger Mason:
>
> You're not showing the full script, so we don't know what $argv
> contains at the time zparseopts is being invoked.
>
> I'd recommend you add a
>
> typeset -p argv
>
> before the zparseopts call.
>
> My guess would be that you're expecting $argv to be:
>
> typeset -a argv=( --symbol Si --rmt 1.55 --nocc 7 --vstates 1112 )
>
> but it's not, possibly because you've called "shift" too many
> times or with the wrong number as argument.

Here is the full script.  It is rather long.

#!/usr/local/bin/zsh

action=$1
ELKVER=elk-7.1.14

case $action in
    printall)
	printbools="true"
	printfloats="true"
	printints="true"
	printtexts="true"	
	;;
    printbools)
	printbools="true"
	;;
    printfloats)
	printfloats="true"
	;;
    printints)
	printints="true"
	;;
    printtexts)
	printtexts="true"
	;;
    names)
	nams="true"
	;;
    values)
	vals="true"
	;;
    naval)
	nvl="true"
	;;
    run)
	run="true"
	;;
    *)
	run="true"
	;;
esac

if [[ $nams == true ]];then
names=($(awk '/!     default values     !/{flag=1;next}/!     read from elk.in     !/{flag=0}flag' \
$HOME/Software/Elk/$ELKVER-omp-fft/src/readinput.f90 \
| awk '!/!/' \
| awk '!/^if/'| awk '!/^allocate/' | awk '!/:/' \ | awk '{gsub(/ /,""); print}' \
| sed 's/[(]/_/g;s/:/_/g;s/)//g;s/,_/all_/g;s/,\([0-9]\)/_\1/g' | sort \
| awk '{gsub(/=/," "); print}' | sed 's/\.\([0-9][0-9]*\)d/\.\1e/g;s/\.d/\.e/g;s|45\.e0\*pi/180\.e0|0\.e0|g' \
| awk '{print $1}'))
# b=('--'${^tmp})
# c=$(printf '%s ' $b)
echo "Variable names:"
echo "$names"
fi

if [[ $vals == true ]];then
# These are all the default values corresponding to the options.
values=($(awk '/!     default values     !/{flag=1;next}/!     read from elk.in     !/{flag=0}flag' \
~/Software/Elk/$ELKVER-omp-fft/src/readinput.f90 \
| awk '!/!/' | awk '!/^if/'| awk '!/^allocate/' | awk '!/:/' \
| awk '{gsub(/ /,""); print}' | sed 's/[(]/_/g;s/:/_/g;s/)//g;s/,_/all_/g;s/,\([0-9]\)/_\1/g' | sort \
| awk '{gsub(/=/," "); print}' | sed 's/\.\([0-9][0-9]*\)d/\.\1e/g;s/\.d/\.e/g;s|45\.e0\*pi/180\.e0|0\.e0|g' \
| awk '{print $2}'))
# b=('--'${^tmp})
# c=$(printf '%s ' $b)
echo "Variable values:"
echo "$values"
fi

# This lists names & values together.
if [[ $nvl == true ]];then
# These are all the default values corresponding to the options.
naval=($(awk '/!     default values     !/{flag=1;next}/!     read from elk.in     !/{flag=0}flag' \
~/Software/Elk/$ELKVER-omp-fft/src/readinput.f90 \
| awk '!/!/' | awk '!/^if/'| awk '!/^allocate/' | awk '!/:/' \
| awk '{gsub(/ /,""); print}' | sed 's/[(]/_/g;s/:/_/g;s/)//g;s/,_/all_/g;s/,\([0-9]\)/_\1/g' | sort \
| awk '{gsub(/=/," "); print}' | sed 's/\.\([0-9][0-9]*\)d/\.\1e/g;s/\.d/\.e/g;s|45\.e0\*pi/180\.e0|0\.e0|g' \
| awk '{printf "%s\\t\\t%s\\n",$1, $2}'))
# b=('--'${^tmp})
# c=$(printf '%s ' $b)
echo "Variable names & values:"
 echo "$naval"
fi

# Booleans only.
elkbools=($(awk '/!     default values     !/{flag=1;next}/!     read from elk.in     !/{flag=0}flag' \
~/Software/Elk/$ELKVER-omp-fft/src/readinput.f90 \
| awk '!/!/' | awk '!/^if/'| awk '!/^allocate/' | awk '!/:/' \
| awk '{gsub(/ /,""); print}' | sed 's/[(]/_/g;s/:/_/g;s/)//g;s/,_/all_/g;s/,\([0-9]\)/_\1/g' | sort \
| awk '{gsub(/=/," "); print}' | awk '{if ($2==".false." || $2==".true.") {print "-"$1":" }}'))
# These need special handling b/c they are groups of settings.  There is probably a way to get them from readinput.f90.
# In addition they should be near the beginning of the elk.in so subsequent settings can override them.
elkbools=(-lowq: "${elkbools[@]}")
elkbools=(-highq: "${elkbools[@]}")
elkbools=(-vhighq: "${elkbools[@]}")
elkbools=(-uhighq: "${elkbools[@]}")
if [[ $printbools == true ]];then
    echo "$elkbools"
fi

# Floats only.
elkfloats=($(awk '/!     default values     !/{flag=1;next}/!     read from elk.in     !/{flag=0}flag' \
~/Software/Elk/$ELKVER-omp-fft/src/readinput.f90 \
| awk '!/!/' | awk '!/^if/'| awk '!/^allocate/' | awk '!/:/' \
| awk '{gsub(/ /,""); print}' | sed 's/[(]/_/g;s/:/_/g;s/)//g;s/,_/all_/g;s/,\([0-9]\)/_\1/g' | sort \
| awk '{gsub(/=/," "); print}' | awk '$2 ~ /[0-9]+(\.)[0-9]*/ {print "-"$1":"}'))
if [[ $printfloats == true ]];then
    echo "$elkfloats"
fi

# Integers only.
elkints=($(awk '/!     default values     !/{flag=1;next}/!     read from elk.in     !/{flag=0}flag' \
~/Software/Elk/$ELKVER-omp-fft/src/readinput.f90 \
| awk '!/!/' | awk '!/^if/'| awk '!/^allocate/' | awk '!/:/' | awk '!/xct/' \
| awk '{gsub(/ /,""); print}' | sed 's/[(]/_/g;s/:/_/g;s/)//g;s/,_/all_/g;s/,\([0-9]\)/_\1/g' | sort \
| awk '{gsub(/=/," "); print}' | awk '$2 ~ /[0-9][0-9]*/' | awk '$2 !~ /\./ {print "-"$1":"}'))
if [[ $printints == true ]];then
    echo "$elkints"
fi

# Text only.  Read as a string between \A\z.
# tasks is a list of integers that is not handled by elkints.  They should be on separate lines.
# The newlines can be entered explicitly like this: '0\n 21'.
# ngridk is  handled similarly, but using spaces vs \n.
elktexts=(-tasks: "${elktexts[@]}")
#elktexts=(-ngridk: "${elktexts[@]}")
elktexts+=($(awk '/!     default values     !/{flag=1;next}/!     read from elk.in     !/{flag=0}flag' \
~/Software/Elk/$ELKVER-omp-fft/src/readinput.f90 \
| awk '!/!/' | awk '!/^if/'| awk '!/^allocate/' | awk '!/:/' \
| awk '{gsub(/ /,""); print}' | sed 's/[(]/_/g;s/:/_/g;s/)//g;s/,_/all_/g;s/,\([0-9]\)/_\1/g' | sort \
| awk '{gsub(/=/," "); print}' | awk '$2 ~ /^\A[0-9][0-9]*\z/ {print "-"$1":"}'))
#elktexts=("${elktexts[@]}" -ngridk:)
if [[ $printtexts == true ]];then
    echo "$elktexts"
fi

# ngridk.  Needs special handling b/c it is an array.  For some reason
# I could not get text like '1 1 1' to load into postgresql correctly.
zparseopts -D -E -A intarrays  - -ngridk: -xctype:
zparseopts -D -E -A elkbools   - $elkbools
zparseopts -D -E -A elkfloats  - $elkfloats
zparseopts -D -E -A elkints    - $elkints
zparseopts -D -E -A elktexts   - $elktexts

# This accumulates most of the options that are used in elk.in
OPTSELK=""

kx=1;ky=1;kz=1			# Defaults
for key value in "${(@kv)intarrays}"; do
    k=$(echo $key | tr -d '-')
    ${k}=${intarrays[$key]} 2>/dev/null # Discard error message: command not found:
    if [[ $k == ngridk ]];then # extract kx,ky & kz for later use in postgres.
	kx=$(echo "${value}" | awk '{print $1}')
	ky=$(echo "${value}" | awk '{print $2}')
	kz=$(echo "${value}" | awk '{print $3}')
    fi
    OPTSELK+="$k\n $value\n\n"
done
# echo "k = $k kx = $kx ky = $ky kz = $kz"
# exit 10


# If given on the command line, the command line versions will be used, otherwise the program defaults are used.
# Loop over the option names and set values to override the defaults.
for key value in "${(@kv)elkbools}"; do
    k=$(echo $key | tr -d '-')
    ${k}=${elkbools[$key]} 2>/dev/null # Discard error message: command not found:
    OPTSELK+="$k\n $value\n\n"
done
#echo $OPTSELK

for key value in "${(@kv)elkfloats}"; do
    k=$(echo $key | tr -d '-')
    ${k}=${elkfloats[$key]} 2>/dev/null # Discard error message: command not found:
    if [[ $k == sc ]];then		# sc is used internally in the elk code vs elk.in.
	k=$(echo $k | sed 's/sc/scale/g') # Should work on sc1, sc2 & sc3.
    fi
    if [[ $k == nempty0 ]];then		# nempty0 is used internally in the elk code vs elk.in.
	k=$(echo $k | sed 's/nempty0/nempty/g') # Remove 0
    fi
      OPTSELK+="$k\n $value\n\n"
done
# echo "$OPTSELK"
# exit 10

for key value in "${(@kv)elkints}"; do
    k=$(echo $key | tr -d '-')
    ${k}=${elkints[$key]} 2>/dev/null # Discard error message: command not found:
    OPTSELK+="$k\n $value\n\n"
done

for key value in "${(@kv)elktexts}"; do
    k=$(echo $key | tr -d '-')
    ${k}=${elktexts[$key]} 2>/dev/null # Discard error message: command not found:
    OPTSELK+="$k\n $value\n\n"
done
#echo $OPTSELK

# Other options This ensures that spsource is set in the species array
# even when not specified on the command line.
# zparseopts -D -E -A species - -spsource: -Z: -symbol: -name: -mass: -rmt: -nocc: -vstates:
# zparseopts -D -E -A species -spsource: 

# spsource=${species[--spsource]:-/home/rmason/Software/Elk/$ELKVER/species/}
# species[--spsource]=${spsource}
# Z=${species[--Z]:-14}
# species[--Z]=${Z}
# symbol=${species[--symbol]:-Si}
# species[--symbol]=${symbol}
# name=${species[--name]:-silicon}
# species[--name]=${name}
# mass=${species[--mass]:-28.0855}
# species[--mass]=${mass}
# rmt=${species[--rmt]:-1.55}
# species[--rmt]=${rmt}
# nocc=${species[--nocc]:-1}
# species[--nocc]=${nocc}
# vstates=${species[--vstates]:-"1 0 1 1"}
# species[--vstates]=${vstates}

# Supercell options
zparseopts -D -E -A scopts -sx: -sy: -sz: -dry:
sx=${scopts[--sx]:-1}
sy=${scopts[--sy]:-1}
sz=${scopts[--sz]:-1}
dry=${scopts[--dry]:-no}	# does not need to be retained for DB.
scopts[--sx]=${sx}
scopts[--sy]=${sy}
scopts[--sz]=${sz}
# echo "sx = $sx sy = $sy sz = $sz"
# exit 1

# Sbatch options
zparseopts -D -E -A sbopts -nodes: -mpitasks: -cppt: -memper: -time: -nodelist:
time=${sbopts[--time]:-00:30:00}
nnodes=${sbopts[--nodes]:-1}	# number of nodes
mpitasks=${sbopts[--mpitasks]:-1}	# number of MPI tasks
cpuper=${sbopts[--cppt]:-1}	# cpus-per-task
memper=${sbopts[--mem]:-250}	# memory per CPU
nodelist=${sbopts[--nodelist]:-} # no default so it does not need the re-insertion used for the others below.
sbopts[--nodes]=$nnodes
sbopts[--mpitasks]=$mpitasks
sbopts[--cpuper]=$cpuper
sbopts[--memper]=$memper
sbopts[--time]=$time

# Composition arguments
# NB: compositions with Al won't be charge balanced.
zparseopts -D -E -A comopts -xti: -xal:
# Composition arguments
xti=${comopts[--xti]-0}
xal=${comopts[--xal]-0}
comopts[--xti]=$xti
comopts[--xal]=$xal

# Job control options.  If submit = no, the job is created along with
# the input tarball but nothing is sent to $target or submitted to
# slurm.  Not stored in DB b/c if the job wasn't run there won't be a
# DB entry for the results.
zparseopts -D -E -A jbcopts - -submit:
submit=${jbcopts[--submit]:-yes}
# echo "Job submit = $submit"
# exit 3

if [[ ${dry} == yes ]];then
    submit=no
    scd="-d"
fi
# echo "submit = $submit dry = $scd"
# exit 10

# PostgreSQL options
zparseopts -D -E -A pgopts - -db:
db=${pgopts[--db]:-elk}
pgopts[--db]=$db

# Tar options
zparseopts -D -E -A taropts -tar:
tar=${taropts[--tar]:-zf}

# No tasks?
if [[ ! ${elktexts[--tasks]+x} ]];then
    echo "The '--tasks' setting is mandatory."
    exit 1
fi

# Species options
typeset -p argv

zparseopts -D -E -A species - -spsource: 
spsource=${species[--spsource]:-/home/rmason/Software/Elk/$ELKVER/species/}

# If spsource = SpeciesGenerated, parse these options too.
if [[ $spsource == SpeciesGenerated ]];then
zparseopts -D -E - -symbol+:=chemsyms -rmt+:=rmts -nocc+:=noccs -vstate+:=vstates
echo "Parsing species options."

function addspecies()
{
ADDSPECIES+="species\n"
ADDSPECIES+=" $Z\n"
ADDSPECIES+=" '$symbol' '$name'\n"
ADDSPECIES+=" $mass\n"
ADDSPECIES+=" $rmt\n"
ADDSPECIES+=" $nocc\n"
ADDSPECIES+=" $states\n"
}

# This could be relaxed so that only the desired quantities need be
# specified.  In that case the defaults need to be given in the case
# statements, somehow.  Ugly.
if [[ ${#chemsyms} -ne ${#rmts} ]] || [[ ${#chemsyms} -ne ${#noccs} ]] || [[ ${#chemsyms} -ne ${#vstates} ]];then
    echo "The numbers of chemical chemsyms, RMTs, occupation numbers and valence states do not match."
    echo "#chemsyms = ${#chemsyms}, #rmts = ${#rmts}, #noccs = ${#noccs}, #vstates = ${#vstates}"
    echo "Check your command line.  Exiting."
    exit -1
fi

# Additional species information to override the defaults.
ADDSPECIES=""
typeset -A helper
helper=($(seq 1 ${#chemsyms}))
echo "helper = $helper"
for item in ${(@v)helper}
do
    echo "${chemsyms[$item]} ${rmts[$item]} ${noccs[$item]} ${vstates[$item]}"
    case ${chemsyms[$item]} in
	Si)
	    name=silicon
	    mass=28.0855
	    Z=14
	    symbol=${chemsyms[$item]}
	    rmt=${rmts[$item]}
	    nocc=${noccs[$item]}
	    states=${vstates[$item]}
	    addspecies
	    ;;
	O)
	    name=oxygen
	    mass=15.9994
	    Z=8
	    symbol=${chemsyms[$item]}
	    rmt=${rmts[$item]}
	    nocc=${noccs[$item]}
	    states=${vstates[$item]}
	    addspecies
	    ;;
	Ti)
	    name=titanium
	    mass=47.867
	    Z=22
	    symbol=${chemsyms[$item]}
	    rmt=${rmts[$item]}
	    nocc=${noccs[$item]}
	    states=${vstates[$item]}
	    addspecies
	    ;;
	Al)
	    name=aluminium
	    mass=26.981538
	    Z=13
    	    symbol=${chemsyms[$item]}
	    rmt=${rmts[$item]}
	    nocc=${noccs[$item]}
	    states=${vstates[$item]}
	    addspecies
	    ;;
	*)
	    echo "${chemsyms[$item]} is not currently in the list of elements."
	    echo "Add it to the script or check your command line.  Exiting."
	    exit -2
	    ;;
    esac
			      
done
fi

And the output from typset -p argv is:

typeset -a argv=( filmperthite --spsource SpeciesGenerated Si --rmt 1.55 \
--nocc 7 --vstates 1112 )

So, the argument to --symbol is not being recognised.

Thanks,
Roger




Messages sorted by: Reverse Date, Date, Thread, Author