PyBigDFT Documentation Release 0.1

Luigi Genovese

Nov 19, 2018

Contents

1 How to write documentation in this package3

2 Module Members 5

3 Index of the Package 55

4 Indices and tables 59

Python Module Index 61

i ii PyBigDFT Documentation, Release 0.1

This package is a collection of Python Modules that are conceived for pre- and post- processing of BigDFT input and output files. Such modules are supposed to enhance the BigDFT experience by high-level approach. Also, calculators and workflows are supposed to be created and inspected with modules of the PyBigDFT package. The documentation of this package is described in

Contents 1 PyBigDFT Documentation, Release 0.1

2 Contents CHAPTER 1

How to write documentation in this package

The syntax in the text pages is ReStructured Text format. see this page for examples of the syntax, and this one for a more comprehensive explanation of the syntax. The syntax chosen for the auto-documentation of the Python module is Google Docstring syntax. see the google Docstring example in the Sphinx-napoleon package.

1.1 How to generate documentation

• Install sphinx package and the requirements written in the file source/requirements.txt of provided with the sources of PyBigDFT. • Copy the quick build file Makefile-sphinxbuild of the PyBigDFT source directory into Makefile • Run the command make html • The documentation of the package can be explored starting from the file build/html/index.html.

1.2 Automodule generation

The directive to be used is mainly the automodule one, see this page:

3 PyBigDFT Documentation, Release 0.1

4 Chapter 1. How to write documentation in this package CHAPTER 2

Module Members

Input file representation and usage from Python

2.1 BigDFT.Inputfiles module

Handling of the input options This module contain the useful quantities to deal with the preparation and the usage of inputfiles for BigDFT code. The main object is the Inputfile class, which inherits from a python dictionary. Such inheritance is made possible by the internal representation of the BigDFT inputfile, which employs the YAML syntax. This means that there is a one-to-one correspondence between a python dictionary and a BigDFT inputfile. class BigDFT.Inputfiles.Inputfile(*args, **kwargs) Bases: dict The BigDFT inputfile. Principal object needed to run a BigDFT calculation. Might be initialized either from a dictionary, a Logfile instance or a (yaml-compliant) filename path

Note: Each of the actions of the module InputActions, which is defined on a generic dictionary, also corresponds to a method of of the Inputfile class, and it is applied to the class instance. Therefore also the first argument of the corresponding action is implicitly the class instance. For the remove() method, the action has to be invoked should come from the InputActions module.

Example

>>> import InputActions asA , Inputfiles asI >>> inp=I.Inputfile() >>> inp.set_hgrids(0.3) # equivalent to A.set_hgrids(inp,0.3) (continues on next page)

5 PyBigDFT Documentation, Release 0.1

(continued from previous page) >>> inp {'dft': {'hgrids': 0.3}} >>> inp.optimize_geometry() # equivalent to A.optimize_geometry(inp) >>> inp {'dft': {'hgrids': 0.3},'geopt': {'method': 'FIRE','ncount_cluster_x': 50} } >>> inp.remove(A.optimize_geometry) # equivalent to A.remove(inp,A.optimize_

˓→geometry) >>> inp {'dft': {'hgrids': 0.3}}

Todo: Consider the possiblity of initializing an Inputfile instance from a yaml file. And also from a Logfile class

Input Actions on the BigDFT input file

2.2 BigDFT.InputActions module

Actions to define on the Input parameters. This module defines some of the most common actions that a BigDFT user might like to perform on the input file. Such module therefore set some of the keys of the input dictionary to the values needed to perform the operations. Users might also inspire to the actions performed in order to customize the runs in a different way. All the functions of this module have as first argument inp, the dictionary of the input parameters. Many other actions are available in BigDFT code. This module only regroups the most common. Any of these functionalities might be removed from the input file by the remove() function.

Note: Any of the action of this module, including the remove() function, can be also applied to an instance of the BigDFT.Inputfiles.Inputfile class, by removing the first argument (inp). This adds extra flexibility as the same method may be used to a dictionary instance or to a BigDFT input files. See the example Example.

Note: Each of the actions here must have default value for the arguments (except the input dictionary inp). This is needed for a good behaviour of the function remove.

remove(inp, action) Remove action from the input dictionary. set_xc(inp[, xc]) Set the exchange and correlation approximation set_hgrid(inp[, hgrids]) Set the grid spacing. set_rmult(inp[, rmult, coarse, fine]) Set the wavelet grid extension by modifying the multi- plicative radii. set_atomic_positions(inp[, posinp]) Insert the atomic positions as a part of the input dictio- nary set_mesh_sizes(inp[, ngrids]) Constrain the number of grid points in each direction. optimize_geometry(inp[, method, nsteps]) Optimize the geometry of the system spin_polarize(inp[, mpol]) Add a collinear spin polarization to the system. charge(inp[, charge]) Charge the system charge_and_polarize(inp) Charge the system by removing one . Continued on next page

6 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

Table 1 – continued from previous page set_symmetry(inp[, yes]) Set the symmetry detection for the charge density and the ionic forces and stressdef set_symmetry(inp,yes=True): apply_electric_field(inp[, elecfield]) Apply an external electric field on the system set_random_inputguess(inp) Input orbitals are initialized as random coefficients write_orbitals_on_disk(inp[, format]) Set the code to write the orbitals on disk in the provided format read_orbitals_from_disk(inp) Read the orbitals from data directory, if available write_density_on_disk(inp) Write the charge density on the disk after the last SCF convergence calculate_dipole(inp) Extract the dipole momenet from the total charge den- sity. use_gpu_acceleration(inp) Employ gpu acceleration when available, for convolu- tions and Fock operator change_data_directory(inp[, name]) Modify the name of the data- directory. connect_run_data(inp[, log]) Associate the data of the run of a given logfile to the input by retrieving the data directory name of the logfile. add_empty_SCF_orbitals(inp[, norbs]) Insert norbs empty orbitals in the SCF procedure extract_virtual_states(inp, nvirt[, davidson]) Extract a given number of empty states after the scf cy- cle. set_electronic_temperature(inp[, kT, T]) Define the electronic temperature, in AU (kT) or K (T) calculate_tddft_coupling_matrix(inp[, Perform a casida TDDFT coupling matrix extraction. tda, . . . ])

BigDFT.InputActions.add_empty_SCF_orbitals(inp, norbs=10) Insert norbs empty orbitals in the SCF procedure Parameters norbs (int) – Number of empty orbitals

Warning: In linear scaling case, this is only meaningful for the direct minimization approach.

BigDFT.InputActions.apply_electric_field(inp, elecfield=[0, 0, 0.001]) Apply an external electric field on the system Parameters electric (list, float) – Values of the Electric Field in the three directions. Might also be a scalar. BigDFT.InputActions.calculate_dipole(inp) Extract the dipole momenet from the total charge density.

Note: This function is useful for the linear scaling setup as the cubic scaling approach always calculates the charge density multipoles.

BigDFT.InputActions.calculate_tddft_coupling_matrix(inp, tda=False, rpa=True, fxc=True) Perform a casida TDDFT coupling matrix extraction. Parameters • tda (bool) – when True, Tamm-Dancoff approximation is used for the extraction of the coupling matrix

2.2. BigDFT.InputActions module 7 PyBigDFT Documentation, Release 0.1

• rpa (bool) – when False, the calculation of the RPA term (the linear response of the hartree potential) is switched off • fxc (bool) – when False, the calculation of the fxc term (the linear response of the XC operator) is switched off.

Note: The arguments fxc and rpa should not be simultaneously False.

Warning: Presently the LR-TDDFT casida fxc is only available for LDA functionals in ABINIT flavour.

BigDFT.InputActions.change_data_directory(inp, name=”) Modify the name of the data- directory. Useful to grab the orbitals from another directory than the run name BigDFT.InputActions.charge(inp, charge=-1) Charge the system Parameters charge (int,float) – value of the charge in units of e (the electron has charge -1). Also accept floating point numbers. BigDFT.InputActions.charge_and_polarize(inp) Charge the system by removing one electron. Assume that the original system is closed shell, thus polarize. BigDFT.InputActions.connect_run_data(inp, log=None) Associate the data of the run of a given logfile to the input by retrieving the data directory name of the logfile. Parameters log (Logfile) – instance of a Logfile class BigDFT.InputActions.extract_virtual_states(inp, nvirt, davidson=False) Extract a given number of empty states after the scf cycle. Parameters davidson (bool) – If set to True activates davidson calculation, otherwise Trace Minimization of the Hamiltonian is employed. BigDFT.InputActions.optimize_geometry(inp, method=’FIRE’, nsteps=50) Optimize the geometry of the system Parameters • nsteps (int) – maximum number of atomic steps. • method (str) – Geometry optimizer. Available keys: * SDCG: A combination of Steepest Descent and Conjugate Gradient * VSSD: Variable Stepsize Steepest Descent method * LBFGS: Limited-memory BFGS * BFGS: Broyden-Fletcher-Goldfarb-Shanno * PBFGS: Same as BFGS with an initial Hessian obtained from a force field * DIIS: Direct inversion of iterative subspace * FIRE: Fast Inertial Relaxation Engine as described by Bitzek et al. * SBFGS: SQNM minimizer, keyword deprecated, will be replaced by SQNM in future release * SQNM: Stabilized quasi-Newton minimzer BigDFT.InputActions.read_orbitals_from_disk(inp) Read the orbitals from data directory, if available BigDFT.InputActions.remove(inp, action) Remove action from the input dictionary. Remove an action from the input file, thereby restoring the default value, as if the action were not specified. Parameters • inp (dict) – dictionary to remove the action from.

8 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

• action (func) – one of the actions of this module. It does not need to be specified before, in which case it produces no effect.

Example

>>> from Calculators import SystemCalculator as C >>> code=C() >>> inp={} >>> set_xc(inp,'PBE') >>> write_orbitals_on_disk(inp) >>> log=code.run(input=inp) # perform calculations >>> remove(write_orbitals_on_disk) #remove the action >>> read_orbitals_from_disk(inp) >>> log2=code.run(input=inp) #this will restart the SCF from the previous orbitals

BigDFT.InputActions.set_SCF_method(inp, method=’dirmin’, mixing_on=’density’, mix- ing_scheme=’Pulay’) Set the algorithm for SCF. Parameters • method (str) – The algoritm chosen. Might be different for the cubic (CS) or linear scaling (LS) algorithm. * dirmin: Direct minimization approach (valid both to LS and CS) * mixing: Mixing scheme (only CS) * foe: Fermi Operator Expansion (only LS) * pexsi: Pole EXpansion and Selected Inversion method (only LS, require PEXSI compilation) * diag: Explicit diagonalization (only LS, for validation purposes) • mixing_on (str) – May be "density" or "potential" in the "mixing" case, decide to which quantity the mixing to be performed • mixing_scheme (str) – May be: – Pulay : DIIS mixing on the last 7 iterations – Simple: Simple mixing – Anderson: Anderson scheme – Anderson2: Anderson scheme based on the two pervious iterations – CG: Conjugate Gradient based on the minimum of the energy with respect of the potential

Warning: Only the FOE method exhibit asymptotic linear scaling regime.

Todo: Check if the linear scaling case needs another input variable for the mixing of the potential (density)

BigDFT.InputActions.set_atomic_positions(inp, posinp=None) Insert the atomic positions as a part of the input dictionary BigDFT.InputActions.set_electronic_temperature(inp, kT=0.001, T=0) Define the electronic temperature, in AU (kT) or K (T) BigDFT.InputActions.set_hgrid(inp, hgrids=0.4) Set the wavelet grid spacing. Parameters hgrid (float,list) – list of the grid spacings in the three directions. It might also be a scalar, which implies the same spacing

2.2. BigDFT.InputActions module 9 PyBigDFT Documentation, Release 0.1

BigDFT.InputActions.set_linear_scaling(inp) Activates the linear scaling mode BigDFT.InputActions.set_mesh_sizes(inp, ngrids=64) Constrain the number of grid points in each direction. This is useful when performing periodic system calcula- tions with variable cells which need to be compared each other. In this way the number of degrees of freedom is kept constant throughout the various simuilations. Parameters ngrids (int,list) – list of the number of mesh points in each direction. Might be a scalar. BigDFT.InputActions.set_random_inputguess(inp) Input orbitals are initialized as random coefficients BigDFT.InputActions.set_rmult(inp, rmult=None, coarse=5.0, fine=8.0) Set the wavelet grid extension by modifying the multiplicative radii. Parameters • rmult (float,list) – list of two values that have to be used for the coarse and the fine resolution grid. It may also be a scalar. • coarse (float) – if the argument rmult is not provided it sets the coarse radius multi- plier • fine (float) – if the argument rmult is not provided it sets the fine radius multiplier BigDFT.InputActions.set_symmetry(inp, yes=True) Set the symmetry detection for the charge density and the ionic forces and stressdef set_symmetry(inp,yes=True): Parameters yes (bool) – If False the symmetry detection is disabled BigDFT.InputActions.set_xc(inp, xc=’PBE’) Set the exchange and correlation approximation Parameters xc (str) – the Acronym of the XC approximation

Todo: Insert the XC codes corresponding to libXC conventions

BigDFT.InputActions.spin_polarize(inp, mpol=1) Add a collinear spin polarization to the system. Parameters mpol (int) – spin polarization in Bohr magneton units. BigDFT.InputActions.use_gpu_acceleration(inp) Employ gpu acceleration when available, for convolutions and Fock operator

Todo: Verify what happens when only one of the functionality is enabled at compile-time

BigDFT.InputActions.write_cubefiles_around_fermi_level(inp, nplot=1) Writes the nplot orbitals around the fermi level in cube format Parameters nplot (int) – the number of orbitals to print around the fermi level.

Warning: This is presently meaningful only for a empty states calculation.

10 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

