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

bg.pwtk

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