Table of contents |
PWTK stands for PWscf ToolKit.
PWTK is a Tcl scripting interface for Quantum ESPRESSO (QE), aiming at providing a flexible and productive framework. With PWTK, one can automate calculations and glue together different computational tasks, where outputs of preceding calculations serve as inputs for subsequent calculations.
(PWTK, standing for PWscf ToolKit, got its name from the consideration that it initially supported only the PWscf subset of Quantum ESPRESSO programs. Moreover, the name “Quantum ESPRESSO” did not yet exist at the time the PWTK project was initiated.)
Among the PWTK features are:
Here is a comparison between the pw.x input file and the corresponding PWTK script:
pw.x input file: scf.Si.in
|
PWTK script file:
Si.pwtk
|
|
|
This calculation is run as: | This calculation is run as: |
|
|
The syntax of the PWTK scripts
is similar to QE
input files, but notice that both Fortran namelists
(e.g. &CONTROL
) and cards
(e.g. ATOMIC_SPECIES
) are enclosed with curly braces
(e.g. CONTROL { ... }
).
The last line of the above PWTK
script, runPW scf.Si.in
, requests the
pw.x calculation. Upon execution, PWTK will:
scf.Si.in
input file (the output will
be written to scf.Si.out
)At a simplistic level of the above example, there is no advantage of using PWTK, but the advantage becomes evident once multiple calculations are performed (see the example below).
The main syntactic attributes of PWTK scripts are:
PWTK scripts use the Tcl syntax because, technically, they are Tcl scripts. Hence, one can use Tcl commands in PWTK scripts. There are many online resorces for learning Tcl, e.g., see Tcl tutorial, Learn Tcl in Y minutes, and manual pages of Tcl commands.
PWTK scripts are
case-sensitive with namelist and card names written
in uppercase. For example, using
control
instead of CONTROL
produces the
error: invalid command name "control"
.
Names of namelist variables are
case-sensitive. Hence, ibrav
and
IBRAV
are treated as two different namelist
variables.
Namelists and cards are bracketed with curly braces
(SYSTEM { ... }
) or double quotes
(SYSTEM " ... "
), e.g.:
# namelist with curly braces
{
SYSTEM 1) = 10.2
celldm(is a comment inside the namelist
! this }
# namelist with double quotes
"
SYSTEM celldm(1) = $a
"
The difference between curly braces and double quotes is that
inside double quotes, the variable $a
is substituted by
its value. In contrast, inside curly braces, $a
is
treated literally without any substitution.
A namelist variable can be unset by assigning it an empty value, i.e.:
# a namelist variable is unset like this:
{
SYSTEM 3) =
celldm(}
Namelists and cards can be cleared (unset) with the input_clear command, e.g.:
input_clear SYSTEM ATOMIC_POSITIONS
Numbers can be specified as mathematical expressions: math-parsing is enabled for all cards and namelist variables of numeric type. Here is an example:
SYSTEM {
ecutrho = 12*30.0
}
Beware that such mathematical expressions should not contain
spaces (e.g., 12 * 30.0
is an invalid expression
because it is parsed as three fields 12, *, and 30.0).
Indices of ntyp-type array variables, such as
starting_magnetization
, can be specified with atomic
labels:
SYSTEM {
starting_magnetization(Fe) = 0.8
}
where Fe
is one among atomic species defined in the
ATOMIC_SPECIES
card. It is highly recommended
to use atomic labels instead of numeric indices.
PWTK allows (re)assigning namelist variables or the content of cards on the fly, which is useful when performing multiple calculations, where only a few parameters per calculation change.
As an example, let us perform a few tests on Si bulk. To this
end, we will use the above scf.Si.si input file. Below is the PWTK script that scans the energy
cutoff (ecutwfc
), k-point mesh (K_POINTS
),
and lattice parameter (celldm(1)
):
# the "load_fromPWI" command loads the pw.x input file
load_fromPWI scf.Si.in
#------------------------
# scan the energy-cuttofs
#------------------------
# the "scanpar" command loops over a parameter;
# it is similar to a one-parameter Tcl "foreach" command
{10.0 14.0 18.0 22.0} {
scanpar e # load the new energy cuttofs
"ecutwfc = $e, ecutrho = 4*$e"
SYSTEM
# perform the pw.x calculation (I/O files: scf.Si_e$e.in & scf.Si_e$e.out)
$e
runPW scf.Si_e
# store $e and total energy in the 'ecut.dat' file
[pwo_totene scf.Si_e$e.out]
write ecut.dat }
# plot the result
-xl "ecutwfc (Ry)" -yl "Total energy (Ry)" ecut.dat
plot
#-----------------
# scan the k-points
#-----------------
{2 4 6} {
scanpar k # load new k-points
"$k $k $k 1 1 1"
K_POINTS automatic
# perform the pw.x calculation (I/O files: scf.Si_k$k.in & scf.Si_k$k.out)
$k
runPW scf.Si_k
# store $k and total energy into the 'k.dat' file
[pwo_totene scf.Si_k$k.out]
write k.dat }
# plot the result
-xl "K of the (KxKxK) k-point mesh" -yl "Total energy (Ry)" k.dat
plot
#---------------------------
# scan the lattice-parameter
#---------------------------
# here we use the "seq" command, which behaves just like the Unix "seq" command
[seq 9.2 0.2 10.8] {
scanpar a # load new celldm(1)
" celldm(1) = $a "
SYSTEM
# perform the calculation (I/O files: scf.Si_alat$a.in & scf.Si_alat$a.out)
$a
runPW scf.Si_alat
# store $a and total energy into the 'alat.dat' file
[pwo_totene scf.Si_alat$a.out]
write alat.dat }
# plot the result
-xl "A lattice paramater (bohr)" -yl "Total energy (Ry)" alat.dat plot
Let us save this script into the scan.pwtk
file. The
script is run from the terminal as:
pwtk scan.pwtk
PWTK explicitly supports all QE executables, which
are documented with the INPUT_*.html documentation. To get
the list of these executables, enter the PWTK interactive prompt by typing
pwtk
in the terminal. Then type:
report programs
which returns the alphabetically sorted list of supported QE executables and the respective commands for running them (e.g. runPW for pw.x, runCP for cp.x, runPH for ph.x…), i.e.:
----------------------------------------------
executable runCmd
----------------------------------------------
all_currents.x runALL_CURRENTS
band_interpolation.x runBAND_INTERPOLATION
bands.x runBANDS
bgw2pw.x runBGW2PW
cp.x runCP
cppp.x runCPPP
d3hess.x runD3HESS
dos.x runDOS
dynmat.x runDYNMAT
hp.x runHP
kcw.x runKCW
ld1.x runLD1
matdyn.x runMATDYN
molecularpdos.x runMOPDOS
neb.x runNEB
oscdft_et.x runOSCDFT_ET
oscdft_pp.x runOSCDFT_PP
ph.x runPH
postahc.x runPOSTAHC
pp.x runPP
ppacf.x runPPACF
pprism.x runPPRISM
projwfc.x runPROJWFC
pw.x runPW
pw2bgw.x runPW2BGW
pw2gw.x runPW2GW
pw2wannier90.x runPW2WANNIER90
pwcond.x runPWCOND
q2r.x runQ2R
turbo_davidson.x runDAVIDSON
turbo_eels.x runEELS
turbo_lanczos.x runLANCZOS
turbo_magnon.x runMAGNON
turbo_spectrum.x runSPECTRUM
----------------------------------------------
Because there are many runCmd commands, which may be hard to remember, there is also an alternative runXX command, whose usage is:
runXX program inputName
where program is the name of the QE executable. For
example, runXX ph.x
is equivalent to runPH.
In the first example above, we used:
runPW scf.Si.in
which is equivalent to:
runXX pw.x scf.Si.in
It is also possible to run other QE programs that are not directly supported by PWTK, using the run command. But in this case, the input file needs to exist before the run command is called. It can be created in a PWTK script with the writeFile command. Here is an example of how to run the ev.x executable:
# create the 'ev.murnaghan.in' file
{
writeFile ev.murnaghan.in
au
fcc4
Etot-vs-alat.dat
Etot-vs-alat.out}
# run the ev.x code; the -serial option requests running in a serial mode
-serial ev.x ev.murnaghan.in run
PWTK has an input data stacking mechanism, which is useful when performing multiple calculations. For example, say that we have a set of default parameters for all calculations, but each calculation requires some input data modification. We do not want a change of input data for a given calculation to affect the input data for subsequent calculations. This can be elegantly achieved using the input data stacking mechanism, and for this purpose, PWTK provides the input_pushpop command. The concept is illustrated below:
# import a default set of parameters (#0)
import input-data.pwtk
# 1st calculation
{
input_pushpop # input data was pushed on the stack;
# at this point the input data is the same as in (#0)
for this calculation (#1)
... modify input data 1st calculation
... perform the }
# the input data modifications (#1) were popped away;
# at this point the input data is the same as in (#0)
# 2nd calculation
{
input_pushpop # input data still the same as in (#0)
for this calculation (#2)
... modify input data 2nd calculation
... perform the }
# at this point the input data is again the same as in (#0)
The PWTK user configuration
files are stored in the ~/.pwtk/
directory. The main
configuration file therein is pwtk.tcl
. In this file,
the following items are typically defined (actually their default
values):
The system configuration files are stored in the
$PWTK/config/
directory and the PWTK first reads the system
configuration files and then the user configuration files, which
implies that user configuration has priority over the system
configuration.
Here is an example of the ~/.pwtk/pwtk.tcl
file:
# ------------------------------------------------------------------------
#
# File: pwtk.tcl -- PWTK main configuration file
#
# This is a main configuration file for PWTK. It contains some custom
# definitions, such as Quantum ESPRESSO executables and alike.
# ------------------------------------------------------------------------
#
# LOCATION OF QUANTUM ESPRESSO EXECUTABLES AND
# HOW TO RUN THEM ...
#
# executables are run as: container prefix bin_dir/program postfix
prefix mpirun -np 32
bin_dir $env(HOME)/bin/espresso
# for containers, one may use:
container apptainer exec /path/to/container.sif
bin_query false
#
# DEFAULT DIRECTORIES ...
#
# N.B. outdir == outdir_prefix/outdir_postfix
# wfcdir == wfcdir_prefix/wfcdir_postfix
outdir_prefix /scratch/$env(USER)/QE
wfcdir_prefix /scratch/$env(USER)/QE
outdir_postfix [pid]
wfcdir_postfix [pid]
# directory for pseudopotential files (aka pseudo_dir)
pseudo_dir $env(HOME)/espresso/pseudo
In this file, the following data are typically specified:
Here is a snippet that automatically determines the number of
available processors that can be used in
~/.pwtk/pwtk.tcl
:
set np [exec nproc]
while { [catch {exec mpirun -n $np echo yes}] } {
set np [expr { $np > 2 ? $np / 2 : 1 }]
}
if { $np > 1 } {
-n $np
prefix mpirun}
The configuration files that a user should usually copy from the
$PWTK/config/ to ~/.pwtk/
directory and edit are:
pwtk.tcl — the main configuration file (typically edited by each user)
remote.tcl — configuration file for specifying how to connect to remote machines
configuration files for HPC schedulers, such as:
The following configuration files typically do not need any user
attention and relying on system configurations in
$PWTK/config/
directory is just fine.
HPC machines use job schedulers. Hence, one needs to provide some
batch-queuing system-specific instructions (directives) in shell
script files, such as the name of the queue, number of processors,
and some other resources. Instead of putting such instructions
inside each shell script (or PWTK
script, if one is using PWTK), the
specific queuing directives can be stored in the corresponding PWTK configuration file
(e.g. ~/.pwtk/slurm.tcl
, ~/.pwtk/lsf.tcl
,
~/.pwtk/pbs.tcl
). Templates for these configuration
files are available in the $PWTK/config/
directory.
Once such configuration file is properly set, a user needs to
instuct PWTK that the script is to
be submitted to the batch queuing system. For Slurm, this can be achieved by
encapsulating the whole script with the SLURM { ... }
command (for the other supported job schedulers, analogous commands
are LSF
, PBS
, LL
). For
example:
SLURM {
... here comes the whole script ...
}
Alternatively, the name of the PWTK script file can be supplied to
the SLURM
command, i.e.:
SLURM job.pwtk
or the pwtk
can be called with the
--slurm
option from the terminal:
pwtk --slurm job.pwtk
Note that the --slurm
option is configurable,
i.e.:
pwtk --slurm=profile job.pwtk
or
pwtk --slurm="profile options" job.pwtk
where profile is the name of the user-defined Slurm profile (see below), and
options are the Slurm sbatch
command-line options.
Likewise, also the SLURM command is analogously configurable; its usage is:
Either:
SLURM script
Or:
SLURM profile script
Or:
SLURM profile --option1=value1 --option2=value2 … script`
where script is either the PWTK script file or the script code
and profile is the name of the profile as defined in the
user ~/.pwtk/slurm.tcl
file that contains the Slurm specific directives. If
the profile is omitted the default profile
is used, which is guaranteed to exist, because it is defined in the
$PWTK/config/slurm.tcl
file.
One can define different profiles in the configuration
file (e.g., ~/.pwtk/slurm.tcl
). Here is an example with
two defined Slurm profiles,
named default and long:
# ------------------------------------------------------------------------
# This is a configuration file for PWTK's SLURM utility
# ------------------------------------------------------------------------
default {
slurm_profile #!/bin/sh
#SBATCH --nodes=1
#SBATCH --ntasks=8
#SBATCH --time=6:00:00
} {
-np 8
prefix mpirun}
{
slurm_profile long #!/bin/sh
#SBATCH --partition=long
#SBATCH --ntasks=64
#SBATCH --time=2-00:00:00
} {
-np 64
prefix mpirun}
The usage of the slurm_profile
command is (for other
supported job schedulers, analogous commands are
lsf_profile
, pbs_profile
, etc.):
slurm_profile name slurmDirectives ?pwtkDirectives?
where the last pwtkDirectives argument is optional
(hence, denotated with the pair of question marks). The purpose of
the optional pwtkDirectives argument is to provide to PWTK a default way of how to run
executables. For example, the long profile request
64 tasks, hence it is reasonable to run executables with
mpirun -np 64
.
The long profile can then be utilized in a PWTK script as:
SLURM long job.pwtk
or from the terminal as:
pwtk --slurm=long job.pwtk
Within namelists and cards, numbers can be specified as
mathematical expressions, e.g.: 1/4*exp(2*log(0.23))
.
Here is an example of how mathematical expressions can be used in
namelists and cards:
SYSTEM { celldm(1) = 7.5*sqrt(2)*$angs2bohr }
ATOMIC_POSITIONS alat {
Si 0.0 0.0 0.0
Si 1/4 1/4 1/4
}
Notice the use of the $angs2bohr
variable in the
example above. This is a predefined constant (a conversion factor
from Å to bohr units).
IMPORTANT: mathematical expression should be
written without any whitespace. For example, the
1/4 * sqrt(2)
expression contains two whitespaces;
hence, it is treated as three separate input-fields and the parser
returns
.25000000000000000000 * 1.41421356237309504880
.
Here is a list of predefined constants that can be used in PWTK scripts and in mathematical expressions of input data specs. Physical constants correspond to CODATA Internationally Recommended 2018 Values.
bohr2angs = 0.529177210903
angs2bohr = 1.0/$bohr2angs
ry2ev = 13.605693122994017
ha2ev = 2.0*$ry2ev
ev2ry = 1.0/$ry2ev
ev2ha = 1.0/$ha2ev
ry2kjm = 1312.7498197399127
ha2kjm = 2.0*$ry2kjm
kjm2ry = 1.0/$ry2kjm
kjm2ha = 1.0/$ha2kjm
pi = 3.14159265358979323844
tpi = 2.0*$pi