Warning: This would work only for the cubic scaling code at present.

BigDFT.InputActions.write_density_on_disk(inp) Write the charge density on the disk after the last SCF convergence BigDFT.InputActions.write_orbitals_on_disk(inp, format=’binary’) Set the code to write the orbitals on disk in the provided format Parameters format (str) – The format to write the orbitals with. Accepts the strings: * ‘binary’ * ‘text’ * ‘etsf’ (requires etsf-io enabled)

Todo: Verify if this option works for a linear scaling calulation.

BigDFT.InputActions.write_support_function_matrices(inp) Write the matrices of the linear scaling formats. BigDFT.InputActions.write_support_functions_on_disk(inp, format=’binary’, matri- ces=True, coefficients=False) Analysis of Logfiles and Ground-state related properties

2.3 BigDFT.Logfiles module

This module is useful to process a logfile of BigDFT run, in yaml format. It also provides some tools to extract typical informations about the run, like the energy, the eigenvalues and so on. class BigDFT.Logfiles.Logfile(*args, **kwargs) Import a Logfile from a filename in yaml format, a list of filenames, an archive (compressed tar file), a dictionary or a list of dictionaries. Parameters • args (strings) – logfile names to be parsed • kwargs – keyword arguments – archive: name of the archive from which retrieve the logfiles – member: name of the logfile within the archive. If absent, all the files of the archive will be considered as args – label: the label of the logfile instance – dictionary: parsed logfile given as a dictionary, serialization of the yaml logfile Example

>>> l= Logfile('one.yaml','two.yaml') >>> l= Logfile(archive='calc.tgz') >>> l= Logfile(archive='calc.tgz',member='one.yaml') >>> l= Logfile(dictionary=dict1) >>> l= Logfile(dictionary=[dict1, dict2])

Todo: Document the automatically generated attributes, perhaps via an inner function in futile python module

2.3. BigDFT.Logfiles module 11 PyBigDFT Documentation, Release 0.1

geopt_plot() For a set of logfiles construct the convergence plot if available. Plot the Maximum value of the forces against the difference between the minimum value of the energy and the energy of the iteration. Also an errorbar is given indicating the noise on the forces for a given point. Show the plot as per plt.show() with matplotlib.pyplots as plt Example

>>> tt=Logfile('log-with-geometry-optimization.yaml') >>> tt.geopt_plot()

get_brillouin_zone() Return an instance of the BrillouinZone class, useful for band structure. :returns: Brillouin Zone of the logfile :rtype: BigDFT.BZ.BrillouinZone get_dos(label=None, npts=2500) Get the density of states from the logfile. Parameters • label (string) – id of the density of states. • npts (int) – number of points of the DoS curve Returns Instance of the DoS class Return type BigDFT.DoS.DoS label = None Label of the Logfile instance reference_log = None Position in the logfile items of the run associated to lower energy srcdir = None Absolute path of the directory of logfile wfn_plot() Plot the wavefunction convergence. BigDFT.Logfiles.find_iterations(log) Identify the different block of the iterations of the wavefunctions optimization.

Todo: Should be generalized and checked for mixing calculation and O(N) logfiles

Parameters log (dictionary) – logfile load Returns wavefunction residue per iterations, per each subspace diagonalization Return type numpy array of rank two

BigDFT.Logfiles.floatify(scalar) Useful to make float from strings compatible from fortran Parameters • scalar (str, float) – When string representing a float that might be given in fortran notation, • it might be a floating point (otherwise)– Returns float. The value associated to scalar as a floating point number

12 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

Example

>>> floatify('1.d-4') #this would be the same with "1.e-4" or with 0.0001 1.e-4

BigDFT.Logfiles.get_logs(files) Return a list of loaded logfiles from files, which is a list of paths leading to logfiles. Parameters files – List of filenames indicating the logfiles Returns List of Logfile instances associated to filename BigDFT.Logfiles.plot_wfn_convergence(wfn_it, gnrm_cv) Plot the convergence of the wavefunction coming from the find_iterations function. Cumulates the plot in matplotlib.pyplot module Parameters • wfn_it – list coming from find_iterations() • gnrm_cv – convergence criterion for the residue of the wfn_it list Processing of Fragment-related quantities

2.4 BigDFT.Fragments module

This module is related to the usage of BigDFT with Fragment-related Quantities. Input as well as Logfiles might be processed with the classes and methods provided by it. BigDFT.Fragments.AU_to_A = 0.52917721092 Conversion between Atomic Units and Bohr BigDFT.Fragments.CreateFragDict(start) BigDFT.Fragments.CreateFragList(frag_dict, merge_list=None) BigDFT.Fragments.Debye_to_AU = 0.393430307 Conversion between Debye and Atomic units class BigDFT.Fragments.Fragment(atomlist=None, id=’Unknown’, units=’AU’) Introduce the concept of fragment. This is a subportion of the system (it may also coincide with the system itself) that is made of . Such fragment might have quantities associated to it, like its electrostatic multipoles (charge, dipole, etc.) and also geometrical information (center of , principla axis etc.). A Fragment might also be rototranslated and combined with other moieteies to form a System. Parameters • atomlist (list-type) – list of atomic dictionaries defining the fragment • id (string) – label of the fragment • units (string) – the units of the fragment, can be ‘AU’ or ‘A’ Example

>>> f= Fragment(atomlist) #provide the list of atomic dictionaries >>> # or otherwise: >>> f= Fragment(units='A') #initialize the fragment >>> f.append() #add an atom according to the f.append spec >>> ... # repeat that until the fragment is completed

2.4. BigDFT.Fragments module 13 PyBigDFT Documentation, Release 0.1

Todo: Define and describe if this API is also suitable for solid-state fragments

Q(atom=None, order=0) Fragment Monopole, when the information is available. If the set_fragment_multipoles routine has been called you can use this routine to get that infor- mation back out. For Q0 you can also compute for just a subset of the atoms. Parameters • atom (list) – atoms to compute the charge from. • order (integer) – which multipole to return (0, 1, 2)

Todo: WD: I’m not sure in which circumstances one would like to pass the atom list. Maybe we can remove that option?

append(atom=None, sym=None, positions=None) Include an atom in the fragment. Parameters • atom (dictionary) – The dictionary of the atom. Should be provided in the yaml format of BigDFT atomic positions. • sym (string) – The symbol of the atom. Need positions when specified. • positions (list) – The atomic positions, given in fragment units. center_of_charge(zion) centroid() d0(center=None) Fragment dipole, calculated only from the atomic charges d1(center=None) Fragment dipole including the atomic dipoles dict() Transform the fragment information into a dictionary ready to be put as external potential element(atom) Provides the name of the element ellipsoid(center=0.0) get_posinp(units=’AU’) Get a list of elements and positions describing this fragment that is suitable for putting in the posinp entry of an input file. Parameters units (str) – units to write line_up() Align the principal axis of inertia of the fragments along the coordinate axis. Also shift the fragment such as its centroid is zero. q0(atom) Provides the charge of the atom

14 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

q1(atom) Provides the dipole of the atom rxyz(atom) set_fragment_multipoles(q0, q1, q2) Set the multipoles associated with an entire fragment. Parameters • q0 (list) – list of floats defining the 0th multipole. • q1 (list) – list of floats defining the 1st multipole. • q2 (list) – list of floats defining the 2nd multipole. set_id(id) set_purity_indicator(pi) transform(Rt) Apply a rototranslation of the fragment positions xyz(filename=None, units=’atomic’) Write the fragment positions in a xyz file BigDFT.Fragments.GetFragTuple(id) BigDFT.Fragments.GetSymbol(atom) Provide the key which contains the positions Parameters atom (dictionary) – the dictionary describing the atom Returns atom symbol Return type string class BigDFT.Fragments.Lattice(vectors) Defines the fundamental objects to deal with periodic systems grid(origin=[0.0, 0.0, 0.0], extremes=None, radius=None) produces a set of translation vectors from a given origin BigDFT.Fragments.MergeFragmentsTogether(frag_dict, merge_list) class BigDFT.Fragments.Rotation(R) Bases: BigDFT.Fragments.RotoTranslation class BigDFT.Fragments.RotoTranslation(pos1, pos2) Define a transformation which can be applied to a group of atoms dot(pos) Apply the rototranslations on the set of positions provided by pos invert() BigDFT.Fragments.SetFragId(name, fragid) class BigDFT.Fragments.System(mp_dict=None, xyz=None, nat_reference=None, units=’AU’, transformations=None, reference_fragments=None, pos- inp_dict=None, frag_partition=None) A system is defined by a collection of Fragments. It might be given by one single fragment Parameters • mp_dict (dict)–

2.4. BigDFT.Fragments module 15 PyBigDFT Documentation, Release 0.1

• xyz (str)– • nat_reference (int)– • units (str)– • () (posinp_dict)– • () – • () – • frag_partition (list) – A list of integers which define the partitioning of a system. For example, a system with fragments [a, b, c, d] will be split in to [[a], [b, c], [d]] if passed the following list: [1, 3, 5]. Q() Provides the global monopole of the system given as a sum of the monopoles of the atoms append(frag) Append a fragment to the System class central_fragment() Returns the fragment whose center of mass is closest to the centroid centroid() Center of mass of the system decompose(reference_fragments) Decompose the system into reference fragments dict(filename=None) fill_from_mp_dict(mpd, nat_reference=None, frag_partition=None) Fill the System from a dictionary of multipole coefficients mpd (dict) : multipole dictionary to build from. nat_reference (int) : specifies an even partitioning of the system. frag_partition (list): A list of integers which define the partitioning of a system. For example, a system with fragments [a, b, c, d] will be split in to [[a], [b, c], [d]] if passed the following list: [1, 3, 5]. fill_from_posinp_dict(dct) fill_from_xyz(file, nat_reference) Import the fragment information from a xyz file fragdict() Provides the value of the dictionary fragment to be used for the inputfile in a fragment calculation fragment_transformation(frag1, frag2) returns the transformation among fragments if exists pop(ifrag) Pop the fragment ifrag from the list of fragments recompose(transformations=None, reference_fragments=None) Rebuild the system from a set of transformations write_fragfile(filename=’log.yaml’) Create a fragment list file and write it to the disk. Parameters filename (string) – the name of the file to write to. xyz(filename=None, units=’atomic’)

16 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

class BigDFT.Fragments.Translation(t) Bases: BigDFT.Fragments.RotoTranslation class BigDFT.Fragments.XYZfile(filename=None, units=’atomic’) A class associated to a xyz input file as processed by BigDFT Parameters • filename (string) – The file which will be created. If None, the file will be eventually dumped in :class:~‘sys.stdout‘. • units (string) – The units of measure of the positions. Allowed avlues are ‘atomic’ or ‘angstroem’ append(array, basename=”, names=None, attributes=None) Add lines to the file position list Parameters • array (list of float triples) – list of the atomic positions • basename (string) – base for the name of the atoms • names (list of strings) – list of atom names. Will be appended to basename if the latter is present • attributes (list of dictionaries) – list of further attributes to be associated to each of the atoms. Will be serialized close to each of the atomic positions dump(position=’w’) Dump the file on the file system if filename has been provided, otherwise dump on sys.stdout. Parameters position (char) – filename position statement. Only menaingful for a file dumping. BigDFT.Fragments.build_transformations(RTlist, ref ) Build the transformation list to be passed to the systems’ creation via the transformation keyword BigDFT.Fragments.close_xyz(f, filename) BigDFT.Fragments.distance(i, j, cell=None) Distance between fragments, defined as distance between center of mass BigDFT.Fragments.dump_xyz(array, basename=”, units=’atomic’, names=None, filename=None, po- sition=’a’, comment=None, cell=None) Create a BigDFT xyz filename. Duplicates the meaning of the XYZfile class. Parameters filename (string) – The file which will be created. If None, the file will be even- tually dumped in :class:~‘sys.stdout‘.

Todo: Remove the duplication of operations in favour or the class. Move the related operation into a lower-level module.

BigDFT.Fragments.dump_xyz_positions(f, array, basename=”, names=None) BigDFT.Fragments.find_reference_fragment(refs, transformed) generate the list of fragments that are associates to a given list of templates BigDFT.Fragments.frag_average(ref, flist, clean_monopole=True) Perform the average in attributes of the fragments provided by the list, with the position of the first fragment BigDFT.Fragments.open_xyz(filename, nat, unit, comment, position=’a’)

2.4. BigDFT.Fragments module 17 PyBigDFT Documentation, Release 0.1

BigDFT.Fragments.prepare_fragment_inputs(name, directory=’.’, flavour=’Isolated’, sys- tem=None, template=None, template_dir=None, template_name=None) BigDFT.Fragments.rotot_collection(ref_frag, lookup, fragments) Deprecated routine, only for backward compatibility BigDFT.Fragments.wahba_fragment(frag1, frag2) Solve the wahba’s problem among fragments, deprecated routine BigDFT.Fragments.xyz_bc_spec(cell) Defines the specification for expressing the Boundary Conditions starting from a cell vector. Parameters cell (triple of floats or None) – array of the (orthorhombic) cell. Should be 0.0 on directions with free BC. If None is given, the BC are assumed to be Free. Returns comment Line of the xyz file specifying the bc Return type string Calculators to be used with BigDFT package to trigger runs of the code

2.5 BigDFT.Calculators module

This module defines some classes to perform a calculation using BigDFT using binding (GIBinding) or using system call (SystemCalculator). class BigDFT.Calculators.GIBinding Calculator for BigDFT from Gobject Introspection bindings. run() set(inputfile=None) update(inputfile) class BigDFT.Calculators.Runner(**kwargs) Run of something. Object dealing with global and local options of a run method. All arguments in the __init__ call is stored as global options. For each run, these global options may updated by the arguments of the run call. get_global_option(key) Get one key in global options Parameters key (string) – the global option key Returns The value of the global options labelled by key global_options() Get all global options Returns The dictionary of the global options in its current status pop_global_option(key) Remove a given global option from the global option dictionary Parameters key (string) – the global option key Returns The value of the global option post_processing(**kwargs) Post-processing, take the arguments as they are provided by the process_run.

