YAMBO TUTORIAL: files and scripts === > [name=Fulvio] Here we give a reference for the various files and scripts used in the tutorials [TOC] ### GW input file for parallel section <details> ```bash= # ____ ____ _ ____ ____ ______ ___ # |_ _||_ _| / \ |_ \ / _||_ _ \ ." `. # \ \ / / / _ \ | \/ | | |_) | / .-. \ # \ \/ / / ___ \ | |\ /| | | __". | | | | # _| |_ _/ / \ \_ _| |_\/_| |_ _| |__) |\ `-" / # |______||____| |____||_____||_____||_______/ `.___." # # # # Version 5.1.0 Revision 21422 Hash (prev commit) fde6e2a07 # Branch is # MPI+OpenMP+SLK+HDF5_MPI_IO Build # http://www.yambo-code.org # rim_cut # [R] Coulomb potential gw0 # [R] GW approximation ppa # [R][Xp] Plasmon Pole Approximation for the Screened Interaction dyson # [R] Dyson Equation solver HF_and_locXC # [R] Hartree-Fock em1d # [R][X] Dynamically Screened Interaction FFTGvecs = 20 Ry # [FFT] Plane-waves X_Threads=0 # [OPENMP/X] Number of threads for response functions DIP_Threads=0 # [OPENMP/X] Number of threads for dipoles SE_Threads=0 # [OPENMP/GW] Number of threads for self-energy RandQpts=1000000 # [RIM] Number of random q-points in the BZ RandGvec= 100 RL # [RIM] Coulomb interaction RS components CUTGeo= "slab z" # [CUT] Coulomb Cutoff geometry: box/cylinder/sphere/ws/slab X/Y/Z/XY.. % CUTBox 0.000000 | 0.000000 | 0.000000 | # [CUT] [au] Box sides % CUTRadius= 0.000000 # [CUT] [au] Sphere/Cylinder radius CUTCylLen= 0.000000 # [CUT] [au] Cylinder length CUTwsGvec= 0.700000 # [CUT] WS cutoff: number of G to be modified EXXRLvcs= 2 Ry # [XX] Exchange RL components VXCRLvcs= 2 Ry # [XC] XCpotential RL components Chimod= "HARTREE" # [X] IP/Hartree/ALDA/LRC/PF/BSfxc % BndsRnXp 1 | 300 | # [Xp] Polarization function bands % NGsBlkXp= 1 Ry # [Xp] Response block size % LongDrXp 1.000000 | 1.000000 | 1.000000 | # [Xp] [cc] Electric Field % PPAPntXp= 27.21138 eV # [Xp] PPA imaginary energy XTermKind= "none" # [X] X terminator ("none","BG" Bruneval-Gonze) % GbndRnge 1 | 300 | # [GW] G[W] bands range % GTermKind= "none" # [GW] GW terminator ("none","BG" Bruneval-Gonze,"BRS" Berger-Reining-Sottile) DysSolver= "n" # [GW] Dyson Equation solver ("n","s","g") %QPkrange # [GW] QP generalized Kpoint/Band indices 1|19|23|30| % ``` </details> ### Slurm submission scripts on VEGA #### Running on CPU: <details> ```bash= #!/bin/bash #SBATCH --nodes=1 #SBATCH --ntasks-per-node=16 #SBATCH --cpus-per-task=1 #SBATCH --partition=cpu #SBATCH --time=0:30:00 #SBATCH --account=d2021-135-users #SBATCH --mem-per-cpu=2000MB #SBATCH --job-name=mos2 #SBATCH --reservation=maxcpu # load yambo and dependencies module purge module use /ceph/hpc/data/d2021-135-users/modules module load YAMBO/5.1.1-FOSS-2022a export OMP_NUM_THREADS=${SLURM_CPUS_PER_TASK} # run job srun --mpi=pmix -n ${SLURM_NTASKS} yambo -F gw.in -J GW_dbs -C GW_reports ``` </details> #### Running on GPU: <details> ```bash= #!/bin/bash #SBATCH --nodes=1 #SBATCH --ntasks-per-node=4 #SBATCH --ntasks-per-socket=2 #SBATCH --cpus-per-task=64 #SBATCH --gres=gpu:4 #SBATCH --partition=gpu #SBATCH --time=0:30:00 #SBATCH --account=d2021-135-users #SBATCH --mem=230000MB #SBATCH --job-name=mos2-test #SBATCH --exclusive #SBATCH --reservation=maxgpu # load yambo and dependencies module purge module use /ceph/hpc/data/d2021-135-users/modules module load YAMBO/5.1.1-OMPI-4.0.5-NVHPC-21.2-CUDA-11.2.1 export OMP_NUM_THREADS=8 srun --mpi=pmix -n ${SLURM_NTASKS} yambo -F gw.in -J GW_dbs -C GW_reports ``` </details> #### Slurm submission for convergence tutorial <details> ```bash= #!/bin/bash #SBATCH --nodes=1 #SBATCH --ntasks-per-node=16 #SBATCH --cpus-per-task=1 #SBATCH --partition=cpu #SBATCH --time=0:30:00 #SBATCH --account=d2021-135-users #SBATCH --mem-per-cpu=2000MB #SBATCH --job-name=mos2 # load yambo and dependencies module purge module use /ceph/hpc/data/d2021-135-users/modules module load YAMBO/5.1.1-FOSS-2022a export OMP_NUM_THREADS=${SLURM_CPUS_PER_TASK} file0='i01-GW' for POL_BANDS in 20 40 60 80; do echo 'NGsBlkXp [Ry] E_vale [eV] E_cond [eV]' > summary_01_${POL_BANDS}bands.txt for NGsBlkXp_Ry in 6 8 10 12; do label=Xp_${POL_BANDS}_bands_${NGsBlkXp_Ry}_Ry jdir=job_${label} cdir=out_${label} filein=i01-GW_${label} sed "s/NGsBlkXp=.*/NGsBlkXp=${NGsBlkXp_Ry} Ry/; /% BndsRnXp/{n;s/.*/ 1 | ${POL_BANDS} |/}" $file0 > $filein # run yambo srun --mpi=pmix -n ${SLURM_NTASKS} yambo -F $filein -J $jdir -C $cdir E_GW_v=`grep -v '#' ${cdir}/o-${jdir}.qp|head -n 1| awk '{print $3+$4}'` E_GW_c=`grep -v '#' ${cdir}/o-${jdir}.qp|tail -n 1| awk '{print $3+$4}'` GAP_GW=`echo $E_GW_c - $E_GW_v |bc` echo ${NGsBlkXp_Ry} ' ' ${E_GW_v} ' ' ${E_GW_c} ' ' ${GAP_GW} >> summary_01_${POL_BANDS}bands.txt done done ``` </details> #### Slurm submission for parallel tutorial <details> ```bash= #!/bin/bash #SBATCH --nodes=1 #SBATCH --ntasks-per-node=16 #SBATCH --cpus-per-task=1 #SBATCH --partition=cpu #SBATCH --time=1:00:00 #SBATCH --account=d2021-135-users #SBATCH --mem-per-cpu=2000MB #SBATCH --job-name=mos2 ##ATCH --reservation=maxcpu # load yambo and dependencies module purge module use /ceph/hpc/data/d2021-135-users/modules module load YAMBO/5.1.1-FOSS-2022a export OMP_NUM_THREADS=${SLURM_CPUS_PER_TASK} # info ncpu=${SLURM_NTASKS} nthreads=${OMP_NUM_THREADS} label=MPI${ncpu}_OMP${nthreads} jdir=run_${label} cdir=run_${label}.out # Update input file filein0=gw.in # Original file filein=gw_${label}.in # New file cp -f $filein0 $filein cat >> $filein << EOF DIP_CPU= "1 $ncpu 1" # [PARALLEL] CPUs for each role DIP_ROLEs= "k c v" # [PARALLEL] CPUs roles (k,c,v) DIP_Threads= 0 # [OPENMP/X] Number of threads for dipoles X_and_IO_CPU= "1 1 1 $ncpu 1" # [PARALLEL] CPUs for each role X_and_IO_ROLEs= "q g k c v" # [PARALLEL] CPUs roles (q,g,k,c,v) X_and_IO_nCPU_LinAlg_INV=1 # [PARALLEL] CPUs for Linear Algebra (if -1 it is automatically set) X_Threads= 0 # [OPENMP/X] Number of threads for response functions SE_CPU= "1 $ncpu 1" # [PARALLEL] CPUs for each role SE_ROLEs= "q qp b" # [PARALLEL] CPUs roles (q,qp,b) SE_Threads= 0 # [OPENMP/GW] Number of threads for self-energy EOF # run yambo srun --mpi=pmix -n $ncpu yambo -F $filein -J $jdir -C $cdir ``` </details> ### Python scripts #### Convergence plot 1 <details> ```python= import numpy as np import matplotlib.pyplot as plt list_of_bands = [20,40,60,80] list_of_data = [] for bands in list_of_bands: data = np.loadtxt(f'summary_01_{bands}bands.txt',comments='NGs') list_of_data.append(data) for bands,data in zip(list_of_bands,list_of_data): X=data[:,0] Y=data[:,2]-data[:,1] plt.plot(X,Y,marker='.',label=f'{bands}_bands') plt.ylabel('Direct Gap [eV]') plt.xlabel('NGsBlkXp [Ry]') plt.legend() plt.savefig('fig-01.png') ``` </details> #### Convergence plot 2 <details> ```python= import numpy as np import matplotlib.pyplot as plt list_of_files = ['summary_02_noBG.txt'] #list_of_files = ['summary_02_noBG.txt','summary_03_BG.txt'] list_of_data = [] for _file in list_of_files: data = np.loadtxt(_file,comments='G b') list_of_data.append(data) for _file,data in zip(list_of_files,list_of_data): X=data[:,0] Y=data[:,2]-data[:,1] _label=_file.split('.')[0].split('_')[2] plt.plot(X,Y,marker='.',label=_label) plt.ylabel('Direct Gap [eV]') plt.xlabel('G bands') plt.legend() plt.savefig('fig-02.png') ``` </details> #### parse_ytiming.py <details> ```python= """ Script used to parse the timings at the end of Yambo reports file. Usage: parse_ytimings.py head_calc_dir head_calc_dir = first characters of the names of directories containing reports Output: - scaling plots """ from glob import glob import sys def parse_timing_data(separator1=" : ",separator2 ="s P",separator3 = "s C",separator4 = "m-"): """ Read timing sections of a list of report files """ # Get report files n_runs = len(glob(sys.argv[1]+'*.out')) reports = glob(sys.argv[1]+'*/r-*') n_reports = len(reports) if n_reports != n_runs: raise ValueError("[ERR] report (%d) and run (%d) numbers are different"%(n_reports,n_runs)) # Produce a dictionary for each output # Key: timing section name, Value: timing in seconds time_dicts = [] n_tasks = [] for report in reports: with open(report) as r: lines = r.readlines() # Find Timing Overview in the report for il,line in enumerate(lines): if "Threads total" in line: n_tasks.append(int(line.split(":")[1].strip())) if "Timing Overview" in line: l0 = il if "Memory Overview" in line: l1 = il lines=lines[l0:l1] time_dict = {} for line in lines: if separator1 in line: aux = line.split(separator1) key = aux[0].strip() # Use separator2 for parallel runs, separator3 for serial if separator2 in aux[1]: value = aux[1].split(separator2)[0].strip() if separator3 in aux[1]: value = aux[1].split(separator3)[0].strip() # Convert in seconds if minutes format found if separator4 in value: value = float(value.split(separator4)[0])*60.+\ float(value.split(separator4)[1]) else: value = float(value) time_dict[key]=value time_dicts.append(time_dict) # Last check n_dicts = len(time_dicts) if n_dicts!=n_reports: raise ValueError("[ERR] Parsing problem (number of dicts. %d different from number of reports %d)"%(n_dicts,n_reports)) return n_tasks,time_dicts def get_global_time(separator1="m-"): """ Read global time (MAX) from list of report files """ # Get report files n_runs = len(glob(sys.argv[1]+'*.out')) reports = glob(sys.argv[1]+'*/r-*') n_reports = len(reports) if n_reports != n_runs: raise ValueError("[ERR] report and run number are different: ",n_reports,n_runs) time_total = [] for report in reports: with open(report) as r: lines = r.readlines() for line in lines: if "[Time-Profile]" in line: time= line.split(':')[1].strip('s\n') if separator1 in time: time = float(time.split(separator1)[0])*60.+\ float(time.split(separator1)[1]) else: time = float(time) time_total.append(time) break n_times = len(time_total) if n_times!=n_reports: raise ValueError("[ERR] Parsing problem (number of times %d different from number of reports %d)"%(n_times,n_reports)) return time_total def plot_scaling(n_tasks,time_total): """ Plot scaling figure: times (s) vs n_tasks """ import matplotlib.pyplot as plt import numpy as np n_tasks = np.array(n_tasks) time_total = np.array(time_total) x = sorted(n_tasks) y = time_total[np.argsort(n_tasks)] plt.xticks(x) plt.xlabel("N tasks") plt.ylabel("Time (s)") plt.plot(x,y, '.-', c='teal',markersize=10) plt.savefig('gw_scaling.png') #plt.show() if __name__=="__main__": if len(sys.argv)!=2: print("Usage: > python parse_ytimings.py header_dir") print("with argument being head chars of report directory i.e. 'header_dir'='run_MPI'") exit() n_tasks, time_dicts = parse_timing_data() time_total = get_global_time() plot_scaling(n_tasks,time_total) ``` </details> #### plot_bands.py <details> ```python= import numpy as np import matplotlib.pyplot as plt import sys def plot_bands(data1,data2): """ Plot bands (DFT vs GW) """ def get_high_sym_indices(Npts): den=3.+np.sqrt(3.) x,y,z=[np.sqrt(3.)/den,1./den,2./den] return [0,int(x*Npts)-1,int((x+y)*Npts)-1,int(Npts)-1] ax = plt.axes() ax.set_ylabel("Energy (eV)") Spts = get_high_sym_indices(len(data1)) Svals= [ data1[pt,0] for pt in Spts ] ax.set_xticks(Svals) ax.set_xticklabels(['G','M','K','G']) for v in Svals: ax.axvline(v,c='black') Nb = data1.shape[1]-1 for ib in range(Nb): if ib==0: ax.plot(data1[:,0],data1[:,ib+1], '-', c='red',label='dft') ax.plot(data2[:,0],data2[:,ib+1], '-', c='blue',label='gw') else: ax.plot(data1[:,0],data1[:,ib+1], '-', c='red') ax.plot(data2[:,0],data2[:,ib+1], '-', c='blue') plt.legend() plt.savefig('gw_bands.png') plt.show() if __name__=="__main__": if len(sys.argv)!=4: print("Usage: > python plot_bands.py DFT_bands_file GW_bands_file N_b") print("with argument being name of interpolated bands file: DFT, GW") print("and N_b the bands number") exit() Nb = int(sys.argv[3]) cols = [ i for i in range(Nb+1) ] dft_bands = np.genfromtxt(sys.argv[1],usecols=(cols)) gw_bands = np.genfromtxt(sys.argv[2],usecols=(cols)) plot_bands(dft_bands,gw_bands) ``` </details> ###### tags: `Yambo` `GW calculations` `HPC` `tutorial`