├── ASG ├── heterobilayer │ ├── twisted │ │ ├── find_moire.m │ │ ├── generate_structure.m │ │ ├── main.m │ │ ├── main_TMD.m │ │ ├── main_TMD_graphene.m │ │ ├── write_kpts.m │ │ ├── write_lammps.m │ │ ├── write_pos.m │ │ ├── write_pot.m │ │ ├── write_xsf.m │ │ └── write_xyz.m │ └── untwisted │ │ ├── generate_structure.m │ │ ├── main.m │ │ ├── write_kpts.m │ │ ├── write_lammps.m │ │ ├── write_pos.m │ │ ├── write_pot.m │ │ ├── write_xsf.m │ │ └── write_xyz.m ├── homobilayer │ └── twisted │ │ ├── TBLG_cell.m │ │ ├── TBLTMD_cell.m │ │ ├── TBLhBN_cell.m │ │ ├── main.m │ │ ├── main_graphene.m │ │ ├── write_full_xyz.m │ │ ├── write_kpts.m │ │ ├── write_lammps.m │ │ ├── write_tb.m │ │ ├── write_xsf.m │ │ └── write_xyz.m └── homomultilayers │ └── twisted │ ├── TMLTMD_cell.m │ ├── analyse_structure_quadlayer.m │ ├── generate_cell.m │ ├── main.m │ ├── plot_corrugation_quadlayer.m │ ├── write_lammps.m │ ├── write_tb.m │ ├── write_xsf.m │ └── write_xyz.m ├── LICENSE ├── README.md └── TB └── src ├── .BSE_parallel.m.swp ├── BSE.m ├── BSE_parallel.m ├── BSE_parallel4.m ├── README.md ├── StruveH0.m ├── StruveH0Y0.m ├── TMDC_monolayer.m ├── Vint.m ├── add_soc.m ├── assign_hoppings.m ├── assign_hoppings_3rdnn.m ├── assign_hoppings_6thnn.m ├── assign_hoppings_6thnn_strain.m ├── assign_hoppings_all.m ├── build_H2.m ├── build_H_3rdnn.m ├── build_H_6thnn.m ├── chern.m ├── cheval.m ├── colorGradient.m ├── compute_amn.m ├── compute_eig.m ├── compute_mmn.m ├── deformation_potential_dorbs.m ├── deformation_potential_porbs.m ├── generate_T.m ├── generate_k_line.m ├── generate_kpoints.m ├── generate_mask.m ├── initialise_orbitals2.m ├── inter_par.m ├── inter_par_new.m ├── interpolate_SK.m ├── keldysh_pot.m ├── keldysh_pot2.m ├── keldysh_pot3.m ├── keldysh_pot4.m ├── lorentzian.m ├── main.m ├── opt_build_and_diag_H.m ├── opt_build_and_diag_H_3rdnn.m ├── opt_build_and_diag_H_6thnn.m ├── opt_find_neigh2.m ├── opt_find_neigh_3rdnn.m ├── opt_find_neigh_6thnn.m ├── orbital.m ├── plot_bandstructure.m ├── plot_exciton_wfc.m ├── plot_exciton_wfc2.m ├── plot_exciton_wfc_test.m ├── plot_projection.m ├── plot_wfc_new.m ├── read_input.m ├── read_kpts.m ├── read_structure.m ├── real_pot2.m ├── screenC2.m ├── screenC3.m ├── screenC4.m ├── set_hopping.m ├── set_parameters.m ├── soc.m ├── w90_nnkp.m ├── wigner_seitz_cell.m ├── write_ham_hdf5.m ├── write_hdf5.m └── write_kpts.m /ASG/heterobilayer/twisted/find_moire.m: -------------------------------------------------------------------------------- 1 | function [m_s,n_s,p_s,theta_s,nmoire] = find_moire(theta,dt,r_t,max_int,size_t,comb,threshold,p,r_p,m_s,n_s,theta_s,p_s) 2 | deg2rad=pi/180; 3 | rad2deg = 1.0/deg2rad; 4 | 5 | dis_m = -1; 6 | dis_n = -1; 7 | xs = -99999; 8 | 9 | iter = 0; 10 | nmoire = 0; 11 | 12 | % Allocate arrays 13 | x_m = zeros(2,size_t); 14 | x_n = zeros(2,size_t); 15 | x_m(:,:) = -88888; 16 | x_n(:,:) = -99999; 17 | lfound = false(size_t,1); 18 | 19 | % Start search 20 | for th = theta - r_t : dt : theta + r_t 21 | iter = iter + 1; 22 | th = th * deg2rad; 23 | ct = cos(th); 24 | st = sin(th); 25 | for im = 1 : max_int 26 | if (lfound(iter)) 27 | break; 28 | end 29 | dis_m = (ct + 1/(2*im)*(st/sqrt(3)+ct))^2 - 1.0 - 1.0/im; 30 | if (dis_m >= 0) 31 | x_m(1,iter) = ct + 1/(2*im)*(st/sqrt(3) + ct) + sqrt(dis_m); 32 | x_m(2,iter) = ct + 1/(2*im)*(st/sqrt(3) + ct) - sqrt(dis_m); 33 | end 34 | 35 | if (comb == -1) 36 | start_in = im + 1; 37 | else 38 | start_in = 1; 39 | end 40 | for in = start_in : max_int 41 | if (lfound(iter) == true) 42 | break; 43 | end 44 | xs = -99999; 45 | err = -99999; 46 | ierr = 0; 47 | dis_n = (ct+st/(sqrt(3)*in))^2-1; 48 | if (dis_n >= 0) 49 | x_n(1,iter) = ct + 1/(in)*st/sqrt(3) + sqrt(dis_n); 50 | x_n(2,iter) = ct + 1/(in)*st/sqrt(3) - sqrt(dis_n); 51 | end 52 | % The assumption here is that we have only one solution 53 | if (abs(x_m(1,iter) - x_n(1,iter)) < threshold) 54 | err = abs(x_m(1,iter) - x_n(1,iter)); 55 | xs = x_m(1,iter); 56 | elseif (abs(x_m(1,iter) - x_n(2,iter)) < threshold) 57 | err = abs(x_m(1,iter) - x_n(2,iter)); 58 | xs = x_m(1,iter); 59 | elseif (abs(x_m(2,iter) - x_n(1,iter)) < threshold) 60 | err = abs(x_m(2,iter) - x_n(1,iter)); 61 | xs = x_m(2,iter); 62 | elseif (abs(x_m(2,iter) - x_n(2,iter)) < threshold) 63 | err = abs(x_m(2,iter) - x_n(2,iter)); 64 | xs = x_m(2,iter); 65 | end 66 | if (err < threshold) 67 | if (abs(xs - p) <= r_p) 68 | % Check that we have not found it yet 69 | for i = 1 : iter - 1; 70 | % if found 71 | if (im == m_s(i)) && (in == n_s(i)) 72 | lfound(iter) = true; 73 | loc_err = -99999; 74 | msg = ['Found another structure with m = ', ... 75 | num2str(im), '; n = ', num2str(in), ... 76 | ' (theta = ', num2str(th*rad2deg), ... 77 | num2str(in), '; p = ', num2str(xs), ... 78 | '; err = ', num2str(err),')', '...']; 79 | disp(msg) 80 | % Check if the error is smaller and swap if it 81 | % is 82 | loc_err = min([abs(x_m(1,i)-x_n(1,i)),abs(x_m(1,i)-x_n(2,i)),... 83 | abs(x_m(2,i)-x_n(1,i)),abs(x_m(2,i)-x_n(2,i))]); 84 | if (loc_err > err) 85 | m_s(i) = im; 86 | n_s(i) = in; 87 | theta_s(i) = th; 88 | p_s(i) = xs; 89 | x_m(:,i) = x_m(:,iter); 90 | x_n(:,i) = x_n(:,iter); 91 | msg = 'Accepted'; 92 | disp(msg) 93 | else 94 | msg = 'Rejected'; 95 | disp(msg) 96 | end 97 | end 98 | end 99 | if (~lfound(iter)) 100 | lfound(iter) = true; 101 | nmoire = nmoire + 1; 102 | m_s(iter) = im; 103 | n_s(iter) = in; 104 | theta_s(iter) = th; 105 | p_s(iter) = xs; 106 | msg = ['Found one moire supercell with theta = ', ... 107 | num2str(th*rad2deg),'; m = ',num2str(im), ... 108 | '; n = ', num2str(in), '; p = ', num2str(xs),... 109 | '; err = ', num2str(err)]; 110 | disp(msg) 111 | break; 112 | end 113 | end 114 | end 115 | end 116 | end 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /ASG/heterobilayer/twisted/generate_structure.m: -------------------------------------------------------------------------------- 1 | function [nat,nat1,nat2,pos,pos2,id1,id2,at_num1,at_num2] = generate_structure(a,u,c1,c2,z,I,Rtheta,ncell,alat1,ialatL,tol,pos,pos2,id1,id2,id11,id12,id13,id21,id22,id23,at_num1,at_num2,at_num11,at_num12,at_num13,at_num21,at_num22,at_num23,layer1,layer2,phase) 2 | k1=0; 3 | if(layer1 == "TMD" ) 4 | for nj = -ncell:ncell 5 | for ni = -ncell:ncell 6 | r1 = ni*alat1(:,1) + nj*alat1(:,2);% + [0.2;0.2]; 7 | r2 = r1 + 1/3*(2*alat1(:,1)+alat1(:,2));%[ r1(1); r1(2)+a/sqrt(3)]; 8 | r3 = r2; 9 | l1 = ialatL*r1; 10 | l2 = ialatL*r2; 11 | % Check if atom coordinates is in moire cell 12 | if (l1(1) < (1-tol) && l1(1) >= -tol && l1(2) < (1-tol) && l1(2) >= -tol) 13 | k1 = k1 + 1; 14 | pos(k1,1)=r1(1); 15 | pos(k1,2)=r1(2); 16 | pos(k1,3)=0.25*c1; 17 | id1(k1) = id11; 18 | at_num1(k1) = at_num11; 19 | lprint1(k1) = true; 20 | end 21 | if (l2(1) < (1-tol) && l2(1) >= -tol && l2(2) < (1-tol) && l2(2) >= -tol) 22 | k1 = k1 + 1; 23 | pos(k1,1)=r2(1); 24 | pos(k1,2)=r2(2); 25 | pos(k1,3)= -(0.5-u)*c1; 26 | id1(k1) = id12; 27 | at_num1(k1) = at_num12; 28 | lprint1(k1) = true; 29 | k1 = k1 + 1; 30 | pos(k1,1)=r3(1); 31 | pos(k1,2)=r3(2); 32 | pos(k1,3)= (1-u)*c1; 33 | id1(k1) = id13; 34 | at_num1(k1) = at_num13; 35 | lprint1(k1) = true; 36 | end 37 | end 38 | end 39 | elseif(layer1 == "graphene") 40 | for nj = -ncell:ncell 41 | for ni = -ncell:ncell 42 | r1 = ni*alat1(:,1) + nj*alat1(:,2); 43 | r2 = [ r1(1); r1(2)+a/sqrt(3)]; 44 | l1 = ialatL*r1; 45 | l2 = ialatL*r2; 46 | % Check if atom coordinates is in moire cell 47 | if (l1(1) < (1-tol) && l1(1) >= -tol && l1(2) < (1-tol) && l1(2) >= -tol) 48 | k1 = k1 + 1; 49 | pos(k1,1)=r1(1); 50 | pos(k1,2)=r1(2); 51 | pos(k1,3)=0.0; 52 | id1(k1) = id11; 53 | at_num1(k1) = at_num11; 54 | lprint1(k1) = true; 55 | end 56 | if (l2(1) < (1-tol) && l2(1) >= -tol && l2(2) < (1-tol) && l2(2) >= -tol) 57 | k1 = k1 + 1; 58 | pos(k1,1)=r2(1); 59 | pos(k1,2)=r2(2); 60 | pos(k1,3)=0.0; 61 | id1(k1) = id12; 62 | at_num1(k1) = at_num12; 63 | lprint1(k1) = true; 64 | end 65 | end 66 | end 67 | end 68 | nat1 = k1; 69 | 70 | % Top layer 71 | k2 = 0; 72 | if(layer2 == "TMD") 73 | for ni=-ncell:ncell 74 | for nj = -ncell:ncell 75 | r1 = ni*alat1(:,1) + nj*alat1(:,2);% + [0.2; 0.2]; 76 | r2 = r1 + 1/3*(2*alat1(:,1)+alat1(:,2));% [r1(1); r1(2)+a/sqrt(3)]; 77 | if(phase=='AA') 78 | rr1 = I*Rtheta*r1; 79 | rr2 = I*Rtheta*r2; 80 | rr3 = rr2; 81 | elseif(phase=='AB') 82 | rr1 = I*Rtheta*(-r1 + [0.0; a]);%/sqrt(3)]); 83 | rr2 = I*Rtheta*(-r2 + [0.0; a]);%/sqrt(3)]); 84 | rr3 = rr2; 85 | end 86 | 87 | l1 = ialatL*rr1; 88 | l2 = ialatL*rr2; 89 | % Check atom belongs to moirè cell within small 90 | % tollerance 91 | if (l1(1) < (1-tol) && l1(1) >= -tol && l1(2) < (1-tol) && l1(2) >= -tol) 92 | k2 = k2 + 1; 93 | pos2(k2,1) = rr1(1); 94 | pos2(k2,2) = rr1(2); 95 | pos2(k2,3) = 0.75*c2; 96 | id2(k2) = id21; 97 | at_num2(k2) = at_num21; 98 | lprint2(k2) = true; 99 | 100 | end 101 | if (l2(1) < (1-tol) && l2(1) >= -tol && l2(2) < (1-tol) && l2(2) >= -tol) 102 | k2 = k2 + 1; 103 | pos2(k2,1) = rr2(1); 104 | pos2(k2,2) = rr2(2); 105 | pos2(k2,3) = u*c2; 106 | id2(k2) = id22; 107 | at_num2(k2) = at_num22; 108 | lprint2(k2) = true; 109 | k2 = k2 + 1; 110 | pos2(k2,1) = rr3(1); 111 | pos2(k2,2) = rr3(2); 112 | pos2(k2,3) = (1.5-u)*c2; 113 | id2(k2) = id23; 114 | at_num2(k2) = at_num23; 115 | lprint2(k2) = true; 116 | end 117 | end 118 | end 119 | elseif(layer2 == "graphene") 120 | for ni=-ncell:ncell 121 | for nj = -ncell:ncell 122 | r1 = ni*alat1(:,1) + nj*alat1(:,2); 123 | r2 = [r1(1); r1(2)+a/sqrt(3)]; 124 | if(phase=='AA') 125 | rr1 = I*Rtheta*r1; 126 | rr2 = I*Rtheta*r2; 127 | elseif(phase=='AB') 128 | rr1 = I*Rtheta*r2; 129 | rr2 = I*Rtheta*[r2(1);r(2)+a/sqrt(3)]; 130 | end 131 | l1 = ialatL*rr1; 132 | l2 = ialatL*rr2; 133 | % Check atom belongs to moirè cell within small 134 | % tollerance 135 | if (l1(1) < (1-tol) && l1(1) >= -tol && l1(2) < (1-tol) && l1(2) >= -tol) 136 | k2 = k2 + 1; 137 | pos2(k2,1) = rr1(1); 138 | pos2(k2,2) = rr1(2); 139 | pos2(k2,3) = z; 140 | id2(k2) = id21; 141 | at_num2(k2) = at_num21; 142 | lprint2(k2) = true; 143 | 144 | end 145 | if (l2(1) < (1-tol) && l2(1) >= -tol && l2(2) < (1-tol) && l2(2) >= -tol) 146 | k2 = k2 + 1; 147 | pos2(k2,1) = rr2(1); 148 | pos2(k2,2) = rr2(2); 149 | pos2(k2,3) = z; 150 | id2(k2) = id22; 151 | at_num2(k2) = at_num22; 152 | lprint2(k2) = true; 153 | end 154 | end 155 | end 156 | end 157 | 158 | nat2 = k2; 159 | nat = nat1 + nat2; 160 | end 161 | -------------------------------------------------------------------------------- /ASG/heterobilayer/twisted/write_lammps.m: -------------------------------------------------------------------------------- 1 | function write_lammps(nat1,nat2,filename,alatL,c,ntype,m,id1,id2,id11,id12,id13,id21,id22,id23,pos,pos2,str_m,str_n,str_theta,phi) 2 | filename = join([filename,str_theta],"_theta="); 3 | filename = join([filename,str_m],"_m="); 4 | filename = join([filename,str_n],"_n="); 5 | lammpsfname = 'lammps_positions'; 6 | lammpsfname = join([lammpsfname,filename,'dat'],"."); 7 | additionalfname = join([filename,'rotation','dat'],"."); 8 | fileID = fopen(lammpsfname,'w'); 9 | fileID2 = fopen(additionalfname,'w'); 10 | fprintf(fileID2,'%8.8f\n',phi*180/pi); 11 | fprintf(fileID2,'%8.8f %8.8f %8.8f\n',alatL(:,1)); 12 | fprintf(fileID2,'%8.8f %8.8f %8.8f\n',alatL(:,2)); 13 | % HEADER of positions.dat 14 | % phi=acos(alatL(1,1)/norm(alatL(1,:))); 15 | % cf=cos(-phi); 16 | % sf=sin(-phi); 17 | % Rphi=[cf -sf; sf cf]; 18 | % rot_alatL = Rphi*alatL'; 19 | % rot_pos = Rphi*pos(:,1:2)'; 20 | % rot_pos2 = Rphi*pos2(:,1:2)'; 21 | fprintf(fileID,'%s\n','LAMMPS data file from TBLG_cell.m'); 22 | fprintf(fileID,'\n'); 23 | fprintf(fileID,'%i %s\n',nat1+nat2,'atoms'); 24 | fprintf(fileID,'\n'); 25 | fprintf(fileID,'%i %s\n',ntype,'atom types'); 26 | fprintf(fileID,'\n'); 27 | fprintf(fileID,'%8.8f %8.8f %s\n',0.0, alatL(1,1), 'xlo xhi'); 28 | fprintf(fileID,'%8.8f %8.8f %s\n',0.0, alatL(2,2), 'ylo yhi'); 29 | fprintf(fileID,'%8.8f %8.8f %s\n',0.0,10*c,'zlo zhi'); 30 | fprintf(fileID,'%8.8f %8.8f %8.8f %s\n', alatL(2,1), 0.0, 0.0, 'xy xz yz'); 31 | fprintf(fileID,'\n'); 32 | fprintf(fileID,'%s\n','Masses'); 33 | fprintf(fileID,'\n'); 34 | for i = 1 : ntype 35 | fprintf(fileID,'%i %2.2f\n',i,m(i)); 36 | end 37 | fprintf(fileID,'\n'); 38 | fprintf(fileID,'%s\n','Atoms'); 39 | fprintf(fileID,'\n'); 40 | 41 | if (ntype==2) 42 | i = 1; 43 | for k = 1:nat1 44 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k,1,pos(k,1),pos(k,2),pos(k,3)); 45 | end 46 | 47 | i = 1; 48 | for k = 1:nat2 49 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',nat1+k,2,pos2(k,1),pos2(k,2),pos2(k,3)); 50 | end 51 | 52 | elseif (ntype==3) 53 | i = 1; 54 | for k = 1:nat1 55 | if (id1(k) == id11) 56 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k,1,pos(k,1),pos(k,2),pos(k,3)); 57 | elseif (id1(k) == id12) 58 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k,2,pos(k,1),pos(k,2),pos(k,3)); 59 | end 60 | end 61 | 62 | i = 1; 63 | for k = 1:nat2 64 | if (id2(k) == id21) 65 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',nat1+k,3,pos2(k,1),pos2(k,2),pos2(k,3)); 66 | elseif (id2(k) == id22) 67 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',nat1+k,3,pos2(k,1),pos2(k,2),pos2(k,3)); 68 | end 69 | end 70 | 71 | elseif (ntype==4) 72 | i = 1; 73 | for k = 1:nat1 74 | if (id1(k) == id11) 75 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k,1,pos(k,1),pos(k,2),pos(k,3)); 76 | elseif (id1(k) == id12) 77 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k,2,pos(k,1),pos(k,2),pos(k,3)); 78 | end 79 | end 80 | 81 | i = 1; 82 | for k = 1:nat2 83 | if (id2(k) == id21) 84 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',nat1+k,3,pos2(k,1),pos2(k,2),pos2(k,3)); 85 | elseif (id2(k) == id22) 86 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',nat1+k,4,pos2(k,1),pos2(k,2),pos2(k,3)); 87 | end 88 | end 89 | 90 | elseif (ntype==6) 91 | i = 1; 92 | for k = 1:nat1 93 | if (id1(k) == id11) 94 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k,1,pos(k,1),pos(k,2),pos(k,3)); 95 | elseif (id1(k) == id12 || id1(k) == id13) 96 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k,2,pos(k,1),pos(k,2),pos(k,3)); 97 | %elseif (id1(k) == id13) 98 | % fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k,3,rot_pos(1,k),rot_pos(2,k),pos(k,3)); 99 | end 100 | end 101 | 102 | i = 1; 103 | for k = 1:nat2 104 | if (id2(k) == id21) 105 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',nat1+k,3,pos2(k,1),pos2(k,2),pos2(k,3)); 106 | elseif (id2(k) == id22 || id2(k) == id23) 107 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',nat1+k,4,pos2(k,1),pos2(k,2),pos2(k,3)); 108 | %elseif (id2(k) == id23) 109 | % fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',nat1+k,6,rot_pos2(1,k),rot_pos2(2,k),pos2(k,3)); 110 | end 111 | end 112 | end 113 | 114 | fclose(fileID); 115 | fclose(fileID2); 116 | end 117 | -------------------------------------------------------------------------------- /ASG/heterobilayer/twisted/write_pos.m: -------------------------------------------------------------------------------- 1 | function write_pos(nat1,nat2,filename,alatL,theta,strain,cell,id1,id2,pos,pos2,str_m,str_n,str_theta) 2 | posfname = join([filename,str_theta],"_theta="); 3 | posfname = join([posfname,str_m],"_m="); 4 | posfname = join([posfname,str_n],"_n="); 5 | posfname = join(['positions',posfname,'dat'],"."); 6 | fileID = fopen(posfname,'w'); 7 | % HEADER of positions.dat 8 | fprintf(fileID,'%i %i\n',nat1,nat2); 9 | fprintf(fileID,'%2.4f\n',theta); 10 | fprintf(fileID,'%2.4f\n',strain); 11 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',cell(1,1:2), 0.0); 12 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',cell(2,1:2), 0.0); 13 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',0.0, 0.0,40); 14 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',alatL(1,1:2), 0.0); 15 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',alatL(2,1:2), 0.0); 16 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',0.0, 0.0,40); 17 | for k = 1:nat1 18 | %d1(k) = 1.0-delta*rlri1(k); 19 | fprintf(fileID,'%s %i %4.6f %4.6f %4.6f\n',id1(k),1,pos(k,1),pos(k,2),pos(k,3)); 20 | end 21 | 22 | % Top layer 23 | for k = 1:nat2 24 | %d2(k) = dmin+delta*rlri2(k); 25 | fprintf(fileID,'%s %i %4.6f %4.6f %4.6f\n',id2(k),2,pos2(k,1),pos2(k,2),pos2(k,3)); 26 | end 27 | fclose(fileID); 28 | end 29 | -------------------------------------------------------------------------------- /ASG/heterobilayer/twisted/write_pot.m: -------------------------------------------------------------------------------- 1 | function write_pot(nat1,nat2,filename,id1,id2,id11,id12,id13,id21,id22,id23,pot_11,pot_12,pot_13,pot_21,pot_22,pot_23,pos,pos2,str_m,str_n,str_theta) 2 | filename = join([filename,str_theta],"_theta="); 3 | filename = join([filename,str_m],"_m="); 4 | filename = join([filename,str_n],"_n="); 5 | 6 | disp(' ') 7 | msg = ['Generating potential.dat']; 8 | disp(msg) 9 | disp(' ') 10 | 11 | potfname = 'potential'; 12 | potfname = join([potfname,filename,'dat'],"."); 13 | fileID = fopen(potfname,'w'); 14 | % Bottom layer 15 | for k = 1:nat1 16 | if (id1(k) == id11) 17 | fprintf(fileID,'%2.4f\n',pot_11); 18 | elseif (id1(k) == id12) 19 | fprintf(fileID,'%2.4f\n',pot_12); 20 | elseif (id1(k) == id13) 21 | fprintf(fileID,'%2.4f\n',pot_13); 22 | end 23 | end 24 | 25 | % Top layer 26 | for k = 1:nat2 27 | if (id2(k) == id21) 28 | fprintf(fileID,'%2.4f\n',pot_21); 29 | elseif (id2(k) == id22) 30 | fprintf(fileID,'%2.4f\n',pot_22); 31 | elseif (id2(k) == id23) 32 | fprintf(fileID,'%2.4f\n',pot_23); 33 | end 34 | end 35 | fclose(fileID); 36 | end 37 | -------------------------------------------------------------------------------- /ASG/heterobilayer/twisted/write_xsf.m: -------------------------------------------------------------------------------- 1 | function write_xsf(nat1,nat2,filename,alatL,c,at_num1,at_num2,pos,pos2,str_m,str_n,str_theta) 2 | 3 | xsffname = join([filename,str_theta],"_theta="); 4 | xsffname = join([xsffname,str_m],"_m="); 5 | xsffname = join([xsffname,str_n],"_n="); 6 | 7 | xsffname = join([xsffname "xsf"],"."); 8 | fileID = fopen(xsffname,'w'); 9 | disp(' ') 10 | msg=['Writing xsf coordinates into output file:',xsffname]; 11 | disp(msg) 12 | % HEADER of XSF file 13 | fprintf(fileID,' %s\n','CRYSTAL'); 14 | fprintf(fileID,' %s\n','PRIMVEC'); 15 | fprintf(fileID,' % 12.10f % 12.10f % 12.10f\n',alatL(1,1), alatL(1,2), 0.0); 16 | fprintf(fileID,' % 12.10f % 12.10f % 12.10f\n',alatL(2,1), alatL(2,2), 0.0); 17 | fprintf(fileID,' % 12.10f % 12.10f % 12.10f\n',0.0, 0.0, 5*c); 18 | fprintf(fileID,' %s\n','CONVVEC'); 19 | fprintf(fileID,' %4.10f %4.10f %4.10f\n',alatL(1,1), alatL(1,2), 0.0); 20 | fprintf(fileID,' %4.10f %4.10f %4.10f\n',alatL(2,1), alatL(2,2), 0.0); 21 | fprintf(fileID,' %4.10f %4.10f %4.10f\n',0.0, 0.0, 5*c); 22 | fprintf(fileID,' %s\n','PRIMCOORD'); 23 | fprintf(fileID,'\t%i\t%i\n',nat1+nat2,1); 24 | % Bottom layer first 25 | for k = 1:nat1 26 | fprintf(fileID,' %i %4.6f %4.6f %4.6f\n',at_num1(k),pos(k,1),pos(k,2),pos(k,3)); 27 | end 28 | 29 | % Top layer 30 | for k = 1:nat2 31 | fprintf(fileID,' %i %4.6f %4.6f %4.6f\n',at_num2(k),pos2(k,1),pos2(k,2),pos2(k,3)); 32 | end 33 | fclose(fileID); 34 | end 35 | -------------------------------------------------------------------------------- /ASG/heterobilayer/twisted/write_xyz.m: -------------------------------------------------------------------------------- 1 | function write_xyz(nat1,nat2,filename,id1,id2,pos,pos2,str_m,str_n,str_theta) 2 | filename = join([filename,str_theta],"_theta="); 3 | filename = join([filename,str_m],"_m="); 4 | filename = join([filename,str_n],"_n="); 5 | 6 | xyzfname = join([filename,"xyz"],"."); 7 | fileID = fopen(xyzfname,'w'); 8 | 9 | disp(' ') 10 | msg=['Writing xyz coordinates into file:',xyzfname]; 11 | disp(msg) 12 | % HEADER of XYZ file 13 | fprintf(fileID,'%i\n',nat1+nat2); 14 | fprintf(fileID,'%s\n',''); 15 | % Bottom layer first 16 | for k1 = 1:nat1 17 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k1),pos(k1,1),pos(k1,2),pos(k1,3)); 18 | end 19 | % Then top layer 20 | for k2 = 1:nat2 21 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id2(k2),pos2(k2,1),pos2(k2,2),pos2(k2,3)); 22 | end 23 | fclose(fileID); 24 | end 25 | -------------------------------------------------------------------------------- /ASG/heterobilayer/untwisted/generate_structure.m: -------------------------------------------------------------------------------- 1 | function [nat,nat1,nat2,pos,pos2,id1,id2,at_num1,at_num2] = generate_structure(a,u,c,I,Rtheta,ncell,alat1,ialatL,tol,pos,pos2,id1,id2,id11,id12,id13,id21,id22,id23,at_num1,at_num2,at_num11,at_num12,at_num13,at_num21,at_num22,at_num23,layer1,layer2) 2 | 3 | k1=0; 4 | if(layer1 == "TMD" ) 5 | for nj = -ncell:ncell 6 | for ni = -ncell:ncell 7 | r1 = ni*alat1(:,1) + nj*alat1(:,2); 8 | r2 = [ r1(1); r1(2)+a/sqrt(3)]; 9 | r3 = r2; 10 | l1 = ialatL*r1; 11 | l2 = ialatL*r2; 12 | % Check if atom coordinates is in moire cell 13 | if (l1(1) < (1-tol) && l1(1) >= -tol && l1(2) < (1-tol) && l1(2) >= -tol) 14 | k1 = k1 + 1; 15 | pos(k1,1)=r1(1); 16 | pos(k1,2)=r1(2); 17 | pos(k1,3)=0.25*c; 18 | id1(k1) = id11; 19 | at_num1(k1) = at_num11; 20 | lprint1(k1) = true; 21 | end 22 | if (l2(1) < (1-tol) && l2(1) >= -tol && l2(2) < (1-tol) && l2(2) >= -tol) 23 | k1 = k1 + 1; 24 | pos(k1,1)=r2(1); 25 | pos(k1,2)=r2(2); 26 | pos(k1,3)= -(0.5-u)*c; 27 | id1(k1) = id12; 28 | at_num1(k1) = at_num12; 29 | lprint1(k1) = true; 30 | k1 = k1 + 1; 31 | pos(k1,1)=r3(1); 32 | pos(k1,2)=r3(2); 33 | pos(k1,3)= (1-u)*c; 34 | id1(k1) = id13; 35 | at_num1(k1) = at_num13; 36 | lprint1(k1) = true; 37 | end 38 | end 39 | end 40 | elseif(layer1 == "graphene") 41 | for nj = -ncell:ncell 42 | for ni = -ncell:ncell 43 | r1 = ni*alat1(:,1) + nj*alat1(:,2); 44 | r2 = [ r1(1); r1(2)+a/sqrt(3)]; 45 | l1 = ialatL*r1; 46 | l2 = ialatL*r2; 47 | % Check if atom coordinates is in moire cell 48 | if (l1(1) < (1-tol) && l1(1) >= -tol && l1(2) < (1-tol) && l1(2) >= -tol) 49 | k1 = k1 + 1; 50 | pos(k1,1)=r1(1); 51 | pos(k1,2)=r1(2); 52 | pos(k1,3)=1.0; 53 | id1(k1) = id11; 54 | at_num1(k1) = at_num11; 55 | lprint1(k1) = true; 56 | end 57 | if (l2(1) < (1-tol) && l2(1) >= -tol && l2(2) < (1-tol) && l2(2) >= -tol) 58 | k1 = k1 + 1; 59 | pos(k1,1)=r2(1); 60 | pos(k1,2)=r2(2); 61 | pos(k1,3)=1.0; 62 | id1(k1) = id12; 63 | at_num1(k1) = at_num12; 64 | lprint1(k1) = true; 65 | end 66 | end 67 | end 68 | end 69 | nat1 = k1; 70 | 71 | % Top layer 72 | k2 = 0; 73 | if(layer2 == "TMD") 74 | for ni=-ncell:ncell 75 | for nj = -ncell:ncell 76 | r1 = ni*alat1(:,1) + nj*alat1(:,2); 77 | r2 = [r1(1); r1(2)+a/sqrt(3)]; 78 | rr1 = I*Rtheta*r1; 79 | rr2 = I*Rtheta*r2; 80 | rr3 = rr2; 81 | 82 | l1 = ialatL*rr1; 83 | l2 = ialatL*rr2; 84 | % Check atom belongs to moirè cell within small 85 | % tollerance 86 | if (l1(1) < (1-tol) && l1(1) >= -tol && l1(2) < (1-tol) && l1(2) >= -tol) 87 | k2 = k2 + 1; 88 | pos2(k2,1) = rr1(1); 89 | pos2(k2,2) = rr1(2); 90 | pos2(k2,3) = 0.75*c; 91 | id2(k2) = id21; 92 | at_num2(k2) = at_num21; 93 | lprint2(k2) = true; 94 | 95 | end 96 | if (l2(1) < (1-tol) && l2(1) >= -tol && l2(2) < (1-tol) && l2(2) >= -tol) 97 | k2 = k2 + 1; 98 | pos2(k2,1) = rr2(1); 99 | pos2(k2,2) = rr2(2); 100 | pos2(k2,3) = u*c; 101 | id2(k2) = id22; 102 | at_num2(k2) = at_num22; 103 | lprint2(k2) = true; 104 | k2 = k2 + 1; 105 | pos2(k2,1) = rr3(1); 106 | pos2(k2,2) = rr3(2); 107 | pos2(k2,3) = (1.5-u)*c; 108 | id2(k2) = id23; 109 | at_num2(k2) = at_num23; 110 | lprint2(k2) = true; 111 | end 112 | end 113 | end 114 | elseif(layer2 == "graphene") 115 | for ni=-ncell:ncell 116 | for nj = -ncell:ncell 117 | r1 = ni*alat1(:,1) + nj*alat1(:,2); 118 | r2 = [r1(1); r1(2)+a/sqrt(3)]; 119 | rr1= I*Rtheta*r1; 120 | rr2 = I*Rtheta*r2; 121 | 122 | l1 = ialatL*rr1; 123 | l2 = ialatL*rr2; 124 | % Check atom belongs to moirè cell within small 125 | % tollerance 126 | if (l1(1) < (1-tol) && l1(1) >= -tol && l1(2) < (1-tol) && l1(2) >= -tol) 127 | k2 = k2 + 1; 128 | pos2(k2,1) = rr1(1); 129 | pos2(k2,2) = rr1(2); 130 | pos2(k2,3) = 1.0+c; 131 | id2(k2) = id21; 132 | at_num2(k2) = at_num21; 133 | lprint2(k2) = true; 134 | 135 | end 136 | if (l2(1) < (1-tol) && l2(1) >= -tol && l2(2) < (1-tol) && l2(2) >= -tol) 137 | k2 = k2 + 1; 138 | pos2(k2,1) = rr2(1); 139 | pos2(k2,2) = rr2(2); 140 | pos2(k2,3) = 1.0+c; 141 | id2(k2) = id22; 142 | at_num2(k2) = at_num22; 143 | lprint2(k2) = true; 144 | end 145 | end 146 | end 147 | end 148 | 149 | nat2 = k2; 150 | nat = nat1 + nat2; 151 | end 152 | -------------------------------------------------------------------------------- /ASG/heterobilayer/untwisted/main.m: -------------------------------------------------------------------------------- 1 | % INPUT FILES 2 | % Here we probably want a table of possible approximants 3 | theta = 0.0; 4 | n=25 ; 5 | m=24 ; 6 | a = 3.183;%/sqrt(3); 7 | u = 0.621; 8 | c = 12.32; 9 | layer1='TMD' 10 | layer2='TMD'; 11 | 12 | % Info for writing Cartesian coordinates and potential to file 13 | write_positions = true; 14 | write_potential = true; 15 | write_cart = true; 16 | % Whether to XYZ or XSF format 17 | plot_f = 'xyz'; 18 | write_lammps_input = false; 19 | 20 | % Atomic symbol of each atomic species 21 | id11 ="Mo";%'Mo'; 22 | id12 ="S";%'S'; 23 | id13 ="S";%'S'; 24 | id21 ="Mo";%'W'; 25 | id22 ="Se";%'Se'; 26 | id23 ="Se";%'Se'; 27 | % Atomic number of each species (used in XSF file) 28 | at_num11 = 42 ;%42; 29 | at_num12 = 16 ;%16; 30 | at_num13 = 16 ;%16; 31 | at_num21 = 42 ;%74; 32 | at_num22 = 34 ;%34; 33 | at_num23 = 34 ;%34; 34 | 35 | % Mass of each atomic species in a.u. (used in LAMMPS input file) 36 | mass_1 =95.94; 37 | mass_2 =32.06; 38 | mass_3 =95.94;%183.84; 39 | mass_4 =78.96; 40 | 41 | % Potential for each atomic species 42 | pot_11 = 3.34; 43 | pot_12 = -1.40; 44 | pot_13 = -1.40; 45 | pot_21 = 0.0; 46 | pot_22 = 0.0; 47 | pot_23 = 0.0; 48 | 49 | write_kpath = true; 50 | path = 'KGMKp'; 51 | init_kpts = 15; 52 | 53 | % SOME PARAMETERS 54 | 55 | str_theta = num2str(theta); 56 | if(layer1=="TMD") 57 | f1 = join([id11,id12,"2"],""); 58 | else 59 | f1 = join([id11,id12],""); 60 | end 61 | if(layer2=="TMD") 62 | f2 = join([id21,id22,"2"],""); 63 | else 64 | f2 = join([id21,id22],""); 65 | end 66 | filename = join([f1,f2],"_on_"); 67 | filename = join([filename,str_theta],"_theta="); 68 | 69 | if(layer1=="TMD" && layer2=="TMD") 70 | comb = 1; 71 | elseif(layer1=="graphene" && layer2=="graphene") 72 | comb = 2; 73 | elseif((layer1=="graphene" && layer2=="TMD")) 74 | comb = 3; 75 | elseif (layer2=="graphene" && layer1=="TMD") 76 | comb = 4; 77 | end 78 | 79 | theta= theta*pi/180; 80 | str_m = num2str(m); 81 | str_n = num2str(n); 82 | st=sin(theta); 83 | ct=cos(theta); 84 | 85 | Rtheta = [ct -st; st ct]; 86 | M = eye(2); 87 | chi = m/n; 88 | expansion = chi; %56/55;%ahBN/a; 89 | M = M*(expansion); 90 | alat1 = [1 0.5; 0 sqrt(3)/2]*a 91 | alat2 = M*Rtheta*alat1 92 | 93 | alatL = (eye(2) - inv(Rtheta)*inv(M))\alat1'; 94 | ialatL = inv(alatL'); 95 | intL1 = alatL/(alat1') 96 | intL2 = alatL/(alat2') 97 | if (any(abs(intL2 - round(intL2))>0.001)) 98 | error('Wrong moirè lattice vectors') 99 | end 100 | 101 | tnat=100; 102 | corr_nat = num_atoms(int64(m),int64(n),int64(comb)); 103 | pos=zeros(corr_nat,3); 104 | pos2=zeros(corr_nat,3); 105 | pos(:,:) = -99999; 106 | pos2(:,:) = -99999; 107 | id1(1,1:corr_nat) = "X"; 108 | id2(1,1:corr_nat) = "X"; 109 | % Array containing the atoms' numbers 110 | at_num1(1,1:corr_nat) = 0; 111 | at_num2(1,1:corr_nat) = 0; 112 | 113 | delta = 1*10^(-5); 114 | 115 | [nat,nat1,nat2,pos,pos2,id1,id2,at_num1,at_num2]=generate_structure(a,u,c,M,Rtheta,tnat,alat1,ialatL,delta,pos,pos2,id1,id2,id11,id12,id13,id21,id22,id23,at_num1,at_num2,at_num11,at_num12,at_num13,at_num21,at_num22,at_num23,layer1,layer2); 116 | 117 | disp('done') 118 | % %Check number of atoms is correct 119 | % %if (nat ~= corr_nat) 120 | % % msg = ['Number of atoms is incorrect. Expected ',num2str(corr_nat),' found ',num2str(nat)]; 121 | % % disp(msg) 122 | % % error('Error') 123 | % %else 124 | % % msg = ['Number of atoms is correct : ', num2str(nat)]; 125 | % % disp(msg) 126 | % %end 127 | 128 | % Generate reciprocal lattice 129 | if (write_kpath) 130 | msg = ['Generating kpoint grid for moirè lattice ',num2str(theta*180/pi),' ...']; 131 | disp(msg) 132 | % Generate reciprocal lattice 133 | recL = 2*pi*inv(alatL'); 134 | irecL = inv(recL); 135 | trecL = recL'; 136 | ralat1 = 2*pi*inv(alat1'); 137 | ralat2 = 2*pi*inv(alat2'); 138 | write_kpts(init_kpts,ralat2,recL,str_theta,str_m,str_n,path,2) 139 | disp('done') 140 | end 141 | 142 | pos = pos(1:nat1,:); 143 | pos2 = pos2(1:nat2,:); 144 | id1 = id1(1,1:nat1); 145 | id2 = id2(1,1:nat2); 146 | 147 | %%%% WRITE POSITION FILE FOR TB_FREE.X %%%% 148 | if (write_positions) 149 | write_pos(nat1,nat2,filename,alatL,c,id1,id2,pos,pos2,str_m,str_n,str_theta) 150 | end 151 | 152 | %%%% WRITE POTENTIAL FILE FOR TB_FREE.X %%%% 153 | if (write_potential) 154 | write_pot(nat1,nat2,filename,id1,id2,id11,id12,id13,id21,id22,id23,pot_11,pot_12,pot_13,pot_21,pot_22,pot_23,pos,pos2,str_m,str_n,str_theta) 155 | end 156 | 157 | %%%% WRITE COORDINATES FILE %%%% 158 | if(write_cart) 159 | if (plot_f=='xyz') 160 | write_xyz(nat1,nat2,filename,id1,id2,pos,pos2,str_m,str_n,str_theta) 161 | elseif (plot_f=='xsf') 162 | write_xsf(nat1,nat2,filename,alatL,c,at_num1,at_num2,pos,pos2,str_m,str_n,str_theta) 163 | end 164 | end 165 | 166 | %%%% WRITE LAMMPS INPUT FILE %%%% 167 | if (write_lammps_input) 168 | m(1) = mass_1; 169 | m(2) = mass_2; 170 | m(3) = mass_3; 171 | m(4) = mass_4; 172 | 173 | write_lammps(nat1,nat2,filename,alatL,c,ntype,m,id1,id2,id11,id12,id13,id21,id22,id23,pos,pos2,str_m,str_n,str_theta) 174 | end 175 | 176 | function y = num_atoms(m,n,c) 177 | if ~isinteger(m) 178 | error('First imput must be an integer (m)') 179 | end 180 | if ~isinteger(n) 181 | error('Second imput must be an integer (n)') 182 | end 183 | if ~isinteger(c) 184 | error('Third imput must be an integer (c)') 185 | elseif c< -1 || c > 4 || c==0 186 | error('c must be equal to: 1 or 2 or 3 or 4') 187 | end 188 | 189 | if (c==1) 190 | y = 3*(n^2) +3*(m^2); 191 | elseif (c==2) 192 | y = 2*(n^2) + 2*(m^2); 193 | elseif (c==3) 194 | y = 2*(n^2) + 3*(m^2); 195 | elseif (c==3) 196 | y = 3*(n^2) + 2*(m^2); 197 | end 198 | 199 | end 200 | -------------------------------------------------------------------------------- /ASG/heterobilayer/untwisted/write_lammps.m: -------------------------------------------------------------------------------- 1 | function write_lammps(nat1,nat2,filename,alatL,c,ntype,m,id1,id2,id11,id12,id13,id21,id22,id23,pos,pos2,str_m,str_n,str_theta) 2 | filename = join([filename,str_theta],"_theta="); 3 | filename = join([filename,str_m],"_m="); 4 | filename = join([filename,str_n],"_n="); 5 | lammpsfname = 'lammps_positions'; 6 | lammpsfname = join([lammpsfname,filename,'dat'],"."); 7 | fileID = fopen(lammpsfname,'w'); 8 | % HEADER of positions.dat 9 | phi=acos(alatL(1,1)/norm(alatL(1,:))); 10 | cf=cos(-phi); 11 | sf=sin(-phi); 12 | Rphi=[cf -sf; sf cf]; 13 | rot_alatL = Rphi*alatL'; 14 | rot_pos = Rphi*pos(:,1:2)'; 15 | rot_pos2 = Rphi*pos2(:,1:2)'; 16 | fprintf(fileID,'%s\n','LAMMPS data file from TBLG_cell.m'); 17 | fprintf(fileID,'\n'); 18 | fprintf(fileID,'%i %s\n',nat1+nat2,'atoms'); 19 | fprintf(fileID,'\n'); 20 | fprintf(fileID,'%i %s\n',ntype,'atom types'); 21 | fprintf(fileID,'\n'); 22 | fprintf(fileID,'%8.8f %8.8f %s\n',0.0, rot_alatL(1,1), 'xlo xhi'); 23 | fprintf(fileID,'%8.8f %8.8f %s\n',0.0, rot_alatL(2,2), 'ylo yhi'); 24 | fprintf(fileID,'%8.8f %8.8f %s\n',0.0,10*c,'zlo zhi'); 25 | fprintf(fileID,'%8.8f %8.8f %8.8f %s\n', rot_alatL(1,2), 0.0, 0.0, 'xy xz yz'); 26 | fprintf(fileID,'\n'); 27 | fprintf(fileID,'%s\n','Masses'); 28 | fprintf(fileID,'\n'); 29 | for i = 1 : ntype 30 | fprintf(fileID,'%i %2.2f\n',i,m(i)); 31 | end 32 | fprintf(fileID,'\n'); 33 | fprintf(fileID,'%s\n','Atoms'); 34 | fprintf(fileID,'\n'); 35 | i = 1; 36 | for k = 1:nat1 37 | if (id1(k) == id11) 38 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k,1,rot_pos(1,k),rot_pos(2,k),pos(k,3)); 39 | elseif (id1(k) == id12 || id1(k) == id13) 40 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k,2,rot_pos(1,k),rot_pos(2,k),pos(k,3)); 41 | end 42 | end 43 | 44 | i = 1; 45 | for k = 1:nat2 46 | if (id2(k) == id21) 47 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',nat1+k,3,rot_pos2(1,k),rot_pos2(2,k),pos2(k,3)); 48 | elseif (id2(k) == id22 || id2(k) == id23) 49 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',nat1+k,4,rot_pos2(1,k),rot_pos2(2,k),pos2(k,3)); 50 | end 51 | end 52 | 53 | fclose(fileID); 54 | end 55 | -------------------------------------------------------------------------------- /ASG/heterobilayer/untwisted/write_pos.m: -------------------------------------------------------------------------------- 1 | function write_pos(nat1,nat2,filename,alatL,c,id1,id2,pos,pos2,str_m,str_n,str_theta) 2 | posfname = join([filename,str_theta],"_theta="); 3 | posfname = join([posfname,str_m],"_m="); 4 | posfname = join([posfname,str_n],"_n="); 5 | posfname = join(['positions',filename,'dat'],"."); 6 | fileID = fopen(posfname,'w'); 7 | % HEADER of positions.dat 8 | fprintf(fileID,'%i\n',nat1+nat2); 9 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',alatL(1,1:2), 0.0); 10 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',alatL(2,1:2), 0.0); 11 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',0.0, 0.0,1000*c); 12 | fprintf(fileID,'%i %i\n',nat1,nat2); 13 | for k = 1:nat1 14 | %d1(k) = 1.0-delta*rlri1(k); 15 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k),pos(k,1),pos(k,2),pos(k,3)); 16 | end 17 | 18 | % Top layer 19 | for k = 1:nat2 20 | %d2(k) = dmin+delta*rlri2(k); 21 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id2(k),pos2(k,1),pos2(k,2),pos2(k,3)); 22 | end 23 | fclose(fileID); 24 | end 25 | -------------------------------------------------------------------------------- /ASG/heterobilayer/untwisted/write_pot.m: -------------------------------------------------------------------------------- 1 | function write_pot(nat1,nat2,filename,id1,id2,id11,id12,id13,id21,id22,id23,pot_11,pot_12,pot_13,pot_21,pot_22,pot_23,pos,pos2,str_m,str_n,str_theta) 2 | filename = join([filename,str_theta],"_theta="); 3 | filename = join([filename,str_m],"_m="); 4 | filename = join([filename,str_n],"_n="); 5 | 6 | disp(' ') 7 | msg = ['Generating potential.dat']; 8 | disp(msg) 9 | disp(' ') 10 | 11 | potfname = 'potential'; 12 | potfname = join([potfname,filename,'dat'],"."); 13 | fileID = fopen(potfname,'w'); 14 | % Bottom layer 15 | for k = 1:nat1 16 | if (id1(k) == id11) 17 | fprintf(fileID,'%2.4f\n',pot_11); 18 | elseif (id1(k) == id12) 19 | fprintf(fileID,'%2.4f\n',pot_12); 20 | elseif (id1(k) == id13) 21 | fprintf(fileID,'%2.4f\n',pot_13); 22 | end 23 | end 24 | 25 | % Top layer 26 | for k = 1:nat2 27 | if (id2(k) == id21) 28 | fprintf(fileID,'%2.4f\n',pot_21); 29 | elseif (id2(k) == id22) 30 | fprintf(fileID,'%2.4f\n',pot_22); 31 | elseif (id2(k) == id23) 32 | fprintf(fileID,'%2.4f\n',pot_23); 33 | end 34 | end 35 | fclose(fileID); 36 | end 37 | -------------------------------------------------------------------------------- /ASG/heterobilayer/untwisted/write_xsf.m: -------------------------------------------------------------------------------- 1 | function write_xsf(nat1,nat2,filename,alatL,c,at_num1,at_num2,pos,pos2,str_m,str_n,str_theta) 2 | 3 | xsffname = join([filename,str_theta],"_theta="); 4 | xsffname = join([xsffname,str_m],"_m="); 5 | xsffname = join([xsffname,str_n],"_n="); 6 | 7 | xsffname = join([xsffname "xsf"],"."); 8 | fileID = fopen(xsffname,'w'); 9 | disp(' ') 10 | msg=['Writing xsf coordinates into output file:',xsffname]; 11 | disp(msg) 12 | % HEADER of XSF file 13 | fprintf(fileID,' %s\n','CRYSTAL'); 14 | fprintf(fileID,' %s\n','PRIMVEC'); 15 | fprintf(fileID,' % 12.10f % 12.10f % 12.10f\n',alatL(1,1), alatL(1,2), 0.0); 16 | fprintf(fileID,' % 12.10f % 12.10f % 12.10f\n',alatL(2,1), alatL(2,2), 0.0); 17 | fprintf(fileID,' % 12.10f % 12.10f % 12.10f\n',0.0, 0.0, 5*c); 18 | fprintf(fileID,' %s\n','CONVVEC'); 19 | fprintf(fileID,' %4.10f %4.10f %4.10f\n',alatL(1,1), alatL(1,2), 0.0); 20 | fprintf(fileID,' %4.10f %4.10f %4.10f\n',alatL(2,1), alatL(2,2), 0.0); 21 | fprintf(fileID,' %4.10f %4.10f %4.10f\n',0.0, 0.0, 5*c); 22 | fprintf(fileID,' %s\n','PRIMCOORD'); 23 | fprintf(fileID,'\t%i\t%i\n',nat1+nat2,1); 24 | % Bottom layer first 25 | for k = 1:nat1 26 | fprintf(fileID,' %i %4.6f %4.6f %4.6f\n',at_num1(k),pos(k,1),pos(k,2),pos(k,3)); 27 | end 28 | 29 | % Top layer 30 | for k = 1:nat2 31 | fprintf(fileID,' %i %4.6f %4.6f %4.6f\n',at_num2(k),pos2(k,1),pos2(k,2),pos2(k,3)); 32 | end 33 | fclose(fileID); 34 | end 35 | -------------------------------------------------------------------------------- /ASG/heterobilayer/untwisted/write_xyz.m: -------------------------------------------------------------------------------- 1 | function write_xyz(nat1,nat2,filename,id1,id2,pos,pos2,str_m,str_n,str_theta) 2 | filename = join([filename,str_theta],"_theta="); 3 | filename = join([filename,str_m],"_m="); 4 | filename = join([filename,str_n],"_n="); 5 | 6 | xyzfname = join([filename,"xyz"],"."); 7 | fileID = fopen(xyzfname,'w'); 8 | 9 | disp(' ') 10 | msg=['Writing xyz coordinates into file:',xyzfname]; 11 | disp(msg) 12 | % HEADER of XYZ file 13 | fprintf(fileID,'%i\n',nat1+nat2); 14 | fprintf(fileID,'%s\n',''); 15 | % Bottom layer first 16 | for k1 = 1:nat1 17 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k1),pos(k1,1),pos(k1,2),pos(k1,3)); 18 | end 19 | % Then top layer 20 | for k2 = 1:nat2 21 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id2(k2),pos2(k2,1),pos2(k2,2),pos2(k2,3)); 22 | end 23 | fclose(fileID); 24 | end 25 | -------------------------------------------------------------------------------- /ASG/homobilayer/twisted/TBLG_cell.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % 3 | % Computes the moire cell for twisted bilayer graphene (TBLG) given two 4 | % integers n and m. Here, we assume that m=n+1. 5 | % 6 | % It generates five output files: 7 | % 1) XYZ or XSF file for visualization 8 | % 2) .dat file that is used as input file for TB_free.x 9 | % 3) kpoints.in file to be used as input for TB_free.x 10 | % 4) kpaths.dat file to be used for plotting the band structure on the 11 | % chosen path in k-space 12 | % 5) lammps geometry file 13 | % 14 | % It returns the xyz coordinates of bottom layer (pos) and top layer (pos2) 15 | % and the total number of atoms (nat). 16 | % 17 | % Note: To compute the LRI for a given structure you need to uncomment the 18 | % relative lines 19 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 20 | function [nat,pos,pos2] = TBLG_cell(n, a, z, plot_f, kpath, nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase) 21 | % Setting parameters 22 | m=n+1; 23 | theta = acos((n^2 + 4*n*m + m^2)/(2*(n^2 + n*m + m^2))); 24 | 25 | filename = "tBLG"; 26 | 27 | % total number of atoms in Moire cell 28 | tot_nat= 4*(n^2 + n*m + m^2); 29 | 30 | % Compute Moire supercell 31 | st=sin(theta); 32 | ct=cos(theta); 33 | Rtheta = [ct -st; st ct]; 34 | % Lattice vectors of top and bottom layer 35 | ualat1 = a*[sqrt(3)/2, sqrt(3)/2; -0.5,0.5]; 36 | Rphi = [cos(pi/6) -sin(pi/6); sin(pi/6) cos(pi/6)]; 37 | alat1 = Rphi*ualat1; 38 | alat2 = Rtheta*alat1; 39 | % Lattice vectors of Moire cell 40 | alatL = [n, m; -m, n+m]*alat1'; 41 | ialatL = inv(alatL'); 42 | 43 | % Generate reciprocal lattice vectors 44 | recL = 2*pi*inv(alatL'); 45 | irecL = inv(recL); 46 | trecL = recL'; 47 | ralat1 = 2*pi*inv(alat1'); 48 | ralat2 = 2*pi*inv(alat2'); 49 | 50 | % Print k-point grid/path to file 51 | theta = theta*180/pi; 52 | str_theta = num2str(theta); 53 | str_m = num2str(m); 54 | str_n = num2str(n); 55 | if (write_kpath) 56 | msg = ['Generating kpoint grid for moirè lattice with a twist angle of ',str_theta,' ...']; 57 | disp(msg) 58 | disp(' ') 59 | write_kpts(nk,ralat1,recL,str_theta,str_m,str_n,kpath,1); 60 | disp(' ') 61 | disp('... done') 62 | end 63 | 64 | % number of supercell for the search 65 | period = norm(alatL,1); 66 | tnat = floor(period/a) 67 | pos = zeros(tot_nat/2,3); 68 | pos2 = zeros(tot_nat/2,3); 69 | pos(:) = -99999; 70 | pos2(:) = -99999; 71 | % tollerance to check atomic coordinates 72 | delta = 1.0*10^(-5); 73 | 74 | disp(' ') 75 | msg = ['Generating Cartesian atomic coordinates for moirè lattice with a twist angle of ',str_theta,' ...']; 76 | disp(msg) 77 | 78 | k1=1; 79 | k2=1; 80 | for nj = -3*tnat:3*tnat 81 | for ni = -3*tnat:3*tnat 82 | r1 = ni*alat1(:,1) + nj*alat1(:,2); 83 | r2 = r1 + 1/3*alat1(:,1) + 1/3*alat1(:,2); 84 | l1 = ialatL*r1; 85 | l2 = ialatL*r2; 86 | if (l1(1) < (1-delta) && l1(1) >= -delta && l1(2) < (1-delta) && l1(2) >= -delta) 87 | pos(k1,1)=r1(1); 88 | pos(k1,2)=r1(2); 89 | pos(k1,3)=1; 90 | k1 = k1 + 1; 91 | end 92 | if (l2(1) < (1-delta) && l2(1) >= -delta && l2(2) < (1-delta) && l2(2) >= -delta) 93 | pos(k1,1)=r2(1); 94 | pos(k1,2)=r2(2); 95 | pos(k1,3)=1; 96 | k1 = k1 + 1; 97 | end 98 | if(phase=='AA') 99 | r1r = Rtheta*r1; 100 | r2r = Rtheta*r2; 101 | elseif(phase=='AB') 102 | r1r = Rtheta*(-r1+1/3*alat1(:,1)+1/3*alat1(:,2)); 103 | r2r = Rtheta*(-r2+1/3*alat1(:,1)+1/3*alat1(:,2));%[r2 + 2/3*alat1(:,1) + 2/3*alat1(:,2)]; 104 | end 105 | l1 = ialatL*r1r; 106 | l2 = ialatL*r2r; 107 | if (l1(1) < (1-delta) && l1(1) >= -delta && l1(2) < (1-delta) && l1(2) >= -delta) 108 | pos2(k2,1) = r1r(1); 109 | pos2(k2,2) = r1r(2); 110 | pos2(k2,3) = 1+z; 111 | k2 = k2 + 1; 112 | end 113 | if (l2(1) < (1-delta) && l2(1) >= -delta && l2(2) < (1-delta) && l2(2) >= -delta) 114 | pos2(k2,1) = r2r(1); 115 | pos2(k2,2) = r2r(2); 116 | pos2(k2,3) = 1+z; 117 | k2 = k2 + 1; 118 | end 119 | end 120 | end 121 | 122 | nat = k1 + k2 - 2; 123 | 124 | %Check number of atoms is 4*(n^2 + n*m + m^2) 125 | if (nat ~= tot_nat) 126 | disp('Wrong number of atoms'); 127 | nat 128 | 4*(n^2 + n*m + m^2) 129 | end 130 | disp('... done') 131 | 132 | %figure 133 | rlri1 = zeros(nat/2,1); 134 | rlri2 = zeros(nat/2,1); 135 | %[rlri1,rlri2] = compLRIgraphene(pos,pos2,nat,alatL,a,false,3); 136 | 137 | if(phase=='AA') 138 | stheta = theta; 139 | elseif(phase=='AB') 140 | stheta = 60 - theta; 141 | end 142 | str_stheta = num2str(stheta); 143 | filename = join([filename,str_stheta],"_theta="); 144 | filename = join([filename,str_m],"_m="); 145 | filename = join([filename,str_n],"_n="); 146 | 147 | dmin=4.34; 148 | dmax=4.58; 149 | delta = 0.5*(dmax-dmin); 150 | d1 = zeros(nat/2,1); 151 | d1(1:nat/2) = 1.0-delta*rlri1(1:nat/2); 152 | d2 = zeros(nat/2,1); 153 | d2(1:nat/2) = dmin+delta*rlri2(1:nat/2); 154 | 155 | id1(1:nat/2) = "C"; 156 | id2(1:nat/2) = "C"; 157 | 158 | if (write_cart) 159 | if (plot_f=='xyz') 160 | write_xyz(nat,filename,alatL,id1,id2,pos,pos2) 161 | elseif (plot_f=='xsf') 162 | write_xsf(nat,filename,alatL,z,id1,id2,6,6,'C','C',pos,pos2) 163 | end 164 | end 165 | 166 | % Write positions for TB_free.x 167 | if (write_positions) 168 | write_tb(nat,filename,alatL,alat1',stheta,id1,id2,pos,pos2) 169 | end 170 | 171 | if (write_potential) 172 | potfname = 'potential'; 173 | potfname = join([potfname,filename,'dat'],"."); 174 | fileID = fopen(potfname,'w'); 175 | disp(' ') 176 | msg=['Writing potential info to be used as TB input file:',potfname]; 177 | disp(msg) 178 | 179 | % Bottom layer 180 | for k1 = 1:nat/2 181 | fprintf(fileID,'%2.4f\n',pot_11); %3.16 182 | fprintf(fileID,'%2.4f\n',pot_22);%-1.50 183 | end 184 | 185 | % Top layer 186 | for k1 = 1:nat/2 187 | fprintf(fileID,'%2.4f\n',3.48); 188 | fprintf(fileID,'%2.4f\n',-3.48); 189 | end 190 | fclose(fileID); 191 | end 192 | 193 | % Write lammps input file 194 | if (write_lammps_input) 195 | m(1) = 12.01; 196 | m(2) = 12.01; 197 | write_lammps(nat,filename,alatL,z,id1,id2,2,m,'C','C',pos,pos2) 198 | end 199 | 200 | %figure 201 | %y = compdist(pos,pos2,nat,alatL,d1,d2,true); 202 | 203 | %Compute interpolate and plot LRI 204 | end 205 | 206 | 207 | function y1 = compdist(pos,pos2,nat,alatL,d1,d2,plot) 208 | n = 0; 209 | supercell = zeros(9*size(pos,1),2); 210 | supercell2 = zeros(9*size(pos,1),2); 211 | talat = alatL'; 212 | for ni = -1 : 1 213 | for nj = -1:1 214 | for j = 1:nat/2 215 | n = n + 1; 216 | xshift = pos(j,1) + ni*talat(1,1) + nj*talat(1,2); 217 | yshift = pos(j,2) + ni*talat(2,1) + nj*talat(2,2); 218 | supercell(n,:) = [xshift,yshift]; 219 | xshift2 = pos2(j,1) + ni*talat(1,1) + nj*talat(1,2); 220 | yshift2 = pos2(j,2) + ni*talat(2,1) + nj*talat(2,2); 221 | supercell2(n,:) = [xshift2,yshift2]; 222 | end 223 | end 224 | end 225 | 226 | superd1 = zeros(9*size(nat/2,1),1); 227 | superd2 = zeros(9*size(nat/2,1),1); 228 | for i = 1 : 9 229 | superd1((i-1)*nat/2+1:i*nat/2) = d1(:); 230 | superd2((i-1)*nat/2+1:i*nat/2) = d2(:); 231 | end 232 | x = linspace(1.2*min(pos(:,1)),1.2*max(pos(:,1)),300); 233 | y = linspace(1.2*min(pos(:,2)),1.2*max(pos(:,2)),300); 234 | [X,Y] = meshgrid(x,y); 235 | f1 = scatteredInterpolant(supercell(:,1),supercell(:,2),superd1,'natural'); 236 | Z1 = f1(X,Y); 237 | f2 = scatteredInterpolant(supercell2(:,1),supercell2(:,2),superd2,'natural'); 238 | Z2 = f2(X,Y); 239 | if (plot) 240 | figure 241 | contourf(X,Y,Z2-Z1) 242 | figure 243 | surf(X,Y,Z2-Z1) 244 | shading interp 245 | end 246 | y1 = superd1; 247 | end 248 | -------------------------------------------------------------------------------- /ASG/homobilayer/twisted/main.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Script to find a set of commensurate moire lattices 3 | % and the atomic coordinates for twisted homobilayers. 4 | % The twisted bilayer is assumed to be made of 5 | % a material whose conventional cell is hexagonal, 6 | % e.g. graphene, hexagonal boron nitride (hBN) and 7 | % Transition-metal dichalcogenides (TMDs) 8 | % 9 | % 10 | % INPUT: 11 | % n - Integer parameter that defines Moire cell, 12 | % m=n+1 by default, see Ref. 1 13 | % a - lattice parameter of 2D material 14 | % c - Interlayer distance when starting 2D material 15 | % consists of a monolayer, e.g. graphene, OR 16 | % disance between central atoms of 2D material 17 | % for trilayers, e.g. distance 18 | % between transition metal atoms in the two 19 | % TMD layers. 20 | % comb - Define which combination of layers to consider 21 | % Possible choices are: 'graphene', 'hBN', 22 | % 'MoS2', 'WSe2', 'MoSe2', 'WS2' 23 | % plot_f - Format for plotting ('xyz' or 'xsf') 24 | % kpath - Path in k-space. Implemented paths are: 25 | % * K-Gamma-M-K' -> 'KMGKp' 26 | % * M-Gamma-K-M -> 'MGKM' 27 | % * Gamma-M-K-Gamma -> 'GMKG' 28 | % * Gamma-K-M -> 'GKM' 29 | % * K-M -> 'KM' 30 | % * Monkhorst-Pack -> 'uniform' 31 | % init_nk - Total number of kpoints for uniform MP grids OR 32 | % number of k-points in the first segment of the 33 | % chosen path 34 | % 35 | % OUTPUT: 36 | % .xyz(xsf) - Cartesian coordinates in XYZ 37 | % (XSF) format 38 | % positions..dat - Cartesian coordinates & 39 | % Moire lattice vectors 40 | % to be used as input file 41 | % for TB_free.x 42 | % lammps_positions..dat - Lammps geometry 43 | % file. 44 | % N.B. The Moire 45 | % cell is rotated 46 | % such as one of 47 | % the vector is 48 | % parallel to 49 | % on the x-axis 50 | % potential..dat - Potential file to be 51 | % used as input in 52 | % TB_free.x. Only for hBN 53 | % at the moment 54 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 55 | % 56 | % Written by Valerio Vitale, October 2019 57 | % 58 | % Refs. 59 | % 1) Nano Lett. 10, 3, 804-808 (2010) 60 | % 2) PRB 86, 155449 (2012) 61 | % 62 | % version 1.0 63 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 64 | 65 | % 11-band TB model PRB 92 205108 (2015) 66 | % All parameters are in Ang 67 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 68 | % a d(M-X) d(X-X) c (sqrt(d(M-X)^2-1/3*a^2)/(3/4-u)) u 69 | % MoS2 3.1824 2.41 3.13 12.29 70 | % WS2 3.1817 2.42 3.14 12.32 71 | % MoSe2 3.3174 2.54 3.34 12.90 72 | % WSe2 3.3155 2.55 3.35 12.96 73 | 74 | % Set from SW classical potential LAMMPs 75 | % All parameters are in Ang 76 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 77 | % a c u 78 | % MoS2 3.110 12.08 0.621 79 | % WS2 3.129 12.12 0.622 80 | % MoSe2 3.3096 12.84 0.621 81 | % WSe2 3.289 12.74 0.621 82 | 83 | % Parameters from our DFT calculations 84 | % All parameters are in Ang 85 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 86 | % a c u 87 | % MoS2 3.183 12.0264 0.621 88 | % WS2 3.182 12.1634 0.621 89 | % MoSe2 3.315 12.9567 0.621 90 | % WSe2 3.3145 13.0089 0.621 91 | 92 | %%%%%%%%%%%% BEGIN INPUT %%%%%%%%%%%%% 93 | % Integer for constructing Moire supercell 94 | n = 6; 95 | % Lattice parameter of monolayer 96 | a = 3.3145; % 97 | % Interlayer distance 98 | c = 13.0089/2; 99 | % Chemical symbol for monolayer 100 | comb = 'WSe2'; 101 | % Info for writing Cartesian coordinates and potential to file 102 | write_positions = true; 103 | write_potential = false; 104 | write_cart = false; 105 | % Whether to XYZ or XSF format 106 | plot_f = 'xyz'; 107 | write_lammps_input = false; 108 | % Initial phase 109 | phase = 'AA'; 110 | 111 | % Info for writing k-points and path in k-space 112 | write_kpath = false; 113 | kpath = 'GMKG'; 114 | init_nk = 10; 115 | %%%%%%%%%%%% END INPUT %%%%%%%%%%%%% 116 | 117 | switch comb 118 | case 'graphene' 119 | disp('Structure and input files for twisted bilayer graphene') 120 | disp(' ') 121 | [num,pos,pos2] = TBLG_cell(n,a,c,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 122 | case 'hBN' 123 | disp('Structure and input files for twisted bilayer hBN') 124 | disp(' ') 125 | [num,pos,pos2] = TBLhBN_cell(n,a,c,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 126 | case 'MoS2' 127 | % Atomic masses 128 | m1 = 95.94; 129 | m2 = 32.06; 130 | % Atoms info 131 | num_at1 = 42; 132 | num_at2 = 16; 133 | disp('Structure and input files for twisted bilayer MoS2') 134 | disp(' ') 135 | [num,pos,pos2] = TBLTMD_cell(n,a,c,'Mo','S',m1,m2,num_at1,num_at2,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 136 | case 'MoSe2' 137 | % Atomic masses 138 | m1 = 95.94; 139 | m2 = 78.96; 140 | % Atoms info 141 | num_at1 = 42; 142 | num_at2 = 34; 143 | disp('Structure and input files for twisted bilayer MoSe2') 144 | disp(' ') 145 | [num,pos,pos2] = TBLTMD_cell(n,a,c,'Mo','Se',m1,m2,num_at1,num_at2,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 146 | case 'WSe2' 147 | % Atomic masses 148 | m1 = 183.84; 149 | m2 = 78.96; 150 | num_at1 = 74; 151 | num_at2 = 34; 152 | disp('Generating structure and input files for twisted bilayer WSe2') 153 | disp(' ') 154 | [num,pos,pos2] = TBLTMD_cell(n,a,c,'W','Se',m1,m2,num_at1,num_at2,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 155 | case 'WS2' 156 | % Atomic masses 157 | m1 = 183.84; 158 | m2 = 32.06; 159 | num_at1 = 74; 160 | num_at2 = 16; 161 | disp('Generating structure and input files for twisted bilayer WSe2') 162 | disp(' ') 163 | [num,pos,pos2] = TBLTMD_cell(n,a,c,'W','S',m1,m2,num_at1,num_at2,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 164 | otherwise 165 | error('Material not supported. Available choices are: graphene, hBN, MoS2 and WSe2') 166 | end 167 | %end 168 | disp('Done! Have a nice day :-)') 169 | -------------------------------------------------------------------------------- /ASG/homobilayer/twisted/main_graphene.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Script to find a set of commensurate moire lattices 3 | % and the atomic coordinates for twisted homobilayers. 4 | % The twisted bilayer is assumed to be made of 5 | % a material whose conventional cell is hexagonal, 6 | % e.g. graphene, hexagonal boron nitride (hBN) and 7 | % Transition-metal dichalcogenides (TMDs) 8 | % 9 | % 10 | % INPUT: 11 | % n - Integer parameter that defines Moire cell, 12 | % m=n+1 by default, see Ref. 1 13 | % a - lattice parameter of 2D material 14 | % c - Interlayer distance when starting 2D material 15 | % consists of a monolayer, e.g. graphene, OR 16 | % disance between central atoms of 2D material 17 | % for trilayers, e.g. distance 18 | % between transition metal atoms in the two 19 | % TMD layers. 20 | % comb - Define which combination of layers to consider 21 | % Possible choices are: 'graphene', 'hBN', 22 | % 'MoS2', 'WSe2', 'MoSe2', 'WS2' 23 | % plot_f - Format for plotting ('xyz' or 'xsf') 24 | % kpath - Path in k-space. Implemented paths are: 25 | % * K-Gamma-M-K' -> 'KMGKp' 26 | % * M-Gamma-K-M -> 'MGKM' 27 | % * Gamma-M-K-Gamma -> 'GMKG' 28 | % * Gamma-K-M -> 'GKM' 29 | % * K-M -> 'KM' 30 | % * Monkhorst-Pack -> 'uniform' 31 | % init_nk - Total number of kpoints for uniform MP grids OR 32 | % number of k-points in the first segment of the 33 | % chosen path 34 | % 35 | % OUTPUT: 36 | % .xyz(xsf) - Cartesian coordinates in XYZ 37 | % (XSF) format 38 | % positions..dat - Cartesian coordinates & 39 | % Moire lattice vectors 40 | % to be used as input file 41 | % for TB_free.x 42 | % lammps_positions..dat - Lammps geometry 43 | % file. 44 | % N.B. The Moire 45 | % cell is rotated 46 | % such as one of 47 | % the vector is 48 | % parallel to 49 | % on the x-axis 50 | % potential..dat - Potential file to be 51 | % used as input in 52 | % TB_free.x. Only for hBN 53 | % at the moment 54 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 55 | % 56 | % Written by Valerio Vitale, October 2019 57 | % 58 | % Refs. 59 | % 1) Nano Lett. 10, 3, 804-808 (2010) 60 | % 2) PRB 86, 155449 (2012) 61 | % 62 | % version 1.0 63 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 64 | 65 | %%%%%%%%%%%% BEGIN INPUT %%%%%%%%%%%%% 66 | % Integer for constructing Moire supercell 67 | n = 8; 68 | % Lattice parameter of monolayer 69 | a = 2.42; % 70 | % Interlayer distance 71 | c = 3.35; 72 | % Chemical symbol for monolayer 73 | comb = 'graphene'; 74 | % Info for writing Cartesian coordinates and potential to file 75 | write_positions = true; 76 | write_potential = false; 77 | write_cart = true; 78 | % Whether to XYZ or XSF format 79 | plot_f = 'xsf'; 80 | write_lammps_input = true; 81 | % Initial phase 82 | phase = 'AB'; 83 | 84 | % Info for writing k-points and path in k-space 85 | write_kpath = true; 86 | kpath = 'GMKG'; 87 | init_nk = 10; 88 | %%%%%%%%%%%% END INPUT %%%%%%%%%%%%% 89 | 90 | switch comb 91 | case 'graphene' 92 | disp('Structure and input files for twisted bilayer graphene') 93 | disp(' ') 94 | [num,pos,pos2] = TBLG_cell(n,a,c,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 95 | case 'hBN' 96 | disp('Structure and input files for twisted bilayer hBN') 97 | disp(' ') 98 | [num,pos,pos2] = TBLhBN_cell(n,a,c,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 99 | case 'MoS2' 100 | % Atomic masses 101 | m1 = 95.94; 102 | m2 = 32.06; 103 | % Atoms info 104 | num_at1 = 42; 105 | num_at2 = 16; 106 | disp('Structure and input files for twisted bilayer MoS2') 107 | disp(' ') 108 | [num,pos,pos2] = TBLTMD_cell(n,a,c,'Mo','S',m1,m2,num_at1,num_at2,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 109 | case 'MoSe2' 110 | % Atomic masses 111 | m1 = 95.94; 112 | m2 = 78.96; 113 | % Atoms info 114 | num_at1 = 42; 115 | num_at2 = 34; 116 | disp('Structure and input files for twisted bilayer MoS2') 117 | disp(' ') 118 | [num,pos,pos2] = TBLTMD_cell(n,a,c,'Mo','Se',m1,m2,num_at1,num_at2,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 119 | case 'WSe2' 120 | % Atomic masses 121 | m1 = 183.84; 122 | m2 = 78.96; 123 | num_at1 = 74; 124 | num_at2 = 34; 125 | disp('Generating structure and input files for twisted bilayer WSe2') 126 | disp(' ') 127 | [num,pos,pos2] = TBLTMD_cell(n,a,c,'W','Se',m1,m2,num_at1,num_at2,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 128 | case 'WS2' 129 | % Atomic masses 130 | m1 = 183.84; 131 | m2 = 32.06; 132 | num_at1 = 74; 133 | num_at2 = 16; 134 | disp('Generating structure and input files for twisted bilayer WSe2') 135 | disp(' ') 136 | [num,pos,pos2] = TBLTMD_cell(n,a,c,'W','S',m1,m2,num_at1,num_at2,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 137 | otherwise 138 | error('Material not supported. Available choices are: graphene, hBN, MoS2 and WSe2') 139 | end 140 | 141 | disp('Done! Have a nice day :-)') 142 | -------------------------------------------------------------------------------- /ASG/homobilayer/twisted/write_full_xyz.m: -------------------------------------------------------------------------------- 1 | function write_xyz(nat,filename,ualat,id1,id2,pos,pos2) 2 | xyzfname = join([filename,"_full",".xyz"]); 3 | fileID = fopen(xyzfname,'w'); 4 | 5 | disp(' ') 6 | msg=['Writing xyz coordinates into file:',xyzfname]; 7 | disp(msg) 8 | % HEADER of XYZ file 9 | fprintf(fileID,'%i\n',4*nat); 10 | fprintf(fileID,'%s\n',''); 11 | % Bottom layer first 12 | for k1 = 1:nat/2 13 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k1),pos(k1,1),pos(k1,2),pos(k1,3)); 14 | end 15 | % Then top layer 16 | for k2 = 1:nat/2 17 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id2(k2),pos2(k2,1),pos2(k2,2),pos2(k2,3)); 18 | end 19 | shift = [ualat(1,:),0.0]; 20 | tpos = pos + shift.*ones(nat/2,1); 21 | for k1 = 1:nat/2 22 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k1),tpos(k1,1),tpos(k1,2),tpos(k1,3)); 23 | end 24 | tpos2 = pos2 + shift.*ones(nat/2,1); 25 | for k1 = 1:nat/2 26 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k1),tpos2(k1,1),tpos2(k1,2),tpos2(k1,3)); 27 | end 28 | shift = [ualat(2,:),0.0]; 29 | tpos = pos + shift.*ones(nat/2,1); 30 | for k1 = 1:nat/2 31 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k1),tpos(k1,1),tpos(k1,2),tpos(k1,3)); 32 | end 33 | tpos2 = pos2 + shift.*ones(nat/2,1); 34 | for k1 = 1:nat/2 35 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k1),tpos2(k1,1),tpos2(k1,2),tpos2(k1,3)); 36 | end 37 | shift = [ualat(1,:) + ualat(2,:),0.0]; 38 | tpos = pos + shift.*ones(nat/2,1); 39 | for k1 = 1:nat/2 40 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k1),tpos(k1,1),tpos(k1,2),tpos(k1,3)); 41 | end 42 | tpos2 = pos2 + shift.*ones(nat/2,1); 43 | for k1 = 1:nat/2 44 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k1),tpos2(k1,1),tpos2(k1,2),tpos2(k1,3)); 45 | end 46 | % pos = pos*Rphi'; 47 | % for k1 = 1:nat/2 48 | % fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k1),pos(k1,1),pos(k1,2),pos(k1,3)); 49 | % end 50 | % pos = pos*Rphi'; 51 | % for k1 = 1:nat/2 52 | % fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k1),pos(k1,1),pos(k1,2),pos(k1,3)); 53 | % end 54 | % pos2 = pos2*Rphi'; 55 | % for k2 = 1:nat/2 56 | % fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id2(k2),pos2(k2,1),pos2(k2,2),pos2(k2,3)); 57 | % end 58 | % pos2 = pos2*Rphi'; 59 | % for k2 = 1:nat/2 60 | % fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id2(k2),pos2(k2,1),pos2(k2,2),pos2(k2,3)); 61 | % end 62 | % pos2 = pos2*Rphi'; 63 | % for k2 = 1:nat/2 64 | % fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id2(k2),pos2(k2,1),pos2(k2,2),pos2(k2,3)); 65 | % end 66 | % pos2 = pos2*Rphi'; 67 | % for k2 = 1:nat/2 68 | % fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id2(k2),pos2(k2,1),pos2(k2,2),pos2(k2,3)); 69 | % end 70 | % pos2 = pos2*Rphi'; 71 | % for k2 = 1:nat/2 72 | % fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id2(k2),pos2(k2,1),pos2(k2,2),pos2(k2,3)); 73 | % end 74 | fclose(fileID); 75 | end 76 | -------------------------------------------------------------------------------- /ASG/homobilayer/twisted/write_lammps.m: -------------------------------------------------------------------------------- 1 | function write_lammps(nat,filename,alatL,z,id1,id2,ntype,m,c_at1,c_at2,pos,pos2) 2 | % HEADER of geometry file for lammps 3 | lammpsfname = 'lammps_positions'; 4 | lammpsfname = join([lammpsfname,filename,'dat'],"."); 5 | additionalfname = join([filename,'rotation','dat'],"."); 6 | fileID = fopen(lammpsfname,'w'); 7 | fileID2 = fopen(additionalfname,'w'); 8 | disp(' ') 9 | msg=['Writing coordinates, moire lattice info and masses into lammps input file:',lammpsfname]; 10 | disp(msg) 11 | phi=acos(alatL(1,1)/norm(alatL(1,:))); 12 | cf=cos(-phi); 13 | sf=sin(-phi); 14 | Rphi=[cf -sf 0; sf cf 0; 0 0 1]; 15 | rot_alatL = Rphi(1:2,1:2)*alatL'; 16 | rot_pos = Rphi*pos'; 17 | rot_pos2 = Rphi*pos2'; 18 | fprintf(fileID2,'%8.8f\n',phi*180/pi); 19 | fprintf(fileID2,'%8.8f %8.8f %8.8f\n',rot_alatL(:,1)); 20 | fprintf(fileID2,'%8.8f %8.8f %8.8f\n',rot_alatL(:,2)); 21 | fprintf(fileID,'%s\n','LAMMPS data file from TBLG_cell.m'); 22 | fprintf(fileID,'\n'); 23 | fprintf(fileID,'%i %s\n',nat,'atoms'); 24 | fprintf(fileID,'\n'); 25 | fprintf(fileID,'%i %s\n',ntype,'atom types'); 26 | fprintf(fileID,'\n'); 27 | fprintf(fileID,'%8.8f %8.8f %s\n',0.0, rot_alatL(1,1), 'xlo xhi'); 28 | fprintf(fileID,'%8.8f %8.8f %s\n',0.0, rot_alatL(2,2), 'ylo yhi'); 29 | fprintf(fileID,'%8.8f %8.8f %s\n',0.0,100*z,'zlo zhi'); 30 | fprintf(fileID,'%8.8f %8.8f %8.8f %s\n', rot_alatL(1,2), 0.0, 0.0, 'xy xz yz'); 31 | fprintf(fileID,'\n'); 32 | fprintf(fileID,'%s\n','Masses'); 33 | fprintf(fileID,'\n'); 34 | for i = 1 : ntype 35 | fprintf(fileID,'%i %2.2f\n',i,m(i)); 36 | end 37 | fprintf(fileID,'\n'); 38 | fprintf(fileID,'%s\n','Atoms'); 39 | fprintf(fileID,'\n'); 40 | if (ntype==2) 41 | for k = 1:nat/2 42 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k,1,rot_pos(1,k),rot_pos(2,k),rot_pos(3,k)); 43 | end 44 | for k = 1:nat/2 45 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k,2,rot_pos2(1,k),rot_pos2(2,k),rot_pos2(3,k)); 46 | end 47 | elseif (ntype==4) 48 | if (c_at1 == 'B' & c_at2 == 'N') 49 | for k1 = 1:nat/2 50 | if (id1(k1) == c_at1) 51 | fprintf(fileID,'%i %i %i %2.4f %4.6f %4.6f %4.6f\n',k1,1,1,0.42,rot_pos(1,k1),rot_pos(2,k1),rot_pos(3,k1)); 52 | elseif (id1(k1) == c_at2) 53 | fprintf(fileID,'%i %i %i %2.4f %4.6f %4.6f %4.6f\n',k1,1,2,-0.42,rot_pos(1,k1),rot_pos(2,k1),rot_pos(3,k1)); 54 | end 55 | end 56 | 57 | for k1 = 1:nat/2 58 | if (id2(k1) == c_at1) 59 | fprintf(fileID,'%i %i %i %2.4f %4.6f %4.6f %4.6f\n',nat/2+k1,2,3,0.42,rot_pos2(1,k1),rot_pos2(2,k1),rot_pos2(3,k1)); 60 | elseif (id2(k1) == c_at2) 61 | fprintf(fileID,'%i %i %i %2.4f %4.6f %4.6f %4.6f\n',nat/2+k1,2,4,-0.42,rot_pos2(1,k1),rot_pos2(2,k1),rot_pos2(3,k1)); 62 | end 63 | end 64 | else 65 | for k1 = 1:nat/2 66 | if (id1(k1) == c_at1 ) 67 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k1,1,rot_pos(1,k1),rot_pos(2,k1),rot_pos(3,k1)); 68 | elseif (id1(k1) == c_at2) 69 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k1,2,rot_pos(1,k1),rot_pos(2,k1),rot_pos(3,k1)); 70 | end 71 | end 72 | 73 | for k1 = 1:nat/2 74 | if (id2(k1) == c_at1) 75 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',nat/2+k1,3,rot_pos2(1,k1),rot_pos2(2,k1),rot_pos2(3,k1)); 76 | elseif (id2(k1) == c_at2) 77 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',nat/2+k1,4,rot_pos2(1,k1),rot_pos2(2,k1),rot_pos2(3,k1)); 78 | end 79 | end 80 | end 81 | end 82 | 83 | fclose(fileID); 84 | fclose(fileID2); 85 | end 86 | -------------------------------------------------------------------------------- /ASG/homobilayer/twisted/write_tb.m: -------------------------------------------------------------------------------- 1 | function write_tb(nat,filename,ualatL,ucell,theta,id1,id2,upos,upos2) 2 | % HEADER of xyz coordinates file for TB 3 | tbfname = 'positions'; 4 | tbfname = join([tbfname,filename,'dat'],"."); 5 | fileID = fopen(tbfname,'w'); 6 | disp(' ') 7 | msg=['Writing coordinates and moire lattice vectors into TB input file:',tbfname]; 8 | disp(msg) 9 | alatL = ualatL; 10 | pos = upos; 11 | pos2 = upos2; 12 | cell = ucell; 13 | 14 | fprintf(fileID,'%i %i\n',nat/2,nat/2); 15 | fprintf(fileID,'%2.4f\n',theta); 16 | fprintf(fileID,'%2.2f\n',1.0); 17 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',cell(1,1:2), 0.0); 18 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',cell(2,1:2), 0.0); 19 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',0.0, 0.0,40); 20 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',alatL(1,1:2), 0.0); 21 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',alatL(2,1:2), 0.0); 22 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',0.0, 0.0,40); 23 | 24 | for k1 = 1:nat/2 25 | fprintf(fileID,'%s %i %4.6f %4.6f %4.6f\n',id1(k1),1,pos(k1,1),pos(k1,2),pos(k1,3)); 26 | end 27 | 28 | for k1 = 1:nat/2 29 | fprintf(fileID,'%s %i %4.6f %4.6f %4.6f\n',id2(k1),2,pos2(k1,1),pos2(k1,2),pos2(k1,3)); 30 | end 31 | 32 | fclose(fileID); 33 | end 34 | -------------------------------------------------------------------------------- /ASG/homobilayer/twisted/write_xsf.m: -------------------------------------------------------------------------------- 1 | function write_xsf(nat,filename,ualatL,z,id1,id2,num_at1,num_at2,c_at1,c_at2,upos,upos2,d1,d2) 2 | xsffname = join([filename,"xsf"],"."); 3 | fileID = fopen(xsffname,'w'); 4 | disp(' ') 5 | msg=['Writing xsf coordinates into file:',xsffname]; 6 | disp(msg) 7 | phi=acos(ualatL(1,1)/norm(ualatL(1,:))); 8 | cf=cos(-phi); 9 | sf=sin(-phi); 10 | Rphi=[cf -sf 0; sf cf 0; 0 0 1]; 11 | alatL = ualatL*Rphi(1:2,1:2)'; 12 | pos = upos*Rphi'; 13 | pos2 = upos2*Rphi'; 14 | % HEADER of XSF file 15 | fprintf(fileID,' %s\n','CRYSTAL'); 16 | fprintf(fileID,' %s\n','PRIMVEC'); 17 | fprintf(fileID,' % 12.10f % 12.10f % 12.10f\n',alatL(1,1), alatL(1,2), 0.0); 18 | fprintf(fileID,' % 12.10f % 12.10f % 12.10f\n',alatL(2,1), alatL(2,2), 0.0); 19 | fprintf(fileID,' % 12.10f % 12.10f % 12.10f\n',0.0, 0.0, z^2 + 2); 20 | fprintf(fileID,' %s\n','CONVVEC'); 21 | fprintf(fileID,' %4.10f %4.10f %4.10f\n',alatL(1,1), alatL(1,2), 0.0); 22 | fprintf(fileID,' %4.10f %4.10f %4.10f\n',alatL(2,1), alatL(2,2), 0.0); 23 | fprintf(fileID,' %4.10f %4.10f %4.10f\n',0.0, 0.0, z^2 + 2); 24 | fprintf(fileID,' %s\n','PRIMCOORD'); 25 | fprintf(fileID,'\t%i\t%i\n',nat,1); 26 | % Bottom layer first 27 | for k = 1:nat/2 28 | if (id1(k) == c_at1) 29 | idat = num_at1; 30 | else 31 | idat = num_at2; 32 | end 33 | fprintf(fileID,' %i %4.6f %4.6f %4.6f\n',idat,pos(k,1),pos(k,2),pos(k,3)); 34 | end 35 | 36 | % Top layer 37 | for k = 1:nat/2 38 | if (id2(k) == c_at1) 39 | idat = num_at1; 40 | else 41 | idat = num_at2; 42 | end 43 | fprintf(fileID,' %i %4.6f %4.6f %4.6f\n',idat,pos2(k,1),pos2(k,2),pos2(k,3)); 44 | end 45 | fclose(fileID); 46 | 47 | -------------------------------------------------------------------------------- /ASG/homobilayer/twisted/write_xyz.m: -------------------------------------------------------------------------------- 1 | function write_xyz(nat,filename,ualatL,id1,id2,upos,upos2) 2 | xyzfname = join([filename,"xyz"],"."); 3 | fileID = fopen(xyzfname,'w'); 4 | 5 | disp(' ') 6 | msg=['Writing xyz coordinates into file:',xyzfname]; 7 | disp(msg) 8 | phi=acos(ualatL(1,1)/norm(ualatL(1,:))); 9 | cf=cos(-phi); 10 | sf=sin(-phi); 11 | Rphi=[cf -sf 0; sf cf 0; 0 0 1]; 12 | alatL = ualatL*Rphi(1:2,1:2)'; 13 | pos = upos*Rphi'; 14 | pos2 = upos2*Rphi'; 15 | % HEADER of XYZ file 16 | fprintf(fileID,'%i\n',nat); 17 | fprintf(fileID,'%s\n',''); 18 | % Bottom layer first 19 | for k1 = 1:nat/2 20 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id1(k1),pos(k1,1),pos(k1,2),pos(k1,3)); 21 | end 22 | % Then top layer 23 | for k2 = 1:nat/2 24 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id2(k2),pos2(k2,1),pos2(k2,2),pos2(k2,3)); 25 | end 26 | fclose(fileID); 27 | end 28 | -------------------------------------------------------------------------------- /ASG/homomultilayers/twisted/TMLTMD_cell.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % 3 | % Computes the moire cell for twisted bilayer graphene (TBLG) given two 4 | % integers n and m. Here, we assume that m=n+1. 5 | % 6 | % It generates five output files: 7 | % 1) XYZ or XSF file for visualization 8 | % 2) .dat file that is used as input file for TB_free.x 9 | % 3) kpoints.in file to be used as input for TB_free.x 10 | % 4) kpaths.dat file to be used for plotting the band structure on the 11 | % chosen path in k-space 12 | % 5) lammps geometry file 13 | % 14 | % It returns the xyz coordinates of bottom layer (pos) and top layer (pos2) 15 | % and the total number of atoms (nat). 16 | % 17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 18 | function [nat,pos] = TMLTMD_cell(theta_vec,n, a, z, atomlabels, ... 19 | plot_f, kpath, nk, write_positions, write_cart, write_lammps_input,... 20 | write_kpath,stackings,orientations,nlayers) 21 | % Setting parameters 22 | m=n+1; 23 | mass = zeros(3*nlayers,1); 24 | num_at = zeros(3*nlayers,1); 25 | for isublayer = 1 : 3*nlayers 26 | % Define masses and atomic numbers 27 | if(strcmp(atomlabels{isublayer},'Mo')) 28 | % Atomic masses 29 | mass(isublayer) = 95.94; 30 | % Atoms info 31 | num_at(isublayer) = 42; 32 | elseif(strcmp(atomlabels{isublayer},'W')) 33 | mass(isublayer) = 183.84; 34 | num_at(isublayer) = 74; 35 | elseif(strcmp(atomlabels{isublayer},'S1') || strcmp(atomlabels{isublayer},'S2') ) 36 | mass(isublayer) = 32.06; 37 | num_at(isublayer) = 16; 38 | elseif(strcmp(atomlabels{isublayer},'Se1') || strcmp(atomlabels{isublayer},'Se2')) 39 | mass(isublayer) = 78.96; 40 | num_at(isublayer) = 34; 41 | end 42 | end 43 | mass 44 | num_at 45 | 46 | theta0 = acos((n^2 + 4*n*m + m^2)/(2*(n^2 + n*m + m^2))); 47 | theta = theta0*theta_vec; 48 | 49 | filename = join(['t',num2str(nlayers),'LTMD']); 50 | for ilayer = 1 : nlayers 51 | filename = join([filename atomlabels{(ilayer-1)*3 + 1}],"_"); 52 | filename = join([filename atomlabels{(ilayer-1)*3 + 2} "2"],''); 53 | end 54 | 55 | % total number of atoms in Moire cell 56 | tot_nat= 3*nlayers*(n^2 + n*m + m^2); 57 | 58 | % Compute Moire supercell 59 | u=0.6226; 60 | c=z; 61 | 62 | % Lattice vectors of top and bottom layer 63 | ualat1 = a*[sqrt(3)/2, sqrt(3)/2; -0.5,0.5]; 64 | Rphi = [cos(pi/6) -sin(pi/6); sin(pi/6) cos(pi/6)]; 65 | alat1 = Rphi*ualat1 66 | % Lattice vectors of Moire cell 67 | alatL = [n, m; -m, n+m]*alat1' 68 | ialatL = inv(alatL'); 69 | 70 | % Generate reciprocal lattice vectors 71 | recL = 2*pi*inv(alatL'); 72 | irecL = inv(recL); 73 | trecL = recL'; 74 | ralat1 = 2*pi*inv(alat1'); 75 | %ralat2 = 2*pi*inv(alat2'); 76 | 77 | % Print k-point grid/path to file 78 | % theta = theta*180/pi 79 | % str_theta = num2str(theta); 80 | % str_m = num2str(m); 81 | % str_n = num2str(n); 82 | % if (write_kpath) 83 | % msg = ['Generating kpoint grid for moirè lattice with a twist angle of ',str_theta,' ...']; 84 | % disp(msg) 85 | % disp(' ') 86 | % write_kpts(nk,ralat1,recL,str_theta,str_m,str_n,kpath,1); 87 | % disp(' ') 88 | % disp('... done') 89 | % end 90 | 91 | [pos,k1,id] = generate_cell(alatL,ialatL,a,c,u,tot_nat,nlayers,theta,alat1,orientations,... 92 | stackings,atomlabels); 93 | nat = k1 - 1; 94 | pos(:,3) = pos(:,3) - 5; 95 | %Check number of atoms is 3*(n^2 + n*m + m^2) 96 | if (nat ~= 3*nlayers*(n^2 + n*m + m^2)) 97 | nat 98 | 3*nlayers*(n^2 + n*m + m^2) 99 | error('Wrong number of atoms'); 100 | end 101 | disp('... done') 102 | 103 | 104 | %figure 105 | theta = theta*180/pi; 106 | for ilayer = 1 : nlayers 107 | if(strcmp(stackings(ilayer),'t0') || strcmp(stackings(ilayer),'t13') || ... 108 | strcmp(stackings(ilayer),'t23')) 109 | stheta = theta(ilayer); 110 | elseif(strcmp(stackings(ilayer),'r')) 111 | stheta = theta(ilayer); 112 | end 113 | str_stheta = num2str(stheta); 114 | filename = join([filename,str_stheta],"_theta="); 115 | end 116 | str_m = num2str(m); 117 | str_n = num2str(n); 118 | filename = join([filename,str_m],"_m="); 119 | filename = join([filename,str_n],"_n="); 120 | 121 | if (write_cart) 122 | if (strcmp(plot_f,'xyz')) 123 | write_xyz(nat,filename,alatL,id,pos) 124 | %write_full_xyz(nat,filename,alatL,id1,id2,id3,id4,pos1,pos2,pos3,pos4) 125 | elseif (strcmp(plot_f,'xsf')) 126 | write_xsf(nat,filename,alatL,z,id,num_at,atomlabels,pos,nlayers) 127 | end 128 | end 129 | 130 | if(write_positions) 131 | write_tb(nat,a,c,filename,alatL,alat1',theta,id,pos,nlayers); 132 | end 133 | 134 | % HEADER of geometry file for lammps 135 | if (write_lammps_input) 136 | write_lammps(nat,filename,alatL,z,id,3*nlayers,mass,atomlabels,pos,nlayers); 137 | end 138 | 139 | end 140 | 141 | 142 | function y1 = compdist(pos,pos2,nat,alatL,d1,d2,plot) 143 | n = 0; 144 | supercell = zeros(9*size(pos,1),2); 145 | supercell2 = zeros(9*size(pos,1),2); 146 | talat = alatL'; 147 | for ni = -1 : 1 148 | for nj = -1:1 149 | for j = 1:nat/2 150 | n = n + 1; 151 | xshift = pos(j,1) + ni*talat(1,1) + nj*talat(1,2); 152 | yshift = pos(j,2) + ni*talat(2,1) + nj*talat(2,2); 153 | supercell(n,:) = [xshift,yshift]; 154 | xshift2 = pos2(j,1) + ni*talat(1,1) + nj*talat(1,2); 155 | yshift2 = pos2(j,2) + ni*talat(2,1) + nj*talat(2,2); 156 | supercell2(n,:) = [xshift2,yshift2]; 157 | end 158 | end 159 | end 160 | 161 | superd1 = zeros(9*size(nat/2,1),1); 162 | superd2 = zeros(9*size(nat/2,1),1); 163 | for i = 1 : 9 164 | superd1((i-1)*nat/2+1:i*nat/2) = d1(:); 165 | superd2((i-1)*nat/2+1:i*nat/2) = d2(:); 166 | end 167 | x = linspace(1.2*min(pos(:,1)),1.2*max(pos(:,1)),300); 168 | y = linspace(1.2*min(pos(:,2)),1.2*max(pos(:,2)),300); 169 | [X,Y] = meshgrid(x,y); 170 | f1 = scatteredInterpolant(supercell(:,1),supercell(:,2),superd1,'natural'); 171 | Z1 = f1(X,Y); 172 | f2 = scatteredInterpolant(supercell2(:,1),supercell2(:,2),superd2,'natural'); 173 | Z2 = f2(X,Y); 174 | if (plot) 175 | figure 176 | contourf(X,Y,Z2-Z1) 177 | figure 178 | surf(X,Y,Z2-Z1) 179 | shading interp 180 | end 181 | y1 = superd1; 182 | end 183 | -------------------------------------------------------------------------------- /ASG/homomultilayers/twisted/analyse_structure_quadlayer.m: -------------------------------------------------------------------------------- 1 | function [out1,out2,strain,theta] = analyse_structure_quadlayer(ax1,ax2,ax3,ax4,mode,class,inputfile,rgb) 2 | data = importdata(join([inputfile,'.dat']),' ',10); 3 | natoms = str2num(data.textdata{1}); 4 | lattice = str2num(data.textdata{2}); 5 | strain=(str2num(data.textdata{4})-1)*100 6 | thetas=str2num(data.textdata{3}); 7 | theta = thetas(2); 8 | nat1 = natoms(1); 9 | nat2 = natoms(2); 10 | nat3 = natoms(3); 11 | nat4 = natoms(4); 12 | pos1 = data.data(1:nat1,2:4); 13 | pos2 = data.data(nat1+1:nat1+nat2,2:4); 14 | pos3 = data.data(nat1+nat2+1:nat1+nat2+nat3,2:4); 15 | pos4 = data.data(nat1+nat2+nat3+1:nat1+nat2+nat3+nat4,2:4); 16 | 17 | cpos1 = mean(pos1(:,3)); %pos1(index1,3) 18 | cpos2 = mean(pos2(:,3)); %pos2(index2,3) 19 | cpos3 = mean(pos3(:,3)); %pos2(index2,3) 20 | cpos4 = mean(pos4(:,3)); %pos2(index2,3) 21 | 22 | tot_mean = (cpos1+cpos4)/2 23 | 24 | cell = zeros(3); 25 | cell(1,1:3) = str2num(data.textdata{8}); 26 | cell(2,1:3) = str2num(data.textdata{9}); 27 | cell(3,1:3) = str2num(data.textdata{10}); 28 | phi = acos(cell(1,1)/norm(cell(1,:))); 29 | Rphi = [cos(-phi) -sin(-phi) 0;sin(-phi) cos(-phi) 0; 0 0 1]; 30 | pos1 = pos1*Rphi'; 31 | pos2 = pos2*Rphi'; 32 | pos3 = pos3*Rphi'; 33 | pos4 = pos4*Rphi'; 34 | cell = cell*Rphi'; 35 | 36 | pos1(:,3) = pos1(:,3) - tot_mean; 37 | pos2(:,3) = pos2(:,3) - tot_mean; 38 | pos3(:,3) = pos3(:,3) - tot_mean; 39 | pos4(:,3) = pos4(:,3) - tot_mean; 40 | cpos1 = mean(pos1(:,3)); 41 | cpos2 = mean(pos2(:,3)); 42 | cpos3 = mean(pos3(:,3)); 43 | cpos4 = mean(pos4(:,3)); 44 | 45 | for iat = 1 : nat1 46 | at_name1(iat) = string(data.textdata{10+iat}); 47 | end 48 | for jat = 1 : nat2 49 | at_name2(jat) = string(data.textdata{10+nat1+jat}); 50 | end 51 | for kat = 1 : nat3 52 | at_name3(kat) = string(data.textdata{10+nat1+nat2+kat}); 53 | end 54 | 55 | for kat = 1 : nat4 56 | at_name4(kat) = string(data.textdata{10+nat1+nat2+nat3+kat}); 57 | end 58 | 59 | 60 | ind1 = find(at_name1 == "Mo"); 61 | if(isempty(ind1)) 62 | ind1 = find(at_name1 == "W"); 63 | end 64 | 65 | 66 | ind2 = find(at_name2 == "Mo"); 67 | if(isempty(ind2)) 68 | ind2 = find(at_name2 == "W"); 69 | end 70 | 71 | 72 | ind3 = find(at_name3 == "Mo"); 73 | if(isempty(ind3)) 74 | ind3 = find(at_name3 == "W"); 75 | end 76 | 77 | 78 | ind4 = find(at_name4 == "Mo"); 79 | if(isempty(ind4)) 80 | ind4 = find(at_name4 == "W"); 81 | end 82 | % Create supercell for top layer 83 | supercell = zeros(length(ind4)*36,3); 84 | siat = 0; 85 | for iiat = 1 : length(ind4) 86 | iat = ind4(iiat); 87 | for in = -3 : 2 88 | for jn = -3 : 2 89 | siat = siat + 1; 90 | supercell(siat,:) = pos4(iat,:) + in*cell(1,:) + jn*cell(2,:); 91 | end 92 | end 93 | end 94 | f4 = scatteredInterpolant(supercell(:,1),supercell(:,2),supercell(:,3),'natural'); 95 | 96 | supercell = zeros(length(ind3)*36,3); 97 | siat = 0; 98 | for iiat = 1 : length(ind3) 99 | iat = ind3(iiat); 100 | for in = -3 : 2 101 | for jn = -3 : 2 102 | siat = siat + 1; 103 | supercell(siat,:) = pos3(iat,:) + in*cell(1,:) + jn*cell(2,:); 104 | end 105 | end 106 | end 107 | f3 = scatteredInterpolant(supercell(:,1),supercell(:,2),supercell(:,3),'natural'); 108 | 109 | % Create supercell for middle layer 110 | supercell = zeros(length(ind2)*36,3); 111 | siat = 0; 112 | for iiat = 1 : length(ind2) 113 | iat = ind2(iiat); 114 | for in = -3 : 2 115 | for jn = -3 : 2 116 | siat = siat + 1; 117 | supercell(siat,:) = pos2(iat,:) + in*cell(1,:) + jn*cell(2,:); 118 | end 119 | end 120 | end 121 | f2 = scatteredInterpolant(supercell(:,1),supercell(:,2),supercell(:,3),'natural'); 122 | 123 | supercell = zeros(length(ind1)*36,3); 124 | siat = 0; 125 | for iiat = 1 : length(ind1) 126 | iat = ind1(iiat); 127 | for in = -3 : 2 128 | for jn = -3 : 2 129 | siat = siat + 1; 130 | supercell(siat,:) = pos1(iat,:) + in*cell(1,:) + jn*cell(2,:); 131 | end 132 | end 133 | end 134 | 135 | f1 = scatteredInterpolant(supercell(:,1),supercell(:,2),supercell(:,3),'natural'); 136 | 137 | if(mode==1) 138 | min_z = zeros(length(ind1),1); 139 | for iiat = 1 : length(ind1) 140 | iat = ind1(iiat); 141 | dis = f2(pos1(iat,1),pos1(iat,2)) - f1(pos1(iat,1),pos1(iat,2)); 142 | min_z(iiat) = dis; 143 | end 144 | 145 | out1 = min(min_z); 146 | out2 = max(min_z); 147 | 148 | elseif(mode==2) 149 | if(class=="homos") 150 | %HOMO 151 | x2 = linspace(0.0,2*(cell(1,1)+cell(2,1)),500); 152 | y2 = linspace(0.0,2*(cell(1,2)+cell(2,2)),500); 153 | fullnorm = norm(cell(1,:)+cell(2,:)); 154 | elseif(class=="heteros") 155 | % HETERO 156 | x2 = linspace(2*cell(2,1)-2*cell(1,1),0.0,200); 157 | y2 = linspace(2*cell(2,2),0.0,200); 158 | fullnorm = (norm(-cell(1,:)+cell(2,:))); 159 | end 160 | out1 = 0; 161 | out2 = 0; 162 | 163 | [X2,Y2] = meshgrid(x2,y2); 164 | Ztest1 = f1(x2,y2); 165 | Ztest2 = f2(x2,y2); 166 | Ztest3 = f3(x2,y2); 167 | Ztest4 = f4(x2,y2); 168 | 169 | l = sqrt(x2.^2+y2.^2); 170 | 171 | plot(ax1,l/fullnorm,Ztest4,'Color',rgb,'Linewidth',2); 172 | plot(ax2,l/fullnorm,Ztest3,'Color',rgb,'Linewidth',2); 173 | plot(ax3,l/fullnorm,Ztest2,'Color',rgb,'Linewidth',2); 174 | plot(ax4,l/fullnorm,Ztest1,'Color',rgb,'Linewidth',2); 175 | 176 | 177 | elseif(mode==3) 178 | supercell = zeros(length(ind1)*4,3); 179 | siat = 0; 180 | for iiat = 1 : length(ind1) 181 | iat = ind1(iiat); 182 | for in = 0 : 1 183 | for jn = 0 : 1 184 | siat = siat + 1; 185 | supercell(siat,:) = pos1(iat,:) + in*cell(1,:) + jn*cell(2,:); 186 | end 187 | end 188 | end 189 | 190 | f = figure; 191 | set(f,'Position',[500.5 500.5 800 600]); 192 | Zdiff = f3(supercell(:,1),supercell(:,2))-f2(supercell(:,1),supercell(:,2)); 193 | scatter(supercell(:,1),supercell(:,2),100,Zdiff,'filled'); 194 | 195 | hold on; 196 | plot([0 cell(1,1)],[0 0],'k','LineWidth',2.0); 197 | plot([0 cell(2,1)],[0 cell(2,2)],'k','LineWidth',2.0); 198 | plot([cell(2,1) cell(2,1)+cell(1,1)],[cell(2,2) cell(2,2)],'k','LineWidth',2.0); 199 | plot([cell(1,1) cell(1,1)+cell(2,1)],[0 cell(2,2)],'k','LineWidth',2.0); 200 | plot([cell(1,1) 2*cell(1,1)],[0 0],'k','LineWidth',2.0); 201 | plot([2*cell(1,1) 2*cell(1,1)+cell(2,1)],[0 cell(2,2)],'k','LineWidth',2.0); 202 | plot([cell(1,1)+cell(2,1) 2*cell(1,1)+ cell(2,1) ],[cell(2,2) cell(2,2)],'k','LineWidth',2.0); 203 | plot([cell(2,1) 2*cell(2,1)],[cell(2,2) 2*cell(2,2)],'k','LineWidth',2.0); 204 | plot([2*cell(2,1) 2*cell(2,1)+cell(1,1)],[2*cell(2,2) 2*cell(2,2)],'k','LineWidth',2.0); 205 | plot([2*cell(2,1)+cell(1,1) 2*cell(2,1)+2*cell(1,1)],[2*cell(2,2) 2*cell(2,2)],'k','LineWidth',2.0); 206 | plot([cell(2,1)+cell(1,1) cell(2,1)+2*cell(1,1)],[cell(2,2) cell(2,2)],'k','LineWidth',2.0); 207 | plot([cell(2,1)+cell(1,1) 2*cell(2,1)+cell(1,1)],[cell(2,2) 2*cell(2,2)],'k','LineWidth',2.0); 208 | plot([cell(2,1)+2*cell(1,1) 2*cell(2,1)+2*cell(1,1)],[cell(2,2) 2*cell(2,2)],'k','LineWidth',2.0); 209 | if(class=="homos") 210 | % HOMO 211 | plot([0 2*cell(1,1)+2*cell(2,1)], [0 2*cell(2,2)],'g--','LineWidth',3.0); 212 | plot([55,105],[20,20],'w','LineWidth',5.0); 213 | text(70,25,'\textbf{50 \AA}','Interpreter','latex','Color','white','FontSize',28,'FontWeight','bold'); 214 | elseif(class=="heteros"); 215 | % HETERO 216 | plot([2*cell(1,1), 2*cell(2,1)], [0 2*cell(2,2)],'g--','LineWidth',3.0); 217 | plot([15,65],[10,10],'w','LineWidth',5.0); 218 | text(25,15,'\textbf{50 \AA}','Interpreter','latex','Color','white','FontSize',28); 219 | end 220 | axis([min(supercell(:,1))-25, max(supercell(:,1)) + 25, min(supercell(:,2))-50, max(supercell(:,2)) + 50]); 221 | axis('off'); 222 | h = colorbar;ylabel(h,'ILS (\AA)','Interpreter','latex','FontSize',24); 223 | colormap('hot'); 224 | x = get(gca,'position'); 225 | xh = get(h,'position'); 226 | xh(1)=0.15; 227 | xh(2)=0.3; 228 | xh(4)=0.5; 229 | set(h,'position',xh); 230 | set(gca,'position',x); 231 | set(gca,'FontSize',28); 232 | 233 | out1=0; 234 | out2=0; 235 | end 236 | clear txt at_name1 at_name2 cpos1 cpos2 data natoms nat1 nat2 X Y tind1 ind1 ind2 tind1 ind1t tind2 ind3 data pos1 pos2 X2 Y2 x y x2 y2 f1 f2 Ztest1 Ztest2 supercell 237 | -------------------------------------------------------------------------------- /ASG/homomultilayers/twisted/generate_cell.m: -------------------------------------------------------------------------------- 1 | function [pos,k1,id] = generate_cell(alatL,ialatL,a,c,u,tot_nat,nlayers,theta,alat1,orientations,... 2 | stackings,atomlabels) 3 | % number of supercell for the search 4 | period = norm(alatL,1); 5 | tnat = floor(period/a); 6 | pos = -10^5*ones(tot_nat,3); 7 | size(pos) 8 | id(1,tot_nat) = "X"; 9 | delta = 1*10^(-5); 10 | 11 | % disp(' ') 12 | % msg = ['Generating Cartesian atomic coordinates for moirè lattice with a twist angle of ',str_theta,' ...']; 13 | % disp(msg) 14 | 15 | k1=1; 16 | 17 | for ilayer = 1 : nlayers 18 | st=sin(theta(ilayer)); 19 | ct=cos(theta(ilayer)); 20 | Rtheta = [ct -st; st ct] 21 | for nj = -3*tnat:3*tnat 22 | for ni = -3*tnat:3*tnat 23 | r1 = ni*alat1(:,1) + nj*alat1(:,2); 24 | r2 = r1 + 1/3*alat1(:,1) + 1/3*alat1(:,2); 25 | %r3 = r2; 26 | f13 = 1/3; 27 | f23 = 2/3; 28 | if(strcmp(orientations{ilayer},'r')) 29 | r1 = -r1 + 1/3*(alat1(:,1)+alat1(:,2)); 30 | r2 = -r2 + 1/3*(alat1(:,1)+alat1(:,2)); 31 | %r3 = -r2; 32 | f13 = 2/3; 33 | f23 = 1/3; 34 | end 35 | if(strcmp(stackings{ilayer},'t0')) 36 | r1r = Rtheta*r1; 37 | r2r = Rtheta*r2; 38 | r3r = Rtheta*r2; 39 | elseif(strcmp(stackings{ilayer},'t13')) 40 | r1r = Rtheta*(r1+f13*(alat1(:,1)+alat1(:,2))); 41 | r2r = Rtheta*(r2+f13*(alat1(:,1)+alat1(:,2))); 42 | r3r = r2r; 43 | elseif(strcmp(stackings{ilayer},'t23')) 44 | r1r = Rtheta*(r1+f23*(alat1(:,1)+alat1(:,2))); 45 | r2r = Rtheta*(r2+f23*(alat1(:,1)+alat1(:,2))); 46 | r3r = r2r; 47 | end 48 | l1 = ialatL*r1r; 49 | l2 = ialatL*r2r; 50 | l3 = ialatL*r3r; 51 | if (l1(1) < (1-delta) && l1(1) >= -delta && l1(2) < (1-delta) && l1(2) >= -delta) 52 | pos(k1,1)=r1r(1); 53 | pos(k1,2)=r1r(2); 54 | pos(k1,3)=((ilayer-1)*0.5 + 0.75)*c; 55 | id(k1) = atomlabels{(ilayer-1)*3 + 1}; 56 | k1 = k1 + 1; 57 | end 58 | if (l2(1) < (1-delta) && l2(1) >= -delta && l2(2) < (1-delta) && l2(2) >= -delta) 59 | pos(k1,1)=r2r(1); 60 | pos(k1,2)=r2r(2); 61 | pos(k1,3)= ((ilayer-1)*0.5 + u)*c; 62 | id(k1) = atomlabels{(ilayer-1)*3 + 2}; 63 | k1 = k1 + 1; 64 | % end 65 | % if (l3(1) < (1-delta) && l3(1) >= -delta && l3(2) < (1-delta) && l3(2) >= -delta) 66 | pos(k1,1)=r3r(1); 67 | pos(k1,2)=r3r(2); 68 | pos(k1,3)=((ilayer-1)*0.5+1.5-u)*c; 69 | id(k1) = atomlabels{(ilayer-1)*3 + 3}; 70 | k1 = k1 + 1; 71 | end 72 | end 73 | end 74 | end 75 | 76 | 77 | end -------------------------------------------------------------------------------- /ASG/homomultilayers/twisted/main.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Script to find a set of commensurate moire lattices 3 | % and the atomic coordinates for twisted homobilayers. 4 | % The twisted bilayer is assumed to be made of 5 | % a material whose conventional cell is hexagonal, 6 | % e.g. graphene, hexagonal boron nitride (hBN) and 7 | % Transition-metal dichalcogenides (TMDs) 8 | % 9 | % 10 | % INPUT: 11 | % n - Integer parameter that defines Moire cell, 12 | % m=n+1 by default, see Ref. 1 13 | % a - lattice parameter of 2D material 14 | % c - Interlayer distance when starting 2D material 15 | % consists of a monolayer, e.g. graphene, OR 16 | % disance between central atoms of 2D material 17 | % for trilayers, e.g. distance 18 | % between transition metal atoms in the two 19 | % TMD layers. 20 | % comb - Define which combination of layers to consider 21 | % Possible choices are: 'graphene', 'hBN', 22 | % 'MoS2', 'WSe2', 'MoSe2', 'WS2' 23 | % plot_f - Format for plotting ('xyz' or 'xsf') 24 | % kpath - Path in k-space. Implemented paths are: 25 | % * K-Gamma-M-K' -> 'KMGKp' 26 | % * M-Gamma-K-M -> 'MGKM' 27 | % * Gamma-M-K-Gamma -> 'GMKG' 28 | % * Gamma-K-M -> 'GKM' 29 | % * K-M -> 'KM' 30 | % * Monkhorst-Pack -> 'uniform' 31 | % init_nk - Total number of kpoints for uniform MP grids OR 32 | % number of k-points in the first segment of the 33 | % chosen path 34 | % 35 | % OUTPUT: 36 | % .xyz(xsf) - Cartesian coordinates in XYZ 37 | % (XSF) format 38 | % positions..dat - Cartesian coordinates & 39 | % Moire lattice vectors 40 | % to be used as input file 41 | % for TB_free.x 42 | % lammps_positions..dat - Lammps geometry 43 | % file. 44 | % N.B. The Moire 45 | % cell is rotated 46 | % such as one of 47 | % the vector is 48 | % parallel to 49 | % on the x-axis 50 | % potential..dat - Potential file to be 51 | % used as input in 52 | % TB_free.x. Only for hBN 53 | % at the moment 54 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 55 | % 56 | % Written by Valerio Vitale, October 2019 57 | % 58 | % Refs. 59 | % 1) Nano Lett. 10, 3, 804-808 (2010) 60 | % 2) PRB 86, 155449 (2012) 61 | % 62 | % version 1.0 63 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 64 | 65 | % 11-band TB model PRB 92 205108 (2015) 66 | % All parameters are in Ang 67 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 68 | % a d(M-X) d(X-X) c (sqrt(d(M-X)^2-1/3*a^2)/(3/4-u)) u 69 | % MoS2 3.1824 2.41 3.13 12.29 70 | % WS2 3.1817 2.42 3.14 12.32 71 | % MoSe2 3.3174 2.54 3.34 12.90 72 | % WSe2 3.3155 2.55 3.35 12.96 73 | 74 | % Set from SW classical potential LAMMPs 75 | % All parameters are in Ang 76 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 77 | % a c u 78 | % MoS2 3.110 12.08 0.621 79 | % WS2 3.129 12.12 0.622 80 | % MoSe2 3.3096 12.84 0.621 81 | % WSe2 3.289 12.74 0.621 82 | 83 | % Parameters from our DFT calculations 84 | % All parameters are in Ang 85 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 86 | % a c u 87 | % MoS2 3.183 12.0264 0.621 88 | % WS2 3.182 12.1634 0.621 89 | % MoSe2 3.315 12.9567 0.621 90 | % WSe2 3.3145 13.0089 0.621 91 | 92 | dft_OPTB88_qe_geom = [ 93 | 3.183 12.0264 94 | 3.315 12.9567 95 | 3.182 12.1634 96 | 3.3145 13.0089]; 97 | 98 | dft_PBE_D3_siesta_geom = [ 99 | 3.183 12.0941 100 | 3.315 12.6589 101 | 3.182 11.7851 102 | 3.3145 12.5227]; 103 | 104 | lammps_sw_geom = [ 105 | 3.117 12.00 106 | 3.311 12.84 107 | 3.127 12.21 108 | 3.288 12.82]; 109 | 110 | geom_data = dft_OPTB88_qe_geom; %lammps_sw_geom; 111 | mat_params = cell(6,5); 112 | %MoS2 imat = 1 113 | mat_params{1,1} = 'Mo';mat_params{1,2} = 'S';mat_params{1,3} = geom_data(1,1);mat_params{1,4} = geom_data(1,2);mat_params{1,5} = 'TMD'; 114 | %MoSe2 imat = 2 115 | mat_params{2,1} = 'Mo';mat_params{2,2} = 'Se';mat_params{2,3} = geom_data(2,1); mat_params{2,4} = geom_data(2,2);mat_params{2,5} = 'TMD'; 116 | %WS2 imat = 3 117 | mat_params{3,1} = 'W';mat_params{3,2} = 'S';mat_params{3,3} = geom_data(3,1); mat_params{3,4} = geom_data(3,2);mat_params{3,5} = 'TMD'; 118 | %WSe2 imat = 4 119 | mat_params{4,1} = 'W';mat_params{4,2} = 'Se';mat_params{4,3} = geom_data(4,1); mat_params{4,4} = geom_data(4,2);mat_params{4,5} = 'TMD'; 120 | %graphene imat = 5 121 | mat_params{5,1} = 'C';mat_params{5,2} = 'C';mat_params{5,3} = 2.46; mat_params{5,4} = 3.30;mat_params{5,5} = 'graphene'; 122 | %hBN imat = 6 123 | mat_params{6,1} = 'B';mat_params{5,2} = 'N';mat_params{5,3} = 2.504; mat_params{5,4} = 3.35/2;mat_params{6,5} = 'hBN' 124 | 125 | 126 | %%%%%%%%%%%% BEGIN INPUT %%%%%%%%%%%%% 127 | % Integer for constructing Moire supercell 128 | n = 1; 129 | % Material index (see table at the top) 130 | imat = 2; 131 | % Lattice parameter of monolayer 132 | a = mat_params{imat,3}; 133 | %a = 3.182; % 134 | % Interlayer distance 135 | c = mat_params{imat,4}; 136 | %c = 12.1634/2; 137 | % Info for writing Cartesian coordinates and potential to file 138 | write_positions = true; 139 | write_potential = false; 140 | write_cart = true; 141 | % Whether to XYZ or XSF format 142 | plot_f = 'xsf'; 143 | write_lammps_input = true; 144 | % Initial phase 145 | nlayers = 1; 146 | orientations = {'u','r','r'};%,'r'}; 147 | translations = {'t0','t0','t0'};%,'t13'}; 148 | atomlabels = {mat_params{imat+2,1},join([mat_params{imat+2,2},'1']),join([mat_params{imat+2,2},'2']), ... 149 | mat_params{imat+2,1},join([mat_params{imat+2,2},'1']),join([mat_params{imat+2,2},'2']),... 150 | mat_params{imat,1},join([mat_params{imat,2},'1']),join([mat_params{imat,2},'2'])} 151 | % Chemical symbol for system 152 | comb = mat_params{imat,5}; 153 | theta_vec = [0,0,1];%,1,1]; 154 | 155 | % Info for writing k-points and path in k-space 156 | write_kpath = true; 157 | kpath = 'GMKG'; 158 | init_nk = 10; 159 | %%%%%%%%%%%% END INPUT %%%%%%%%%%%%% 160 | 161 | switch comb 162 | case 'graphene' 163 | disp('Structure and input files for twisted bilayer graphene') 164 | disp(' ') 165 | [num,pos,pos2] = TBLG_cell(n,a,c,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 166 | case 'hBN' 167 | disp('Structure and input files for twisted bilayer hBN') 168 | disp(' ') 169 | [num,pos,pos2] = TBLhBN_cell(n,a,c,plot_f,kpath,init_nk, write_positions, write_potential, write_cart, write_lammps_input, write_kpath,phase); 170 | case 'TMD' 171 | disp('Structure and input files for twisted bilayer TMD') 172 | disp(' ') 173 | [num,pos] = TMLTMD_cell(theta_vec,n,a,c,atomlabels,... 174 | plot_f,kpath,init_nk, write_positions, ... 175 | write_cart, write_lammps_input, write_kpath,translations,... 176 | orientations,nlayers); 177 | otherwise 178 | error('Material not supported. Available choices are: graphene, hBN, MoS2 and WSe2') 179 | end 180 | %end 181 | disp('Done! Have a nice day :-)') 182 | -------------------------------------------------------------------------------- /ASG/homomultilayers/twisted/write_lammps.m: -------------------------------------------------------------------------------- 1 | function write_lammps(nat,filename,alatL,z,id,ntype,m,atomlabels,pos,nlayers) 2 | % HEADER of geometry file for lammps 3 | lammpsfname = 'lammps_positions'; 4 | lammpsfname = join([lammpsfname,filename,'dat'],"."); 5 | additionalfname = join([filename,'rotation','dat'],"."); 6 | fileID = fopen(lammpsfname,'w'); 7 | fileID2 = fopen(additionalfname,'w'); 8 | disp(' ') 9 | msg=['Writing coordinates, moire lattice info and masses into lammps input file:',lammpsfname]; 10 | disp(msg) 11 | phi=acos(alatL(1,1)/norm(alatL(1,:))); 12 | cf=cos(-phi); 13 | sf=sin(-phi); 14 | Rphi=[cf -sf 0; sf cf 0; 0 0 1]; 15 | rot_alatL = Rphi(1:2,1:2)*alatL'; 16 | rot_pos = pos*Rphi'; 17 | fprintf(fileID2,'%8.8f\n',phi*180/pi); 18 | fprintf(fileID2,'%8.8f %8.8f %8.8f\n',rot_alatL(:,1)); 19 | fprintf(fileID2,'%8.8f %8.8f %8.8f\n',rot_alatL(:,2)); 20 | fprintf(fileID,'%s\n','LAMMPS data file from TBLG_cell.m'); 21 | fprintf(fileID,'\n'); 22 | fprintf(fileID,'%i %s\n',nat,'atoms'); 23 | fprintf(fileID,'\n'); 24 | fprintf(fileID,'%i %s\n',ntype,'atom types'); 25 | fprintf(fileID,'\n'); 26 | fprintf(fileID,'%8.8f %8.8f %s\n',0.0, rot_alatL(1,1), 'xlo xhi'); 27 | fprintf(fileID,'%8.8f %8.8f %s\n',0.0, rot_alatL(2,2), 'ylo yhi'); 28 | fprintf(fileID,'%8.8f %8.8f %s\n',0.0,100*z,'zlo zhi'); 29 | fprintf(fileID,'%8.8f %8.8f %8.8f %s\n', rot_alatL(1,2), 0.0, 0.0, 'xy xz yz'); 30 | fprintf(fileID,'\n'); 31 | fprintf(fileID,'%s\n','Masses'); 32 | fprintf(fileID,'\n'); 33 | for i = 1 : ntype 34 | fprintf(fileID,'%i %2.2f\n',i,m(i)); 35 | end 36 | fprintf(fileID,'\n'); 37 | fprintf(fileID,'%s\n','Atoms'); 38 | fprintf(fileID,'\n'); 39 | for ilayer = 0 : nlayers - 1 40 | for ik = 1:nat/nlayers 41 | k1 = ik+ilayer*nat/nlayers; 42 | if (strcmp(id(k1),atomlabels{3*ilayer+1})) 43 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k1,1+3*ilayer,rot_pos(k1,1),rot_pos(k1,2),rot_pos(k1,3)); 44 | elseif (strcmp(id(k1),atomlabels{3*ilayer+2})) 45 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k1,2+3*ilayer,rot_pos(k1,1),rot_pos(k1,2),rot_pos(k1,3)); 46 | elseif (strcmp(id(k1),atomlabels{3*ilayer+3})) 47 | fprintf(fileID,'%i %i %4.6f %4.6f %4.6f\n',k1,3+3*ilayer,rot_pos(k1,1),rot_pos(k1,2),rot_pos(k1,3)); 48 | end 49 | end 50 | end 51 | fclose(fileID); 52 | fclose(fileID2); 53 | end 54 | -------------------------------------------------------------------------------- /ASG/homomultilayers/twisted/write_tb.m: -------------------------------------------------------------------------------- 1 | function write_tb(nat,a,c,filename,ualatL,ucell,theta,id,upos,nlayers) 2 | % HEADER of xyz coordinates file for TB 3 | tbfname = 'positions'; 4 | tbfname = join([tbfname,filename,'dat'],"."); 5 | fileID = fopen(tbfname,'w'); 6 | disp(' ') 7 | msg=['Writing coordinates and moire lattice vectors into TB input file:',tbfname]; 8 | disp(msg) 9 | alatL = ualatL; 10 | pos = upos; 11 | cell = ucell; 12 | 13 | nat_per_layer_vec = nat/nlayers*ones(1,nlayers); 14 | format1 = ''; 15 | for ilayer = 1 : nlayers 16 | format1 = join([format1,' %i ']); 17 | end 18 | format1 = join([format1,'\n']); 19 | 20 | format2 = ''; 21 | for ilayer = 1 : nlayers 22 | format2 = join([format2,' %2.4f ']); 23 | end 24 | format2 = join([format2,'\n']); 25 | 26 | fprintf(fileID,format1,nat_per_layer_vec); 27 | fprintf(fileID,format2,a*ones(1,nlayers)); 28 | fprintf(fileID,format2,theta); 29 | fprintf(fileID,format2,ones(1,nlayers)); 30 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',cell(1,1:2), 0.0); 31 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',cell(2,1:2), 0.0); 32 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',0.0, 0.0,c); 33 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',alatL(1,1:2), 0.0); 34 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',alatL(2,1:2), 0.0); 35 | fprintf(fileID,'%8.8f %8.8f %8.8f\n',0.0, 0.0,c); 36 | 37 | for ilayer = 0 : nlayers - 1 38 | for ik = 1:nat/nlayers 39 | k1 = ik + ilayer*nat/nlayers; 40 | fprintf(fileID,'%s %i %4.6f %4.6f %4.6f\n',id(k1),ilayer+1,pos(k1,1),pos(k1,2),pos(k1,3)); 41 | end 42 | end 43 | 44 | fclose(fileID); 45 | end 46 | -------------------------------------------------------------------------------- /ASG/homomultilayers/twisted/write_xsf.m: -------------------------------------------------------------------------------- 1 | function write_xsf(nat,filename,ualatL,z,id,num_at,atomlabels,upos,nlayers) 2 | xsffname = join([filename,"xsf"],"."); 3 | fileID = fopen(xsffname,'w'); 4 | disp(' ') 5 | msg=['Writing xsf coordinates into file:',xsffname]; 6 | disp(msg) 7 | phi=acos(ualatL(1,1)/norm(ualatL(1,:))); 8 | cf=cos(-phi); 9 | sf=sin(-phi); 10 | Rphi=[cf -sf 0; sf cf 0; 0 0 1]; 11 | alatL = ualatL*Rphi(1:2,1:2)'; 12 | pos = upos*Rphi'; 13 | % HEADER of XSF file 14 | fprintf(fileID,' %s\n','CRYSTAL'); 15 | fprintf(fileID,' %s\n','PRIMVEC'); 16 | fprintf(fileID,' % 12.10f % 12.10f % 12.10f\n',alatL(1,1), alatL(1,2), 0.0); 17 | fprintf(fileID,' % 12.10f % 12.10f % 12.10f\n',alatL(2,1), alatL(2,2), 0.0); 18 | fprintf(fileID,' % 12.10f % 12.10f % 12.10f\n',0.0, 0.0, z^2 + 2); 19 | fprintf(fileID,' %s\n','CONVVEC'); 20 | fprintf(fileID,' %4.10f %4.10f %4.10f\n',alatL(1,1), alatL(1,2), 0.0); 21 | fprintf(fileID,' %4.10f %4.10f %4.10f\n',alatL(2,1), alatL(2,2), 0.0); 22 | fprintf(fileID,' %4.10f %4.10f %4.10f\n',0.0, 0.0, z^2 + 2); 23 | fprintf(fileID,' %s\n','PRIMCOORD'); 24 | fprintf(fileID,'\t%i\t%i\n',nat,1); 25 | for ilayer = 0 : nlayers - 1 26 | for ik = 1:nat/nlayers 27 | k = ik+ilayer*nat/nlayers; 28 | if (strcmp(id(k),atomlabels{ilayer+1})) 29 | idat = num_at(ilayer+1); 30 | elseif(strcmp(id(k),atomlabels{ilayer+2})) 31 | idat = num_at(ilayer+2); 32 | elseif(strcmp(id(k),atomlabels{ilayer+3})) 33 | idat = num_at(ilayer+3); 34 | end 35 | fprintf(fileID,' %i %4.6f %4.6f %4.6f\n',idat,pos(k,1),pos(k,2),pos(k,3)); 36 | end 37 | end 38 | fclose(fileID); 39 | end 40 | 41 | -------------------------------------------------------------------------------- /ASG/homomultilayers/twisted/write_xyz.m: -------------------------------------------------------------------------------- 1 | function write_xyz(nat,filename,ualatL,id,upos) 2 | xyzfname = join([filename,"xyz"],"."); 3 | fileID = fopen(xyzfname,'w'); 4 | 5 | disp(' ') 6 | msg=['Writing xyz coordinates into file:',xyzfname]; 7 | disp(msg) 8 | phi=acos(ualatL(1,1)/norm(ualatL(1,:))); 9 | cf=cos(-phi); 10 | sf=sin(-phi); 11 | Rphi=[cf -sf 0; sf cf 0; 0 0 1]; 12 | pos = upos*Rphi'; 13 | % HEADER of XYZ file 14 | fprintf(fileID,'%i\n',nat); 15 | fprintf(fileID,'%s\n',''); 16 | for k1 = 1:nat 17 | fprintf(fileID,'%s %4.6f %4.6f %4.6f\n',id(k1),pos(k1,1),pos(k1,2),pos(k1,3)); 18 | end 19 | fclose(fileID); 20 | end 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ______ ______ ____ 3 | /\__ _\ __ /\__ _\/\ _`\ 4 | \/_/\ \/ __ __ __/\_\ ____\/_/\ \/\ \ \L\ \ 5 | \ \ \/\ \/\ \/\ \/\ \ /',__\ \ \ \ \ \ _ <' 6 | \ \ \ \ \_/ \_/ \ \ \/\__, `\ \ \ \ \ \ \L\ \ 7 | \ \_\ \___x___/'\ \_\/\____/ \ \_\ \ \____/ 8 | \/_/\/__//__/ \/_/\/___/ \/_/ \/___/ 9 | 10 | ``` 11 | 12 | # TwisTB 13 | This GitHub repository hosts the MATLAB codes developed at University of Trieste and Imperial College for the calculation of the structural and electronic properties of twisted homo- and hetero- multilayer of different transition metal dichalcogenides. 14 | 15 | ## Authors 16 | * Valerio Vitale (MATLAB codes for the generation of inital structures) 17 | * Valerio Vitale and Kemal Atalar (MATLAB codes for tight-binding calculations of twisted bilayer TMDs) 18 | 19 | ## In publications arising from using this code please cite: 20 | Vitale, V., Atalar, K., *et al.* 2D Mater. **8** 045010 (2021) 21 | 22 | 23 | # ASG - Atomic Structures Generator 24 | 25 | Author 26 | ------ 27 | 28 | Valerio Vitale, University of Trieste 29 | 30 | * Email: vitale.valerio .at. units.it 31 | 32 | 33 | Description 34 | ----------- 35 | 36 | This module is a suite of MATLAB codes to generate the atomic structures of twisted homo- and hetero-bilayers of 2D 37 | materials with a hexagonal unit cell, e.g. graphene, hBN, TMDs. 38 | The input parameters can be specified in the `main.m` MATLAB file, both for homo and hetero bilayers. 39 | Several files can be generated: 40 | 1. `.xyz` or `.xsf` file for visualisation purposes 41 | 4. `lammps_positions..dat` file to be used as input file for `LAMMPS` 42 | 43 | Usage 44 | ----- 45 | 46 | You must have a MATLAB installed on your machine. 47 | 48 | 1. In MATLAB 49 | * Change directory working directory to the one containing the `main.m` file relative to the system of interest (e.g. homobilayer) 50 | * Simply type `main` in MATLAB Command Window 51 | * Your output files can be found in your working directory 52 | 53 | 2. From terminal 54 | * Open a new terminal window 55 | * Change directory to the one containing the `main.m` relative to the system of interest (e.g. homobilayer) 56 | * Type the following command: 57 | `$> matlab -nodisplay -nodesktop -nojvm -r "main ;exit"` 58 | * Your output files can be found in your working directory 59 | 60 | Notes 61 | ----- 62 | 63 | For twisted homo-bilayers, e.g. twisted bilayer graphene (TBLG), the twist angle is specified by a pair of integers (n,m). 64 | The commensurate Moirè lattice is constructed from n,m and the lattice parameter of the single layer. 65 | The resulting Moirè cell is also hexagonal. A description of the input file is given in the header of the `main.m` file 66 | 67 | For twisted hetero-bilayers, e.g. graphene on hBN, one has to specify a target angle and the ratio of the two lattice parameters. 68 | A description of the input parameters is given in the header of the `main.m` file 69 | 70 | 71 | # TB - Tight-Binding 72 | 73 | To use the tight-binding code you need to create an input file (see the header in the read_input.m routine) 74 | 75 | # Funding: 76 | This project has received funding from the European Union’s Horizon 2020 research and innovation programme under the Marie Skłodowska-Curie grant agreement no. 101067977 77 | 78 | -------------------------------------------------------------------------------- /TB/src/.BSE_parallel.m.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VVitale/TwisTB/aa7a74dc9d264ad604f8c6c00884fd52c34a3739/TB/src/.BSE_parallel.m.swp -------------------------------------------------------------------------------- /TB/src/README.md: -------------------------------------------------------------------------------- 1 | To run the MATLAB code you will need an input file (default is 'input.dat'). 2 | Keywords to specify in the input file are described below 3 | 4 | ``` 5 | - task (I) 1: bandstructure 2: Chern number and Berry curvature 3: DOS 4: charge density 5: exciton spectra and JDOS 6 | 6: Plot wavefunctions at Gamma, M and K 7: Build Hamiltonian on uniform grid and write in hdf5 format 8: Compute eigenvectors and matrices for Wannier90 7 | - restart (L) Whether this is a restart calculation 8 | - read_ham (L) Whether to read Hamiltonian 9 | - geomfname (S) Name of geometry file 10 | - gw_par (L) Whether to use GW parameters 11 | - d12 (R) maximum distance between chalcogen atom on bottom layer and chalcogen atom on top layer for computing 12 | interlayer hopping (aXX2 = 5.0) 13 | - nlayer (I) Number of layers 14 | - tmdc (I) TMD material code --- 1: MoS2 2: MoSe2 3: WS2 4:WSe2, e.g. MoS2 monolayer tmdc: = 1, MoS2 bilayer: tmdc = 11, 15 | MoS2 trilayer tmdc : 111, WS2/MoS2 bilayer: tmdc = 13 16 | - convention (I) Convention for the unit cell vectors of the monolayer (a=sqrt(3)*aXM) 17 | a1 a2 18 | convention 1 (120 deg) | (1, 0)*a | (-1/2,sqrt(3)/2)*a 19 | convention 2 (60 deg) | (1, 0)*a | (1/2,sqrt(3)/2)*a 20 | - knum (I) Number of k-points in the first segment (Gamma-M) when task = 1. Number of k-points along one reciprocal 21 | vector when task = {2,3,4,5,7}, in this case the total number of k-points is knum^2 22 | - miniBZ (L) Whether to use Gamma-M-K-Gamma of the miniBZ of Gamma-M-K-Gamma of the BZ of the monolayer folded onto the miniBZ 23 | - interlayer_int (L) Whether to compute the interlayer interaction 24 | - spin_orbit (L) Whether to compute spin-orbit 25 | - reduced_workspace (L) Whether to use eig or eigs in the diagonalisation 26 | - num_eigs (I) Number of conduction bands when reduced_workspace = true 27 | - eigvecs (L) Whether to compute the eigenvectors 28 | - save_workspace (L) Whether to save the orbital class for restart calculations 29 | - num_workers (I,S) Number of workers in parallel diagonalisation or 'max' maximum number of workers allowed by local profile 30 | - dos_spacing (R) Energy spacing in eV for DOS plot (e.g. 0.005) 31 | - gradient (L) Whether to compute the x component of the Hamiltonian gradient 32 | - Interpd (L) Whether to compute the pz-dz2 hopping 33 | - lambda (R) Shift of eigenspectrum, H = H + lambda*I 34 | - bse_num_vbnd (I) Number of valence bands in BSE 35 | - bse_num_cbnd (I) Number of conduction bands in BSE 36 | - bse_int (L) Whether to compute spectra with BSE interaction 37 | - bse_broadening (R) Broadening of the Lorentzian used to approximate the delta function in optical spectra 38 | - bse_eig_plot (I) Number of excitonic eigenvfunction to plot 39 | - bse_irh (I) Index of hole atomic position in the (moire) unit cell 40 | - bse_serial (L) Whether to run the BSE solver serially 41 | - bse_shifted (L) Whether to use a randomly shifted from (0,0) uniform k-grid for BSE 42 | - write_ham (L) Write Hamiltonian to hdf5 format 43 | - ham_fname (S) Name of hamiltonian hdf5 file 44 | - flipped (S) Whether a layer has been flipped to form a 2H stacking 45 | - read_kpts (L) Whether to read k-points 46 | - ef_strength (R) Electric-field strength in V/Ang 47 | - onsite_moire (R) Strength of onsite term proportional to local angle 48 | - sixth_nn (L) Whether to use the Hamiltonian with up to 6th nearest neighbour hoppings 49 | - g1 (R) Screened deformation potential for d orbitals 50 | - w90_root (S) root filename for Wannier90 files 51 | 52 | R = real number 53 | I = integer number 54 | L = boolean (true, false) 55 | S = string 56 | ``` 57 | -------------------------------------------------------------------------------- /TB/src/StruveH0.m: -------------------------------------------------------------------------------- 1 | function fun=StruveH0(z) 2 | % 3 | % StruveH0 calculates the function StruveH0 for complex argument z 4 | % 5 | % Author : T.P. Theodoulidis 6 | % Date : 11 June 2012 7 | % 8 | % Arguments 9 | % z : can be scalar, vector, matrix 10 | % 11 | % External routines called : cheval, StruveH0Y0 12 | % Matlab intrinsic routines called : bessely, besselh 13 | % 14 | bn=[... 15 | 7.741208505217204e-002 -1.489049907224780e-001 1.365908688119806e-001... 16 | -1.244408977167160e-001 1.213210541746413e-001 -9.902285991131098e-002... 17 | 9.285469594924457e-002 -8.889396057027860e-002 6.318108596562945e-002... 18 | -3.164140591816664e-002 1.160282350916835e-002 -3.255171535152174e-003... 19 | 7.240935462046915e-004 -1.313122517655078e-004 1.984234861137538e-005... 20 | -2.542464986238115e-006 2.802187746192928e-007 -2.688335553599889e-008... 21 | 2.267665290294826e-009 -1.696387437431367e-010 1.133879020090459e-011... 22 | -6.816279772928244e-013 3.706645666482425e-014 -1.832769429508806e-015... 23 | 8.278232328724399e-017 -3.429926823742390e-018 1.308568653462734e-019... 24 | -4.612908468868213e-021 1.507287730295555e-022 -4.578534841587558e-024... 25 | 1.296387199302720e-025 -3.430073819717729e-027 8.500386329076394e-029... 26 | -1.977322978489543e-030 4.326093533645215e-032]; 27 | % 28 | x=z(:); 29 | % 30 | % |x|<=16 31 | i1=abs(x)<=16; 32 | x1=x(i1); 33 | if isempty(x1)==0 34 | z1=x1.^2/400; 35 | fun1=cheval('shifted',bn,z1)*2.*x1/pi; 36 | else 37 | fun1=[]; 38 | end 39 | % 40 | % |x|>16 41 | i2=abs(x)>16; 42 | x2=x(i2); 43 | if isempty(x2)==0 44 | fun2=StruveH0Y0(x2)+bessely(0,x2); 45 | else 46 | fun2=[]; 47 | end 48 | % 49 | fun=x*0; 50 | fun(i1)=fun1; 51 | fun(i2)=fun2; 52 | % 53 | fun=reshape(fun,size(z)); 54 | % -------------------------------------------------------------------------------- /TB/src/StruveH0Y0.m: -------------------------------------------------------------------------------- 1 | function fun=StruveH0Y0(z) 2 | % 3 | % StruveH0Y0 calculates the function StruveH0-BesselY0 for complex argument z 4 | % 5 | % Author : T.P. Theodoulidis 6 | % Date : 11 June 2012 7 | % 8 | % Arguments 9 | % z : can be scalar, vector, matrix 10 | % 11 | % External routines called : cheval, StruveH0 12 | % Matlab intrinsic routines called : bessely, besselh 13 | % 14 | nom=[4,0,8816 ,0,6778206 ,... 15 | 0,2317961250 ,0,374638650750 ,... 16 | 0,28306147182390 ,0,937687098467700 ,... 17 | 0,11970864124436700,0,46174193179143750,... 18 | 0,32071055725170000,0,840808761085125]; 19 | % 20 | den=[4,0,8820 ,0,6786990 ,... 21 | 0,2324669760 ,0,376904178000 ,... 22 | 0,28663562736900 ,0,963414191990250 ,... 23 | 0,12740661151218000,0,54025303535453250,... 24 | 0,50023429199493750,0,4092826025413125]; 25 | % 26 | x=z(:); 27 | % 28 | % |x|<=16 29 | i1=abs(x)<=16; 30 | x1=x(i1); 31 | if isempty(x1)==0 32 | fun1=StruveH0(x1)-bessely(0,x1); 33 | else 34 | fun1=[]; 35 | end 36 | % 37 | % |x|>16 and real(x)<0 and imag(x)<0 38 | i2=(abs(x)>16 & real(x)<0 & imag(x)<0); 39 | x2=x(i2); 40 | if isempty(x2)==0 41 | x2=-x2; 42 | fun2=-(2/pi./x2.*polyval(nom,x2)./polyval(den,x2))+2i*besselh(0,1,x2); 43 | else 44 | fun2=[]; 45 | end 46 | % |x|>16 and real(x)<0 and imag(x)>=0 47 | i3=(abs(x)>16 & real(x)<0 & imag(x)>=0); 48 | x3=x(i3); 49 | if isempty(x3)==0 50 | x3=-x3; 51 | fun3=-(2/pi./x3.*polyval(nom,x3)./polyval(den,x3))-2i*besselh(0,2,x3); 52 | else 53 | fun3=[]; 54 | end 55 | 56 | % |x|>16 and real(x)>=0 57 | i4=(abs(x)>16 & real(x)>=0); 58 | x4=x(i4); 59 | if isempty(x4)==0 60 | fun4=2/pi./x4.*polyval(nom,x4)./polyval(den,x4); 61 | else 62 | fun4=[]; 63 | end 64 | fun=x*0; 65 | fun(i1)=fun1; 66 | fun(i2)=fun2; 67 | fun(i3)=fun3; 68 | fun(i4)=fun4; 69 | % 70 | fun=reshape(fun,size(z)); 71 | % -------------------------------------------------------------------------------- /TB/src/add_soc.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Routine to add SOC to TB Hamiltonian matrix 3 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 | % Inputs: 5 | % Hmat - Hamiltonian matrix 6 | % Hsoc - 22x22 SOC matrix in 22-orbital basis 7 | % orbitals - orbitals class 8 | % norbs - Number of orbitals 9 | % 10 | % Outputs: 11 | % Hmat - Hamiltonian matrix with SOC 12 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 | % Written by Valerio Vitale 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | 16 | 17 | function Hmat = add_soc(Hmat,Hsoc,orbitals,ilayer) 18 | 19 | liorb = cell(2,2); 20 | 21 | for ispin = 1 : 2 22 | if(ispin == 1) 23 | iispin = -1; 24 | else 25 | iispin = 1; 26 | end 27 | for il = 1 : 2 28 | orb = findobj(orbitals,'Spin',iispin,'l',il,'Layer',ilayer); 29 | liorb{ispin,il} = [orb.Ham_index]; 30 | end 31 | end 32 | clear orb 33 | orb1 = liorb{1,2}; 34 | orb2 = liorb{2,2}; 35 | orb3 = liorb{1,1}; 36 | orb4 = liorb{2,1}; 37 | for ii = 1 : length(orb1) 38 | iorb = orb1(ii); 39 | for jj = 1 : length(orb1) 40 | jorb = orb1(jj); 41 | if(orbitals(jorb).Centre == orbitals(iorb).Centre) 42 | Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) + Hsoc(orbitals(iorb).Rel_index,orbitals(jorb).Rel_index); 43 | end 44 | end 45 | for jj = 1 : length(orb2) 46 | jorb = orb2(jj); 47 | if(orbitals(jorb).Centre == orbitals(iorb).Centre) 48 | Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) + Hsoc(orbitals(iorb).Rel_index,orbitals(jorb).Rel_index+11); 49 | Hmat(orbitals(jorb).Ham_index,orbitals(iorb).Ham_index) = Hmat(orbitals(jorb).Ham_index,orbitals(iorb).Ham_index) + conj(Hsoc(orbitals(iorb).Rel_index,orbitals(jorb).Rel_index+11));% + conj(Hsoc(orb1.Rel_index,orb2.Rel_index)); 50 | end 51 | end 52 | end 53 | for ii = 1 : length(orb2) 54 | iorb = orb2(ii); 55 | for jj = 1 : length(orb2) 56 | jorb = orb2(jj); 57 | if(orbitals(jorb).Centre == orbitals(iorb).Centre) 58 | Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) + Hsoc(orbitals(iorb).Rel_index+11,orbitals(jorb).Rel_index+11); 59 | end 60 | end 61 | end 62 | 63 | for ii = 1 : length(orb3) 64 | iorb = orb3(ii); 65 | for jj = 1 : length(orb3) 66 | jorb = orb3(jj); 67 | if(orbitals(jorb).Pcentre == orbitals(iorb).Pcentre) 68 | Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) + Hsoc(orbitals(iorb).Rel_index,orbitals(jorb).Rel_index); 69 | end 70 | end 71 | for jj = 1 : length(orb4) 72 | jorb = orb4(jj); 73 | if(orbitals(jorb).Pcentre == orbitals(iorb).Pcentre) 74 | Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) + Hsoc(orbitals(iorb).Rel_index,orbitals(jorb).Rel_index+11); 75 | Hmat(orbitals(jorb).Ham_index,orbitals(iorb).Ham_index) = Hmat(orbitals(jorb).Ham_index,orbitals(iorb).Ham_index) + conj(Hsoc(orbitals(iorb).Rel_index,orbitals(jorb).Rel_index+11));% + conj(Hsoc(orb1.Rel_index,orb2.Rel_index)); 76 | %Hmat(orbitals(jorb).Ham_index,orbitals(iorb).Ham_index) = conj(Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index));% + conj(Hsoc(orb1.Rel_index,orb2.Rel_index)); 77 | end 78 | end 79 | end 80 | 81 | 82 | for ii = 1 : length(orb4) 83 | iorb = orb4(ii); 84 | for jj = 1 : length(orb4) 85 | jorb = orb4(jj); 86 | if(orbitals(jorb).Pcentre == orbitals(iorb).Pcentre) 87 | Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = Hmat(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) + Hsoc(orbitals(iorb).Rel_index+11,orbitals(jorb).Rel_index+11); 88 | end 89 | end 90 | end 91 | clear orb1 orb2 orb3 orb4 liorb 92 | end 93 | -------------------------------------------------------------------------------- /TB/src/assign_hoppings.m: -------------------------------------------------------------------------------- 1 | function hopping = assign_hoppings(a1,a2,delta,neigh_shell,layer,sym_sign,ir,jr,type1,type2,type3,type4,type5,type6) 2 | hopping = zeros(size(delta,1),1); 3 | tol = 0.3; 4 | if (neigh_shell == 1) 5 | del4=-(2*a1+a2)/3; 6 | del5=(a1+2*a2)/3; 7 | del6=(a1-a2)/3; 8 | for ih = 1 : length(hopping) 9 | d4=dot(delta(ih,:),del4)/(norm(delta(ih,:))*norm(del4)); 10 | d5=dot(delta(ih,:),del5)/(norm(delta(ih,:))*norm(del5)); 11 | d6=dot(delta(ih,:),del6)/(norm(delta(ih,:))*norm(del6)); 12 | if(abs(d4)-1>tol && abs(d5)-1>tol && abs(d6)-1>tol) 13 | error('Error in build_H.m: hopping cannot be assigned!') 14 | end 15 | 16 | if(sym_sign(ih) < 0) 17 | % Only hopping of type 4 18 | if(abs(d4-1) 0) 26 | % type 4 and type 5 27 | if(abs(d4-1) ir) 55 | if(sym_sign(ih) < 0) 56 | %Hopping of type 1 2 and 3 57 | if(abs(d1+1) 0) 73 | if(abs(d1-1)tol && abs(d8)-1>tol && abs(d9)-1>tol) 98 | error('Error in build_H.m: hopping cannot be assigned!') 99 | end 100 | if(ir == 9 && jr(ih) == 6) 101 | if(abs(d7-1) < tol || abs(d8-1) < tol || abs(d9-1) < tol) 102 | hopping(ih) = type6(9,6,layer); 103 | end 104 | elseif(ir == 11 && jr(ih) == 6) 105 | if(abs(d7-1) < tol) 106 | hopping(ih) = type6(11,6,layer); 107 | elseif(abs(d8-1) < tol || abs(d9-1) < tol) 108 | hopping(ih) = -0.5*type6(11,6,layer); 109 | end 110 | elseif(ir == 10 && jr(ih) == 6) 111 | if(abs(d8-1) < tol) 112 | hopping(ih) = -sqrt(3)/2*type6(11,6,layer); 113 | elseif(abs(d9-1) < tol) 114 | hopping(ih) = sqrt(3)/2*type6(11,6,layer); 115 | end 116 | elseif(ir == 9 && jr(ih) == 8) 117 | if(abs(d7-1) < tol) 118 | hopping(ih) = type6(9,8,layer); 119 | elseif(abs(d8-1) < tol || abs(d9-1) < tol) 120 | hopping(ih) = -0.5*type6(9,8,layer); 121 | end 122 | elseif(ir == 9 && jr(ih) == 7) 123 | if(abs(d8-1) < tol) 124 | hopping(ih) = -sqrt(3)/2*type6(9,8,layer); 125 | elseif(abs(d9-1) < tol) 126 | hopping(ih) = sqrt(3)/2*type6(9,8,layer); 127 | end 128 | elseif(ir == 10 && jr(ih) == 7) 129 | if(abs(d8-1) < tol || abs(d9-1) < tol) 130 | hopping(ih) = 3/4*type6(11,8,layer); 131 | end 132 | elseif((ir == 11 && jr(ih) == 7) || (ir == 10 && jr(ih) == 8)) 133 | if(abs(d8-1) < tol) 134 | hopping(ih) = sqrt(3)/4*type6(11,8,layer); 135 | elseif(abs(d9-1) < tol) 136 | hopping(ih) = -sqrt(3)/4*type6(11,8,layer); 137 | end 138 | elseif(ir == 11 && jr(ih) == 8) 139 | if(abs(d7-1) < tol) 140 | hopping(ih) = type6(11,8,layer); 141 | elseif(abs(d8-1) < tol || abs(d9-1) < tol) 142 | hopping(ih) = 1/4*type6(11,8,layer); 143 | end 144 | else 145 | hopping(ih) = 0; 146 | end 147 | end 148 | end 149 | end 150 | 151 | -------------------------------------------------------------------------------- /TB/src/build_H2.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Routine to compute Hamiltonian matrix 3 | % This routine generalises the TB Hamiltonian 4 | % in PRB 92, 205108 (2015) for different systems 5 | % This routines generates the TB Hamiltonian 6 | % matrix for monolayers and bilayers. 7 | % In the case of bilayers this routines computes 8 | % the block-diagonal part for each layer. 9 | % The off-diagonal interlayer interaction is 10 | % computed in a different routine Vint.m 11 | % In the case of a SOC calculation this routines 12 | % only compute the block-diagonal part of the 13 | % Hamiltonian for spin-up and spin-down channel 14 | % The off-diagonal blocks are added by add_soc.m 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 | % Inputs: 17 | % Hmat - Hamiltonian matrix 18 | % norbs - Number of orbitals 19 | % orbitals - orbitals class 20 | % ia1,ia2,ia3 - Planar vectors used to assign hoppings 21 | % k - k-point in Cartesian coordinates 22 | % onsite,type1,type2,type3,type4,type5,type6 - All TB parameters for monolayer 23 | % Rot - Rotation matrix for upper layer 24 | % bilayer - Whether dealing with a bilayer or monolayer 25 | % nspins - nspins = 2 for SOC, otherwise nspins = 1 26 | % interlayer_int - whether to compute interlayer interaction 27 | % lsoc - Whether to add SOC 28 | % T - unsymmetrising matrix 29 | % Vsigma - sigma parameter for p-orbitals in 30 | % Slater-Koster rule 31 | % Vpi - pi parameter for p-orbitals in 32 | % Slater-Koster rule 33 | % R,eta - Parameters for spatial-dependent part 34 | % in Slater-Koster rule [1] 35 | % theta - twist angle 36 | % Hsoc - SOC matrices for p and d orbitals 37 | % 38 | % Outputs: 39 | % Hmat - Hamiltonian matrix 40 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 41 | % Written by Valerio Vitale 42 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 43 | function [Hmat,gradH_x] = build_H2(Hmat,orbitals,Mxz,k,nlayer,multilayer,... 44 | nspins,interlayer_int,lsoc,T,pp_vint_z,pp_vint_parm, ... 45 | pd_vint_lay1_z,pd_vint_lay1_parm,pd_vint_lay2_z,pd_vint_lay2_parm,theta,Hsoc,... 46 | Interpd,gradient,varargin) 47 | 48 | if(gradient && isempty(varargin)) 49 | error('Error in build_H.m: Hamiltonian gradient required. Aborting ...') 50 | end 51 | 52 | if(~gradient && ~isempty(varargin)) 53 | error('Error in build_H.m: Found gradient but gradient not required. Aborting ...') 54 | end 55 | 56 | if(gradient && length(varargin)==1) 57 | gradH_x = cell2mat(varargin(1)); 58 | end 59 | 60 | for layer = 1 : nlayer 61 | orb = findobj(orbitals,'Layer',layer); 62 | liorb = [orb.Ham_index]; 63 | clear orb1; 64 | for ii = 1 : size(liorb,2) 65 | iorb = liorb(ii); 66 | if(orbitals(iorb).M1sym > 0) 67 | nnn = size(orbitals(iorb).Intra_nnn_list,2); 68 | % Contribution from next nearest neighbors 69 | for in = 1 : nnn 70 | jorb = orbitals(iorb).Intra_nnn_list(in); 71 | hopping = orbitals(iorb).Intra_nnn_hoppings(in); 72 | delta = orbitals(iorb).Intra_nnn_centre(in,1:3) - orbitals(iorb).Centre; 73 | 74 | % Find type of hopping 75 | % Take only even states 76 | hij = hopping*exp(1i*dot(delta,k)); 77 | Hmat(iorb,jorb) = Hmat(iorb,jorb) + hij; 78 | Hmat(jorb,iorb) = Hmat(jorb,iorb) + conj(hij); %hopping*exp(1i*dot(delta,k)); 79 | if(gradient) 80 | gradH_x(iorb,jorb) = gradH_x(iorb,jorb) - delta(1)*hij - 1i*delta(2)*hij; 81 | gradH_x(jorb,iorb) = gradH_x(jorb,iorb) + conj(- delta(1)*hij - 1i*delta(2)*hij); %hopping*exp(1i*dot(delta,k)); 82 | end 83 | end 84 | end 85 | nn1 = size(orbitals(iorb).Intra_nn_list,2); 86 | for in = 1 : nn1 87 | jorb = orbitals(iorb).Intra_nn_list(in); 88 | if(orbitals(jorb).Rel_index > orbitals(iorb).Rel_index) 89 | hopping = orbitals(iorb).Intra_nn_hoppings(in); 90 | delta = orbitals(iorb).Intra_nn_centre(in,1:3) - orbitals(iorb).Centre; 91 | hij = hopping*exp(1i*dot(delta,k)); 92 | Hmat(iorb,jorb) = Hmat(iorb,jorb) + hij; 93 | Hmat(jorb,iorb) = Hmat(jorb,iorb) + conj(hij); %hopping*exp(1i*dot(delta,k)); 94 | if(gradient) 95 | gradH_x(iorb,jorb) = gradH_x(iorb,jorb) - delta(1)*hij - 1i*delta(2)*hij; 96 | gradH_x(jorb,iorb) = gradH_x(jorb,iorb) + conj(- delta(1)*hij - 1i*delta(2)*hij); %hopping*exp(1i*dot(delta,k)); 97 | end 98 | end 99 | end 100 | n = size(orbitals(iorb).Intra_n_list,2); 101 | % Contribution from nearest neighbors 102 | for in = 1 : n 103 | jorb = orbitals(iorb).Intra_n_list(in); 104 | hopping = orbitals(iorb).Intra_n_hoppings(in); 105 | delta = orbitals(iorb).Intra_n_centre(in,1:3) - orbitals(iorb).Centre; 106 | 107 | % Find type of hopping 108 | hij = hopping*exp(1i*dot(delta,k)); 109 | Hmat(iorb,jorb) = Hmat(iorb,jorb) + hij; 110 | if(gradient) 111 | gradH_x(iorb,jorb) = gradH_x(iorb,jorb) - delta(1)*hij - 1i*delta(2)*hij; 112 | end 113 | end 114 | % Contribution from next nearest neighbors 115 | nn2 = size(orbitals(iorb).Intra_nn_list,2); 116 | for in = 1 : nn2 117 | jorb = orbitals(iorb).Intra_nn_list(in); 118 | if(orbitals(jorb).Rel_index == orbitals(iorb).Rel_index) 119 | hopping = orbitals(iorb).Intra_nn_hoppings(in); 120 | delta = orbitals(iorb).Intra_nn_centre(in,1:3) - orbitals(iorb).Centre; 121 | 122 | % Get connecting vector between centres 123 | 124 | % Find type of hopping 125 | hij = hopping*exp(1i*dot(delta,k)); 126 | Hmat(iorb,jorb) = Hmat(iorb,jorb) + hij; 127 | if(gradient) 128 | gradH_x(iorb,jorb) = gradH_x(iorb,jorb) - delta(1)*hij - 1i*delta(2)*hij; 129 | end 130 | end 131 | end 132 | end 133 | end 134 | 135 | H_rotated = false; 136 | % Add interlayer interaction 137 | if(multilayer && interlayer_int) 138 | % Rotate Hamiltonian into unsymmetrised basis 139 | Hmat = T'*(Hmat*T); 140 | % Apply mask for 2H stackings 141 | Hmat = Mxz'*Hmat*Mxz; 142 | % Check Hamiltonian is Hermitian 143 | if(gradient) 144 | gradH_x = T'*(gradH_x*T); 145 | [Hmat,gradH_x] = Vint(Hmat,nlayer,orbitals,pp_vint_z,pp_vint_parm,pd_vint_lay1_z,pd_vint_lay1_parm,pd_vint_lay2_z,pd_vint_lay2_parm,k,theta,Interpd,nspins,gradient,gradH_x); 146 | else 147 | [Hmat] = Vint(Hmat,nlayer,orbitals,pp_vint_z,pp_vint_parm,pd_vint_lay1_z,pd_vint_lay1_parm,pd_vint_lay2_z,pd_vint_lay2_parm,k,theta,Interpd,nspins,gradient); 148 | end 149 | H_rotated = true; 150 | end 151 | 152 | % Add SOC 153 | if (lsoc) 154 | if (~H_rotated) 155 | Hmat = T'*(Hmat*T); 156 | H_rotated = true; 157 | end 158 | for ilayer = 1 : nlayer 159 | Hmat = add_soc(Hmat,Hsoc{ilayer},orbitals,ilayer); 160 | end 161 | end 162 | 163 | 164 | %check if Hamiltonian is Hermitian 165 | %if(normest(Hmat-Hmat')>1E-4) 166 | % error('Hamiltonian is not hermitian!') 167 | %end 168 | Hmat = 0.5*(Hmat+Hmat'); 169 | if(gradient) 170 | gradH_x = 0.5*(gradH_x+gradH_x'); 171 | end 172 | end 173 | -------------------------------------------------------------------------------- /TB/src/build_H_3rdnn.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Routine to compute Hamiltonian matrix 3 | % This routine generalises the TB Hamiltonian 4 | % in PRB 92, 205108 (2015) for different systems 5 | % This routines generates the TB Hamiltonian 6 | % matrix for monolayers and bilayers. 7 | % In the case of bilayers this routines computes 8 | % the block-diagonal part for each layer. 9 | % The off-diagonal interlayer interaction is 10 | % computed in a different routine Vint.m 11 | % In the case of a SOC calculation this routines 12 | % only compute the block-diagonal part of the 13 | % Hamiltonian for spin-up and spin-down channel 14 | % The off-diagonal blocks are added by add_soc.m 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 | % Inputs: 17 | % Hmat - Hamiltonian matrix 18 | % norbs - Number of orbitals 19 | % orbitals - orbitals class 20 | % ia1,ia2,ia3 - Planar vectors used to assign hoppings 21 | % k - k-point in Cartesian coordinates 22 | % onsite,type1,type2,type3,type4,type5,type6 - All TB parameters for monolayer 23 | % Rot - Rotation matrix for upper layer 24 | % bilayer - Whether dealing with a bilayer or monolayer 25 | % nspins - nspins = 2 for SOC, otherwise nspins = 1 26 | % interlayer_int - whether to compute interlayer interaction 27 | % lsoc - Whether to add SOC 28 | % T - unsymmetrising matrix 29 | % Vsigma - sigma parameter for p-orbitals in 30 | % Slater-Koster rule 31 | % Vpi - pi parameter for p-orbitals in 32 | % Slater-Koster rule 33 | % R,eta - Parameters for spatial-dependent part 34 | % in Slater-Koster rule [1] 35 | % theta - twist angle 36 | % Hsoc - SOC matrices for p and d orbitals 37 | % 38 | % Outputs: 39 | % Hmat - Hamiltonian matrix 40 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 41 | % Written by Valerio Vitale 42 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 43 | function [Hmat,gradH_x] = build_H2(Hmat,orbitals,Mxz,k,nlayer,multilayer,... 44 | nspins,interlayer_int,lsoc,T,pp_vint_z,pp_vint_parm, ... 45 | pd_vint_lay1_z,pd_vint_lay1_parm,pd_vint_lay2_z,pd_vint_lay2_parm,theta,Hsoc,... 46 | Interpd,gradient,varargin) 47 | 48 | if(gradient && isempty(varargin)) 49 | error('Error in build_H.m: Hamiltonian gradient required. Aborting ...') 50 | end 51 | 52 | if(~gradient && ~isempty(varargin)) 53 | error('Error in build_H.m: Found gradient but gradient not required. Aborting ...') 54 | end 55 | 56 | if(gradient && length(varargin)==1) 57 | gradH_x = cell2mat(varargin(1)); 58 | end 59 | 60 | for layer = 1 : nlayer 61 | orb = findobj(orbitals,'Layer',layer); 62 | liorb = [orb.Ham_index]; 63 | clear orb; 64 | for ii = 1 : size(liorb,2) 65 | iorb = liorb(ii); 66 | if(orbitals(iorb).M1sym > 0) 67 | nn3 = size(orbitals(iorb).Intra_nn3_list,2); 68 | % Contribution from next nearest neighbors 69 | for in = 1 : nn3 70 | jorb = orbitals(iorb).Intra_nn3_list(in); 71 | hopping = orbitals(iorb).Intra_nn3_hoppings(in); 72 | delta = orbitals(iorb).Intra_nn3_centre(in,1:3) - orbitals(iorb).Centre; 73 | 74 | % Find type of hopping 75 | % Take only even states 76 | hij = hopping*exp(1i*dot(delta,k)); 77 | Hmat(iorb,jorb) = Hmat(iorb,jorb) + hij; 78 | Hmat(jorb,iorb) = Hmat(jorb,iorb) + conj(hij); %hopping*exp(1i*dot(delta,k)); 79 | if(gradient) 80 | gradH_x(iorb,jorb) = gradH_x(iorb,jorb) - delta(1)*hij - 1i*delta(2)*hij; 81 | gradH_x(jorb,iorb) = gradH_x(jorb,iorb) + conj(- delta(1)*hij - 1i*delta(2)*hij); %hopping*exp(1i*dot(delta,k)); 82 | end 83 | end 84 | end 85 | nn1 = size(orbitals(iorb).Intra_nn2_list,2); 86 | for in = 1 : nn1 87 | jorb = orbitals(iorb).Intra_nn2_list(in); 88 | if(orbitals(jorb).Rel_index > orbitals(iorb).Rel_index) 89 | hopping = orbitals(iorb).Intra_nn2_hoppings(in); 90 | delta = orbitals(iorb).Intra_nn2_centre(in,1:3) - orbitals(iorb).Centre; 91 | hij = hopping*exp(1i*dot(delta,k)); 92 | Hmat(iorb,jorb) = Hmat(iorb,jorb) + hij; 93 | Hmat(jorb,iorb) = Hmat(jorb,iorb) + conj(hij); %hopping*exp(1i*dot(delta,k)); 94 | if(gradient) 95 | gradH_x(iorb,jorb) = gradH_x(iorb,jorb) - delta(1)*hij - 1i*delta(2)*hij; 96 | gradH_x(jorb,iorb) = gradH_x(jorb,iorb) + conj(- delta(1)*hij - 1i*delta(2)*hij); %hopping*exp(1i*dot(delta,k)); 97 | end 98 | end 99 | end 100 | n = size(orbitals(iorb).Intra_nn1_list,2); 101 | % Contribution from nearest neighbors 102 | for in = 1 : n 103 | jorb = orbitals(iorb).Intra_nn1_list(in); 104 | hopping = orbitals(iorb).Intra_nn1_hoppings(in); 105 | delta = orbitals(iorb).Intra_nn1_centre(in,1:3) - orbitals(iorb).Centre; 106 | 107 | % Find type of hopping 108 | hij = hopping*exp(1i*dot(delta,k)); 109 | Hmat(iorb,jorb) = Hmat(iorb,jorb) + hij; 110 | if(gradient) 111 | gradH_x(iorb,jorb) = gradH_x(iorb,jorb) - delta(1)*hij - 1i*delta(2)*hij; 112 | end 113 | end 114 | % Contribution from next nearest neighbors 115 | nn2 = size(orbitals(iorb).Intra_nn2_list,2); 116 | for in = 1 : nn2 117 | jorb = orbitals(iorb).Intra_nn2_list(in); 118 | if(orbitals(jorb).Rel_index == orbitals(iorb).Rel_index) 119 | hopping = orbitals(iorb).Intra_nn2_hoppings(in); 120 | delta = orbitals(iorb).Intra_nn2_centre(in,1:3) - orbitals(iorb).Centre; 121 | 122 | % Get connecting vector between centres 123 | 124 | % Find type of hopping 125 | hij = hopping*exp(1i*dot(delta,k)); 126 | Hmat(iorb,jorb) = Hmat(iorb,jorb) + hij; 127 | if(gradient) 128 | gradH_x(iorb,jorb) = gradH_x(iorb,jorb) - delta(1)*hij - 1i*delta(2)*hij; 129 | end 130 | end 131 | end 132 | end 133 | end 134 | 135 | H_rotated = false; 136 | % Add interlayer interaction 137 | if(multilayer && interlayer_int) 138 | % Rotate Hamiltonian into unsymmetrised basis 139 | Hmat = T'*(Hmat*T); 140 | % Apply mask for 2H stackings 141 | Hmat = Mxz'*Hmat*Mxz; 142 | % Check Hamiltonian is Hermitian 143 | if(gradient) 144 | gradH_x = T'*(gradH_x*T); 145 | [Hmat,gradH_x] = Vint(Hmat,nlayer,orbitals,pp_vint_z,pp_vint_parm,pd_vint_lay1_z,pd_vint_lay1_parm,pd_vint_lay2_z,pd_vint_lay2_parm,k,theta,Interpd,nspins,gradient,gradH_x); 146 | else 147 | [Hmat] = Vint(Hmat,nlayer,orbitals,pp_vint_z,pp_vint_parm,pd_vint_lay1_z,pd_vint_lay1_parm,pd_vint_lay2_z,pd_vint_lay2_parm,k,theta,Interpd,nspins,gradient); 148 | end 149 | H_rotated = true; 150 | end 151 | 152 | % Add SOC 153 | if (lsoc) 154 | if (~H_rotated) 155 | Hmat = T'*(Hmat*T); 156 | H_rotated = true; 157 | end 158 | for ilayer = 1 : nlayer 159 | Hmat = add_soc(Hmat,Hsoc{ilayer},orbitals,ilayer); 160 | end 161 | end 162 | 163 | %check if Hamiltonian is Hermitian 164 | %if(normest(Hmat-Hmat')>1E-4) 165 | % disp('WARNING: Hamiltonian is not Hermitian!') 166 | % error('Error: Hamiltonian is not hermitian!') 167 | %end 168 | Hmat = 0.5*(Hmat+Hmat'); 169 | if(gradient) 170 | gradH_x = 0.5*(gradH_x+gradH_x'); 171 | end 172 | end 173 | -------------------------------------------------------------------------------- /TB/src/cheval.m: -------------------------------------------------------------------------------- 1 | function eval = cheval(Ctype,An,xv) 2 | % 3 | % cheval evaluates any one of the four types of Chebyshev series. 4 | % It is a Matlab translation of the Fortran function EVAL 5 | % found in page 20 of: 6 | % Y.L. Luke, Algorithms for the computation of mathematical functions 7 | % Academic Press, 1977, p.20 8 | % 9 | % Author : T.P. Theodoulidis 10 | % Date : 11 June 2012 11 | % 12 | % Ctype (string): type of Chebyshev polynomial 13 | % 'regular' T_n(x) 14 | % 'shifted' T*_n(x) 15 | % 'even' T_2n(x) 16 | % 'odd' T_2n+1(x) 17 | % An : vector of Chebyshev coefficients 18 | % z : argument, can be scalar, vector, matrix 19 | % 20 | switch Ctype 21 | case {'regular'} 22 | log1=1; log2=1; 23 | case {'shifted'} 24 | log1=1; log2=0; 25 | case {'even'} 26 | log1=0; log2=1; 27 | case {'odd'} 28 | log1=0; log2=0; 29 | otherwise 30 | return; 31 | end 32 | % 33 | x=xv(:); 34 | % 35 | xfac=2*(2*x-1); 36 | if log1 && log2, xfac=2*x; end 37 | if ~log1, xfac=2*(2*x.*x-1); end 38 | n=length(An); 39 | n1=n+1; 40 | Bn=zeros(length(x),n1+1); 41 | % 42 | for j=1:n 43 | Bn(:,n1-j)=xfac.*Bn(:,n1+1-j)-Bn(:,n1+2-j)+An(n1-j); 44 | end 45 | eval=Bn(:,1)-xfac.*Bn(:,2)/2; 46 | if ~log1 && ~log2, eval=x.*(Bn(:,1)-Bn(:,2)); end 47 | eval=reshape(eval,size(xv)); 48 | % 49 | -------------------------------------------------------------------------------- /TB/src/colorGradient.m: -------------------------------------------------------------------------------- 1 | function [grad,im]=colorGradient(c1,c2,depth) 2 | % COLORGRADIENT allows you to generate a gradient between 2 given colors, 3 | % that can be used as colormap in your figures. 4 | % 5 | % USAGE: 6 | % 7 | % [grad,im]=getGradient(c1,c2,depth) 8 | % 9 | % INPUT: 10 | % - c1: color vector given as Intensity or RGB color. Initial value. 11 | % - c2: same as c1. This is the final value of the gradient. 12 | % - depth: number of colors or elements of the gradient. 13 | % 14 | % OUTPUT: 15 | % - grad: a matrix of depth*3 elements containing colormap (or gradient). 16 | % - im: a depth*20*3 RGB image that can be used to display the result. 17 | % 18 | % EXAMPLES: 19 | % grad=colorGradient([1 0 0],[0.5 0.8 1],128); 20 | % surf(peaks) 21 | % colormap(grad); 22 | % 23 | % -------------------- 24 | % [grad,im]=colorGradient([1 0 0],[0.5 0.8 1],128); 25 | % image(im); %display an image with the color gradient. 26 | % Copyright 2011. Jose Maria Garcia-Valdecasas Bernal 27 | % v:1.0 22 May 2011. Initial release. 28 | %Check input arguments. 29 | %input arguments must be 2 or 3. 30 | error(nargchk(2, 3, nargin)); 31 | %If c1 or c2 is not a valid RGB vector return an error. 32 | if numel(c1)~=3 33 | error('color c1 is not a valir RGB vector'); 34 | end 35 | if numel(c2)~=3 36 | error('color c2 is not a valir RGB vector'); 37 | end 38 | if max(c1)>1&&max(c1)<=255 39 | %warn if RGB values are given instead of Intensity values. Convert and 40 | %keep procesing. 41 | warning('color c1 is not given as intensity values. Trying to convert'); 42 | c1=c1./255; 43 | elseif max(c1)>255||min(c1)<0 44 | error('C1 RGB values are not valid.') 45 | end 46 | if max(c2)>1&&max(c2)<=255 47 | %warn if RGB values are given instead of Intensity values. Convert and 48 | %keep procesing. 49 | warning('color c2 is not given as intensity values. Trying to convert'); 50 | c2=c2./255; 51 | elseif max(c2)>255||min(c2)<0 52 | error('C2 RGB values are not valid.') 53 | end 54 | %default depth is 64 colors. Just in case we did not define that argument. 55 | if nargin < 3 56 | depth=64; 57 | end 58 | %determine increment step for each color channel. 59 | dr=(c2(1)-c1(1))/(depth-1); 60 | dg=(c2(2)-c1(2))/(depth-1); 61 | db=(c2(3)-c1(3))/(depth-1); 62 | %initialize gradient matrix. 63 | grad=zeros(depth,3); 64 | %initialize matrix for each color. Needed for the image. Size 20*depth. 65 | r=zeros(20,depth); 66 | g=zeros(20,depth); 67 | b=zeros(20,depth); 68 | %for each color step, increase/reduce the value of Intensity data. 69 | for j=1:depth 70 | grad(j,1)=c1(1)+dr*(j-1); 71 | grad(j,2)=c1(2)+dg*(j-1); 72 | grad(j,3)=c1(3)+db*(j-1); 73 | r(:,j)=grad(j,1); 74 | g(:,j)=grad(j,2); 75 | b(:,j)=grad(j,3); 76 | end 77 | %merge R G B matrix and obtain our image. 78 | im=cat(3,r,g,b); -------------------------------------------------------------------------------- /TB/src/compute_amn.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % 3 | % Function to compute the Amn matrices 4 | % from the TB eigenvectors in the 5 | % format required by Wannier90 6 | % 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | 9 | fid = fopen(amn_fname,'w'); 10 | time = datestr(clock,'YYYY/mm/dd HH:MM:SS:FFF'); 11 | fprintf(fid,'%50s\n',join(['File generated with twisted bilayer studio. ',time])); 12 | num_loc_bands = tot_norbs-num_exclude_bands; 13 | if(~lsoc) 14 | fprintf(fid,'%i \t %i \t %i\n',num_loc_bands,knum_tot,num_proj); 15 | else 16 | fprintf(fid,'%i \t %i \t %i\n',num_loc_bands,knum_tot,num_sproj); 17 | end 18 | iik = 0; 19 | loc_bands = setdiff([1:tot_norbs],exclude_bands); 20 | 21 | % check the number of bands is correct 22 | if(num_loc_bands ~= length(loc_bands)) 23 | error('Wrong number of bands!') 24 | end 25 | 26 | if(~lsoc) 27 | if(num_proj == tot_norbs) 28 | % Make sure we have exactly 5d orbitals per metal atom 29 | % and 3p orbitals per chalcogen atom 30 | if(nnz(ismember(proj_qnum(:,1),1))~=tot_norbs/11*6) 31 | error('number of p orbitals in projection block not correct!') 32 | end 33 | if(nnz(ismember(proj_qnum(:,1),2))~=tot_norbs/11*5) 34 | error('number of d orbitals in projection block not correct!') 35 | end 36 | % Assign each projection to an orbital in the TB basis 37 | proj2orb = zeros(num_proj,1); 38 | for iproj = 1 : num_proj 39 | for jorb = 1 : tot_norbs 40 | if(norm(proj_centres(iproj,:)-coords(jorb,:))<1e-4 &&... 41 | proj_qnum(iproj,1) == orbitals(jorb).l && ... 42 | proj_qnum(iproj,2) == orbitals(jorb).m) 43 | proj2orb(iproj) = jorb; 44 | end 45 | end 46 | end 47 | end 48 | 49 | % MAIN LOOP 50 | if(num_proj == tot_norbs) 51 | if(num_loc_bands == num_proj) 52 | for ikpt = 1 : knum_tot 53 | for iwann = 1 : num_proj 54 | for iband = 1 : num_proj 55 | amn = conj(tb_vecs(proj2orb(iwann),iband,ikpt))*exp(-1.i*dot(all_kpts(ik,:),coords(proj2orb(iwann),:))); 56 | fprintf(fid,'%i \t %i \t %i \t %+2.8f \t %+2.8f\n', iband, proj2orb(iwann), ikpt, real(amn), imag(amn)); 57 | end 58 | end 59 | end 60 | end 61 | elseif(num_proj < tot_norbs && num_proj > 0) 62 | % NB: only s orbitals are allowed in this case! 63 | % All these checks should be moved in w90_nnkp 64 | if(any(proj_qnum(:,1)~=0)) 65 | error('Only s orbitals can be specified if num_proj not the same as total number of orbitals!') 66 | end 67 | rcut_thr = 1e-5; 68 | for ikpt = 1 : knum_tot 69 | for iband = 1 : num_loc_bands 70 | % Run over all orbitals and compute integrals, assuming each orbital to be 71 | % delta function 72 | for iwann = 1 : num_proj 73 | % Compute cutoff radius 74 | zona = proj_zona(iwann); 75 | rcut = log(rcut_thr * sqrt(4*pi) / (2*zona))*(-1.0/zona) 76 | if(rcut > min(norm(mcell(1,:)),norm(mcell(2,:)))/2) 77 | error('Projection function too spread out. Increase zona value!') 78 | end 79 | % compute integrals including only those orbitals whose distance from the center is less then rcut 80 | amn = complex(0.0,0.0); 81 | for jorb = 1 : tot_norbs 82 | for icell = -1 : 1 83 | for jcell = -1 : 1 84 | Rtauj = coords(jorb,:)+icell*mcell(1,:)+jcell*mcell(2,:); 85 | if(norm(proj_centres(iwann,:)-Rtauj) 0) 134 | % NB: only s orbitals are allowed in this case! 135 | % All these checks should be moved in w90_nnkp 136 | if(any(sproj_qnum(:,1)~=0)) 137 | error('Only s orbitals can be specified if num_proj not the same as total number of orbitals!') 138 | end 139 | rcut_thr = 1e-5; 140 | for ikpt = 1 : knum_tot 141 | for iband = 1 : num_loc_bands 142 | % Run over all orbitals and compute integrals, assuming each orbital to be 143 | % delta function 144 | for iwann = 1 : num_sproj 145 | % Compute cutoff radius 146 | zona = sproj_zona(iwann); 147 | rcut = log(rcut_thr * sqrt(4*pi) / (2*zona))*(-1.0/zona); 148 | if(rcut > min(norm(mcell(1,:)),norm(mcell(2,:)))/2) 149 | error('Projection function too spread out. Increase zona value!') 150 | end 151 | % compute integrals including only those orbitals whose distance from the center is less then rcut 152 | amn = complex(0.0,0.0); 153 | for jorb = 1 : tot_norbs 154 | for icell = -1 : 1 155 | for jcell = -1 : 1 156 | Rtauj = coords(jorb,:)+icell*mcell(1,:)+jcell*mcell(2,:); 157 | if(norm(sproj_centres(iwann,:)-Rtauj) 0) 30 | nn_up = nn_up + 1; 31 | if(nn_up > 3) 32 | error('Too many neighbors') 33 | end 34 | chalc_atoms_up(nn_up,:) = dist; 35 | elseif(dist(3) < 0) 36 | nn_down = nn_down + 1; 37 | if(nn_down > 3) 38 | error('Too many neighbors') 39 | end 40 | chalc_atoms_down(nn_down,:) = dist; 41 | end 42 | end 43 | end 44 | end 45 | end 46 | end 47 | pts_up = [chalc_atoms_up;[0 0 0]]; 48 | pts_down = [[0 0 0];chalc_atoms_down]; 49 | [K_up,V_up] = convhull(pts_up(:,1),pts_up(:,2),pts_up(:,3)); 50 | [K_down,V_down] = convhull(pts_down(:,1),pts_down(:,2),pts_down(:,3)); 51 | %pts = [chalc_atoms_up;chalc_atoms_down]; 52 | %[K,V] = convhull(pts(:,1),pts(:,2),pts(:,3)); 53 | deformation(iat) = ((V_down-V0)+(V_up-V0))/(2*V0); 54 | if(exist("plot_surf",'var') ... 55 | && plot_surf && iiat==1) 56 | figure 57 | trisurf(K_down,pts_down(:,1),pts_down(:,2),pts_down(:,3),'Facecolor','cyan'); 58 | hold on 59 | plot3(pts_down(:,1),pts_down(:,2),pts_down(:,3),'.r') 60 | end 61 | end 62 | 63 | %met_coor = [coor.x(ind_met) coor.y(ind_met) coor.z(ind_met)]; 64 | %supercell = [repmat(-mcell(1,:)-mcell(2,:),[natoms_met,1]); 65 | % repmat(-mcell(1,:),[natoms_met,1]); 66 | % repmat(-mcell(1,:)+mcell(2,:),[natoms_met,1]); 67 | % repmat(-mcell(2,:),[natoms_met,1]); 68 | % repmat([0 0 0],[natoms_met,1]); 69 | % repmat(mcell(2,:),[natoms_met,1]); 70 | % repmat(mcell(1,:)-mcell(2,:),[natoms_met,1]); 71 | % repmat(mcell(1,:),[natoms_met,1]); 72 | % repmat(mcell(1,:)+mcell(2,:),[natoms_met,1]);] + repmat(met_coor,[9,1]); 73 | %index_atom_supercell = repmat([1:natoms_met]',[9,1]); 74 | %average_deformation = average_radius(deformation(ind_met),natoms_met,met_coor,1.2*sqrt(3)*a0(1),supercell,index_atom_supercell); 75 | %def_avg(ind_met) = average_deformation; 76 | %figure 77 | %scatter3(coor.x(ind_met),coor.y(ind_met),coor.z(ind_met),100,deformation(ind_met),'filled') 78 | %colorbar 79 | 80 | % Computes macroscopic average over a lattice 81 | function value_on_lattice = average_radius(chern_op,num_atoms,at_pos,cutoff,at_pos_supercell,... 82 | index_atom_supercell) 83 | for iat = 1 : num_atoms 84 | dist_all = sum((at_pos(iat,:) - at_pos_supercell).^2,2); 85 | in_cutoff = find(dist_all <= cutoff^2); 86 | value_on_lattice(iat) = sum(chern_op(index_atom_supercell(in_cutoff)))./length(in_cutoff); 87 | end 88 | end 89 | end 90 | -------------------------------------------------------------------------------- /TB/src/deformation_potential_porbs.m: -------------------------------------------------------------------------------- 1 | function deformation = deformation_potential_porbs(deformation,coor,natoms,mcell,a0,nlayers) 2 | def_avg = zeros(natoms,1); 3 | ind_chalc = find(strcmp(coor.name,'S')); 4 | if(isempty(ind_chalc)) 5 | ind_chalc = find(strcmp(coor.name,'Se')); 6 | end 7 | natoms_chalc = length(ind_chalc); 8 | for iiat = 1 : natoms_chalc 9 | iat = ind_chalc(iiat); 10 | iatom = [coor.x(iat) coor.y(iat) coor.z(iat)]; 11 | nn = 0; 12 | nn_metal_atoms = zeros(3,3); 13 | layer = coor.layer(iat); 14 | % Area of hexagon composed of Chalcogen atoms 15 | S0 = sqrt(3)/4 * a0(layer)^2; 16 | h = (1.5 - 2*0.6226)*mcell(3,3); 17 | V0 = (S0 * h/2)/3; 18 | for jat = 1 : natoms 19 | if(layer == coor.layer(jat) && iat ~= jat) 20 | for ic = -1 : 1 21 | for jc = -1 : 1 22 | jatom = [coor.x(jat) coor.y(jat) coor.z(jat)] + ic*mcell(1,:) + jc*mcell(2,:); 23 | dist = iatom - jatom; 24 | if(abs(norm(dist(1:2)) - a0(layer)/sqrt(3)) < 0.1) 25 | nn = nn + 1; 26 | if(nn > 3) 27 | error('Too many neighbors') 28 | end 29 | nn_metal_atoms(nn,:) = dist; 30 | end 31 | end 32 | end 33 | end 34 | end 35 | %nn_chalc_atoms(4,:) = nn_chalc_atoms(1,:); 36 | 37 | %rad = cart2pol(nn_chalc_atoms(:,1),nn_chalc_atoms(:,2));%poly2cw(nn_chalc_atoms(:,1),nn_chalc_atoms(:,2)); 38 | %radWrapped = mod(rad,2*pi); 39 | %radWrapped(radWrapped==0 & rad>0) = 2*pi; 40 | %[~, sortIdx] = sort(radWrapped, 'descend'); 41 | %sortedData = nn_chalc_atoms(sortIdx,:); 42 | %S = polyarea(sortedData(:,1),sortedData(:,2)); 43 | %deformation(iat) = ((abs((S_up-S0)) - abs(S_down-S0))/S0)*100; %tanh((dist-L/2)/4)*(1.0 - 44 | [K,V] = convhull([nn_metal_atoms;[0 0 0]]); 45 | deformation(iat) =(V-V0)/(V0); %tanh((dist-L/2)/4)*(1.0 - 46 | end 47 | 48 | % chalc_coor = [coor.x(ind_chalc) coor.y(ind_chalc) coor.z(ind_chalc)]; 49 | % supercell = [repmat(-mcell(1,:)-mcell(2,:),[natoms_chalc,1]); 50 | % repmat(-mcell(1,:),[natoms_chalc,1]); 51 | % repmat(-mcell(1,:)+mcell(2,:),[natoms_chalc,1]); 52 | % repmat(-mcell(2,:),[natoms_chalc,1]); 53 | % repmat([0 0 0],[natoms_chalc,1]); 54 | % repmat(mcell(2,:),[natoms_chalc,1]); 55 | % repmat(mcell(1,:)-mcell(2,:),[natoms_chalc,1]); 56 | % repmat(mcell(1,:),[natoms_chalc,1]); 57 | % repmat(mcell(1,:)+mcell(2,:),[natoms_chalc,1]);] + repmat(chalc_coor,[9,1]); 58 | % index_atom_supercell = repmat([1:natoms_chalc]',[9,1]); 59 | % average_deformation = average_radius(deformation(ind_chalc),natoms_chalc,chalc_coor,1.2*sqrt(3)*a0(1),supercell,index_atom_supercell); 60 | % def_avg(ind_chalc) = average_deformation; 61 | %figure 62 | %scatter3(coor.x(ind_chalc),coor.y(ind_chalc),coor.z(ind_chalc),100,deformation(ind_chalc),'filled') 63 | %colorbar 64 | 65 | % Computes macroscopic average over a lattice 66 | function value_on_lattice = average_radius(chern_op,num_atoms,at_pos,cutoff,at_pos_supercell,... 67 | index_atom_supercell) 68 | for iat = 1 : num_atoms 69 | dist_all = sum((at_pos(iat,:) - at_pos_supercell).^2,2); 70 | in_cutoff = find(dist_all <= cutoff^2); 71 | value_on_lattice(iat) = sum(chern_op(index_atom_supercell(in_cutoff)))./length(in_cutoff); 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /TB/src/generate_T.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Routine to generate rotation matrix from 3 | % symmetrised to unsymmetrised basis 4 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5 | % Inputs: 6 | % orbitals - orbitals class 7 | % norbs - Number of orbitals 8 | % 9 | % Outputs: 10 | % T - rotation matrix 11 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 12 | % Written by Valerio Vitale 13 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 14 | 15 | function T = generate_T(orbitals,norbs,nspin,nlayer) 16 | T = zeros(norbs); 17 | for spin = -nspin + 1 : 2 : nspin - 1 18 | orb1 = findobj(orbitals,'l',2,'Spin',spin); 19 | diorb = [orb1.Ham_index]; 20 | clear orb1; 21 | for ii = 1 : size(diorb,2) 22 | iorb = diorb(ii); 23 | for jj = 1 : size(diorb,2) 24 | jorb = diorb(jj); 25 | if((orbitals(jorb).Centre == orbitals(iorb).Centre)) 26 | if (orbitals(jorb).Rel_index == orbitals(iorb).Rel_index) 27 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = 1.0; 28 | end 29 | end 30 | end 31 | end 32 | 33 | for ilayer = 1 : nlayer 34 | orb1 = findobj(orbitals,'l',1,'Spin', spin,'Layer',ilayer); 35 | piorb = [orb1.Ham_index]; 36 | clear orb1; 37 | for ii = 1 : size(piorb,2) 38 | iorb = piorb(ii); 39 | for jj = 1 : size(piorb,2) 40 | jorb = piorb(jj); 41 | if(norm(orbitals(jorb).Centre-orbitals(iorb).Centre) < 0.1) 42 | if(orbitals(iorb).Rel_index == 3 && orbitals(jorb).Rel_index == 3) 43 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = 1/sqrt(2); 44 | elseif(orbitals(iorb).Rel_index == 4 && orbitals(jorb).Rel_index == 4) 45 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = -1/sqrt(2); 46 | elseif(orbitals(iorb).Rel_index == 5 && orbitals(jorb).Rel_index == 5) 47 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = -1/sqrt(2); 48 | elseif(orbitals(iorb).Rel_index == 9 && orbitals(jorb).Rel_index == 9) 49 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = 1/sqrt(2); 50 | elseif(orbitals(iorb).Rel_index == 10 && orbitals(jorb).Rel_index == 10) 51 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = 1/sqrt(2); 52 | elseif(orbitals(iorb).Rel_index == 11 && orbitals(jorb).Rel_index == 11) 53 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = 1/sqrt(2); 54 | elseif(orbitals(iorb).Rel_index == 3 && orbitals(jorb).Rel_index == 9) 55 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = 1/sqrt(2); 56 | elseif(orbitals(iorb).Rel_index == 4 && orbitals(jorb).Rel_index == 10) 57 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = 1/sqrt(2); 58 | elseif(orbitals(iorb).Rel_index == 5 && orbitals(jorb).Rel_index == 11) 59 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = 1/sqrt(2); 60 | elseif(orbitals(iorb).Rel_index == 9 && orbitals(jorb).Rel_index == 3) 61 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = -1/sqrt(2); 62 | elseif(orbitals(iorb).Rel_index == 10 && orbitals(jorb).Rel_index == 4) 63 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = 1/sqrt(2); 64 | elseif(orbitals(iorb).Rel_index == 11 && orbitals(jorb).Rel_index == 5) 65 | T(orbitals(iorb).Ham_index,orbitals(jorb).Ham_index) = 1/sqrt(2); 66 | end 67 | end 68 | end 69 | end 70 | end 71 | end 72 | 73 | end 74 | -------------------------------------------------------------------------------- /TB/src/generate_k_line.m: -------------------------------------------------------------------------------- 1 | function [ allks, rsegind] = generate_k_line( num_kpts, klist ) 2 | % Reference citation: Phys. Rev. B 92, 205108 (2015). 3 | % Ab initio tight-binding Hamiltonian for transition metal dichalcogenides 4 | % by Shiang Fang, Rodrick Kuate Defo, Sharmila N. Shirodkar, Simon Lieu, Georgios A. Tritsaris, and Efthimios Kaxiras 5 | % code version: July 2017 6 | 7 | klist_size=size(klist); 8 | num_segs=klist_size(1)-1; 9 | allks=zeros(num_segs*num_kpts,3); 10 | rsegind=zeros(num_segs*num_kpts,1); 11 | 12 | comp=linspace(0,1,num_kpts); 13 | 14 | ind=1; 15 | 16 | seg_length(1)=0; 17 | for inds=1:num_segs 18 | kstart=klist(inds,:); 19 | kend=klist(inds+1,:); 20 | deltak=kend-kstart; 21 | seg_length(inds+1)=sqrt(dot(deltak,deltak)); 22 | for indk=1:num_kpts 23 | allks(ind,:)=kstart+comp(indk)*(kend-kstart); 24 | ind=ind+1; 25 | end 26 | end 27 | 28 | sum_seg_length=cumsum(seg_length)/sum(seg_length); 29 | 30 | ind=1; 31 | for inds=1:num_segs 32 | segstart=sum_seg_length(inds); 33 | segend=sum_seg_length(inds+1); 34 | 35 | for indk=1:num_kpts 36 | rsegind(ind,:)=segstart+comp(indk)*(segend-segstart); 37 | ind=ind+1; 38 | end 39 | end 40 | 41 | end 42 | -------------------------------------------------------------------------------- /TB/src/generate_kpoints.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | %% Generate k-point set for %% 3 | %% for bandstructure calculations %% 4 | %% along the Gamma-M-K-Gamma path %% 5 | %% and for DOS/LDOS/chern etc. on %% 6 | %% a uniform M.P. grid %% 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | %% %% 9 | %% Written by Valerio Vitale %% 10 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 11 | function [all_kpts,scale_axis,knum_tot,recL,frac_k] = generate_kpoints(task,multilayer,twisted,miniBZ,mb1,mb2,mb3,b1,b2,b3,knum,bse_shifted) 12 | 13 | % If computing bandstructure set \Gamma-M-K-\Gamma path 14 | if(task==1 || task==6) 15 | 16 | % If twisted bilayer, find high-symmetry k-points of monolayer BZ with respect to the vectors of the 17 | % mini-Brillouin zone 18 | if(multilayer && twisted && ~miniBZ) 19 | recL=[mb1;mb2;mb3]; 20 | k1=[0,0,0]; 21 | k2=b2/2; 22 | k3=(2*b1-b2)/3; 23 | %k1=(2*b1+b2)/3; 24 | %k2=(b1+2*b2)/6; 25 | %k3= [0 0 0]; 26 | fM = k2*inv(recL); 27 | fK = k3*inv(recL); 28 | % Find closest M and K points 29 | C3 = [cos(pi/3) sin(pi/3) 0; -sin(pi/3) cos(pi/3) 0; 0 0 1]; 30 | k3_all = [k3;k3*C3;k3*C3*C3;k3*C3*C3*C3;k3*C3*C3*C3*C3;k3*C3*C3*C3*C3*C3]; 31 | [minv,iv] = min(sqrt(sum((k3_all - k2).^2,2))); 32 | k3 = k3_all(iv,:); 33 | fK = k3*inv(recL); 34 | if(abs(fM(1)) >= 1) 35 | if(fM(1) > 0) 36 | fM(1) = fM(1) - floor(fM(1)); % 37 | else 38 | fM(1) = fM(1) - ceil(fM(1)); % 39 | end 40 | end 41 | if(abs(fM(2)) >= 1) 42 | if(fM(2) > 0) 43 | fM(2) = fM(2) - floor(fM(2)); % 44 | else 45 | fM(2) = fM(2) - ceil(fM(2)); % 46 | end 47 | end 48 | if(abs(fK(1)) >= 1) 49 | if(fK(1) > 0) 50 | fK(1) = fK(1) - floor(fK(1)); % 51 | else 52 | fK(1) = fK(1) - ceil(fK(1)); % 53 | end 54 | end 55 | if(abs(fK(2)) >= 1) 56 | if(fK(2) > 0) 57 | fK(2) = fK(2) - floor(fK(2)); % 58 | else 59 | fK(2) = fK(2) - ceil(fK(2)); % 60 | end 61 | end 62 | fM = [0.5 0.0 0.0]; 63 | fK = [2/3 -1/3 0]; 64 | k2 = fM*recL; 65 | k3 = fK*recL; 66 | else 67 | recL = [mb1;mb2;mb3];% 68 | k1 = [0,0,0]; 69 | k2 = [0.5,0,0]*recL; 70 | k3 = [2/3,-1/3,0]*recL; 71 | end 72 | % Generate path in k-space 73 | 74 | scan_klist=[k1;k2;k3;k1]; 75 | 76 | [ all_kpts, scale_axis] = generate_k_line( knum, scan_klist ); 77 | dk = norm(all_kpts(2,:) - all_kpts(1,:)); 78 | dk = dk*0.529177210903; 79 | knum_tot=size(all_kpts); 80 | knum_tot=knum_tot(1); 81 | frac_k = all_kpts*(inv(recL)); 82 | %[all_kpts, ones(knum_tot,1)/knum_tot] 83 | elseif(task==2 || task==3 || task==4 || task==5 || task==7) 84 | 85 | recL = [mb1;mb2;mb3];% 86 | K = zeros(knum*knum,3); 87 | all_kpts = zeros(knum*knum,3); 88 | kxi=0; 89 | kyi=0; 90 | kxf=(knum-1)/knum; 91 | kyf=kxf; 92 | kx=linspace(kxi,kxf,knum); 93 | ky=linspace(kyi,kyf,knum); 94 | ikk = 0; 95 | for ikx = 1 : knum 96 | for iky = 1 : knum 97 | ikk = ikk + 1; 98 | K(ikk,:) = [kx(ikx),ky(iky),0.0]; 99 | end 100 | end 101 | scale_axis = sqrt(sum(K.^2,2)); 102 | all_kpts = K*recL; 103 | knum_tot = knum*knum; 104 | % Shift the uniform grid by a small dk with a positive random direction 105 | % for the calculation of BSE eigenvalues/eigenfunctions 106 | if(task == 5 && bse_shifted) 107 | % Fix the seed for the random number generator 108 | rng(42); 109 | cost = rand(1); 110 | sint = sqrt(1-cost); 111 | shift = norm(all_kpts(2,:)-all_kpts(1,:))/10 * [cost,sint,0]; 112 | all_kpts = all_kpts + shift; 113 | end 114 | clear K; 115 | end 116 | end 117 | -------------------------------------------------------------------------------- /TB/src/generate_mask.m: -------------------------------------------------------------------------------- 1 | function M = generate_mask(orbitals,tot_norbs,nlayer,flipped) 2 | M = eye(tot_norbs); 3 | I = ones(tot_norbs,1); 4 | for ilayer = 1 : nlayer 5 | if(flipped(ilayer)==1) 6 | orby = findobj(orbitals,'Layer',ilayer,{'Rel_index',2,'-or','Rel_index',5,'-or','Rel_index',7,'-or','Rel_index',11}); 7 | lorby = [orby(:).Ham_index]; 8 | I(lorby) = -1; 9 | end 10 | end 11 | M = M.*I; 12 | end 13 | -------------------------------------------------------------------------------- /TB/src/interpolate_SK.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Routine to choose more accurate Slater-Koster 3 | % interlayer parameters for interlayer p-p and 4 | % pz-dz2 interactions. Interpolates to given 5 | % vertical distance for two atoms involved in 6 | % hopping 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | % Inputs: 9 | % hop - Type of hopping parameter: 1: 'pp' or 2: 'pd' 10 | % dsqr - Modulus of distance between 2 atoms 11 | % rz - Magnitude of z-component of the connecting 12 | % vector between 2 atoms involved in hopping 13 | % zpar - Interlayer seperations corresponding to each 14 | % parameter in intpar cell array 15 | % intpar - SK parameter cell array for each 16 | % interlayer seperation 17 | % 18 | % Outputs: 19 | % Vsigval - Interpolated value of the SK parm. Vsig 20 | % Vpival - Interpolated value of the SK param. Vpi 21 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 22 | % Written by Kemal Atalar 23 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 24 | function [Vsigval,Vpival] = interpolate_SK(hop,dsqr,rz,zpar,intpar) 25 | 26 | % Range 27 | zpar = cell2mat(zpar); 28 | 29 | % Range of hopping values calculated at different parameters 30 | Vsig_lst = zeros(size(intpar)); 31 | Vpi_lst = zeros(size(intpar)); 32 | 33 | % Calculate hoppings to put in hoprange 34 | for ii = 1 : length(intpar) 35 | % Choose the type of hopping values to interpolate 36 | if(hop == 1) 37 | % p-p SL parameters 38 | Vsig = intpar{ii}(1)*exp(-(dsqr/abs(intpar{ii}(3)))^intpar{ii}(5)); 39 | Vpi = intpar{ii}(2)*exp(-(dsqr/abs(intpar{ii}(4)))^intpar{ii}(6)); 40 | elseif(hop == 2) 41 | % pd SK parameters 42 | Vsig = intpar{ii}(1)*(dsqr^intpar{ii}(3))*cos(intpar{ii}(5)*dsqr + intpar{ii}(7)); 43 | Vpi = intpar{ii}(2)*(dsqr^intpar{ii}(4))*cos(intpar{ii}(6)*dsqr + intpar{ii}(8)); 44 | else 45 | error('Incorrect hopping type set in interpolate_SK.m') 46 | end 47 | Vsig_lst(ii) = Vsig; % add to array 48 | Vpi_lst(ii) = Vpi; % add to array 49 | end 50 | 51 | % Interpolate if it is in zpar range 52 | % (might implement extrapolation in the future if out of range) 53 | % Try to extrapolate 54 | if(rz < zpar(1)) 55 | Vsigval=interp1(zpar,Vsig_lst,rz,'spline','extrap'); 56 | Vpival=interp1(zpar,Vpi_lst,rz,'spline','extrap'); 57 | % Try to extrapolate 58 | elseif(rz > zpar(length(zpar))) 59 | %Vsigval=Vsig_lst(length(zpar)); 60 | %Vpival=Vpi_lst(length(zpar)); 61 | Vsigval=interp1(zpar,Vsig_lst,rz,'spline','extrap'); 62 | Vpival=interp1(zpar,Vpi_lst,rz,'spline','extrap'); 63 | else 64 | % Interpolate with a spline method 65 | Vsigval=interp1(zpar,Vsig_lst,rz,'spline'); 66 | Vpival=interp1(zpar,Vpi_lst,rz,'spline'); 67 | end 68 | 69 | end 70 | -------------------------------------------------------------------------------- /TB/src/keldysh_pot.m: -------------------------------------------------------------------------------- 1 | function y = keldysh_pot(dist,inat,jnat,a) 2 | ed = 2.5; 3 | r0 = 33.875/ed; 4 | U = 1; 5 | keldysh_prefactor = 22.59; 6 | tV = 0; 7 | if(dist==0) 8 | tV = -U/(ed*r0) * (StruveH0(a/sqrt(3)/r0)-bessely(0,a/sqrt(3)/r0)); 9 | else 10 | tV = -1/(ed*r0) * (StruveH0(dist/r0)-bessely(0,dist/r0)); 11 | end 12 | y = keldysh_prefactor*tV; 13 | end 14 | -------------------------------------------------------------------------------- /TB/src/keldysh_pot2.m: -------------------------------------------------------------------------------- 1 | function y = keldysh_pot2(q,R,positions,nat,a,shift,knum_tot) 2 | % These are hard-coded at the moment 3 | % TODO: make these input variables 4 | ed = 2.5; 5 | r0 = 33.875/ed; 6 | U = 1; 7 | keldysh_prefactor = 22.59; 8 | y = zeros(nat); 9 | qmat = repmat(q,[nat,1]); 10 | T = [positions(:).x,positions(:).y,positions(:).z] - shift; 11 | tij_mat = repmat(T,[1,nat]) - repmat(reshape(T',[1,nat*3]),[nat,1]); 12 | for iR = 1 : knum_tot 13 | %qdotR = dot(q,R(iR,:)); 14 | for inat = 1 : nat 15 | %ti = [positions.x(inat),positions.y(inat),positions.z(inat)] - shift; 16 | tijR_mat = tij_mat(:,(inat-1)*3 + 1 : (inat-1)*3 + 3 ) + R(iR,:); 17 | eiqdotRt_mat = exp(1i.*dot(qmat,tijR_mat,2)); 18 | dist_mat = vecnorm(tijR_mat,2,2); 19 | dist_mat(dist_mat == 0) = a/sqrt(3); 20 | % for jnat = 1 : nat 21 | % tj = [positions.x(jnat),positions.y(jnat),positions.z(jnat)] - shift; 22 | % tji = tj - ti; 23 | % qdott = dot(q,tji); 24 | % dist = norm(R(iR,:) + tji); 25 | % tV = 0; 26 | % if(dist==0) 27 | % tV = -U/(ed*r0) * (StruveH0(a/sqrt(3)/r0)-bessely(0,a/sqrt(3)/r0)); 28 | % else 29 | tV = -U/(ed*r0) * (StruveH0(dist_mat/r0)-bessely(0,dist_mat/r0)); 30 | % end 31 | % y(inat,jnat) = keldysh_prefactor*tV*exp(1i*qdotR)*exp(1i*qdott); 32 | y(inat,:) = keldysh_prefactor.*tV'.*conj(eiqdotRt_mat'); 33 | % end 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /TB/src/keldysh_pot3.m: -------------------------------------------------------------------------------- 1 | function y = keldysh_pot2(q,R,positions,nat,a,shift,knum_tot) 2 | % These are hard-coded at the moment 3 | % TODO: make these input variables 4 | ed = 2.5; 5 | r0 = 33.875/ed; 6 | U = 1; 7 | keldysh_prefactor = 22.59; 8 | y = zeros(nat); 9 | dist_mat = zeros(nat); 10 | Tx = [positions(:).x] - shift(1); 11 | Ty = [positions(:).y] - shift(2); 12 | Tz = [positions(:).z] - shift(3); 13 | Tx_mat = repmat(Tx',[nat,1]) - repmat(Tx,[1,nat]); 14 | Ty_mat = repmat(Ty',[nat,1]) - repmat(Ty,[1,nat]); 15 | Tz_mat = repmat(Tz',[nat,1]) - repmat(Tz,[1,nat]); 16 | for iR = 1 : knum_tot 17 | eiqdotR = exp(1i*dot(q,R(iR,:))); 18 | RTx_mat = (Tx_mat + R(iR,1)).^2; 19 | RTy_mat = (Ty_mat + R(iR,2)).^2; 20 | RTz_mat = (Tz_mat + R(iR,3)).^2; 21 | dist_mat = sqrt(RTx_mat + RTy_mat + RTz_mat); 22 | dist_mat(dist_mat == 0) = a/sqrt(3); 23 | eiqdotT = exp(1i.*(q(1).*Tx_mat + q(2).*Ty_mat + q(3).*Tz_mat)); 24 | tV = -U/(ed*r0) * (StruveH0(dist_mat/r0)-bessely(0,dist_mat/r0)); 25 | y = keldysh_prefactor*eiqdotR.*eiqdotT.*tV; 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /TB/src/keldysh_pot4.m: -------------------------------------------------------------------------------- 1 | function y = keldysh_pot4(Rnorm,a) 2 | ed = 2.5; 3 | r0 = 33.875/ed; 4 | U = 1; 5 | keldysh_prefactor = 22.59; 6 | tV = 0; 7 | if(Rnorm==0) 8 | tV = -U/(ed*r0) * (StruveH0(a/sqrt(3)/r0)-bessely(0,a/sqrt(3)/r0)); 9 | else 10 | tV = -1/(ed*r0) * (StruveH0(Rnorm/r0)-bessely(0,Rnorm/r0)); 11 | end 12 | y = keldysh_prefactor*tV; 13 | end 14 | -------------------------------------------------------------------------------- /TB/src/lorentzian.m: -------------------------------------------------------------------------------- 1 | function L = lorentzian(x,center,gamma) 2 | L = 1/pi * (0.5*gamma/((x-center)^2 + (0.5*gamma)^2)); 3 | end 4 | 5 | -------------------------------------------------------------------------------- /TB/src/plot_bandstructure.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Plot bandstructure 3 | % Adapted from: 4 | % Ab initio tight-binding Hamiltonian for transition metal dichalcogenides 5 | % by Shiang Fang, Rodrick Kuate Defo, Sharmila N. Shirodkar, Simon Lieu, Georgios A. Tritsaris, and Efthimios Kaxiras 6 | % code version: July 2017 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | %Plot bands 9 | 10 | fprintf('--> Plotting bandstructure on Gamma-M-K-Gamma ... ') 11 | line([scale_axis(knum),scale_axis(knum)],[-100,100],'Color','k'); 12 | hold on 13 | line([scale_axis(2*knum),scale_axis(2*knum)],[-100,100],'Color','k'); 14 | 15 | 16 | if(reduced_workspace) 17 | plot(scale_axis,tb_bands,'ko','LineWidth',1.0,'MarkerSize',1.5); 18 | else 19 | plot(scale_axis,tb_bands,'r','LineWidth',2.0); 20 | end 21 | 22 | %ylabel('Band Energy (eV)'); 23 | axis([-inf,inf,-6,5]); 24 | box on; 25 | 26 | ax = gca; 27 | set(gca,'XTick',[0,scale_axis(knum),scale_axis(2*knum),1]); 28 | set(gca,'YTick',[-6,-4,-2,0,2,4,6]); 29 | if(~miniBZ) 30 | set(gca,'XTickLabel',{'\Gamma','M','K','\Gamma'}); 31 | else 32 | set(gca,'XTickLabel',{'\Gamma','M','K','\Gamma'}); 33 | end 34 | set(gca,'YTickLabel',{'-6','-4','-2','0','2','4','6'}); 35 | set(gca,'FontSize',26); 36 | set(gca,'Fontname','Times New Roman'); 37 | ylabel('Energy (eV)'); 38 | fprintf('done\n\n') 39 | fprintf('--> Saving bandstructure in %s ... ',join([outfname,'.png'])) 40 | saveas(gca,join([outfname,'.png'])) 41 | fprintf('done\n\n') 42 | % 43 | if (twisted) 44 | figure 45 | line([scale_axis(knum),scale_axis(knum)],[-100,100],'Color','k'); 46 | hold on 47 | line([scale_axis(2*knum),scale_axis(2*knum)],[-100,100],'Color','k'); 48 | 49 | plot(scale_axis,tb_bands,'ko','LineWidth',1.0,'MarkerSize',2); 50 | box on; 51 | ax = gca; 52 | axis([-inf,inf,-0.85,-0.75]); 53 | set(gca,'XTick',[0,scale_axis(knum),scale_axis(2*knum),1]); 54 | set(gca,'YTick',[-0.85,-0.80,-0.75]); 55 | if(~miniBZ) 56 | set(gca,'XTickLabel',{'\Gamma','M','K','\Gamma'}); 57 | else 58 | set(gca,'XTickLabel',{'\Gamma','K','M','\Gamma'}); 59 | end 60 | set(gca,'YTickLabel',{'-0.85','-0.80','-0.75'}); 61 | set(gca,'FontSize',26); 62 | set(gca,'Fontname','Times New Roman'); 63 | ylabel('Energy (eV)'); 64 | 65 | saveas(gca,join([outfname,'_magnification.png'])) 66 | end 67 | % 68 | % axis([-inf,inf,-0.1,0.1]); 69 | % set(gca,'XTick',[0,scale_axis(knum),scale_axis(2*knum),1]); 70 | % set(gca,'YTick',[-2,-1,0,1,2]); 71 | % set(gca,'XTickLabel',{'\Gamma','M','K','\Gamma'}); 72 | % set(gca,'YTickLabel',{'-2','-1','0','1','2'}); 73 | % 74 | % saveas(gca,join([outfname,'_magnification_2.png'])) 75 | -------------------------------------------------------------------------------- /TB/src/plot_exciton_wfc.m: -------------------------------------------------------------------------------- 1 | function [supercell,psi_M1,psi_M2,psi_k1,psi_k2] = plot_exciton_wfc(index_orb_up,index_orb_down,r_h, orb_h_up, orb_h_down, Acvk, ... 2 | Cv, Cc, mcell, X, Y, Z, all_kpts, knum_tot, Nat, indc, indv, indk, ... 3 | dim, eig, outname, twisted) 4 | 5 | % Define supercell in real space from k-grid 6 | is = 0; 7 | tot_r = knum_tot*Nat; 8 | supercell = zeros(tot_r,3); 9 | knum = sqrt(knum_tot); 10 | psi_M1 = zeros(tot_r,1); 11 | psi_M2 = zeros(tot_r,1); 12 | nat_index = zeros(tot_r,1); 13 | sum_M1 = 0.0; 14 | sum_M2 = 0.0; 15 | % tic 16 | for in = 0 : knum - 1 17 | for jn = 0 : knum - 1 18 | R = in*mcell(1,:) + jn*mcell(2,:); 19 | for iat = 1 : Nat 20 | %is = (Nat+1)*in*(knum-1) + Nat*jn + iat; 21 | is = is + 1; 22 | r_e = [X(iat), Y(iat), Z(iat)]; 23 | supercell(is,:) = r_e + R; 24 | nat_index(is) = iat; 25 | end 26 | end 27 | end 28 | 29 | parfor is = 1 : tot_r 30 | sum_M1 = 0.0; 31 | sum_M2 = 0.0; 32 | for idim = 1 : dim 33 | psi_vk_rh_up = conj(Cv([orb_h_up.Ham_index], indv(idim), indk(idim))); 34 | %psi_vk_rh_up = conj(Cv([index_orb_down{nat_index(is)}], indv(idim), indk(idim))); 35 | psi_ck_re_up = Cc([index_orb_up{nat_index(is)}], indc(idim), indk(idim)); 36 | %psi_ck_re_up = Cc([orb_h_up.Ham_index], indc(idim), indk(idim)); 37 | psi_vk_rh_down = conj(Cv([orb_h_down.Ham_index], indv(idim), indk(idim))); 38 | %psi_vk_rh_down = conj(Cv([index_orb_down{nat_index(is)}], indv(idim), indk(idim))); 39 | psi_ck_re_down = Cc([index_orb_down{nat_index(is)}], indc(idim), indk(idim)); 40 | %psi_ck_re_down = Cc([orb_h_up.Ham_index], indc(idim), indk(idim)); 41 | eikdotR = exp(1i*(dot(all_kpts(indk(idim),:), supercell(is,:) - r_h))); 42 | CvCc = (dot(psi_vk_rh_up,psi_vk_rh_up)*dot(psi_ck_re_up,psi_ck_re_up) + dot(psi_vk_rh_down,psi_vk_rh_down)*dot(psi_ck_re_down,psi_ck_re_down)); 43 | %sum(psi_vk_rh_up)*sum(psi_ck_re_down) + sum(psi_vk_rh_down)*sum(psi_ck_re_up)); 44 | sum_M1 = sum_M1 + Acvk(idim,1) * eikdotR * CvCc; 45 | sum_M2 = sum_M2 + Acvk(idim,2) * eikdotR * CvCc; 46 | end 47 | psi_M1(is) = psi_M1(is) + abs(sum_M1)^2; 48 | psi_M2(is) = psi_M2(is) + abs(sum_M2)^2; 49 | end 50 | % toc 51 | psi_M1 = psi_M1 / knum_tot^2; 52 | psi_M2 = psi_M2 / knum_tot^2; 53 | 54 | scatter3(supercell(:,1), supercell(:,2), supercell(:,3), 100, psi_M1, 'filled'); 55 | title(join(['$\epsilon =$', num2str(eig),' (eV)', '\textbf{r}$_h$ =', '(', num2str(r_h(1)),', ', num2str(r_h(2)),', ', num2str(r_h(3)),') \AA']),'Interpreter','latex','FontSize',22) 56 | saveas(gcf, join([outname,'_M1.fig'])); 57 | 58 | scatter3(supercell(:,1), supercell(:,2), supercell(:,3), 100, psi_M2, 'filled'); 59 | title(join(['$\epsilon =$', num2str(eig),' (eV)', '\textbf{r}$_h$ =', '(', num2str(r_h(1)),', ', num2str(r_h(2)),', ', num2str(r_h(3)),') \AA']),'Interpreter','latex','FontSize',22) 60 | saveas(gcf, join([outname,'_M2.fig'])); 61 | 62 | close all 63 | if(~twisted) 64 | super_supercell = zeros(4*size(supercell,1),3); 65 | super_psi_M1 = zeros(4*size(psi_M1,1),1); 66 | super_psi_M2 = zeros(4*size(psi_M2,1),1); 67 | is = 0; 68 | for in = 0 : 1 69 | for jn = 0 : 1 70 | for inat = 1 : size(supercell,1) 71 | is = is + 1; 72 | super_supercell(is,:) = supercell(inat,:) + in*knum*mcell(1,:) + jn*knum*mcell(2,:); 73 | super_psi_M1(is,:) = psi_M1(inat); 74 | super_psi_M2(is,:) = psi_M2(inat); 75 | end 76 | end 77 | end 78 | scatter3(super_supercell(:,1),super_supercell(:,2),super_supercell(:,3),500,super_psi_M1,'filled') 79 | title(join(['$\epsilon =$', num2str(eig),' (eV)', '\textbf{r}$_h$ =', '(', num2str(r_h(1)),', ', num2str(r_h(2)),', ', num2str(r_h(3)),') \AA']),'Interpreter','latex','FontSize',22) 80 | saveas(gcf,join([outname,'_supercell_M1.fig'])) 81 | scatter3(super_supercell(:,1),super_supercell(:,2),super_supercell(:,3),500,super_psi_M2,'filled') 82 | title(join(['$\epsilon =$', num2str(eig),' (eV)', '\textbf{r}$_h$ =', '(', num2str(r_h(1)),', ', num2str(r_h(2)),', ', num2str(r_h(3)),') \AA']),'Interpreter','latex','FontSize',22) 83 | saveas(gcf,join([outname,'_supercell_M2.fig'])) 84 | close all 85 | end 86 | % Reciprocal space 87 | psi_k1 = zeros(knum_tot,1); 88 | psi_k2 = zeros(knum_tot,1); 89 | for idim = 1 : dim 90 | psi_k1(indk(idim)) = psi_k1(indk(idim)) + abs(Acvk(idim,1)).^2; 91 | psi_k2(indk(idim)) = psi_k2(indk(idim)) + abs(Acvk(idim,2)).^2; 92 | end 93 | scatter3(all_kpts(:,1),all_kpts(:,2),zeros(size(psi_k1)),200,psi_k1(:),'filled') 94 | saveas(gcf,join([outname,'_recspace_M1.fig'])) 95 | close all 96 | scatter3(all_kpts(:,1),all_kpts(:,2),zeros(size(psi_k2)),200,psi_k2(:),'filled') 97 | saveas(gcf,join([outname,'_recspace_M2.fig'])) 98 | 99 | clear psi_ck_rh psi_vk_rh psi_ck_re psi_vk_re super_supercell super_psi_M1 super_psi_M2 CvCc eikdotR 100 | 101 | end 102 | -------------------------------------------------------------------------------- /TB/src/plot_exciton_wfc2.m: -------------------------------------------------------------------------------- 1 | function [supercell,psi_M1,psi_M2,psi_k1,psi_k2] = plot_exciton_wfc2(index_orb_up,index_orb_down,r_h, orb_h_up, orb_h_down, Acvk, ... 2 | Cv, Cc, mcell, X, Y, Z, all_kpts, knum_tot, Nat, indc, indv, indk, ... 3 | dim, eig, outname, twisted) 4 | 5 | % Define supercell in real space from k-grid 6 | is = 0; 7 | tot_r = knum_tot*Nat; 8 | supercell = zeros(tot_r,3); 9 | knum = sqrt(knum_tot); 10 | psi_M1 = zeros(tot_r,1); 11 | psi_M2 = zeros(tot_r,1); 12 | nat_index = zeros(tot_r,1); 13 | sum_M1 = zeros(dim,1); 14 | sum_M2 = zeros(dim,1); 15 | % tic 16 | for in = 0 : knum - 1 17 | for jn = 0 : knum - 1 18 | R = in*mcell(1,:) + jn*mcell(2,:); 19 | for iat = 1 : Nat 20 | %is = (Nat+1)*in*(knum-1) + Nat*jn + iat; 21 | is = is + 1; 22 | r_e = [X(iat), Y(iat), Z(iat)]; 23 | supercell(is,:) = r_e + R; 24 | nat_index(is) = iat; 25 | end 26 | end 27 | end 28 | 29 | s_h = size([orb_h_up.Ham_index],2); 30 | Cv_u = zeros(dim,s_h); 31 | Cv_d = zeros(dim,s_h); 32 | Cv_sud = zeros(dim); 33 | 34 | 35 | Cc_u = zeros(dim,5,Nat); 36 | Cc_d = zeros(dim,5,Nat); 37 | Cc_sud = zeros(dim); 38 | for idim = 1 : dim 39 | psi_vk_rh_up = Cv([orb_h_up.Ham_index], indv(idim), indk(idim)); 40 | psi_vk_rh_down = Cv([orb_h_down.Ham_index], indv(idim), indk(idim)); 41 | Cv_u(idim,:) = psi_vk_rh_up'; 42 | Cv_d(idim,:) = psi_vk_rh_down'; 43 | end 44 | 45 | Cv_sud = Cv_u * Cv_u' + Cv_d * Cv_d'; 46 | 47 | for iat = 1 : Nat 48 | for idim = 1 : dim 49 | psi_ck_re_up = Cc([index_orb_up{iat}], indc(idim), indk(idim)); 50 | psi_ck_re_down = Cc([index_orb_down{iat}], indc(idim), indk(idim)); 51 | psi_ck_re_up(numel([1 2 3 4 5])) = 0; 52 | psi_ck_re_down(numel([1 2 3 4 5])) = 0; 53 | Cc_u(idim,:,iat) = psi_ck_re_up'; 54 | Cc_d(idim,:,iat) = psi_ck_re_down'; 55 | end 56 | end 57 | 58 | tic 59 | for is = 1 : tot_r 60 | Cc_sud = Cc_u(:,:,nat_index(is)) * Cc_u(:,:,nat_index(is))' + Cc_d(:,:,nat_index(is)) * Cc_d(:,:,nat_index(is))'; 61 | CvCc_s = conj(Cc_sud).*Cv_sud; 62 | re_rh = supercell(is,:) - r_h; 63 | for idim = 1 : dim 64 | eikdotR = exp(1i*(dot(all_kpts(indk(idim),:), re_rh))); 65 | sum_M1(idim) = Acvk(idim,1) * eikdotR ; 66 | sum_M2(idim) = Acvk(idim,2) * eikdotR ; 67 | end 68 | psi_M1(is) = psi_M1(is) + real(sum(sum(kron(sum_M1',sum_M1).*CvCc_s))); 69 | psi_M2(is) = psi_M2(is) + real(sum(sum(kron(sum_M2',sum_M2).*CvCc_s))); 70 | end 71 | psi_M1 = psi_M1 / knum_tot^2; 72 | psi_M2 = psi_M2 / knum_tot^2; 73 | toc 74 | 75 | scatter3(supercell(:,1), supercell(:,2), supercell(:,3), 100, psi_M1, 'filled'); 76 | title(join(['$\epsilon =$', num2str(eig),' (eV)', '\textbf{r}$_h$ =', '(', num2str(r_h(1)),', ', num2str(r_h(2)),', ', num2str(r_h(3)),') \AA']),'Interpreter','latex','FontSize',22) 77 | saveas(gcf, join([outname,'_M1.fig'])); 78 | 79 | scatter3(supercell(:,1), supercell(:,2), supercell(:,3), 100, psi_M2, 'filled'); 80 | title(join(['$\epsilon =$', num2str(eig),' (eV)', '\textbf{r}$_h$ =', '(', num2str(r_h(1)),', ', num2str(r_h(2)),', ', num2str(r_h(3)),') \AA']),'Interpreter','latex','FontSize',22) 81 | saveas(gcf, join([outname,'_M2.fig'])); 82 | 83 | close all 84 | if(~twisted) 85 | super_supercell = zeros(4*size(supercell,1),3); 86 | super_psi_M1 = zeros(4*size(psi_M1,1),1); 87 | super_psi_M2 = zeros(4*size(psi_M2,1),1); 88 | is = 0; 89 | for in = 0 : 1 90 | for jn = 0 : 1 91 | for inat = 1 : size(supercell,1) 92 | is = is + 1; 93 | super_supercell(is,:) = supercell(inat,:) + in*knum*mcell(1,:) + jn*knum*mcell(2,:); 94 | super_psi_M1(is,:) = psi_M1(inat); 95 | super_psi_M2(is,:) = psi_M2(inat); 96 | end 97 | end 98 | end 99 | scatter3(super_supercell(:,1),super_supercell(:,2),super_supercell(:,3),500,super_psi_M1,'filled') 100 | title(join(['$\epsilon =$', num2str(eig),' (eV)', '\textbf{r}$_h$ =', '(', num2str(r_h(1)),', ', num2str(r_h(2)),', ', num2str(r_h(3)),') \AA']),'Interpreter','latex','FontSize',22) 101 | saveas(gcf,join([outname,'_supercell_M1.fig'])) 102 | scatter3(super_supercell(:,1),super_supercell(:,2),super_supercell(:,3),500,super_psi_M2,'filled') 103 | title(join(['$\epsilon =$', num2str(eig),' (eV)', '\textbf{r}$_h$ =', '(', num2str(r_h(1)),', ', num2str(r_h(2)),', ', num2str(r_h(3)),') \AA']),'Interpreter','latex','FontSize',22) 104 | saveas(gcf,join([outname,'_supercell_M2.fig'])) 105 | close all 106 | end 107 | % Reciprocal space 108 | psi_k1 = zeros(knum_tot,1); 109 | psi_k2 = zeros(knum_tot,1); 110 | for idim = 1 : dim 111 | psi_k1(indk(idim)) = psi_k1(indk(idim)) + abs(Acvk(idim,1)).^2; 112 | psi_k2(indk(idim)) = psi_k2(indk(idim)) + abs(Acvk(idim,2)).^2; 113 | end 114 | scatter3(all_kpts(:,1),all_kpts(:,2),zeros(size(psi_k1)),200,psi_k1(:),'filled') 115 | saveas(gcf,join([outname,'_recspace_M1.fig'])) 116 | close all 117 | scatter3(all_kpts(:,1),all_kpts(:,2),zeros(size(psi_k2)),200,psi_k2(:),'filled') 118 | saveas(gcf,join([outname,'_recspace_M2.fig'])) 119 | 120 | clear psi_ck_rh psi_vk_rh psi_ck_re psi_vk_re super_supercell super_psi_M1 super_psi_M2 CvCc eikdotR 121 | 122 | end 123 | -------------------------------------------------------------------------------- /TB/src/plot_exciton_wfc_test.m: -------------------------------------------------------------------------------- 1 | function [supercell,psi_M1,psi_M2,psi_k1,psi_k2] = plot_exciton_wfc(index_orb_up,index_orb_down,r_h, orb_h_up, orb_h_down, Acvk, ... 2 | Cv, Cc, mcell, X, Y, Z, all_kpts, knum_tot, Nat, indc, indv, indk, ... 3 | dim, eig, outname, twisted) 4 | 5 | % Define supercell in real space from k-grid 6 | is = 0; 7 | tot_r = knum_tot*Nat; 8 | supercell = zeros(tot_r,3); 9 | knum = sqrt(knum_tot); 10 | psi_M1 = zeros(tot_r,1); 11 | psi_M2 = zeros(tot_r,1); 12 | nat_index = zeros(tot_r,1); 13 | % tic 14 | for in = 0 : knum - 1 15 | for jn = 0 : knum - 1 16 | R = in*mcell(1,:) + jn*mcell(2,:); 17 | for iat = 1 : Nat 18 | %is = (Nat+1)*in*(knum-1) + Nat*jn + iat; 19 | is = is + 1; 20 | r_e = [X(iat), Y(iat), Z(iat)]; 21 | supercell(is,:) = R + r_e; 22 | nat_index(is) = iat; 23 | end 24 | end 25 | end 26 | 27 | fprintf("Computing Fkk'...") 28 | FR = zeros(tot_r,knum_tot,knum_tot); 29 | parfor iR = 1 : tot_r 30 | for ik = 1 : knum_tot 31 | for jk = 1 : knum_tot 32 | tmp = exp(1i*dot(all_kpts(ik,:) - all_kpts(jk,:),r_h - supercell(iR,:))); 33 | FR(iR,ik,jk) = tmp; 34 | end 35 | end 36 | end 37 | fprintf('done.\n') 38 | 39 | Asq1 = zeros(dim,dim); 40 | Asq2 = zeros(dim,dim); 41 | CvkCvk = zeros(dim,dim); 42 | vk_rh_up = zeros(dim); 43 | vk_rh_down = zeros(dim); 44 | fprintf("Computing Acvk*.Ac'v'k'...") 45 | parfor idim = 1 : dim 46 | for jdim = 1 : dim 47 | Asq1(idim,jdim) = conj(Acvk(idim,1)) * Acvk(jdim,1); 48 | Asq2(idim,jdim) = conj(Acvk(idim,2)) * Acvk(jdim,2); 49 | CvkCvk(idim,jdim) = dot(Cv([orb_h_up.Ham_index], indv(jdim), indk(jdim)),Cv([orb_h_up.Ham_index], indv(idim), indk(idim))) ... 50 | + dot(Cv([orb_h_down.Ham_index], indv(jdim), indk(jdim)),Cv([orb_h_down.Ham_index], indv(idim), indk(idim))); 51 | end 52 | end 53 | fprintf('done.\n') 54 | 55 | fprintf('Computing |Psi_X|^2 ...') 56 | parfor is = 1 : tot_r 57 | for idim = 1 : dim 58 | ck_re_up_i = Cc([index_orb_up{nat_index(is)}], indc(idim), indk(idim)); 59 | ck_re_down_i = Cc([index_orb_down{nat_index(is)}], indc(idim), indk(idim)); 60 | for jdim = 1 : dim 61 | ck_re_up_j = Cc([index_orb_up{nat_index(is)}], indc(jdim), indk(jdim)); 62 | ck_re_down_j = Cc([index_orb_down{nat_index(is)}], indc(jdim), indk(jdim)); 63 | CckCck = dot(ck_re_up_i,ck_re_up_j) + dot(ck_re_down_i,ck_re_down_j); 64 | psi_M1(is) = psi_M1(is) + Asq1(idim,jdim) * FR(is,indk(idim),indk(jdim)) * CvkCvk(idim,jdim) * CckCck ; 65 | psi_M2(is) = psi_M2(is) + Asq2(idim,jdim) * FR(is,indk(idim),indk(jdim)) * CvkCvk(idim,jdim) * CckCck ; 66 | end 67 | end 68 | end 69 | psi_M1 = real(psi_M1) / knum_tot^2; 70 | psi_M2 = real(psi_M2) / knum_tot^2; 71 | fprintf('done.\n') 72 | 73 | scatter3(supercell(:,1), supercell(:,2), supercell(:,3), 100, psi_M1, 'filled'); 74 | title(join(['$\epsilon =$', num2str(eig),' (eV)', '\textbf{r}$_h$ =', '(', num2str(r_h(1)),', ', num2str(r_h(2)),', ', num2str(r_h(3)),') \AA']),'Interpreter','latex','FontSize',22) 75 | saveas(gcf, join([outname,'_M1.fig'])); 76 | 77 | scatter3(supercell(:,1), supercell(:,2), supercell(:,3), 100, psi_M2, 'filled'); 78 | title(join(['$\epsilon =$', num2str(eig),' (eV)', '\textbf{r}$_h$ =', '(', num2str(r_h(1)),', ', num2str(r_h(2)),', ', num2str(r_h(3)),') \AA']),'Interpreter','latex','FontSize',22) 79 | saveas(gcf, join([outname,'_M2.fig'])); 80 | 81 | close all 82 | if(~twisted) 83 | super_supercell = zeros(4*size(supercell,1),3); 84 | super_psi_M1 = zeros(4*size(psi_M1,1),1); 85 | super_psi_M2 = zeros(4*size(psi_M2,1),1); 86 | is = 0; 87 | for in = 0 : 1 88 | for jn = 0 : 1 89 | for inat = 1 : size(supercell,1) 90 | is = is + 1; 91 | super_supercell(is,:) = supercell(inat,:) + in*knum*mcell(1,:) + jn*knum*mcell(2,:); 92 | super_psi_M1(is,:) = psi_M1(inat); 93 | super_psi_M2(is,:) = psi_M2(inat); 94 | end 95 | end 96 | end 97 | scatter3(super_supercell(:,1),super_supercell(:,2),super_supercell(:,3),500,super_psi_M1,'filled') 98 | title(join(['$\epsilon =$', num2str(eig),' (eV)', '\textbf{r}$_h$ =', '(', num2str(r_h(1)),', ', num2str(r_h(2)),', ', num2str(r_h(3)),') \AA']),'Interpreter','latex','FontSize',22) 99 | saveas(gcf,join([outname,'_supercell_M1.fig'])) 100 | scatter3(super_supercell(:,1),super_supercell(:,2),super_supercell(:,3),500,super_psi_M2,'filled') 101 | title(join(['$\epsilon =$', num2str(eig),' (eV)', '\textbf{r}$_h$ =', '(', num2str(r_h(1)),', ', num2str(r_h(2)),', ', num2str(r_h(3)),') \AA']),'Interpreter','latex','FontSize',22) 102 | saveas(gcf,join([outname,'_supercell_M2.fig'])) 103 | close all 104 | % Reciprocal space 105 | psi_k1 = zeros(knum_tot,1); 106 | psi_k2 = zeros(knum_tot,1); 107 | for idim = 1 : dim 108 | psi_k1(indk(idim)) = psi_k1(indk(idim)) + abs(Acvk(idim,1)).^2; 109 | psi_k2(indk(idim)) = psi_k2(indk(idim)) + abs(Acvk(idim,2)).^2; 110 | end 111 | scatter3(all_kpts(:,1),all_kpts(:,2),zeros(size(psi_k1)),200,psi_k1(:),'filled') 112 | saveas(gcf,join([outname,'_recspace_M1.fig'])) 113 | close all 114 | scatter3(all_kpts(:,1),all_kpts(:,2),zeros(size(psi_k2)),200,psi_k2(:),'filled') 115 | saveas(gcf,join([outname,'_recspace_M2.fig'])) 116 | end 117 | 118 | 119 | clear psi_ck_rh psi_vk_rh psi_ck_re psi_vk_re super_supercell super_psi_M1 super_psi_M2 CvCc eikdotR 120 | 121 | end 122 | -------------------------------------------------------------------------------- /TB/src/plot_projection.m: -------------------------------------------------------------------------------- 1 | function y = plot_projection(orbitals,tot_norbs,knum_tot,knum,tb_bands,... 2 | tb_vecs,scale_axis,property,value,fname,stitle,end_color) 3 | 4 | line([scale_axis(knum),scale_axis(knum)],[-100,100],'Color','k'); 5 | hold on 6 | line([scale_axis(2*knum),scale_axis(2*knum)],[-100,100],'Color','k'); 7 | 8 | [~,~] = projection(orbitals,scale_axis,tb_bands,tb_vecs,fname,{property,value}); 9 | 10 | data = importdata(fname); 11 | data_r = reshape(data(:,3),[knum_tot, tot_norbs]); 12 | size(data_r) 13 | 14 | for iband = 1 : tot_norbs 15 | h = surface([scale_axis';scale_axis'],... 16 | [tb_bands(iband,:);tb_bands(iband,:)],... 17 | [zeros(size(scale_axis'));zeros(size(scale_axis'))],... 18 | [data_r(:,iband)';data_r(:,iband)'],'FaceColor','none',... 19 | 'EdgeColor','interp'); 20 | set(h,'LineWidth',3) 21 | hold on 22 | end 23 | map = colorGradient([200 200 200]/255,end_color,100); 24 | colormap(map) 25 | colorbar 26 | y = 0; 27 | axis([-inf,inf,-6,5]); 28 | box on; 29 | ax = gca; 30 | set(ax,'XTick',[0,scale_axis(knum),scale_axis(2*knum),1]); 31 | set(ax,'YTick',[-6,-4,-2,0,2,4,6]); 32 | set(ax,'XTickLabel',{'\Gamma','M','K','\Gamma'}); 33 | set(ax,'YTickLabel',{'-6','-4','-2','0','2','4','6'}); 34 | set(ax,'FontSize',26); 35 | set(ax,'Fontname','Times New Roman'); 36 | ylabel('Energy (eV)'); 37 | title(stitle,'Interpreter','latex') 38 | saveas(ax,join([fname,'.fig'])) 39 | end -------------------------------------------------------------------------------- /TB/src/plot_wfc_new.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Routine to plot wave function on atoms for 3 | % a given k-point 4 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5 | % Inputs: 6 | % tb_vecs - TB eigenvectors 7 | % orbitals - orbitals class 8 | % X, Y, Z - Cartesian coordinates of atoms 9 | % at_name - ordered list of atomic symbols 10 | % mcell - lattice vectors of moire cell (ang) 11 | % natoms - Number of atoms 12 | % norbs - Number of orbitals 13 | % n - band index of psi state 14 | % kpoint - k-point in MP grid 15 | % filename - Output file name 16 | % 17 | % Outputs: 18 | % psink - wave function at k squared 19 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 20 | % Written by Valerio Vitale 21 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 22 | function psink= plot_wfc(tb_vecs,orbitals,X,Y,Z,at_name,mcell,natoms,norbs,filename,twisted,multilayer,nlayer,k) 23 | 24 | psink = zeros(natoms,1); 25 | for ir = 1 : natoms 26 | r = [X(ir),Y(ir),Z(ir)]; 27 | orb1 = findobj(orbitals,'Centre',r); 28 | orb2 = findobj(orbitals,'Pcentre',r); 29 | if(~isempty(orb1)) 30 | iorb = orb1; %orb1.Ham_index; 31 | %centre = orbitals(iorb).Centre; 32 | elseif(~isempty(orb2)) 33 | iorb = orb2; %orb2.Ham_index; 34 | %centre = orbitals(iorb).Pcentre; 35 | end 36 | if(twisted && multilayer) 37 | %psink(ir) = psink(ir) + dot(tb_vecs([iorb.Ham_index]),tb_vecs([iorb.Ham_index])); 38 | psink(ir) = psink(ir) + abs(sum(tb_vecs([iorb.Ham_index])))^2; 39 | end 40 | end 41 | clear orb1 orb2 iorb 42 | nsublayers = 3*nlayer; 43 | llim = 0; 44 | ulim = 2.5; 45 | for isl = 1 : nsublayers 46 | ilayer(isl,:) = find(Z > llim & Z < ulim); 47 | llim = llim + 2; 48 | ulim = ulim + 2; 49 | end 50 | pos = cell(nsublayers,1); 51 | for il = 1 : nsublayers 52 | pos{il} = [X(ilayer(il,:)),Y(ilayer(il,:)),Z(ilayer(il,:))]; 53 | end 54 | mean_z = mean(Z); 55 | figure(1) 56 | colormap(hot); 57 | supercell = cell(nsublayers,1); %zeros(6,9*size(psink,1),3); 58 | spsink = cell(nsublayers,1); %zeros(6,9*size(psink,1),1); 59 | for il = 1 : nsublayers 60 | jp = 0; 61 | tmp = zeros(size(ilayer(il,:),2),3); 62 | tmp2 = zeros(size(ilayer(il,:),2),1); 63 | tmp3 = zeros(size(ilayer(il,:),2),3); 64 | for n = - 2 : 2 65 | for m = -2 : 2 66 | for ip = 1 : size(ilayer(il,:),2) 67 | jp = jp + 1; 68 | tmp3 = pos{il}; 69 | tmp(jp,:) = tmp3(ip,:) + n*mcell(1,:) + m*mcell(2,:); 70 | tmp2(jp) = psink(ilayer(il,ip))/(tmp(jp,3)-mean_z)^2; 71 | end 72 | end 73 | end 74 | supercell{il} = tmp; 75 | spsink{il} = tmp2; 76 | end 77 | clear tmp tmp2 tmp3; 78 | phi = acos(mcell(1,1)/norm(mcell(1,:))); 79 | Rphi = [cos(-phi) -sin(-phi) 0;sin(-phi) cos(-phi) 0; 0 0 1]; 80 | rot_cell = mcell*Rphi'; 81 | x = linspace(-rot_cell(1,1),rot_cell(1,1),300); 82 | y = linspace(-rot_cell(2,2),rot_cell(2,2),300); 83 | [XX,YY] = meshgrid(x,y); 84 | ZZ = 0.*XX + 0.*YY; 85 | for il = 1 : nsublayers 86 | spos = supercell{il}*Rphi'; 87 | f = scatteredInterpolant(spos(:,1),spos(:,2),spsink{il},'natural'); 88 | ZZ = ZZ + f(XX,YY); 89 | clear spos; 90 | end 91 | surf(XX,YY,ZZ) 92 | shading interp 93 | colormap(jet); 94 | colorbar; 95 | view(0,90) 96 | axis off 97 | 98 | hold on 99 | alatL = rot_cell; 100 | line([0 alatL(1,1)],[0 0],[1 1]) 101 | line([0 -alatL(2,1)],[0 -alatL(2,2)],[1 1]) 102 | line([-alatL(2,1) -alatL(2,1)+alatL(1,1)],[-alatL(2,2) -alatL(2,2)],[1 1]) 103 | line([-alatL(2,1)+alatL(1,1) alatL(1,1)],[-alatL(2,2) 0],[1 1]) 104 | C = [1/2*alatL(1,1),-1/3*alatL(2,2),1.1] ; % center of circle 105 | R = 1.5; 106 | teta=0:0.01:2*pi ; 107 | x=C(1)+R*cos(teta); 108 | y=C(2)+R*sin(teta) ; 109 | z = C(3)+zeros(size(x)) ; 110 | patch(x,y,z,'g') 111 | plot3(C(1),C(2),C(3),'k') 112 | C = [0,-2/3*alatL(2,2),1.1] ; % center of circle 113 | R = 1.5; 114 | teta=0:0.01:2*pi ; 115 | x=C(1)+R*cos(teta); 116 | y=C(2)+R*sin(teta) ; 117 | z = C(3)+zeros(size(x)) ; 118 | patch(x,y,z,'c') 119 | plot3(C(1),C(2),C(3),'k') 120 | C = [-alatL(2,1),-alatL(2,2),1.1] ; % center of circle 121 | R = 1.5; 122 | teta=0:0.01:2*pi ; 123 | x=C(1)+R*cos(teta); 124 | y=C(2)+R*sin(teta) ; 125 | z = C(3)+zeros(size(x)) ; 126 | patch(x,y,z,'m') 127 | plot3(C(1),C(2),C(3),'k') 128 | %scatter3(supercell(:,1),supercell(:,2),supercell(:,3),10,spsink(:),'filled') 129 | 130 | 131 | clear XX YY ZZ x y rot_cell supercell spsink 132 | saveas(gca,join([filename,'_psink_',k,'.fig'])) 133 | end 134 | -------------------------------------------------------------------------------- /TB/src/read_kpts.m: -------------------------------------------------------------------------------- 1 | % Check kpts.in file exists in the path 2 | if(exist('kpts.in','file')) 3 | data = importdata('kpts.in',' ') 4 | recL=[mb1;mb2;mb3]; 5 | all_kpts = data*recL; 6 | knum_tot = size(all_kpts,1) 7 | scale_axis = zeros(knum_tot,1); 8 | for ik = 2 : knum_tot 9 | dk = norm(all_kpts(ik,:)-all_kpts(ik-1,:)); 10 | scale_axis(ik) = scale_axis(ik-1) + dk; 11 | end 12 | else 13 | error('Error main.m cannot find kpts.in. Aborting ...') 14 | end 15 | -------------------------------------------------------------------------------- /TB/src/read_structure.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | % Routine to read in geometry info from 3 | % structure.dat 4 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5 | % Inputs: 6 | % filename - name of geometry file ('structure.dat') 7 | % 8 | % Outputs: 9 | % nat - Number of atoms on each layer 10 | % theta - twist angle in degrees 11 | % unit_cell - cell vectors of unit cell of monolayer (ang) 12 | % cell - cell vectors of moire cell (ang) 13 | % structure - structure containing info on all atoms 14 | % Atom label, layer, X, Y, Z (ang) 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 | % Written by Valerio Vitale 17 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 18 | function [nat,theta,strain,unit_cell,cell,structure,bondlength] = read_structure(filename,nlayer) 19 | fileID = fopen(filename,'r'); 20 | data = textscan(fileID,'%f %f %f %f %f',1); 21 | % Read number of atoms 22 | for ilayer = 1 : nlayer 23 | nat(ilayer) = cell2mat(data(ilayer)); 24 | end 25 | data = textscan(fileID,'%f %f %f %f %f',1); 26 | for ilayer = 1 : nlayer 27 | bondlength(ilayer) = cell2mat(data(ilayer)); 28 | end 29 | % Read theta 30 | data = textscan(fileID,'%f %f %f %f %f',1); 31 | for ilayer = 1 : nlayer 32 | theta(ilayer) = cell2mat(data(ilayer)); 33 | end 34 | % Read strain 35 | data = textscan(fileID,'%f %f %f %f',1); 36 | for ilayer = 1 : nlayer 37 | strain(ilayer) = cell2mat(data(ilayer)); 38 | end 39 | bondlength = bondlength.*strain; 40 | % Read unit cell 41 | data = textscan(fileID,'%f %f %f',3); 42 | unit_cell = cell2mat(data); 43 | % Read cell 44 | data = textscan(fileID,'%f %f %f',3); 45 | cell = cell2mat(data); 46 | data = textscan(fileID,'%s %f %f %f %f',sum(nat)); 47 | structure = cell2struct(data,{'name','layer','x','y','z'},2); 48 | fclose(fileID); 49 | end 50 | -------------------------------------------------------------------------------- /TB/src/real_pot2.m: -------------------------------------------------------------------------------- 1 | function [VR,lattice] = real_pot2(mcell,structure,a,nat,Nk) 2 | % Epsilon, r0 and U (these are hard-coded at the moment) 3 | ed = 2.5; 4 | r0 = 33.875/ed; 5 | U = 1; 6 | keldysh_prefactor = 22.59; 7 | lattice=zeros(Nk*Nk,3); 8 | VR = cell(Nk,1); 9 | kn = 0; 10 | if(mod(Nk,2)==0) 11 | Ni = -(Nk-1)/2; 12 | Nf = -Ni; 13 | dN = 1; 14 | else 15 | Ni = -(Nk-1)/2; 16 | Nf = -Ni; 17 | dN = 1; 18 | end 19 | 20 | % Shift centre of unit cell 21 | shift = 2/3*mcell(1,:)+1/3*mcell(2,:); 22 | 23 | % Compute the keldysh potential VR in real space 24 | for im = Ni : dN : Nf 25 | for jn = Ni : dN : Nf 26 | kn = kn + 1; 27 | lattice(kn,:) = im*mcell(1,:) + jn*mcell(2,:); 28 | tV = zeros(nat,nat); 29 | for inat = 1 : nat 30 | ti = [structure.x(inat),structure.y(inat),structure.z(inat)] - shift; 31 | for jnat = 1 : nat 32 | tj = [structure.x(jnat),structure.y(jnat),structure.z(jnat)] - shift; 33 | dist = norm(lattice(kn,:) + tj - ti); 34 | if(dist==0) 35 | tV(inat,jnat) = -U/(ed*r0) * (StruveH0(a/sqrt(3)/r0)-bessely(0,a/sqrt(3)/r0)); 36 | else 37 | tV(inat,jnat) = -1/(ed*r0) * (StruveH0(dist/r0)-bessely(0,dist/r0)); 38 | end 39 | 40 | end 41 | end 42 | VR{kn} = keldysh_prefactor.*tV; 43 | end 44 | end 45 | clear R dist 46 | end 47 | -------------------------------------------------------------------------------- /TB/src/screenC2.m: -------------------------------------------------------------------------------- 1 | function u = screenC2(q,Nk,nat,VR,lattice,structure,mcell) 2 | u = zeros(nat); 3 | M = complex(zeros(nat)); 4 | shift = 2/3*mcell(1,:)+1/3*mcell(2,:); 5 | for kn = 1 : Nk 6 | R = lattice(kn,:); 7 | for inat = 1 : nat 8 | ti = [structure.x(inat),structure.y(inat),structure.z(inat)] - shift; 9 | for jnat = 1 : nat 10 | tj = [structure.x(jnat),structure.y(jnat),structure.z(jnat)] - shift; 11 | qdotRij = dot(q,tj - ti); 12 | M(inat,jnat) = exp(1i*qdotRij); 13 | end 14 | end 15 | u = u + exp(1i*dot(q,R)).*M.*VR{kn,1}; 16 | end 17 | clear R qdotR 18 | end 19 | -------------------------------------------------------------------------------- /TB/src/screenC3.m: -------------------------------------------------------------------------------- 1 | function u = screenC3(q,Nk,nat,structure,mcell,a) 2 | u = zeros(nat); 3 | M = complex(zeros(nat)); 4 | shift = 2/3*mcell(1,:)+1/3*mcell(2,:); 5 | Ni = -(Nk-1)/2; 6 | Nf = -Ni; 7 | dN = 1; 8 | kn = 0; 9 | for im = Ni : dN : Nf 10 | for jn = Ni : dN : Nf 11 | kn = kn + 1; 12 | R = im*mcell(1,:) + jn*mcell(2,:); 13 | VR_ij = zeros(nat); 14 | M = zeros(nat); 15 | for inat = 1 : nat 16 | ti = [structure.x(inat),structure.y(inat),structure.z(inat)] - shift; 17 | for jnat = 1 : nat 18 | tj = [structure.x(jnat),structure.y(jnat),structure.z(jnat)] - shift; 19 | qdotRij = dot(q,tj - ti); 20 | M(inat,jnat) = exp(1i*qdotRij); 21 | dist = norm(R + tj - ti); 22 | VR_ij(inat,jnat) = keldysh_pot(dist,inat,jnat,a); 23 | end 24 | end 25 | u = u + exp(1i*dot(q,R)).*M.*VR_ij; 26 | end 27 | end 28 | clear R qdotR 29 | end 30 | 31 | 32 | -------------------------------------------------------------------------------- /TB/src/screenC4.m: -------------------------------------------------------------------------------- 1 | function u = screenC4(q,Nk,mcell,a) 2 | Ni = -(Nk-1)/2; 3 | Nf = -Ni; 4 | dN = 1; 5 | kn = 0; 6 | u = 0.0; 7 | for im = Ni : dN : Nf 8 | for jn = Ni : dN : Nf 9 | kn = kn + 1; 10 | R = im*mcell(1,:) + jn*mcell(2,:); 11 | eiqdotR = exp(1i*dot(q,R)); 12 | Rnorm = norm(R); 13 | u = u + eiqdotR*keldysh_pot4(Rnorm,a); 14 | end 15 | end 16 | clear R qdotR 17 | end 18 | 19 | 20 | -------------------------------------------------------------------------------- /TB/src/set_hopping.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | %% Function to set p-p %% 3 | %% and p-d hoppings %% 4 | %% according to rotation %% 5 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 6 | %% %% 7 | %% Written by Valerio Vitale %% 8 | %% February 2021 %% 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | 11 | function y = set_hopping(type,Vsig,Vpi,l,m,n,theta,layer) 12 | 13 | ct = cos(theta(layer+1) - theta(layer)); 14 | st = sin(theta(layer+1) - theta(layer)); 15 | s2t = sin(2*(theta(layer+1) - theta(layer))); 16 | 17 | switch type 18 | case "pzpz" 19 | y = (Vsig - Vpi)*n^2 + Vpi; 20 | case "pxpx" 21 | y = ct*((Vsig -Vpi)*l^2 + Vpi) - st*(Vsig - Vpi)*l*m; 22 | case "pypy" 23 | y = ct*((Vsig -Vpi)*m^2 + Vpi) + st*(Vsig - Vpi)*l*m; 24 | case "pxpz" 25 | y = (Vsig -Vpi)*l*n; 26 | case "pypz" 27 | y = (Vsig -Vpi)*m*n; 28 | case "pxpy" 29 | y = ct*(Vsig - Vpi)*l*m + st*((Vsig - Vpi)*l^2 + Vpi); 30 | case "pypx" 31 | y = ct*(Vsig - Vpi)*l*m - st*((Vsig - Vpi)*m^2 + Vpi); 32 | case "pzpx" 33 | y = ct*(Vsig - Vpi)*n*l - st*(Vsig - Vpi)*n*m; 34 | case "pzpy" 35 | y = ct*(Vsig - Vpi)*n*m + st*(Vsig - Vpi)*n*l; 36 | case "dz2pz" 37 | y = n*(n^2 - 0.5*(l^2 + m^2))*Vsig + sqrt(3)*n*(l^2+m^2)*Vpi; 38 | case "dxypz" 39 | y = sqrt(3)*n*l*m*Vsig - 2*n*l*m*Vpi; 40 | case "dx2y2pz" 41 | y = 0.5*sqrt(3)*n*(l^2 - m^2)*Vsig - n*(l^2 - m^2)*Vpi; 42 | case "pzdxy" %dxy dxz 43 | y = ct*(sqrt(3)*n*l*m*Vsig - 2*n*l*m*Vpi) + st*(sqrt(3)*l*m^2*Vsig + l*(1-2*m^2)*Vpi); 44 | case "pzdx2y2" %dx2my2 dz^2 dyz 45 | y = 0.5*(1+ct^2)*(0.5*sqrt(3)*n*(l^2 - m^2)*Vsig - n*(l^2 - m^2)*Vpi) - sqrt(3)*0.5*st^2*(n*(n^2 - 0.5*(l^2 + m^2))*Vsig + sqrt(3)*n*(l^2+m^2)*Vpi) - 0.5*s2t*(sqrt(3)*m*n^2*Vsig - 2*m*n^2*Vpi); 46 | end 47 | 48 | end 49 | -------------------------------------------------------------------------------- /TB/src/wigner_seitz_cell.m: -------------------------------------------------------------------------------- 1 | function [structure_in_ws, id_in_ws, IN,tr_vec] = wigner_seitz_cell(convention,structure,mcell,nat) 2 | 3 | % Generate 3x3 supercell 4 | supercell = zeros(4*nat,3); 5 | superid = zeros(4*nat,1); 6 | structure_in_ws = zeros(size(supercell)); 7 | id_in_ws = zeros(size(superid)); 8 | is = 0; 9 | min_dis = 100; 10 | for im = [0,-1] 11 | for jm = [0,-1] 12 | for inat = 1 : nat 13 | is = is + 1; 14 | supercell(is,:) = [structure.x(inat),structure.y(inat),structure.z(inat)] + im*mcell(1,:) + jm*mcell(2,:); 15 | if(norm(supercell(is,:)) < min_dis && (strcmp(structure.name(inat),'Mo') || strcmp(structure.name(inat),'W'))) 16 | min_dis = norm(supercell(is,:)); 17 | min_at_id = is; 18 | end 19 | superid(is) = inat; 20 | end 21 | end 22 | end 23 | % Translate supercell such that a metal atom is at the origin. 24 | tr_vec = supercell(min_at_id,:); 25 | supercell = supercell - tr_vec; 26 | 27 | % Define WS cell 28 | delta = 0.0; 29 | if(convention==2) 30 | % Define vertices of polyong 31 | x1 = 1/3*(mcell(1,1:2) + mcell(2,1:2)); 32 | x2 = 1/3*(-mcell(1,1:2) + 2*mcell(2,1:2)); 33 | x3 = 1/3*(-2*mcell(1,1:2) + mcell(2,1:2)); 34 | x4 =-1/3*(mcell(1,1:2) + mcell(2,1:2)); 35 | x5 = 1/3*(mcell(1,1:2) - 2*mcell(2,1:2)); 36 | x6 = 1/3*(2*mcell(1,1:2) - mcell(2,1:2)); 37 | elseif(convention==1) 38 | % Define vertices of polyong 39 | x1 = 1/3*(2*mcell(1,1:2) + mcell(2,1:2)); 40 | x2 = 1/3*(mcell(1,1:2) + 2*mcell(2,1:2)); 41 | x3 = 1/3*(-mcell(1,1:2) + mcell(2,1:2)); 42 | x4 =-1/3*(2*mcell(1,1:2) + mcell(2,1:2)); 43 | x5 =-1/3*(mcell(1,1:2) + 2*mcell(2,1:2)); 44 | x6 = 1/3*(mcell(1,1:2) - mcell(2,1:2)); 45 | end 46 | XV = [x1(1);x2(1);x3(1);x4(1)-delta;x5(1)-delta;x6(1)-delta;x1(1)]; 47 | YV = [x1(2);x2(2);x3(2);x4(2)-delta;x5(2)-delta;x6(2)-delta;x1(2)]; 48 | IN = inpolygon(supercell(:,1),supercell(:,2),XV,YV); 49 | structure_in_ws = supercell(IN,:); 50 | id_in_ws = superid(IN); 51 | % Check number of atoms in WS cell is the same as moire cell 52 | nat_ws = size(structure_in_ws,1); 53 | if(nat_ws ~= nat) 54 | nat_ws 55 | nat 56 | error('Number of atoms in WS cell is not the equal to Nat') 57 | end 58 | 59 | end 60 | -------------------------------------------------------------------------------- /TB/src/write_ham_hdf5.m: -------------------------------------------------------------------------------- 1 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 | %% Routine to write Hamiltonian in hdf5 %% 3 | %% format. It also writes info on the %% 4 | %% moire geometry and k vectors. %% 5 | %% %% 6 | %% The hamiltonian is divided into real anc %% 7 | %% imaginary part as matlab hdf5 cannot %% 8 | %% deal with complex numbers %% 9 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 10 | %% %% 11 | %% Written by Valerio Vitale, April 2021 %% 12 | %% %% 13 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 14 | 15 | 16 | % Hamiltonian is written in the following format: 17 | % leading dimension (ncolumns) is total number of orbitals * number of k-points 18 | % second dimension (nrows) is total number of orbitals (Norb) 19 | % H = 20 | % __Norb__________________ ________ 21 | % | | | | | | 22 | % Norb{| H(k1)| H(k2)| H(k3)| ... | H(kN)| 23 | % | | | | | | 24 | % |______|______|______|__ _|______| 25 | 26 | 27 | % First transform sparse Hamiltonian into full matrix 28 | Hmat_full = cell(knum_tot); 29 | for ik = 1 : knum_tot 30 | Hmat_full{ik} = full(Hmat{ik}); 31 | end 32 | 33 | % Create an entry for real and complex part of Hamiltonian 34 | h5create(ham_fname,'/hamiltonian/realH',[tot_norbs,tot_norbs*knum_tot]) 35 | h5create(ham_fname,'/hamiltonian/cmplxH',[tot_norbs,tot_norbs*knum_tot]) 36 | count = [tot_norbs,tot_norbs]; 37 | for ik = 1 : knum_tot 38 | start = [1,tot_norbs*(ik-1)+1]; 39 | h5write(ham_fname,'/hamiltonian/realH',real(Hmat_full{ik}),start,count) 40 | h5write(ham_fname,'/hamiltonian/cmplxH',imag(Hmat_full{ik}),start,count) 41 | end 42 | 43 | % Create a geometry/crystal entry 44 | h5create(ham_fname,'/crystal/moire_cell',size(mcell)) 45 | h5write (ham_fname,'/crystal/moire_cell',mcell) 46 | h5create(ham_fname,'/crystal/n_atoms',1) 47 | h5write (ham_fname,'/crystal/n_atoms',tot_natoms) 48 | h5create(ham_fname,'/crystal/n_orbs',1) 49 | h5write (ham_fname,'/crystal/n_orbs',tot_norbs) 50 | h5create(ham_fname,'/crystal/positions',[tot_natoms 3]) 51 | h5write (ham_fname,'/crystal/positions',[structure.x(:) structure.y(:) structure.z(:)]) 52 | h5create(ham_fname,'/crystal/kgrid',[knum_tot 3]) 53 | h5write (ham_fname,'/crystal/kgrid',all_kpts) 54 | 55 | % Create an entry for orbitals properties 56 | % Index as defined in Fang et al. PRB 92 205108 (2015) 57 | % dxz = 1, dyz = 2, pz(bottom) = 3, px(bottom) = 4, py(bottom) = 5 58 | % dz2 = 6, dxy = 7, dx2-y2 = 8, pz(top) = 9, px(top) = 10, py(top) = 11 59 | % N.B. Same orbitals with different spin projections have same index 60 | % So the relative index runs from 1 to 11 61 | h5create(ham_fname,'/orbitals/pattern',[1 tot_norbs]) 62 | orb_pattern = [orbitals.Rel_index]; 63 | h5write (ham_fname,'/orbitals/pattern',orb_pattern) 64 | 65 | % z-component of Spin for each orbital 66 | h5create(ham_fname,'/orbitals/spin',[1 tot_norbs]) 67 | spins = [orbitals.Spin]; 68 | h5write (ham_fname,'/orbitals/spin',spins) 69 | 70 | % Layer to which each orbital belongs to 71 | h5create(ham_fname,'/orbitals/layer',[1 tot_norbs]) 72 | layers = [orbitals.Layer]; 73 | h5write (ham_fname,'/orbitals/layer',layers) 74 | 75 | clear count start Hmat Hmat_full orb_pattern spins 76 | -------------------------------------------------------------------------------- /TB/src/write_hdf5.m: -------------------------------------------------------------------------------- 1 | nv = 2; 2 | nc = 1; 3 | h5create('myfile.h5','/crystal/alat',1) 4 | h5write('myfile.h5','/crystal/alat',aXM1*sqrt(3)) 5 | h5create('myfile.h5','/crystal/avecs',size(unit_cell)) 6 | h5write('myfile.h5','/crystal/avecs',unit_cell) 7 | h5create('myfile.h5','/crystal/centre',[1 3]) 8 | h5write('myfile.h5','/crystal/centre',(a1+a2)/2) 9 | h5create('myfile.h5','/crystal/motif',[tot_natoms 3]) 10 | h5write('myfile.h5','/crystal/motif',[structure.x(:) structure.y(:) structure.z(:)]) 11 | h5create('myfile.h5','/crystal/n_atoms',1) 12 | h5write('myfile.h5','/crystal/n_atoms',tot_natoms) 13 | h5create('myfile.h5','/crystal/n_orbs',1) 14 | h5write('myfile.h5','/crystal/n_orbs',tot_norbs/2) 15 | h5create('myfile.h5','/crystal/orb_pattern',[1 tot_natoms]) 16 | ind1 = find(structure.name == "Mo"); 17 | ind2 = find(structure.name == "S"); 18 | orb_pattern(ind1) = 5; 19 | orb_pattern(ind2) = 3; 20 | h5write('myfile.h5','/crystal/orb_pattern',orb_pattern) 21 | h5create('myfile.h5','/crystal/positions',size(mcell)) 22 | h5write('myfile.h5','/crystal/positions',mcell) 23 | h5create('myfile.h5','/eigensystem/eigenvalues',[nv knum_tot]) 24 | h5write('myfile.h5','/eigensystem/eigenvalues',tb_bands(noccs-1:noccs,:)) 25 | h5create('myfile.h5','/eigensystem/eigenvectors_real',[nc tot_norbs knum_tot]) 26 | h5write('myfile.h5','/eigensystem/eigenvectors_real',real(tb_vecs(noccs+1,:,:))) 27 | h5create('myfile.h5','/eigensystem/eigenvectors_imag',[nc tot_norbs knum_tot]) 28 | h5write('myfile.h5','/eigensystem/eigenvectors_imag',imag(tb_vecs(noccs+1,:,:))) 29 | h5create('myfile.h5','/eigensystem/kgrid',[knum_tot 3]) 30 | h5write('myfile.h5','/eigensystem/kgrid',all_kpts) 31 | h5create('myfile.h5','/eigensystem/n_k',1) 32 | h5write('myfile.h5','/eigensystem/n_k',knum) 33 | h5create('myfile.h5','/eigensystem/n_con',1) 34 | h5write('myfile.h5','/eigensystem/n_con',nc) 35 | h5create('myfile.h5','/eigensystem/n_val',1) 36 | h5write('myfile.h5','/eigensystem/n_val',nv) -------------------------------------------------------------------------------- /TB/src/write_kpts.m: -------------------------------------------------------------------------------- 1 | task = 1 2 | bilayer = true 3 | multilayer = false 4 | knum = 20 5 | path = 'MK' % GM: Gamma-M, MK : M-K, KG: K-Gamma 6 | 7 | % Create kpts.in file 8 | fileID = fopen('kpts.in','w'); 9 | 10 | 11 | % Copy-paste unit lattice vectors from the position file into mcell 12 | ucell = [3.18300000 0.00000000 0.00000000 13 | -1.59150000 2.75655886 0.00000000 14 | 0.00000000 0.00000000 20.00000000]; 15 | ua1 = ucell(1,:); 16 | ua2 = ucell(2,:); 17 | ua3 = ucell(3,:); 18 | 19 | v=abs(dot(ua1,cross(ua2,ua3))); 20 | b1=2*pi*cross(ua2,ua3)/v; 21 | b2=2*pi*cross(ua3,ua1)/v; 22 | b3=2*pi*cross(ua1,ua2)/v; 23 | 24 | % Copy-paste the moire lattice vectors from the position file into mcell 25 | mcell = [3.18300000 0.00000000 0.00000000 26 | -1.59150000 2.75655886 0.00000000 27 | 0.00000000 0.00000000 20.00000000]; 28 | ma1 = mcell(1,:); 29 | ma2 = mcell(2,:); 30 | ma3 = mcell(3,:); 31 | 32 | % Reciprocal lattice vectors of moire cell 33 | mv=abs(dot(ma1,cross(ma2,ma3))); 34 | mb1=2*pi*cross(ma2,ma3)/mv; 35 | mb2=2*pi*cross(ma3,ma1)/mv; 36 | mb3=2*pi*cross(ma1,ma2)/mv; 37 | 38 | [all_kpts,scale_axis,knum_tot,recL,frac_k] = generate_kpoints(task,multilayer,twisted,false,mb1,mb2,mb3,b1,b2,b3,knum); 39 | 40 | % Print first 20 k-points 41 | if(strcmp(path,'GM')) 42 | kinit = 1; 43 | kfinal = knum; 44 | elseif(strcmp(path,'MK')) 45 | kinit = knum+1; 46 | kfinal = 2*knum; 47 | elseif(strcmp(path,'KG')) 48 | kinit = 2*knum + 1; 49 | kfinal = 3*knum; 50 | else 51 | error('k-path not recognised. Aborting') 52 | end 53 | 54 | for ik = kinit : kfinal 55 | fprintf(fileID,'%2.8f %2.8f %2.8f\n',all_kpts(ik,:)); 56 | end 57 | 58 | % Close file 59 | fclose(fileID); 60 | --------------------------------------------------------------------------------