18 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

Returns The final object that each call to the run method is supposed to provide. pre_processing() Pre-treat the keyword arguments and the options, if needed. Returns dictionary of the pre-treated keyword arguments that have to be actually considered by process_run. process_run(**kwargs) Main item of the runner, defines the information that have to be post_processed by post_processing. Parameters **kwargs** (dict) – keyword arguments as returned from the pre_processing() method. Returns objects to be passed to post_processing run(**kwargs) Run method of the class. It performs the following actions: • Constructs the local dictionary to be passed as *kwargs* to the process_run function • Calls the pre_processing method (intended to prepare some actions associated to the process_run method • Calls process_run • Returns the object passed by the call to post_processing class method update_global_options(**kwargs) Update the global options by providing keyword arguments. class BigDFT.Calculators.SystemCalculator(omp=’1’, mpi_run=”, dry_run=False, skip=False, verbose=True) Bases: BigDFT.Calculators.Runner Define a BigDFT calculator. Main calculator of BigDFT code. It performs os.system() calls to the main executable in the $BIGDFT_ROOT directory. It is designed for two purposes: • Run the code in a workstation-based environment, for exemple within notebooks or scripts. • Run the code from a python script that is submitted to a batch scheduler in a potnentially large-scale supercomputer. For triggering the execution, this code gets two variables from the environment: • The value of OMP_NUM_THREADS to set the number of OMP_NUM_THREADS. If this variable is not present in the environment, SystemCalculator sets it to the value provided by the omp keyword at initialization. • The value of BIGDFT_MPIRUN to define the MPI execution command. If absent, the run is executed simply by $BIGDFT_ROOT/bigdft, followed by the command given by post-processing.

Parameters • omp (int) – number of OpenMP threads. It defaults to the $OMP_NUM_THREADS variable in the environment, if present, otherwise it fixes the run to 1 thread. • mpi_run (str) – define the MPI command to be used. It defaults to the value $BIGDFT_MPIRUN of the environment, if present. When using this calculator into a job submission script, the value of $BIGDFT_MPIRUN variable may be set appropriately to launch the bigdft executable. • skip (bool) – if True, do not run the calculation if the corresponding logfile exists.

2.5. BigDFT.Calculators module 19 PyBigDFT Documentation, Release 0.1

• verbose (bool) – if True the class prints out informations about the operations that are being performed by the calculator • dry_run (bool) – check the input, estimate the memory but do not perform the calcula- tion. • dry_mpi (int) – Number of MPI processes for the estimation of the memory when dry_run is True (not yet implemented) • taskgroup_size (int) – number of MPI processes of each of the taskgroup in the case of a runs_file.

Warning: At the initialization, SystemCalculator checks if the environment variable $BIGDFT_ROOT is defined. This would mean (although not guarantee) that the environment has been properly set prior to the evaluation of the python command. Also, it checks that the executable file bigdft might be found in the $BIGDFT_ROOT/bigdft path.

Example

>>> inpdict={'dft':{'ixc':'LDA'}} #a simple input file >>> study= SystemCalculator(omp=1) >>> logf= study.run(name="test",input=inpdict) Executing command: $BIGDFT_MPIRUN /bigdft test

os = post_processing(timedbg, logname, command) Check the existence and the log file and return an instance logfile. Returns A BigDFT.Logfile class instance associated to the run which has been just performed. If the run failed for some reasons, the logfile seem not existing or it cannot be parsed it returns None. pre_processing() Run a calculation building the input file from a dictionary. Parameters • name (str) – naming scheme of the run i.e. .yaml is the input file and log-.yaml the output one. Data will then be written in the directory data- .yaml, unless the “radical” keyword is specified in the input dictionary. • run_dir (str) – specify the directory where bigdft will be executed (the input and log file will be created in it) it must be a simple • outdir (str) – specify the output directory for all data coming from bigdft (parameter of bigdft) • run_name (str) – File containing the list of the run ids which have to be launched independently (list in yaml format). The option runs-file is not compatible with the name option. • input (dict) – give the input parameters (a dictionary or a list of dictionary) • posinp (filename) – indicate the posinp file (atomic position file). Returns a Logfile instance is returned. It returns None if an error occurred

20 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

Return type Logfile

Todo: Set the return value of run in the case of a run_file. It should be a list of Logfile classes

process_run(command) Finally launch the code. Routine associated to the running of the bigdft executable. Parameters command (str) – the command as it is set by the pre_processing method. shutil = Organize runs and analyze output in a dataset

2.6 The Datasets module

Calculation datasets. This module deals with the handling of series of calculations. Classes and functions of this module are meant to simplify the approach to ensemble calculations with the code, and to deal with parallel executions of multiple instances of the code. class BigDFT.Datasets.Dataset(label=’BigDFT dataset’, run_dir=’runs’, **kwargs) Bases: BigDFT.Calculators.Runner A set of calculations. Such class contains the various instances of a set of calculations with the code. The different calculations are labelled by parameter values and information that might then be retrieved for inspection and plotting. Parameters • label (str) – The label of the dataset. It will be needed to identify the instance for example in plot titles or in the running directory. • run_dir (str) – path of the directory where the runs will be performed. • input (dict) – Inputfile to be used for the runs as default, can be overridden by the specific inputs of the run append_run(id, runner, **kwargs) Add a run into the dataset. Append to the list of runs to be performed the corresponding runner and the arguments which are associated to it. Parameters • id (dict) – the id of the run, useful to identify the run in the dataset. It has to be a dictionary as it may contain different keyword. For example a run might be classified as id = {'hgrid':0.35, 'crmult': 5}. • runner (Runner) – the runner class to which the remaining keyword arguments will be passed at the input. Raises ValueError – if the provided id is identical to another previously appended run.

Todo: include id in the runs spcification

2.6. The Datasets module 21 PyBigDFT Documentation, Release 0.1

calculators = None Calculators which will be used by the run method, useful to gather the inputs in the case of a multiple run. fetch_results(id=None, attribute=None) Retrieve some attribute from some of the results. Selects out of the results the objects which have in their id at least the dictionary specified as input. May return an attribute of each result if needed. Parameters • id (dict) – dictionary of the retrieved id. Return a list of the runs that have the id argument inside the provided id in the order provided by append_run(). • attribute (str) – if present, provide the attribute of each of the results instead of the result object

Example

>>> study=Dataset() >>> study.append_run(id={'cr':3},input={'dft':{'rmult':[3,8]}}) >>> study.append_run(id={'cr':4},input={'dft':{'rmult':[4,8]}}) >>> study.append_run(id={'cr':3,'h': 0.5}, >>> input={'dft':{'hgrids': 0.5,'rmult':[4,8]}}) >>> #append other runs if needed >>> study.run() #run the calculations >>> # returns a list of the energies of first and the third result in this

˓→example >>> data=study.fetch_results(id={'cr':3},attribute='energy')

ids = None List of run ids, to be used in order to classify and fetch the results names = None List of run names, needed for distinguishing the logfiles and input files. Eah name should be unique to correctly identify a run. post_processing(**kwargs) Calls the Dataset function with the results of the runs as arguments process_run() Run the dataset, by performing explicit run of each of the item of the runs_list. results = None Set of the results of each of the runs. The set is not ordered as the runs may be executed asynchronously. runs = None List of the runs which have to be treated by the dataset these runs contain the input parameter to be passed to the various runners. set_postprocessing_function(func) Set the callback of run. Calls the function func after having performed the appended runs. Parameters func (func) – function that process the inputs results and returns the value of the run method of the dataset. The function is called as func(self). BigDFT.Datasets.combine_datasets(*args) Define a new instance of the dataset class that should provide as a result a list of the runs of the datasets

22 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

(Py)BigDFT Tutorial page

2.7 (Py)BigDFT Tutorials

In this page you may found different tutorials and exercises that will help you in the usage of BigDFT. There are two main different categories, one associated to the usage of the code to perform calculations, and the second is more related to the post-processing tools that the PyBigDFT package offers to ease the extraction of scientific data. • Running the code

2.7.1 Basics of BigDFT: first runs and managing different calculations, N2 as example

With this lesson you will have to deal with some of the outputs of BigDFT code, such as to learn how to manipulate basic DFT objects from a python script. BigDFT can be also run in “traditional” way, i.e. with input and output files. We will here employ python commands to show how the I/O files of BigDFT can be handled by simple scripting techniques. First you need to have the correct environment variables: the script “bigdftvars.sh” from the install/bin directory of bigdft has to be sourced (“source bigdftvars.sh”) before doing this tutorial and load the module python BigDFT. See this page for more information. In [1]: from BigDFT import Calculators as calc The main executable of the BigDFT suite is bigdft.

Atomic position file: ‘posinp.xyz’

A simple file with the position of atoms is enough to run bigdft performing a single-point calculation (calculating the ground state energy of the system). Consider for example the N2 molecule, given by the posinp.xyz file: Copy it into the current directory. In [2]: study = calc.SystemCalculator() #Create a calculator study.run() #run the code Initialize a Calculator with OMP_NUM_THREADS=2 and command /local/binaries/gfortran-fpe-1.8/install/bin/bigdft Creating the yaml input file "input.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft Out[2]: The run() method of the BigDFT.Calculators.SystemCalculator class shows in the stan- dard output which is the command that is invoked. Then, an instance of the Logfile class is returned. Such class can be used (we will see after) to extract the information about the electronic structure of the system. In the disk, after that the run is performed, different files are created: * input_minimal.yaml which con- tains the minimal set of input variables to perform the run; * log.yaml which contains the log of the run with all calculated quantities; * time.yaml and forces_posinp.xyz which we will see later. For its I/O, bigdft uses the yaml format. If you look at the input_minimal.yaml file, you can see: In this case, only the atomic positions are indicated using a yaml format. In the log file log.yaml, BigDFT automatically displays all the input parameters used for the calculations.

2.7. (Py)BigDFT Tutorials 23 PyBigDFT Documentation, Release 0.1

The parameters which were not explicitly given are set to a default value, except the atomic positions of course, which have to be given. As we did not specified input files here, our run is a single-point LDA calculation, without spin-polarisation.

Using a naming scheme for Input/Output files

To specify non-default input parameters to the code, we should create a yaml file with a naming prefix. By default, this prefix is input (or posinp.xyz for atomic input positions). One can choose the naming prefix by providing an argument to bigdft command line. However, there is a one-to-one correspondence between a yaml file and a python dictionary. For this reason we will create the input parameters of this runs from dictionaries. See the useful yaml online parser page to understand the correspondence. Imagine for example that you are interested in visualizing the wavefunctions output of the calculation. To do that, you should enter the suitable parameters in the .yaml file. Create a new calculation set by using, for instance, the LDA prefix. Instead of creating a yaml input file LDA.yaml by hand, we create a dictionary which will be serialized into yaml by our SystemCalculator class. In [3]: inp = {} inp['dft'] = { 'ixc': 'LDA' } inp['output'] = { 'orbitals': 'binary' } #this is the parameter that output the orbitals on the disk This shows the one-to-one correspondence between the keys of the input file and the ones of the python dictionary. However, it might be uneasy, especially for beginners, to understand what is the function of each key -> value mapping, and even more importantly, to figure out how to adjust basic parameters like the grid spacing, the XC approximation and so on. In order to simplify the procedure, we have prepared the BigDFT.InputAction module, which is a collection of functions acting python dictionary equipped with basic methods and actions. For exemple, the above operations might be implmemented by calling methods of this module: In [6]: from BigDFT import InputActions as A inp={} A.set_xc(inp,'LDA') A.write_orbitals_on_disk(inp) The wavefunctions will be present at the end of calculation, by indicating the value of the key orbitals in the output dictionary. In [7]: #Run the code with the LDA prefix, using a python dictionary (dico) and the file 'posinp.xyz' for the atomic positions. lda = study.run(name="LDA",input=inp,posinp='posinp.xyz') Creating the yaml input file "./LDA.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n LDA Now we can retrieve important informations on the run. See the examples below: In [8]: lda.energy #this value is in Ha Out[8]: -19.883483725688038 In [9]: lda.evals[0].tolist() # the eigenvalues in Ha ([0] stands for the first K-point, here meaningless) Out[9]: [[-1.031892602676, -0.4970106443181, -0.4307276296665, -0.430727289646, -0.3812107719151]] In [10]: lda.get_dos().plot() #the density of states

24 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

When using a naming scheme, the output files are placed in a directory called data-LDA. In our LDA example, the wavefunctions of the system can thus be found in the data-LDA directory: In [11]: !ls data-LDA time-LDA.yaml wavefunction-k001-NR.bin.b000004 wavefunction-k001-NR.bin.b000001 wavefunction-k001-NR.bin.b000005 wavefunction-k001-NR.bin.b000002 wavefunction-rhoij.bin wavefunction-k001-NR.bin.b000003 Here 001 means the first K-point (meaningless in this case), N stands for non spin-polarized, R for real part and the remaining number is the orbital ID. Post-processing of these files is done in the another tutorial. In the same spirit, another calculation can be done with different parameters. Imagine we want to perform a Hartree-Fock calculation. In BigDFT, this can be done by putting the ixc input variable to HF. So, we use the same dictionary changing only the dft key. We add also a posinp key to indicate what atomic positions file we use (this was done when we indicate posinp=’posinp.xyz’ into the run method). In [12]: A.set_xc(inp,'HF') A.set_atomic_positions(inp,'posinp.xyz') hf = study.run(name="HF",input=inp) #Run the code with the name scheme HF Creating the yaml input file "./HF.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n HF ERROR: some problem occured during the execution of the command, check the 'debug/' directory and the logfile The error occured is BIGDFT_INPUT_FILE_ERROR Additional Info: The parameter file "psppar.N" is lacking, and no registered pseudo found for "N" This time, an error will occur, as we can see above. The same error is specified at the end of the file log-HF.yaml and also in debug/bigdft-err-0.yaml: This is because the pseudopotential is assigned by default in the code only for LDA and PBE XC ap- proximations. You can find here the pseudopotential which is taken by default in the LDA run. Put it in

2.7. (Py)BigDFT Tutorials 25 PyBigDFT Documentation, Release 0.1

a psppar.N file, and run the calculation. Another alternative is to specify the internal PSP that might be used, taking from the default database of BigDFT. This can be done as follows: In [13]: inp['psppar.N']={'Pseudopotential XC': 1} #here 1 stands for LDA as per the XC codes hf = study.run(name="HF",input=inp) #Run the code with the name scheme HF Creating the yaml input file "./HF.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n HF When possible, care should be taken in choosing a pseudopotential which has been generated with the same XC approximation used. Unfortunately, at present HGH data are only available for semilocal func- tionals. For example, the same exercise as follows could have been done with Hybrid XC functionals, like for example PBE0 (ixc=-406). See the XC codes for a list of the supported XC functionals. Data of the calculations can be analysed. In [14]: A.set_xc(inp,'PBE0') pbe0 = study.run(name="PBE0",input=inp) #Run the code with the name scheme PBE0 Creating the yaml input file "./PBE0.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n PBE0 The variables lda, hf, and pbe0 contains all information about the calculation. This is a class Logfile which simplify considerably the extraction of parameters of the associated output file log-LDA.yaml. If we simply type: In [15]: from futile.Utils import write write(lda) - Atom types: -N - Cell: Free BC - Convergence criterion on forces: 0.0 - Max val of Forces: 0.05670554140672 - Energy: -19.883483725688038 - Symmetry group: disabled - fermi_level: -0.3812107719151 - Number of Atoms: 2 - Convergence criterion on Wfn. Residue: 0.0001 - No. of KS orbitals: - 5

we display some information about the LDA calculation. For instance, we can extract the eigenvalues of the Hamiltonian i.e. the DOS (Density of States): In [16]: lda.evals[0].tolist() Out[16]: [[-1.031892602676, -0.4970106443181, -0.4307276296665, -0.430727289646, -0.3812107719151]] lda.log is the python dictionary associated to the full output file. The tutorial explains the basic methods. The following exercise (and its solution) gives some clues about it. In [17]: write(pbe0) - Atom types: -N - Cell: Free BC - Convergence criterion on forces: 0.0 - Max val of Forces: 0.1001956813857 - Energy: -19.968681994148028

26 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

- Symmetry group: disabled - fermi_level: -0.4502961029675 - Number of Atoms: 2 - Convergence criterion on Wfn. Residue: 0.0001 - No. of KS orbitals: - 5

Exercise Compare the values of the HOMO and HOMO-1 eigenvalues for the LDA and the HF run. Change the values of the hgrid and crmult to find the converged values. Note that, both in the LDA and in the HF calculation, a norm-conserving PSP is used. The results can be compared to all-electron calculations, done with different basis sets, from references (units are eV) (1) S. Hamel et al. J. Electron Spectrospcopy and Related Phenomena 123 (2002) 345-363 and (2) P. Politzer, F. Abu-Awwad, Theor. Chem. Acc. (1998), 99, 83-87:

LDA(1)HF(1)HF(2)(Exp.)

3휎g 10.36 17.25 17.31 (15.60) 1휋u

11.8416.7117.02(16.98)

2휎u 13.41 21.25 21.08 (18.78) The results depends, of course, on the precision chosen for the calculation, and of the presence of the pseudopotential. As it is well-known, the pseudopotential appoximation is however much less severe than the approximation induced by typical XC functionals. We might see that, even in the HF case, the presence of a LDA-based pseudopotential (of rather good quality) does not alter so much the results. Here you can find the values from BigDFT calculation using a very good precision (hgrid=0.3, crmult=7.0). Note that 1 ha=27.21138386 eV.

LDAHF

3휎g 10.40 17.32 1휋u

11.7516.62

2.7. (Py)BigDFT Tutorials 27 PyBigDFT Documentation, Release 0.1

2휎u 13.52 21.30 How much do these values differ from the calculation with default parameters? Do they converge to a given value? What is the correlation for the N2 molecule in (PSP) LDA? See here the solution. In [ ]:

2.7.2 Solution of N2 exercise: Handling the log files

In this tutorial, we will learn how to avoid to read directly the logfiles log.yaml, log-LDA.yaml, log- HF.yaml and log-PBE0.yaml where all information about the calculation are stored. because the logfile is a serialized python dictionary written in yaml, it is possible using the yaml module to convert it into a python dictionary and process it. In order to simplify this step, we will use the Logfile class which has nice method to extract easily the information. This tutorial explains the basics of the Logfile class. Exercise Compare the values of the HOMO and HOMO-1 eigenvalues for the LDA and the HF run. Change the values of the hgrid and crmult to find the converged values. Note that, both in the LDA and in the HF calculation, a norm-conserving PSP is used. The results can be compared to all-electron calculations, done with different basis sets, from references (units are eV) (1) S. Hamel et al. J. Electron Spectrospcopy and Related Phenomena 123 (2002) 345-363 and (2) P. Politzer, F. Abu-Awwad, Theor. Chem. Acc. (1998), 99, 83-87:

LDA(1)HF(1)HF(2)(Exp.)

3휎g 10.36 17.25 17.31 (15.60) 1휋u

11.8416.7117.02(16.98)

2휎u 13.41 21.25 21.08 (18.78) The results depends, of course, on the precision chosen for the calculation, and of the presence of the pseudopotential. As it is well-known, the pseudopotential appoximation is however much less severe than the approximation induced by typical XC functionals. We might see that, even in the HF case, the presence of a LDA-based pseudopotential (of rather good quality) does not alter so much the results. Here

28 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

you can find the values from BigDFT calculation using a very good precision (hgrid=0.3, crmult=7.0). Note that 1 ha=27.21138386 eV.

LDAHF

3휎g 10.40 17.32 1휋u

11.7516.62

2휎u 13.52 21.30 How much do these values differ from the calculation with default parameters? Do they converge to a given value? What is the correlation for the N2 molecule in (PSP) LDA? In [5]: from BigDFT import Calculators as calc #Import the python modules needed from BigDFT import Logfiles as lf from BigDFT import InputActions as A

HtoeV = 27.21138386 #Conversion Hartree to meV

dico = dict()

A.set_atomic_positions(dico,'posinp.xyz') study = calc.SystemCalculator() #Create a calculator

A.set_xc(dico,'LDA') LDA = study.run(name="LDA",input=dico,skip=True) #Run the code with the name scheme LDA A.set_xc(dico,'HF') HF = study.run(name="HF",input=dico,skip=True) #Run the code with the name scheme HF A.set_xc(dico,'PBE0') PBE0 = study.run(name="PBE0",input=dico,skip=True) #Run the code with the name scheme HF Initialize a Calculator with OMP_NUM_THREADS=2 and command /local/binaries/gfortran-fpe-1.8/install/bin/bigdft Creating the yaml input file "./LDA.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n LDA -s Yes Creating the yaml input file "./HF.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n HF -s Yes Creating the yaml input file "./PBE0.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n PBE0 -s Yes The variables first, LDA, HF and PBE0 are instances of the class BigDFT.Logfiles.Logfile which contain all information as the total energy. We should also use directly this call loading the corresponding output file as In [6]: PBE0 = lf.Logfile("log-PBE0.yaml") We compare the values of HOMO-1 and HOMO for LDA and HF. In [7]: lda_evals = LDA.evals[0][0] hf_evals = HF.evals[0][0] print "LDA",lda_evals[-3:]*HtoeV print "HF", hf_evals[-3:]*HtoeV

2.7. (Py)BigDFT Tutorials 29 PyBigDFT Documentation, Release 0.1

LDA [-11.72069487 -11.72068562 -10.37327265] HF [-17.31174049 -16.60642809 -16.60642409]

Modifications of the calculation parameters

Then we do a convergence curve varying hgrid which controls the grid step of the Daubechies and crmult the extension. The default values are: In [8]: print 'hgrids',LDA.log['dft']['hgrids'] print 'rmult',LDA.log['dft']['rmult'] hgrids [0.45, 0.45, 0.45] rmult [5.0, 8.0] hgrids is an array of 3 values for the x, y, and z direction. A simple scalar can be indicated for the input. rmult is composed into two multiplied factors, one for the coarse grid, and the second one for the fine grid. We build our script for LDA and run it (on one core, it takes 10 minutes roughly for all calculations). Todo: This part has to be modernized with the new input file syntax and dataset retrieval In [5]: Hgrids = [0.45, 0.40, 0.35, 0.30, 0.25] Crmult = [3.0, 5.0, 7.0, 9.0] dico = lf.Logfile('LDA.yaml').log #Build the dictionary in order to change it (yaml.load with import yaml could be another way) dico['dft'] = LDA.log['dft'] #Add the dictionary coming from the logfile (which can be also used as an input file) log_LDA = {} emin_LDA = 0.0 for crmult in Crmult: log_LDA[crmult] = [] for hgrid in Hgrids: A.set_hgrid(dico,hgrid) dico['dft']['rmult'] = [ crmult, 8.0] name = "LDA-%4.2f-%04.1f" % (hgrid,crmult) log = study.run(name=name,input=dico,skip=True) log_LDA[crmult].append( log ) emin_LDA =min(emin_LDA,log.energy) Creating from a dictionary the yaml input file "LDA-0.45-03.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.45-03.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.40-03.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.40-03.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.35-03.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.35-03.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.30-03.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.30-03.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.25-03.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.25-03.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.45-05.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.45-05.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.40-05.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.40-05.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.35-05.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.35-05.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.30-05.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.30-05.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.25-05.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.25-05.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.45-07.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.45-07.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.40-07.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.40-07.0 -s Yes

30 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

Creating from a dictionary the yaml input file "LDA-0.35-07.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.35-07.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.30-07.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.30-07.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.25-07.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.25-07.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.45-09.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.45-09.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.40-09.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.40-09.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.35-09.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.35-09.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.30-09.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.30-09.0 -s Yes Creating from a dictionary the yaml input file "LDA-0.25-09.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n LDA-0.25-09.0 -s Yes We do the same loops to run the Hartree-Fock calculations. In [6]: dico = lf.Logfile('HF.yaml').log #Build the dictionary in order to change it (yaml.load with import yaml could be another way) dico['dft'] = HF.log['dft'] #Add the dictionary coming from the logfile (which can be also used as an input file) log_HF = {} emin_HF = 0.0 for crmult in Crmult: log_HF[crmult] = [] for hgrid in Hgrids: dico['dft']['hgrids'] = hgrid dico['dft']['rmult'] = [ crmult, 8.0] name = "HF-%4.2f-%04.1f" % (hgrid,crmult) log = study.run(name=name,input=dico,skip=True) log_HF[crmult].append(log) emin_HF = min(emin_HF,log.energy) Creating from a dictionary the yaml input file "HF-0.45-03.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.45-03.0 -s Yes Creating from a dictionary the yaml input file "HF-0.40-03.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.40-03.0 -s Yes Creating from a dictionary the yaml input file "HF-0.35-03.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.35-03.0 -s Yes Creating from a dictionary the yaml input file "HF-0.30-03.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.30-03.0 -s Yes Creating from a dictionary the yaml input file "HF-0.25-03.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.25-03.0 -s Yes Creating from a dictionary the yaml input file "HF-0.45-05.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.45-05.0 -s Yes Creating from a dictionary the yaml input file "HF-0.40-05.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.40-05.0 -s Yes Creating from a dictionary the yaml input file "HF-0.35-05.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.35-05.0 -s Yes Creating from a dictionary the yaml input file "HF-0.30-05.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.30-05.0 -s Yes Creating from a dictionary the yaml input file "HF-0.25-05.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.25-05.0 -s Yes Creating from a dictionary the yaml input file "HF-0.45-07.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.45-07.0 -s Yes Creating from a dictionary the yaml input file "HF-0.40-07.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.40-07.0 -s Yes Creating from a dictionary the yaml input file "HF-0.35-07.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.35-07.0 -s Yes Creating from a dictionary the yaml input file "HF-0.30-07.0.yaml"

2.7. (Py)BigDFT Tutorials 31 PyBigDFT Documentation, Release 0.1

Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.30-07.0 -s Yes Creating from a dictionary the yaml input file "HF-0.25-07.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.25-07.0 -s Yes Creating from a dictionary the yaml input file "HF-0.45-09.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.45-09.0 -s Yes Creating from a dictionary the yaml input file "HF-0.40-09.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.40-09.0 -s Yes Creating from a dictionary the yaml input file "HF-0.35-09.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.35-09.0 -s Yes Creating from a dictionary the yaml input file "HF-0.30-09.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.30-09.0 -s Yes Creating from a dictionary the yaml input file "HF-0.25-09.0.yaml" Executing command: /local/deutsch/Forge/BigDFT/build-mpif90/install/bin/bigdft -n HF-0.25-09.0 -s Yes In [7]: import matplotlib.pyplot as plt import numpy as np %matplotlib inline # Lists of markers and colors (for matplotlib) colors = ['#74a9cf', '#2b8cbe', '#045a8d', '#009900', '#FF8000'] colors = ['#000000', '#ff0000', '#045a8d', '#009900', '#FF8000'] markers = ['o','s','d','d','d']

plt.figure(figsize=(15,7)) # Plot with matplotlib for i,crmult in enumerate(Crmult): im = i%len(colors) ener = [ HtoeV*(l.energy-emin_LDA) for l in log_LDA[crmult] ] plt.plot(Hgrids, ener, marker=markers[im], ls='-', label=str(crmult),color=colors[im])

plt.yscale('log') plt.xlabel('Grid step (Bohr)') plt.ylabel('Total energy $\Delta E$ (eV)') plt.title('Dissociation energy of the N2 dimer for different rmult') plt.legend(loc=4) plt.show()

In [8]: plt.figure(figsize=(15,7)) # Plot with matplotlib for i,crmult in enumerate(Crmult):

32 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

im = i%len(colors) ener = [ HtoeV*(l.energy-emin_HF) for l in log_HF[crmult] ] plt.plot(Hgrids, ener, marker=markers[im], ls='-', label=str(crmult),color=colors[im])

plt.yscale('log') plt.xlabel('Grid step (Bohr)') plt.ylabel('Total energy $\Delta E$ (eV)') plt.title('Dissociation energy of the N2 dimer for different crmult') plt.legend(loc=4) plt.show()

In order to converge the result, you need to decrease the grid step and also increase the extension of the mesh. For a given crmult, the curve are almost flat. For a hgrid value of of 0.35, there is few difference between the values with crmult=5.0 and 7.0 but for a hgrid value of 0.20 it is important. Now we give the HOMO-1 and HOMO eigenvalues both for LDA and HF functionals In [9]: ih = Hgrids.index(0.3) lda_evals = log_LDA[7.0][ih].evals[0][0] hf_evals = log_HF[7.0][ih].evals[0][0] print "LDA HF" for (l,h) in zip(reversed(lda_evals),reversed(hf_evals)): print "%5.2f %5.2f" % (-HtoeV*l, -HtoeV*h) LDA HF 10.40 16.63 11.75 16.63 11.75 17.32 13.52 21.30 28.08 39.83

2.7.3 Usage of SystemCalculator Instance

We here provide some examples on how to run the code with system calculator. Let us consider a very simple inputfile and a small system, that can be give from file and from a dictionary of atomic positions. In [1]: from BigDFT import Inputfiles as I from BigDFT.Calculators import SystemCalculator from futile.Utils import write

2.7. (Py)BigDFT Tutorials 33 PyBigDFT Documentation, Release 0.1

inp=I.Inputfile() inp.set_xc('PBE') inp.set_rmult(coarse=3) #very very little, only for test inp Out[1]: {'dft': {'ixc': 'PBE', 'rmult': [3, 8.0]}} We initalize the SystemCalculator instance by specifying the number of OMP threads and the command to be used for the mpirun calculation. In [2]: code=SystemCalculator(omp=1,mpi_run='mpirun -np 2') Initialize a Calculator with OMP_NUM_THREADS=1 and command mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft Let us define the function for validating the runs: In [3]: def validate_run(inputfile,logfile): """ Checks that the inputfile and the logfiles exists and have recent dates. """ import os.path as P from futile.Utils import write,file_time from time import time write('Input and log existing',P.isfile(inputfile),P.isfile(logfile)) write('Created since',time()-file_time(inputfile),time()-file_time(logfile))

Basic run, no name and atomic positions from a file: In [4]: result=code.run(input=inp,posinp='CH4_posinp.xyz') write('Energy',result.energy) validate_run('input.yaml','log.yaml') Creating the yaml input file "./input.yaml" Executing command: mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft Energy -8.09733985003 Input and log existing True True Created since 2.02708792686 0.0871000289917 Now let us provide a naming scheme. The inputfile and the logfile will have different names: In [5]: result=code.run(input=inp,posinp='CH4_posinp.xyz',name='test1') write('Energy',result.energy) validate_run('test1.yaml','log-test1.yaml') Creating the yaml input file "./test1.yaml" Executing command: mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft -n test1 Energy -8.09733985003 Input and log existing True True Created since 1.93355202675 0.0256290435791 Let us now provide a output directory. To do that there are two different options: * Provide the outdir command to the bigdft executable * Define a run_dir for the run of the calculator instance. The difference between the two is the position of the input files. In the first case they will be in the Current Working Directory, whereas in the second one they will be placed in the run_directory. In [6]: from os.path import join as j #first case result=code.run(input=inp,posinp='CH4_posinp.xyz',name='test2',outdir='out1') write('Energy',result.energy) validate_run('test2.yaml',j('out1','log-test2.yaml')) #second case result=code.run(input=inp,posinp='CH4_posinp.xyz',name='test3',run_dir='out2') write('Energy',result.energy)

34 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

validate_run(j('out2','test3.yaml'),j('out2','log-test3.yaml')) #combine the two result=code.run(input=inp,posinp='CH4_posinp.xyz',name='test4',run_dir='out3',outdir='out4') write('Energy',result.energy) validate_run(j('out3','test4.yaml'),j('out3','out4','log-test4.yaml'))

Creating the yaml input file "./test2.yaml" Executing command: mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft -n test2 -d out1 Energy -8.09733985003 Input and log existing True True Created since 1.86937189102 0.0214099884033 Create the sub-directory 'out2' Copy the posinp file 'CH4_posinp.xyz' into 'out2' Creating the yaml input file "out2/test3.yaml" Run directory out2 Executing command: mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft -n test3 Energy -8.06514886077 Input and log existing True True Created since 1.96282911301 0.0228381156921 Create the sub-directory 'out3' Copy the posinp file 'CH4_posinp.xyz' into 'out3' Creating the yaml input file "out3/test4.yaml" Run directory out3 Executing command: mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft -n test4 -d out4 Energy -8.06514886077 Input and log existing True True Created since 1.95026421547 0.0226290225983 In [ ]:

2.7.4 Usage of Dataset class

We here show the API of the Dataset class, conceived to run and collects ensemble calculations. In [1]: from BigDFT import Datasets as D, Calculators as C, Inputfiles as I In [2]: from BigDFT.Database import CO=Molecules.Molecule('CO') print CO {'units': 'angstroem', 'positions': [{'C': [0.0, 0.0, 0.0], 'sym': 'C'}, {'sym': 'O', 'O': [0.0, 0.0, 1.1282]}], 'global monopole': 0.0} In [3]: inp=I.Inputfile({'dft': {'rmult': [3,8]}}) In [4]: code=C.SystemCalculator(omp=2,mpi_run='mpirun -np 2') Initialize a Calculator with OMP_NUM_THREADS=2 and command mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft In [5]: reload(D) Out[5]: In [6]: study=D.Dataset(label='CO',run_dir='CO',posinp=CO) In [7]: inp.set_rmult(coarse=3) study.append_run(id={'crmult': 3}, runner= code, input=inp,skip=False) inp.set_rmult(coarse=4) study.append_run(id={'crmult': 4}, runner= code, input=inp) inp.set_rmult(coarse=5) study.append_run(id={'crmult': 5}, runner= code, input=inp) In [8]: code.update_global_options(skip=False)

2.7. (Py)BigDFT Tutorials 35 PyBigDFT Documentation, Release 0.1

In [9]: data=study.run() Creating the yaml input file "CO/crmult:3.yaml" Run directory CO Executing command: mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft -n crmult:3 Creating the yaml input file "CO/crmult:4.yaml" Run directory CO Executing command: mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft -n crmult:4 Creating the yaml input file "CO/crmult:5.yaml" Run directory CO Executing command: mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft -n crmult:5 In [10]: study.fetch_results(attribute='energy') Out[10]: [-21.611635946132814, -21.64835568408899, -21.651311269276533] In [11]: for d in range(len(study.runs)): print study.runs[d] print study.results[d].energy {'run_dir': 'CO', 'input': {'dft': {'rmult': [3, 8.0]}}, 'posinp': {'units': 'angstroem', 'positions': [{'C': [0.0, 0.0, 0.0], 'sym': 'C'}, {'O': [0.0, 0.0, 1.1282], 'sym': 'O'}], 'global monopole': 0.0}, 'skip': False, 'label': 'CO'} -21.6116359461 {'run_dir': 'CO', 'input': {'dft': {'rmult': [4, 8.0]}}, 'posinp': {'units': 'angstroem', 'positions': [{'C': [0.0, 0.0, 0.0], 'sym': 'C'}, {'O': [0.0, 0.0, 1.1282], 'sym': 'O'}], 'global monopole': 0.0}, 'label': 'CO'} -21.6483556841 {'run_dir': 'CO', 'input': {'dft': {'rmult': [5, 8.0]}}, 'posinp': {'units': 'angstroem', 'positions': [{'C': [0.0, 0.0, 0.0], 'sym': 'C'}, {'O': [0.0, 0.0, 1.1282], 'sym': 'O'}], 'global monopole': 0.0}, 'label': 'CO'} -21.6513112693

2.7.5 Polarizability tensor of a molecule

In [87]: inp=I.Inputfile() mol=Molecules.Molecule('CO') #mol['positions'][1]['O']=[0.0,0.0,1.12016] #our positions inp.set_xc('PBE') inp.set_hgrid('0.37') inp.set_rmult(coarse=11) logGS=code.run(input=inp,posinp=mol,name='CO-GS') Creating the yaml input file "./CO-GS.yaml" Executing command: mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft -n CO-GS In [88]: import numpy as np intensity=-1.e-2 PolTensor=D.Dataset(label='Poltensor',run_dir='polt',input=inp,posinp=mol,d0=logGS.dipole,F=intensity) for idir,coord in enumerate(['x','y','z']): el=np.zeros(3) el[idir]=intensity inp.apply_electric_field(el.tolist()) PolTensor.append_run({'id': coord,'F':intensity},code,input=inp) In [89]: def extract_alpha(PolT): d0=np.array(PolT.get_global_option('d0')) F=PolT.get_global_option('F') ds=PolT.fetch_results(attribute='dipole') alpha=np.mat(np.zeros(9)).reshape(3,3) for idir in range(3): alpha[idir]=(np.array(ds[idir])-d0)/F return alpha In [90]: code.update_global_options(skip=False) In [91]: PolTensor.set_postprocessing_function(extract_alpha) In [92]: alpha=PolTensor.run()

36 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

Creating the yaml input file "polt/F:-0.01,id:x.yaml" Run directory polt Executing command: mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft -n F:-0.01,id:x Creating the yaml input file "polt/F:-0.01,id:y.yaml" Run directory polt Executing command: mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft -n F:-0.01,id:y Creating the yaml input file "polt/F:-0.01,id:z.yaml" Run directory polt Executing command: mpirun -np 2 /home/marco/Applications/BigDFT/binaries/v1.8.3/install/bin/bigdft -n F:-0.01,id:z In [50]: alpha1=_ In [51]: alpha1 Out[51]: matrix([[ 1.26423306e+01, 3.50890610e-03, -3.31700000e-02], [ 3.50890610e-03, 1.26423306e+01, -3.31700000e-02], [ 3.70690000e-05, 3.70690000e-05, 1.58543700e+01]]) In [64]: alpha2=alpha In [65]: alpha1 Out[65]: matrix([[ 1.26423306e+01, 3.50890610e-03, -3.31700000e-02], [ 3.50890610e-03, 1.26423306e+01, -3.31700000e-02], [ 3.70690000e-05, 3.70690000e-05, 1.58543700e+01]]) In [57]: alpha2 Out[57]: {0: , 1: , 2: } In [85]: alpha Out[85]: matrix([[ 1.26686738e+01, -3.23449840e-03, 3.77370000e-02], [-3.23449840e-03, 1.26686738e+01, 3.77370000e-02], [-1.11158900e-03, -1.11158900e-03, 1.58224360e+01]])

In [68]: a=0.5*(alpha1+alpha2) In [93]: np.mean(np.diag(alpha))*(0.529177**3) Out[93]: 2.1334035481704943 In [ ]:

2.7.6 Running a wavelet computation on a 퐶퐻4 molecule

The purpose of this lesson is to get familiar with the basic variables needed to run a wavelet computation in isolated boundary conditions. At the end of the lesson, you can run a wavelet run, check the amount of needed memory and understand the important part of the output. We propose to use python in a Jupyter notebook to simplify the use of the bigdft executable and to have tools to combine pre-processing, execution, post-processing and analysis.

Introduction: Running the code

As already explained in the N2 molecule tutorial.bigdft uses dictionaries (a collection of pairs of key and value) for the input and output which are serialized by means of the yaml format. This allows us to manipulate dictionaries instead of files and define simple actions on them for the basic code operations, instead of manually modifying the input keys.

2.7. (Py)BigDFT Tutorials 37 PyBigDFT Documentation, Release 0.1

We here introduce the BigDFT.Inputfiles.Inpufile class, which is a generalisation of a python dictionary and that has as class methods the same methods that are available in the BigDFT. InputActions module. In [1]: #the dictionary below: inp = { 'dft': { 'hgrids': 0.55, 'rmult': [3.5, 9.0]} } # becomes from BigDFT import Inputfiles as I inp=I.Inputfile() inp.set_hgrid(0.55) inp.set_rmult([3.5,9.0]) Beside a default input file called input.yaml, BigDFT requires the atomic positions for the studied system and optionaly the pseudo-potential files. For the following tutorial, a methane molecule will be used. The position file is a simple XYZ file named CH4_posinp.xyz: We can copy this file into the default posinp file posinp.xyz as cp CH4_posinp.xyzz posinp.xyz or indicate it in the input dictionary: In [2]: inp.set_atomic_positions('CH4_posinp.xyz') The pseudo-potential files are following the ABINIT structure and are of GTH or HGH types (see the pseudo-potential file page on the ABINIT website for several LDA and GGA files and the page on the CP2K server for HGH pseudo for several functionals). The following files may be used for this tutorial: **psppar.C** and **psppar.H**. Warning, to run properly, the pseudo-potential files must be psppar.XX where XX is the symbol used in the position file. The other files can have user-defined names, as explained in Tutorial-N2.ipynb lesson. If the code has been compiled with MPI capabilities (which is enabled by default), running BigDFT on several cores is as easy as run it as a serial job. There is no need to change anything in the input files. Running BigDFT is done using the bigdft executable in a standard Unix way. In this notebook, we use the SystemCalculator class: In [3]: from BigDFT import Calculators as calc reload(calc) study = calc.SystemCalculator() #Create a calculator ch4 = study.run(input=inp) Initialize a Calculator with OMP_NUM_THREADS=2 and command /local/binaries/gfortran-fpe-1.8/install/bin/bigdft Creating the yaml input file "./input.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft ch4 is the instance of the class Logfile which can handle easily all information coming from the output file log.yaml. Then we can display some information as: In [4]: print ch4 - Atom types: -C -H - Cell: Free BC - Convergence criterion on forces: 0.0 - Max val of Forces: 0.0214711014196 - Energy: -8.025214366429553 - Symmetry group: disabled - fermi_level: -0.3414840466884 - Number of Atoms: 5 - Convergence criterion on Wfn. Residue: 0.0001 - No. of KS orbitals: - 4

38 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

2.7.7 The wavelet basis set, a convergence study

Daubechies is a systematic basis set (as plane waves are), which means than one can increase arbitrarily the accuracy of the results by varying some parameters which are defined in the dft dictio- nary (inp['dft']). We here explain what are the meaning and the typical values for the principal parameters, hgrid and rmult.

Fig. 1: CH4-grid

‘‘hgrids‘‘ are used to set up the basis set. In free boundary conditions, the basis set is characterised by a spatial expansion and a grid step, as shown in the side figure. There is ‘’one float value” describing the ‘’grid steps” in the three space directions (‘’i.e.” x, y and z) or a 3D array is also accepted. These values are in bohr unit and typically range from 0.3 to 0.65. The harder the pseudo-potential, the lower value should be set up. These values are called hgrids in the input dictionary, and can be set by the set_hgrid method of the Inpufile class. ‘‘rmult‘‘ contains an array of two float values that are two multiplying factors. They multiply quantities that are chemical species dependent. The first factor is the most important since it describes ‘’the spatial expansion” of the basis set (in yellow on the figure beside). Indeed the basis set is defined as a set of real space points with non-zero values. These points are on a global regular mesh and located inside spheres centered on atoms. The first multiplying factor is called crmult for Coarse grid Radius MULTiplier. Increasing it means that further spatial expansion is possible for the wavefunctions. Typical values are 5 to 7. The second one called frmult for Fine grid Radius MULTiplier is related to the fine resolution. This parameter is less pertinent for the convergence of energy and can be ignored. It is possible to indicate only one float value, the crmult parameter. Such parameters can be set by the method set_rmult of Inputfile class.

Exercise

Run BigDFT for the following values of hgrid and crmult and plot the total energy convergence versus hgrids. The final total energy can be retrieved using th emethod energy from the result of each of the runs. The unit of the energies is in Hartree. This tutorial also explains how to use the Dataset class. This precision plot shows the systematicity of the wavelet basis set: by improving the basis set, we improve the absolute value of the total energy.

2.7. (Py)BigDFT Tutorials 39 PyBigDFT Documentation, Release 0.1

Indeed, there are two kind of errors arising from the basis set. The first one is due to the fact the basis set can’t account for quickly varying wavefunctions (value of hgrids should be decreased). The second error is the fact that the wavefunctions are constrained to stay inside the defined basis set (output values are zero). In the last case crmult should be raised.

2.7.8 Construction of the input dataset dictionaries

Let us build three different dataset of inputfiles, the first two varying hgrid and crmult and the last by varying the two toghether. We also label each of the input dictionaries by a unique name identifying the run. In [ ]: from BigDFT import Datasets as D h_and_c_dataset=D.Dataset('h_and_c') for h,c in zip(hgrids,crmult): inp_run=copy.deepcopy(inp) inp_run['dft']['hgrids'] = h inp_run['dft']['rmult'] = [c,9.0] #only change crmult label_run='h='+str(h)+'c='+str(c) h_and_c_dataset.append({'name': label_run,'input': inp_run}) In [20]: import copy hgrids = [ 0.55 - i*0.05 for i in range(8)] crmult = [ 3.5 + i*0.5 for i in range(8)] In [6]: h_only_dataset=[] for h in hgrids: inp_run=copy.deepcopy(inp) inp_run['dft']['hgrids'] = h label_run='h='+str(h) h_only_dataset.append({'name': label_run,'input': inp_run}) In [7]: c_only_dataset=[] for c in crmult: inp_run=copy.deepcopy(inp) inp_run['dft']['rmult'] = [c,9.0] #only change crmult label_run='c='+str(c) c_only_dataset.append({'name': label_run,'input': inp_run}) In [8]: h_and_c_dataset=[] for h,c in zip(hgrids,crmult): inp_run=copy.deepcopy(inp) inp_run['dft']['hgrids'] = h inp_run['dft']['rmult'] = [c,9.0] #only change crmult label_run='h='+str(h)+'c='+str(c) h_and_c_dataset.append({'name': label_run,'input': inp_run}) We then define a function that runs the calculation written in the dataset and store their result in a corre- sponding dictionary key log: In [9]: def run_dataset(dataset): for configuration in dataset: if 'log' not in configuration: configuration['log']=study.run(name=configuration['name'],input=configuration['input']) #the same command could have been written as #configuration['log']=study.run(**configuration) We then run the three datasets: In [10]: run_dataset(h_only_dataset) run_dataset(c_only_dataset) run_dataset(h_and_c_dataset)

40 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

Creating the yaml input file "h=0.55.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.55 Creating the yaml input file "h=0.5.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.5 Creating the yaml input file "h=0.45.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.45 Creating the yaml input file "h=0.4.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.4 Creating the yaml input file "h=0.35.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.35 Creating the yaml input file "h=0.3.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.3 Creating the yaml input file "h=0.25.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.25 Creating the yaml input file "h=0.2.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.2 Creating the yaml input file "c=3.5.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n c=3.5 Creating the yaml input file "c=4.0.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n c=4.0 Creating the yaml input file "c=4.5.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n c=4.5 Creating the yaml input file "c=5.0.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n c=5.0 Creating the yaml input file "c=5.5.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n c=5.5 Creating the yaml input file "c=6.0.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n c=6.0 Creating the yaml input file "c=6.5.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n c=6.5 Creating the yaml input file "c=7.0.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n c=7.0 Creating the yaml input file "h=0.55c=3.5.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.55c=3.5 Creating the yaml input file "h=0.5c=4.0.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.5c=4.0 Creating the yaml input file "h=0.45c=4.5.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.45c=4.5 Creating the yaml input file "h=0.4c=5.0.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.4c=5.0 Creating the yaml input file "h=0.35c=5.5.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.35c=5.5 Creating the yaml input file "h=0.3c=6.0.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.3c=6.0 Creating the yaml input file "h=0.25c=6.5.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.25c=6.5 Creating the yaml input file "h=0.2c=7.0.yaml" Executing command: /local/binaries/gfortran-fpe-1.8/install/bin/bigdft -n h=0.2c=7.0 We now store the energies of each of the dataset runs, and identify the minimum as the minimum value from the h_and_c dataset: In [14]: import matplotlib.pyplot as plt import numpy as np energies_h=np.array([c['log'].energy for c in h_only_dataset]) energies_c=np.array([c['log'].energy for c in c_only_dataset]) energies_hc=np.array([c['log'].energy for c in h_and_c_dataset]) #find the minimum emin=np.min(energies_hc)

2.7. (Py)BigDFT Tutorials 41 PyBigDFT Documentation, Release 0.1

We plot the energy values varying the grid spacing or the extension In [21]: %matplotlib inline plt.xlabel('Grid step (Bohr)') plt.plot(hgrids,energies_h-emin,label='crmult=3.5') plt.plot(hgrids,energies_hc-emin,label='varying hgrids+crmult') plt.yscale('log') plt.legend(loc='best') Out[21]:

In [22]: plt.xlabel('Crmult value') plt.plot(crmult,energies_c-emin,label='hgrid=0.55') plt.plot(crmult,energies_hc-emin,label='varying hgrids+crmult') plt.yscale('log') plt.legend(loc='best') Out[22]:

42 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

Considerations

We see that both the parameters hgrids and rmult have to be decreased and increased (respectively) in order to achieve convergence. Increasing only one of the two parameter will eventually lead to saturation of the absolute error on the energy. In [ ]: import matplotlib.pyplot as plt import numpy as np

HtoeV = 27.21138386 #Conversion Hartree to meV

emin = HtoeV*results[-1].energy ener = [ HtoeV*l.energy - emin for l in results ]

ener2 = [ HtoeV*l.energy - emin for l in res2 ]

plt.figure(figsize=(15,7)) # Plot with matplotlib plt.plot(Hgrids, ener, marker='o', ls='-', color='#ff0000', label='varying hgrids+crmult') plt.plot(Hgrids, ener2, marker='s', ls='-', color='#888888', label='crmult=3.5')

plt.yscale('log') plt.xlim(0.55,0.25) plt.xlabel('Grid step (Bohr)') plt.ylabel('Total energy precision (eV)') plt.title('Total energy convergence versus the grid step for the CH$_4$ molecule') plt.legend(loc=3) plt.show() In [ ]:

2.7. (Py)BigDFT Tutorials 43 PyBigDFT Documentation, Release 0.1

Fine tuning of the basis set

The multi-scale property of the wavelets is used in BigDFT and a two level grid is used for the calculation. We’ve seen previously the coarse grid definition using the the multiplying factor rmult. The second multiplying value on this line of the input file is used for the fine grid and is called frmult. Like crmult, it defines a factor for the radii used to define the fine grid region where the number of degrees of freedom is indeed eight times the one of the coarse grid. It allows to define region near the atoms where the wavefunctions are allowed to vary more quickly. Typical values for this factor are 8 to 10. It’s worth to note that even if the value of the multiplier is greater than crmult it defines a smaller region due to the fact that the units which are associated to these radii are significantly different. The physical quantities used by crmult and frmult can be changed in the pseudo-potential by adding an additional line with two values in bohr. The two values that the code is using (either computed or read from the pseudo-potential files) are output in the following way in the screen output:

Analysing the output

The output of BigDFT is divided into four parts: * Input values are printed out, including a summary of the different input files (DFT calculation parameters, atom positions, pseudo-potential values. . . ); * Input wavefunction creation, usually called “input guess”; * The SCF (Self-Consistent Field) loop itself; * The post SCF calculations including the forces calculation and other possible treatment like a finite size effect estimation or a virtual states determination.

The system parameters output

All the read values from the different input files are printed out at the program startup. Some additional values are provided there also, like the memory consumption. Values are given for one process, which corresponds to one core in an MPI environment. In [ ]: import yaml print yaml.dump(ch4.memory,default_flow_style=False)

print 'Estimated Memory Peak',ch4.memory_peak,'MB' The overall memory requirement needed for this calculation is thus: 39 MB (Estimated Memory Peak) which is provided by thememory_peak attribute. In this example, the memory requirement is given for one process run and the peak of memory will be in the initialisation during the Kernel calculation, while the SCF loop will reach 36MB during the Poisson solver calculation. For bigger systems, with more orbitals, the peak of memory is usually reached during the Hamiltonian application.

Exercise

Run a script to estimate the memory requirement of a run before submitting it to the queue system of a super-computer using the dry_run option. It reads the same input, and is thus convenient to validate inputs. Try several values from 1 to 6 and discuss the memory distribution. In [ ]: study = calc.SystemCalculator(dry_run=True) #Create a calculator peak = [] for i in range(1,7): study.set_global_option('dry_mpi',i)

44 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

dry = study.run(input=inp) peak.append(dry.memory_peak) print yaml.dump(dry.memory,default_flow_style=False) for i,p in enumerate(peak): print "mpi=",i+1,"Estimated memory peak (MB)",p BigDFT distributes the orbitals over the available processes. The value All (distributed) orbitals does not decrease anymore after 4 processes since there are only 4 bands in our example). This means that running a parallel job with more processors than orbitals will result in a bad speedup. The number of cores involved in the calculation might be however increased via OMP parallelisation, as it is indicated in Scalability with MPI and OpenMP lesson.

