1#!/bin/bash 2 3# Script to create output for multiple electrodes 4# and/or multiple chemical potentials 5 6_this=$(basename $0) 7 8function error { 9 echo "ERROR: something went wrong... Please see the following output:" 10 while [ $# -gt 0 ]; do 11 echo "$1" 12 shift 13 done 14 exit 1 15} 16 17 18# We must require to be able to use the hash-able arrays 19# This allows us to reuse the same input twice more easily 20help=0 21def=2 22tbt=0 23# Options about what to print 24print_mu=0 25print_el=0 26print_c=0 27declare -a opts 28_N=0 29volt=0 30while [ $# -gt 0 ]; do 31 opt=$1 32 case $opt in 33 --*) 34 opt=${1:1} ;; 35 esac 36 case $opt in 37 -def|-orig|-original) 38 # Will produce output for standard TS 39 def=2 ; shift 40 ;; 41 -V|-bias) 42 volt=$1 ; shift ; shift 43 ;; 44 -1|-2|-3|-4|-5|-6|-7|-8|-9) 45 # Will produce output for standard TS 46 def=${opt:1} ; shift 47 ;; 48 -only-el|-only-elec|-only-electrode) 49 print_el=1 ; shift 50 ;; 51 -only-mu|-only-chem|-only-chemical) 52 print_mu=1 ; shift 53 ;; 54 -only-c|-only-contour) 55 print_c=1 ; shift 56 ;; 57 -T|-tbtrans) 58 # Prefix with TBT instead of TS 59 tbt=1 ; shift 60 ;; 61 -help|-h) 62 # We need to print help 63 help=1 ; shift 64 ;; 65 -*) 66 error "Unknown option: $opt" 67 ;; 68 *) 69 break 70 esac 71done 72 73# Correct what to print (if the user) 74# has not specified anything 75if [ $print_el -eq 0 ] && [ $print_mu -eq 0 ] && [ $print_c -eq 0 ]; then 76 print_el=1 77 print_mu=1 78 print_c=1 79fi 80 81if [ $help -eq 1 ]; then 82 fmt=" %20s : %s\n" 83 echo "Usage:" 84 echo " $_this <options>" 85 echo "" 86 echo "For intrinsic transiesta runs call this:" 87 echo " $_this -2 -V <bias>" 88 echo "" 89 echo "If one wishes to divide it in several files do:" 90 echo " $_this -only-el > ELECS.fdf" 91 echo " $_this -only-mu > CHEMPOTS.fdf" 92 echo " $_this -only-c > CONTOURS.fdf" 93 echo "" 94 echo "Only print out tbtrans related options:" 95 echo " $_this -T|--tbtrans" 96 echo "" 97 echo "For specifying the contour energy levels you can use these options:" 98 printf "$fmt" "-Emin <val>" "band bottom energy in eV (-40. eV)" 99 printf "$fmt" "-dE <val>" "real-axis distance between integration points (0.01 eV)" 100 echo "" 101 echo "There are preset creations of 2,3 and 4 electrodes, call:" 102 echo " $_this -[2-9]" 103 echo "to create the equivalent systems, note that these options can be accompanied by further setup." 104 echo "" 105 echo "Available options for the chemical potentials:" 106 echo " -mu<idx>-X where X is one of the following:" 107 printf "$fmt" "mu <val>" "the chemical potential value in eV, or in fractions of V (V/2, |V|/3, etc.)" 108 printf "$fmt" "name <name>" "the name of the chemical potential (to be referenced by the electrodes)" 109 echo "" 110 echo "A shorthand notation for supplying the options is:" 111 echo " -mu<idx> Y=<val>,Z=<val> where Y,Z is one of X above" 112 echo "" 113 echo "" 114 echo "Available options for the electrodes:" 115 echo " -el<idx>-X where X is one of the following:" 116 printf "$fmt" "mu <name>" "the chemical potential name as given by -mu-name" 117 printf "$fmt" "name <name>" "the name of the electrode" 118 printf "$fmt" "tshs <file>" "the electrode TSHS-file" 119 printf "$fmt" "semi-inf <val>" "the semi-infinite direction [-+][a-c|a[1-3]]" 120 printf "$fmt" "pos <val>" "the first atom of the electrode in the structure" 121 printf "$fmt" "end-pos <val>" "the last atom of the electrode in the structure" 122 printf "$fmt" "used-atoms|ua <val>" "number of atoms used in the electrode (all)" 123 printf "$fmt" "bloch-a[1-3] <val>" "the Bloch expansion in the equivalent direction (1)" 124 printf "$fmt" "bulk <T|F>" "whether the electrode is a bulk electrode (true)" 125 printf "$fmt" "gf <file>" "name of the Greens function file (TSGF[el<idx>-name])" 126 echo "" 127 echo "A shorthand notation for supplying the options is:" 128 echo " -el<idx> Y=<val>,Z=<val> where Y,Z is one of X above" 129 echo "" 130 echo "You can combine -2 with additional electrode options to easily generate different schemes" 131 echo "To generate 3 electrodes and 2 chemical potentials you can do this:" 132 echo " $_this -2 -el3 name=Top,mu=Left,inf-dir=+a2,end-pos=-1" 133 exit 1 134fi 135 136prefix=TS 137# If we are doing tbtrans output 138# we should not print the contour information 139if [ $tbt -eq 1 ]; then 140 prefix=TBT 141 print_c=0 142fi 143 144# Add an option to the option array, enables easy creations 145function add_opt { 146 local rem=0 147 [ "x$1" == "x-r" ] && rem=1 && shift 148 local opt=$1 ; shift 149 local val=$1 ; shift 150 if [ $rem -eq 1 ]; then 151 rem_opt $opt 152 fi 153 # array indices are zero-based 154 local tmp=$(get_opt $opt 1) 155 [ ${#tmp} -gt 0 ] && return 0 156 opts+=($opt) 157 opts+=($val) 158 let _N++ 159 let _N++ 160} 161 162# Removes an option from the option array, enables customization of the options in-code 163function rem_opt { 164 local opt= 165 local i= 166 while [ $# -gt 0 ]; do 167 opt=$1 ; shift 168 i=0 169 while [ $i -le $_N ]; do 170 local val=${opts[$i]} 171 if [ "x$val" == "x$opt" ]; then 172 #echo "Removing ($val|$opt: ${opts[$i]}" 173 unset opts[$i] 174 let i++ 175 #echo "Removing: ${opts[$i]}" 176 unset opts[$i] 177 break 178 fi 179 let i++ 180 done 181 done 182 opts=( "${opts[@]}" ) 183 _N=${#opts[@]} 184} 185 186 187# Lower-case function 188function lc { printf "%b" "$@" | tr '[A-Z]' '[a-z]' ; } 189 190 191function get_opt { 192 # Returns the option from the array input 193 # get_opt <opt-name (with ONE dash)> [number of arguments gobbled] 194 # If [...] is 0: 195 # 0) will return 0 or 1 whether or not the option exists 196 # 1-9) will return the consecutive [...] number of elements 197 local opt="$1" ; shift 198 local count=0 199 if [ $# -gt 0 ]; then 200 count=$1 ; shift 201 fi 202 local i=0 ; local j=0 203 local ret="" 204 while [ $i -le $_N ]; do 205 local oo=$(lc ${opts[$i]}) 206 #echo "searching for: $opt in $oo" 1>&2 207 if [ "x$opt" == "x$oo" ]; then 208 if [ $count -gt 0 ]; then 209 ret="" 210 for j in `seq 1 $count` ; do 211 let i++ 212 ret="$ret ${opts[$i]}" 213 done 214 else 215 ret=1 216 fi 217 break 218 fi 219 let i++ 220 done 221 [ ${#ret} -eq 0 ] && [ $count -eq 0 ] && ret=0 222 # trim white-space 223 ret=${ret%% } 224 ret=${ret## } 225 printf "%b" "$ret" 226} 227 228# Expands the "short-hand" keywords to their full equivalents 229function expand_key { 230 local nm="$1" ; shift 231 local i=1 232 local reg_opt= 233 local opt= 234 local val= 235 while : ; do 236 reg_opt=$(get_opt -$nm$i 1) 237 # If the option does not exist, we simply return 238 [ ${#reg_opt} -eq 0 ] && [ $i -gt 6 ] && break 239 # Delete, so that we only keep the wanted options (not necessary, but) 240 rem_opt -$nm$i 241 reg_opt="${reg_opt//,/ }" 242 reg_opt="${reg_opt//;/ }" 243 # Loop over comma/semi-colon separated entries 244 for reg in $reg_opt ; do 245 # Add to the option list 246 # Retrive the option and value 247 opt=${reg%=*} 248 val=${reg#*=} 249 add_opt -r "-$nm$i-$opt" "$val" 250 done 251 let i++ 252 done 253} 254 255function reduce { 256 local -a tmp 257 local i=0 258 local j=0 259 while [ $j -le $_N ]; do 260 if [ ${#opts[$j]} -gt 0 ]; then 261 tmp[$i]=${opts[$j]} 262 let i++ 263 fi 264 let j++ 265 done 266 opts=( "${tmp[@]}" ) 267 _N=$i 268} 269 270for i in `seq 1 $def` ; do 271 # The user has requested a default setting for some electrodes 272 # We add them to the option stack 273 add_opt "-mu$i-name" "mu-$i" 274 add_opt "-mu$i-mu" "<mu-mu$i>" 275 add_opt "-el$i-name" "el-$i" 276 add_opt "-el$i-mu" "mu-$i" 277 add_opt "-el$i-pos" "<input-value>" 278 add_opt "-el$i-semi-inf" "+a3" 279done 280 281# In case of only two electrodes we have 282# the particular case of the traditional transiesta code 283case $def in 284 1) 285 add_opt -r "-mu1-name" "single" 286 add_opt -r "-mu1-mu" "0." 287 add_opt -r "-el1-name" "single" 288 add_opt -r "-el1-mu" "single" 289 rem_opt -el1-pos -el1-end-pos -el1-semi-inf 290 add_opt "-el1-pos" "1" 291 add_opt "-el1-semi-inf" "-a3" 292 ;; 293 2) 294 add_opt -r "-mu1-name" "Left" 295 add_opt -r "-mu1-mu" "V/2" 296 add_opt -r "-el1-name" "Left" 297 add_opt -r "-el1-mu" "Left" 298 rem_opt -el1-pos -el1-end-pos -el1-semi-inf 299 add_opt "-el1-pos" "1" 300 add_opt "-el1-semi-inf" "-a3" 301 add_opt -r "-mu2-name" "Right" 302 add_opt -r "-mu2-mu" "-V/2" 303 add_opt -r "-el2-name" "Right" 304 add_opt -r "-el2-mu" "Right" 305 rem_opt -el2-pos -el2-end-pos -el2-semi-inf 306 add_opt "-el2-end-pos" "-1" 307 add_opt "-el2-semi-inf" "+a3" 308 ;; 309esac 310 311 312# Add the user options 313while [ $# -gt 0 ]; do 314 opt=$1 ; shift 315 case $opt in 316 --*) 317 opt=${1:1} 318 rem_opt $opt ;; 319 -el*|-mu*) 320 rem_opt $opt ;; 321 esac 322 let _N++ 323 opts[$_N]="$opt" 324done 325 326# Expand again after the user things 327expand_key mu 328expand_key el 329reduce 330 331 332function count { 333 local nm=$1 ; shift 334 local n=0 335 local i= 336 local oldn=-1 337 local opt= 338 local j= 339 while [ $oldn -ne $n ]; do 340 oldn=$n 341 i=$n 342 let i++ 343 j=0 344 while [ $j -lt $_N ]; do 345 opt=${opts[$j]} 346 case $opt in 347 -${nm}${i}*) 348 n=$i ;; 349 esac 350 let j++ 351 done 352 done 353 printf "%b" "$n" 354} 355 356# Save the options 357old_opts=( "${opts[@]}" ) 358i=0 359while [ $i -lt $_N ]; do 360 case ${opts[$i]} in 361 -el*) 362 unset opts[$i] 363 let i++ 364 unset opts[$i] 365 ;; 366 esac 367 let i++ 368done 369# Remove empty array elements 370reduce 371 372# Energy for the contour 373emin=$(get_opt -emin 1) 374[ ${#emin} -eq 0 ] && emin=-40. 375emin="$emin eV" 376de=$(get_opt -de 1) 377[ ${#de} -eq 0 ] && de=0.01 378 379 380 381# The chemical potentials should be denoted like this option: 382# -mu1 <options for the chemical potential in comma separated list> 383# Another way of supplying information regarding the chemical potentials 384# -mu1-name <name> 385# -mu1-mu <the value of the chemical potential> 386_mus=$(count mu) 387# First we need to figure out the number of chemical potentials: 388# I don't suspect ANY user will go above 10 chemical potentials 389[ $_mus -eq 0 ] && \ 390 error "You have zero chemical potentials." "Please supply at least one..." 391 392# Create the chemical potential array 393_mu_names=() 394j=0 395for i in `seq 1 $_mus` ; do 396 _mu_names+=( "$(get_opt -mu$i-name 1)" ) 397 let j++ 398done 399 400function mu_e_correct { 401 local mu=$1 ; shift 402 if [ "x${mu:0:1}" == "x-" ]; then 403 # we have a negative sign 404 if [ "x${mu:1:2}" != "x|V" ] && [ "x${mu:1:1}" != "xV" ]; then 405 mu="$mu eV" 406 fi 407 else 408 if [ "x${mu:0:2}" != "x|V" ] && [ "x${mu:0:1}" != "xV" ]; then 409 mu="$mu eV" 410 fi 411 fi 412 printf "%b" "$mu" 413} 414 415if [ $print_mu -eq 1 ]; then 416 417# Print out chemical potential block: 418echo "$prefix.Voltage $volt eV" 419echo "%block $prefix.ChemPots" 420for mu in ${_mu_names[@]} ; do 421 echo " $mu" 422done 423echo "%endblock $prefix.ChemPots" 424echo "" 425 426 427function create_mu { 428 local mu=$1 ; shift 429 local name=$(get_opt -mu$mu-name 1) 430 if [ ${#name} -eq 0 ]; then 431 error "Chemical potential: $mu" "Has not received a name (-mu$mu-name)" 432 fi 433 local chem=$(get_opt -mu$mu-mu 1) 434 if [ ${#chem} -eq 0 ]; then 435 error "Chemical potential: $mu" "Has not received a chemical potential value (-mu$mu-mu)" 436 fi 437 chem=$(mu_e_correct $chem) 438 echo "%block $prefix.ChemPot.$name" 439 echo " mu $chem" 440 if [ $tbt -eq 0 ]; then 441 echo " contour.eq" 442 echo " begin" 443 echo " C-$name" 444 echo " T-$name" 445 echo " end" 446 fi 447 echo "%endblock $prefix.ChemPot.$name" 448} 449for i in `seq 1 $_mus` ; do 450 create_mu $i 451done 452fi 453 454# Create all the contours 455 456if [ $print_c -eq 1 ]; then 457 458echo "" 459echo "TS.Contours.Eq.Pole 2.5 eV" 460 461for i in `seq 1 $_mus` ; do 462 mu=$(get_opt -mu$i-name 1) 463 # Create the contours 464 echo "%block TS.Contour.C-$mu" 465 echo " part circle" 466 e=$(get_opt -mu$i-mu 1) 467 e=$(mu_e_correct $e) 468 [ ${e:0:1} != "-" ] && e="+ $e" 469 echo " from $emin $e to -10 kT $e" 470 echo " points 25" 471 echo " method g-legendre" 472 echo " opt right" 473 echo "%endblock TS.Contour.C-$mu" 474 475 # Create the contours 476 echo "%block TS.Contour.T-$mu" 477 echo " part tail" 478 echo " from prev to inf" 479 echo " points 10" 480 echo " method g-fermi" 481 echo "%endblock TS.Contour.T-$mu" 482 483done 484 485echo "" 486echo "MSG: You may need to correct the TS.Contours.nEq for signs of bias" >&2 487echo "MSG: The energies must be in increasing order (you may use |V|/2 to designate absolute values)" >&2 488 489if [ $_mus -gt 1 ]; then 490 # Create the non-equilbrium contour 491 echo "%block TS.Contours.nEq" 492 for i in `seq 1 $_mus` ; do 493 [ $i -eq $_mus ] && continue 494 echo " neq-$i" 495 done 496 echo "%endblock TS.Contours.nEq" 497fi 498 499# Create array of chemical potentials sorted 500mus=() 501j=1 502for i in `seq $_mus -1 1` ; do 503 tmp="$(get_opt -mu$i-mu 1)" 504 tmp=${tmp//\|V\|/V} 505 tmp=${tmp//V/\|V\|} 506 mus[$j]=$(mu_e_correct $tmp) 507 let j++ 508done 509 510 511# Create the contours 512if [ $_mus -gt 2 ]; then 513 echo "MSG: You can do with a single contour line in the bias window" >&2 514 echo "MSG: Use the lowest bias to the highest bias." >&2 515 echo "MSG: Here we supply as many different parts as there are chemical potentials" >&2 516fi 517 518if [ $_mus -gt 1 ]; then 519 520 i=1 521 echo "%block TS.Contour.nEq.neq-$i" 522 echo " part line" 523 j=$((i+1)) 524 if [ $j -eq $_mus ]; then 525 echo " from ${mus[$i]} - 5 kT to ${mus[$j]} + 5 kT" 526 else 527 echo " from ${mus[$i]} - 5 kT to ${mus[$j]}" 528 fi 529 echo " delta $de eV" 530 echo " method mid-rule" 531 echo "%endblock TS.Contour.nEq.neq-$i" 532 533 # Sort all chemical potentials 534 for i in `seq 3 $((_mus))` ; do 535 # Create the contours 536 echo "%block TS.Contour.nEq.neq-$((i-1))" 537 echo " part line" 538 if [ $i -eq $_mus ]; then 539 echo " from prev to ${mus[$i]} + 5 kT" 540 else 541 echo " from prev to ${mus[$i]}" 542 fi 543 echo " delta $de eV" 544 echo " method mid-rule" 545 echo "%endblock TS.Contour.nEq.neq-$((i-1))" 546 done 547fi 548 549fi 550 551 552 553# Recreate the old 554opts=( "${old_opts[@]}" ) 555_N=${#opts[@]} 556# remove all mu 557i=0 558while [ $i -lt $_N ]; do 559 case ${opts[$i]} in 560 -mu*) 561 unset opts[$i] 562 let i++ 563 unset opts[$i] ;; 564 esac 565 let i++ 566done 567# Remove empty things 568reduce 569 570 571# Now we will concentrate on the electrodes 572# First we need to figure out the number of electrode 573# I don't suspect ANY user will go above 10 electrodes 574_els=$(count el) 575[ $_els -eq 0 ] && \ 576 error "You have zero electrodes." "Please supply at least one..." 577[ $_els -lt $_mus ] && \ 578 error "You have fewer electrodes than chemical potentials." "Please correct your input..." 579 580 581if [ $print_el -eq 1 ]; then 582 583# Print out electrodes block: 584echo "" 585echo "%block $prefix.Elecs" 586for i in `seq 1 $_els` ; do 587 echo " $(get_opt -el$i-name 1)" 588done 589echo "%endblock $prefix.Elecs" 590echo "" 591 592# Get whether or not we should print everything 593_all=$(get_opt -print-all) 594[ $_all -eq 0 ] && _all=$(get_opt -el-all) 595 596 597function create_el { 598 local el=$1 ; shift 599 local name=$(get_opt -el$el-name 1) 600 [ ${#name} -eq 0 ] && error "Electrode: $el" "Has not received a name (-el$el-name)" 601 local chem=$(get_opt -el$el-mu 1) 602 [ ${#chem} -eq 0 ] && error "Electrode: $el" "Has not received a chemical potential reference (-el$el-mu)" 603 # Currently we don't check for the existance of 604 # the chemical potential. 605 local found=0 606 local i=$_mus 607 let i-- 608 for j in `seq 0 $i` ; do 609 if [ "x${_mu_names[$j]}" == "x$chem" ]; then 610 found=1 611 fi 612 done 613 [ $found -ne 1 ] && error "Electrode: $el could not be associated with a matching chemical potential: $chem" 614 echo "%block $prefix.Elec.$name" 615 local tshs=$(get_opt -el$el-tshs 1) 616 617 if [ ${#tshs} -ne 0 ]; then 618 echo " HS $tshs" 619 else 620 echo " HS <input file>" 621 fi 622 echo " chemical-potential $chem" 623 echo " semi-inf-direction $(get_opt -el$el-semi-inf 1)" 624 local pos=$(get_opt -el$el-pos 1) 625 if [ ${#pos} -eq 0 ]; then 626 pos=$(get_opt -el$el-end-pos 1) 627 [ ${#pos} -ne 0 ] && pos="end $pos" 628 fi 629 [ ${#pos} -eq 0 ] && pos="<set value>" 630 echo " electrode-position $pos" 631 # Now we can set all the other things (non-important) 632 function print_if { 633 local opt= 634 for opt in ${1//:/ } ; do 635 local val=$(get_opt -el$el-$opt 1) 636 if [ ${#val} -gt 0 ]; then 637 echo " $2 $val" 638 break 639 fi 640 done 641 } 642 print_if used-atoms:ua "used-atoms" 643 print_if bloch-a:bloch-a1 "bloch-a1" 644 print_if bloch-b:bloch-a2 "bloch-a2" 645 print_if bloch-c:bloch-a3 "bloch-a3" 646 print_if bulk "bulk" 647 print_if gf "GF" 648 echo "%endblock $prefix.Elec.$name" 649} 650for i in `seq 1 $_els` ; do 651 create_el $i 652done 653 654fi 655 656 657# Recreate the options 658opts=( "${old_opts[@]}" ) 659_N=${#opts[@]} 660 661