├── .gitignore ├── Amber ├── README.md ├── bias_MD_XX.in ├── disang ├── eq-NVT.in ├── minH.in ├── min_wat.in ├── mintot.in ├── sim-NPT.in └── topology.f90 ├── CRYSTAL ├── README.rst ├── anaFreq.py ├── cry2cif.py ├── cry2cif_old.py ├── crycvg.py ├── cryslab2poscar.py └── crystalio.py ├── GAUSSIAN ├── README.rst ├── spectre.py └── xyz.f90 ├── GROMACS ├── gro2qm.py └── hbonds.py ├── LICENSE ├── README.rst ├── Tex ├── abrbib.py ├── citations └── figures ├── VASP ├── README.rst ├── Uanalyse.py ├── anaStruct.py ├── ana_kpoints.py ├── ana_kpoints_kspacing.py ├── bands_Cu.py ├── bandstructure.py ├── chgmag.f90 ├── chgsplit.f90 ├── chgsum.f90 ├── distorsion.py ├── encut.job ├── getCharges ├── kpoints.job ├── kpoints_kspacing.job ├── makeCL.py ├── makeKpoints.py ├── moduleDOS.py ├── opt_slab.py ├── readCL.py ├── readU.py ├── runU.py ├── scofield.py ├── v └── vacantPosition.py └── Various ├── README.rst ├── ads.py ├── bigfiles.py ├── convert.py ├── groupes.py ├── spheric.py ├── supFile.py ├── vmdmo.py └── zipFile.py /.gitignore: -------------------------------------------------------------------------------- 1 | # MAC OS 2 | .DS_Store 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | 7 | -------------------------------------------------------------------------------- /Amber/README.md: -------------------------------------------------------------------------------- 1 | # AMBER : input files, scripts, fortran topology module 2 | 3 | This folder contains **OLD** [Amber](http://ambermd.org/) input files 4 | or scripts (2010). 5 | 6 | ## Read topology file 7 | 8 | This is a Fortran90 module which contains variables for 9 | 10 | * The atom number and the residu number 11 | * A vector containing the residu number of each atom 12 | * The number of the first atom of each residu 13 | * The mass and the charge of each atom 14 | * The name of each atom 15 | * The residu name of each atom 16 | * The list of residu 17 | 18 | 19 | There is also a subroutine which allocate each vector or table and read the topology file. 20 | 21 | ## AMBER input files and Scripts 22 | 23 | Here are input files to run classical molecular dynamics or minimization with sander or pmemd program of [Amber](http://ambermd.org/). 24 | Scripts files are bash commands which generate the MDIN file and other necessary input file and run the calculation. 25 | 26 | MDIN file are classical sander/pmemd input files. Each line starting with \# are 27 | commentary and must be removed before you used it. 28 | 29 | The following MDIN files are given in a specific order. 30 | You can follow this order to run (N,P,T) simulation from 31 | a pdb file of the [Protein Data Bank](http://www.rcsb.org/) 32 | (you have to prepare topology and coordinate files before you start the first minimization). 33 | 34 | * **minH.in**: Minimization of all hydrogen atoms. Constraints are put on all heavy atoms. 35 | * **min_wat.in**: Minimization of all water molecules. Constraint are put on the protein. 36 | * **mintot.in**: Total minimization of the protein and water molecules with small constraints on the protein. 37 | * **eq-NVT.in**: Simulation at constant volume with small constraints on the protein. Now we warm slowly the simulation box from 100K to 300K. 38 | * **sim-NPT.in**: (N,P,T) Simulation at T = 300 K and P = 1.0 atm. 39 | * **sim-NVE.in**: (N,V,E) Simulation. 40 | * **bias_MD_XX.in**: Bias simulations. You also nead forget the **disang** file in 41 | order to define the bias potential. 42 | -------------------------------------------------------------------------------- /Amber/bias_MD_XX.in: -------------------------------------------------------------------------------- 1 | * * * * * * * * * * * * * * * * * * * * * 2 | REMARK : do not forget the disang file 3 | * * * * * * * * * * * * * * * * * * * * * 4 | 5 | Simulation biaisée à pression constante 6 | &cntrl 7 | NMROPT = 1 8 | IREST = 1, NTX = 5, 9 | NTPR = 1000, NTWR = -10000, NTWX = 1000, 10 | IWRAP = 1, NTWPRT = 4029, 11 | NTR = 0, 12 | NSTLIM = 500000, DT = 0.002, 13 | TEMPI = 300.0, TEMP0 = 300.0, IG = 311008, 14 | NTT = 3, GAMMA_LN = 1.0, 15 | NTP = 1, TAUP = 2.0, PRES0 = 1.0, 16 | NTC = 2, 17 | NTF = 2, NTB = 2, CUT = 10.0, 18 | / 19 | &wt 20 | TYPE = 'DUMPFREQ', ISTEP1 = 50, 21 | / 22 | &wt TYPE = 'END' / 23 | DISANG=disang 24 | DUMPAVE=x_vs_time 25 | -------------------------------------------------------------------------------- /Amber/disang: -------------------------------------------------------------------------------- 1 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 2 | # this file contains the bias potential 3 | 4 | # write a &rst namelist for each coordinate on which you want 5 | # to put a restraint 6 | # RK2 is the force constant between max1 and min1 7 | # RK3 is the force constant between min2 and max2 8 | # the force constant is zero elsewhere 9 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 10 | 11 | # biais on dihASP = C-CA-CB-CG =-30.0 12 | &rst 13 | IAT = iat1, iat2, iat3, iat4, 14 | R1 = max1, R2 = min1, R3 = min2, R4 = max2, 15 | RK2 = 10.0, RK3 = 10.0, 16 | / 17 | 18 | -------------------------------------------------------------------------------- /Amber/eq-NVT.in: -------------------------------------------------------------------------------- 1 | # equilibration ( N , V , T ) Warm the simulation box slowly 2 | # delete all lines begining with # 3 | # 4 | #title 5 | Equilibration a volume constant 6 | #General minimization and dynamics parameters 7 | &cntrl 8 | # General flags describing the calculation 9 | NMROPT = 1, 10 | # Nature and format of the input 11 | IREST = 0, NTX = 1, 12 | # Nature and format of the output 13 | NTPR = 1000, NTWR = 1000, NTWX = 1000, 14 | IWRAP = 1, 15 | # Frozen or restrained atoms 16 | NTR = 1, RESTRAINT_WT = 5.0, 17 | RESTRAINTMASK = ":1-227", 18 | # Molecular Dynamics 19 | NSTLIM = 50000, DT = 0.002, T = 0.0, 20 | # Temperature regulation 21 | TEMPI = 100.0, TEMP0 = 300.0, IG = 220908, 22 | NTT = 3, GAMMA_LN = 1.0, 23 | # Pressure regulation 24 | NTP = 0, 25 | # Shake bond length constraints 26 | NTC = 2, 27 | # Potential function parameters 28 | NTF = 2, NTB = 1, CUT = 10.0, 29 | / 30 | # 31 | # Weight change information 32 | &wt 33 | # defines quantity being varied 34 | TYPE = 'TEMP0', 35 | # This change is applied over steps ISTEP1 throught ISTEP2 36 | ISTEP1 = 1, ISTEP2 = 20000, 37 | # Value of the change corresponding to ISTEP1 and ISTEP2 38 | VALUE1 = 100, VALUE2 = 300, 39 | # The change is done continuously 40 | IINC = 0, 41 | # The change is linearly interpolated from VALUE1 to VALUE2 42 | IMULT = 0, 43 | # end 44 | / 45 | &wt 46 | type='END' 47 | / 48 | 49 | -------------------------------------------------------------------------------- /Amber/minH.in: -------------------------------------------------------------------------------- 1 | # AMBER : Minimization of hydrogen atoms 2 | # delete all lines begining with # 3 | # 4 | #title 5 | minimisation des hydrogenes 6 | #General minimization and dynamics parameters 7 | &cntrl 8 | # General flags describing the calculation 9 | IMIN = 1, 10 | # Nature and format of the output 11 | NTPR = 100, 12 | # Frozen or restrained atoms 13 | NTR = 1, RESTRAINT_WT = 5000.0, 14 | RESTRAINTMASK = ":* & !@H=", 15 | # mask = all residues AND NOT(all atom name starting with H) 16 | # thus mask = all atoms except hydrogen 17 | # 18 | # Energy minimization 19 | MAXCYC = 4000, NCYC = 1000, 20 | # Potential function parameters 21 | NTB = 1, CUT = 10.0, 22 | / 23 | -------------------------------------------------------------------------------- /Amber/min_wat.in: -------------------------------------------------------------------------------- 1 | # AMBER : Water Minimization 2 | # delete all lines begining with # 3 | # 4 | #title 5 | minimization of water molecues 6 | #General minimization and dynamics parameters 7 | &cntrl 8 | # General flags describing the calculation 9 | IMIN = 1, 10 | # Nature and format of the output 11 | NTPR = 100, 12 | # Frozen or restrained atoms 13 | NTR = 1, RESTRAINT_WT = 5000.0, 14 | RESTRAINTMASK = ":1-227", 15 | # Energy minimization 16 | MAXCYC = 4000, NCYC = 1000, 17 | # Potential function parameters 18 | NTB = 1, CUT = 10.0, 19 | / 20 | 21 | -------------------------------------------------------------------------------- /Amber/mintot.in: -------------------------------------------------------------------------------- 1 | # AMBER : Minimization with small constraint 2 | # delete all lines begining with # 3 | # 4 | #title 5 | minimization with small constraint 6 | #General minimization and dynamics parameters 7 | &cntrl 8 | # General flags describing the calculation 9 | IMIN = 1, 10 | # Nature and format of the output 11 | NTPR = 100, 12 | # Frozen or restrained atoms 13 | NTR = 1, RESTRAINT_WT = 5.0, 14 | RESTRAINTMASK = ":1-227", 15 | # Energy minimization 16 | MAXCYC = 4000, NCYC = 1000, 17 | # Potential function parameters 18 | NTB = 1, CUT = 10.0, 19 | / 20 | -------------------------------------------------------------------------------- /Amber/sim-NPT.in: -------------------------------------------------------------------------------- 1 | # AMBER : Simulation ( N , P , T ) 2 | # delete all lines begining with # 3 | # 4 | #title 5 | Simulation ( N , P , T ) 6 | #General minimization and dynamics parameters 7 | &cntrl 8 | # Nature and format of the input 9 | IREST = 1, NTX = 5, 10 | # Nature and format of the output 11 | NTPR = 1000, NTWR = 1000, NTWX = 1000, 12 | IWRAP = 1, 13 | # Frozen or restrained atoms 14 | NTR = 0, 15 | # Molecular Dynamics 16 | NSTLIM = 250000, DT = 0.002, 17 | # Temperature regulation 18 | TEMPI = 300.0, TEMP0 = 300.0, IG = 300908, 19 | NTT = 3, GAMMA_LN = 1.0, 20 | # Pressure regulation 21 | NTP = 1, TAUP = 2.0, PRES0 = 1.0, 22 | # Shake bond length constraints 23 | NTC = 2, 24 | # Potential function parameters 25 | NTF = 2, NTB = 2, CUT = 10.0, 26 | / 27 | 28 | -------------------------------------------------------------------------------- /Amber/topology.f90: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gVallverdu/myScripts/ca84505f8bb6195e50a5950cea68054c474b40c9/Amber/topology.f90 -------------------------------------------------------------------------------- /CRYSTAL/README.rst: -------------------------------------------------------------------------------- 1 | CRYSTAL scripts 2 | =============== 3 | 4 | Script concerning post or pre treatments with CRYSTAL. 5 | 6 | cry2cif.py 7 | Read the output file of a CRYSTAL calcualtion and create a cif file to be 8 | read with VESTA. 9 | 10 | cryslab2poscar.py 11 | Read the output file of a CRYSTAL calculation with SLABCUT instruction in 12 | order to construct a surface and write the corresponding POSCAR file. 13 | 14 | anaFreq.py 15 | Read IR modes in a CRYSTAL output. 16 | 17 | -------------------------------------------------------------------------------- /CRYSTAL/anaFreq.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding=utf-8 -*- 3 | 4 | import sys 5 | #from math import sqrt 6 | 7 | def readModes(outfile): 8 | """ read frequencies data on file outfile """ 9 | 10 | out = open(outfile, "r") 11 | line = None 12 | atom = list() 13 | while line != "": 14 | line = out.readline() 15 | if "NUMBER OF IRREDUCIBLE ATOMS IN THE CONVENTIONAL CELL" in line: 16 | nat = int(line.split(":")[1]) 17 | 18 | if "COORDINATES OF THE EQUIVALENT ATOMS" in line: 19 | out.readline() 20 | out.readline() 21 | out.readline() 22 | line = out.readline() 23 | while "NUMBER OF SYMMETRY" not in line: 24 | atom.append(line.split()[4]) 25 | out.readline() 26 | line = out.readline() 27 | 28 | if "NORMAL MODES NORMALIZED TO CLASSICAL AMPLITUDES" in line: 29 | out.readline() 30 | out.readline() 31 | out.readline() 32 | break 33 | 34 | ndep = 3 * nat 35 | 36 | nmodes = 0 37 | modes = list() 38 | while nmodes != ndep: 39 | for i in range(6): 40 | modes.append(list()) 41 | line = out.readline() 42 | while line.strip() != "": 43 | if "AT." in line: 44 | val = [float(v) for i, v in enumerate(line.split()) if i in range(4, 10)] 45 | else: 46 | val = [float(v) for v in line.split()[1:]] 47 | 48 | for i in range(6): 49 | modes[nmodes + i].append(val[i]) 50 | 51 | line = out.readline() 52 | 53 | nmodes += 6 54 | out.readline() 55 | out.readline() 56 | 57 | out.close() 58 | print("3 * Natoms : {0}".format(ndep)) 59 | print("Nombre de modes : {0}".format(nmodes)) 60 | 61 | return modes, atom 62 | 63 | def readFrequencies(outfile): 64 | """ read frequencies data on file outfile """ 65 | 66 | out = open(outfile, "r") 67 | line = None 68 | while line != "": 69 | line = out.readline() 70 | if "CONVERSION FACTORS FOR FREQUENCIES:" in line: 71 | for i in range(7): 72 | out.readline() 73 | break 74 | 75 | nmodes = 0 76 | frequencies = list() 77 | line = out.readline() 78 | while line.strip() != "": 79 | data = [float(val.strip(")")) for i, val in enumerate(line.split()) if i in [2, 3, 4, 9]] 80 | frequencies.append(data) 81 | nmodes += 1 82 | line = out.readline() 83 | 84 | out.close() 85 | print("Nombre de modes : {0}".format(nmodes)) 86 | 87 | # dans frequences : [ua, cm^-1, THz, Intens IR] 88 | return frequencies 89 | 90 | def anaFreq(): 91 | """ build a spectrum """ 92 | 93 | outfile = sys.argv[1] 94 | print("reading file {0}".format(outfile)) 95 | 96 | freqData = readFrequencies(outfile) 97 | modes, atoms = readModes(outfile) 98 | 99 | for n, mode in enumerate(modes): 100 | 101 | tot = 0. 102 | for val in mode: 103 | tot += val**2 104 | #tot = sqrt(tot) 105 | 106 | contrib = dict() 107 | for i, iat in zip(range(0, 96, 3), range(len(atoms))): 108 | #at = sqrt(mode[i]**2 + mode[i + 1]**2 + mode[i + 2]**2) 109 | at = mode[i]**2 + mode[i + 1]**2 + mode[i + 2]**2 110 | if atoms[iat] not in contrib.keys(): 111 | contrib[atoms[iat]] = at 112 | else: 113 | contrib[atoms[iat]] += at 114 | 115 | line = "%12.4f" % freqData[n][1] 116 | for atom in contrib.keys(): 117 | line += "%10.2f" % (contrib[atom] / tot * 100.0) 118 | print(line) 119 | 120 | 121 | #print("\nFreq %12.4f cm**-1" % freqData[n][1]) 122 | 123 | for atom in contrib.keys(): 124 | print(atom) 125 | 126 | if __name__ == "__main__": 127 | anaFreq() 128 | -------------------------------------------------------------------------------- /CRYSTAL/cry2cif.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | cry2cif\n\n 6 | 7 | Read the last geometry corresponding to the CRYSTALLOGRAPHIC CELL on a 8 | CRYSTAL09 output file and print it in a cif format. If geometry 9 | optimization did not converge, input geometry is printed instead. 10 | """ 11 | 12 | # TODO: 13 | # * returns coordinates instead of write a file 14 | # * make functions for various formats 15 | 16 | __author__ = "Germain Vallverdu" 17 | __email__ = "germain.vallverdu@univ-pau.fr" 18 | __licence__ = "GPL" 19 | 20 | import os 21 | import argparse 22 | from pymatgen import Structure, Lattice 23 | from crystalio import CrystalOutfile 24 | 25 | 26 | def get_options(): 27 | """ get options from command lines """ 28 | 29 | parser = argparse.ArgumentParser(prog="cry2cif", description=__doc__) 30 | 31 | # mandatory argument is CRYSTAL output filename 32 | parser.add_argument("filename", 33 | help="CRYSTAL output file", 34 | metavar="FILENAME", 35 | type=str) 36 | 37 | # choose either cif or POSCAR format 38 | parser.add_argument("-t", "--to", 39 | help="output format: either cif or VASP (POSCAR)", 40 | metavar="format", 41 | default="cif", 42 | choices=("cif", "vasp"), 43 | type=str) 44 | 45 | # center slab or nanotubes 46 | parser.add_argument("-i", "--center", 47 | help="move the slab or nanotubes in the center of the box", 48 | action="store_true", 49 | dest="center", 50 | default=False) 51 | 52 | parser.add_argument("-n", "--num_structure", 53 | help="Structure number to be extracted (default, the last)", 54 | metavar="N", 55 | default=-1, 56 | type=int) 57 | 58 | # sort atom along z or x for slab or nanotubes 59 | parser.add_argument("-z", "--sortz", 60 | help="Sort atoms along z axis (for slabs)", 61 | dest="sortz", 62 | action="store_true", 63 | default=False) 64 | parser.add_argument("-x", "--sortx", 65 | help="Sort atoms along x axis (for nanotubes)", 66 | dest="sortx", 67 | action="store_true", 68 | default=False) 69 | 70 | # in the case of slabs or nanotubes, you have to give a value for b or c 71 | parser.add_argument("-b", 72 | help="lattice parameter b", 73 | metavar="b", 74 | default=50, 75 | type=float) 76 | parser.add_argument("-c", 77 | help="lattice parameter c", 78 | metavar="c", 79 | default=50, 80 | type=float) 81 | 82 | return parser.parse_args() 83 | 84 | 85 | def cry2cif(filename, to="cif", center=False, sortx=False, sortz=False, 86 | b_dum=50, c_dum=50, istruct=-1): 87 | """ 88 | Read a CRYSTAL output file and return the structure in a cif or POSCAR format. 89 | 90 | Args: 91 | filename (str): crystal output filename 92 | to (str): 'cif' or 'vasp', format of the output file (default is cif) 93 | center (bool): if True, the slab or nanotube is translated to the center of 94 | the box (default is False) 95 | sortx (bool): Nanotube : if True, atoms are sorted along x axes (default is False). 96 | sortz (bool): slab : if True, atoms are sorted along z axes (default is False). 97 | b_dum (float): dummy lattice paramters b in angstrom for nanotubes (default 50 A) 98 | c_dum (float): dummy lattice paramters c in angstrom for nanotubes and slabs (default 50 A) 99 | istruct (int): structure to be extracted 100 | 101 | """ 102 | cryout = CrystalOutfile(filename) 103 | 104 | print("title : ", cryout.title) 105 | if cryout.group: 106 | print("group : ", cryout.group) 107 | 108 | # print("Number of structure read: ", len(cryout.structures)) 109 | 110 | if istruct == -1: 111 | print("structure : Final structure") 112 | structure = cryout.final_structure 113 | else: 114 | print("structure : Structure %d" % istruct) 115 | structure = cryout.get_structure(istruct) 116 | print("# atom : ", structure.num_sites) 117 | print("composition: ", structure.composition) 118 | print("Cell parameters:") 119 | print("a : %10.4f" % structure.lattice.a) 120 | print("b : %10.4f" % structure.lattice.b) 121 | print("c : %10.4f" % structure.lattice.c) 122 | print("alpha : %10.4f" % structure.lattice.alpha) 123 | print("beta : %10.4f" % structure.lattice.beta) 124 | print("gamma : %10.4f" % structure.lattice.gamma) 125 | 126 | # ---------------------------------------------------------- 127 | # New b and c axes 128 | # ---------------------------------------------------------- 129 | if cryout.slab: 130 | frac_coords = structure.frac_coords 131 | frac_coords[:, 2] *= structure.lattice.c / c_dum 132 | matrix = structure.lattice.matrix.copy() 133 | matrix[2, 2] = c_dum 134 | structure = Structure(Lattice(matrix), structure.species, frac_coords) 135 | if cryout.nanotube: 136 | frac_coords = structure.frac_coords 137 | frac_coords[:, 1] *= structure.lattice.c / c_dum 138 | frac_coords[:, 2] *= structure.lattice.b / b_dum 139 | matrix = structure.lattice.matrix.copy() 140 | matrix[1, 1] = b_dum 141 | matrix[2, 2] = c_dum 142 | structure = Structure(Lattice(matrix), structure.species, frac_coords) 143 | 144 | # ---------------------------------------------------------- 145 | # move slab or nanotube to the center of the box 146 | # ---------------------------------------------------------- 147 | if center: 148 | if cryout.slab: 149 | coords = structure.frac_coords.copy() 150 | coords[:, 2] += .5 151 | structure = Structure(structure.lattice, structure.species, coords) 152 | elif cryout.nanotube: 153 | coords = structure.frac_coords 154 | coords += .5 155 | structure = Structure(structure.lattice, structure.species, coords) 156 | 157 | # ---------------------------------------------------------- 158 | # sort atom along x or z axis for slab 159 | # ---------------------------------------------------------- 160 | if sortz: 161 | isort = 2 162 | elif sortx: 163 | isort = 0 164 | 165 | axes = {2: "z", 0: "x"} 166 | if sortz or sortx: 167 | print("\nSort atoms along %s" % axes[isort]) 168 | data = zip(structure.species, structure.frac_coords) 169 | data = sorted(data, key=lambda d: d[-1][isort], reverse=True) 170 | 171 | species = [d[0] for d in data] 172 | coords = [d[1] for d in data] 173 | structure = Structure(structure.lattice, species, coords) 174 | 175 | # ---------------------------------------------------------- 176 | # export in the given format 177 | # ---------------------------------------------------------- 178 | basename, _ = os.path.splitext(filename) 179 | if to.lower() == "cif": 180 | ext = ".cif" 181 | elif to.lower() == "vasp": 182 | to = "POSCAR" 183 | ext = ".vasp" 184 | else: 185 | to = "POSCAR" 186 | ext = ".vasp" 187 | structure.to(to, filename=basename + ext) 188 | 189 | 190 | if __name__ == "__main__": 191 | # get arguments 192 | args = vars(get_options()) 193 | # rename some args 194 | args["b_dum"] = args.pop("b") 195 | args["c_dum"] = args.pop("c") 196 | args["istruct"] = args.pop("num_structure") 197 | # call main program 198 | cry2cif(**args) 199 | -------------------------------------------------------------------------------- /CRYSTAL/crycvg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | crycvg 6 | 7 | Read a CRYSTAL output file and plot convergence data. 8 | """ 9 | 10 | __author__ = "Germain Vallverdu" 11 | __email__ = "germain.vallverdu@univ-pau.fr" 12 | __licence__ = "GPL" 13 | 14 | import sys 15 | import matplotlib.pyplot as plt 16 | from crystalio import CrystalOutfile 17 | 18 | 19 | def crycvg(filename): 20 | """ 21 | Plot relevant quantities in order to follow a geometry convergence with CRYSTAL 22 | """ 23 | 24 | cryout = CrystalOutfile(filename) 25 | nstep = len(cryout.convergence_data) 26 | 27 | print("title : ", cryout.title) 28 | print("Optimization steps: ", nstep) 29 | 30 | plt.rcParams.update({"axes.grid": True, "font.size": 16}) 31 | 32 | fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(nrows=2, ncols=2, sharex=True, 33 | figsize=(12, 8)) 34 | fig.suptitle("CRYSTAL: Convergence panel") 35 | 36 | ax1.plot([e - min(cryout.energies) for e in cryout.energies], marker="o", 37 | label="$E_{min}$ = %e ua" % min(cryout.energies), linestyle="--") 38 | ax1.set_ylabel("$E - E_{min}$ (ua)") 39 | ax1.set_xlabel("Optimization steps") 40 | ax1.legend() 41 | 42 | ax2.plot([data["max_grad"] for data in cryout.convergence_data], 43 | marker="o", linestyle="dashed", label="max gradient") 44 | ax2.plot([data["rms_grad"] for data in cryout.convergence_data], 45 | label="rms gradient", marker="o", linestyle="dashed") 46 | ax2.plot([data["max_grad_thr"] for data in cryout.convergence_data], color="C0") 47 | ax2.plot([data["rms_grad_thr"] for data in cryout.convergence_data], color="C1") 48 | ax2.set_ylabel("MAX/RMS GRADIENT") 49 | ax2.set_xlabel("Optimization steps") 50 | ax2.legend() 51 | 52 | # displacement start at step 1 53 | ax3.plot(range(1, nstep), [data["max_displac"] for data in cryout.convergence_data[1:]], 54 | label="Max Displacement", marker="o", linestyle="dashed") 55 | ax3.plot(range(1, nstep), [data["rms_displac"] for data in cryout.convergence_data[1:]], 56 | label="RMS Displacement", marker="o", linestyle="dashed") 57 | ax3.plot(range(1, nstep), [data["max_displac_thr"] for data in cryout.convergence_data[1:]], 58 | color="C0") 59 | ax3.plot(range(1, nstep), [data["rms_displac_thr"] for data in cryout.convergence_data[1:]], 60 | color="C1") 61 | ax3.set_ylabel("MAX/RMS Displacement") 62 | ax3.set_xlabel("Optimization steps") 63 | ax3.legend() 64 | 65 | # Gradient norm is not printed if STEP is rejected ! 66 | plt_data = list() 67 | for step, data in enumerate(cryout.convergence_data): 68 | if "norm_grad" in data: 69 | plt_data.append([step, data["norm_grad"], data["norm_grad_thr"]]) 70 | else: 71 | plt.axvline(step, color="C3") 72 | ax4.plot([data[0] for data in plt_data], [data[1] for data in plt_data], 73 | label="norm grad", marker="o", linestyle="dashed") 74 | ax4.plot([data[0] for data in plt_data], [data[2] for data in plt_data], color="C0") 75 | ax4.set_ylabel("NORME GRADIENT") 76 | ax4.set_xlabel("Optimization steps") 77 | ax4.text(1, 1, "Rejected steps", color="C3", horizontalalignment='right', 78 | verticalalignment='bottom', transform=ax4.transAxes, fontsize=12) 79 | 80 | # fig.tight_layout() 81 | # ax1.set_xticklabels(ax1.get_xticks()) 82 | # [tk.set_visible(True) for tk in ax1.get_xticklabels()] 83 | 84 | plt.show() 85 | 86 | 87 | if __name__ == "__main__": 88 | crycvg(sys.argv[1]) 89 | -------------------------------------------------------------------------------- /CRYSTAL/cryslab2poscar.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | Read the CRYSTAL output file after a SLABCUT and build a POSCAR for the surface model. 6 | The slab model is put at the center of the box (-c option) or at the bottom of 7 | the box (-b option). Use -h or --help to get help. 8 | """ 9 | 10 | __author__ = "Germain Vallverdu" 11 | __email__ = "germain.vallverdu@univ-pau.fr" 12 | __licence__ = "GPL" 13 | 14 | import os 15 | import argparse 16 | from pymatgen.core.sites import Site 17 | from pymatgen.core.structure import Lattice, Structure 18 | from pymatgen.io.vasp.inputs import Poscar 19 | 20 | def get_args(): 21 | """ get CRYSTAL output file names and options """ 22 | 23 | def exist(f): 24 | """ 'Type' for argparse - checks that file exists but does not open """ 25 | if not os.path.isfile(f): 26 | raise argparse.ArgumentTypeError("{0} does not exist".format(f)) 27 | return f 28 | 29 | parser = argparse.ArgumentParser(description=__doc__) 30 | 31 | # CRYSTAL output file name is mandatory 32 | parser.add_argument("cryout", 33 | help="path to the CRYSTAL output file containing the SLABCUT run", 34 | nargs=1, 35 | metavar="FILE.out", 36 | type=exist) 37 | # options 38 | parser.add_argument("-o", "--poscar", 39 | help="Name of POSCAR output file", 40 | metavar="POSCAR", 41 | default="POSCAR_slabcut.vasp") 42 | parser.add_argument("-z", "--zvide", 43 | help="Vacuum height in angstrom", 44 | metavar="ZVIDE", 45 | default=12., 46 | type=float) 47 | parser.add_argument("-c", '--center', dest='center', 48 | help="Put the slab at the center of the box.", 49 | action='store_true') 50 | parser.add_argument("-b", '--bottom', dest='bottom', 51 | help="Put the slab at the bottom of the box.", 52 | action='store_true') 53 | 54 | return parser.parse_args() 55 | 56 | 57 | def read_struct(filename): 58 | """ 59 | Read lattice and atom positions from the crystal output file after a 60 | SLABCUT run. 61 | """ 62 | with open(filename, "r") as f: 63 | lignes = f.readlines() 64 | 65 | sectionCoord = False 66 | sites = list() 67 | for i, ligne in enumerate(lignes): 68 | 69 | if "DEFINITION OF THE NEW LATTICE VECTORS" in ligne: 70 | while "LATTICE PARAMETERS (ANGSTROM" not in ligne: 71 | i += 1 72 | ligne = lignes[i] 73 | params = [float(val) for val in lignes[i+2].split()] 74 | slab_lattice = Lattice.from_parameters(*params[0:3], *params[3:]) 75 | 76 | if "COORDINATES OF THE ATOMS BELONGING TO THE SLAB" in ligne: 77 | sectionCoord = True 78 | continue 79 | 80 | if sectionCoord: 81 | # on saute la premiere ligne 82 | if "LAB" in ligne: 83 | continue 84 | 85 | # si ligne blanche on sort 86 | if ligne.strip() == "" : 87 | break 88 | 89 | z = int(ligne.split()[1]) 90 | valeurs = [float(val) for val in ligne[56:].split()] 91 | sites.append(Site(z, valeurs)) 92 | 93 | return slab_lattice, sites 94 | 95 | if __name__ == "__main__": 96 | 97 | # read args from command line 98 | args = get_args() 99 | slab_lattice, sites = read_struct(args.cryout[0]) 100 | 101 | # -------------------- 102 | # zmin et zmax 103 | # -------------------- 104 | zmin = min([site.z for site in sites]) 105 | zmax = max([site.z for site in sites]) 106 | print("zmin = {:12.7f}".format(zmin)) 107 | print("zmax = {:12.7f}".format(zmax)) 108 | print("dz = {:12.7f}".format(zmax - zmin)) 109 | 110 | # -------------------------------------------------------------- 111 | # new value of the lattice parameter perpendcular to the surface 112 | # -------------------------------------------------------------- 113 | newc = zmax - zmin + args.zvide 114 | print("new c = {:12.7f}\n".format(newc)) 115 | 116 | a, b, c = slab_lattice.abc 117 | newLattice = Lattice.from_parameters(a=a, b=b, c=newc, 118 | alpha=90., beta=90., gamma=slab_lattice.gamma) 119 | 120 | # -------------------------------------------- 121 | # decalage des coordonnees entre 0 et 1 dans (xy) 122 | # conversion de z en coordonnees reduites 123 | # -------------------------------------------- 124 | print(args) 125 | newSites = list() 126 | for site in sites: 127 | coords = site.coords 128 | coords[0] += .5 129 | coords[1] += .5 130 | if args.center: 131 | coords[2] = coords[2] / newLattice.c + .5 132 | elif args.bottom: 133 | coords[2] = (coords[2] - zmin) / newLattice.c 134 | else: 135 | coords[2] = coords[2] / newLattice.c 136 | 137 | newSites.append(Site(site.specie, coords)) 138 | 139 | # ----------------------------------- 140 | # make a structure and print POSCAR 141 | # ----------------------------------- 142 | struct = Structure(newLattice, [site.specie for site in newSites], [site.coords for site in newSites]) 143 | struct.sort() 144 | Poscar(struct).write_file(args.poscar) 145 | print(struct) 146 | -------------------------------------------------------------------------------- /GAUSSIAN/README.rst: -------------------------------------------------------------------------------- 1 | Gaussian scripts 2 | ================ 3 | 4 | Script concerning post or pre treatments with Gaussian. 5 | 6 | spectre.py 7 | Plot an UV-visible spectum from the output of a td-DFT calculation. To each 8 | transition, a gaussian function is added with a given width (in energy) and 9 | an area equal to the oscillator strength. 10 | 11 | xyz.f90 12 | Extract the last geometry from a gaussian ouput file. 13 | -------------------------------------------------------------------------------- /GAUSSIAN/spectre.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | Plot an UV-visible spectum from the output of a td-DFT calculation. To each 6 | transition, a gaussian function is added with a given width (in energy) and 7 | an area equal to the oscillator strength. 8 | 9 | Syntaxe : 10 | 11 | spectre.py fichier [sigma, [step ] ] 12 | 13 | fichier : fichier gaussian que l'on va lire (obligatoire) 14 | sigma : largeur de la gaussienne (optionnel) 15 | step : nombre de points pour construire le spectre (optionnel) 16 | 17 | """ 18 | __author__ = "Germain Vallverdu " 19 | __licence__ = "GPL" 20 | __date__ = "Janvier 2014" 21 | 22 | import os 23 | import sys 24 | import scipy as sp 25 | import scipy.constants as cst 26 | import matplotlib.pyplot as plt 27 | from matplotlib.mlab import normpdf 28 | 29 | def readTransitions(fichier): 30 | """ read excitations energies from a gaussian log file 31 | 32 | :param fichier: Name of the gaussian log file 33 | :type fichier: string 34 | :return: List of excitation energies, wavelength and oscillator strength 35 | :rtype: List 36 | 37 | """ 38 | 39 | transitions = list() 40 | 41 | td = False 42 | for line in open(fichier, "r"): 43 | if "Excitation energies" in line: 44 | td = True 45 | continue 46 | 47 | if td: 48 | if "Excited State" in line: 49 | ene = float(line.split()[4]) 50 | lam = float(line.split()[6]) 51 | f = float(line.split("f=")[1]) 52 | transitions.append([ene, lam, f]) 53 | elif "****" in line: 54 | break 55 | 56 | for i, trans in enumerate(transitions): 57 | print("%2d E = %8.4f eV ; L = %8.2f nm ; f = %6.4f" % (i+1, trans[0], trans[1], trans[2])) 58 | 59 | return transitions 60 | 61 | def makeSpectre(transitions, sigma, step): 62 | """ Build a spectrum from transitions energies. For each transitions a gaussian 63 | function of width sigma is added in order to mimick natural broadening. 64 | 65 | :param transitions: list of transitions for readTransitions() 66 | :type transititions: list 67 | :param sigma: gaussian width in eV 68 | :type sigma: float 69 | :param step: number of absissa value 70 | :type step: int 71 | :return: absissa and spectrum value in this order 72 | :rtype: list, list 73 | 74 | """ 75 | 76 | # max and min transition energies 77 | minval = min([val[0] for val in transitions]) - 5.0 * sigma 78 | maxval = max([val[0] for val in transitions]) + 5.0 * sigma 79 | 80 | # points 81 | npts = int((maxval - minval) / step) + 1 82 | 83 | # absice 84 | eneval = sp.linspace(minval, maxval, npts) 85 | 86 | spectre = sp.zeros(npts) 87 | for trans in transitions: 88 | spectre += trans[2] * normpdf(eneval, trans[0], sigma) 89 | 90 | return eneval, spectre 91 | 92 | def plotSpectre(transitions, eneval, spectre): 93 | """ plot the UV-visible spectrum using matplotlib. Absissa are converted in nm. """ 94 | 95 | # lambda in nm 96 | lambdaval = [cst.h * cst.c / (val * cst.e) * 1.e9 for val in eneval] 97 | 98 | # plot gaussian spectra 99 | plt.plot(lambdaval, spectre, "r-", label = "spectre") 100 | 101 | # plot transitions 102 | plt.vlines([val[1] for val in transitions], \ 103 | 0., \ 104 | [val[2] for val in transitions], \ 105 | color = "blue", \ 106 | label = "transitions" ) 107 | 108 | plt.xlabel("lambda / nm") 109 | plt.ylabel("Arbitrary unit") 110 | plt.title("UV-visible spectra") 111 | plt.grid() 112 | plt.legend(fancybox = True, shadow = True) 113 | plt.show() 114 | 115 | def spectre(fichier, sigma, step): 116 | """ call previous routine and make the spectra """ 117 | 118 | # read transitions 119 | transitions = readTransitions(fichier) 120 | 121 | # build spectrum 122 | eneval, spectre = makeSpectre(transitions, sigma, step) 123 | 124 | # plot spectre 125 | plotSpectre(transitions, eneval, spectre) 126 | 127 | line = "# Spectre\n" 128 | line += "# column 1 : energies in eV\n" 129 | line += "# column 2 : spectre (arbitrary unit)\n" 130 | for x, y in zip(eneval, spectre): 131 | line += "%12.6f %12.6f\n" % (x, y) 132 | open("spectre.dat", "w").write(line) 133 | 134 | if __name__ == "__main__": 135 | 136 | fichier = sys.argv[1] 137 | if not os.path.exists(fichier): 138 | print("File %s does not exist" % fichier) 139 | 140 | try: 141 | sigma = float(sys.argv[2]) 142 | except IndexError: 143 | sigma = 0.05 144 | 145 | try: 146 | step = float(sys.argv[3]) 147 | except IndexError: 148 | step = 0.001 149 | 150 | print("--------------------------------------") 151 | print("File : %s" % fichier) 152 | print("sigma : %8.4f" % sigma) 153 | print("step : %8.4f" % step) 154 | print("--------------------------------------") 155 | 156 | spectre(fichier, sigma, step) 157 | 158 | -------------------------------------------------------------------------------- /GAUSSIAN/xyz.f90: -------------------------------------------------------------------------------- 1 | ! ****************************************************************************** 2 | ! 3 | ! programme : xyz 4 | ! 5 | ! description : genere un fichier au format xyz a partir d'une geometrie lu 6 | ! sur un fichier .log ou .com de gaussian 7 | ! 8 | ! format xyz : 9 | ! ligne 1 = nbre d'atome 10 | ! ligne 2 = titre 11 | ! ligne 3 -> nbre d'atome = nomatome x y z 12 | ! 13 | ! syntaxe : xyz mon_calcul.log 14 | ! fichier de sortie mon_calcul.xyz 15 | ! 16 | ! dans un .log en entree 17 | ! Extrait la derniere geometrie Input orientation trouvee 18 | ! 19 | ! dans un .com contenant des coordonnées cartesienne 20 | ! Extrait la geometrie et l'ecrit au format xyz 21 | ! 22 | ! ****************************************************************************** 23 | 24 | program xyz 25 | 26 | implicit none 27 | 28 | integer, parameter :: ndim = 1000 29 | integer :: nat, iat, k, io 30 | integer :: klog, kcom 31 | character(len=100) :: fichier, ligne 32 | character(len=4), dimension(ndim) :: nomcom 33 | character(len=4) :: nom 34 | integer, dimension(ndim) :: mass 35 | double precision,dimension(ndim,3) :: x 36 | logical :: existe, fin, trouve 37 | 38 | write(*,*) 39 | 40 | call get_command_argument(1,fichier) 41 | write(*,*)"lecture du fichier "//trim(fichier) 42 | 43 | ! test d'existence du fichier et reconnaissance 44 | inquire( file=trim(fichier) , exist=existe) 45 | if( .not. existe ) then 46 | write(*,*)" fichier non trouve: "//trim(fichier) 47 | stop 48 | end if 49 | 50 | ! teste .com ou .log 51 | klog = 0 52 | kcom = 0 53 | if( index(fichier,".log") /= 0 .or. index(fichier,".out") /= 0 ) klog = 1 54 | if( index(fichier,".com") /= 0 ) kcom = 1 55 | if( klog == 0 .and. kcom == 0) then 56 | write(*,*)" type .log ou .com non identifie "//trim(fichier) 57 | write(*,*)"le nom du fichier doit finir par .log ou .com" 58 | stop 59 | end if 60 | if( klog == 1 .and. kcom == 1) then 61 | write(*,*)" type .log ou .com non identifie "//trim(fichier) 62 | write(*,*)" le nom du fichier contient .com et .log" 63 | stop 64 | end if 65 | 66 | nom(:) = "XX" 67 | 68 | ! LECTURE DU FICHIER 69 | 70 | if( klog == 1 ) then 71 | 72 | ! CAS DU FICHIER LOG 73 | 74 | write(*,*)"c'est un fichier .log" 75 | open(10,file=trim(fichier),action="read") 76 | fin = .false. 77 | do while ( .not. fin ) 78 | trouve = .false. 79 | do while( .not. trouve ) 80 | read( 10, "(a)", iostat=io)ligne 81 | if( io < 0 ) then 82 | fin = .true. 83 | trouve = .true. 84 | end if 85 | if( index(ligne,"Input orientation") /= 0 ) trouve = .true. 86 | if( index(ligne,"Z-Matrix orientation") /= 0 ) trouve = .true. 87 | end do 88 | 89 | if( .not. fin ) then 90 | read(10,*) 91 | read(10,*) 92 | read(10,*) 93 | read(10,*) 94 | iat = 0 95 | trouve = .false. 96 | do while ( .not. trouve ) 97 | ligne = "" 98 | read(10,"(a)") ligne 99 | if(index(ligne,"-------") /= 0 ) then 100 | trouve = .true. 101 | else 102 | iat = iat + 1 103 | read(ligne,*) k, mass(iat), k, (x(iat,k), k=1,3) 104 | end if 105 | end do 106 | nat = iat 107 | end if 108 | 109 | end do 110 | close(10) 111 | 112 | else if( kcom == 1 ) then 113 | 114 | ! CAS DU FICHIER COM 115 | 116 | write(*,*)"c'est un fichier .com" 117 | open(10,file=trim(fichier),action="read") 118 | ! calcul 119 | fin = .false. 120 | do while ( .not. fin ) 121 | ligne="" 122 | read(10,"(a)")ligne 123 | if( len_trim(ligne) == 0) fin = .true. ! ligne blanche 124 | end do 125 | ! titre 126 | fin = .false. 127 | do while ( .not. fin ) 128 | ligne="" 129 | read(10,"(a)")ligne 130 | if( len_trim(ligne) == 0) fin = .true. ! ligne blanche 131 | end do 132 | ! ligne charge multiplicite 133 | read(10,"(a)")ligne 134 | ! atomes 135 | iat=0 136 | fin = .false. 137 | do while ( .not. fin ) 138 | ligne="" 139 | read(10,"(a)")ligne 140 | if( ligne == "" ) then 141 | fin = .true. 142 | else 143 | iat = iat + 1 144 | read(ligne,*) nomcom(iat), (x(iat,k), k=1,3) 145 | end if 146 | end do 147 | nat=iat 148 | close(10) 149 | else 150 | 151 | write(*,*)"type de fichier inconnu" 152 | stop 153 | 154 | end if 155 | 156 | write(*,*)"nombre d'atome lu ",nat 157 | 158 | ! ecriture du fichier xyz 159 | 160 | if( klog == 1 ) then 161 | if( index(fichier,".log") /= 0 ) k=index(fichier,".log") 162 | if( index(fichier,".out") /= 0 ) k=index(fichier,".out") 163 | 164 | open(11,file=trim(fichier(:k-1) )//".xyz" ) 165 | write(*,*)"fichier xyz => "//trim(fichier(:k-1) )//".xyz" 166 | else if(kcom == 1 ) then 167 | k=index(fichier,".com") 168 | open(11,file=trim(fichier(:k-1) )//".xyz" ) 169 | write(*,*)"fichier xyz => "//trim(fichier(:k-1) )//".xyz" 170 | else 171 | write(*,*)"type de fichier inconnu" 172 | stop 173 | end if 174 | 175 | write(ligne,*)nat 176 | 177 | write(11,"(a)")trim(adjustl(ligne)) 178 | write(11,"(a)")"geometrie issue du fichier "//trim(fichier) 179 | 180 | do iat=1,nat 181 | 182 | if( klog == 1 ) then 183 | 184 | if( mass(iat) == 1 ) nom = "H" 185 | if( mass(iat) == 2 ) nom = "He" 186 | 187 | if( mass(iat) == 3 ) nom = "Li" 188 | if( mass(iat) == 4 ) nom = "Be" 189 | if( mass(iat) == 5 ) nom = "B" 190 | if( mass(iat) == 6 ) nom = "C" 191 | if( mass(iat) == 7 ) nom = "N" 192 | if( mass(iat) == 8 ) nom = "O" 193 | if( mass(iat) == 9 ) nom = "F" 194 | if( mass(iat) ==10 ) nom = "Ne" 195 | 196 | if( mass(iat) ==11 ) nom = "Na" 197 | if( mass(iat) ==12 ) nom = "Mg" 198 | if( mass(iat) ==13 ) nom = "Al" 199 | if( mass(iat) ==14 ) nom = "Si" 200 | if( mass(iat) ==15 ) nom = "P" 201 | if( mass(iat) ==16 ) nom = "S" 202 | if( mass(iat) ==17 ) nom = "Cl" 203 | if( mass(iat) ==18 ) nom = "Ar" 204 | 205 | if( mass(iat) ==19 ) nom = "K" 206 | if( mass(iat) ==20 ) nom = "Ca" 207 | if( mass(iat) ==21 ) nom = "Sc" 208 | if( mass(iat) ==22 ) nom = "Ti" 209 | if( mass(iat) ==23 ) nom = "V" 210 | if( mass(iat) ==24 ) nom = "Cr" 211 | if( mass(iat) ==25 ) nom = "Mn" 212 | if( mass(iat) ==26 ) nom = "Fe" 213 | if( mass(iat) ==27 ) nom = "Co" 214 | if( mass(iat) ==28 ) nom = "Ni" 215 | if( mass(iat) ==29 ) nom = "Cu" 216 | if( mass(iat) ==30 ) nom = "Zn" 217 | if( mass(iat) ==31 ) nom = "Ga" 218 | if( mass(iat) ==32 ) nom = "Ge" 219 | if( mass(iat) ==33 ) nom = "As" 220 | if( mass(iat) ==34 ) nom = "Se" 221 | if( mass(iat) ==35 ) nom = "Br" 222 | if( mass(iat) ==36 ) nom = "Kr" 223 | 224 | if( mass(iat) ==37 ) nom = "Rb" 225 | if( mass(iat) ==38 ) nom = "Sr" 226 | if( mass(iat) ==39 ) nom = "Y" 227 | if( mass(iat) ==40 ) nom = "Zr" 228 | if( mass(iat) ==41 ) nom = "Nb" 229 | if( mass(iat) ==42 ) nom = "Mo" 230 | if( mass(iat) ==43 ) nom = "Tc" 231 | if( mass(iat) ==44 ) nom = "RU" 232 | if( mass(iat) ==45 ) nom = "Rh" 233 | if( mass(iat) ==46 ) nom = "Pd" 234 | if( mass(iat) ==47 ) nom = "Ag" 235 | if( mass(iat) ==48 ) nom = "Cd" 236 | if( mass(iat) ==49 ) nom = "In" 237 | if( mass(iat) ==50 ) nom = "Sn" 238 | if( mass(iat) ==51 ) nom = "Sb" 239 | if( mass(iat) ==52 ) nom = "Te" 240 | if( mass(iat) ==53 ) nom = "I" 241 | if( mass(iat) ==54 ) nom = "Xe" 242 | 243 | if( mass(iat) ==55 ) nom = "Cs" 244 | if( mass(iat) ==56 ) nom = "Ba" 245 | 246 | if( mass(iat) ==72 ) nom = "Hf" 247 | if( mass(iat) ==73 ) nom = "Ta" 248 | if( mass(iat) ==74 ) nom = "W" 249 | if( mass(iat) ==75 ) nom = "Re" 250 | if( mass(iat) ==76 ) nom = "Os" 251 | if( mass(iat) ==77 ) nom = "Ir" 252 | if( mass(iat) ==78 ) nom = "Pt" 253 | if( mass(iat) ==79 ) nom = "Au" 254 | if( mass(iat) ==80 ) nom = "Hg" 255 | if( mass(iat) ==81 ) nom = "Tl" 256 | if( mass(iat) ==82 ) nom = "Pb" 257 | if( mass(iat) ==83 ) nom = "Bi" 258 | if( mass(iat) ==84 ) nom = "Po" 259 | if( mass(iat) ==85 ) nom = "At" 260 | if( mass(iat) ==86 ) nom = "Rn" 261 | 262 | write(11,"(a4,3F12.6)")adjustl(nom),(x(iat,k),k=1,3) 263 | else if( kcom == 1 ) then 264 | write(11,"(a4,3F12.6)")adjustl(nomcom(iat)),(x(iat,k),k=1,3) 265 | else 266 | write(*,*)"type de fichier inconnu" 267 | stop 268 | end if 269 | 270 | end do 271 | write(11,*) 272 | close(11) 273 | 274 | write(*,*) 275 | 276 | end program xyz 277 | -------------------------------------------------------------------------------- /GROMACS/gro2qm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | ___ 6 | |__ \\ 7 | __ _ _ __ ___ ) | __ _ _ __ ___ 8 | / _ || __|/ _ \ / / / _ || _ _ \\ 9 | | (_| || | | (_) |/ /_| (_| || | | | | | 10 | \__, ||_| \___/|____|\__, ||_| |_| |_| 11 | __/ | | | 12 | |___/ |_| 13 | 14 | This program export a Gromacs configuration from a centered trajectory to an 15 | input file for a QM calculation. Use the following command in order to get a 16 | centered GROMACS trajectory from the traj_comp.xtc file. 17 | 18 | gmx trjconv -pbc mol -center -ur compact -s run.tpr -f traj_comp.xtc -o trajout.xtc 19 | 20 | 21 | """ 22 | 23 | import os 24 | import re 25 | import argparse 26 | import time 27 | 28 | import numpy as np 29 | 30 | import pymatgen as mg 31 | from pymatgen.io.gaussian import GaussianInput 32 | 33 | import mdtraj as md 34 | 35 | TITLE = """ 36 | ___ 37 | |__ \\ 38 | __ _ _ __ ___ ) | __ _ _ __ ___ 39 | / _ || __|/ _ \ / / / _ || _ _ \\ 40 | | (_| || | | (_) |/ /_| (_| || | | | | | 41 | \__, ||_| \___/|____|\__, ||_| |_| |_| 42 | __/ | | | 43 | |___/ |_| 44 | 45 | """ 46 | 47 | 48 | def extract_confs(trajectory, **kwargs): 49 | """ 50 | Extract a snapshot and make a QM input file. In order to set up the QM input 51 | file you have to write the custum_work function. That function must take 52 | as arguments a numpy array of the coordinates of the current snapshot and a 53 | mdtraj.Topology object. Moreover, the whole input arg are passed as a kwargs. 54 | """ 55 | 56 | # number of frame, for array dimention 57 | nframe, natom = trajectory.xyz.shape[:2] 58 | 59 | # get needed variables: 60 | interval = kwargs["interval"] 61 | path = kwargs["path"] 62 | begin = kwargs["begin"] 63 | end = kwargs["end"] 64 | qm_software = kwargs["qm_software"] 65 | 66 | print("Start configuration extraction") 67 | print("------------------------------") 68 | 69 | t1 = time.time() 70 | t0 = t1 71 | jobs = "" 72 | for iframe, coords in enumerate(trajectory.xyz): 73 | 74 | # exclude frame before 'begin' 75 | if iframe < begin: 76 | continue 77 | 78 | # exclude frame after 'end' 79 | if end != -1 and iframe > end: 80 | continue 81 | 82 | # time evaluation 83 | if iframe % (nframe // 10) == 0 and iframe != 0: 84 | t2 = time.time() 85 | dt = t2 - t1 86 | print(" **** %3.0f%% in %.0f s - frame %4d (ETA %.0f s)" % ( 87 | iframe / nframe * 100, dt, iframe, dt * 10 - (t2 - t0))) 88 | t1 = t2 89 | 90 | # extract one frame every interval 91 | if (iframe - begin) % interval == 0: 92 | 93 | qm_coords, qm_names = custom_work(coords, mdtop=trajectory.top, **kwargs) 94 | 95 | # make the input file 96 | if qm_software == "gaussian": 97 | jobs += write_gau_input(qm_names, qm_coords, iframe, **kwargs) 98 | elif qm_software == "orca": 99 | print("Will be supported soon !") 100 | raise ValueError() 101 | else: 102 | raise ValueError("Wrong QM software name.") 103 | 104 | jobs += "\n" 105 | 106 | dt = time.time() - t0 107 | print("Done in %.0f s" % dt) 108 | 109 | # script to launch jobs 110 | with open(os.path.join(path, "lancer.sh"), "w") as f: 111 | f.write("#!/bin/bash\n\n") 112 | f.write("cd %s\n\n" % os.path.join(os.getcwd(), path)) 113 | f.write(jobs) 114 | 115 | 116 | def write_gau_input(species, coords, iframe, jobname="run_gau", **kwargs): 117 | """ write a gaussian input file """ 118 | 119 | path = kwargs["path"] 120 | functional = kwargs["functional"] 121 | basis_set = kwargs["basis_set"] 122 | nprocs = kwargs["nprocs"] 123 | 124 | # get first letter of atom name => element 125 | species = [specie[0] for specie in species] 126 | 127 | # convert nm to angstrom 128 | coords = np.array(coords) * 10 129 | 130 | # build Molecule and Gaussian object 131 | mol = mg.Molecule(species, coords, validate_proximity=True) 132 | ginp = GaussianInput( 133 | mol, 134 | charge=0, 135 | title="Written by gro2qm - snapshot %d" % iframe, 136 | functional=functional, basis_set=basis_set, 137 | route_parameters={"pop": "(MK, MBS)"}, 138 | link0_parameters={"%nprocs": nprocs}, 139 | dieze_tag="#" 140 | ) 141 | 142 | basename = "gau_%05d" % iframe 143 | ginp.write_file(os.path.join(path, basename + ".com"), cart_coords=True) 144 | mol.to(fmt="xyz", filename=os.path.join(path, basename + ".xyz")) 145 | 146 | return "sbatch -J snap_%05d %s %s.com" % (iframe, jobname, basename) 147 | 148 | 149 | def read_xtc(trajfile, top, **kwargs): 150 | """ read the trajectrory using mdtraj module from the xtc file """ 151 | 152 | print("Read trajectory file: ", trajfile) 153 | print("Read topology from: ", top) 154 | 155 | t1 = time.time() 156 | trajectory = md.load(trajfile, top=top) 157 | t2 = time.time() - t1 158 | 159 | nframes, natoms = trajectory.xyz.shape[:2] 160 | print("# frames: ", nframes) 161 | print("# atoms: ", natoms) 162 | print("Read trajecory in %.0f s\n" % t2) 163 | 164 | return trajectory 165 | 166 | 167 | def get_options(): 168 | """ get options from the command line """ 169 | 170 | parser = argparse.ArgumentParser( 171 | prog="gro2gau", 172 | formatter_class=argparse.RawDescriptionHelpFormatter, 173 | description=__doc__ 174 | ) 175 | 176 | # trying to mimic gromacs gmx option names 177 | parser.add_argument("-f", "--trajfile", 178 | help="GROMACS trajectory file.", 179 | metavar="TRAJFILE", 180 | default="traj_comp.xtc", 181 | type=str) 182 | 183 | parser.add_argument("-s", "--top", 184 | help="A file which contains topology: a gro or pdb file for example.", 185 | metavar="TOP", 186 | default="confout.gro", 187 | type=str) 188 | 189 | parser.add_argument("-p", "--path", 190 | help="output path for QM input files", 191 | metavar="PATH", 192 | default="./gau/", 193 | type=str) 194 | 195 | parser.add_argument("-i", "--interval", 196 | help="Frame is extracted if mod(iframe, interval) == 0", 197 | metavar="I", 198 | default=10, 199 | type=int) 200 | 201 | parser.add_argument("-b", "--begin", 202 | help="Index of the first snapshot.", 203 | metavar="I", 204 | default=0, 205 | type=int) 206 | 207 | parser.add_argument("-e", "--end", 208 | help="Index of the last snapshot.", 209 | metavar="I", 210 | default=-1, 211 | type=int) 212 | 213 | # QM calculation options 214 | parser.add_argument("-q", "--qm_software", 215 | help="Name of the QM software for which input files will be done (gaussian or orca).", 216 | metavar="QM_SOFTWARE", 217 | default="gaussian", 218 | choices=["gaussian", "orca"], 219 | type=str) 220 | 221 | parser.add_argument("--functional", 222 | help="Hamiltonian for the QM calculation.", 223 | metavar="FUNC", 224 | default="cam-B3LYP", 225 | type=str) 226 | 227 | parser.add_argument("--basis_set", 228 | help="Basis set for the QM calculation.", 229 | metavar="BASIS", 230 | default="6-31+G**", 231 | type=str) 232 | 233 | parser.add_argument("--nprocs", 234 | help="Number of cpu required for the QM calculation.", 235 | metavar="PROCS", 236 | default=1, 237 | type=int) 238 | 239 | return vars(parser.parse_args()) 240 | 241 | 242 | def custom_work(coords, mdtop, **kwargs): 243 | """ """ 244 | 245 | # data 246 | rcut = 0.7 247 | natmol1 = 1 - 1 248 | natmol2 = 26 - 1 249 | 250 | # conformation C 251 | # 2 = N2 252 | # 9 = O3 253 | # 12 = O4 254 | # 16 = O1 255 | # 20 = O2 256 | # 24 = N1 257 | # hetatoms = [i - 1 for i in [2, 9, 12, 16, 20, 24]] 258 | # nwat_by_atoms = [3, 1, 3, 3, 3, 3] 259 | 260 | # conformation B 261 | # 2 = N2 262 | # 9 = O3 263 | # 12 = O1 264 | # 16 = O2 265 | # 25 = O4 266 | # 20 = N1 267 | hetatoms = [i - 1 for i in [2, 9, 12, 16, 25, 20]] 268 | nwat_by_atoms = [3, 1, 3, 3, 3, 3] 269 | 270 | # coordinates of the molecule 271 | qm_coords = coords[natmol1: natmol2 + 1] 272 | qm_names = [mdtop.atom(iat).name for iat in range(natmol1, natmol2 + 1)] 273 | qm_coords = qm_coords.tolist() 274 | 275 | # look for the first sovation shell of the molecule 276 | dmax = 0. 277 | nwat = 0 278 | all_water_selected = list() 279 | for hetatom, nwat_by_atom in zip(hetatoms, nwat_by_atoms): 280 | water_selected = list() 281 | for atom in mdtop.atoms: 282 | # exclude the solute molecule 283 | if natmol1 <= atom.index <= natmol2: 284 | continue 285 | 286 | # look for O atom of water molecule 287 | if atom.name == "O" and atom.residue.name == "HOH" and \ 288 | atom.index not in all_water_selected: 289 | 290 | iat = atom.index 291 | rij = coords[iat] - coords[hetatom] 292 | dij = np.sqrt((rij**2).sum()) 293 | 294 | if dij <= rcut: 295 | water_selected.append((iat, dij)) 296 | 297 | # extract the nwat_by_atom cloesest molecules 298 | water_selected.sort(key=lambda item: item[1]) 299 | d_val = "" 300 | nLH = 0 301 | for iwat in range(nwat_by_atom): 302 | iat, d = water_selected[iwat] 303 | 304 | # add to the whole water selected 305 | all_water_selected.append(iat) 306 | 307 | nwat += 1 308 | dmax = max(dmax, d) 309 | if d < 0.32: 310 | d_val += "%8.3f*" % d 311 | nLH += 1 312 | else: 313 | d_val += "%8.3f " % d 314 | 315 | # add the water molecule to qm_coords 316 | qm_coords.append(coords[iat].tolist()) 317 | qm_coords.append(coords[iat + 1].tolist()) 318 | qm_coords.append(coords[iat + 2].tolist()) 319 | qm_names += ["OW", "HW", "HW"] 320 | 321 | print("{:4d} {:4d} {:4d} {}".format(hetatom, nwat_by_atom, nLH, d_val)) 322 | 323 | 324 | print("{:10.4f} {:5d}".format(dmax, nwat)) 325 | return qm_coords, qm_names 326 | 327 | if __name__ == "__main__": 328 | 329 | # read command line arguments 330 | args = get_options() 331 | if not os.path.exists(args["path"]): 332 | os.mkdir(args["path"]) 333 | print("Make folder: ", args["path"]) 334 | if not os.path.isdir(args["path"]): 335 | raise OSError("%s is not a directory." % args["path"]) 336 | 337 | print(TITLE) 338 | 339 | # read trajectory 340 | trajectory = read_xtc(**args) 341 | 342 | # make gaussian inputs 343 | extract_confs(trajectory, **args) 344 | 345 | # add = False 346 | # if add: 347 | # # add H 348 | # # N2, H14, H13, C6 349 | # # 1, 0, 2, 3 => isomere C 350 | # N = 1 351 | # H1 = 0 352 | # H2 = 2 353 | # C = 3 354 | # b1 = coords[H1, :] - coords[N, :] 355 | # b1 /= np.sqrt((b1**2).sum()) 356 | # b2 = coords[H2, :] - coords[N, :] 357 | # b2 /= np.sqrt((b2**2).sum()) 358 | # b3 = coords[C, :] - coords[N, :] 359 | # b3 /= np.sqrt((b3**2).sum()) 360 | # vec = -(b1 + b2 + b3) 361 | # vec /= np.sqrt((vec**2).sum()) 362 | # newH = coords[N, :] + 1 * vec 363 | # 364 | # species.append("H") 365 | # coords = np.concatenate([coords, newH.reshape(1, 3)], axis=0) 366 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | myScripts 2 | ========= 3 | 4 | Script library mainly about chemical physics. 5 | 6 | -------------------------------------------------------------------------------- /Tex/abrbib.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import re 4 | import sys 5 | import os 6 | 7 | CASSI= {"physical review b": "Phys. Rev. B", 8 | "journal of applied crystallography": "J. Appl. Crystallogr.", 9 | "journal of the electrochemical society": "J. Electrochem. Soc.", 10 | "the journal of chemical physics": "J. Chem. Phys.", 11 | "journal of chemical physics": "J. Chem. Phys.", 12 | "solid state ionics": "Solid State Ionics", 13 | "computational materials science": "Comput. Mater. Sci.", 14 | "journal of materials chemistry": "J. Mater. Chem.", 15 | "vibrational spectroscopy": "Vib. Spectrosc.", 16 | "journal of power sources": "J. Power Sources", 17 | "physical review letters": "Phys. Rev. Lett.", 18 | "acta crystallographica section c": "Acta Crystallogr., Sect. C", 19 | "crystallography reports": "Crystallogr. Rep.", 20 | "philosophical magazine part b": "Philos. Mag. B", 21 | "journal of non-crystalline solids": "J. Non-Cryst. Solids", 22 | "journal of solid state chemistry": "J. Solid State Chem.", 23 | "solid state communications": "Solid State Commun.", 24 | "advanced energy materials": "Adv. Energy Mater.", 25 | # "Zeitschrift für Physik": "Z. Phys.", 26 | "Zeitschrift fuer Physik": "Z. Phys.", 27 | "surface science": "Surf. Sci.", 28 | "catalysis today": "Catal. Today" 29 | } 30 | 31 | def cassi_abr(fname): 32 | """ 33 | Modify the journal key of all bib entries in fname and replace it by its 34 | corresponding abreviation 35 | """ 36 | j_patt = re.compile("^\s*journal\s*=\s*\{\s*(.+)\s*\}") 37 | 38 | with open(fname, "r") as f: 39 | newbib = "" 40 | for line in f: 41 | m = j_patt.match(line) 42 | if m: 43 | journal = m.group(1) 44 | newbib += " journal = {{{0}}},\n".format(find_abbreviation(journal)) 45 | else: 46 | newbib += line 47 | 48 | base, ext = os.path.splitext(fname) 49 | with open(base + "_abr" + ext, "w") as f: 50 | f.write(newbib) 51 | 52 | def find_abbreviation(journal): 53 | """ 54 | Look for abreviation of journal in CASSI conventions 55 | 56 | Args: 57 | journal: full name of the journal 58 | 59 | Returns: 60 | abrreviation: abreviation of the journal or the journal if the 61 | abreviation was not found. 62 | """ 63 | if journal.lower() in CASSI: 64 | return CASSI[journal.lower()] 65 | else: 66 | print("abreviation of {0} not found".format(journal)) 67 | suggest = [j for j in CASSI if dameraulevenshtein(j, journal.lower()) > .5] 68 | if suggest: 69 | print("Similar Journals :") 70 | for j in suggest: 71 | print(" * {0}: {1}".format(j, CASSI[j])) 72 | return journal 73 | 74 | def dameraulevenshtein(seq1, seq2): 75 | """Calculate the Damerau-Levenshtein distance between sequences. 76 | 77 | This distance is the number of additions, deletions, substitutions, 78 | and transpositions needed to transform the first sequence into the 79 | second. Although generally used with strings, any sequences of 80 | comparable objects will work. 81 | 82 | Transpositions are exchanges of *consecutive* characters; all other 83 | operations are self-explanatory. 84 | 85 | This implementation is O(N*M) time and O(M) space, for N and M the 86 | lengths of the two sequences. 87 | """ 88 | # http://blog.developpez.com/philben/p11268/vba-access/similarite_entre_deux_chaines_de_caracte 89 | # http://mwh.geek.nz/2009/04/26/python-damerau-levenshtein-distance/ 90 | # Conceptually, this is based on a len(seq1) + 1 * len(seq2) + 1 matrix. 91 | # However, only the current and two previous rows are needed at once, 92 | # so we only store those. 93 | oneago = None 94 | thisrow = list(range(1, len(seq2) + 1)) + [0] 95 | for x in range(len(seq1)): 96 | # Python lists wrap around for negative indices, so put the 97 | # leftmost column at the *end* of the list. This matches with 98 | # the zero-indexed strings and saves extra calculation. 99 | twoago, oneago, thisrow = oneago, thisrow, [0] * len(seq2) + [x + 1] 100 | for y in range(len(seq2)): 101 | delcost = oneago[y] + 1 102 | addcost = thisrow[y - 1] + 1 103 | subcost = oneago[y - 1] + (seq1[x] != seq2[y]) 104 | thisrow[y] = min(delcost, addcost, subcost) 105 | # This block deals with transpositions 106 | if (x > 0 and y > 0 and seq1[x] == seq2[y - 1] 107 | and seq1[x-1] == seq2[y] and seq1[x] != seq2[y]): 108 | thisrow[y] = min(thisrow[y], twoago[y - 2] + 1) 109 | 110 | dls = 1 - thisrow[len(seq2) - 1] / max(len(seq1), len(seq2)) 111 | return dls 112 | 113 | if __name__ == "__main__": 114 | #print("barette ", dameraulevenshtein("tbalrette", "barette")) 115 | #print("tablette ", dameraulevenshtein("tbalrette", "tablette")) 116 | #print("turbulette ", dameraulevenshtein("tbalrette", "turbulette")) 117 | cassi_abr(sys.argv[1]) 118 | 119 | -------------------------------------------------------------------------------- /Tex/citations: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | citations 6 | --------- 7 | 8 | NAME 9 | citations - return the name of all bibitems cited in a tex file and eventually 10 | compare the list of these bibitems withe the bibentries found in a 11 | bibtex file. 12 | 13 | SYNTAX 14 | citations [OPTIONS] file1.tex [file2.tex [file2.tex [file3.tex ...]] biblio.bib] 15 | 16 | DESCRIPTION 17 | file_i.tex latex files (at least one is needed) 18 | biblio.bib bibtex file (optional, only one) 19 | 20 | look for all command \cite{bibitem} in tex files and return all bibitem. If a 21 | bibtex file is provided, a comparison between the bibitems found in the tex file 22 | and bibentries found in the bibtex file is done. 23 | 24 | The command used for doing the citation reference can be modified via the -c option. 25 | 26 | OPTIONS 27 | -h, --help 28 | print this help and exit 29 | 30 | -c cmd1,cmd2,... 31 | cmd are the tex command used in order to insert citation 32 | references. They must be given comma separated and without 33 | white spaces. 34 | default : cite,citet,citep 35 | 36 | TODO : 37 | * It does not work if a line is broken inside a citation command. 38 | """ 39 | 40 | import sys 41 | import os 42 | 43 | __author__ = "Germain Vallverdu " 44 | __licence__ = "GPL" 45 | 46 | def usage(code = 0): 47 | """ usage """ 48 | print(__doc__) 49 | exit(code) 50 | 51 | def citations(cmd, texlist, bibfile): 52 | """ Read a LaTeX file and print all citations included in the document via the 53 | cmd command. 54 | 55 | args : 56 | * cmd (list) : list of commands used for citations 57 | * bibfile (str) : bibtex file 58 | 59 | """ 60 | 61 | for tex in texlist: 62 | if os.path.isfile(tex): 63 | print("\n-------------------------------------------") 64 | print("file : {0}".format(tex)) 65 | print("-------------------------------------------") 66 | citedKeys = list() 67 | for cmdi in cmd: 68 | cited = searchCite(tex, cmdi) 69 | for akey in cited: 70 | if akey not in citedKeys: 71 | citedKeys.append(akey) 72 | citedKeys.sort() 73 | for citedKey in citedKeys: 74 | print(citedKey) 75 | print(" ---------- {0} citations".format(len(citedKeys))) 76 | else: 77 | print("file {0} does not exist".format(tex)) 78 | 79 | 80 | if bibfile is not None: 81 | if os.path.isfile(bibfile): 82 | bibkeys = searchBibentry(bibfile) 83 | print("\n-------------------------------------------") 84 | print("bibkeys missing in bibtex file ") 85 | print("-------------------------------------------") 86 | for citedKey in citedKeys: 87 | if citedKey not in bibkeys: 88 | print(citedKey) 89 | print("\n-------------------------------------------") 90 | print("bibkey not used in tex file") 91 | print("-------------------------------------------") 92 | for bibkey in bibkeys: 93 | if bibkey not in citedKeys: 94 | print(bibkey) 95 | else: 96 | print("file {0} does not exist".format(bibfile)) 97 | 98 | def searchBibentry(bibfile): 99 | """ return all bibtex entry found in bibfile """ 100 | 101 | liste = list() 102 | for line in open(bibfile, "r"): 103 | if line[0] == "@": 104 | entry = line.split("{")[1].strip()[:-1] 105 | liste.append(entry.lower()) 106 | return liste 107 | 108 | def searchCite(source, cmd): 109 | """ return all bibkey used in file source with the command cmd """ 110 | citeList = list() 111 | for line in open(source, "r"): 112 | if cmd in line: 113 | for linePart in line.split("\\" + cmd + "{")[1:]: 114 | citeContains = linePart.split("}")[0].split(",") 115 | for bibkey in citeContains: 116 | if bibkey.strip().lower() not in citeList: 117 | citeList.append(bibkey.strip().lower()) 118 | return citeList 119 | 120 | if __name__ == "__main__": 121 | cmd = ["cite", "citet", "citep"] 122 | bibfile = None 123 | texlist = list() 124 | i = 1 125 | if len(sys.argv) > 1: 126 | while i < len(sys.argv): 127 | if sys.argv[i] == "-h" or sys.argv[i] == "--help": 128 | usage(0) 129 | 130 | elif sys.argv[i] == "-c": 131 | cmd = sys.argv[i+1].split(",") 132 | i += 1 133 | 134 | else: 135 | if i == len(sys.argv)-1: 136 | if ".bib" in sys.argv[i]: 137 | bibfile = sys.argv[i] 138 | else: 139 | texlist.append(sys.argv[i]) 140 | else: 141 | texlist.append(sys.argv[i]) 142 | 143 | i += 1 144 | 145 | else: 146 | usage(0) 147 | 148 | citations(cmd, texlist, bibfile) 149 | -------------------------------------------------------------------------------- /Tex/figures: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding=utf-8 -*- 3 | 4 | import sys 5 | import os 6 | 7 | def figures(): 8 | """ Read a LaTeX file and print all figure included in the document via the 9 | includegraphics command """ 10 | 11 | if len(sys.argv) > 1: 12 | for tex in sys.argv[1:]: 13 | if os.path.isfile(tex): 14 | print("\n-------------------------------------------") 15 | print("file : {0}".format(tex)) 16 | print("-------------------------------------------") 17 | printFiguresName(tex) 18 | else: 19 | print("file {0} does not exist".format(tex)) 20 | 21 | else: 22 | print("First argument must be a latex file name or a path to a latex file") 23 | exit(1) 24 | 25 | def printFiguresName(source): 26 | """ print figure name included in the tex code with the includegraphics command """ 27 | n = 0 28 | print("{:>3s} {:>5s} {: 0 and line[0] == "%": 33 | continue 34 | elif "includegraphics" in line: 35 | name = line.split("includegraphics")[1].split("{")[1].split("}")[0] 36 | n += 1 37 | print("{:3d} {:5d} {:8s} {si:>8s} " 50 | lines += f"{ave_mag:10.4f} {std_mag:10.4f} " 51 | lines += f"{total_mag:10.4f} " 52 | lines += f"{ave_dist:10.4f} {std_dist:10.4f} " 53 | lines += "".join([f"{d:6.3f}" for d in distances]) 54 | lines += "\n" 55 | 56 | 57 | with open("data.dat", "w") as f: 58 | f.write(lines) 59 | -------------------------------------------------------------------------------- /VASP/anaStruct.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | from __future__ import print_function, division 5 | 6 | """ 7 | script anaStruct 8 | ---------------- 9 | 10 | L'objectif de ce script est de calculer tous les angles et toutes les liaisons 11 | à partir d'un fichier vasprun.xml ou POSCAR/CONTCAR. 12 | 13 | """ 14 | 15 | import os 16 | import sys 17 | import numpy as np 18 | from scipy.stats import norm 19 | import pymatgen as mg 20 | import matplotlib.pyplot as plt 21 | 22 | 23 | def anaStruct(poscar, calcDistance=True, calcAngle=True, plot=True): 24 | """ main program """ 25 | 26 | # load data 27 | if not os.path.exists(poscar): 28 | print("file %s does not exist" % poscar) 29 | exit(1) 30 | else: 31 | print("Read file ", poscar) 32 | struct = mg.Structure.from_file(poscar) 33 | 34 | # distance analysis 35 | sigma = .005 36 | npts = 500 37 | xmin = .9 38 | xmax = 2. 39 | if calcDistance: 40 | x, data = getDistances(struct, sigma, npts, xmin, xmax) 41 | 42 | if plot: 43 | for bond, h in data.items(): 44 | plt.plot(x, h, label=bond) 45 | plt.xlabel(r"distance / $\AA$") 46 | plt.ylabel("Histogram") 47 | plt.grid() 48 | plt.legend() 49 | plt.title("Histogram of distances") 50 | plt.show() 51 | 52 | # angle analysis 53 | amin = 80. 54 | amax = 100. 55 | cutoff = 3.0 56 | centralAtom = "Mn" 57 | ligandAtom = "O" 58 | sigma = .5 59 | npts = 200 60 | if calcAngle: 61 | x, h = getAngles(struct, sigma, npts, amin, amax, cutoff, centralAtom, ligandAtom) 62 | 63 | if plot: 64 | plt.plot(x, h, "k-") 65 | plt.xlabel("Angle / degree") 66 | plt.ylabel("Histogram") 67 | plt.grid() 68 | plt.title("Histogram of angles %s-%s-%s" % (ligandAtom, 69 | centralAtom, ligandAtom)) 70 | plt.show() 71 | 72 | 73 | def getAngles(struct, sigma, npts, amin, amax, cutoff, centralAtom, ligandAtom): 74 | """ compute all angles """ 75 | 76 | # info 77 | print("\nBending angles analyses :") 78 | print("-------------------------") 79 | print("Central atom : %s" % centralAtom) 80 | print("Ligand atom : %s" % ligandAtom) 81 | print("cutoff : %f" % cutoff) 82 | 83 | # central sites 84 | central_sites = [site for site in struct 85 | if site.specie == mg.Element(centralAtom)] 86 | 87 | # x values for histogram 88 | aval = np.linspace(amin, amax, npts) 89 | 90 | # data 91 | data = np.zeros(npts) 92 | 93 | print("\nCoordinence") 94 | for csite in central_sites: 95 | neighbors = [(site, d) for site, d in struct.get_neighbors(csite, cutoff) 96 | if site.specie == mg.Element(ligandAtom)] 97 | iat = struct.index(csite) 98 | print("%5s(%2d) : %d" % (csite.specie.symbol, iat, len(neighbors))) 99 | 100 | #neighbors.append((distance, xij)) 101 | 102 | # compute bending angles and build histogram 103 | for i in range(len(neighbors)): 104 | isite, di = neighbors[i] 105 | xic = isite.coords - csite.coords 106 | for j in range(i + 1, len(neighbors)): 107 | jsite, dj = neighbors[j] 108 | xjc = jsite.coords - csite.coords 109 | scal = np.dot(xic, xjc) / di / dj 110 | if np.fabs(scal) > 1.: 111 | print("Dot product error : %f" % scal) 112 | raise ValueError 113 | angle = np.degrees(np.arccos(scal)) 114 | 115 | # add a gaussian function 116 | data += norm.pdf(aval, loc=angle, scale=sigma) 117 | 118 | # print data 119 | line = "# structural analysis\n" 120 | line += "# column 1 : angle (degree)\n" 121 | line += "# column 2 : histogram of angle %s-%s-%s\n" % (ligandAtom, centralAtom, ligandAtom) 122 | for a, h in zip(aval, data): 123 | line += "%12.4f %12.4f\n" % (a, h) 124 | 125 | print("\n=> Print file anaAngles.dat\n") 126 | open("anaAngles.dat", "w").write(line) 127 | 128 | return aval, data 129 | 130 | 131 | def getDistances(struct, sigma, npts, xmin, xmax): 132 | """ compute all distances """ 133 | 134 | # system composition 135 | atomTypes = [e.symbol for e in struct.composition.elements] 136 | NAtomsType = len(struct.composition.elements) 137 | 138 | print("\nBond length analyses :") 139 | print("----------------------") 140 | print("Atoms : ", " ; ".join(atomTypes)) 141 | print("N atoms : ", NAtomsType) 142 | 143 | # bond types 144 | bondsList = list() 145 | for ityp in range(NAtomsType): 146 | for jtyp in range(ityp, NAtomsType): 147 | if atomTypes[ityp] > atomTypes[jtyp]: 148 | bondsList.append(atomTypes[ityp] + "-" + atomTypes[jtyp]) 149 | else: 150 | bondsList.append(atomTypes[jtyp] + "-" + atomTypes[ityp]) 151 | 152 | NBondsType = len(bondsList) 153 | print("N bonds : ", (NBondsType)) 154 | print("Bonds : " + " ; ".join(bondsList)) 155 | 156 | # x values for histogram 157 | xval = np.linspace(xmin, xmax, npts) 158 | 159 | # histogram 160 | data = dict() 161 | 162 | # compute all distances 163 | Natoms = len(struct) 164 | for iat in range(Natoms): 165 | for jat in range(iat + 1, Natoms): 166 | 167 | # compute the cartesian coordinate and the distance 168 | distance = struct.get_distance(iat, jat) 169 | 170 | # xmax act as a cutoff 171 | if distance > xmax: 172 | continue 173 | 174 | # select the relevant bond 175 | if struct[iat].specie.symbol > struct[jat].specie.symbol: 176 | selectedBond = struct[iat].specie.symbol + "-" + struct[jat].specie.symbol 177 | else: 178 | selectedBond = struct[jat].specie.symbol + "-" + struct[iat].specie.symbol 179 | 180 | # add a gaussian 181 | if selectedBond in data: 182 | data[selectedBond] += norm.pdf(xval, loc=distance, scale=sigma) 183 | else: 184 | data[selectedBond] = norm.pdf(xval, loc=distance, scale=sigma) 185 | 186 | # print data 187 | line = "# structural analysis \n" 188 | line += "# column 1 : x (A)\n" 189 | for i, bond in enumerate(data.keys()): 190 | line += "# column %d : bond %s \n" % (i + 2, bond) 191 | for i, x in enumerate(xval): 192 | line += "%10.4f" % x 193 | for key in data.keys(): 194 | line += " %10.4f" % data[key][i] 195 | line += "\n" 196 | 197 | print("\n=> Print file anaDistances.dat\n") 198 | open("anaDistances.dat", "w").write(line) 199 | 200 | return xval, data 201 | 202 | if __name__ == "__main__": 203 | # poscar name 204 | if len(sys.argv) == 2: 205 | poscar = sys.argv[1] 206 | else: 207 | poscar = "CONTCAR" 208 | anaStruct(poscar, calcAngle=False, plot=True) 209 | -------------------------------------------------------------------------------- /VASP/ana_kpoints.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | 5 | # use pymatgen objects 6 | from pymatgen.io.vasp.inputs import Poscar 7 | from pymatgen.io.vasp.outputs import Oszicar 8 | 9 | # header 10 | print("# k a b c alpha beta gamma" + 11 | " Econv SinglePts DE") 12 | 13 | # OSZICAR files 14 | oszicar = [f for f in os.listdir("./") if "OSZICAR_" in f] 15 | oszicar.sort(key=lambda x: int(x.strip("OSZICAR_"))) 16 | 17 | # CONTCAR files 18 | contcar = [f for f in os.listdir("./") if "CONTCAR_" in f] 19 | contcar.sort(key=lambda x: int(x.strip("CONTCAR_"))) 20 | 21 | save = 0.0 22 | 23 | # boucle sur les points k 24 | for cont, osz in zip(contcar, oszicar): 25 | i = int(cont.strip("CONTCAR_")) 26 | 27 | # chargement de la structure 28 | p = Poscar.from_file(cont) 29 | a, b, c = p.structure.lattice.abc 30 | alpha, beta, gamma = p.structure.lattice.angles 31 | 32 | # lecture du fichier OSZICAR 33 | o = Oszicar(osz) 34 | elast = o.final_energy 35 | singlePoint = o.ionic_steps[0]["E0"] 36 | 37 | # affiche les resultats 38 | print("%4d %7.3f %7.3f %7.3f %6.1f %6.1f %6.1f %12.7f %12.7f %12.3f" % 39 | (i, a, b, c, alpha, beta, gamma, elast, singlePoint, 40 | (singlePoint - save) * 1000.)) 41 | 42 | # save energy to compute convergence 43 | save = singlePoint 44 | -------------------------------------------------------------------------------- /VASP/ana_kpoints_kspacing.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os 4 | 5 | # use pymatgen objects 6 | from pymatgen.io.vasp.inputs import Poscar 7 | from pymatgen.io.vasp.outputs import Oszicar 8 | 9 | # header 10 | print("# kspacing grid a b c alpha beta gamma" 11 | " Econv SinglePts DE") 12 | 13 | 14 | # OSZICAR files 15 | oszicar = [f for f in os.listdir("./") if "OSZICAR_" in f] 16 | oszicar.sort(key=lambda x: int(x.strip("OSZICAR_"))) 17 | 18 | # CONTCAR files 19 | contcar = [f for f in os.listdir("./") if "CONTCAR_" in f] 20 | contcar.sort(key=lambda x: int(x.strip("CONTCAR_"))) 21 | 22 | # OUTCAR files 23 | outcar = [f for f in os.listdir("./") if "OUTCAR_" in f] 24 | outcar.sort(key=lambda x: int(x.strip("OUTCAR_"))) 25 | 26 | kspacing = [float(val) for val in "1.4 0.9 0.8 0.6 0.45 0.4 0.35 0.3 0.275 0.25 0.225 0.2 0.19 0.17".split()] 27 | 28 | save = 0.0 29 | 30 | # boucle sur les points k 31 | for cont, osz, out, ksp in zip(contcar, oszicar, outcar, kspacing): 32 | i = int(cont.strip("CONTCAR_")) 33 | 34 | # chargement de la structure 35 | p = Poscar.from_file(cont) 36 | a, b, c = p.structure.lattice.abc 37 | alpha, beta, gamma = p.structure.lattice.angles 38 | 39 | # lecture du fichier OSZICAR 40 | o = Oszicar(osz) 41 | elast = o.final_energy 42 | singlePoint = o.ionic_steps[0]["E0"] 43 | 44 | # lecture de l'OUTCAR 45 | with open(out, "r") as f: 46 | for line in f: 47 | if "generate k-points for:" in line: 48 | kx, ky, kz = [int(k) for k in line.split()[-3:]] 49 | break 50 | 51 | # affiche les resultats 52 | print("%10.2f %2d %2d %2d %7.3f %7.3f %7.3f %6.1f %6.1f %6.1f %12.7f %12.7f %12.3f" % 53 | (ksp, kx, ky, kz, a, b, c, alpha, beta, gamma, elast, singlePoint, 54 | (singlePoint - save) * 1000.)) 55 | 56 | # save energy to compute convergence 57 | save = singlePoint 58 | -------------------------------------------------------------------------------- /VASP/bands_Cu.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | import sys 5 | import numpy as np 6 | 7 | import matplotlib.pyplot as plt 8 | from matplotlib.collections import LineCollection 9 | from matplotlib.gridspec import GridSpec 10 | 11 | import pymatgen as mg 12 | from pymatgen.symmetry.bandstructure import HighSymmKpath 13 | from pymatgen.io.vaspio.vasp_output import Vasprun 14 | from pymatgen.electronic_structure.core import Spin 15 | 16 | def rgbline(ax, k, e, red, green, blue, alpha=1.): 17 | #creation of segments based on 18 | #http://nbviewer.ipython.org/urls/raw.github.com/dpsanders/matplotlib-examples/master/colorline.ipynb 19 | pts = np.array([k, e]).T.reshape(-1, 1, 2) 20 | seg = np.concatenate([pts[:-1], pts[1:]], axis=1) 21 | 22 | nseg = len(k)-1 23 | r = [0.5*(red[i]+red[i+1]) for i in range(nseg)] 24 | g = [0.5*(green[i]+green[i+1]) for i in range(nseg)] 25 | b = [0.5*(blue[i]+blue[i+1]) for i in range(nseg)] 26 | a = np.ones(nseg, np.float)*alpha 27 | lc = LineCollection(seg, colors=zip(r,g,b,a), linewidth = 2) 28 | ax.add_collection(lc) 29 | 30 | if __name__ == "__main__": 31 | # read data 32 | # --------- 33 | 34 | # kpoints labels 35 | path = HighSymmKpath(mg.read_structure("./POSCAR")).kpath["path"] 36 | labels = list() 37 | for p in path: 38 | if len(labels) != 0: 39 | labels[-1] = r"$%s,%s$" % (labels[-1].strip("$"), p[0]) 40 | else: 41 | labels.append(r"$%s$" % p[0]) 42 | for kp in p[1:]: 43 | labels.append(r"$%s$" % kp) 44 | 45 | # density of state 46 | dosrun = Vasprun("../../DOS/Cu/vasprun.xml") 47 | spd_dos = dosrun.complete_dos.get_spd_dos() 48 | 49 | # bands 50 | run = Vasprun("vasprun.xml", parse_projected_eigen = True) 51 | bands = run.get_band_structure("KPOINTS", 52 | line_mode = True, 53 | efermi = dosrun.efermi) 54 | 55 | # set up matplotlib plot 56 | # ---------------------- 57 | 58 | # general options for plot 59 | font = {'family': 'serif', 'size': 24} 60 | plt.rc('font', **font) 61 | 62 | # set up 2 graph with aspec ration 2/1 63 | # plot 1: bands diagram 64 | # plot 2: Density of State 65 | gs = GridSpec(1, 2, width_ratios=[2,1]) 66 | fig = plt.figure(figsize=(11.69, 8.27)) 67 | fig.suptitle("Bands diagram of copper") 68 | ax1 = plt.subplot(gs[0]) 69 | ax2 = plt.subplot(gs[1]) # , sharey=ax1) 70 | 71 | # set ylim for the plot 72 | # --------------------- 73 | emin = -10. 74 | emax = 10. 75 | ax1.set_ylim(emin, emax) 76 | ax2.set_ylim(emin, emax) 77 | 78 | # Band Diagram 79 | # ------------ 80 | name = "Cu" 81 | pbands = bands.get_projections_on_elts_and_orbitals({name: ["s", "p", "d"]}) 82 | 83 | # compute s, p, d normalized contributions 84 | contrib = np.zeros((bands.nb_bands, len(bands.kpoints), 3)) 85 | for b in range(bands.nb_bands): 86 | for k in range(len(bands.kpoints)): 87 | sc = pbands[Spin.up][b][k][name]["s"]**2 88 | pc = pbands[Spin.up][b][k][name]["p"]**2 89 | dc = pbands[Spin.up][b][k][name]["d"]**2 90 | tot = sc + pc + dc 91 | if tot != 0.0: 92 | contrib[b, k, 0] = sc / tot 93 | contrib[b, k, 1] = pc / tot 94 | contrib[b, k, 2] = dc / tot 95 | 96 | # plot bands using rgb mapping 97 | for b in range(bands.nb_bands): 98 | rgbline(ax1, 99 | range(len(bands.kpoints)), 100 | [e - bands.efermi for e in bands.bands[Spin.up][b]], 101 | contrib[b,:,0], 102 | contrib[b,:,1], 103 | contrib[b,:,2]) 104 | 105 | # style 106 | ax1.set_xlabel("k-points") 107 | ax1.set_ylabel(r"$E - E_f$ / eV") 108 | ax1.grid() 109 | 110 | # fermi level at 0 111 | ax1.hlines(y=0, xmin=0, xmax=len(bands.kpoints), color="k", lw=2) 112 | 113 | # labels 114 | nlabs = len(labels) 115 | step = len(bands.kpoints) / (nlabs - 1) 116 | for i, lab in enumerate(labels): 117 | ax1.vlines(i * step, emin, emax, "k") 118 | ax1.set_xticks([i * step for i in range(nlabs)]) 119 | ax1.set_xticklabels(labels) 120 | 121 | ax1.set_xlim(0, len(bands.kpoints)) 122 | 123 | # Density of state 124 | # ---------------- 125 | 126 | ax2.set_yticklabels([]) 127 | ax2.grid() 128 | ax2.set_xlim(1e-6, 32) 129 | ax2.hlines(y=0, xmin=0, xmax=32, color="k", lw=2) 130 | ax2.set_xlabel("Density of State") 131 | 132 | # spd contribution 133 | ax2.plot(spd_dos["S"].densities[Spin.up], 134 | dosrun.tdos.energies - dosrun.efermi, 135 | "r-", label = "3s", lw = 2) 136 | ax2.plot(spd_dos["P"].densities[Spin.up], 137 | dosrun.tdos.energies - dosrun.efermi, 138 | "g-", label = "3p", lw = 2) 139 | ax2.plot(spd_dos["D"].densities[Spin.up], 140 | dosrun.tdos.energies - dosrun.efermi, 141 | "b-", label = "3d", lw = 2) 142 | 143 | # total dos 144 | ax2.fill_between(dosrun.tdos.densities[Spin.up], 145 | 0, 146 | dosrun.tdos.energies - dosrun.efermi, 147 | color = (0.7, 0.7, 0.7), 148 | facecolor = (0.7, 0.7, 0.7)) 149 | 150 | ax2.plot(dosrun.tdos.densities[Spin.up], 151 | dosrun.tdos.energies - dosrun.efermi, 152 | color = (0.6, 0.6, 0.6), 153 | label = "total DOS") 154 | 155 | # plot format style 156 | # ----------------- 157 | ax2.legend(fancybox=True, shadow=True, prop={'size':18}) 158 | plt.subplots_adjust(wspace = 0) 159 | 160 | #plt.show() 161 | plt.savefig(sys.argv[0].strip(".py") + ".pdf", format="pdf") 162 | 163 | -------------------------------------------------------------------------------- /VASP/chgmag.f90: -------------------------------------------------------------------------------- 1 | program chgmag 2 | ! Read a CHGCAR file and extract the up - down density 3 | ! 4 | ! args: 5 | ! CHGCAR file name 6 | ! 7 | ! Output is written into the CHGCAR_mag 8 | ! 9 | 10 | implicit none 11 | 12 | ! arguments: 13 | character(len=100) :: chgcar 14 | 15 | ! local: 16 | integer :: i, j, k, nline, nval, io 17 | integer :: ngxf1, ngyf1, ngzf1 18 | integer :: ngxf2, ngyf2, ngzf2 19 | character(len=100) :: line, bid 20 | character(len=100), dimension(:), allocatable :: header 21 | real(kind=8) :: occ 22 | real(kind=8), dimension(:,:,:), allocatable :: rho 23 | 24 | ! get arguments 25 | call get_command_argument(1, chgcar) 26 | 27 | ! read file 28 | ! --------- 29 | write(*, "('Reading file : ', a)") trim(chgcar) 30 | open(unit=10, file=chgcar, action="read") 31 | nline = 1 32 | read(10, "(a)") line 33 | do while (.not. line == "") 34 | read(10, "(a)") line 35 | nline = nline + 1 36 | end do 37 | !write(*,*) nline 38 | 39 | read(10, *) ngxf1, ngyf1, ngzf1 40 | !write(*,"(3i6)") ngxf1, ngyf1, ngzf1 41 | allocate(rho(ngxf1, ngyf1, ngzf1)) 42 | allocate(header(nline)) 43 | 44 | ! read up+down density 45 | rewind(10) 46 | do i = 1, nline 47 | read(10, "(a)") header(i) 48 | end do 49 | read(10, *) 50 | read(10, *) (((rho(i, j, k), i = 1, ngxf1), j = 1, ngyf1), k = 1, ngzf1) 51 | 52 | ! skip augementation occupancies part 53 | io = 1 54 | do while (io /= 0) 55 | read(10, "(3i5)", iostat=io) ngxf2, ngyf2, ngzf2 56 | end do 57 | 58 | ! do while (index(line, "occupancies") /= 0) 59 | ! read(line, *) bid, bid, bid, nval 60 | ! read(10, *) (occ, i = 1, nval) 61 | ! read(10, "(a)") line 62 | ! end do 63 | 64 | ! write(*,*) line 65 | ! read(10, *) ngxf2, ngyf2, ngzf2 66 | 67 | ! check array size 68 | if( ngxf1 /= ngxf2 .or. ngyf1 /= ngyf2 .or. ngzf1 /= ngzf2) then 69 | write(* ,"('1: NGXF = ', i5, ', NGYF = ',i5,', NGZF = ',i5)") ngxf1, ngyf1, ngzf1 70 | write(* ,"('2: NGXF = ', i5, ', NGYF = ',i5,', NGZF = ',i5)") ngxf2, ngyf2, ngzf2 71 | stop "unconsistant grid" 72 | end if 73 | 74 | ! read up-down density 75 | read(10, *) (((rho(i, j, k), i = 1, ngxf1), j = 1, ngyf1), k = 1, ngzf1) 76 | close(10) 77 | 78 | 79 | ! write up - down density 80 | write(*, "('Writting file : ', a)") "CHGCAR_mag.vasp" 81 | open(unit=10, file="CHGCAR_mag.vasp", action="write") 82 | do i = 1, nline 83 | write(10, "(a)") trim(header(i)) 84 | end do 85 | write(10, "(3i6)") ngxf1, ngyf1, ngzf1 86 | write(10, "(5E19.11)") (((rho(i, j, k), i = 1, ngxf1), j = 1, ngyf1), k = 1, ngzf1) 87 | close(10) 88 | 89 | deallocate(rho) 90 | 91 | end program chgmag 92 | -------------------------------------------------------------------------------- /VASP/chgsplit.f90: -------------------------------------------------------------------------------- 1 | program chgsplit 2 | ! Read a CHGCAR file and split up and down density 3 | ! 4 | ! args: 5 | ! CHGCAR file name 6 | ! 7 | ! Output is written into the files CHGCAR_up and CHGCAR_down 8 | ! 9 | 10 | implicit none 11 | 12 | ! arguments: 13 | character(len=100) :: chgcar 14 | 15 | ! local: 16 | integer :: i, j, k, nline, nval, io 17 | integer :: ngxf1, ngyf1, ngzf1 18 | integer :: ngxf2, ngyf2, ngzf2 19 | character(len=100) :: line, bid 20 | character(len=100), dimension(:), allocatable :: header 21 | real(kind=8) :: occ 22 | real(kind=8), dimension(:,:,:), allocatable :: rho1, rho2 23 | real(kind=8), dimension(:,:,:), allocatable :: rhoup, rhodown 24 | 25 | ! get arguments 26 | call get_command_argument(1, chgcar) 27 | 28 | ! read file 29 | ! --------- 30 | write(*, "('Reading file : ', a)") trim(chgcar) 31 | open(unit=10, file=chgcar, action="read") 32 | nline = 1 33 | read(10, "(a)") line 34 | do while (.not. line == "") 35 | read(10, "(a)") line 36 | nline = nline + 1 37 | end do 38 | !write(*,*) nline 39 | 40 | read(10, *) ngxf1, ngyf1, ngzf1 41 | !write(*,"(3i6)") ngxf1, ngyf1, ngzf1 42 | allocate(rho1(ngxf1, ngyf1, ngzf1)) 43 | allocate(header(nline)) 44 | 45 | ! read up+down density 46 | rewind(10) 47 | do i = 1, nline 48 | read(10, "(a)") header(i) 49 | end do 50 | read(10, *) 51 | read(10, *) (((rho1(i, j, k), i = 1, ngxf1), j = 1, ngyf1), k = 1, ngzf1) 52 | 53 | ! skip augementation occupancies part 54 | io = 1 55 | do while (io /= 0) 56 | read(10, "(3i5)", iostat=io) ngxf2, ngyf2, ngzf2 57 | end do 58 | 59 | ! do while (index(line, "occupancies") /= 0) 60 | ! read(line, *) bid, bid, bid, nval 61 | ! read(10, *) (occ, i = 1, nval) 62 | ! read(10, "(a)") line 63 | ! end do 64 | 65 | ! write(*,*) line 66 | ! read(10, *) ngxf2, ngyf2, ngzf2 67 | 68 | ! check array size 69 | if( ngxf1 /= ngxf2 .or. ngyf1 /= ngyf2 .or. ngzf1 /= ngzf2) then 70 | write(* ,"('1: NGXF = ', i5, ', NGYF = ',i5,', NGZF = ',i5)") ngxf1, ngyf1, ngzf1 71 | write(* ,"('2: NGXF = ', i5, ', NGYF = ',i5,', NGZF = ',i5)") ngxf2, ngyf2, ngzf2 72 | stop "unconsistant grid" 73 | end if 74 | 75 | ! read up-down density 76 | allocate(rho2(ngxf2, ngyf2, ngzf2)) 77 | read(10, *) (((rho2(i, j, k), i = 1, ngxf1), j = 1, ngyf1), k = 1, ngzf1) 78 | close(10) 79 | 80 | ! compute up and down densities 81 | allocate(rhoup(ngxf1, ngyf1, ngzf1),rhodown(ngxf1, ngyf1, ngzf1)) 82 | rhoup(:,:,:) = 0.5 * (rho1(:,:,:) + rho2(:,:,:)) 83 | rhodown(:,:,:) = 0.5 * (rho1(:,:,:) - rho2(:,:,:)) 84 | 85 | deallocate(rho1, rho2) 86 | 87 | ! write up density 88 | write(*, "('Writting file : ', a)") "CHGCAR_up.vasp" 89 | open(unit=10, file="CHGCAR_up.vasp", action="write") 90 | do i = 1, nline 91 | write(10, "(a)") trim(header(i)) 92 | end do 93 | write(10, "(3i6)") ngxf1, ngyf1, ngzf1 94 | write(10, "(5E19.11)") (((rhoup(i, j, k), i = 1, ngxf1), j = 1, ngyf1), & 95 | k = 1, ngzf1) 96 | close(10) 97 | 98 | ! write down density 99 | write(*, "('Writting file : ', a)") "CHGCAR_down.vasp" 100 | open(unit=10, file="CHGCAR_down.vasp", action="write") 101 | do i = 1, nline 102 | write(10, "(a)") trim(header(i)) 103 | end do 104 | write(10, "(3i6)") ngxf1, ngyf1, ngzf1 105 | write(10, "(5E19.11)") (((rhodown(i, j, k), i = 1, ngxf1), j = 1, ngyf1), & 106 | k = 1, ngzf1) 107 | close(10) 108 | 109 | end program chgsplit 110 | -------------------------------------------------------------------------------- /VASP/chgsum.f90: -------------------------------------------------------------------------------- 1 | program chgsum 2 | ! Read two CHGCAR file and compute a linear combination. Three arguments 3 | ! are mandatory: 4 | ! * args 1: CHGCAR file 1 5 | ! * args 2: CHGCAR file 2 6 | ! * args 3: scale_factor 7 | ! 8 | ! Linear combination: 9 | ! CHGCAR1 + scale_factor * CHGCAR2 10 | ! 11 | ! Output is written into the file CHGCAR_sum 12 | ! 13 | 14 | implicit none 15 | 16 | ! arguments: 17 | character(len=100) :: chgcar1, chgcar2, fact 18 | 19 | ! local: 20 | integer :: i, j, k, nline 21 | integer :: ngxf1, ngyf1, ngzf1 22 | integer :: ngxf2, ngyf2, ngzf2 23 | character(len=100) :: line 24 | character(len=100), dimension(:), allocatable :: header 25 | real(kind=8) :: scale_factor 26 | real(kind=8), dimension(:,:,:), allocatable :: rho1, rho2 27 | 28 | ! get arguments 29 | if( command_argument_count() /= 3 ) then 30 | write(*, *) "Syntax : CHGCAR1 CHGCAR2 scale_factor" 31 | stop "STOP : bad numbers of arguments" 32 | end if 33 | 34 | call get_command_argument(1, chgcar1) 35 | call get_command_argument(2, chgcar2) 36 | call get_command_argument(3, fact) 37 | read(fact, *) scale_factor 38 | 39 | !write(*,*) trim(chgcar1) 40 | !write(*,*) trim(chgcar2) 41 | !write(*,*) scale_factor 42 | 43 | ! read file 1 44 | write(*, "('Reading file 1 : ', a)") trim(chgcar1) 45 | open(unit=10, file=chgcar1, action="read") 46 | nline = 1 47 | read(10, "(a)") line 48 | do while (.not. line == "") 49 | read(10, "(a)") line 50 | nline = nline + 1 51 | end do 52 | !write(*,*) nline 53 | 54 | read(10, *) ngxf1, ngyf1, ngzf1 55 | !write(*,"(3i6)") ngxf1, ngyf1, ngzf1 56 | allocate(rho1(ngxf1, ngyf1, ngzf1)) 57 | allocate(header(nline)) 58 | read(10, *) (((rho1(i, j, k), i = 1, ngxf1), j = 1, ngyf1), k = 1, ngzf1) 59 | close(10) 60 | 61 | ! read file 2 62 | write(*, "('Reading file 2 : ', a)") trim(chgcar2) 63 | open(unit=10, file=chgcar2, action="read") 64 | do i = 1, nline 65 | read(10, "(a)") header(i) 66 | end do 67 | read(10, *) ngxf2, ngyf2, ngzf2 68 | !write(*,"(3i6)") ngxf2, ngyf2, ngzf2 69 | if( ngxf1 /= ngxf2 .or. ngyf1 /= ngyf2 .or. ngzf1 /= ngzf2) then 70 | stop "unconsistant grid" 71 | end if 72 | allocate(rho2(ngxf2, ngyf2, ngzf2)) 73 | read(10, *) (((rho2(i, j, k), i = 1, ngxf2), j = 1, ngyf2), k = 1, ngzf2) 74 | close(10) 75 | 76 | ! do the sum 77 | write(*, "('Compute ', a, ' + ', F5.2, a)") trim(chgcar1), scale_factor, & 78 | " " // trim(chgcar2) 79 | rho1(:,:,:) = rho1(:,:,:) + scale_factor * rho2(:,:,:) 80 | 81 | ! write sum file 82 | write(*, "('Writting file : ', a)") "CHGCAR_sum" 83 | open(unit=10, file="CHGCAR_sum", action="write") 84 | do i = 1, nline 85 | write(10, "(a)") trim(header(i)) 86 | end do 87 | write(10, "(3i6)") ngxf1, ngyf1, ngzf1 88 | write(10, "(5E19.11)") (((rho1(i, j, k), i = 1, ngxf1), j = 1, ngyf1), & 89 | k = 1, ngzf1) 90 | close(10) 91 | 92 | end program chgsum 93 | -------------------------------------------------------------------------------- /VASP/distorsion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | from __future__ import print_function, division 5 | 6 | """ 7 | doc 8 | """ 9 | __author__ = "Germain Vallverdu " 10 | __licence__ = "GPL" 11 | __date__ = "Février 2015" 12 | 13 | import numpy as np 14 | import matplotlib.pyplot as plt 15 | import pymatgen as mg 16 | 17 | #----------------------------------------------------------------------------- 18 | # ideal molecule constructor 19 | #----------------------------------------------------------------------------- 20 | def mol_Oh(central, ligand, scale): 21 | """ 22 | Return a perfect octahedra as a mg.Molecule object. 23 | 24 | Args: 25 | central: (string) Name of the central atom 26 | ligand: (string) Name of ligand atoms 27 | scale: (float) length of central-ligand distance 28 | 29 | Returns 30 | mg.Molecule object 31 | """ 32 | species = [mg.Element(central)] + 6 * [mg.Element(ligand)] 33 | template = [[ 0., 0., 0.], 34 | [ 1., 0., 0.], 35 | [-1., 0., 0.], 36 | [ 0., 1., 0.], 37 | [ 0.,-1., 0.], 38 | [ 0., 0., 1.], 39 | [ 0., 0.,-1.]] 40 | coords = [[scale * xi for xi in coord] for coord in template] 41 | return mg.Molecule(species, coords) 42 | 43 | def mol_D4h(central, ligand, d1, d2): 44 | """ 45 | Return a D4h molecule as a mg.Molecule object. 46 | 47 | Args: 48 | central: (string) Name of the central atom 49 | ligand: (string) Name of ligand atoms 50 | d1: (float) length of central-ligand axial distance 51 | d2: (float) length of central-ligand equatorial distance 52 | 53 | Returns 54 | mg.Molecule object 55 | """ 56 | species = [mg.Element(central)] + 6 * [mg.Element(ligand)] 57 | template = [[ 0., 0., 0.], 58 | [ 1., 0., 0.], 59 | [-1., 0., 0.], 60 | [ 0., 1., 0.], 61 | [ 0.,-1., 0.], 62 | [ 0., 0., 1.], 63 | [ 0., 0.,-1.]] 64 | coords = [template[0]] \ 65 | + [[d1 * xi for xi in coord] for coord in template[1:5]] \ 66 | + [[d2 * xi for xi in coord] for coord in template[5:]] 67 | return mg.Molecule(species, coords) 68 | 69 | #----------------------------------------------------------------------------- 70 | # Distortion measurment 71 | #----------------------------------------------------------------------------- 72 | def centralDist(envs, ideal, dmin=1., dmax=3.5, step=0.05): 73 | """ 74 | Plot an histogram of central to ligand distances between dmin and dmax with 75 | a bin size step. 76 | 77 | Args: 78 | envs: list of mg.Molecule object. The first atom is the central atom 79 | the following atoms are the ligand. 80 | dmin (float): lower bound of the histogram 81 | dmax (float): upper bound of the histogram 82 | step (float): bin size 83 | 84 | """ 85 | # compute all central - ligand distances 86 | data = list() 87 | for mol in envs: 88 | data += sorted([di for n, di in mol.get_neighbors(mol[0], 10.)]) 89 | 90 | # print data 91 | nligand = len(envs[0][1:]) 92 | nsite = len(envs) 93 | np.savetxt("all_env.dat", 94 | np.array(data).reshape(nsite, nligand).transpose(), 95 | fmt="%10.4f", 96 | header="Each column contains the sorted central-ligand" \ 97 | + " distances of one site") 98 | 99 | # plot data 100 | font = {'family': 'serif', 'size': 20} 101 | plt.rc('font', **font) 102 | plt.figure(figsize=(11.69, 8.27)) # A4 103 | 104 | mybins = np.arange(dmin, dmax, step) 105 | hval, bins, p = plt.hist(data, mybins, normed=False) 106 | hval /= nsite 107 | 108 | ideal_d = [di for n, di in ideal.get_neighbors(ideal[0], 10.)] 109 | hid, b, p = plt.hist(ideal_d, mybins, normed=False) 110 | 111 | plt.clf() 112 | 113 | plt.bar(bins[:-1], hval, width=step, color="blue", label="structure") 114 | plt.bar(bins[:-1], hid, width=step, color="green", label="reference") 115 | plt.xlabel("distances (A)") 116 | plt.ylabel("Histogram") 117 | plt.legend() 118 | plt.grid() 119 | plt.xlim(dmin, dmax) 120 | plt.show() 121 | 122 | def paramVector(mol, radius = 10.): 123 | """ 124 | Build the vector representing the site in the parameters' space. 125 | 126 | Args: 127 | * mol : mg.Molecule object of the central atom plus the ligand atoms. 128 | : The first atom must be the central atom 129 | * radius : cut off distance for neighbors of the central atoms 130 | 131 | Returns: 132 | * a numpy array. The n first distances are the central to all ligand 133 | distances sorted from the smallest to the largest. The m following 134 | distances are all ligand - ligand distances sorted from the smallest to 135 | the largest. 136 | """ 137 | # distances central atom to ligand 138 | d_central = [di for n, di in mol.get_neighbors(mol[0], radius)] 139 | # all distances 140 | dm = mol.distance_matrix 141 | d_all = [di for line in np.triu(dm) for di in line if di > 0.] 142 | return np.array(sorted(d_central) + sorted(d_all)) 143 | 144 | def readStructures(sfile, central, ligand, radius=3.): 145 | """ 146 | Read structure from file sfile and look for environments of all central 147 | atoms in the structure. Only neighbors of type ligand are taken into 148 | account. 149 | 150 | Returns a list of mg.Molecule in which the first atom is the central atom 151 | and the following atoms are the neighbors of type ligand of this central 152 | atom. 153 | """ 154 | 155 | struct = mg.Structure.from_file(sfile) 156 | central_sites = [site for site in struct 157 | if site.specie == mg.Element(central)] 158 | 159 | envs = list() 160 | 161 | print("Identified sites:") 162 | for site in central_sites: 163 | 164 | mol = mg.Molecule([site.specie], [site.coords]) 165 | 166 | neighbors = struct.get_neighbors(site, radius) 167 | 168 | for neighbor, d in neighbors: 169 | if neighbor.specie == mg.Element(ligand): 170 | mol.append(neighbor.specie, neighbor.coords) 171 | 172 | envs.append(mol) 173 | print("%2s[%2d] : #ligand = %d (%s)" % 174 | (site.specie, 175 | struct.index(site), 176 | len(mol[1:]), 177 | " ".join([at.specie.symbol for at in mol[1:]]))) 178 | 179 | return envs 180 | 181 | def norm(vec, origin): 182 | """ 183 | return the norm considering the vector vec in the parameters' space and 184 | the ideal vector origin in the same parameters' space. 185 | """ 186 | return np.sqrt(((vec - origin)**2).sum()/(origin**2).sum()) 187 | 188 | if __name__ == "__main__": 189 | 190 | # ideal 191 | #envfile = "ideal.xyz" 192 | #ideal_mol = mg.Molecule.from_file(envfile) 193 | #ideal_mol = mol_Oh("Mn", "O", 2.) 194 | ideal_mol = mol_D4h("Mn", "O", 1.9, 2.2) 195 | ideal_mol.to("xyz", "d4h.xyz") 196 | idealVec = paramVector(ideal_mol) 197 | 198 | # analysed structure 199 | radius = 2.5 200 | sfile = "POSCAR" 201 | envs = readStructures(sfile, "Mn", "O", radius) 202 | 203 | for mol in envs: 204 | vec = paramVector(mol) 205 | print(norm(vec, idealVec)) 206 | 207 | centralDist(envs, ideal_mol) 208 | 209 | -------------------------------------------------------------------------------- /VASP/encut.job: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #SBATCH --account=uppa 4 | #SBATCH --partition=compute 5 | 6 | ##SBATCH --mail-type=END 7 | ##SBATCH --mail-user=germain.vallverdu@univ-pau.fr 8 | 9 | #SBATCH --time=0-02:00:00 10 | 11 | #SBATCH --ntasks=4 12 | #SBATCH --cpus-per-task=1 13 | 14 | # dossier de travail (securite) 15 | source /etc/profile.d/modules.sh 16 | module purge 17 | module load vasp/5.4.4 18 | module list 19 | 20 | # le chemin vers vasp est defini dans le module 21 | echo "vasp : `which vasp`" 22 | echo "------------------------------------------------------------" 23 | echo "SLURM_JOB_NAME =" $SLURM_JOB_NAME 24 | echo "SLURM_JOBID =" $SLURM_JOBID 25 | echo "SLURM_NODELIST = "$SLURM_NODELIST 26 | echo "" 27 | echo "SLURM_NNODES =" $SLURM_NNODES 28 | echo "SLURM_NTASKS =" $SLURM_NTASKS 29 | echo "SLURM_TASKS_PER_NODE =" $SLURM_TASKS_PER_NODE 30 | echo "SLURM_CPUS_PER_TASK =" $SLURM_CPUS_PER_TASK 31 | echo "SLURM_NPROCS =" $SLURM_NPROCS 32 | echo "------------------------------------------------------------" 33 | 34 | # script pour l'optimisation du cut-off 35 | # 36 | # Fichier INCAR 37 | # ------------- 38 | # 39 | # Céer un fichier nommé INCAR_origine avec au moins les mots clefs suivants 40 | # 41 | # ISTART = 0 42 | # LWAVE = False 43 | # LCHARG = False 44 | # ISMEAR = 0; SIGMA = 0.05 (semi-cond, isolants) 45 | # ISMEAR = 1; SIGMA = 0.2 (metaux) 46 | # 47 | # Fichier KPOINTS 48 | # --------------- 49 | # 50 | # On calcule l'énergie uniquement au point Gamma 51 | # 52 | # Les resultats sont donnees à la fin des calculs 53 | # 54 | # ------------------------------------------------------------------------------ 55 | 56 | # KPOINTS 57 | echo "kpts grille : 1 point" > KPOINTS 58 | echo "0" >> KPOINTS 59 | echo "Gamma" >> KPOINTS 60 | echo " 1 1 1 " >> KPOINTS 61 | echo " 0 0 0" >> KPOINTS 62 | 63 | # INCAR 64 | echo "PREC = Accurate" > INCAR 65 | echo "EDIFF = 1e-6" >> INCAR 66 | echo "ENCUT = 200" >> INCAR 67 | echo "ISTART = 0" >> INCAR 68 | echo "LWAVE = False" >> INCAR 69 | echo "LCHARG = False" >> INCAR 70 | echo "NSW = 0" >> INCAR 71 | echo "ISMEAR = 0" >> INCAR 72 | echo "SIGMA = 0.05" >> INCAR 73 | 74 | cp -v INCAR INCAR_origine 75 | 76 | # declaration des variables 77 | declare -a encut energie 78 | declare -i i e 79 | 80 | # choix des valeurs de ENCUT 81 | e=250 82 | i=0 83 | while (( e < 900 )) 84 | do 85 | (( e += 50 )) 86 | (( i++ )) 87 | encut[$i]=$e 88 | done 89 | 90 | # calculs 91 | npts=${#encut[*]} 92 | # boucle sur les valeurs de encut 93 | for i in $(seq 1 $npts) 94 | do 95 | # substitution du ENCUT dans le fichier INCAR 96 | sed "s/ENCUT =.*/ENCUT = ${encut[$i]}/" < INCAR_origine > INCAR 97 | 98 | # affiche la ligne du ENCUT dans le INCAR 99 | echo " ======================================== " 100 | echo " ENCUT = ${encut[$i]}" 101 | echo " ======================================== " 102 | echo " check input : " 103 | grep ENCUT INCAR 104 | echo "" 105 | 106 | # execution de VASP 107 | time $MPI_RUN vasp 108 | 109 | # lecture de l'energie 110 | set `tail -n1 OSZICAR` 111 | energie[$i]=$5 112 | 113 | # sauvegarde de fichier 114 | echo "" 115 | echo "recopie des resutlats" 116 | cp -v OSZICAR OSZICAR_${encut[$i]} 117 | cp -v OUTCAR OUTCAR_${encut[$i]} 118 | 119 | done 120 | 121 | # impression des resultats 122 | echo "" 123 | echo " ======================================== " 124 | echo " Nombre de valeurs : " $npts 125 | echo " ======================================== " 126 | echo "# encut (ev) Energy (eV)" > encut.dat 127 | for i in $(seq 1 $npts) 128 | do 129 | echo ${encut[$i]} ${energie[$i]} 130 | echo ${encut[$i]} ${energie[$i]} >> encut.dat 131 | done 132 | 133 | -------------------------------------------------------------------------------- /VASP/getCharges: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | getCharges 6 | ---------- 7 | 8 | NAME 9 | getCharges - compute atomic charges from a bader calculation 10 | 11 | SYNTAX 12 | getCharges [OPTIONS] 13 | 14 | DESCRIPTION 15 | Compute atomic charges from a Bader caclculations done with the bader program of 16 | the University of Texas at Austin : 17 | 18 | http://theory.cm.utexas.edu/bader/ 19 | 20 | Requirements : 21 | * a ACF.dat file (bader output) 22 | * a POSCAR/CONTCAR file of the structure (read atom names). 23 | * a POTCAR file (read valence electron) 24 | 25 | options : 26 | -h, --help 27 | print this help and exit 28 | """ 29 | 30 | import sys 31 | import os 32 | from math import sqrt, fabs 33 | 34 | import pymatgen as mg 35 | from pymatgen.io.vasp.inputs import Potcar 36 | from pymatgen.core import Structure 37 | 38 | __author__ = "Germain Vallverdu " 39 | __licence__ = "GPL" 40 | 41 | def getCharges(): 42 | """ compute charges """ 43 | 44 | # 45 | # print documentation 46 | # 47 | args = sys.argv 48 | if "-h" in args or "--help" in args: 49 | print(__doc__) 50 | exit(0) 51 | 52 | # 53 | # read atom names 54 | # 55 | if os.path.exists("POSCAR"): 56 | struct = Structure.from_file("POSCAR") 57 | atomNames = [el.symbol for el in struct.species] 58 | 59 | elif os.path.exists("CONTCAR"): 60 | struct = Structure.from_file("CONTCAR") 61 | atomNames = [el.symbol for el in struct.species] 62 | 63 | else: 64 | print("ERROR : need a POSCAR/CONTCAR file\n") 65 | print(__doc__) 66 | exit(1) 67 | 68 | nat = len(atomNames) 69 | 70 | #  71 | # read potcar 72 | # 73 | if os.path.exists("POTCAR"): 74 | potcar = Potcar.from_file("POTCAR") 75 | else: 76 | print("ERROR : need a POTCAR file\n") 77 | print(__doc__) 78 | exit(1) 79 | 80 | # 81 | # System composition and valence electron 82 | # 83 | valence = dict() 84 | for singlePotcar in potcar: 85 | print("%3s POTCAR : %10s zval : %f" % \ 86 | (singlePotcar.element, singlePotcar.symbol, singlePotcar.zval)) 87 | valence[singlePotcar.element] = singlePotcar.zval 88 | 89 | # 90 | # read population from ACF.dat file 91 | # 92 | acf = open("ACF.dat", "r").read().split(80 * "-")[1].split("\n")[1:-1] 93 | population = [float(line.split()[4]) for line in acf] 94 | if len(population) != nat: 95 | print("Error, number of atom in ACF.dat not consistent") 96 | 97 | # 98 | # output 99 | # 100 | print("\n i name Z pop charge") 101 | print("------------------------------------") 102 | for iat in range(nat): 103 | charge = valence[atomNames[iat]] - population[iat] 104 | print("%4d %4s %4d %10.4f %10.4f" % (iat + 1, atomNames[iat], \ 105 | valence[atomNames[iat]], population[iat], charge)) 106 | print("------------------------------------\n") 107 | 108 | # 109 | # average charges 110 | # 111 | avePop = dict() 112 | av2Charge = dict() 113 | for el in struct.composition.elements: 114 | avePop[el.symbol] = 0. 115 | av2Charge[el.symbol] = 0. 116 | 117 | print("Composition : {0}\n".format(struct.formula)) 118 | 119 | for iat in range(nat): 120 | name = atomNames[iat] 121 | avePop[name] += population[iat] 122 | av2Charge[name] += (valence[name] - population[iat])**2 123 | 124 | print("Averages :") 125 | print(" name Z charge") 126 | print("------------------------------------") 127 | for el in struct.composition.elements: 128 | nel = struct.composition[el.symbol] 129 | name = el.symbol 130 | avePop[name] /= nel 131 | charge = valence[name] - avePop[name] 132 | 133 | av2Charge[name] /= nel 134 | if fabs(av2Charge[name] - charge**2) < 1e-5: 135 | av2Charge[name] = 0. 136 | else: 137 | av2Charge[name] = sqrt(av2Charge[name] - charge**2) 138 | 139 | print("%4s %4d %10.4f +/- %7.4f" % (name, valence[name], charge, \ 140 | av2Charge[name])) 141 | print("------------------------------------\n") 142 | 143 | if __name__ == "__main__": 144 | getCharges() 145 | 146 | -------------------------------------------------------------------------------- /VASP/kpoints.job: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #SBATCH --account=uppa 4 | #SBATCH --partition=compute 5 | 6 | ##SBATCH --mail-type=END 7 | ##SBATCH --mail-user=germain.vallverdu@univ-pau.fr 8 | 9 | #SBATCH --time=0-12:00:00 10 | 11 | #SBATCH --nodes=1 12 | #SBATCH --ntasks-per-node=4 13 | ##SBATCH --ntasks=4 14 | #SBATCH --cpus-per-task=1 15 | 16 | # dossier de travail (securite) 17 | source /etc/profile.d/modules.sh 18 | module purge 19 | module load vasp/5.4.4 20 | module list 21 | 22 | # le chemin vers vasp est defini dans le module 23 | echo "vasp : `which vasp`" 24 | echo "------------------------------------------------------------" 25 | echo "SLURM_JOB_NAME =" $SLURM_JOB_NAME 26 | echo "SLURM_JOBID =" $SLURM_JOBID 27 | echo "SLURM_NODELIST = "$SLURM_NODELIST 28 | echo "" 29 | echo "SLURM_NNODES =" $SLURM_NNODES 30 | echo "SLURM_NTASKS =" $SLURM_NTASKS 31 | echo "SLURM_TASKS_PER_NODE =" $SLURM_TASKS_PER_NODE 32 | echo "SLURM_CPUS_PER_TASK =" $SLURM_CPUS_PER_TASK 33 | echo "SLURM_NPROCS =" $SLURM_NPROCS 34 | echo "------------------------------------------------------------" 35 | 36 | # script pour l'optimisation des kpoints 37 | 38 | # INCAR 39 | echo "PREC = Accurate" > INCAR 40 | echo "EDIFF = 1e-6" >> INCAR 41 | echo "ENCUT = 600" >> INCAR 42 | echo "NELMIN = 4" >> INCAR 43 | echo "ISTART = 0" >> INCAR 44 | echo "LWAVE = False" >> INCAR 45 | echo "LCHARG = False" >> INCAR 46 | echo "NSW = 30" >> INCAR 47 | echo "IBRION = 2" >> INCAR 48 | echo "ISIF = 3" >> INCAR 49 | echo "EDIFFG = -0.01" >> INCAR 50 | echo "ISMEAR = 0" >> INCAR 51 | echo "SIGMA = 0.05" >> INCAR 52 | 53 | # boucle sur i = 1 a 12 54 | for i in $(seq 1 12) 55 | do 56 | # ecriture du fichier KPOINTS 57 | echo "k points" > KPOINTS 58 | echo " 0" >> KPOINTS 59 | echo "Gamma" >> KPOINTS 60 | echo " $i $i $i" >> KPOINTS 61 | echo " 0 0 0" >> KPOINTS 62 | 63 | # affiche le fichier KPOINTS 64 | echo -e "\n ================================================================" 65 | echo " KPOINTS file" 66 | echo " ================================================================" 67 | cat KPOINTS 68 | echo -e " ================================================================\n" 69 | 70 | # execution de vasp 71 | time $MPI_RUN vasp 72 | 73 | # sauvegarde des fichiers importants 74 | echo "" 75 | cp -v OSZICAR OSZICAR_$i 76 | cp -v CONTCAR CONTCAR_$i 77 | 78 | # supprime les fichiers de fonction d'onde (WAVECAR) 79 | # et de densite (CHGCAR) pour eviter un restart 80 | echo "" 81 | rm -v WAVECAR CHGCAR 82 | 83 | done 84 | -------------------------------------------------------------------------------- /VASP/kpoints_kspacing.job: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #PBS -l nodes=1:ppn=12:c6100 4 | #PBS -l walltime=24:00:00 5 | #PBS -j oe 6 | #PBS -m ae -M germain.vallverdu@univ-pau.fr 7 | 8 | # le chemin vers vasp est defini dans le module 9 | echo "vasp : `which vasp`" 10 | echo "------------------------------------------------------------" 11 | echo "SLURM_JOB_NAME =" $SLURM_JOB_NAME 12 | echo "SLURM_JOBID =" $SLURM_JOBID 13 | echo "SLURM_NODELIST = "$SLURM_NODELIST 14 | echo "" 15 | echo "SLURM_NNODES =" $SLURM_NNODES 16 | echo "SLURM_NTASKS =" $SLURM_NTASKS 17 | echo "SLURM_TASKS_PER_NODE =" $SLURM_TASKS_PER_NODE 18 | echo "SLURM_CPUS_PER_TASK =" $SLURM_CPUS_PER_TASK 19 | echo "SLURM_NPROCS =" $SLURM_NPROCS 20 | echo "------------------------------------------------------------" 21 | 22 | # chargement des libs 23 | source /etc/profile.d/modules.sh 24 | module purge 25 | module load vasp/5.3.5/openmpi/1.6.5 26 | module list 27 | 28 | # script pour l'optimisation des kpoints 29 | kspacings="1.4 0.9 0.8 0.6 0.45 0.4 0.35 0.3 0.275 0.25 0.225 0.2" 30 | 31 | # boucle su 32 | i=0 33 | for k in $kspacings 34 | do 35 | (( i++ )) 36 | 37 | # INCAR 38 | echo "PREC = Accurate" > INCAR 39 | echo "EDIFF = 1e-6" >> INCAR 40 | echo "ENCUT = 600" >> INCAR 41 | echo "NELMIN = 4" >> INCAR 42 | echo "NELM = 200" >> INCAR 43 | echo "ISTART = 0" >> INCAR 44 | echo "LWAVE = False" >> INCAR 45 | echo "LCHARG = False" >> INCAR 46 | echo "NSW = 60" >> INCAR 47 | echo "IBRION = 2" >> INCAR 48 | echo "ISIF = 3" >> INCAR 49 | echo "EDIFFG = -0.01" >> INCAR 50 | echo "ISMEAR = 1" >> INCAR 51 | echo "SIGMA = 0.2" >> INCAR 52 | echo "KSPACING = $k" >> INCAR 53 | 54 | # affiche le fichier KPOINTS 55 | echo -e "\n ================================================================" 56 | echo " KSPACING value" 57 | echo " ================================================================" 58 | grep KSPACING INCAR 59 | echo -e " ================================================================\n" 60 | 61 | # execution de vasp 62 | time $MPI_RUN vasp 63 | 64 | # sauvegarde des fichiers importants 65 | echo "" 66 | cp -v OUTCAR OUTCAR_$i 67 | cp -v OSZICAR OSZICAR_$i 68 | cp -v CONTCAR CONTCAR_$i 69 | 70 | # supprime les fichiers de fonction d'onde (WAVECAR) 71 | # et de densite (CHGCAR) pour eviter un restart 72 | echo "" 73 | rm -v WAVECAR CHGCAR 74 | 75 | done 76 | -------------------------------------------------------------------------------- /VASP/makeCL.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | import os 5 | import shutil 6 | import pymatgen as mg 7 | from pymatgen.io.vaspio.vasp_input import Poscar, Potcar 8 | 9 | 10 | def qnumber(oa): 11 | """ 12 | return n and l quantum number from an atomic orbital defined as a string. 13 | 14 | args: 15 | oa (str): atomic orbital such as '1s', '3p' ... 16 | 17 | return: 18 | n, l: quantum number 19 | """ 20 | oa = oa.strip() 21 | try: 22 | n = int(oa[0]) 23 | except ValueError: 24 | print("Reading n: Error in AO name") 25 | print("OA = " + oa) 26 | exit(1) 27 | 28 | try: 29 | l = ["s", "p", "d", "f"].index(oa[1]) 30 | except ValueError: 31 | print("Reading l: Error in AO name") 32 | print("OA = " + oa) 33 | exit(1) 34 | 35 | return n, l 36 | 37 | 38 | def add_CL_tags(oa, clz=.5): 39 | """ 40 | print core level part of INCAR file. The atom for which calculation is done, is 41 | supposed to be the first one (CLNT = 1). 42 | 43 | args: 44 | oa (str): atomic orbital such as '1s', '3p' ... 45 | clz (float): CLZ value 46 | """ 47 | 48 | n, l = qnumber(oa) 49 | 50 | line = "\nCore Level\n" 51 | line += " ICORELEVEL = 2\n" 52 | line += " CLNT = 1\n" 53 | line += " LVTOT = .TRUE.\n" 54 | line += " CLN = %d\n" % n 55 | line += " CLL = %d\n" % l 56 | line += " CLZ = %3.1f\n\n" % clz 57 | 58 | return line 59 | 60 | 61 | def buildPOTCAR(atname, fpotcar="POTCAR"): 62 | """ 63 | Build POTCAR file according to atom for wich CL calculation is required. The POTCAR of 64 | the atom is placed in first postion. 65 | """ 66 | potcar = Potcar.from_file(fpotcar) 67 | add = False 68 | for pot in potcar: 69 | if pot.symbol == atname: 70 | newpot = pot 71 | add = True 72 | break 73 | if not add: 74 | print("Atom " + atname + " not found in POTCAR") 75 | exit(1) 76 | else: 77 | potcar.insert(0, newpot) 78 | 79 | potcar.write_file("POTCAR_CL") 80 | 81 | 82 | def buildPOSCAR(iat, fposcar="POSCAR"): 83 | """ 84 | Build POSCAR file according to atom for wich CL calculation is required. The 85 | corresponding atom is placed in first position in the POSCAR. 86 | """ 87 | poscar = Poscar.from_file(fposcar, read_velocities=False) 88 | 89 | # move up the selected atom and ad "_" to differentiate it 90 | site = poscar.structure.pop(iat) 91 | poscar.structure.insert(0, mg.DummySpecie("_" + site.specie.symbol), site.frac_coords) 92 | 93 | poscar.write_file("POSCAR_CL.vasp") 94 | 95 | # remove the _ symbol on 6th line 96 | with open("POSCAR_CL.vasp", "r") as f: 97 | lines = f.readlines() 98 | lines[5] = "".join(["%4s" % el.strip("_") for el in lines[5].split()]) + "\n" 99 | lines = "".join(lines) 100 | with open("POSCAR_CL.vasp", "w") as f: 101 | f.write(lines) 102 | 103 | 104 | def makeRun(ao, job, clz=.5, poscar="POSCAR_CL.vasp", potcar="POTCAR_CL", 105 | incar="INCAR_CL", dirname=None): 106 | """ 107 | Setup the job: 108 | 109 | 1. Make job directory named CL_XX where XX is the clz value. 110 | 2. Copy POSCAR, POTCAR and KPOINTS input files. 111 | 3. Add Core Level tags to the INCAR file according to the AO. 112 | 4. Copy job file in the job directory and add clz value to the name. 113 | 114 | 115 | Note that POTCAR and POSCAR file have to be previously checked. The atom for which the 116 | corelevel calculation will be done is the first one. See buildPOTCAR and buildPOSCAR 117 | functions. 118 | 119 | Args: 120 | oa (str): atomic orbital such as '1s', '3p' ... 121 | job (str): name of job file to submit calculation. 122 | clz (float): value of CLZ INCAR tag 123 | poscar (str): name of POSCAR file. 124 | potcar (str): name of POTCAR file. 125 | incar (str): name of the initial INCAR file. 126 | dirname (str): name of the job directory, if None "CL_%3.1f" % clz is used 127 | 128 | Return: 129 | dirname (str): name of the job directory 130 | jobname (str): name of the script for submission 131 | """ 132 | 133 | # make job directory 134 | if not dirname: 135 | dirname = "CL_%3.1f" % clz 136 | dirname = os.path.join(os.getcwd(), dirname) 137 | os.mkdir(dirname) 138 | 139 | # copy files 140 | shutil.copy(poscar, os.path.join(dirname, "POSCAR")) 141 | shutil.copy(potcar, os.path.join(dirname, "POTCAR")) 142 | shutil.copy("KPOINTS", dirname) 143 | jobname = job + "_%3.1f" % clz 144 | shutil.copy(job, os.path.join(dirname, jobname)) 145 | 146 | # complete and copy INCAR file 147 | with open(incar, "r") as fincar: 148 | incar_lines = fincar.read() + add_CL_tags("1s", clz) 149 | with open(os.path.join(dirname, "INCAR"), "w") as fincar: 150 | fincar.write(incar_lines) 151 | 152 | return dirname, jobname 153 | 154 | if __name__ == "__main__": 155 | 156 | # pic de coeur Li1s 157 | buildPOTCAR("Li", "../opt/POTCAR") 158 | 159 | # make super cell 160 | struct = mg.Structure.from_file("../opt/CONTCAR") 161 | struct.make_supercell(4) 162 | 163 | p = mg.io.vasp.inputs.Poscar(struct) 164 | p.write_file("POSCAR_4.vasp") 165 | 166 | buildPOSCAR(1, "POSCAR_4.vasp") 167 | 168 | # make runs 169 | zval = [0., 0.2, 0.4, 0.5, 0.6, 0.8, 1.] 170 | print(zval) 171 | 172 | lines = "#!/bin/bash\n" 173 | for clz in zval: 174 | dirname, job = makeRun("1s", "jLi_bcc", clz) 175 | dirname = "/" + dirname.strip("/Users/gvallver/pyrene") 176 | print("cd " + dirname) 177 | print("sbatch " + job) 178 | lines += "cd %s \n" % dirname 179 | lines += "sbatch %s \n" % job 180 | 181 | with open("lancer.sh", "w") as f: 182 | f.write(lines) 183 | -------------------------------------------------------------------------------- /VASP/makeKpoints.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | from __future__ import print_function 5 | 6 | """ 7 | Create a KPOINTS file for a band structure calculation. This script use 8 | methods of pymatgen in order to compute and select high symetry lines 9 | in the first brillouin zone. 10 | 11 | SYNTAX 12 | makeKpoints.py [OPTIONS] [STRUCTURE FILE] 13 | 14 | STRUCTURE FILE 15 | must contain a structure. For example a POSCAR file. 16 | 17 | OPTIONS 18 | -d ndiv 19 | ndiv is a integer corresponding to the number of 20 | k-points needed along each symetry line 21 | """ 22 | 23 | __author__ = "Germain Salvato-Vallverdu" 24 | __email__ = "germain.vallverdu@univ-pau.fr" 25 | __licence__ = "GPL" 26 | __date__ = "April 2014" 27 | 28 | import sys 29 | import os 30 | 31 | import pymatgen as mg 32 | from pymatgen.symmetry.analyzer import SpacegroupAnalyzer 33 | from pymatgen.symmetry.bandstructure import HighSymmKpath 34 | from pymatgen.io.vasp.inputs import Kpoints 35 | 36 | # default args 37 | fstruct = "POSCAR" 38 | ndiv = 20 39 | 40 | # read args 41 | if len(sys.argv) > 1: 42 | if len(sys.argv) == 2: 43 | fstruct = sys.argv[1] 44 | else: 45 | fstruct = sys.argv[-1] 46 | if "-d" in sys.argv: 47 | try: 48 | ndiv = int(sys.argv[sys.argv.index("-d") + 1]) 49 | except (ValueError, IndexError): 50 | print("-d must be followed by an integer") 51 | exit(1) 52 | 53 | # read structure 54 | if os.path.exists(fstruct): 55 | struct = mg.Structure.from_file(fstruct) 56 | else: 57 | print("File %s does not exist" % fstruct) 58 | exit(1) 59 | 60 | # symmetry information 61 | struct_sym = SpacegroupAnalyzer(struct) 62 | print("\nLattice details:") 63 | print("----------------") 64 | print("lattice type : {0}".format(struct_sym.get_lattice_type())) 65 | print("space group : {0} ({1})".format(struct_sym.get_space_group_symbol(), 66 | struct_sym.get_space_group_number())) 67 | 68 | # Compute first brillouin zone 69 | ibz = HighSymmKpath(struct) 70 | print("ibz type : {0}".format(ibz.name)) 71 | #ibz.get_kpath_plot(savefig="path.png") 72 | 73 | # print specific kpoints in the first brillouin zone 74 | print("\nList of high symmetry k-points:") 75 | print("-------------------------------") 76 | for key, val in ibz.kpath["kpoints"].items(): 77 | print("%8s %s" % (key, str(val))) 78 | 79 | # suggested path for the band structure 80 | print("\nSuggested paths in first brillouin zone:") 81 | print("----------------------------------------") 82 | for i, path in enumerate(ibz.kpath["path"]): 83 | print(" %2d:" % (i + 1), " -> ".join(path)) 84 | 85 | # write the KPOINTS file 86 | print("\nWrite file KPOINTS") 87 | Kpoints.automatic_linemode(ndiv, ibz).write_file("KPOINTS") 88 | -------------------------------------------------------------------------------- /VASP/moduleDOS.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*-coding:utf-8 -*- 3 | 4 | """ 5 | Apply scofield cross sections to a DOS 6 | Journal of Electron Spectroscopy and Related Phenomena, 8 (1976) 129-137) 7 | """ 8 | 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | from pymatgen.electronic_structure.core import Spin, OrbitalType 12 | from pymatgen.io.vasp.outputs import Vasprun 13 | 14 | 15 | __author__ = "Germain Salvato-Vallverdu" 16 | __email__ = "germain.vallverdu@univ-pau.fr" 17 | __licence__ = "GPL" 18 | __date__ = "June 2014" 19 | 20 | 21 | def modulate(xmlfile="vasprun.xml", tofile=False): 22 | """ 23 | Multiply DOS by cross sections and plot it using matplotlib 24 | 25 | Args: 26 | xmlfile(string): name of the vasprun.xml file 27 | tofile(bool): data are printed into file BV.dat if true 28 | """ 29 | 30 | run = Vasprun(xmlfile) 31 | dos = run.complete_dos 32 | 33 | BV = dict() 34 | BV["total"] = np.zeros(dos.energies.shape) 35 | for el in dos.structure.composition.elements: 36 | # cross section 37 | sigma = CrossSec.from_string(el.symbol) 38 | print(sigma.comment) 39 | 40 | # spd DOS of the element 41 | el_dos = dos.get_element_spd_dos(el) 42 | 43 | # sum up spin contribution 44 | spd_dos = dict() 45 | if run.is_spin: 46 | for orb in el_dos.keys(): 47 | spd_dos[orb] = el_dos[orb].densities[Spin.up] \ 48 | + el_dos[orb].densities[Spin.down] 49 | else: 50 | for orb in el_dos.keys(): 51 | spd_dos[orb] = el_dos[orb].densities[Spin.up] 52 | 53 | # compute the BV 54 | BV[el] = sigma.s * spd_dos[OrbitalType.s] \ 55 | + sigma.p * spd_dos[OrbitalType.p] \ 56 | + sigma.d * spd_dos[OrbitalType.d] 57 | 58 | BV["total"] += BV[el] 59 | 60 | if tofile: 61 | lines = "# Valence Band of compound %s\n" % \ 62 | dos.structure.composition.reduced_formula 63 | lines += "# column 1: E - E_fermi (eV)\n" 64 | lines += "# column 2: total valence band\n" 65 | i = 2 66 | for el in dos.structure.composition.elements: 67 | i += 1 68 | lines += "# column %d: Contribution of %s \n" % (i, el.symbol) 69 | for i in range(len(dos.energies)): 70 | lines += "%12.7f " % (dos.energies[i] - dos.efermi) 71 | lines += "%12.7f " % BV["total"][i] 72 | for el in dos.structure.composition.elements: 73 | lines += "%12.7f " % BV[el][i] 74 | lines += "\n" 75 | 76 | open("BV.dat", "w").write(lines) 77 | 78 | else: 79 | # plot 80 | font = {'family': 'serif', 'size': 20} 81 | plt.rc('font', **font) 82 | plt.figure(figsize=(11.69, 8.27)) # A4 83 | 84 | plt.fill_between(dos.energies - dos.efermi, BV["total"], 0, 85 | color=(.8, .8, .8)) 86 | plt.plot(dos.energies - dos.efermi, BV["total"], color=(.5, .5, .5), 87 | label="total") 88 | color = ["r-", "g-", "b-", "y-", "m-", "c-"] 89 | for el, c in zip(dos.structure.composition.elements, color): 90 | plt.plot(dos.energies - dos.efermi, BV[el], c, label=el.symbol) 91 | 92 | # set up figure 93 | plt.title("Valence band of " + 94 | run.initial_structure.composition.reduced_formula) 95 | plt.xlabel(r"$E - E_{f}$ / eV") 96 | plt.ylabel("Density of states times cross sections") 97 | plt.grid() 98 | ymin, ymax = plt.ylim() 99 | plt.vlines(0, ymin, ymax, color="k", lw=1, linestyle="--") 100 | plt.legend(prop={"size": 18}) 101 | 102 | plt.show() 103 | 104 | 105 | class Kalpha(object): 106 | """ 107 | Enum type for energies of K alpha photons 108 | """ 109 | 110 | Mg = 1254 111 | Al = 1487 112 | all_energies = {"Mg": Mg, "Al": Al} 113 | 114 | 115 | class CrossSecSpecie(object): 116 | """ 117 | Store cross sections values of a specie 118 | """ 119 | 120 | def __init__(self, ener, name, s=0, p1=0, p2=0, d1=0, d2=0, comment=None): 121 | """ 122 | Store cross sections values of element of symbol name 123 | 124 | Args: 125 | ener: Photon energy 126 | name: Element symbol 127 | s: cross section for s electrons 128 | p1: cross section for p1/2 electrons 129 | p2: cross section for p3/2 electrons 130 | d1: cross section for d3/2 electrons 131 | d2: cross section for d5/2 electrons 132 | """ 133 | 134 | if ener not in Kalpha.all_energies.values(): 135 | print("Error, energy must be in ", Kalpha.all_energies) 136 | exit(1) 137 | 138 | self._ener = ener 139 | self._name = name 140 | self._s = s 141 | self._p1 = p1 142 | self._p2 = p2 143 | self._d1 = d1 144 | self._d2 = d2 145 | if not comment: 146 | comment = name + " cross section for energy " + str(ener) 147 | self._comment = comment 148 | 149 | @property 150 | def energy(self): 151 | """ 152 | Photon energy 153 | """ 154 | return self._ener 155 | 156 | @property 157 | def name(self): 158 | """ 159 | specie name 160 | """ 161 | return self._name 162 | 163 | @property 164 | def s(self): 165 | """ 166 | p1/2 cross section 167 | """ 168 | return self._s 169 | 170 | @property 171 | def p_half(self): 172 | """ 173 | p1/2 cross section 174 | """ 175 | return self._p1 176 | 177 | @property 178 | def p_three_halves(self): 179 | """ 180 | p3/2 cross section 181 | """ 182 | return self._p2 183 | 184 | @property 185 | def d_three_halves(self): 186 | """ 187 | d3/2 cross section 188 | """ 189 | return self._d1 190 | 191 | @property 192 | def d_five_halves(self): 193 | """ 194 | d5/2 cross section 195 | """ 196 | return self._d2 197 | 198 | @property 199 | def p(self): 200 | """ 201 | Cross section for p1/2 and p3/2 electrons weighted by the multiplicity. 202 | """ 203 | return (2 * self._p1 + 4 * self._p2) / 6 204 | 205 | @property 206 | def d(self): 207 | """ 208 | Cross section for d3/2 and d5/2 electrons weighted by the multiplicity. 209 | """ 210 | return (4 * self._d1 + 6 * self._d2) / 10 211 | 212 | @property 213 | def comment(self): 214 | """ 215 | Comment on value 216 | """ 217 | return self._comment 218 | 219 | def __repr__(self): 220 | return self.name 221 | 222 | def __str__(self): 223 | line = "Specie name: " + self._name + "\n" 224 | line += "Photon energy: " + str(self._ener) + "\n" 225 | line += self._comment + "\n" 226 | line += "s = " + str(self.s) + "\n" 227 | line += "p = " + str(self.p) + "\n" 228 | line += "d = " + str(self.d) + "\n" 229 | return line 230 | 231 | 232 | class CrossSec(object): 233 | """ 234 | Cross section object from publication of J.H. Scofield (Journal of Electron 235 | Spectroscopy and Related Phenomena, 8 (1976) 129-137). 236 | """ 237 | 238 | H_Mg = CrossSecSpecie(Kalpha.Mg, "H_Mg", 0.0002, 239 | comment="H, 1s1 configuration, Mg Kalpha") 240 | H_Al = CrossSecSpecie(Kalpha.Al, "H_Al", 0.0002, 241 | comment="H, 1s1 configuration, Al Kalpha") 242 | 243 | # second row 244 | Li_p_Mg = CrossSecSpecie(Kalpha.Mg, "Li_p_Mg", 0.0593, 245 | comment="Li+, 1s2 configuration, Mg Kalpha") 246 | Li_p_Al = CrossSecSpecie(Kalpha.Al, "Li_p_Al", 0.0568, 247 | comment="Li+, 1s2 configuration, Al Kalpha") 248 | 249 | N_Mg = CrossSecSpecie(Kalpha.Mg, "N_Mg", 0.0841, 0.0025, 0.0049, 250 | comment="N: 1s2 2s2 2p3 configuration, Mg Kalpha") 251 | N_Al = CrossSecSpecie(Kalpha.Al, "N_Al", 0.0867, 0.0022, 0.0043, 252 | comment="N: 1s2 2s2 2p3 configuration, Al Kalpha") 253 | 254 | O_Mg = CrossSecSpecie(Kalpha.Mg, "O_Mg", 0.1345, 0.0073, 0.0145, 255 | comment="O: 1s2 2s2 2p4 configuration, Mg Kalpha") 256 | O_Al = CrossSecSpecie(Kalpha.Al, "O_Al", 0.1405, 0.0065, 0.0128, 257 | comment="O: 1s2 2s2 2p4 configuration, Al Kalpha") 258 | 259 | # third row 260 | Na_p_Mg = CrossSecSpecie(Kalpha.Mg, "Na_p_Mg", 0.390, 0.0714, 0.1406, 261 | comment="Na+: 1s2 2s2 2p6 configuration, Mg Kalpha") 262 | Na_p_Al = CrossSecSpecie(Kalpha.Al, "Na_p_Al", 0.422, 0.0654, 0.1287, 263 | comment="Na+: 1s2 2s2 2p6 configuration, Al Kalpha") 264 | 265 | P_Mg = CrossSecSpecie(Kalpha.Mg, "P_Mg", 0.0998, 0.0129, 0.0253, 266 | comment="P: 1s2 2s2 2p6 3s2 3p3 configuration, Mg Kalpha") 267 | P_Al = CrossSecSpecie(Kalpha.Al, "P_Al", 0.1116, 0.0124, 0.0244, 268 | comment="P: 1s2 2s2 2p6 3s2 3p3 configuration, Al Kalpha") 269 | 270 | S_Mg = CrossSecSpecie(Kalpha.Mg, "S_Mg", 0.1302, 0.0269, 0.0527, 271 | comment="S: 1s2 2s2 2p6 3s2 3p4 configuration, Mg Kalpha") 272 | S_Al = CrossSecSpecie(Kalpha.Al, "S_Al", 0.1465, 0.0262, 0.0512, 273 | comment="S: 1s2 2s2 2p6 3s2 3p3 configuration, Al Kalpha") 274 | 275 | # fourth row 276 | Co_Mg = CrossSecSpecie(Kalpha.Mg, "Co_Mg", 0.0451, 0, 0, 0.1220, 0.1787, 277 | comment="Co: 4s2 3d7, Mg Kalpha, 0 for p cros section") 278 | Co_Al = CrossSecSpecie(Kalpha.Al, "Co_Al", 0.0529, 0, 0, 0.1082, 0.1582, 279 | comment="Co: 4s2 3d7, Al Kalpha, 0 for p cros section") 280 | Mn_Mg = CrossSecSpecie(Kalpha.Mg, "Mn_Mg", 0.0398, 0, 0, 0.0484, 0.0711, 281 | comment="Mn: 4s2 3d5, Mg Kalpha, 0 for p cros section") 282 | Mn_Al = CrossSecSpecie(Kalpha.Al, "Mn_Al", 0.0464, 0, 0, 0.0424, 0.0622, 283 | comment="Mn: 4s2 3d5, Al Kalpha, 0 for p cros section") 284 | Fe_Mg = CrossSecSpecie(Kalpha.Mg, "Fe_Mg", 0.0425, 0, 0, 0.0788, 0.1156, 285 | comment="Cu: 4s2 3d6, Mg Kalpha, 0 for p cros section") 286 | Fe_Al = CrossSecSpecie(Kalpha.Al, "Fe_Al", 0.0497, 0, 0, 0.1017, 0.0497, 287 | comment="Cu: 4s2 3d6, Al Kalpha, 0 for p cros section") 288 | Cu_Mg = CrossSecSpecie(Kalpha.Mg, "Cu_Mg", 0.0188, 0, 0, 0.268, 0.390, 289 | comment="Cu: 4s1 3d10, Mg Kalpha, 0 for p cros section") 290 | Cu_Al = CrossSecSpecie(Kalpha.Al, "Cu_Al", 0.0221, 0, 0, 0.240, 0.349, 291 | comment="Cu: 4s1 3d10, Al Kalpha, 0 for p cros section") 292 | 293 | all_data = (H_Mg, H_Al, 294 | Li_p_Mg, Li_p_Al, N_Mg, N_Al, O_Mg, O_Al, 295 | Na_p_Mg, Na_p_Al, P_Mg, P_Al, S_Mg, S_Al, 296 | Mn_Mg, Mn_Al, Fe_Mg, Fe_Al, Co_Mg, Co_Al, Cu_Mg, Cu_Al) 297 | 298 | @staticmethod 299 | def from_string(specie, ener=Kalpha.Al): 300 | """ 301 | Return cross section of a specie from a string representation. 302 | """ 303 | for cs in CrossSec.all_data: 304 | if specie in cs.name and ener == cs.energy: 305 | return cs 306 | raise ValueError("%s not found in the data base" % specie) 307 | 308 | 309 | if __name__ == "__main__": 310 | xmlfile = "vasprun.xml" 311 | modulate(xmlfile, tofile=True) 312 | -------------------------------------------------------------------------------- /VASP/opt_slab.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | opt_slab\n\n 5 | 6 | A quick script to write VASP inputs to explore the lattice parameters of a 7 | slab system. 8 | """ 9 | 10 | import argparse 11 | import shutil 12 | from pathlib import Path 13 | import numpy as np 14 | 15 | # use pymatgen objects 16 | import pymatgen as mg 17 | from pymatgen.io.vasp.inputs import Poscar 18 | 19 | 20 | def copy_files(wd, args, struct): 21 | """ Copy files into the give directory """ 22 | 23 | shutil.copy(args.incar, wd) 24 | shutil.copy(args.kpoints, wd) 25 | shutil.copy(args.potcar, wd) 26 | shutil.copy(args.jobfile, wd / ("j" + wd.name)) 27 | 28 | Poscar(struct).write_file(str(wd / "POSCAR")) 29 | 30 | 31 | def scale_structure(struct, sf): 32 | """ 33 | Scale the lattice of a structure according to the choosen dimension and 34 | using the give scale factor. 35 | """ 36 | 37 | sf_array = np.array(sf) 38 | 39 | # multiply by line 40 | matrix = struct.lattice.matrix 41 | matrix = (matrix.T * sf_array).T 42 | 43 | return mg.Structure(mg.Lattice(matrix), struct.species, struct.frac_coords) 44 | 45 | 46 | def gen_calcs(args): 47 | """ set up all calculations """ 48 | 49 | # set up scale factors and dimension 50 | if args.from_file: 51 | with open(args.from_file, "r") as f: 52 | scale_factors = list() 53 | dim = list() 54 | for line in f: 55 | values = [float(val) for val in line.split()] 56 | scale_factors.append(values) 57 | dim.append(len(values)) 58 | 59 | if not all(d == dim[0] for d in dim): 60 | raise ValueError("You have to provide the same number of scaling " 61 | "factors on each line.") 62 | else: 63 | dimension = args.dimension 64 | if dim[0] == 1: 65 | if dimension > 1 and dimension != -3: 66 | raise ValueError("scale factors values and dimension are not consistent.") 67 | elif dim[0] != dimension: 68 | raise ValueError("scale factors values and dimension are not consistent.") 69 | 70 | for sf in scale_factors: 71 | if dimension == 1: 72 | sfx = sf[0] 73 | if args.axis == "a": 74 | sf += [1.0, 1.0] 75 | elif args.axis == "b": 76 | sf.append(1.0) 77 | sf.insert(0, 1.0) 78 | elif args.axis == "c": 79 | sf.insert(0, 1.0) 80 | sf.insert(0, 1.0) 81 | elif dimension == 2: 82 | sf += [1.] 83 | elif dimension == -3: 84 | sfx = sf[0] 85 | sf += [sfx, sfx] 86 | scale_factors = [tuple(sf) for sf in scale_factors] 87 | 88 | else: 89 | dimension = args.dimension 90 | scale_factors = list() 91 | for sfx in args.scale_factors: 92 | if dimension == 1: 93 | if args.axis == "a": 94 | scale_factors.append((sfx, 1.0, 1.0)) 95 | elif args.axis == "b": 96 | scale_factors.append((1.0, sfx, 1.0)) 97 | elif args.axis == "c": 98 | scale_factors.append((1.0, 1.0, sfx)) 99 | continue 100 | elif dimension == -3: 101 | scale_factors.append((sfx, sfx, sfx)) 102 | continue 103 | for sfy in args.scale_factors: 104 | if dimension == 2: 105 | scale_factors.append((sfx, sfy, 1.0)) 106 | continue 107 | for sfz in args.scale_factors: 108 | scale_factors.append((sfx, sfy, sfz)) 109 | 110 | # set up working directory name 111 | if dimension == 1: 112 | wd = Path(args.to) / "scan_axes" 113 | elif dimension == 2: 114 | wd = Path(args.to) / "scan_surf" 115 | elif dimension == 3: 116 | wd = Path(args.to) / "scan_anisotrop" 117 | elif dimension == -3: 118 | wd = Path(args.to) / "scan_vol" 119 | 120 | wd.mkdir(parents=True) 121 | 122 | print("Files will be generated in:", str(wd)) 123 | print(" * Initial structure:", args.poscar) 124 | print(" * INCAR file from:", args.incar) 125 | print(" * KPOINTS file from:", args.kpoints) 126 | print(" * POTCAR file from:", args.potcar) 127 | print(" * job file:", args.jobfile) 128 | 129 | # initial structure 130 | struct0 = mg.Structure.from_file(args.poscar) 131 | 132 | # bash script to submit all Files 133 | lancer = "#!/bin/bash\n\n" 134 | scale_values = "# scaling factor values and folder names\n" 135 | 136 | # make inputs 137 | print("\nGrid in %d dimension(s)" % dimension) 138 | print("Number of calculations: ", len(scale_factors)) 139 | print(scale_factors) 140 | 141 | for sfx, sfy, sfz in scale_factors: 142 | 143 | if dimension == 1 or dimension == -3: 144 | val = sfx if args.axis == "a" else sfy if args.axis == "b" else sfz 145 | wd_sf = wd / ("SF_%.2f" % val) 146 | print("--> Run %5.2f in %s" % (val, wd_sf)) 147 | scale_values += "%10f %s\n" % (val, wd_sf.name) 148 | elif dimension == 2: 149 | wd_sf = wd / ("SF_%.2f_%.2f" % (sfx, sfy)) 150 | print("--> Run (%.2f, %.2f) in %s" % (sfx, sfy, wd_sf)) 151 | scale_values += "%10f %10f %s\n" % (sfx, sfy, wd_sf.name) 152 | elif dimension == 3: 153 | wd_sf = wd / ("SF_%.2f_%.2f_%.2f" % (sfx, sfy, sfz)) 154 | print("--> Run (%.2f, %.2f, %.2f) in %s" % (sfx, sfy, sfy, wd_sf)) 155 | scale_values += "%10f %10f %10f %s\n" % (sfx, sfy, sfz, wd_sf.name) 156 | 157 | wd_sf.mkdir() 158 | 159 | structi = scale_structure(struct0, (sfx, sfy, sfz)) 160 | copy_files(wd_sf, args, structi) 161 | 162 | lancer += "cd %s\n" % str(wd_sf.resolve()) 163 | lancer += "sbatch j%s\n\n" % wd_sf.name 164 | 165 | with open(wd / "lancer.sh", "w") as f: 166 | f.write(lancer) 167 | 168 | with open(wd / "scale_values.dat", "w") as f: 169 | f.write(scale_values) 170 | 171 | 172 | def get_options(): 173 | """ get options from command lines """ 174 | 175 | parser = argparse.ArgumentParser(prog="opt_slab", description=__doc__) 176 | 177 | # scaling factor to be used 178 | parser.add_argument( 179 | "-s", "--scale_factors", 180 | type=float, nargs="+", 181 | default=[0.99, 1.0, 1.01], 182 | help="Scaling factors of lattice parameters", 183 | metavar="SCALE_FACTOR" 184 | ) 185 | 186 | # dimension 187 | parser.add_argument( 188 | "-d", "--dimension", type=int, default=1, 189 | help="Dimension of the grid 1, 2 or 3.\n If dimension is 2, be sure the" 190 | " slab is perpendicular to the c axis. Dimension 3 is for an " 191 | "anisotropic grid. Dimension -3 is for an isotropic scan.", 192 | choices=(1, 2, 3, -3), metavar="DIMENSION" 193 | ) 194 | 195 | # dimension 196 | parser.add_argument( 197 | "-a", "--axis", type=str, default="a", 198 | help="If dimension is 1, define the axis along which the scan is done.", 199 | choices=("a", "b", "c"), metavar="AXIS" 200 | ) 201 | 202 | # scaling factors from a file 203 | parser.add_argument( 204 | "-f", "--from_file", type=str, default=None, metavar="FILE", 205 | help="The list of scaling factors is provided in a file. " 206 | "Each line corresponds to one calculation and provides 1, 2 or 3 " 207 | "values depending on the dimension.", 208 | ) 209 | 210 | # workind directory for all calculations 211 | parser.add_argument("-t", "--to", 212 | help="parent directory where inputs will be written", 213 | metavar="WORKDIR", 214 | default="./", 215 | type=str) 216 | 217 | # vasp input files 218 | parser.add_argument("-i", "--incar", metavar="INCAR", 219 | default="./INCAR", type=str, 220 | help="INCAR file to be used for the calculations.") 221 | 222 | parser.add_argument("-p", "--poscar", metavar="POSCAR", 223 | default="./POSCAR", type=str, 224 | help="POSCAR file to be used for the calculations.") 225 | 226 | parser.add_argument("-k", "--kpoints", metavar="KPOINTS", 227 | default="./KPOINTS", type=str, 228 | help="KPOINTS file to be used for the calculations.") 229 | 230 | parser.add_argument("-c", "--potcar", metavar="POTCAR", 231 | default="./POTCAR", type=str, 232 | help="POTCAR file to be used for the calculations.") 233 | 234 | parser.add_argument("-j", "--jobfile", metavar="JOBFILE", 235 | default="./job", type=str, 236 | help="job file to be used in order to submit the calculations.") 237 | 238 | return parser.parse_args() 239 | 240 | 241 | if __name__ == "__main__": 242 | args = get_options() 243 | gen_calcs(args) 244 | -------------------------------------------------------------------------------- /VASP/readCL.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import numpy as np 5 | from pymatgen.io.vasp.outputs import Outcar 6 | import matplotlib.pyplot as plt 7 | 8 | ao = "1s" 9 | zvals = [0.0, 0.2, 0.4, 0.5, 0.6, 0.8, 1.0] 10 | 11 | foutcars = ["CL_%3.1f/OUTCAR" % z for z in zvals] 12 | print(foutcars) 13 | 14 | clz = list() 15 | clz_e = list() 16 | 17 | lines = "# Clz eps_i(1s) for all atoms\n" 18 | for zval, foutcar in zip(zvals, foutcars): 19 | # print("OUTCAR = ", foutcar) 20 | out = Outcar(foutcar) 21 | cl = out.read_core_state_eigen() 22 | clz.append(cl[0][ao][-1]) 23 | clz_e.append(cl[0][ao][-1] + out.efermi) 24 | line = "%5f" % zval 25 | for cl_at in cl: 26 | line += "%12.4f" % cl_at[ao][-1] 27 | print("%4.1f %10.4f %10.4f %10.4f" % (zval, out.efermi, cl[0][ao][-1], cl[0][ao][-1] + out.efermi)) 28 | 29 | lines += line + "\n" 30 | #print(line) 31 | 32 | #print(clz) 33 | with open("cl.dat", "w") as f: 34 | f.write(lines) 35 | 36 | params = np.polyfit(x=zvals, y=clz, deg=2) 37 | a, b, c = params 38 | print(params) 39 | params = np.polyfit(x=zvals, y=clz_e, deg=2) 40 | a, b, c = params 41 | print(params) 42 | fit = lambda x: a * x**2 + b * x + c 43 | 44 | plt.plot(zvals, clz, "ro--", label="eps") 45 | plt.plot(zvals, clz_e, "yo--", label="epsi - eF") 46 | x = np.linspace(0, 1, 200) 47 | y = fit(x) 48 | plt.plot(x, y, "b-") 49 | plt.plot((x[0], x[-1]), (y[0], y[-1]), "k-") 50 | plt.legend() 51 | plt.show() 52 | 53 | print("integration:" ,np.trapz(y, x)) 54 | for z, e in zip(zvals, clz): 55 | print("%4.1f %10.4f" % (z, e)) 56 | 57 | -------------------------------------------------------------------------------- /VASP/readU.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | from pymatgen.io.vasp.outputs import Vasprun, Outcar 4 | 5 | class UData(object): 6 | 7 | def __init__(self, U=None): 8 | self.U = U 9 | 10 | self.a = None 11 | self.b = None 12 | self.c = None 13 | 14 | self.alpha = None 15 | self.beta = None 16 | self.gamma = None 17 | 18 | self.charges = None 19 | self.ave_charges = None 20 | self.magnetization = None 21 | self.ave_magnetization = None 22 | 23 | self.gap = None 24 | 25 | self.energy = None 26 | 27 | self.dirname = None 28 | 29 | def as_dict(self): 30 | 31 | d = {} 32 | d["a"] = self.a 33 | d["b"] = self.b 34 | d["c"] = self.c 35 | d["alpha"] = self.alpha 36 | d["beta"] = self.beta 37 | d["gamma"] = self.gamma 38 | d["charges"] = [q for at, q in self.charges] 39 | d["atoms"] = [at for at, q in self.charges] 40 | d["magnetization"] = [m for at, m in self.magnetization] 41 | d["average"] = {"magnetization": self.ave_magnetization, 42 | "charges": self.ave_charges} 43 | d["gap"] = self.gap 44 | d["energy"] = self.energy 45 | 46 | d["dirname"] = self.dirname 47 | 48 | return d 49 | 50 | def write_line(self): 51 | line = "" 52 | def write_val(val, fmt): 53 | if not val: 54 | val = 0.0 55 | return fmt % val 56 | line += write_val(self.U, "%5.1f") 57 | line += write_val(self.a, "%10.4f") 58 | line += write_val(self.b, "%10.4f") 59 | line += write_val(self.c, "%10.4f") 60 | line += write_val(self.alpha, "%10.4f") 61 | line += write_val(self.beta, "%10.4f") 62 | line += write_val(self.gamma, "%10.4f") 63 | line += write_val(self.energy, "%16.8e") 64 | 65 | for q in self.ave_charges.values(): 66 | line += write_val(q, "%10.4f") 67 | 68 | for m in self.ave_magnetization.values(): 69 | line += write_val(m, "%10.4f") 70 | 71 | line += write_val(self.gap, "%8.3f") 72 | 73 | return line + "\n" 74 | 75 | def head(self): 76 | head = "# U" 77 | head += "a".rjust(10) 78 | head += "b".rjust(10) 79 | head += "c".rjust(10) 80 | head += "alpha".rjust(10) 81 | head += "beta".rjust(10) 82 | head += "gamma".rjust(10) 83 | head += "energy (eV)".rjust(16) 84 | for el in self.ave_charges: 85 | head += ("q_%s" % el).rjust(10) 86 | for el in self.ave_magnetization: 87 | head += ("m_%s" % el).rjust(10) 88 | 89 | head += "gap (eV)".rjust(10) 90 | 91 | return head + "\n" 92 | 93 | @staticmethod 94 | def from_calc(U): 95 | data = UData(U=U) 96 | 97 | dirname = os.path.join(os.getcwd(), "U_%d" % U) 98 | data.dirname = dirname 99 | 100 | # read lattice 101 | optxml = os.path.join(dirname, "vasprun.xml") 102 | optrun = Vasprun(optxml, parse_dos=False, parse_eigen=False, parse_potcar_file=False) 103 | 104 | data.a, data.b, data.c = optrun.final_structure.lattice.abc 105 | data.alpha, data.beta, data.gamma = optrun.final_structure.lattice.angles 106 | 107 | # read charges 108 | fcharges = os.path.join(dirname, "Bader/charges.dat") 109 | ave_charges = {} 110 | charges = [] 111 | with open(fcharges, "r") as f: 112 | charge_read = False 113 | for line in f: 114 | if not charge_read and "-------" in line: 115 | line = f.readline() 116 | while "------" not in line: 117 | val = line.split() 118 | charges.append((val[1], float(val[4]))) 119 | line = f.readline() 120 | charge_read = True 121 | if "Averages :" in line: 122 | f.readline() 123 | f.readline() 124 | val = f.readline().split() 125 | ave_charges[val[0]] = float(val[2]) 126 | val = f.readline().split() 127 | ave_charges[val[0]] = float(val[2]) 128 | 129 | data.ave_charges = ave_charges 130 | data.charges = charges 131 | 132 | # read OUTCAR 133 | foutcar = os.path.join(dirname, "Bader/OUTCAR") 134 | outcar = Outcar(foutcar) 135 | 136 | # read energy from OUTCAR 137 | data.energy = outcar.final_energy 138 | 139 | # read magnetization from OUTCAR 140 | mag = [(site.specie.symbol, atmag["tot"]) for atmag, site in zip(outcar.magnetization, optrun.final_structure)] 141 | data.magnetization = mag 142 | avemag = {el.name: 0. for el in optrun.final_structure.composition.elements} 143 | for el, atmag in mag: 144 | avemag[el] += atmag 145 | for el, count in optrun.final_structure.composition.as_dict().items(): 146 | avemag[el] /= float(count) 147 | 148 | data.ave_magnetization = avemag 149 | 150 | # gap 151 | dosxml = os.path.join(dirname, "DOS/vasprun.xml") 152 | dosrun = Vasprun(dosxml, parse_eigen=False, parse_potcar_file=False) 153 | data.gap = dosrun.complete_dos.get_gap() 154 | 155 | return data 156 | 157 | if __name__ == "__main__": 158 | 159 | all_data = [UData.from_calc(U) for U in [0.]] 160 | # all_data = [UData.from_calc(U) for U in [0., 2., 4., 6., 8., 10.]] 161 | 162 | print(all_data[0].head()) 163 | 164 | for data in all_data: 165 | print(data.write_line()) 166 | 167 | 168 | # for U in [0., 2., 4., 6., 8., 10.]: 169 | # 170 | # all_data.adata = UData.from_calc(U) 171 | # 172 | # print(3 * "%10.4f" % (data.a, data.b, data.a)) 173 | # print(3 * "%10.4f" % (data.alpha, data.beta, data.gamma)) 174 | # 175 | # print("average charges") 176 | # for el, q in data.ave_charges.items(): 177 | # print("%4s %10.4f" % (el, q)) 178 | # 179 | # 180 | # print("average mu_B:") 181 | # for el, atmag in data.ave_magnetization.items(): 182 | # print("%4s %10.4f" % (el, atmag)) 183 | # 184 | # print("gap = %10.4f" % data.gap) 185 | # 186 | # print("energy = %16.6e" % data.energy) 187 | # 188 | -------------------------------------------------------------------------------- /VASP/runU.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import shutil 4 | import stat 5 | from pymatgen.io.vasp.inputs import Kpoints 6 | 7 | # points k 8 | kx, ky, kz = 4, 4, 4 9 | 10 | # job name : 11 | # * doit finir par .job 12 | # ou 13 | # * doit commencer par j 14 | job = "test.job" 15 | basename = "test" 16 | 17 | lancer = "#!/bin/bash\n\n" 18 | 19 | for U in [0, 2, 4, 6, 8, 10]: 20 | print("U = %f" % U) 21 | 22 | # make job directory 23 | dirname = "U_%d" % U 24 | dirname = os.path.join(os.getcwd(), dirname) 25 | os.mkdir(dirname) 26 | 27 | # copy files 28 | shutil.copy("POSCAR", os.path.join(dirname, "POSCAR")) 29 | shutil.copy("POTCAR", os.path.join(dirname, "POTCAR")) 30 | 31 | kpoints = Kpoints.gamma_automatic((kx, ky, kz)) 32 | kpoints.write_file(os.path.join(dirname, "KPOINTS")) 33 | 34 | jobname = basename + ("_U%d" % U) + ".job" 35 | shutil.copy(job, os.path.join(dirname, jobname)) 36 | 37 | # complete and copy INCAR file 38 | with open("INCAR", "r") as fincar: 39 | incar_lines = "" 40 | for line in fincar: 41 | if "LDAUU" in line: 42 | line = " LDAUU = %3.1f 0.0\n" % U 43 | incar_lines += line 44 | with open(os.path.join(dirname, "INCAR"), "w") as fincar: 45 | fincar.write(incar_lines) 46 | 47 | lancer += "cd %s\n" % dirname 48 | lancer += "sbatch %s\n\n" % jobname 49 | 50 | with open("lancer.sh", "w") as f: 51 | f.write(lancer) 52 | os.chmod("lancer.sh", 0o755) 53 | -------------------------------------------------------------------------------- /VASP/scofield.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | Example of DOS modulation 6 | Apply moduleDOS module 7 | """ 8 | 9 | from __future__ import division, print_function 10 | 11 | import moduleDOS 12 | from pymatgen.io.vaspio.vasp_output import Vasprun 13 | 14 | __author__ = "Germain Salvato-Vallverdu" 15 | __email__ = "germain.vallverdu@univ-pau.fr" 16 | __licence__ = "GPL" 17 | __date__ = "Nov. 2014" 18 | 19 | # options: 20 | xmlfile = "dos.xml" 21 | tofile = False 22 | 23 | # print cross sections: 24 | print("Cross sections :") 25 | run = Vasprun(xmlfile, parse_dos=False, parse_eigen=False) 26 | for el in run.initial_structure.composition.elements: 27 | print(moduleDOS.CrossSec.from_string(el.symbol)) 28 | 29 | # molate DOS: 30 | moduleDOS.modulate(xmlfile, tofile) 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /VASP/vacantPosition.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding=utf-8 -*- 3 | 4 | import sys 5 | import pymatgen as mg 6 | import numpy as np 7 | from pymatgen.io.vaspio.vasp_input import Poscar 8 | 9 | def look4VacantPosition(): 10 | """ """ 11 | 12 | s = mg.Structure.from_file(sys.argv[1]) 13 | 14 | fill_s = s.copy() 15 | grid = mg.Structure(s.lattice, [], []) 16 | 17 | # grid step in frac coords 18 | step = 0.1 19 | # radius for looking for neighbors 20 | radius = 2.5 21 | # threshold to exclude vacant position 22 | els = s.composition.elements 23 | th = {els[0]: 1.7, els[1]: 2., els[2]: 2.} 24 | 25 | # grid ranges 26 | xmin = 0 27 | xmax = 1 28 | ymin = 0 29 | ymax = 1 30 | zmin = 0 31 | zmax = 1 32 | 33 | print("Parameters\n" + 10 * "-") 34 | print("Grid step : %6.2f" % step) 35 | print("Neighbors radius : %6.2f" % radius) 36 | print("threshold tolerence:") 37 | for el, dmax in th.items(): 38 | print("X - %2s : %8.3f" % (el.symbol, dmax)) 39 | 40 | vaclist = list() 41 | for xi in np.arange(xmin, xmax, step): 42 | for yi in np.arange(ymin, ymax, step): 43 | for zi in np.arange(zmin, zmax, step): 44 | vacsite = mg.PeriodicSite("X", [xi, yi, zi], s.lattice) 45 | neigh = s.get_neighbors(vacsite, radius) 46 | 47 | grid.append("X", [xi, yi, zi]) 48 | 49 | add = True 50 | nLi = 0 51 | for neighsite, d in neigh: 52 | dmax = th[neighsite.specie] 53 | if d < dmax: 54 | add = False 55 | break 56 | if neighsite.specie.symbol == "Li": 57 | nLi += 1 58 | 59 | if nLi >= 2: 60 | print("nLi >= 2") 61 | add = False 62 | 63 | if add: 64 | fill_s.append(vacsite.specie, vacsite.frac_coords) 65 | vaclist.append([xi, yi, zi]) 66 | 67 | print("\nResults\n" + 7 * "-") 68 | print("Write file 'POSCAR_fill.vasp': initial structure + vacant positions") 69 | Poscar(fill_s).write_file("POSCAR_fill.vasp") 70 | print("Write file 'POSCAR_grid.vasp': grid positions (%d atoms)" % len(grid)) 71 | Poscar(grid).write_file("POSCAR_grid.vasp") 72 | print("\nNumber of positions : %d" % len(vaclist)) 73 | if len(vaclist) < 30: 74 | for xyz in vaclist: 75 | print((3 * "%8.3f") % tuple(xyz)) 76 | 77 | if __name__ == "__main__": 78 | look4VacantPosition() 79 | 80 | -------------------------------------------------------------------------------- /Various/README.rst: -------------------------------------------------------------------------------- 1 | Various scripts 2 | =============== 3 | 4 | vmdmo.py 5 | Python script that aims to set up a VMD script to load one or a series of cube files 6 | and visualize the MO in VMD (Visual Molecular Dynamics). 7 | 8 | spectre.py 9 | Python module for spheric to cartesian and cartesian to spheric coordinates 10 | calculations. 11 | 12 | groupes.py 13 | Python module for using symmetry tools when studying molecular system. 14 | 15 | supFile.py 16 | Python script which look for specific files which correpond to a mask and ask for 17 | deletion. 18 | 19 | bigfiles.py 20 | Pyhton script which look for bigest files in a directory and 21 | subdirectories. 22 | 23 | zipFile.py 24 | Python script which look for specific files which correpond to a mask and zip them. 25 | 26 | convert.py 27 | A simple script to resize a bunch of image using PIL. Look at ImageMagick 28 | if available. 29 | -------------------------------------------------------------------------------- /Various/ads.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | from pymatgen.core import Molecule, SymmOp 5 | import numpy as np 6 | 7 | 8 | def local_frame(mol, origin=0, xat=1, yat=2, barycenter=False): 9 | """ 10 | Return a new molecule object where the atoms are in the local frame defined 11 | from the three atoms given as argument. 12 | 13 | Args: 14 | mol (Molecule): The molecule to adsorb. 15 | origin (int): origin of the frame 16 | xat (int): atom at the end of x axis 17 | yat (int): third atom to define the frame 18 | 19 | Retuns 20 | Returns a new molecule object with coordinates in the frame. 21 | 22 | """ 23 | 24 | # set up the local frame 25 | u = mol[xat - 1].coords - mol[origin - 1].coords 26 | u /= np.linalg.norm(u) 27 | v = mol[yat - 1].coords - mol[origin - 1].coords 28 | v = v - np.dot(u, v) * u 29 | v /= np.linalg.norm(v) 30 | w = np.cross(u, v) 31 | 32 | mat = np.array([u, v, w]) 33 | 34 | # move molecule around an origin 35 | G = np.zeros(3) 36 | if barycenter is True: 37 | G = mol.cart_coords.sum(axis=0) / len(mol) 38 | elif len(barycenter) == 3: 39 | G = np.array(barycenter) 40 | 41 | # new coordinates in the local frame 42 | newcoords = np.dot(mol.cart_coords - G, mat.T) 43 | 44 | return Molecule(mol.species, newcoords, mol.charge, mol.spin_multiplicity, 45 | mol.site_properties) 46 | 47 | 48 | def adsorb(mol, slab, atmol, atslab, z, img=None, shift=[0., 0., 0.]): 49 | """ 50 | Add molecule `mol` on the surface `slab` at a distance from the slab `z`. The 51 | list `atmol` defines the atoms of the molecule which will be adsorbed. The list 52 | `atslab` define the adsorption site on the slab. The function assumes that the slab 53 | surface is perpendicular to the z axes. 54 | 55 | Args: 56 | mol (Molecule): The molecule to adsorb. 57 | slab (Slab): The slab on which adsorption is done. 58 | atmol ([int]): Sequence of atom's numbers of the molecule which define 59 | the anchor point of the molecule. 60 | atslab ([int]): Sequance of atom's numbers of the slab which define the 61 | adsorption site. 62 | z (float): distance between the barycenters of atslab and atmol atoms. 63 | img (Nx3 array): translation vectors which define periodic images of 64 | atoms belonging to the slab. 65 | shift ([x, y, z]): add a translation vector to the molecule 66 | 67 | All parameters are mandatory, the periodic images definition (img), the shift 68 | vector and the verbosity control. 69 | 70 | The adsorption site type on the slab is defined by the `atslab` argument.. 71 | This list contains the atom number of atoms belonging to the slab on which 72 | we will adsorb the molecule. 73 | 74 | * 1 atom : top site 75 | * 2 atom : bridge site (2fold site) 76 | * 3 atom : hollow bridge site (3fold site) 77 | * 4 atom : 4 fold site 78 | * ... 79 | 80 | The img argument define for each atom present in the atslab list, the 81 | periodic image which has to be used in order to build the adsorption site. 82 | 83 | The z axes will be kept perpendicular to the slab. Thus take care to prepare the 84 | molecule in a way that the adsorption will be done along the z axes. The distance 85 | z, will be the distance between the atoms of the molecule defined by the parameter 86 | `atmol` and the barycenter of the slab's atoms defined by the `atslab` parameter. The 87 | barycenter is not computed using atoms mass. 88 | 89 | """ 90 | 91 | # check 92 | # ----- 93 | if not isinstance(mol, Molecule): 94 | print("mol must be a Molecule object") 95 | exit(1) 96 | if not isinstance(atmol, list): 97 | print("atmol must be a list of atom number") 98 | print("atmol : {0}".format(atmol)) 99 | exit(1) 100 | if img is not None: 101 | if len(img) != len(atslab): 102 | print("You must give imaging information for all atslab atoms") 103 | exit(1) 104 | if not isinstance(atslab, list): 105 | print("atslab must be a list of atom number") 106 | print("atslab : {0}".format(atslab)) 107 | exit(1) 108 | if not isinstance(shift, list) and not isinstance(shift, np.ndarray): 109 | print("shift must be a list or a ndarray") 110 | exit(1) 111 | elif len(shift) != 3: 112 | print("shift length must be 3") 113 | print("len(shift) = " + str(len(shift))) 114 | exit(1) 115 | 116 | # default value for periodic images 117 | if img is None: 118 | img = [[0., 0., 0.] for i in range(len(atslab))] 119 | 120 | # convert shift to numpy array 121 | if not isinstance(shift, np.ndarray): 122 | shift = np.array(shift) 123 | 124 | # atom numbers start at 0 125 | atslab = [iat - 1 for iat in atslab] 126 | atmol = [iat - 1 for iat in atmol] 127 | 128 | # move slab's atoms of the adsorption site according to img vectors 129 | # xyz_site are the coordinate of slab's atom which define the asorption site 130 | xyz_site = list() 131 | for i, iat in enumerate(atslab): 132 | imgtrans = np.zeros(3) 133 | for k in range(3): 134 | imgtrans += img[i][k] * slab.lattice.matrix[k] 135 | xyz_site.append(slab[iat].coords + imgtrans) 136 | xyz_site = np.array(xyz_site) 137 | 138 | # coordinates of the barycenter of the adsorption site : Gslab 139 | Gslab = xyz_site.mean(axis=0) 140 | 141 | # coordinate of the barycenter of molecule's atoms : Gmol 142 | Gmol = np.zeros(3) 143 | for iat in atmol: 144 | Gmol += mol[iat].coords 145 | Gmol /= float(len(atmol)) 146 | 147 | # vertical vector along which the adsorption is done 148 | if len(atslab) == 1: 149 | # top site: adsorption along z axis 150 | ztrans = slab.normal 151 | 152 | elif len(atslab) == 2: 153 | # bridge or 2-fold site adsorption perpendicularly to the vector 154 | # joining the 2 slab atoms 155 | u = xyz_site[1] - xyz_site[0] 156 | u /= np.sqrt((u**2).sum()) 157 | 158 | ztrans = slab.normal - np.dot(u, slab.normal) * u 159 | 160 | elif len(atslab) == 3: 161 | # 3-fold site: ztrans is obtained from a cross product 162 | u = xyz_site[1] - xyz_site[0] 163 | u /= np.sqrt((u**2).sum()) 164 | 165 | v = xyz_site[2] - xyz_site[0] 166 | v = v - np.dot(u, v) * v 167 | v /= np.sqrt((v**2).sum()) 168 | 169 | ztrans = np.cross(u, v) 170 | 171 | # ztrans and z axes in the same direction 172 | if np.dot(ztrans, np.array([0., 0., 1.])) < 0: 173 | ztrans *= -1. 174 | 175 | else: 176 | # TODO: average plane 177 | print("WARNING : z shift along z axes from barycenter of atoms") 178 | ztrans = slab.normal 179 | 180 | # translate the molecule above the adsorption site 181 | vtrans = Gslab - Gmol + z * ztrans + shift 182 | trans = SymmOp.from_axis_angle_and_translation(axis=np.array([1., 0., 0.]), 183 | angle=0., 184 | translation_vec=vtrans) 185 | mol.apply_operation(trans) 186 | 187 | # create the new slab with the adsorbed molecule 188 | for specie, coords in zip(mol.species, mol.cart_coords): 189 | slab.append(specie, coords, coords_are_cartesian=True) 190 | 191 | return slab 192 | 193 | 194 | if __name__ == "__main__": 195 | import pymatgen as mg 196 | from pymatgen.core.surface import Slab 197 | 198 | slabfile = "./CONTCAR_1x1.vasp" 199 | # slabfile = "./CONTCAR" 200 | s = mg.Structure.from_file(slabfile) 201 | slab = Slab(s.lattice, s.species, s.frac_coords, 202 | miller_index=[0, 0, 1], 203 | oriented_unit_cell=s, 204 | shift=0., 205 | scale_factor=[]) 206 | 207 | # ------------------------------ 208 | molxyz = "./h2O.xyz" 209 | mol = mg.Molecule.from_file(molxyz) 210 | G = [0, 0, 0] 211 | mol = local_frame(mol, origin=1, xat=0, yat=2, barycenter=G) 212 | 213 | op = SymmOp.from_origin_axis_angle(mol[1].coords, axis=[0, 1, 0], angle=-90) 214 | mol.apply_operation(op) 215 | 216 | ads_slab = adsorb(mol, slab.copy(), atmol=[1], atslab=[22], z=0.) 217 | mg.io.vasp.inputs.Poscar(ads_slab).write_file("ads_H2O.vasp") 218 | 219 | 220 | exit() 221 | # ------------------------------- 222 | # monolayer H2O 223 | ads_slab = adsorb(mol, slab.copy(), atmol=[2], atslab=[6], z=1.) 224 | 225 | op = SymmOp.from_origin_axis_angle(mol[1].coords, axis=[0, 0, 1], angle=180) 226 | mol.apply_operation(op) 227 | ads_slab = adsorb(mol, ads_slab, atmol=[2], atslab=[15], z=-1.) 228 | 229 | mg.io.vasp.inputs.Poscar(ads_slab).write_file("ads1x1_H2O.vasp") 230 | 231 | 232 | -------------------------------------------------------------------------------- /Various/bigfiles.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | BigFiles 6 | -------- 7 | 8 | print the first bigest files in all subdirectories of a given path 9 | 10 | SYNTAX 11 | bigfiles [OPTIONS] ... [PATH] 12 | 13 | DESCRIPTION 14 | Print the first 20 bigest files in directory [PATH] and in all subdirectories of 15 | [PATH]. Default [PATH] is the current working directory. 16 | 17 | -h, --help 18 | print this help 19 | 20 | -n, --nfiles=N 21 | output the first N bigest files, instead if the first 20. If N is negative, 22 | print all files. 23 | 24 | EXAMPLES 25 | bigfile -h 26 | bigfile -n 50 27 | bigfile ./another/directory/ 28 | bigfile -n -1 29 | bigfile -n 20 ./anotherdirectory 30 | """ 31 | 32 | __licence__ = "GPL" 33 | __author__ = "Germain Vallverdu " 34 | 35 | import doctest 36 | import os 37 | import sys 38 | 39 | KILO_OCTET = 1024 40 | MEGA_OCTET = 1048576 41 | GIGA_OCTET = 1073741824 42 | TERA_OCTET = 1099511627776 43 | 44 | def humanSize(taille): 45 | """ return a byte number in human readable format (1ko 234Mo 2Go 46 | 47 | >>> humanSize( 345) 48 | '345 o' 49 | >>> humanSize( 123478) 50 | '120.6 ko' 51 | >>> humanSize( 983435743) 52 | '937.9 Mo' 53 | >>> humanSize( 12983435743) 54 | '12.1 Go' 55 | >>> humanSize( 755812983435743) 56 | '687.4 To' 57 | 58 | """ 59 | taille = float(taille) 60 | if taille >= TERA_OCTET: 61 | size = "%.1f To" % (taille / TERA_OCTET) 62 | elif taille >= GIGA_OCTET: 63 | size = "%.1f Go" % (taille / GIGA_OCTET) 64 | elif taille >= MEGA_OCTET: 65 | size = "%.1f Mo" % (taille / MEGA_OCTET) 66 | elif taille >= KILO_OCTET: 67 | size = "%.1f ko" % (taille / KILO_OCTET) 68 | else: 69 | size = "%.0f o" % taille 70 | 71 | return size 72 | 73 | def BigFiles( dossier = "./", nmax = 20): 74 | """ print the first bigest files in all subdirectories of a given path 75 | 76 | arguments : 77 | * dossier : path where you want to list bigest files 78 | * nmax : maximum number of files you want BigFiles to list 79 | """ 80 | 81 | fichier = list() 82 | tailleTotale = 0 83 | nFiles = 0 84 | for root, dirs, files in os.walk(dossier): 85 | for name in files: 86 | if not os.path.isfile(os.path.join(root,name)): continue 87 | taille = os.path.getsize(os.path.join(root, name)) 88 | nFiles += 1 89 | tailleTotale += taille 90 | fichier.append({"nom":name, "dossier":root, "taille":taille}) 91 | 92 | print("\n" + " * * * BigFiles * * *".center(80) + "\n") 93 | print("--------------------------------------------------------------------------------") 94 | print(" Analyse du dossier : " + dossier) 95 | print(" Nombre de fichiers traités : " + str(nFiles)) 96 | print(" Taille totale des fichiers : " + humanSize(tailleTotale)) 97 | print("--------------------------------------------------------------------------------\n") 98 | 99 | # sort files and print the first nmax 100 | sorted_fichier = sorted( fichier, key = lambda f:f["taille"], reverse = True) 101 | for i, f in enumerate(sorted_fichier): 102 | print(str(i+1).rjust(6) + humanSize(f["taille"]).rjust(10) + f["nom"].rjust(30) + " " + f["dossier"]) 103 | if i == (nmax-1): break 104 | 105 | if __name__ == "__main__": 106 | doctest.testmod() 107 | 108 | # -------------------------------------------------------- 109 | # default values 110 | # -------------------------------------------------------- 111 | dossier = "./" 112 | nmax = 20 113 | 114 | # -------------------------------------------------------- 115 | # get options 116 | # -------------------------------------------------------- 117 | narg = len(sys.argv) 118 | if narg > 1: 119 | args = sys.argv 120 | i = 1 121 | while i < narg: 122 | if args[i] == "-h" or args[i] == "--help": 123 | print(__doc__) 124 | exit(0) 125 | elif args[i] == "-n" or args[i] == "--nfiles": 126 | try: 127 | nmax = int(args[i+1]) 128 | except ValueError: 129 | print("\nError : bad arguments " + args[i]) 130 | print(" try : " + args[0] + " --help\n") 131 | exit(1) 132 | except IndexError: 133 | print("\nError : bad arguments " + args[i]) 134 | print(" try : " + args[0] + " --help\n") 135 | exit(1) 136 | i += 2 137 | 138 | elif args[i] == "-v": 139 | i += 1 140 | else: 141 | if i == narg - 1: 142 | dossier = args[i] 143 | else: 144 | print(args) 145 | print("\nError : bad arguments") 146 | print(" try : " + args[0] + " --help\n") 147 | exit(1) 148 | i += 1 149 | 150 | BigFiles(dossier, nmax) 151 | 152 | -------------------------------------------------------------------------------- /Various/convert.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """ 4 | Resize all images according to a given width. 5 | Look at ImageMagick if available on your OS. 6 | """ 7 | 8 | __author__ = "Germain Salvato Vallverdu" 9 | 10 | import os 11 | import shutil 12 | import argparse 13 | 14 | try: 15 | from PIL import Image 16 | except ImportError: 17 | print("The module PIL is needed !! sorry") 18 | raise ImportError("Need module PIL") 19 | 20 | 21 | def list_img_files(folder="./", ext=(".jpg", ".jpeg", ".png", ".gif")): 22 | """ Return a list of image files according to ext list """ 23 | files = os.listdir(folder) 24 | for f in files: 25 | if f[0] == ".": 26 | files.remove(f) 27 | 28 | return [f for f in files if any(f.lower().endswith(e) for e in ext)] 29 | 30 | def get_options(): 31 | """ get options from command lines """ 32 | 33 | parser = argparse.ArgumentParser(description='Read options from the command line') 34 | parser.add_argument("-t", "--to", 35 | help="final directory where resized images will be stored", 36 | metavar="PATH", 37 | default="./convert") 38 | parser.add_argument("-f", "--from", 39 | help="working directory from where images to be resized have to be read", 40 | metavar="PATH", 41 | default="./") 42 | parser.add_argument("width", 43 | help="Desired width of resized images", 44 | metavar="WIDTH", 45 | default=500, 46 | type=int) 47 | 48 | return parser.parse_args() 49 | 50 | if __name__ == "__main__": 51 | 52 | # manage options 53 | args = vars(get_options()) # convert to dict 54 | final_width = args["width"] 55 | final_dir = args["to"] 56 | workdir = args["from"] 57 | 58 | if os.path.exists(final_dir): 59 | print("Directory '{}' exists. Remove or rename it first !".format(final_dir)) 60 | answer = input("Delete it ? (y/n) ") 61 | n = 0 62 | while answer.strip() != "n" and answer.strip() != "y" and n != 4: 63 | print("Please say 'y' for Yes, or 'n' for No") 64 | answer = input("Delete it ? (y/n) ") 65 | n += 1 66 | 67 | if answer == "y": 68 | shutil.rmtree(final_dir) 69 | print("Remove {}".format(final_dir)) 70 | else: 71 | print("Nothing, was done") 72 | print("Remove or rename your output dir first") 73 | exit(0) 74 | 75 | os.mkdir(final_dir) 76 | 77 | for fimg in list_img_files(workdir): 78 | print(fimg) 79 | 80 | # open image file 81 | img = Image.open(fimg) 82 | w, h = img.size 83 | 84 | # compute resize factor according to the width 85 | rfactor = final_width / w 86 | 87 | # new width, height and image 88 | nw, nh = int(rfactor * w), int(rfactor * h) 89 | rimg = img.resize((nw, nh)) 90 | 91 | # save image to new dir 92 | rimg.save(os.path.join(final_dir, fimg)) 93 | -------------------------------------------------------------------------------- /Various/groupes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | Modules groupes 6 | =============== 7 | 8 | Contact : Germain Vallverdu 9 | 10 | Description 11 | ----------- 12 | 13 | Ce module a pour but de decomposer rapidement une representation reductible en 14 | representations irreductibles. Il met a disposition la classe `Groupe` qui contient la 15 | methode `Groupe.reduire(rep)` permettant de reduire une representation et la methode 16 | `Groupe.testGroupe()` qui test les donnees contenu dans l'objet (dimension des RI, 17 | orthognonalite des RI ...). 18 | 19 | Tous les groupes ne sont pas disponnibles. Groupes disponnibles : 20 | 21 | * C2v 22 | * C3v 23 | * C4v 24 | * D3h 25 | * D4h 26 | * D2h 27 | 28 | Exemple d'utilisation 29 | --------------------- 30 | 31 | >>> from groupes import c4v 32 | >>> rep = [4, 0, 0, 2, 0] 33 | >>> print(c4v) 34 | C4v | 1E 2C4 1C2 2sigma_v 2sigma_d 35 | ------------------------------------------------------------ 36 | A1 | 1 1 1 1 1 37 | A2 | 1 1 1 -1 -1 38 | B1 | 1 -1 1 1 -1 39 | B2 | 1 -1 1 -1 1 40 | E | 2 0 -2 0 0 41 | >>> c4v.ordre 42 | 8 43 | >>> c4v.reduce(rep) 44 | 1 A1 + 1 B1 + 1 E 45 | 46 | Licence 47 | ------- 48 | 49 | GPL 50 | 51 | """ 52 | 53 | import numpy as np 54 | 55 | __licence__ = "GPL" 56 | __author__ = "Germain Vallverdu " 57 | __date__ = "Juin 2012" 58 | 59 | class Groupe(object): 60 | """ groupe ponctuel """ 61 | 62 | def __init__(self, name = "", ordre = -1 ): 63 | """ init group """ 64 | 65 | # nom du groupe 66 | self.name = name 67 | 68 | # ordre du groupe 69 | self.ordre = ordre 70 | 71 | # Representation irreductible 72 | self.RI = dict() 73 | self.ordreRI = list() 74 | 75 | # liste des operations de symetrie 76 | self.Op = list() 77 | 78 | # classes d'equivalences 79 | self.classes = dict() 80 | self.ordreClasses = list() 81 | 82 | def reduce(self, rep): 83 | """ reduit la representation rep """ 84 | 85 | if not isinstance(rep, list) and not isinstance(rep, np.ndarray): 86 | raise TypeError("rep doit etre une liste") 87 | 88 | if len(rep) != len(self.classes.keys()): 89 | raise ValueError("dimension de rep non coherante") 90 | 91 | nRI = dict() 92 | for RI in self.RI: 93 | nRI[RI] = 0 94 | for i, classe in enumerate(self.ordreClasses): 95 | nRI[RI] += self.classes[classe] * self.RI[RI][i] * rep[i] 96 | nRI[RI] /= self.ordre 97 | 98 | ligne = "" 99 | for RI in self.ordreRI: 100 | if nRI[RI] == 0: 101 | continue 102 | ligne += "{0} {1} + ".format(nRI[RI], RI) 103 | print(ligne[:-3]) 104 | 105 | def testGroupe(self): 106 | """ Teste les donnees du groupes """ 107 | 108 | if self.ordre == -1: 109 | raise NameError(self.name + " : ordre inconnu") 110 | 111 | if self.name == "": 112 | raise NameError("nom inconnu") 113 | 114 | if self.classes == {}: 115 | raise NameError(self.name + " : classes d'equivalence inconnuees") 116 | 117 | if self.ordreClasses == {}: 118 | raise NameError(self.name + " : ordre des classes d'equivalence inconnuees") 119 | 120 | if self.Op == []: 121 | raise NameError(self.name + " : Operations inconnues") 122 | 123 | if self.RI == {}: 124 | raise NameError(self.name + " : RI inconnues") 125 | 126 | if self.ordreRI == []: 127 | raise NameError(self.name + " : ordre RI inconnues") 128 | 129 | # calcule l'ordre a partir de la definition des classes 130 | ordre = 0 131 | for clef in self.classes: 132 | ordre += self.classes[clef] 133 | 134 | if ordre != self.ordre: 135 | raise ValueError(self.name + " : Ordre du groupe non coherant avec les classes d'equivalence") 136 | 137 | # verifie l'ordre du groupe et le nombre d'operation 138 | if ordre != len(self.Op): 139 | raise ValueError(self.name + " : Ordre du groupe non coherant avec les operations de symetrie") 140 | 141 | # verifie l'ordre des classes 142 | if len(self.ordreClasses) != len(self.classes.keys()): 143 | raise ValueError(self.name + " : Nombre de classes incoherent entre l'ordre des classes et les classes") 144 | 145 | # verifie l'ordre des RI 146 | if len(self.ordreRI) != len(self.RI.keys()): 147 | raise ValueError(self.name + " : Nombre de RI incoherent entre l'ordre des RI et les RI") 148 | 149 | # verifie les dimensions des RI 150 | for RI in self.RI: 151 | if len(self.RI[RI]) != len(self.classes.keys()): 152 | raise ValueError(self.name + " : RI " + str(RI) + " non coherent avec le nombre de classes") 153 | 154 | # verifie l'orthogonalite des RI 155 | for RIi in self.ordreRI: 156 | for RIj in self.ordreRI: 157 | scal = 0 158 | for i, classe in enumerate(self.ordreClasses): 159 | scal += self.classes[classe] * self.RI[RIi][i] * self.RI[RIj][i] 160 | if RIi == RIj and not scal / self.ordre == 1: 161 | raise ValueError("groupe : " + self.name + " RI " + RIi + " et RI " + RIj + " non normee") 162 | elif RIi != RIj and scal != 0: 163 | raise ValueError("groupe : " + self.name + "RI " + RIi + " et RI " + RIj + " non orthonormee") 164 | 165 | return "ok" 166 | 167 | def __str__(self): 168 | """ print group """ 169 | 170 | ligne = self.name.center(5) + " | " 171 | for clef in self.ordreClasses: 172 | ligne += "{0}{1}".format(self.classes[clef], clef).center(9) 173 | ligne += "\n" 174 | 175 | ligne += "".join(60 * ["-"]) + "\n" 176 | 177 | for RI in self.ordreRI: 178 | ligne += RI.center(5) + " | " 179 | for val in self.RI[RI]: 180 | ligne += str(val).center(9) 181 | ligne += "\n" 182 | 183 | return ligne 184 | 185 | # ----------------------------------------------------------------------------- 186 | # 187 | # Groupe C2v 188 | # 189 | # ----------------------------------------------------------------------------- 190 | c2v = Groupe(name = "C2v", ordre = 4) 191 | 192 | c2v.classes["E"] = 1 193 | c2v.classes["C2"] = 1 194 | c2v.classes["sigma_xz"] = 1 195 | c2v.classes["sigma_yz"] = 1 196 | c2v.ordreClasses = ["E", "C2", "sigma_xz", "sigma_yz"] 197 | 198 | c2v.Op = c2v.ordreClasses 199 | 200 | c2v.RI["A1"] = [1, 1, 1, 1] 201 | c2v.RI["A2"] = [1, 1, -1, -1] 202 | c2v.RI["B1"] = [1, -1, 1, -1] 203 | c2v.RI["B2"] = [1, -1, -1, 1] 204 | 205 | c2v.ordreRI = ["A1", "A2", "B1", "B2"] 206 | 207 | # ----------------------------------------------------------------------------- 208 | # 209 | # Groupe C3v 210 | # 211 | # ----------------------------------------------------------------------------- 212 | c3v = Groupe(name = "C3v", ordre = 6) 213 | 214 | c3v.classes["E"] = 1 215 | c3v.classes["C3"] = 2 216 | c3v.classes["sigma_v"] = 3 217 | c3v.ordreClasses = ["E", "C3", "sigma_v"] 218 | 219 | c3v.Op = ["E", "C_3^1", "C_3^2", "sigma_1", "sigma_2", "sigma_3"] 220 | 221 | c3v.RI["A1"] = [1, 1, 1] 222 | c3v.RI["A2"] = [1, 1, -1] 223 | c3v.RI["E"] = [2, -1, 0] 224 | 225 | c3v.ordreRI = ["A1", "A2", "E"] 226 | 227 | # ----------------------------------------------------------------------------- 228 | # 229 | # Groupe C4v 230 | # 231 | # ----------------------------------------------------------------------------- 232 | c4v = Groupe(name = "C4v", ordre = 8) 233 | 234 | c4v.classes["E"] = 1 235 | c4v.classes["C4"] = 2 236 | c4v.classes["C2"] = 1 237 | c4v.classes["sigma_v"] = 2 238 | c4v.classes["sigma_d"] = 2 239 | c4v.ordreClasses = ["E", "C4", "C2", "sigma_v", "sigma_d"] 240 | 241 | c4v.Op = ["E", "C_4^1", "C_4^3", "C2", "sigma_v1", "sigma_v2", "sigma_d1", "sigma_d2"] 242 | 243 | c4v.RI["A1"] = [ 1, 1, 1, 1, 1] 244 | c4v.RI["A2"] = [ 1, 1, 1, -1, -1] 245 | c4v.RI["B1"] = [ 1, -1, 1, 1, -1] 246 | c4v.RI["B2"] = [ 1, -1, 1, -1, 1] 247 | c4v.RI["E"] = [ 2, 0, -2, 0, 0] 248 | 249 | c4v.ordreRI = ["A1", "A2", "B1", "B2", "E"] 250 | 251 | # ----------------------------------------------------------------------------- 252 | # 253 | # Groupe D2h 254 | # 255 | # ----------------------------------------------------------------------------- 256 | d2h = Groupe(name = "D2h", ordre = 8) 257 | 258 | d2h.classes["E"] = 1 259 | d2h.classes["C2(z)"] = 1 260 | d2h.classes["C2(y)"] = 1 261 | d2h.classes["C2(x)"] = 1 262 | d2h.classes["i"] = 1 263 | d2h.classes["sigma_xy"] = 1 264 | d2h.classes["sigma_xz"] = 1 265 | d2h.classes["sigma_yz"] = 1 266 | d2h.ordreClasses = ["E", "C2(z)", "C2(y)", "C2(x)", "i", "sigma_xy", "sigma_xz", "sigma_yz"] 267 | d2h.Op = ["E", "C2(z)", "C2(y)", "C2(x)", "i", "sigma_xy", "sigma_xz", "sigma_yz"] 268 | 269 | d2h.RI["Ag"] = [ 1, 1, 1, 1, 1, 1, 1, 1] 270 | d2h.RI["B1g"] = [ 1, 1, -1, -1, 1, 1, -1, -1] 271 | d2h.RI["B2g"] = [ 1, -1, 1, -1, 1, -1, 1, -1] 272 | d2h.RI["B3g"] = [ 1, -1, -1, 1, 1, -1, -1, 1] 273 | d2h.RI["Au"] = [ 1, 1, 1, 1, -1, -1, -1, -1] 274 | d2h.RI["B1u"] = [ 1, 1, -1, -1, -1, -1, 1, 1] 275 | d2h.RI["B2u"] = [ 1, -1, 1, -1, -1, 1, -1, 1] 276 | d2h.RI["B3u"] = [ 1, -1, -1, 1, -1, 1, 1, -1] 277 | 278 | d2h.ordreRI = ["Ag", "B1g", "B2g", "B3g", "Au", "B1u", "B2u", "B3u"] 279 | 280 | # ----------------------------------------------------------------------------- 281 | # 282 | # Groupe D3h 283 | # 284 | # ----------------------------------------------------------------------------- 285 | d3h = Groupe(name = "D3h", ordre = 12) 286 | 287 | d3h.classes["E"] = 1 288 | d3h.classes["C3"] = 2 289 | d3h.classes["C2"] = 3 290 | d3h.classes["sigma_h"] = 1 291 | d3h.classes["S3"] = 2 292 | d3h.classes["sigma"] = 3 293 | d3h.ordreClasses = ["E", "C3", "C2", "sigma_h", "S3", "sigma"] 294 | 295 | d3h.Op = ["E", "C_3^1", "C_3^2", "C_2a", "C_2a", "C_2a", "sigma_h", "S_3^1", "S_3^5", "sigma_1", "sigma_2", "sigma_3"] 296 | 297 | d3h.RI["A1'"] = [ 1, 1, 1, 1, 1, 1] 298 | d3h.RI["A2'"] = [ 1, 1, -1, 1, 1, -1] 299 | d3h.RI["E'"] = [ 2, -1, 0, 2, -1, 0] 300 | d3h.RI["A1''"] = [ 1, 1, 1, -1, -1, -1] 301 | d3h.RI["A2''"] = [ 1, 1, -1, -1, -1, 1] 302 | d3h.RI["E''"] = [ 2, -1, 0, -2, 1, 0] 303 | 304 | d3h.ordreRI = ["A1'", "A2'", "E'", "A1''", "A2''", "E''"] 305 | 306 | # ----------------------------------------------------------------------------- 307 | # 308 | # Groupe D4h 309 | # 310 | # ----------------------------------------------------------------------------- 311 | d4h = Groupe(name = "D4h", ordre = 16) 312 | 313 | d4h.classes["E"] = 1 314 | d4h.classes["C4"] = 2 315 | d4h.classes["C2"] = 1 316 | d4h.classes["C2'"] = 2 317 | d4h.classes["C2\""] = 2 318 | d4h.classes["i"] = 1 319 | d4h.classes["S4"] = 2 320 | d4h.classes["sigma_h"] = 1 321 | d4h.classes["sigma_v"] = 2 322 | d4h.classes["sigma_d"] = 2 323 | d4h.ordreClasses = ["E", "C4", "C2", "C2'", "C2\"", "i", "S4", "sigma_h", "sigma_v", "sigma_d"] 324 | 325 | d4h.Op = ["E", "C_4^1", "C_4^3", "C2", "C2'x", "C2'y", "C2\"", "C2\"", "i", 326 | "S_4^1", "S_4^3", "sigma_h", "sigma_v1", "sigma_v2", "sigma_d1", "sigma_d2"] 327 | 328 | d4h.RI["A1g"] = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 329 | d4h.RI["A2g"] = [ 1, 1, 1, -1, -1, 1, 1, 1, -1, -1] 330 | d4h.RI["B1g"] = [ 1, -1, 1, 1, -1, 1, -1, 1, 1, -1] 331 | d4h.RI["B2g"] = [ 1, -1, 1, -1, 1, 1, -1, 1, -1, 1] 332 | d4h.RI["Eg"] = [ 2, 0, -2, 0, 0, 2, 0, -2, 0, 0] 333 | d4h.RI["A1u"] = [ 1, 1, 1, 1, 1, -1, -1, -1, -1, -1] 334 | d4h.RI["A2u"] = [ 1, 1, 1, -1, -1, -1, -1, -1, 1, 1] 335 | d4h.RI["B1u"] = [ 1, -1, 1, 1, -1, -1, 1, -1, -1, 1] 336 | d4h.RI["B2u"] = [ 1, -1, 1, -1, 1, -1, 1, -1, 1, -1] 337 | d4h.RI["Eu"] = [ 2, 0, -2, 0, 0, -2, 0, 2, 0, 0] 338 | 339 | d4h.ordreRI = ["A1g", "A2g", "B1g", "B2g", "Eg", "A1u", "A2u", "B1u", "B2u", "Eu"] 340 | 341 | # ----------------------------------------------------------------------------- 342 | # 343 | # Groupe D6h 344 | # 345 | # ----------------------------------------------------------------------------- 346 | d6h = Groupe(name = "D6h", ordre = 24) 347 | 348 | d6h.classes["E"] = 1 349 | d6h.classes["C6"] = 2 350 | d6h.classes["C3"] = 2 351 | d6h.classes["C2"] = 1 352 | d6h.classes["C2'"] = 3 353 | d6h.classes["C2\""] = 3 354 | d6h.classes["i"] = 1 355 | d6h.classes["S3"] = 2 356 | d6h.classes["S6"] = 2 357 | d6h.classes["sigma_h"] = 1 358 | d6h.classes["sigma_d"] = 3 359 | d6h.classes["sigma_v"] = 3 360 | 361 | d6h.ordreClasses = ["E", "C6", "C3", "C2", "C2'", "C2\"", "i", "S3","S6", "sigma_h", "sigma_d", "sigma_v"] 362 | 363 | d6h.Op = ["E", "C6^1", "C6^5", "C3^1", "C3^2", "C2", "C'2", "C'2", "C'2", 364 | "C\"2", "C\"2", "C\"2", "i", "S3^1", "S3^5", "S6^1", "S6^5", "sigma_h", 365 | "sigma_d1", "sigma_d2", "sigma_d3", "sigma_v1", "sigma_v2", "sigma_v3"] 366 | 367 | d6h.RI["A1g"] = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 368 | d6h.RI["A2g"] = [ 1, 1, 1, 1,-1,-1, 1, 1, 1, 1,-1,-1] 369 | d6h.RI["B1g"] = [ 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1] 370 | d6h.RI["B2g"] = [ 1,-1, 1,-1,-1, 1, 1,-1, 1,-1,-1, 1] 371 | d6h.RI["E1g"] = [ 2, 1,-1,-2, 0, 0, 2, 1,-1,-2, 0, 0] 372 | d6h.RI["E2g"] = [ 2,-1,-1, 2, 0, 0, 2,-1,-1, 2, 0, 0] 373 | d6h.RI["A1u"] = [ 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1,-1] 374 | d6h.RI["A2u"] = [ 1, 1, 1, 1,-1,-1,-1,-1,-1,-1, 1, 1] 375 | d6h.RI["B1u"] = [ 1,-1, 1,-1, 1,-1,-1, 1,-1, 1,-1, 1] 376 | d6h.RI["B2u"] = [ 1,-1, 1,-1,-1, 1,-1, 1,-1, 1, 1,-1] 377 | d6h.RI["E1u"] = [ 2, 1,-1,-2, 0, 0,-2,-1, 1, 2, 0, 0] 378 | d6h.RI["E2u"] = [ 2,-1,-1, 2, 0, 0,-2, 1, 1,-2, 0, 0] 379 | 380 | d6h.ordreRI = ["A1g", "A2g", "B1g", "B2g", "E1g", "E2g", "A1u", "A2u", "B1u", 381 | "B2u", "E1u", "E2u"] 382 | 383 | # ----------------------------------------------------------------------------- 384 | # ----------------------------------------------------------------------------- 385 | if __name__ == "__main__": 386 | """ Test des donnees saisies """ 387 | 388 | print(" --- TEST DES DONNEES SAISIEES --- ") 389 | print("Groupes :") 390 | print(" {0} : {1}".format("C2v", c2v.testGroupe())) 391 | print(" {0} : {1}".format("C3v", c3v.testGroupe())) 392 | print(" {0} : {1}".format("C4v", c4v.testGroupe())) 393 | print(" {0} : {1}".format("D3h", d3h.testGroupe())) 394 | print(" {0} : {1}".format("D4h", d4h.testGroupe())) 395 | print(" {0} : {1}".format("D2h", d2h.testGroupe())) 396 | print(" {0} : {1}".format("D6h", d6h.testGroupe())) 397 | 398 | -------------------------------------------------------------------------------- /Various/spheric.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | Conversion en coordonnees spheriques 6 | ------------------------------------ 7 | 8 | Relation entre les coordonnées : 9 | 10 | .. 11 | 12 | x = r * sin theta * cos phi 13 | y = r * sin theta * sin phi 14 | z = r * cos theta 15 | 16 | """ 17 | 18 | import doctest 19 | from math import sin, cos, degrees, radians, sqrt, acos, pi 20 | 21 | def spheric2cart(r, theta, phi, unit = "deg"): 22 | """ Calcule les coordonnees cartesiennes x, y, z d'un point M en fonction de ses 23 | coordonnees spheriques r, theta, phi. 24 | 25 | arguments : 26 | 27 | * r : rayon 28 | * theta : angle entre le vecteur OM et l'axe z 29 | * phi : angle antre l'axe x et la projection du vecteur OM dans le plan xOy 30 | * unit : precise si les angles sont donnes en degres (deg) ou radians (rad) 31 | 32 | """ 33 | 34 | if unit.strip().lower() == "deg": 35 | th = radians(theta) 36 | ph = radians(phi) 37 | elif unit.strip().lower() == "rad": 38 | th = theta 39 | ph = phi 40 | else: 41 | raise NameError("unit must take the value 'deg' or 'rad'. You enter " + \ 42 | unit.strip().lower()) 43 | 44 | x = r * sin(th) * cos(ph) 45 | y = r * sin(th) * sin(ph) 46 | z = r * cos(th) 47 | 48 | return [x, y, z] 49 | 50 | def cart2spheric(xyz, unit = "deg", origine = [0., 0., 0.]): 51 | """ Calcule les coordonnees spheriques r, theta, phi d'un point M en fonction de ses 52 | coordonnees cartesiennes x, y, z. 53 | 54 | arguments : 55 | 56 | * xyz : coordonnees cartesiennes 57 | * unit : precise si les angles sont renvoye en degres (deg) ou radians (rad) 58 | * origine : coordonnees x, y, z de l'origine du repere 59 | 60 | >>> x = 2. * cos(radians(120.)) 61 | >>> y = -2. * sin(radians(120.)) 62 | >>> z = 0. 63 | >>> cart2spheric([x,y,z]) 64 | (1.9999999999999998, 90.0, 240.00000000000003) 65 | 66 | """ 67 | 68 | # substract origin 69 | x = xyz[0] - origine[0] 70 | y = xyz[1] - origine[1] 71 | z = xyz[2] - origine[2] 72 | 73 | # compute coordinates 74 | r = sqrt(x**2 + y**2 + z**2) 75 | th = acos(z / r) 76 | if y >= 0: 77 | ph = acos(x / r) 78 | else: 79 | ph = 2. * pi - acos(x / r) 80 | 81 | # degrees or radians 82 | if unit.strip().lower() == "rad": 83 | theta = th 84 | phi = ph 85 | elif unit.strip().lower() == "deg": 86 | theta = degrees(th) 87 | phi = degrees(ph) 88 | else: 89 | raise NameError("unit must take the value 'deg' or 'rad'. You enter " + \ 90 | unit.strip().lower()) 91 | 92 | return r, theta, phi 93 | 94 | if __name__ == "__main__": 95 | doctest.testmod() 96 | 97 | -------------------------------------------------------------------------------- /Various/supFile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | supFile 6 | ------- 7 | 8 | SYNTAX 9 | supFile [OPTIONS] 10 | 11 | DESCRIPTION 12 | Print all files corresponding to the argument list and ask for deletion. 13 | The script start from the current workind directory and look for all files 14 | in all subdirectories. 15 | 16 | -h, --help 17 | print this help 18 | 19 | EXAMPLES 20 | supFile CHG WAVECAR 21 | supFile CHGCAR 22 | supFile -h 23 | """ 24 | 25 | __licence__ = "GPL" 26 | __author__ = "Germain Vallverdu " 27 | __date__ = "12 Novembre 2013" 28 | 29 | import doctest 30 | import os 31 | import sys 32 | import fnmatch 33 | 34 | KILO_OCTET = 1024 35 | MEGA_OCTET = 1048576 36 | GIGA_OCTET = 1073741824 37 | TERA_OCTET = 1099511627776 38 | 39 | def humanSize(taille): 40 | """ return a byte number in human readable format (1ko 234Mo 2Go 41 | 42 | >>> humanSize(345) 43 | '345 o' 44 | >>> humanSize(123478) 45 | '120.6 ko' 46 | >>> humanSize(983435743) 47 | '937.9 Mo' 48 | >>> humanSize(12983435743) 49 | '12.1 Go' 50 | >>> humanSize(755812983435743) 51 | '687.4 To' 52 | 53 | """ 54 | taille = float(taille) 55 | if taille >= TERA_OCTET: 56 | size = "%.1f To" % (taille / TERA_OCTET) 57 | elif taille >= GIGA_OCTET: 58 | size = "%.1f Go" % (taille / GIGA_OCTET) 59 | elif taille >= MEGA_OCTET: 60 | size = "%.1f Mo" % (taille / MEGA_OCTET) 61 | elif taille >= KILO_OCTET: 62 | size = "%.1f ko" % (taille / KILO_OCTET) 63 | else: 64 | size = "%.0f o" % taille 65 | 66 | return size 67 | 68 | def delFile(filenames): 69 | """ List all file in an path tree and delete it 70 | 71 | arguments : 72 | * filenames (list) : name of the file you want to delete 73 | """ 74 | 75 | # check 76 | if not isinstance(filenames, list): 77 | print("filenames must be a list of file name") 78 | exit(1) 79 | 80 | fichier = list() 81 | tailleTotale = 0 82 | nFiles = 0 83 | for root, dirs, files in os.walk("./"): 84 | for name in files: 85 | if not os.path.isfile(os.path.join(root,name)): 86 | continue 87 | for filename in filenames: 88 | if fnmatch.fnmatch(name, filename): 89 | taille = os.path.getsize(os.path.join(root, name)) 90 | nFiles += 1 91 | tailleTotale += taille 92 | fichier.append({"nom":name, "dossier":root, "taille":taille}) 93 | 94 | print("\n * * * files * * *\n") 95 | print("--------------------------------------------------------------------------------") 96 | print(" Nombre de fichiers : " + str(nFiles)) 97 | print(" Taille totale des fichiers : " + humanSize(tailleTotale)) 98 | print("--------------------------------------------------------------------------------\n") 99 | 100 | # sort files and print 101 | sorted_fichier = sorted(fichier, key = lambda f:f["taille"], reverse = True) 102 | for i, f in enumerate(sorted_fichier): 103 | print(str(i+1).rjust(6) + humanSize(f["taille"]).rjust(10) + f["nom"].rjust(30) + " " + f["dossier"]) 104 | print("--------------------------------------------------------------------------------\n") 105 | print("### WARNING, ALL ABOVE FILES WILL BE DELETE ###") 106 | answer = "" 107 | while answer != "y": 108 | answer = input(" ARE YOU SURE ? (y/n) : ") 109 | if answer == "n": 110 | print("nothing was deleted") 111 | exit(0) 112 | elif answer == "y": 113 | continue 114 | else: 115 | print(" hit 'y' for yes or 'n' for non") 116 | for f in sorted_fichier: 117 | print("rm " + os.path.join(f["dossier"], f["nom"])) 118 | os.remove(os.path.join(f["dossier"], f["nom"])) 119 | 120 | if __name__ == "__main__": 121 | doctest.testmod() 122 | 123 | nargs = len(sys.argv) 124 | if nargs >= 2: 125 | if "-h" in sys.argv or "--help" in sys.argv: 126 | print(__doc__) 127 | exit(0) 128 | else: 129 | filenames = sys.argv[1:] 130 | else: 131 | print("Error: You have to give at least one file name") 132 | print(__doc__) 133 | exit(1) 134 | 135 | delFile(filenames) 136 | 137 | -------------------------------------------------------------------------------- /Various/vmdmo.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | # Display settings 5 | import argparse 6 | from pathlib import Path 7 | 8 | 9 | def add_molecule(cube_file, isovalue=0.02, mode="wireframe", state=1): 10 | """ Add a molecule in the vmd script """ 11 | 12 | if mode == "wireframe": 13 | mode = 1 14 | material = "Opaque" 15 | elif mode == "solid": 16 | mode = 0 17 | material = "Transparent" 18 | else: 19 | print(f"WARNING: mode '{mode}' is not known, set wireframe") 20 | 21 | new_mol = f""" 22 | mol new {cube_file} type cube first 0 last -1 step 1 filebonds 1 autobonds 1 waitfor all 23 | # load rep CPK 24 | mol delrep 0 top 25 | mol representation CPK 1.000000 0.500000 20.000000 20.000000 26 | mol color Name 27 | mol selection {{all}} 28 | mol material Opaque 29 | mol addrep top 30 | # load rep Surf pos 31 | mol representation Isosurface {isovalue:.6f} 0 0 {mode} 1 1 32 | mol color ColorID 1 33 | mol selection {{all}} 34 | mol material {material} 35 | mol addrep top 36 | # load rep Surf neg 37 | mol representation Isosurface {-isovalue:.6f} 0 0 {mode} 1 1 38 | mol color ColorID 0 39 | mol selection {{all}} 40 | mol material {material} 41 | mol addrep top 42 | #load rep nodal surface 43 | mol representation Isosurface 0.000000 0 0 1 1 1 44 | mol color ColorID 6 45 | mol selection {{all}} 46 | mol material Opaque 47 | mol addrep top 48 | mol showrep top 3 0 49 | #rename mol 50 | mol rename top {cube_file} 51 | molinfo top set drawn {state} 52 | """ 53 | 54 | return new_mol 55 | 56 | 57 | def get_options(): 58 | """ Define the argparse parser and returns options """ 59 | 60 | def exist(f): 61 | """ 'Type' for argparse - checks that file exists but does not open """ 62 | if not Path(f).is_file(): 63 | raise argparse.ArgumentTypeError(f"{f} does not exist") 64 | return f 65 | 66 | # parse command line options 67 | parser = argparse.ArgumentParser( 68 | description="VMD Molecular Orbitals", 69 | epilog="Author: Germain Salvato Vallverdu") 70 | 71 | parser.add_argument('-v', '--version', action='version', version="0.1") 72 | 73 | parser.add_argument( 74 | "-i", "--isovalue", type=float, default=0.02, 75 | help="Isovalue used to draw the MO." 76 | ) 77 | 78 | group_cube = parser.add_mutually_exclusive_group(required=True) 79 | group_cube.add_argument( 80 | "-a", "--all", 81 | help="Load all cube files in the directory.", 82 | action="store_const", 83 | const="all") 84 | group_cube.add_argument( 85 | "-c", '--cube', 86 | help="The cube file containing the OM to be read.", 87 | metavar="OM.cube", 88 | type=exist) 89 | 90 | group_rep = parser.add_mutually_exclusive_group() 91 | group_rep.add_argument( 92 | "-w", "--wireframe", 93 | help="Draw isosurfaces as wireframes (default).", 94 | action="store_const", 95 | const="wireframe") 96 | group_rep.add_argument( 97 | "-s", "--solid", 98 | help="Draw isosurfaces as solid surfaces.", 99 | action="store_const", 100 | const="solid") 101 | 102 | parser.add_argument( 103 | "-o", "--output", 104 | help="Name of the output VMD script", 105 | metavar="VMDSCRIPT", 106 | default="orbitals.vmd" 107 | ) 108 | 109 | args = parser.parse_args() 110 | 111 | return args 112 | 113 | 114 | def main(): 115 | """ run the script """ 116 | 117 | # get options 118 | args = get_options() 119 | 120 | # vmd file header 121 | lines = "# VMD script written using save_state $Revision: 1.47 $/n" 122 | lines += "# VMD version: 1.9.3/n" 123 | lines += "display projection Orthographic/n" 124 | lines += "display depthcue off/n" 125 | lines += "display shadows off\n" 126 | 127 | mode = "wireframe" if args.solid is None else "solid" 128 | 129 | if args.all is not None: 130 | p = Path("./") 131 | print(f"Read all cub(e) files in: {p.absolute()}") 132 | cube_files = [f for f in p.glob("*.cub*")] 133 | 134 | else: 135 | cube_files = [args.cube] 136 | 137 | for i, cube_file in enumerate(cube_files): 138 | lines += f"# Start with molecule {i}" 139 | lines += add_molecule( 140 | cube_file=cube_file, isovalue=args.isovalue, mode=mode, 141 | state=1 if i == 0 else 0 142 | ) 143 | lines += f"# done with molecule {i}\n\n" 144 | 145 | with open(args.output, "w") as fout: 146 | fout.write(lines) 147 | 148 | 149 | if __name__ == '__main__': 150 | main() 151 | -------------------------------------------------------------------------------- /Various/zipFile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding=utf-8 -*- 3 | 4 | """ 5 | zipFile 6 | ------- 7 | 8 | SYNTAX 9 | zipFile [OPTIONS] 10 | 11 | DESCRIPTION 12 | Print all files corresponding to the argument list and ask before 13 | compression. The script start from the current workind directory and look 14 | for all files in all subdirectories. Default compression command is gzip. 15 | 16 | -h, --help 17 | print this help and exit 18 | 19 | -zipcmd [cmd] 20 | select the command for compression. For example : gzip, bzip2 21 | This can be used to uncompress a list of files. 22 | 23 | EXAMPLES 24 | zipFile CHG* WAVECAR 25 | zipFile CHGCAR -zipcmd bzip2 26 | zipFile -h 27 | """ 28 | 29 | __licence__ = "GPL" 30 | __author__ = "Germain Vallverdu " 31 | __date__ = "09 juillet 2015" 32 | 33 | import doctest 34 | import os 35 | import sys 36 | import fnmatch 37 | 38 | KILO_OCTET = 1024 39 | MEGA_OCTET = 1048576 40 | GIGA_OCTET = 1073741824 41 | TERA_OCTET = 1099511627776 42 | 43 | def humanSize(taille): 44 | """ return a byte number in human readable format (1ko 234Mo 2Go 45 | 46 | >>> humanSize(345) 47 | '345 o' 48 | >>> humanSize(123478) 49 | '120.6 ko' 50 | >>> humanSize(983435743) 51 | '937.9 Mo' 52 | >>> humanSize(12983435743) 53 | '12.1 Go' 54 | >>> humanSize(755812983435743) 55 | '687.4 To' 56 | 57 | """ 58 | taille = float(taille) 59 | if taille >= TERA_OCTET: 60 | size = "%.1f To" % (taille / TERA_OCTET) 61 | elif taille >= GIGA_OCTET: 62 | size = "%.1f Go" % (taille / GIGA_OCTET) 63 | elif taille >= MEGA_OCTET: 64 | size = "%.1f Mo" % (taille / MEGA_OCTET) 65 | elif taille >= KILO_OCTET: 66 | size = "%.1f ko" % (taille / KILO_OCTET) 67 | else: 68 | size = "%.0f o" % taille 69 | 70 | return size 71 | 72 | def zipFile(filenames, zipcmd="gzip"): 73 | """ List all file in an path tree and compress it with zipcmd 74 | 75 | args : 76 | * filenames (list): name of the file you want to delete 77 | * zipcmd (str): command and options for file compression 78 | """ 79 | 80 | # check 81 | if not isinstance(filenames, list): 82 | print("filenames must be a list of file name") 83 | exit(1) 84 | 85 | fichier = list() 86 | tailleTotale = 0 87 | nFiles = 0 88 | for root, dirs, files in os.walk("./"): 89 | for name in files: 90 | if not os.path.isfile(os.path.join(root,name)): 91 | continue 92 | for filename in filenames: 93 | if fnmatch.fnmatch(name, filename): 94 | taille = os.path.getsize(os.path.join(root, name)) 95 | nFiles += 1 96 | tailleTotale += taille 97 | fichier.append({"nom":name, "dossier":root, "taille":taille}) 98 | 99 | print("\n * * * files * * *\n") 100 | print("--------------------------------------------------------------------------------") 101 | print(" Nombre de fichiers : " + str(nFiles)) 102 | print(" Taille totale des fichiers : " + humanSize(tailleTotale)) 103 | print(" Commande pour compression : " + zipcmd) 104 | print("--------------------------------------------------------------------------------\n") 105 | 106 | # sort files and print 107 | sorted_fichier = sorted(fichier, key = lambda f:f["taille"], reverse = True) 108 | for i, f in enumerate(sorted_fichier): 109 | print(str(i+1).rjust(6) + humanSize(f["taille"]).rjust(10) + f["nom"].rjust(30) + " " + f["dossier"]) 110 | print("--------------------------------------------------------------------------------\n") 111 | print("All above files will be compressed") 112 | answer = "" 113 | while answer != "y": 114 | answer = input(" are you sure ? (y/n) : ") 115 | if answer == "n": 116 | print("nothing was done") 117 | exit(0) 118 | elif answer == "y": 119 | continue 120 | else: 121 | print(" hit 'y' for yes or 'n' for non") 122 | for f in sorted_fichier: 123 | run = zipcmd + " " + os.path.join(f["dossier"], f["nom"]) 124 | print(run) 125 | os.system(run) 126 | 127 | if __name__ == "__main__": 128 | doctest.testmod() 129 | 130 | nargs = len(sys.argv) 131 | if nargs >= 2: 132 | if "-h" in sys.argv or "--help" in sys.argv: 133 | print(__doc__) 134 | exit(0) 135 | 136 | if "--zipcmd" in sys.argv: 137 | try: 138 | pos = sys.argv.index("--zipcmd") 139 | sys.argv.pop(pos) 140 | zipcmd = sys.argv[pos] 141 | sys.argv.pop(pos) 142 | except: 143 | print("\n !# ERROR #! reading options") 144 | print(__doc__) 145 | exit(1) 146 | else: 147 | zipcmd = "gzip" 148 | 149 | filenames = sys.argv[1:] 150 | else: 151 | print("Error: You have to give at least one file name") 152 | print(__doc__) 153 | exit(1) 154 | 155 | zipFile(filenames, zipcmd) 156 | 157 | --------------------------------------------------------------------------------