The input guess

The initial wavefunctions in BigDFT are calculated using the atomic orbitals for all the of the s, p, d shells, obtained from the solution of the PSP self-consistent equation for the isolated atom. In [ ]: print yaml.dump(ch4.log['Input Hamiltonian']) The corresponding hamiltonian is then diagonalised and the n_band (norb in the code notations) lower eigenfunctions are used to start the SCF loop. BigDFT outputs the eigenvalues, in the following example, 8 electrons were used in the input guess and the resulting first fourth eigenfunctions will be used for a four band calculation.

The SCF loop

The SCF loop follows a direct minimisation scheme and is made of the following steps: * Calculate the charge density from the previous wavefunctions. * Apply the Poisson solver to obtain the Hartree potential from the charges and calculate the exchange-correlation energy and the energy of the XC potential thanks to the chosen functional. * Apply the resulting hamiltonian on the current wavefunctions. * Precondition the result and apply a steepest descent or a DIIS history method. This depends on idsx, not specified in the present input. It is therefore set to the default value, which is 6 (for an history of 6 previous set of vectors. To perform a SD minimisation one should add “idsx: 0” to the dft dictionary of inp.* Orthogonalise the new wavefunctions. Finally the total energy and the square norm of the residue (gnrm) are printed out. The gnrm value is the stopping criterion. It can be chosen using gnrm_cv in the dft dictionary. The default value (1e-4) is used here and a good value can reach 1e-5. In [ ]: print 'gnrm_cv by default',ch4.gnrm_cv The minimisation scheme coupled with DIIS (and thanks to the good preconditioner) is a very efficient way to obtain convergence for systems with a gap, even with a very small one. Usual run should reach the 1e-4 stop criterion within 15 to 25 iterations. Otherwise, there is an issue with the system, either there is no gap, or the input guess is too symmetric due to the LCAO diagonalization, specific spin polarization. . . In [ ]: ch4.wfn_plot()

The post-SCF treatments

At the end of the SCF loop, a diagonalisation of the current hamiltonian is done to obtain Kohn-Sham eigenfunctions. The corresponding eigenvalues are also given. In [ ]: print ch4.evals The forces are then calculated.

2.7. (Py)BigDFT Tutorials 45 PyBigDFT Documentation, Release 0.1

In [ ]: print yaml.dump(ch4.forces,default_flow_style=False) Some other post-SCF may be done depending on the parameters in the dft dictionary of inp.

Exercise

Run bigdft when varying the DIIS history length and discuss the memory consumption. Reducing the DIIS history is a good way to reduce the memory consumption when one cannot increase the number of processes. Of course this implies more iterations in SCF loops.

Adding a charge

BigDFT can treat charged system without the requirement to add a compensating background like in plane waves. The additional charge to add to the system is set in the dft dictionary with the qcharge key. In the following example an electron has been added (-1): In [ ]: inp3 = {} inp3['dft'] = { 'hgrids': 0.55, 'nrepmax': 'accurate' } inp3['posinp'] = 'CH3-_posinp.xyz'

Exercise

Remove the last hydrogen atom in the previous methane example and modify to add an electron. Then run BigDFT for an electronic convergence. One can notice that the total charge in the system is indeed -8 thanks to the additional charge. The − convergence rate is still good for this CH3 radical since it is a closed shell system. In [ ]: study = calc.SystemCalculator() #Use a new calculator) ch3m = study.run(input=inp3) print ch3m ch3m.wfn_plot()

Running a geometry optimisation

In the previous charged example the geometry of the radical is kept the same than for the methane molecule, while it is likely to change. One can thus optimize the geometry with BigDFT. To run geometry calculations (, structure optimisations. . . ) one should add another dictionary geopt in the input which contains the method to use. In the log file, all input variables are indicated with their default value. Here, we look for a local minimum so we can use the keyword LBFGS. We can add also the stopping criteria. There are two stopping criteria: the first ncount_cluster_x being the number of loops (force evaluations) and the second forcemax is the maximum on forces. For isolated systems, the first criterion is well adapted while the second is good for periodic boundary conditions. In [ ]: inpg = {} inpg['dft'] = { 'hgrids': 0.55, 'nrepmax': 'accurate' } inpg['posinp'] = 'CH4_posinp.xyz' inpg['geopt'] = { 'method': 'LBFGS', 'ncount_cluster_x': 20} study = calc.SystemCalculator() #Use a new calculator) ch4geopt = study.run(input=inpg)

46 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

In [ ]: %matplotlib inline ch4geopt.geopt_plot()

Exercise

− Take the CH3 radical **CH3-_posinp.xyz** file and run a geometry optimisation. The evolution of the forces during relaxation can be easily obtained using the geop_plot function to the result of the calculation. At each iteration, BigDFT outputs a file posout_XXXX.xyz in the directory data with the geometry of the iteration XXX. You can visualize it using v_sim (select all files in the “Browser” tab). • Examining and postpocessing the output

2.7.9 Analyze a BigDFT run

In this example we will inspect how the BigDFT python library can be used to retrieve the results from a run. As a first operation we have to be sure that the path for the BigDFT scripts is present in the PYTHON- PATH. If not so, this might be updated by the script in the following way: In [1]: #write here the position of the BigDFT installation (usually /install/lib/pythonX.X/site-packages) import os BIGDFT_PYTHONDIR=os.path.abspath( os.path.join(os.pardir,os.pardir,'src','python') ) #refer to the sources, only for test #then update the path import sys if BIGDFT_PYTHONDIR not in sys.path: sys.path+=[BIGDFT_PYTHONDIR] Now we can load the Logfiles module: In [1]: from BigDFT import Logfiles as lf #for interactive plots remove the following line %matplotlib inline /usr/local/lib/python2.7/dist-packages/matplotlib/font_manager.py:273: UserWarning: Matplotlib is building the font cache using fc-list. This may take a moment. warnings.warn('Matplotlib is building the font cache using fc-list. This may take a moment.') Let us now load a file into a instance of a Logfile class. Imagine that our logfile corresponds to a single- point run, and it is present in a file named “log-HBDMI.yaml”: In [2]: HBDMI=lf.Logfile('testfiles/log-HBDMI.yaml') The run is now loaded. To inspect its behaviour we might print it down to inspect the usual information: In [3]: print HBDMI #HBDMI.geopt_plot() - Atom types: -C -H -N -O - Cell: Free BC - Convergence criterion on forces: 0.0 - Symmetry group: disabled - Energy: -127.35074499502582

2.7. (Py)BigDFT Tutorials 47 PyBigDFT Documentation, Release 0.1

- fermi_level: -0.1921099447862 - Max val of Forces: 0.01730347812308 - Number of Atoms: 28 - Convergence criterion on Wfn. Residue: 0.0001 - No. of KS orbitals per k-point: - 41 - 0

The above information can also be accessed separately, by having a look at the attributes of the HBDMI object: In [4]: HBDMI.__dict__.keys() #you may also type: dir(HBDMI)

Out[4]: ['evals', 'forcemax_cv', 'log', 'symmetry', 'energy', 'label', 'forcemax', 'fermi_level', 'forces', 'nat', 'astruct', 'gnrm_cv'] For this reason, we might consider to postprocess some of the variables for study of the system. Here an example: In [5]: print 'The average energy per atom is:',HBDMI.energy/HBDMI.nat,\ '(',HBDMI.energy,' Ha),',HBDMI.nat,' atoms)' print 'There are also,',HBDMI.evals[0].info,' (up,down) orbitals in the run' The average energy per atom is: -4.54824089268 ( -127.350744995 Ha), 28 atoms) There are also, [41, 0] (up,down) orbitals in the run We might access the Density of States of this system (note that if the matplotlib inlining is deactivated, the RadioButton widget below allows to adjust the smearing): In [7]: HBDMIDos=HBDMI.get_dos(label='HBDMI molecule') HBDMIDos.plot(sigma=0.1)

