TABLE OF CONTENTS
51-bg
DESCRIPTION
This example shows how to run script snippets in parallel with ::pwtk::bg (N.B. bg stands for background).
In this example, a lateral position of O adatom on a two-layer Al(111)-1x1 slab is scanned using a 6x6 lateral XY-grid, implying 36 pw.x calculations. Four jobs run concomitantly and when they finish, a new quadruple is submitted and so on until all jobs are done.
EXAMPLE SOURCE FILE
SOURCE
# jobs submitted with ::pwtk::bg are child processes born in an empty state; # ::pwtk::propagate is used to inform PWTK what to propagate to the child processes propagate { # we will run 4 concurrent jobs; the number of processors used for # each job depends on the number of available cores; # edit according to your preference prefix mpirun -np 2 # load the pw.x input data with ::pwtk::pwi::load_fromPWI load_fromPWI relax.OAl111-1x1-2L.in # Make some simple structure modification: # 1. fix the O adatom and the top Al layer laterally with ::pwtk::pwi::fixAtoms1st # 2. fix the bottom layer of Al-slab with ::pwtk::pwi::fixAtomsLast fixAtoms1st 2 "0 0 1" fixAtomsLast 1 } # scan the O adatom over the lateral x,y positions set seq [seq 0.0 0.2 1.0]; # this sequence will be used multiple times foreach dx $seq { foreach dy $seq { # a counter to count # of concurrent jobs incr ijob # ::pwtk::bg runs a script snippet in the non-blocking mode (aka background) bg { # each job should have its own prefix or else jobs will # write to the same temporary files CONTROL " prefix = 'O-$dx,$dy.Al111' " # shift the O adatom to a new position with ::pwtk::pwi::displaceAtoms displaceAtoms "$dx $dy 0.0" 1 # run pw.x calculation with ::pwtk::runPW runPW relax-z.O-$dx,$dy.Al111-1x1-2L } # allow only 4 parallel jobs if { $ijob == 4 } { # ::pwtk::bg_wait waits for background jobs to finish bg_wait # reset the concurrent job counter set ijob 0 } } } bg_wait; # not really needed because 36 is divisible by 4, hence # all "bg" jobs should be finished at this point # extract all total energies foreach dx $seq { foreach dy $seq { # get the total energy with pwo_totene, a shortcut to ::pwtk::pwo::totene set E($dx,$dy) [pwo_totene relax-z.O-$dx,$dy.Al111-1x1-2L.out] # get the minimum total energy ifset Emin $E($dx,$dy); # ::pwtk::ifset assigns the variable only if it is not yet assigned if { $E($dx,$dy) < $Emin } { set Emin $E($dx,$dy) } } } # calculate ΔE(x,y) = E(x,y) - Emin, and write a datafile foreach dx $seq { foreach dy $seq { # calculate ΔE(x,y) in eV units set dE [expr $ry2ev*($E($dx,$dy) - $Emin)] # lateral Cartesian position of the O atom in alat units set x [expr $dx - 0.5*$dy] set y [expr sqrt(3)/2*$dy] # write data to a file with ::pwtk::write write ene.OAl.dat "$x $y $dE" } write ene.OAl.dat "" } # plot the heatmap with ::pwtk::heatmap heatmap -pal dark -i 10,10 -contour -cc black \ -xr -0.5:1 -yr 0:sqrt(3)/2 \ -xl "Δx (alat)" -yl "Δy (alat)" \ -xf %.1f -yf %.1f -cbf %.1f ene.OAl.dat # plot the surface plot with ::pwtk::splot splot -pal dark -i 10,10 -contour -cc black \ -xr -0.5:1 -yr 0:sqrt(3)/2 \ -xl "Δx (alat)" -yl "Δy (alat)" -zl "ΔE (eV)" \ -xf %.1f -yf %.1f -zf %.1f -cbf %.1f \ -x {set zlabel rotate by 90} ene.OAl.dat