TABLE OF CONTENTS


53-tpool

DESCRIPTION

This example shows how to use a thread-pool with PWTK. A thread-pool is a mechanism for achieving concurrency of execution, consisting of multiple threads waiting for jobs to be allocated for concurrent execution.

This example is analogous to the 51-bg example (file: bg.pwtk), but uses thread-pool (::pwtk::tpool) instead of ::pwtk::bg. In particular, 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. A thread-pool with 4 workers is created, implying that initially 4 jobs are distributed to 4 workers. When the first job finishes, thread-pool submits the next job to a free worker, and so on until all jobs are completed.

BEWARE

EXAMPLE SOURCE FILE

tpool.pwtk

SOURCE

# jobs submitted to thread-pool 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 jobs in parallel; 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
}

# create a thread-pool ::pwtk::tpool object with 4 concurrent thread-workers

set tp [tpool new -t 4]

set seq [seq 0.0 0.2 1.0]; # this sequence will be used multiple times

foreach dx $seq {
    foreach dy $seq {
        
        # jobs are submitted to thread-pool with the "job" method (see ::pwtk::tpool::job)
        
        $tp job {            
            # 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
        }
    }
}

# wait for all tpool jobs to finish (see ::pwtk::tpool::wait)

$tp wait


# 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