48 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

In [8]: HBDMI.wfn_plot()

Case of a periodic system

The above case was a Free BC molecule single point run. Let us now consider the case of a periodic calculation. We take as an example a logfile coming from one run of the DeltaTest benchmark (see this

2.7. (Py)BigDFT Tutorials 49 PyBigDFT Documentation, Release 0.1

page to know what it is all about). In any case, let us load the “log-K-1.0.yaml” file: In [9]: K=lf.Logfile('testfiles/log-K.yaml') print K - Atom types: -K - Cell: - 9.98888442684 - 9.98888442684 - 9.98888442684 - Convergence criterion on forces: 0.0 - Symmetry group: not prim. - Energy: -56.52301363451743 - fermi_level: 0.0609691899665294 - Max val of Forces: 2.038812434232e-07 - Number of Atoms: 2 - Convergence criterion on Wfn. Residue: 1e-08 - kpt_mesh: - 15 - 15 - 15 - No. of KS orbitals per k-point: - 13 - 0

Here we can see that there are also other attributes available, like the k-points and the pressure (in GPa): In [9]: dir(K) Out[9]: ['__doc__', '__getitem__', '__init__', '__module__', '__str__', '_get_bz', '_initialize_class', '_print_information', 'astruct', 'energy', 'evals', 'fermi_level', 'forcemax', 'forcemax_cv', 'geopt_plot', 'get_brillouin_zone', 'get_dos', 'kpt_mesh', 'kpts', 'label', 'log', 'nat', 'nkpt', 'symmetry'] Here we might trace the density of states but also the band structure plot, in a similar fashion (sse also the Band Structure notebook): In [10]: K.get_dos().plot() K.get_brillouin_zone().plot()

