TABLE OF CONTENTS


52-thread

DESCRIPTION

This example shows how to run script snippets concurrently using threads as implemented by ::pwtk::thread

This example is analogous to the 51-bg example (file: bg.pwtk), with the difference that that ::pwtk::thread is used instead of ::pwtk::bg.

WARNING

EXAMPLE SOURCE FILE

thread.pwtk

SOURCE

# jobs submitted with ::pwtk::thread 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 2
}

# 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 threads
        incr ithread
        
        # ::pwtk::thread runs a script snippet in the non-blocking
        # mode allowing for the concurrent execution of many threads
        thread {            
            # 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 threads
        if { $ithread == 4 } {            
            # ::pwtk::thread_wait waits for threads to finish
            thread_wait

            # reset the concurrent thread counter
            set ithread 0
        }  
    }
}

thread_wait; # not really needed because 36 is divisible by 4, hence
             # all "thread" 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 \
    -e {set zlabel rotate by 90} ene.OAl.dat