Commit 0abb31a2 authored by Marco Govoni's avatar Marco Govoni
Browse files

Added electronic structure

parent f2549ac0
......@@ -6,35 +6,50 @@ Manual
The complete **westpy** manual.
Module contents
---------------
.. automodule:: westpy
:members:
:undoc-members:
:show-inheritance:
Units
-----
.. automodule:: westpy.units
:members:
:undoc-members:
:show-inheritance:
Utilities
---------
.. automodule:: westpy.utils
:members:
:undoc-members:
:show-inheritance:
Atom
----
.. automodule:: westpy.atom
:members:
:undoc-members:
:show-inheritance:
Geometry
--------
.. automodule:: westpy.geometry
:members:
:undoc-members:
:show-inheritance:
Ground State
------------
.. automodule:: westpy.groundState
:members:
:undoc-members:
:show-inheritance:
Electronic Structure
--------------------
.. automodule:: westpy.electronicStructure
:members:
:undoc-members:
:show-inheritance:
......@@ -11,3 +11,4 @@ Contents:
:maxdepth: 1
westpy_100.ipynb
westpy_200.ipynb
%% Cell type:markdown id: tags:
This tutorial can be downloaded [link](http://greatfire.uchicago.edu/west-public/westpy/raw/master/doc/westpy_100.ipynb).
%% Cell type:markdown id: tags:
# 1.1 Getting Started: Ground State
# 1.0 Getting Started: Ground State
%% Cell type:markdown id: tags:
We are going to generate an input file for the [QuantumEspresso](https://www.quantum-espresso.org/) code or [Qbox](http://qboxcode.org/). Each code will compute the ground state electronic stucture for the methane molecule using Density Functional Theory.
%% Cell type:markdown id: tags:
## Step 1: Load westpy
%% Cell type:code id: tags:
``` python
from westpy import *
```
%%%% Output: stream
_ _ _____ _____ _____
| | | | ___/ ___|_ _|
| | | | |__ \ `--. | |_ __ _ _
| |/\| | __| `--. \ | | '_ \| | | |
\ /\ / |___/\__/ / | | |_) | |_| |
\/ \/\____/\____/ \_/ .__/ \__, |
| | __/ |
|_| |___/
WEST version : 3.1.0
Today : 2018-06-25 07:01:41.214544
%% Cell type:markdown id: tags:
## Step 2: Geometry
%% Cell type:code id: tags:
``` python
geom = Geometry()
```
%% Cell type:markdown id: tags:
Let's define a cubic cell of edge 25 Bohr.
%% Cell type:code id: tags:
``` python
geom.setCell((25,0,0),(0,25,0),(0,0,25))
```
%% Cell type:markdown id: tags:
We load the atomic positions from a XYZ file, available online.
%% Cell type:code id: tags:
``` python
geom.addAtomsFromOnlineXYZ( "http://www.west-code.org/database/gw100/xyz/CH4.xyz" )
```
%% Cell type:markdown id: tags:
We associate pseudopotential files to each species.
%% Cell type:code id: tags:
``` python
geom.addSpecies( "C", "http://www.quantum-simulation.org/potentials/sg15_oncv/upf/C_ONCV_PBE-1.0.upf")
geom.addSpecies( "H", "http://www.quantum-simulation.org/potentials/sg15_oncv/upf/H_ONCV_PBE-1.0.upf")
```
%% Cell type:markdown id: tags:
## Step 3.1: Ground State
%% Cell type:markdown id: tags:
The ground state calculation is defined by the geometry, a choice of the exchange-correlation functional, and by setting an energy cutoff for the wavefunctions.
%% Cell type:code id: tags:
``` python
gs = GroundState(geom,xc="PBE",ecut=40.0)
```
%% Cell type:markdown id: tags:
We are now able to generate the input file for QuantumEspresso.
%% Cell type:code id: tags:
``` python
gs.generateInputPW()
```
%%%% Output: stream
Generated file: pw.in
%% Cell type:markdown id: tags:
We can inspect the file pw.in
%% Cell type:code id: tags:
``` python
with open("pw.in","r") as file :
data = file.read()
print(data)
```
%%%% Output: stream
&CONTROL
calculation = 'scf'
restart_mode = 'from_scratch'
pseudo_dir = './'
outdir = './'
prefix = 'calc'
wf_collect = .TRUE.
/
&SYSTEM
ibrav = 0
nat = 5
ntyp = 2
ecutwfc = 40.0
nbnd = 8
input_dft = 'PBE'
nosym = .TRUE.
noinv = .TRUE.
/
&ELECTRONS
diago_full_acc = .TRUE.
conv_tol = 1.d-8
/
ATOMIC_SPECIES
C 12.011 C_ONCV_PBE-1.0.upf
H 1.008 H_ONCV_PBE-1.0.upf
ATOMIC_POSITIONS {bohr}
C 0.0 0.0 0.0
H 1.185992116575257 -1.185803143962673 1.185992116575257
H -1.185992116575257 1.185992116575257 1.185992116575257
H -1.185992116575257 -1.185992116575257 -1.185992116575257
H 1.185992116575257 1.185992116575257 -1.185992116575257
K_POINTS {gamma}
CELL_PARAMETERS {bohr}
25.0 0.0 0.0
0.0 25.0 0.0
0.0 0.0 25.0
%% Cell type:markdown id: tags:
We can optionally also download the pseudopotentials files.
%% Cell type:code id: tags:
``` python
gs.downloadPseudopotentials()
```
%%%% Output: stream
Downloaded file: C_ONCV_PBE-1.0.upf , from url: http://www.quantum-simulation.org/potentials/sg15_oncv/upf/C_ONCV_PBE-1.0.upf
Downloaded file: H_ONCV_PBE-1.0.upf , from url: http://www.quantum-simulation.org/potentials/sg15_oncv/upf/H_ONCV_PBE-1.0.upf
%% Cell type:markdown id: tags:
## Step 3.2: Ground State with Qbox
%% Cell type:markdown id: tags:
To generate the input for Qbox we can simply update Species to use the xml formats.
%% Cell type:code id: tags:
``` python
gs.updateSpecies("C", "http://www.quantum-simulation.org/potentials/sg15_oncv/xml/C_ONCV_PBE-1.0.xml")
gs.updateSpecies("H", "http://www.quantum-simulation.org/potentials/sg15_oncv/xml/H_ONCV_PBE-1.0.xml")
```
%% Cell type:markdown id: tags:
We are now able to generate the input file for QuantumEspresso.
%% Cell type:code id: tags:
``` python
gs.generateInputQbox()
```
%%%% Output: stream
Generated file: qbox.in
%% Cell type:markdown id: tags:
We can inspect the file qbox.in
%% Cell type:code id: tags:
``` python
with open("qbox.in","r") as file :
data = file.read()
print(data)
```
%%%% Output: stream
set cell 25.0 0.0 0.0 0.0 25.0 0.0 0.0 0.0 25.0
species Carbon C_ONCV_PBE-1.0.xml
species Hydrogen H_ONCV_PBE-1.0.xml
atom C1 Carbon 0.0 0.0 0.0
atom H2 Hydrogen 1.185992116575257 -1.185803143962673 1.185992116575257
atom H3 Hydrogen -1.185992116575257 1.185992116575257 1.185992116575257
atom H4 Hydrogen -1.185992116575257 -1.185992116575257 -1.185992116575257
atom H5 Hydrogen 1.185992116575257 1.185992116575257 -1.185992116575257
set ecut 40.0
set wf_dyn JD
set xc PBE
set scf_tol 1.e-8
randomize_wf
run -atomic_density 0 100 5
save gs.xml
%% Cell type:markdown id: tags:
We can optionally also download the pseudopotentials files.
%% Cell type:code id: tags:
``` python
gs.downloadPseudopotentials()
```
%%%% Output: stream
Downloaded file: C_ONCV_PBE-1.0.xml , from url: http://www.quantum-simulation.org/potentials/sg15_oncv/xml/C_ONCV_PBE-1.0.xml
Downloaded file: H_ONCV_PBE-1.0.xml , from url: http://www.quantum-simulation.org/potentials/sg15_oncv/xml/H_ONCV_PBE-1.0.xml
%% Cell type:code id: tags:
``` python
```
......
%% Cell type:markdown id: tags:
This tutorial can be downloaded [link](http://greatfire.uchicago.edu/west-public/westpy/raw/master/doc/westpy_200.ipynb).
%% Cell type:markdown id: tags:
# 2.0 Plot Density of States
%% Cell type:markdown id: tags:
We are going to plot the electronic density of states.
%% Cell type:markdown id: tags:
## Step 1: Load westpy
%% Cell type:code id: tags:
``` python
from westpy import *
```
%%%% Output: stream
_ _ _____ _____ _____
| | | | ___/ ___|_ _|
| | | | |__ \ `--. | |_ __ _ _
| |/\| | __| `--. \ | | '_ \| | | |
\ /\ / |___/\__/ / | | |_) | |_| |
\/ \/\____/\____/ \_/ .__/ \__, |
| | __/ |
|_| |___/
WEST version : 3.1.0
Today : 2018-06-25 16:20:56.893787
%% Cell type:markdown id: tags:
## Step 2: Electronic Structure
%% Cell type:code id: tags:
``` python
es = ElectronicStructure()
```
%% Cell type:markdown id: tags:
We add information about the k-points, in this case only gamma.
%% Cell type:code id: tags:
``` python
es.addKpoint(1,[0.,0.,0.])
```
%% Cell type:markdown id: tags:
We add keys that will be used to browse the electronic structure.
%% Cell type:code id: tags:
``` python
es.addKey("eks","Kohn-Sham energy (eV)")
es.addKey("eqp","Quasiparticle energy (eV)")
```
%% Cell type:markdown id: tags:
We add three data points.
%% Cell type:code id: tags:
``` python
es.addDataPoint([1,1,1],"eks",-4.6789)
es.addDataPoint([1,1,2],"eks",-4.3789)
es.addDataPoint([1,1,1],"eqp",-4.5789)
```
%% Cell type:markdown id: tags:
We can plot the DOS for both the key "eks" and "eqp"
%% Cell type:code id: tags:
``` python
%matplotlib inline
es.plotDOS(k=1,s=1,energyKeys=["eks","eqp"],energyRange=[-5,-4,0.01])
```
%%%% Output: stream
Requested (emin,emax) : -5 -4
Detected (emin,emax) : -4.6789 -4.3789
output written in : dos.png
waiting for user to close image preview...
%% Cell type:code id: tags:
``` python
```
......@@ -5,6 +5,7 @@ from westpy.utils import *
from westpy.atom import *
from westpy.geometry import *
from westpy.groundState import *
from westpy.electronicStructure import *
__version__ = '3.1.0'
......
from __future__ import print_function
class ElectronicStructure(object) :
"""Class for representing an electronic structure calculation.
:Example:
>>> from westpy import *
>>> es = ElectronicStructure()
"""
#
def __init__(self) :
self.info = {}
self.data = []
#
def loadFromJsonFile(self,fname) :
"""Loads an electronic structure from file (Json format).
:param fname: file name
:type fname: string
:Example:
>>> from westpy import *
>>> es = ElectronicStructure()
>>> es.loadFromJsonFile("es.json")
"""
from westpy import readJsonFile
data = readJsonFile(fname)
self.info = data["info"]
self.data = data["data"]
#
def dumpToJsonFile(self,fname) :
"""Dumps an electronic structure to file (Json format).
:param fname: file name
:type fname: string
:Example:
>>> from westpy import *
>>> es = ElectronicStructure()
>>> es.dumpToJsonFile("es.json")
"""
from westpy import writeJsonFile
data = {}
data["info"] = self.info
data["data"] = self.data
writeJsonFile(fname,data)
#
def addKey(self,key,value) :
"""Sets key-value in metadata.
:param key: key
:type key: string
:param value: value
:type value: string
:Example:
>>> from westpy import *
>>> es = ElectronicStructure()
>>> es.addKey("eks","Kohn-Sham")
"""
if "keys" not in self.info.keys() :
self.info["keys"] = {}
self.info["keys"][key] = value
#
def removeKey(self,key) :
"""Removes key from metadata.
:param key: key
:type key: string
:Example:
>>> from westpy import *
>>> es = ElectronicStructure()
>>> es.removeKey("eks")
"""
if "keys" in self.info.keys() :
if key in self.info["keys"] :
self.info["keys"].pop(key,None)
else :
print("key not recognized")
else :
print("No keys")
#
#
def showKeys(self) :
"""Shows keys in metadata.
:Example:
>>> from westpy import *
>>> es = ElectronicStructure()
>>> es.showKeys()
"""
if "keys" in self.info.keys() :
for key in self.info["keys"] :
print( key, self.info["keys"][key])
else :
print("No keys")
#
def addKpoint(self,kpoint,coord) :
"""Adds kpoint info to metadata.
:param kpoint: k-point integer label
:type kpoint: int
:param coord: crystal coordinates of the k-point
:type coord: 3-dim list of int
:Example:
>>> from westpy import *
>>> es = ElectronicStructure()
>>> es.addKpoint(1,[0.,0.,0.])
"""
if "k" not in self.info.keys() :
self.info["k"] = {}
self.info["k"][kpoint] = [float(coord[0]), float(coord[1]), float(coord[2])]
#
def __addSpins(self,spins) :
"""Adds spin labels to metadata.
:param spin: list of spin integer label
:type spin: list of int
:Example:
>>> from westpy import *
>>> es = ElectronicStructure()
>>> es.addSpins([1,2])
"""
if "s" not in self.info.keys() :
self.info["s"] = []
for spin in spins :
self.info["s"].append(spin)
#
def __addBands(self,bands) :
"""Adds band label to metadata.
:param band: list of band integer label
:type band: list of int
:Example:
>>> from westpy import *
>>> es = ElectronicStructure()
>>> es.addBands([1,2,3])
"""
if "b" not in self.info.keys() :
self.info["b"] = []
for band in bands :
self.info["b"].append(band)
#
def addDataPoint(self,ksb,key,what) :
"""Adds datapoint to data.
:param ksb: triplet of k-point, spin, band (integer labels)
:type ksb: 3-dim int
:param key: key
:type key: string
:param what: content attached to key
:type what: *
:Example:
>>> from westpy import *
>>> es = ElectronicStructure()
>>> es.addKey("eks","Kohn-Sham energy in eV")
>>> es.addKpoint(1,[0.,0.,0.])
>>> es.addDataPoint([1,1,1],"eks",-4.6789)
"""
lk = False
lkey = False
if "k" in self.info.keys() :
lk = ( ksb[0] in self.info["k"] )
else :
print("No k")
if "keys" in self.info.keys() :
lkey = ( key in self.info["keys"] )
else :
print("No keys")
if( lk and lkey ) :
lfound = False
for x in self.data :
if x["ksb"] == ksb :
x[key] = what
lfound = True
break
if not lfound :
d = {}
d["ksb"] = ksb
d[key] = what
self.data.append(d)
else :
if not lk :
print(ksb[0], "not in k, add it first")
if not lkey :
print(key, "not in keys, add it first")
#
def plotDOS(self,k=1,s=1,energyKeys=["eks"],sigma=0.1,weight=1.,energyRange=[-20.,0.,0.01],fname="dos.png") :
"""Plots desnity of states (DOS).
:param k: k-point integer label
:type k: int
:param s: spin integer label
:type s: int
:param energyKeys: energy keys
:type energyKeys: list of string (needs to match the available keys)
:param sigma: standard deviation of gaussian (eV), optional
:type sigma: float .OR. list of string (needs to match the available keys)
:param weight: weight, optional