50 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

lattice [[ 9.98888443 0. 0. ] [ 0. 9.98888443 0. ] [ 0. 0. 9.98888443]] spacegroup Im-3m (229) Lattice found: cubic irreductible k-points 120 Interpolation bias 2.38385636069e-09

2.7. (Py)BigDFT Tutorials 51 PyBigDFT Documentation, Release 0.1

As another example for the system we might inspect the kpoints: In [11]: print K.kpts[0] print K.kpts[-1] {'Wgt': 0.0003, 'Bz': [0.0, 0.0, 0.0], 'Rc': [0.0, 0.0, 0.0]} {'Wgt': 0.0024, 'Bz': [0.2935, 0.2935, 0.2935], 'Rc': [0.4667, 0.4667, 0.4667]}

Case of a Geometry optimization

For a geometry optimization the situation is similar, with the extra point that the code automatically recognize multiple runs inside the logfile. Let us see the example of the following logfile: In [11]: geopt=lf.Logfile('testfiles/GEOPT-all_sqnmbiomode.out.ref.yaml') print geopt WARNING: More than one document are present expected a single document in the stream in "", line 2, column 2 but found another document in "", line 729, column 1 Loading... 21 % 29 % 37 % 45 % 53 % 61 % 68 % 76 % 84 % 92 % 100 % Found 11 different runs - Atom types: -C -H - Cell: Free BC - Convergence criterion on forces: 0.01 - Symmetry group: disabled - Energy: -14.900068217309986 - fermi_level: -0.2935133380623 - Threshold fluctuation of Forces: 0.000771111 - Max val of Forces: 0.00376314 - Number of Atoms: 8 - Convergence criterion on Wfn. Residue: 0.0001 - No. of KS orbitals per k-point: - 7 - 0

The interesting point is that now the logfile can be iterated among the different geometry steps: In [12]: en=[l.energy for l in geopt] for i,e in enumerate(en): print i,e 0 -14.8960952539 1 -14.8973771723 2 -14.8984824334 3 -14.8988612802 4 -14.8992643257

52 Chapter 2. Module Members PyBigDFT Documentation, Release 0.1

5 -14.8995896652 6 -14.8996942689 7 -14.8997814206 8 -14.8998305686 9 -14.8999870545 10 -14.9000682173 The geopt_plot() function allows to plot the relation beween energy and forces, where it can be also seen that the desired criterion is reached. Errorbars show the local fluctuation of the forces, an indication of the (cleaned) center of mass drift. See the example: In [13]: geopt.geopt_plot()

In [ ]:

2.7. (Py)BigDFT Tutorials 53 PyBigDFT Documentation, Release 0.1

54 Chapter 2. Module Members CHAPTER 3

Index of the Package

3.1 BigDFT

3.1.1 BigDFT package

Submodules

BigDFT.BZ module

class BigDFT.BZ.BZPath(lattice, path, special_points, npts=50) Defines a set of points which are associated to a path in the reduced Brillouin Zone. class BigDFT.BZ.BandArray(*args, **kwargs) Bases: numpy.ndarray Defines the array of data for one band. It is a dictionary which contains a numpy array for both spin channels. set_kpt(ikpt, kpt, kwgt=1.0) class BigDFT.BZ.BrillouinZone(astruct, mesh, evals, fermi_energy)

plot(path=None, npts=50) BigDFT.BZ.astruct_to_cell(astruct) Convert the astruct information as parsed from the module Logfiles into the cell structure as needed from spglib BigDFT.BZ.get_ev(ev, keys=None, ikpt=1) Get the correct list of the energies for this eigenvalue.

BigDFT.DoS module

This module is used to display the Density of States (DoS).

55 PyBigDFT Documentation, Release 0.1

class BigDFT.DoS.DiracSuperposition(dos, wgts=[1.0]) Defines as superposition of deltas which can be used to plot the density of states curve(xs, sigma, wgts=None) peak(omega, e, sigma) Define if a peak is a or a Lorenzian (temporarily only the gaussian is defined) peaks(xs, dos, norms, sigma) Return the array of the whole set of peaks class BigDFT.DoS.DoS(bandarrays=None, energies=None, evals=None, units=’eV’, label=’1’, sigma=0.007349865079592464, npts=2500, fermi_level=None, norm=1.0, sdos=None) Definition of the density of state class append(energies, label=None, units=’eV’, norm=1.0) append_from_bandarray(bandarrays, label) Add a new band array to the previous DoS. Important for kpoints DOS append_from_dict(evals, label) conversion_factor(units) curve(dos, norm, sigma=None) dump(sigma=None) For Gnuplot fermi_level(fermi_level, units=’eV’) get_ev(ev, keys=None) Get the correct list of the energies for this eigenvalue plot(sigma=None, legend=True, xlmin=None, xlmax=None, ylmin=None, ylmax=None) update(val)

BigDFT.Krylov module

BigDFT.wahba module

BigDFT.wahba.apply_R(R, A) Apply the rotation on the set of vectors A BigDFT.wahba.apply_Rt(R, t, A) Rotate the element and apply the translation on the rotated vector BigDFT.wahba.apply_t(t, A) Apply a translation on the set of vectors A BigDFT.wahba.rigid_transform_3D(A, B, verbose=False) Find the transformation R and t such that R*A + t ~= B, with an error quantified by J

Subpackages

Such subpackage contains scripts that can be used with the code

56 Chapter 3. Index of the Package PyBigDFT Documentation, Release 0.1

BigDFT.scripts package

Submodules

BigDFT.scripts.DeltaTest module

class BigDFT.scripts.DeltaTest.Benchmark(calculator)

run(atoms=None, force=False) BigDFT.scripts.DeltaTest.elements_from_cif(files) BigDFT.scripts.DeltaTest.process_element(run, var, dico, force_run, Elements, strains) BigDFT.scripts.DeltaTest.set_inputfile(hgrid, dico) BigDFT.scripts.DeltaTest.set_kpoints(nat) Define the k point mesh BigDFT.scripts.DeltaTest.set_restart() BigDFT.scripts.DeltaTest.set_spin(name, nat) Define the spin in function of the nature of the atoms BigDFT.scripts.DeltaTest.set_strain(strain, ngrids, dico) BigDFT.scripts.DeltaTest.xyz_from_elements(dirXYZ, Elements, ortho, nonortho)

Module contents

Module contents

BigDFT.InputActions Actions to define on the Input parameters. This module defines some of the most common actions that a BigDFT user might like to perform on the input file. Such module therefore set some of the keys of the input dictionary to the values needed to perform the operations. Users might also inspire to the actions performed in order to customize the runs in a different way. All the functions of this module have as first argument inp, the dictionary of the input parameters. Many other actions are available in BigDFT code. This module only regroups the most common. Any of these functionalities might be removed from the input file by the remove() function.

Note: Any of the action of this module, including the remove() function, can be also applied to an instance of the BigDFT.Inputfiles.Inputfile class, by removing the first argument (inp). This adds extra flexibility as the same method may be used to a dictionary instance or to a BigDFT input files. See the example Example.

Note: Each of the actions here must have default value for the arguments (except the input dictionary inp). This is needed for a good behaviour of the function remove.

remove Continued on next page

3.1. BigDFT 57 PyBigDFT Documentation, Release 0.1

Table 1 – continued from previous page set_xc set_hgrid set_rmult set_atomic_positions set_mesh_sizes optimize_geometry spin_polarize charge charge_and_polarize set_symmetry apply_electric_field set_random_inputguess write_orbitals_on_disk read_orbitals_from_disk write_density_on_disk calculate_dipole use_gpu_acceleration change_data_directory connect_run_data add_empty_SCF_orbitals extract_virtual_states set_electronic_temperature calculate_tddft_coupling_matrix

58 Chapter 3. Index of the Package CHAPTER 4

Indices and tables

• genindex • modindex • search

59 PyBigDFT Documentation, Release 0.1

60 Chapter 4. Indices and tables Python Module Index

b BigDFT, 57 BigDFT.BZ, 55 BigDFT.Calculators, 18 BigDFT.Datasets, 21 BigDFT.DoS, 55 BigDFT.Fragments, 13 BigDFT.InputActions,6 BigDFT.Inputfiles,5 BigDFT.Logfiles, 11 BigDFT.scripts, 57 BigDFT.scripts.DeltaTest, 57 BigDFT.wahba, 56

61 PyBigDFT Documentation, Release 0.1

62 Python Module Index Index

A C add_empty_SCF_orbitals() (in module calculate_dipole() (in module BigDFT.InputActions),7 BigDFT.InputActions),7 calculate_tddft_coupling_matrix() (in module append() (BigDFT.DoS.DoS method), 56 BigDFT.InputActions),7 append() (BigDFT.Fragments.Fragment method), 14 calculators (BigDFT.Datasets.Dataset attribute), 21 append() (BigDFT.Fragments.System method), 16 center_of_charge() (BigDFT.Fragments.Fragment append() (BigDFT.Fragments.XYZfile method), 17 method), 14 append_from_bandarray() (BigDFT.DoS.DoS method), central_fragment() (BigDFT.Fragments.System method), 56 16 append_from_dict() (BigDFT.DoS.DoS method), 56 centroid() (BigDFT.Fragments.Fragment method), 14 append_run() (BigDFT.Datasets.Dataset method), 21 centroid() (BigDFT.Fragments.System method), 16 apply_electric_field() (in module BigDFT.InputActions), change_data_directory() (in module 7 BigDFT.InputActions),8 apply_R() (in module BigDFT.wahba), 56 charge() (in module BigDFT.InputActions),8 apply_Rt() (in module BigDFT.wahba), 56 charge_and_polarize() (in module BigDFT.InputActions), apply_t() (in module BigDFT.wahba), 56 8 astruct_to_cell() (in module BigDFT.BZ), 55 close_xyz() (in module BigDFT.Fragments), 17 AU_to_A (in module BigDFT.Fragments), 13 combine_datasets() (in module BigDFT.Datasets), 22 connect_run_data() (in module BigDFT.InputActions),8 B conversion_factor() (BigDFT.DoS.DoS method), 56 BandArray (class in BigDFT.BZ), 55 CreateFragDict() (in module BigDFT.Fragments), 13 Benchmark (class in BigDFT.scripts.DeltaTest), 57 CreateFragList() (in module BigDFT.Fragments), 13 BigDFT (module), 57 curve() (BigDFT.DoS.DiracSuperposition method), 56 BigDFT.BZ (module), 55 curve() (BigDFT.DoS.DoS method), 56 BigDFT.Calculators (module), 18 BigDFT.Datasets (module), 21 D BigDFT.DoS (module), 55 d0() (BigDFT.Fragments.Fragment method), 14 BigDFT.Fragments (module), 13 d1() (BigDFT.Fragments.Fragment method), 14 BigDFT.InputActions (module),6 Dataset (class in BigDFT.Datasets), 21 BigDFT.Inputfiles (module),5 Debye_to_AU (in module BigDFT.Fragments), 13 BigDFT.Logfiles (module), 11 decompose() (BigDFT.Fragments.System method), 16 BigDFT.scripts (module), 57 dict() (BigDFT.Fragments.Fragment method), 14 BigDFT.scripts.DeltaTest (module), 57 dict() (BigDFT.Fragments.System method), 16 BigDFT.wahba (module), 56 DiracSuperposition (class in BigDFT.DoS), 55 BrillouinZone (class in BigDFT.BZ), 55 distance() (in module BigDFT.Fragments), 17 build_transformations() (in module BigDFT.Fragments), DoS (class in BigDFT.DoS), 56 17 dot() (BigDFT.Fragments.RotoTranslation method), 15 BZPath (class in BigDFT.BZ), 55 dump() (BigDFT.DoS.DoS method), 56 dump() (BigDFT.Fragments.XYZfile method), 17

63 PyBigDFT Documentation, Release 0.1 dump_xyz() (in module BigDFT.Fragments), 17 L dump_xyz_positions() (in module BigDFT.Fragments), label (BigDFT.Logfiles.Logfile attribute), 12 17 Lattice (class in BigDFT.Fragments), 15 line_up() (BigDFT.Fragments.Fragment method), 14 E Logfile (class in BigDFT.Logfiles), 11 element() (BigDFT.Fragments.Fragment method), 14 elements_from_cif() (in module M BigDFT.scripts.DeltaTest), 57 MergeFragmentsTogether() (in module ellipsoid() (BigDFT.Fragments.Fragment method), 14 BigDFT.Fragments), 15 extract_virtual_states() (in module BigDFT.InputActions),8 N F names (BigDFT.Datasets.Dataset attribute), 22 fermi_level() (BigDFT.DoS.DoS method), 56 O fetch_results() (BigDFT.Datasets.Dataset method), 22 fill_from_mp_dict() (BigDFT.Fragments.System open_xyz() (in module BigDFT.Fragments), 17 method), 16 optimize_geometry() (in module BigDFT.InputActions), fill_from_posinp_dict() (BigDFT.Fragments.System 8 method), 16 os (BigDFT.Calculators.SystemCalculator attribute), 20 fill_from_xyz() (BigDFT.Fragments.System method), 16 find_iterations() (in module BigDFT.Logfiles), 12 P find_reference_fragment() (in module peak() (BigDFT.DoS.DiracSuperposition method), 56 BigDFT.Fragments), 17 peaks() (BigDFT.DoS.DiracSuperposition method), 56 floatify() (in module BigDFT.Logfiles), 12 plot() (BigDFT.BZ.BrillouinZone method), 55 frag_average() (in module BigDFT.Fragments), 17 plot() (BigDFT.DoS.DoS method), 56 fragdict() (BigDFT.Fragments.System method), 16 plot_wfn_convergence() (in module BigDFT.Logfiles), Fragment (class in BigDFT.Fragments), 13 13 fragment_transformation() (BigDFT.Fragments.System pop() (BigDFT.Fragments.System method), 16 method), 16 pop_global_option() (BigDFT.Calculators.Runner method), 18 G post_processing() (BigDFT.Calculators.Runner method), geopt_plot() (BigDFT.Logfiles.Logfile method), 11 18 get_brillouin_zone() (BigDFT.Logfiles.Logfile method), post_processing() (BigDFT.Calculators.SystemCalculator 12 method), 20 get_dos() (BigDFT.Logfiles.Logfile method), 12 post_processing() (BigDFT.Datasets.Dataset method), 22 get_ev() (BigDFT.DoS.DoS method), 56 pre_processing() (BigDFT.Calculators.Runner method), get_ev() (in module BigDFT.BZ), 55 19 get_global_option() (BigDFT.Calculators.Runner pre_processing() (BigDFT.Calculators.SystemCalculator method), 18 method), 20 get_logs() (in module BigDFT.Logfiles), 13 prepare_fragment_inputs() (in module get_posinp() (BigDFT.Fragments.Fragment method), 14 BigDFT.Fragments), 17 GetFragTuple() (in module BigDFT.Fragments), 15 process_element() (in module BigDFT.scripts.DeltaTest), GetSymbol() (in module BigDFT.Fragments), 15 57 GIBinding (class in BigDFT.Calculators), 18 process_run() (BigDFT.Calculators.Runner method), 19 global_options() (BigDFT.Calculators.Runner method), process_run() (BigDFT.Calculators.SystemCalculator 18 method), 21 grid() (BigDFT.Fragments.Lattice method), 15 process_run() (BigDFT.Datasets.Dataset method), 22 I Q ids (BigDFT.Datasets.Dataset attribute), 22 Q() (BigDFT.Fragments.Fragment method), 14 InputActions (in module BigDFT), 57 Q() (BigDFT.Fragments.System method), 16 Inputfile (class in BigDFT.Inputfiles),5 q0() (BigDFT.Fragments.Fragment method), 14 invert() (BigDFT.Fragments.RotoTranslation method), 15 q1() (BigDFT.Fragments.Fragment method), 14

64 Index PyBigDFT Documentation, Release 0.1

R T read_orbitals_from_disk() (in module transform() (BigDFT.Fragments.Fragment method), 15 BigDFT.InputActions),8 Translation (class in BigDFT.Fragments), 16 recompose() (BigDFT.Fragments.System method), 16 reference_log (BigDFT.Logfiles.Logfile attribute), 12 U remove() (in module BigDFT.InputActions),8 update() (BigDFT.Calculators.GIBinding method), 18 results (BigDFT.Datasets.Dataset attribute), 22 update() (BigDFT.DoS.DoS method), 56 rigid_transform_3D() (in module BigDFT.wahba), 56 update_global_options() (BigDFT.Calculators.Runner Rotation (class in BigDFT.Fragments), 15 method), 19 rotot_collection() (in module BigDFT.Fragments), 18 use_gpu_acceleration() (in module RotoTranslation (class in BigDFT.Fragments), 15 BigDFT.InputActions), 10 run() (BigDFT.Calculators.GIBinding method), 18 run() (BigDFT.Calculators.Runner method), 19 W run() (BigDFT.scripts.DeltaTest.Benchmark method), 57 wahba_fragment() (in module BigDFT.Fragments), 18 Runner (class in BigDFT.Calculators), 18 wfn_plot() (BigDFT.Logfiles.Logfile method), 12 runs (BigDFT.Datasets.Dataset attribute), 22 write_cubefiles_around_fermi_level() (in module rxyz() (BigDFT.Fragments.Fragment method), 15 BigDFT.InputActions), 10 S write_density_on_disk() (in module BigDFT.InputActions), 11 set() (BigDFT.Calculators.GIBinding method), 18 write_fragfile() (BigDFT.Fragments.System method), 16 set_atomic_positions() (in module write_orbitals_on_disk() (in module BigDFT.InputActions),9 BigDFT.InputActions), 11 set_electronic_temperature() (in module write_support_function_matrices() (in module BigDFT.InputActions),9 BigDFT.InputActions), 11 set_fragment_multipoles() (BigDFT.Fragments.Fragment write_support_functions_on_disk() (in module method), 15 BigDFT.InputActions), 11 set_hgrid() (in module BigDFT.InputActions),9 set_id() (BigDFT.Fragments.Fragment method), 15 X set_inputfile() (in module BigDFT.scripts.DeltaTest), 57 xyz() (BigDFT.Fragments.Fragment method), 15 set_kpoints() (in module BigDFT.scripts.DeltaTest), 57 xyz() (BigDFT.Fragments.System method), 16 set_kpt() (BigDFT.BZ.BandArray method), 55 xyz_bc_spec() (in module BigDFT.Fragments), 18 set_linear_scaling() (in module BigDFT.InputActions), xyz_from_elements() (in module 10 BigDFT.scripts.DeltaTest), 57 set_mesh_sizes() (in module BigDFT.InputActions), 10 XYZfile (class in BigDFT.Fragments), 17 set_postprocessing_function() (BigDFT.Datasets.Dataset method), 22 set_purity_indicator() (BigDFT.Fragments.Fragment method), 15 set_random_inputguess() (in module BigDFT.InputActions), 10 set_restart() (in module BigDFT.scripts.DeltaTest), 57 set_rmult() (in module BigDFT.InputActions), 10 set_SCF_method() (in module BigDFT.InputActions),9 set_spin() (in module BigDFT.scripts.DeltaTest), 57 set_strain() (in module BigDFT.scripts.DeltaTest), 57 set_symmetry() (in module BigDFT.InputActions), 10 set_xc() (in module BigDFT.InputActions), 10 SetFragId() (in module BigDFT.Fragments), 15 shutil (BigDFT.Calculators.SystemCalculator attribute), 21 spin_polarize() (in module BigDFT.InputActions), 10 srcdir (BigDFT.Logfiles.Logfile attribute), 12 System (class in BigDFT.Fragments), 15 SystemCalculator (class in BigDFT.Calculators), 19

Index 65