├── LICENSE
├── README.md
├── clean
├── example
├── AlN_abs.txt
├── create_workflow.ipynb
├── input.yaml
└── postprocessing.ipynb
├── pyGWBSE
├── config.py
├── inputset.py
├── inputset.yaml
├── make_wflow.py
├── out2db.py
├── run_calc.py
├── tasks.py
├── wannier_tasks.py
└── wflows.py
├── requirements.txt
├── setup.py
└── sphinx
├── Makefile
├── README
├── README.md
├── _static
├── github.png
└── orcid.jpg
├── clean
├── compile
├── conf.py
├── example
├── AlN_abs.txt
├── create_workflow.ipynb
├── input.yaml
└── postprocessing.ipynb
├── index.rst
├── make.bat
├── pyGWBSE
├── config.py
├── inputset.py
├── inputset.yaml
├── make_wflow.py
├── out2db.py
├── run_calc.py
├── tasks.py
├── wannier_tasks.py
└── wflows.py
├── requirement.txt
├── rst
├── modules.rst
├── project
│ ├── gwbse_wf
│ │ ├── getfromdb.rst
│ │ ├── inputset.rst
│ │ ├── modules.rst
│ │ ├── out2db.rst
│ │ ├── run_calc.rst
│ │ ├── tasks.rst
│ │ ├── wannier_tasks.rst
│ │ └── wflows.rst
│ ├── make_wf.rst
│ └── modules.rst
└── project_intro
│ ├── installation.rst
│ ├── introduction.rst
│ ├── modules.rst
│ ├── references.rst
│ └── team.rst
└── setup.py
/README.md:
--------------------------------------------------------------------------------
1 | # *py*GWBSE
2 | *py*GWBSE is a high-throughtput python workflow package designed to perform automtaed GW-BSE (Bethe-Salpeter Equation) calculation. The *py*GWBSE package leverages well known computational tools: *pymatgen, atomate, fireworks* and first principles software such as: *VASP* and *Wannier90* to perform high-throughput GW-BSE calculations. The workflow creates, computes, analyzes and stores all relevant simulation parameters and results in a queryable MongoDB database that can be accessed through our API. Check out our [documentation](https://cmdlab.github.io/pyGWBSE/) or the [paper](https://arxiv.org/abs/2210.00152)!
3 |
4 | ## Package Description
5 | *py*GWBSE package takes input structure of materials and performs GW-BSE simulations for studying excited state properties. It performs automated convergence calculations required to obtain accurate results from such simulations. *py*GWBSE uses widely used *VASP* software to perform first-principles calculations. It uses *Wannier90* software to obtain quasiparticle (QP) bandstructure (both the one-shot G0W0 and partially self-consistent GW0 level) using maximally localized wannier functions. The electron and hole effective masses are computed using Sumo package. *py*GWBSE is also capable of solving BSE, which calculates absorption spectra of materials that incorporates excitonic effects and is accurate enough to comapre with experimental spectra. In addition to performing excited state property simulations, *py*GWBSE also computes several key electronic structure properties of materials such as, orbital resolved density of states (both at DFT and QP level), real and imaginary part of the dielectric function (with and without incorporating electron-hole interaction), the exciton energies, and their corresponding oscillator strengths, band-edges, static dielectric tensors etc.
6 |
7 |
8 | ## Installation Instructions for *py*GWBSE
9 | IMPORTANT NOTE: Atomate and FireWorks do not run on Windows OS. You need a unix-based OS (Mac or Linux) in order for these packages to run. As such, all setup instructions are given for Unix systems.
10 |
11 | 1. Download the repo from the green code icon or via github's clone method.
12 | - ``git clone https://github.com/cmdlab/pyGWBSE.git``
13 | 2. Install *py*GWBSE in a clean enviromnent using python=3.9. I suggest using Anaconda3 to manange environments.
14 | - ``conda create --name pygwbse python=3.9``
15 | 3. Activate the *py*GWBSE environment and run the line below in the *py*GWBSE directory to install:
16 | - ``pip install -r requirements.txt``
17 | 4. After installation, *py*GWBSE needs to be added to your python path. This can be done by running the first line below **OR** by adding the 2nd line listed below to your *.bashrc* file. Only necessary if python cannot find the package or the setup.py failed for some reason.
18 | - ``python setup.py develop`` or ``python setup.py install``
19 | - ``export PYTHONPATH="$HOME/path_to_package/pyGWBSE:$PYTHONPATH"``
20 | 5. If this is your first time installing the package dependencies listed below, please ensure you have followed the respective setup instructions:
21 | - [atomate](https://atomate.org/)
22 | - [FireWorks](https://materialsproject.github.io/fireworks/installation.html)
23 | - [pymatgen](https://pymatgen.org/installation.html)
24 | 6. To run jupyter notebooks on various resources the ipykernel has to be installed. Sometimes this isn't enough and you need explicitly add the kernel to the list of environments. Via the command line:
25 | - Activate your environment ``conda activate pygwbse``
26 | - Install ipykernel ``python -m pip install ipykernel``
27 | - Add pygwbse kernel ``python -m ipykernel install --user --name pygwbse``
28 |
29 | ## Setting up dependancies
30 | The *py*GWBSE package dependancies have a lot of documentation to look over. I will highlight the essential documentation to get started as quickly as possible.
31 | 1. *atomate* requires the most set up. Mainly, creating a directory scaffold and writing the 5 required files to connect to the database and run jobs. (MongoDB or free Atlas MongoDB is required)
32 | 2. *pymatgen* has a command line tool installed to set up default directory paths called pmg. There are 2 essential commands you have to run to use *py*GWBSE on any system.
33 | - Reference directory for the VASP POTCARs. You need to have the POTCARs from VASP yourself.
34 | - `pmg config -p `
35 | - Default pseudopotential files from VASP
36 | - `pmg config --add PMG_DEFAULT_FUNCTIONAL PBE_54`
37 | 3. *VASP* should be installed with Wannier90 support (for more information visit [here](https://www.vasp.at/wiki/index.php/LWANNIER90)). We have tested our code with VASP.5.4.4. The VASP execution command should be specified in atomate config file my_fworker.yaml as,
38 | - `vasp_cmd: "srun --mpi=pmi2 [location of VASP executable] > vasp.log"`
39 | 5. *Wannier90* version 3.1.0 should be installed (for more information visit [here](http://www.wannier.org/)). The Wannier90 execution command should be specified in the atomate config file my_fworker.yaml as,
40 | - wannier_cmd: "[location of Wannier90 executable] > wannier90"
41 | 7. *Sumo* version 2.2.5 should be installed (for more information visit [here](https://smtg-ucl.github.io/sumo/index.html)). The Sumo execution command should be specified in the atomate config file my_fworker.yaml as,
42 | - sumo_cmd: "sumo-bandstats"
43 |
44 | ## Examples
45 | To get started using *py*GWBSE, various tutorials and examples have been created using Jupyter Notebooks. These notebooks demonstrate the basic functionality of *py*GWBSE to enable users to quickly learn how to use the various modules within this package. These can be found under pyGWBSE/examples.
46 |
47 | ## Issues Installing
48 | 1. If you have a new install you likely do not have the gcc compiler that pymatgen requires. In that case run
49 | - `sudo apt install build-essential`
50 | - `sudo apt-get install manpages-dev`
51 |
52 | ## How to cite *py*GWBSE
53 | If you use *py*GWBSE in your research, please consider citing the paper!
54 |
55 | > Tathagata Biswas, Arunima K. Singh. *pyGWBSE: A high throughput workflow package for GW-BSE calculations*. [https://doi.org/10.1038/s41524-023-00976-y](https://doi.org/10.1038/s41524-023-00976-y)
56 |
57 |
--------------------------------------------------------------------------------
/clean:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | rm -rf build/ dist/ pyGWBSE.egg-info/ __pycache__/
3 | rm -rf pyGWBSE/__init__.py pyGWBSE/__pycache__/
4 |
--------------------------------------------------------------------------------
/example/AlN_abs.txt:
--------------------------------------------------------------------------------
1 | 6.15789 0.430108 0 0 0 0
2 | 6.17895 0.55914 0 0 0 0
3 | 6.15789 0.924731 0 0 0 0
4 | 6.17895 1.5914 0 0 0 0
5 | 6.22105 2.04301 0 0 0 0
6 | 6.28421 2.43011 0 0 0 0
7 | 6.32632 2.47312 0 0 0 0
8 | 6.51579 2.34409 0 0 0 0
9 | 6.57895 2.36559 0 0 0 0
10 | 6.74737 2.45161 0 0 0 0
11 | 6.97895 2.66667 0 0 0 0
12 | 7.06316 2.94624 0 0 0 0
13 | 7.14737 3.24731 0 0 0 0
14 | 7.23158 3.5914 0 0 0 0
15 | 7.29474 3.87097 0 0 0 0
16 | 7.33684 4.25806 0 0 0 0
17 | 7.42105 4.7957 0 0 0 0
18 | 7.50526 5.50538 0 0 0 0
19 | 7.54737 6.15054 0 0 0 0
20 | 7.58947 6.7957 0 0 0 0
21 | 7.63158 7.33333 0 0 0 0
22 | 7.65263 7.65591 0 0 0 0
23 | 7.69474 8 0 0 0 0
24 | 7.73684 8.8172 0 0 0 0
25 | 7.75789 9.22581 0 0 0 0
26 | 7.8 9.5914 0 0 0 0
27 | 7.84211 9.97849 0 0 0 0
28 | 7.98947 9.5914 0 0 0 0
29 | 8.07368 9.26882 0 0 0 0
30 | 8.26316 8.88172 0 0 0 0
31 | 8.49474 8.53763 0 0 0 0
32 | 8.6 8.47312 0 0 0 0
33 | 8.74737 8.58065 0 0 0 0
34 | 8.87368 8.62366 0 0 0 0
35 | 9.04211 8.53763 0 0 0 0
36 | 9.14737 8.15054 0 0 0 0
37 | 9.23158 7.87097 0 0 0 0
38 | 9.31579 7.65591 0 0 0 0
39 | 9.42105 7.22581 0 0 0 0
40 | 9.48421 6.90323 0 0 0 0
41 | 9.58947 6.36559 0 0 0 0
42 | 9.67368 5.87097 0 0 0 0
43 | 9.73684 5.52688 0 0 0 0
44 |
--------------------------------------------------------------------------------
/example/create_workflow.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "These examples show how to create GW-BSE workflow using $py$GWBSE\n",
8 | "package. We will show how to compute QP bandstructure for wurtzite-AlN\n",
9 | "at the partial self-consistent (GW$_0$) level by obtaining input \n",
10 | "structure from Material Project (MP) database. We will also compute the \n",
11 | "absorption spectra of wurtzite-AlN by solving Bethe-Salpeter equation (BSE)."
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": 1,
17 | "metadata": {
18 | "scrolled": true
19 | },
20 | "outputs": [
21 | {
22 | "name": "stderr",
23 | "output_type": "stream",
24 | "text": [
25 | "/home/tatha/anaconda3/envs/pygwbse/lib/python3.9/site-packages/pymatgen/analysis/phase_diagram.py:26: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
26 | " from tqdm.autonotebook import tqdm\n",
27 | "/home/tatha/anaconda3/envs/pygwbse/lib/python3.9/site-packages/atomate/vasp/drones.py:46: FutureWarning: which is deprecated; use which in shutil instead.\n",
28 | "shutil.which has been available since Python 3.3. This will be removed in v2023.\n",
29 | " BADER_EXE_EXISTS = which(\"bader\") or which(\"bader.exe\")\n"
30 | ]
31 | }
32 | ],
33 | "source": [
34 | "#First let's load the required libraries such as pymatgen and Fireworks\n",
35 | "import sys\n",
36 | "from pyGWBSE.make_wflow import read_input, create_wfs\n",
37 | "from fireworks import LaunchPad"
38 | ]
39 | },
40 | {
41 | "cell_type": "code",
42 | "execution_count": 2,
43 | "metadata": {
44 | "scrolled": false
45 | },
46 | "outputs": [
47 | {
48 | "name": "stdout",
49 | "output_type": "stream",
50 | "text": [
51 | "PARAMS:\r\n",
52 | " kpar: 8 \r\n",
53 | " # 'KPAR' tag to be used in VASP simulations\r\n",
54 | " \r\n",
55 | " ppn: 13 \r\n",
56 | " # NPROCS/KPAR ; NPROCS: number of total processors to be used in VASP simulations \r\n",
57 | " \r\n",
58 | " reciprocal_density: 200 \r\n",
59 | " # reciprocal density that determines the k-grid using 'automatic_density_by_vol' method of pymatgen\r\n",
60 | " \r\n",
61 | " encutgw: 100 \r\n",
62 | " # ENCUTGW to be used in VASP simulations\r\n",
63 | " \r\n",
64 | " nbgwfactor: 5 \r\n",
65 | " # NBANDS=nbgwfactor x nocc'; nocc' is the smallest multiple of ppn which is larger than number of occupied bands\r\n",
66 | " \r\n",
67 | " nomegagw: 80 \r\n",
68 | " # NOMEGAGW to be used in VASP simulations\r\n",
69 | " \r\n",
70 | " convparam: NBANDS \r\n",
71 | " # NBANDS/ENCUTGW/NOMEGA parameter to run convergence test for \r\n",
72 | " \r\n",
73 | " convsteps: 2 \r\n",
74 | " # steps to be used for convergence test\r\n",
75 | " \r\n",
76 | " conviter: 5 \r\n",
77 | " # maximum number of iteration in convergence test \r\n",
78 | " \r\n",
79 | " enwinbse: 3.0 \r\n",
80 | " # energy window in BSE calculations\r\n",
81 | "\r\n",
82 | "\r\n",
83 | "\r\n",
84 | "STRUCTURE:\r\n",
85 | " \r\n",
86 | " source: MID \r\n",
87 | " # MID/POSCAR MID:get structure from MP database, POSCAR: structure from a file\r\n",
88 | " \r\n",
89 | " mat_name: NEW_MAT \r\n",
90 | " # unique identifier in the database when source=POSCAR\r\n",
91 | " \r\n",
92 | " material_id: mp-661 \r\n",
93 | " # material_id of the input structure in MP database\r\n",
94 | " \r\n",
95 | " \r\n",
96 | " \r\n",
97 | "WFLOW_DESIGN:\r\n",
98 | " \r\n",
99 | " skip_emc: false \r\n",
100 | " # set true to skip effective mass calculation \r\n",
101 | " \r\n",
102 | " skip_wannier: false \r\n",
103 | " # set true to skip wannier bandstructure interpolation\r\n",
104 | " \r\n",
105 | " skip_conv: false \r\n",
106 | " # set true to skip convergence test\r\n",
107 | " \r\n",
108 | " skip_gw: false \r\n",
109 | " # set true to skip GW calculation\r\n",
110 | " \r\n",
111 | " scgw: true \r\n",
112 | " # set true to perform self-consistent GW instead of G0W0\r\n",
113 | " \r\n",
114 | " skip_bse: false \r\n",
115 | " # set true to skip BSE calculation\r\n"
116 | ]
117 | }
118 | ],
119 | "source": [
120 | "#Now let's check the content of the 'input.yaml' file.\n",
121 | "!cat 'input.yaml'"
122 | ]
123 | },
124 | {
125 | "cell_type": "code",
126 | "execution_count": 3,
127 | "metadata": {},
128 | "outputs": [
129 | {
130 | "name": "stderr",
131 | "output_type": "stream",
132 | "text": [
133 | "/home/tatha/anaconda3/envs/pygwbse/lib/python3.9/site-packages/pymatgen/ext/matproj.py:182: UserWarning: You are using the legacy MPRester. This version of the MPRester will no longer be updated. To access the latest data with the new MPRester, obtain a new API key from https://materialsproject.org/api and consult the docs at https://docs.materialsproject.org/ for more information.\n",
134 | " warnings.warn(\n"
135 | ]
136 | }
137 | ],
138 | "source": [
139 | "\"\"\"\n",
140 | " 'read_input' function reads input parameters from input.yaml file.\n",
141 | " \n",
142 | " Returns:\n",
143 | " \n",
144 | " structure: pymatgen structure object for the input structure\n",
145 | " input_dict: a dictionary of all the input paramters\n",
146 | " \n",
147 | "\"\"\"\n",
148 | "\n",
149 | "structure, input_dict = read_input()\n",
150 | "#To obtain one go to https://materialsproject.org/api"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "execution_count": 4,
156 | "metadata": {
157 | "scrolled": false
158 | },
159 | "outputs": [
160 | {
161 | "name": "stdout",
162 | "output_type": "stream",
163 | "text": [
164 | "-------------------------------------------\n",
165 | "material: mp-661\n",
166 | "Information for efficient parallelization\n",
167 | "You have 8 occupied bands\n",
168 | "You have 76 kpoints\n",
169 | "You have [[12, 12, 7]] k-grid\n",
170 | "Will perform convergence test for: NBANDS\n",
171 | "Values that will be used for convergence test: 65 91 117 143 169 \n",
172 | "KPAR= 8\n",
173 | "reciprocal_density= 200\n",
174 | "BSE calculation will include bands in the energy window (eV)= 3.0\n",
175 | "-------------------------------------------\n"
176 | ]
177 | },
178 | {
179 | "name": "stderr",
180 | "output_type": "stream",
181 | "text": [
182 | "/home/tatha/anaconda3/envs/pygwbse/lib/python3.9/site-packages/pymatgen/io/vasp/sets.py:419: BadInputSetWarning: Overriding the POTCAR functional is generally not recommended as it significantly affect the results of calculations and compatibility with other calculations done with the same input set. Note that some POTCAR symbols specified in the configuration file may not be available in the selected functional.\n",
183 | " warnings.warn(\n",
184 | "/home/tatha/anaconda3/envs/pygwbse/lib/python3.9/site-packages/pymatgen/io/vasp/inputs.py:1822: UnknownPotcarWarning: POTCAR with symbol Al_GW has metadata that does not match any VASP POTCAR known to pymatgen. The data in this POTCAR is known to match the following functionals: ['PBE_54', 'PBE_52', 'unvie_PBE_52']\n",
185 | " warnings.warn(\n",
186 | "/home/tatha/anaconda3/envs/pygwbse/lib/python3.9/site-packages/pymatgen/io/vasp/inputs.py:1822: UnknownPotcarWarning: POTCAR with symbol N_GW has metadata that does not match any VASP POTCAR known to pymatgen. The data in this POTCAR is known to match the following functionals: ['PBE_54', 'PBE_52', 'unvie_PBE_52']\n",
187 | " warnings.warn(\n"
188 | ]
189 | }
190 | ],
191 | "source": [
192 | "\"\"\"\n",
193 | " 'create_wfs' function creates the GW-BSE workflow based on input specification.\n",
194 | " \n",
195 | " Args:\n",
196 | " \n",
197 | " structure: pymatgen structure object for the input structure\n",
198 | " input_dict: a dictionary of all the input paramters\n",
199 | " \n",
200 | " Returns:\n",
201 | " \n",
202 | " wf_gwbse: GW-BSE workflow as a Fireworks workflow object.\n",
203 | " \n",
204 | "\"\"\"\n",
205 | "\n",
206 | "wf_gwbse=create_wfs(structure, input_dict)"
207 | ]
208 | },
209 | {
210 | "cell_type": "markdown",
211 | "metadata": {},
212 | "source": [
213 | "The error message \"Overriding the POTCAR functional is generally not ...\" is due to changing default POTCAR symbols to GW POTCAR files. One can choose other POTCARs by modifying inputset.yaml file. "
214 | ]
215 | },
216 | {
217 | "cell_type": "code",
218 | "execution_count": 5,
219 | "metadata": {},
220 | "outputs": [],
221 | "source": [
222 | "#Load the Fireworks Launchpad \n",
223 | "lpad = LaunchPad.auto_load() "
224 | ]
225 | },
226 | {
227 | "cell_type": "code",
228 | "execution_count": 6,
229 | "metadata": {},
230 | "outputs": [
231 | {
232 | "name": "stdout",
233 | "output_type": "stream",
234 | "text": [
235 | "2022-10-04 11:55:19,394 INFO Added a workflow. id_map: {-7: 1, -6: 2, -5: 3, -4: 4, -3: 5, -2: 6, -1: 7}\n"
236 | ]
237 | },
238 | {
239 | "data": {
240 | "text/plain": [
241 | "{-7: 1, -6: 2, -5: 3, -4: 4, -3: 5, -2: 6, -1: 7}"
242 | ]
243 | },
244 | "execution_count": 6,
245 | "metadata": {},
246 | "output_type": "execute_result"
247 | }
248 | ],
249 | "source": [
250 | "#Add the workflow you just created\n",
251 | "lpad.add_wf(wf_gwbse)"
252 | ]
253 | },
254 | {
255 | "cell_type": "code",
256 | "execution_count": 7,
257 | "metadata": {
258 | "scrolled": false
259 | },
260 | "outputs": [
261 | {
262 | "name": "stdout",
263 | "output_type": "stream",
264 | "text": [
265 | "/home/tatha/anaconda3/envs/pygwbse/lib/python3.9/site-packages/atomate/vasp/drones.py:46: FutureWarning: which is deprecated; use which in shutil instead.\n",
266 | "shutil.which has been available since Python 3.3. This will be removed in v2023.\n",
267 | " BADER_EXE_EXISTS = which(\"bader\") or which(\"bader.exe\")\n",
268 | "/home/tatha/anaconda3/envs/pygwbse/lib/python3.9/site-packages/pymatgen/io/vasp/sets.py:419: BadInputSetWarning: Overriding the POTCAR functional is generally not recommended as it significantly affect the results of calculations and compatibility with other calculations done with the same input set. Note that some POTCAR symbols specified in the configuration file may not be available in the selected functional.\n",
269 | " warnings.warn(\n",
270 | "[\n",
271 | " {\n",
272 | " \"fw_id\": 1,\n",
273 | " \"created_on\": \"2022-10-04T18:55:18.450316\",\n",
274 | " \"updated_on\": \"2022-10-04T18:55:18.450319\",\n",
275 | " \"state\": \"PAUSED\",\n",
276 | " \"name\": \"mp-661-BSE\"\n",
277 | " },\n",
278 | " {\n",
279 | " \"fw_id\": 2,\n",
280 | " \"created_on\": \"2022-10-04T18:55:18.450282\",\n",
281 | " \"updated_on\": \"2022-10-04T18:55:18.450283\",\n",
282 | " \"name\": \"mp-661-WANNIER\",\n",
283 | " \"state\": \"WAITING\"\n",
284 | " },\n",
285 | " {\n",
286 | " \"fw_id\": 3,\n",
287 | " \"created_on\": \"2022-10-04T18:55:18.450243\",\n",
288 | " \"updated_on\": \"2022-10-04T18:55:18.450248\",\n",
289 | " \"name\": \"mp-661-GW\",\n",
290 | " \"state\": \"WAITING\"\n",
291 | " },\n",
292 | " {\n",
293 | " \"fw_id\": 4,\n",
294 | " \"created_on\": \"2022-10-04T18:55:18.450060\",\n",
295 | " \"updated_on\": \"2022-10-04T18:55:18.450062\",\n",
296 | " \"name\": \"mp-661-CONV\",\n",
297 | " \"state\": \"WAITING\"\n",
298 | " },\n",
299 | " {\n",
300 | " \"fw_id\": 5,\n",
301 | " \"created_on\": \"2022-10-04T18:55:18.436622\",\n",
302 | " \"updated_on\": \"2022-10-04T18:55:18.436623\",\n",
303 | " \"name\": \"mp-661-WANNIER_CHECK\",\n",
304 | " \"state\": \"WAITING\"\n",
305 | " },\n",
306 | " {\n",
307 | " \"fw_id\": 6,\n",
308 | " \"created_on\": \"2022-10-04T18:55:18.435151\",\n",
309 | " \"updated_on\": \"2022-10-04T18:55:18.435152\",\n",
310 | " \"name\": \"mp-661-EMC\",\n",
311 | " \"state\": \"WAITING\"\n",
312 | " },\n",
313 | " {\n",
314 | " \"fw_id\": 7,\n",
315 | " \"created_on\": \"2022-10-04T18:55:18.433728\",\n",
316 | " \"updated_on\": \"2022-10-04T18:55:18.501427\",\n",
317 | " \"state\": \"READY\",\n",
318 | " \"name\": \"mp-661-SCF\"\n",
319 | " }\n",
320 | "]\n"
321 | ]
322 | }
323 | ],
324 | "source": [
325 | "#Check the Fireworks loaded to the Launchpad\n",
326 | "lp='lpad get_fws'\n",
327 | "!{lp}"
328 | ]
329 | },
330 | {
331 | "cell_type": "markdown",
332 | "metadata": {},
333 | "source": [
334 | "As you can see there are 7 fireworks with prefix `mp-661` were loaded to the Launchpad. \n",
335 | "Also one should note that the BSE Firework is in a `PAUSED` state by default. This is \n",
336 | "because, the k-point parallelization is not implemented for BSE calculation in VASP. \n",
337 | "Therefore, to make the number of bands in the WAVEDER file a multiple of number of \n",
338 | "processor used (requirement for VASP, otherwise it will change the NBANDS value) we \n",
339 | "need to run the BSE workflow on NPROCS=NPROCS$'$/KPAR, where NPROCS$'$ is the number \n",
340 | "of processors used for the `fw_id: 2-7`. Now that we have all the Fireworks in the \n",
341 | "Launchpad we can run them and use the postprocessing scripts to analyze the results once \n",
342 | "they are `COMPLETED`."
343 | ]
344 | }
345 | ],
346 | "metadata": {
347 | "kernelspec": {
348 | "display_name": "pygwbse",
349 | "language": "python",
350 | "name": "pygwbse"
351 | },
352 | "language_info": {
353 | "codemirror_mode": {
354 | "name": "ipython",
355 | "version": 3
356 | },
357 | "file_extension": ".py",
358 | "mimetype": "text/x-python",
359 | "name": "python",
360 | "nbconvert_exporter": "python",
361 | "pygments_lexer": "ipython3",
362 | "version": "3.9.13"
363 | }
364 | },
365 | "nbformat": 4,
366 | "nbformat_minor": 4
367 | }
368 |
--------------------------------------------------------------------------------
/example/input.yaml:
--------------------------------------------------------------------------------
1 | PARAMS:
2 | kpar: 4
3 | # 'KPAR' tag to be used in VASP simulations
4 |
5 | ppn: 13
6 | # NPROCS/KPAR ; NPROCS: number of total processors to be used in VASP simulations
7 |
8 | reciprocal_density: 50
9 | # reciprocal density that determines the k-grid using 'automatic_density_by_vol' method of pymatgen
10 |
11 | encutgw: 100
12 | # ENCUTGW to be used in VASP simulations
13 |
14 | nbgwfactor: 2
15 | # NBANDS=nbgwfactor x nocc'; nocc' is the smallest multiple of ppn which is larger than number of occupied bands
16 |
17 | nomegagw: 50
18 | # NOMEGAGW to be used in VASP simulations
19 |
20 | convsteps: [50, 0, 0]
21 | # percentage increments to be used for convergence tests of NBANDS, ENCUTGW, NOMEGA
22 |
23 | conviter: 5
24 | # maximum number of iteration in convergence test
25 |
26 | enwinbse: 3.0
27 | # energy window in BSE calculations
28 |
29 |
30 |
31 | STRUCTURE:
32 |
33 | source: MID
34 | # MID/POSCAR MID:get structure from MP database, POSCAR: structure from a file
35 |
36 | mat_name: NEW_MAT
37 | # unique identifier in the database when source=POSCAR
38 |
39 | material_id: mp-149
40 | # material_id of the input structure in MP database
41 |
42 |
43 |
44 | WFLOW_DESIGN:
45 |
46 | skip_emc: true
47 | # set true to skip effective mass calculation
48 |
49 | skip_wannier: true
50 | # set true to skip wannier bandstructure interpolation
51 |
52 | skip_conv: false
53 | # set true to skip convergence test
54 |
55 | skip_gw: true
56 | # set true to skip GW calculation
57 |
58 | scgw: true
59 | # set true to perform self-consistent GW instead of G0W0
60 |
61 | skip_bse: true
62 | # set true to skip BSE calculation
63 |
--------------------------------------------------------------------------------
/pyGWBSE/config.py:
--------------------------------------------------------------------------------
1 | __author__ = 'Tathagata Biswas '
2 |
3 | # TODO: @computron should be able to load from YAML -computron
4 |
5 | VASP_CMD = ">>vasp_cmd<<"
6 | SUMO_CMD = ">>sumo_cmd<<"
7 | WANNIER_CMD = ">>wannier_cmd<<"
8 | DB_FILE = ">>db_file<<"
9 |
10 |
--------------------------------------------------------------------------------
/pyGWBSE/inputset.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | # Copyright (c) Pymatgen Development Team.
3 | # Distributed under the terms of the MIT License.
4 |
5 | import os
6 |
7 | from monty.serialization import loadfn
8 | from pymatgen.io.vasp.inputs import Incar, Kpoints
9 | from pymatgen.io.vasp.sets import DictSet
10 | from pymatgen.symmetry.bandstructure import HighSymmKpath
11 |
12 | MODULE_DIR = os.path.dirname(os.path.abspath(__file__))
13 |
14 | class CreateInputs(DictSet):
15 | """
16 | Your Comments Here
17 | """
18 | CONFIG = loadfn(os.path.join(MODULE_DIR, "inputset.yaml"))
19 |
20 | SUPPORTED_MODES = ("DIAG", "GW", "STATIC", "BSE", "CONV", "EMC")
21 |
22 | def __init__(self, structure, prev_incar=None, nbands=None, nomegagw=None, encutgw=None,
23 | potcar_functional="PBE_54", reciprocal_density=100, kpoints_line_density = 100, kpar=None, nbandsgw=None,
24 | mode="STATIC", copy_wavecar=True, nbands_factor=5, ncores=16,nbandso=None, nbandsv=None, wannier_fw=None,
25 | **kwargs):
26 | super().__init__(structure, CreateInputs.CONFIG, **kwargs)
27 | self.prev_incar = prev_incar
28 | self.nbands = nbands
29 | self.encutgw = encutgw
30 | self.nomegagw = nomegagw
31 | self.potcar_functional = potcar_functional
32 | self.reciprocal_density = reciprocal_density
33 | self.kpoints_line_density = kpoints_line_density
34 | self.mode = mode.upper()
35 | if self.mode not in CreateInputs.SUPPORTED_MODES:
36 | raise ValueError("%s not one of the support modes : %s" %
37 | (self.mode, CreateInputs.SUPPORTED_MODES))
38 | self.kwargs = kwargs
39 | self.copy_wavecar = copy_wavecar
40 | self.nbands_factor = nbands_factor
41 | self.ncores = ncores
42 | self.kpar = kpar
43 | self.nbandsgw = nbandsgw
44 | self.nbandso = nbandso
45 | self.nbandsv = nbandsv
46 | self.wannier_fw = wannier_fw
47 |
48 | @property
49 | def kpoints(self):
50 | """
51 | Generate gamma center k-points mesh grid for GW calc,
52 | which is requested by GW calculation.
53 | """
54 | if self.mode == "EMC":
55 | kpath = HighSymmKpath(self.structure)
56 | frac_k_points, k_points_labels = kpath.get_kpoints(
57 | line_density=self.kpoints_line_density,
58 | coords_are_cartesian=False)
59 | kpoints = Kpoints(
60 | comment="Non SCF run along symmetry lines",
61 | style=Kpoints.supported_modes.Reciprocal,
62 | num_kpts=len(frac_k_points),
63 | kpts=frac_k_points, labels=k_points_labels,
64 | kpts_weights=[1] * len(frac_k_points))
65 |
66 | return kpoints
67 |
68 | else:
69 |
70 | kpoints=Kpoints.automatic_density_by_vol(self.structure,
71 | self.reciprocal_density, force_gamma=True)
72 |
73 | return kpoints
74 |
75 | @property
76 | def incar(self):
77 | """
78 | Your Comments Here
79 | """
80 | parent_incar = super().incar
81 | incar = Incar(self.prev_incar) if self.prev_incar is not None else \
82 | Incar(parent_incar)
83 | if self.wannier_fw == True:
84 | incar.update({
85 | "LWANNIER90": True
86 | })
87 | if self.mode == "EMC":
88 | incar.update({
89 | "IBRION": -1,
90 | "ISMEAR": 0,
91 | "SIGMA": 0.001,
92 | "LCHARG": False,
93 | "LORBIT": 11,
94 | "LWAVE": False,
95 | "NSW": 0,
96 | "ISYM": 0,
97 | "ICHARG": 11
98 | })
99 | incar.pop("LWANNIER90", None)
100 | incar.pop("LEPSILON", None)
101 | if self.mode == "DIAG":
102 | # Default parameters for diagonalization calculation.
103 | incar.update({
104 | "ALGO": "Exact",
105 | "NELM": 1,
106 | "LOPTICS": True,
107 | "LPEAD": True
108 | })
109 | incar.pop("LEPSILON", None)
110 | incar.pop("LWANNIER90", None)
111 | elif self.mode == "GW":
112 | # Default parameters for GW calculation.
113 | incar.update({
114 | "ALGO": "GW",
115 | "NELM": 1,
116 | "NOMEGA": self.nomegagw,
117 | "ENCUTGW": self.encutgw,
118 | "NBANDSGW": self.nbandsgw,
119 | "LWAVE": True
120 | })
121 | if self.wannier_fw == True:
122 | incar.update({
123 | "LWANNIER90": True
124 | })
125 | incar.pop("EDIFF", None)
126 | incar.pop("LOPTICS", None)
127 | incar.pop("LPEAD", None)
128 | incar.pop("LEPSILON", None)
129 | elif self.mode == "CONV":
130 | # Default parameters for GW calculation.
131 | incar.update({
132 | "ALGO": "GW0",
133 | "NELM": 1,
134 | "NOMEGA": self.nomegagw,
135 | "ENCUTGW": self.encutgw,
136 | "NBANDSGW": self.nbandsgw,
137 | "LWAVE": False
138 | })
139 | incar.pop("EDIFF", None)
140 | incar.pop("LOPTICS", None)
141 | incar.pop("LEPSILON", None)
142 | incar.pop("LPEAD", None)
143 | incar.pop("LWANNIER90", None)
144 | elif self.mode == "BSE":
145 | # Default parameters for BSE calculation.
146 | incar.update({
147 | "ALGO": "BSE",
148 | "ANTIRES": 0,
149 | "NBANDSO": self.nbandso,
150 | "NBANDSV": self.nbandsv,
151 | "KPAR": 1,
152 | "CSHIFT": 0.2
153 | })
154 | incar.pop("LEPSILON", None)
155 | incar.pop("LWANNIER90", None)
156 | if self.nbands:
157 | incar["NBANDS"] = self.nbands
158 |
159 | if self.kpar:
160 | incar["KPAR"] = self.kpar
161 |
162 | rd=self.reciprocal_density
163 |
164 | incar["SYSTEM"] = 'reciprocal density: '+str(rd)
165 |
166 | # Respect user set INCAR.
167 | incar.update(self.kwargs.get("user_incar_settings", {}))
168 |
169 | return incar
170 |
171 |
--------------------------------------------------------------------------------
/pyGWBSE/inputset.yaml:
--------------------------------------------------------------------------------
1 | # Default VASP settings for GW calculations used by the Materials Virtual Lab.
2 | INCAR:
3 | ALGO: Normal
4 | ENCUT: 500
5 | EDIFF: 1.0e-8
6 | ISMEAR: 0
7 | LREAL: AUTO
8 | ISPIN: 1
9 | LWAVE: true
10 | NELM: 100
11 | PREC: Accurate
12 | SIGMA: 0.01
13 | LEPSILON: true
14 | LVHAR: false
15 | LOPTICS: true
16 | LPEAD: false
17 | LORBIT: 11
18 | KPOINTS:
19 | reciprocal_density: 100
20 | POTCAR:
21 | Ac: Ac
22 | Ag: Ag_sv_GW
23 | Al: Al_GW
24 | Ar: Ar_GW
25 | As: As_GW
26 | At: At_d_GW
27 | Au: Au_sv_GW
28 | B: B_GW
29 | Ba: Ba_sv_GW
30 | Be: Be_sv_GW
31 | Bi: Bi_d_GW
32 | Br: Br_GW
33 | C: C_GW
34 | Ca: Ca_sv_GW
35 | Cd: Cd_sv_GW
36 | Ce: Ce_GW
37 | Cl: Cl_GW
38 | Co: Co_sv_GW
39 | Cr: Cr_sv_GW
40 | Cs: Cs_sv_GW
41 | Cu: Cu_sv_GW
42 | Dy: Dy_3
43 | Er: Er_3
44 | Eu: Eu
45 | F: F_GW
46 | Fe: Fe_sv_GW
47 | Ga: Ga_d_GW
48 | Gd: Gd
49 | Ge: Ge_d_GW
50 | H: H_GW
51 | He: He_GW
52 | Hf: Hf_sv_GW
53 | Hg: Hg_sv_GW
54 | Ho: Ho_3
55 | I: I_GW
56 | In: In_d_GW
57 | Ir: Ir_sv_GW
58 | K: K_sv_GW
59 | Kr: Kr_GW
60 | La: La_GW
61 | Li: Li_sv_GW
62 | Lu: Lu_3
63 | Mg: Mg_sv_GW
64 | Mn: Mn_sv_GW
65 | Mo: Mo_sv_GW
66 | N: N_GW
67 | Na: Na_sv_GW
68 | Nb: Nb_sv_GW
69 | Nd: Nd_3
70 | Ne: Ne_GW
71 | Ni: Ni_sv_GW
72 | Np: Np
73 | O: O_GW
74 | Os: Os_sv_GW
75 | P: P_GW
76 | Pa: Pa
77 | Pb: Pb_d_GW
78 | Pd: Pd_sv_GW
79 | Pm: Pm_3
80 | Po: Po_d_GW
81 | Pr: Pr_3
82 | Pt: Pt_sv_GW
83 | Pu: Pu
84 | Rb: Rb_sv_GW
85 | Re: Re_sv_GW
86 | Rh: Rh_sv_GW
87 | Rn: Rn_d_GW
88 | Ru: Ru_sv_GW
89 | S: S_GW
90 | Sb: Sb_d_GW
91 | Sc: Sc_sv_GW
92 | Se: Se_GW
93 | Si: Si_GW
94 | Sm: Sm_3
95 | Sn: Sn_d_GW
96 | Sr: Sr_sv_GW
97 | Ta: Ta_sv_GW
98 | Tb: Tb_3
99 | Tc: Tc_sv_GW
100 | Te: Te_GW
101 | Th: Th
102 | Ti: Ti_sv_GW
103 | Tl: Tl_d_GW
104 | Tm: Tm_3
105 | U: U
106 | V: V_sv_GW
107 | W: W_sv_GW
108 | Xe: Xe_GW
109 | Y: Y_sv_GW
110 | Yb: Yb_2
111 | Zn: Zn_sv_GW
112 | Zr: Zr_sv_GW
113 |
--------------------------------------------------------------------------------
/pyGWBSE/make_wflow.py:
--------------------------------------------------------------------------------
1 | #This code is to create the workflow based on inputs from input.yaml file
2 |
3 | from fireworks import Firework, Workflow
4 | from pyGWBSE.wflows import ScfFW, convFW, BseFW, GwFW, EmcFW, WannierCheckFW, WannierFW
5 | from pyGWBSE.inputset import CreateInputs
6 | from pymatgen.core import Structure
7 | from fireworks import LaunchPad
8 | from pyGWBSE.config import VASP_CMD, DB_FILE, SUMO_CMD, WANNIER_CMD
9 | from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
10 | from pymatgen.io.vasp.inputs import Kpoints
11 | from pymatgen.ext.matproj import MPRester
12 | import numpy as np
13 | from pymongo import MongoClient
14 | import yaml
15 | import sys
16 |
17 |
18 | #Function to find the kgrid and number of symmtery reduced kpoints based on symmetry of the structure and the reciprocal density
19 | def num_ir_kpts(struct,reciprocal_density):
20 | spg=SpacegroupAnalyzer(struct, symprec=0.01, angle_tolerance=5)
21 | Kpts=Kpoints.automatic_density_by_vol(struct,reciprocal_density,force_gamma=True)
22 | kpts=spg.get_ir_reciprocal_mesh(mesh=Kpts.kpts, is_shift=(0, 0, 0))
23 | return Kpts.kpts,len(kpts)
24 |
25 |
26 | #Function to find the number of occupied bands from the input structure
27 | def num_occ_bands(struct):
28 | vasp_input_set = CreateInputs(struct)
29 | nel=vasp_input_set.nelect
30 | nocc=int(nel/2)
31 | return nocc
32 |
33 |
34 | #Function to read the input.yaml file
35 | def read_input(mp_key):
36 |
37 | yaml_file = open("input.yaml")
38 | input_dict = yaml.load(yaml_file, Loader=yaml.FullLoader)
39 | struc_src=input_dict["STRUCTURE"]["source"]
40 |
41 | if struc_src=='POSCAR':
42 | struct=Structure.from_file('POSCAR')
43 | mat_name=input_dict["STRUCTURE"]["mat_name"]
44 | elif struc_src=='MID':
45 | material_id=input_dict["STRUCTURE"]["material_id"]
46 | mat_name=material_id
47 | with MPRester(mp_key) as m:
48 | struct = m.get_structure_by_material_id(material_id,conventional_unit_cell=False)
49 | else:
50 | sys.exit('Error: use MID/POSCAR as structure source .... Exiting NOW')
51 | input_dict["PARAMS"]["mat_name"]=mat_name
52 | return struct, input_dict
53 |
54 | #Function to create the workflow
55 | def create_wfs(struct, params_dict, vasp_cmd=None, sumo_cmd=None, wannier_cmd=None, db_file=None, c=None):
56 |
57 | c = c or {}
58 | vasp_cmd = c.get("VASP_CMD", VASP_CMD)
59 | sumo_cmd = c.get("SUMO_CMD", SUMO_CMD)
60 | wannier_cmd = c.get("WANNIER_CMD", WANNIER_CMD)
61 | db_file = c.get("DB_FILE", DB_FILE)
62 |
63 | params=params_dict["PARAMS"]
64 | mat_name=params["mat_name"]
65 | nocc=num_occ_bands(struct)
66 | kpar=params["kpar"]
67 | ppn=params["ppn"]
68 | rd=params["reciprocal_density"]
69 | nbgwfactor=params["nbgwfactor"]
70 | encutgw=params["encutgw"]
71 | nomegagw=params["nomegagw"]
72 | convsteps=params["convsteps"]
73 | conviter=params["conviter"]
74 | enwinbse=params["enwinbse"]
75 | skip_emc=params_dict["WFLOW_DESIGN"]["skip_emc"]
76 | skip_wannier=params_dict["WFLOW_DESIGN"]["skip_wannier"]
77 | skip_conv=params_dict["WFLOW_DESIGN"]["skip_conv"]
78 | skip_gw=params_dict["WFLOW_DESIGN"]["skip_gw"]
79 | scgw=params_dict["WFLOW_DESIGN"]["scgw"]
80 | skip_bse=params_dict["WFLOW_DESIGN"]["skip_bse"]
81 |
82 | mesh,nkpt=num_ir_kpts(struct,rd)
83 | nbands=(int(nocc/ppn)+1)*ppn
84 | nbandsgw=nocc+10
85 |
86 | print("-------------------------------------------")
87 | print("material: ",mat_name)
88 | print("Information for efficient parallelization")
89 | print("You have ",nocc,"occupied bands")
90 | print("You have ",nkpt,"kpoints")
91 | print("You have ",mesh,"k-grid")
92 | print("KPAR=",kpar)
93 | print("reciprocal_density=",rd)
94 | if not(skip_bse):
95 | print("BSE calculation will include bands in the energy window (eV)=", enwinbse)
96 | print("-------------------------------------------")
97 |
98 | if scgw==True:
99 | gw_tag='GW0'
100 | else:
101 | gw_tag='G0W0'
102 |
103 | ifw=0
104 |
105 | fws = [ScfFW(structure=struct, mat_name=mat_name, nbands=nbands, vasp_cmd=vasp_cmd,db_file=db_file,kpar=kpar,reciprocal_density=rd,wannier_fw=not(skip_wannier))]
106 |
107 | if skip_emc==False:
108 | ifw=ifw+1
109 | parents = fws[0]
110 | fw = EmcFW(structure=struct, mat_name=mat_name, vasp_cmd=vasp_cmd, sumo_cmd=sumo_cmd, db_file=db_file,kpar=kpar,reciprocal_density=rd, steps=0.001,parents=parents)
111 | fws.append(fw)
112 |
113 | if skip_wannier==False:
114 | ifw=ifw+1
115 | parents = fws[0]
116 | fw = WannierCheckFW(structure=struct, mat_name=mat_name, kpar=kpar, ppn=ppn,vasp_cmd=vasp_cmd,wannier_cmd=wannier_cmd,db_file=db_file,parents=parents,reciprocal_density=rd)
117 | fws.append(fw)
118 |
119 | ifw=ifw+1
120 | parents = fws[0]
121 | fw = convFW(structure=struct, mat_name=mat_name, nbands=nbands, nbgwfactor=nbgwfactor, encutgw=encutgw, nomegagw=nomegagw, convsteps=convsteps, conviter=conviter,
122 | tolerence=0.1, no_conv=skip_conv, vasp_cmd=vasp_cmd,db_file=db_file,parents=parents,kpar=kpar,nbandsgw=nbandsgw,reciprocal_density=rd)
123 | fws.append(fw)
124 |
125 | if skip_gw==False:
126 | ifw=ifw+1
127 | parents = fws[ifw-1]
128 | fw = GwFW(structure=struct, mat_name=mat_name, tolerence=0.1, no_conv=not(scgw),
129 | vasp_cmd=vasp_cmd,db_file=db_file,parents=parents,reciprocal_density=rd, nbandsgw=nbandsgw, wannier_fw=not(skip_wannier), job_tag=gw_tag)
130 | fws.append(fw)
131 |
132 | if skip_wannier==False and skip_gw==False:
133 | ifw=ifw+1
134 | parents = fws[ifw-1]
135 | fw = WannierFW(structure=struct,mat_name=mat_name, wannier_cmd=wannier_cmd,db_file=db_file,parents=parents)
136 | fws.append(fw)
137 |
138 | if skip_bse==False and skip_gw==True:
139 | sys.exit('Error: Need QP energies from GW calculation to perform BSE .... Exiting NOW')
140 |
141 | if skip_bse==False and skip_gw==False:
142 | ifw=ifw+1
143 | if skip_wannier==False:
144 | parents = fws[ifw-2]
145 | else:
146 | parents = fws[ifw-1]
147 | fw = BseFW(structure=struct, mat_name=mat_name,
148 | vasp_cmd=vasp_cmd,db_file=db_file,parents=parents,reciprocal_density=rd,enwinbse=enwinbse, job_tag=gw_tag+'-BSE')
149 | fws.append(fw)
150 |
151 |
152 | wf_gwbse = Workflow(fws)
153 |
154 | return wf_gwbse
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/pyGWBSE/out2db.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 |
3 | import glob
4 | import os
5 |
6 | from atomate.utils.utils import env_chk
7 | from atomate.vasp.database import VaspCalcDb
8 | from fireworks import explicit_serialize, FiretaskBase, FWAction
9 | from monty.json import jsanitize
10 | from pymatgen.io.vasp.outputs import Vasprun, Outcar
11 |
12 | from pyGWBSE.tasks import read_emcpyout, read_epsilon, get_gap_from_dict, read_vac_level
13 | from pyGWBSE.wannier_tasks import read_vbm, read_wannier, read_vasp, read_special_kpts
14 |
15 |
16 | @explicit_serialize
17 | class gw2db(FiretaskBase):
18 | """
19 | Insert quasi-particle energies into the database for a GW calculation.
20 | """
21 | required_params = ["structure", "task_label", "db_file", "mat_name"]
22 | optional_params = ["job_tag", "defuse_unsuccessful"]
23 |
24 | def run_task(self, fw_spec):
25 | """
26 | Your Comments Here
27 | """
28 | # get adddtional tags to parse the directory for
29 | db_file = env_chk(self.get('db_file'), fw_spec)
30 | mmdb = VaspCalcDb.from_db_file(db_file, admin=True)
31 | ifconv = fw_spec["ifconv"]
32 | structure = self["structure"]
33 | task_label = self["task_label"]
34 | if "job_tag" in self:
35 | job_tag = self["job_tag"]
36 | else:
37 | job_tag = None
38 | mat_name = self["mat_name"]
39 | task_collection = 'QP_Results'
40 | dir_name = os.getcwd()
41 | file = glob.glob('vasprun.xml*')[-1]
42 | vasprun = Vasprun(file)
43 | file = glob.glob('OUTCAR*')[-1]
44 | outcar = Outcar(file)
45 | run_stats=outcar.run_stats
46 | qp_energies = vasprun.eigenvalues
47 | en, eps1, eps2 = vasprun.dielectric
48 | igap, dgap = get_gap_from_dict(qp_energies)
49 | incar = vasprun.incar
50 | parameters = vasprun.parameters
51 | bgap, cbm, vbm, is_band_gap_direct = vasprun.eigenvalue_band_properties
52 | kpts_dict = vasprun.kpoints.as_dict()
53 | # dictionary to update the database with
54 | d = {"structure": structure.as_dict(),
55 | "formula_pretty": structure.composition.reduced_formula,
56 | "material_id": mat_name, "run_stats": run_stats,
57 | "run_directory": dir_name, 'direct_gap': dgap, 'indirect_gap': igap,
58 | "qp_energies": qp_energies, "task_label": task_label,
59 | "frequency": en, "epsilon_1": eps1, "epsilon_2": eps2,
60 | "job_tag": job_tag, "ifconv": ifconv, "vbm": vbm, "cbm": cbm,
61 | "incar": incar, "parameters": parameters, "kpoints": kpts_dict}
62 | d = jsanitize(d)
63 | coll = mmdb.db[task_collection]
64 | coll.insert_one(d)
65 |
66 | return FWAction(update_spec={"gw_gaps": [igap, dgap]})
67 |
68 |
69 | @explicit_serialize
70 | class bse2db(FiretaskBase):
71 | """
72 | Insert exciton energies, oscillator strength and dielectric function into the database for a BSE calculation.
73 | """
74 | required_params = ["structure", "task_label", "db_file", "mat_name"]
75 | optional_params = ["job_tag", "defuse_unsuccessful"]
76 |
77 | def run_task(self, fw_spec):
78 | """
79 | Your Comments Here
80 | """
81 | # get adddtional tags to parse the directory for
82 | db_file = env_chk(self.get('db_file'), fw_spec)
83 | mmdb = VaspCalcDb.from_db_file(db_file, admin=True)
84 | structure = self["structure"]
85 | task_label = self["task_label"]
86 | job_tag = self["job_tag"]
87 | mat_name = self["mat_name"]
88 | igap = fw_spec["gw_gaps"][0]
89 | dgap = fw_spec["gw_gaps"][1]
90 | task_collection = 'BSE_Results'
91 | dir_name = os.getcwd()
92 | filename = glob.glob('vasprun.xml*')[-1]
93 | if "job_tag" in self:
94 | job_tag = self["job_tag"]
95 | else:
96 | job_tag = None
97 | with open(filename, "a") as file:
98 | file.write("")
99 | vasprun = Vasprun(filename)
100 | incar = vasprun.incar
101 | parameters = vasprun.parameters
102 | optical_transition = vasprun.optical_transition
103 | en, eps1, eps2 = vasprun.dielectric
104 | kpts_dict = vasprun.kpoints.as_dict()
105 | file = glob.glob('OUTCAR*')[-1]
106 | outcar = Outcar(file)
107 | run_stats=outcar.run_stats
108 | d = {"structure": structure.as_dict(),
109 | "formula_pretty": structure.composition.reduced_formula,
110 | "material_id": mat_name, "run_directory": dir_name,
111 | "frequency": en, "epsilon_1": eps1, "epsilon_2": eps2,
112 | 'direct_gap': dgap, 'indirect_gap': igap, "run_stats": run_stats,
113 | "optical_transition": optical_transition, "task_label": task_label, "job_tag": job_tag,
114 | "incar": incar, "parameters": parameters, "kpoints": kpts_dict}
115 | d = jsanitize(d)
116 | coll = mmdb.db[task_collection]
117 | coll.insert_one(d)
118 |
119 | @explicit_serialize
120 | class rpa2db(FiretaskBase):
121 | """
122 | Insert exciton energies, oscillator strength and dielectric function into the database for a BSE calculation.
123 | """
124 | required_params = ["structure", "task_label", "db_file", "mat_name"]
125 | optional_params = ["defuse_unsuccessful"]
126 |
127 | def run_task(self, fw_spec):
128 | """
129 | Your Comments Here
130 | """
131 | # get adddtional tags to parse the directory for
132 | db_file = env_chk(self.get('db_file'), fw_spec)
133 | mmdb = VaspCalcDb.from_db_file(db_file, admin=True)
134 | structure = self["structure"]
135 | task_label = self["task_label"]
136 | mat_name = self["mat_name"]
137 | task_collection = 'RPA_Results'
138 | dir_name = os.getcwd()
139 | filename = glob.glob('vasprun.xml*')[-1]
140 | vasprun = Vasprun(filename)
141 | incar = vasprun.incar
142 | parameters = vasprun.parameters
143 | dft_energies = vasprun.eigenvalues
144 | en, eps1, eps2 = vasprun.dielectric
145 | kpts_dict = vasprun.kpoints.as_dict()
146 | file = glob.glob('OUTCAR*')[-1]
147 | outcar = Outcar(file)
148 | run_stats=outcar.run_stats
149 | d = {"structure": structure.as_dict(),
150 | "formula_pretty": structure.composition.reduced_formula,
151 | "material_id": mat_name, "run_directory": dir_name,
152 | "dft_energies": dft_energies, "run_stats": run_stats,
153 | "frequency": en, "epsilon_1": eps1, "epsilon_2": eps2, "task_label": task_label,
154 | "incar": incar, "parameters": parameters, "kpoints": kpts_dict}
155 | d = jsanitize(d)
156 | coll = mmdb.db[task_collection]
157 | coll.insert_one(d)
158 |
159 | @explicit_serialize
160 | class emc2db(FiretaskBase):
161 | """
162 | Insert effective masses for a SUMO-BANDSTATS calculation.
163 | """
164 | required_params = ["structure", "db_file", "mat_name"]
165 | optional_params = ["defuse_unsuccessful"]
166 |
167 | def run_task(self, fw_spec):
168 | """
169 | Your Comments Here
170 | """
171 | # get adddtional tags to parse the directory for
172 | db_file = env_chk(self.get('db_file'), fw_spec)
173 | dir_name = os.getcwd()
174 | mmdb = VaspCalcDb.from_db_file(db_file, admin=True)
175 | structure = self["structure"]
176 | mat_name = self["mat_name"]
177 | task_collection = 'EMC_Results'
178 | filename = glob.glob('sumo-bandstats.log*')[-1]
179 | hmass, emass = read_emcpyout(filename)
180 | # dictionary to update the database with
181 | d = {"structure": structure.as_dict(),
182 | "formula_pretty": structure.composition.reduced_formula,
183 | "material_id": mat_name, "run_directory": dir_name,
184 | "hole_effective_mass": hmass, "electron_effective_mass": emass}
185 | d = jsanitize(d)
186 | coll = mmdb.db[task_collection]
187 | coll.insert_one(d)
188 |
189 | @explicit_serialize
190 | class eps2db(FiretaskBase):
191 | """
192 | Insert macroscopic dielectric constants for LEPSILON=TRUE calculation.
193 | """
194 | required_params = ["structure", "db_file", "mat_name"]
195 | optional_params = ["defuse_unsuccessful"]
196 |
197 | def run_task(self, fw_spec):
198 | """
199 | Your Comments Here
200 | """
201 | # get additional tags to parse the directory for
202 | db_file = env_chk(self.get('db_file'), fw_spec)
203 | mmdb = VaspCalcDb.from_db_file(db_file, admin=True)
204 | dir_name = os.getcwd()
205 | structure = self["structure"]
206 | mat_name = self["mat_name"]
207 | task_collection = 'EPS_Results'
208 | filename = glob.glob('vasprun.xml*')[-1]
209 | try:
210 | locpot_fname = glob.glob('LOCPOT*')[-1]
211 | zvac, evac, delta_evac=read_vac_level(locpot_fname, filename)
212 | ifvac=True
213 | except:
214 | ifvac=False
215 | epsilon = read_epsilon(filename)
216 | vrun = Vasprun(filename, parse_projected_eigen=True)
217 | ks_energies = vrun.eigenvalues
218 | proj_eigs=vrun.projected_eigenvalues
219 | kwgs=vrun.actual_kpoints_weights
220 | file = glob.glob('OUTCAR*')[-1]
221 | outcar = Outcar(file)
222 | run_stats=outcar.run_stats
223 | igap, dgap = get_gap_from_dict(ks_energies)
224 | bgap, cbm, vbm, is_band_gap_direct = vrun.eigenvalue_band_properties
225 | # dictionary to update the database with
226 | d = {"structure": structure.as_dict(),
227 | "formula_pretty": structure.composition.reduced_formula,
228 | "material_id": mat_name, "dielectric constant": epsilon,
229 | "run_stats": run_stats, "run_directory": dir_name,
230 | 'direct_gap': dgap, 'indirect_gap': igap,
231 | "kpoint_weights": kwgs, "cbm": cbm, "vbm": vbm,
232 | "projected_eigs": proj_eigs, "ks_energies": ks_energies}
233 | if ifvac:
234 | d.update({"z_vacuum": zvac, "e_vacuum": evac, "delta_e_vacuum": delta_evac})
235 | d = jsanitize(d)
236 | coll = mmdb.db[task_collection]
237 | coll.insert_one(d)
238 |
239 |
240 |
241 | @explicit_serialize
242 | class Wannier2DB(FiretaskBase):
243 | """
244 | Insert a optical transition and quasi-particle energies
245 | into the database for a GW and BSE calculation.
246 |
247 | Args:
248 | db_file (str): path to file containing the database credentials.
249 | Supports env_chk. Default: write data to JSON file.
250 | task_collection (str): The name of the task collection you
251 | want to push the data to.
252 | wf_name (str): The name of the workflow that this analysis is part of.
253 | """
254 |
255 | required_params = ["structure", "task_label", "db_file", "compare_vasp", "mat_name"]
256 | optional_params = ["defuse_unsuccessful"]
257 |
258 | def run_task(self, fw_spec):
259 | """
260 | Your Comments Here
261 | """
262 | # get adddtional tags to parse the directory for
263 | db_file = env_chk(self.get('db_file'), fw_spec)
264 | mmdb = VaspCalcDb.from_db_file(db_file, admin=True)
265 | structure = self["structure"]
266 | task_label = self["task_label"]
267 | compare_vasp = self["compare_vasp"]
268 | mat_name = self["mat_name"]
269 | task_collection = 'WANNIER_Results'
270 | dir_name = os.getcwd()
271 | fname_band = glob.glob('wannier90_band.dat*')[-1]
272 | fname_kpt = glob.glob('wannier90_band.kpt*')[-1]
273 | fname_gnu = glob.glob('wannier90_band.gnu*')[-1]
274 | fname_vasp = glob.glob('vasprun.xml*')[-1]
275 | gap, vbm = read_vbm(fname_vasp)
276 | kpts, eigs_wann = read_wannier(fname_band, fname_kpt, vbm)
277 | spkptl, spkptc = read_special_kpts(fname_gnu)
278 | if compare_vasp:
279 | kpt_vasp, eigs_vasp = read_vasp(fname_vasp, vbm)
280 | d = {"structure": structure.as_dict(),
281 | "formula_pretty": structure.composition.reduced_formula,
282 | "material_id": mat_name,
283 | "run_directory": dir_name,
284 | "wannier_kpoints": kpts, "wannier_eigenvalues": eigs_wann,
285 | "actual_kpoints": kpt_vasp, "actual_eigenvalues": eigs_vasp,
286 | "special_kpoint_labels": spkptl,
287 | "special_kpoint_coordinates": spkptc,
288 | "task_label": task_label}
289 | else:
290 | d = {"structure": structure.as_dict(),
291 | "formula_pretty": structure.composition.reduced_formula,
292 | "material_id": mat_name,
293 | "run_directory": dir_name,
294 | "wannier_kpoints": kpts, "wannier_eigenvalues": eigs_wann,
295 | "special_kpoint_labels": spkptl,
296 | "special_kpoint_coordinates": spkptc,
297 | "task_label": task_label}
298 | d = jsanitize(d)
299 | coll = mmdb.db[task_collection]
300 | coll.insert_one(d)
301 |
--------------------------------------------------------------------------------
/pyGWBSE/run_calc.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 |
3 | """
4 | This module defines tasks that support running vasp in various ways.
5 | """
6 |
7 | import os
8 | import subprocess
9 |
10 | from atomate.utils.utils import env_chk, get_logger
11 | from fireworks import explicit_serialize, FiretaskBase
12 |
13 | __author__ = 'Anubhav Jain '
14 | __credits__ = 'Shyue Ping Ong '
15 |
16 | logger = get_logger(__name__)
17 |
18 |
19 | @explicit_serialize
20 | class Run_Vasp(FiretaskBase):
21 | """
22 | Execute a command directly (no custodian).
23 |
24 | Args:
25 | cmd (str): the name of the full executable to run. Supports env_chk.
26 |
27 | Other Parameters:
28 | expand_vars (str): Set to true to expand variable names in the cmd.
29 | """
30 |
31 | required_params = ["vasp_cmd"]
32 | optional_params = ["expand_vars"]
33 |
34 | def run_task(self, fw_spec):
35 | """
36 | Your Comments Here
37 | """
38 | cmd = env_chk(self["vasp_cmd"], fw_spec)
39 | if self.get("expand_vars", False):
40 | cmd = os.path.expandvars(cmd)
41 |
42 | logger.info("Running command: {}".format(cmd))
43 | return_code = subprocess.call(cmd, shell=True)
44 | logger.info("Command {} finished running with returncode: {}".format(cmd, return_code))
45 |
46 |
47 | @explicit_serialize
48 | class Run_Sumo(FiretaskBase):
49 | """
50 | Your Comments Here
51 | """
52 | required_params = ["sumo_cmd"]
53 |
54 | def run_task(self, fw_spec):
55 | """
56 | Your Comments Here
57 | """
58 | cmd = env_chk(self["sumo_cmd"], fw_spec)
59 | logger.info("Running command: {}".format(cmd))
60 | return_code = subprocess.call(cmd, shell=True)
61 | logger.info("Command {} finished running with returncode: {}".format(cmd, return_code))
62 |
63 |
64 | @explicit_serialize
65 | class Run_Wannier(FiretaskBase):
66 | """
67 | Your Comments Here
68 | """
69 | required_params = ["wannier_cmd"]
70 |
71 | def run_task(self, fw_spec):
72 | """
73 | Your Comments Here
74 | """
75 | cmd = env_chk(self["wannier_cmd"], fw_spec)
76 | logger.info("Running command: {}".format(cmd))
77 | return_code = subprocess.call(cmd, shell=True)
78 | logger.info("Command {} finished running with returncode: {}".format(cmd, return_code))
79 |
--------------------------------------------------------------------------------
/pyGWBSE/tasks.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 |
3 | import glob
4 | import gzip
5 | import os
6 | import re
7 | from atomate.common.firetasks.glue_tasks import CopyFiles, get_calc_loc
8 | from atomate.utils.utils import env_chk, get_logger
9 | from fireworks import explicit_serialize, FiretaskBase, FWAction
10 | from pymatgen.io.vasp import Vasprun, Locpot
11 | from pymatgen.io.vasp.inputs import Incar
12 | from pymatgen.core import Structure
13 |
14 | from pyGWBSE.inputset import CreateInputs
15 |
16 | """
17 | This module defines tasks that acts as a glue between other vasp Firetasks to allow communication
18 | between different Firetasks and Fireworks. This module also contains tasks that affect the control
19 | flow of the workflow, e.g. tasks to check stability or the gap is within a certain range.
20 | """
21 |
22 | logger = get_logger(__name__)
23 |
24 | __author__ = 'Anubhav Jain, Kiran Mathew'
25 | __email__ = 'ajain@lbl.gov, kmathew@lbl.gov'
26 |
27 |
28 | @explicit_serialize
29 | class CheckBeConv(FiretaskBase):
30 | """
31 | Your Comments Here
32 | """
33 | required_params = ["niter", "tolerence", "no_conv"]
34 |
35 | def run_task(self, fw_spec):
36 | """
37 | Your Comments Here
38 | """
39 | niter = self["niter"]
40 | conv = self["no_conv"]
41 | tol = self["tolerence"]
42 | filename = str(os.getcwd()) + '/vasprun.xml'
43 | vasprun = Vasprun(filename)
44 | gap, cbm, vbm, is_direct = vasprun.eigenvalue_band_properties
45 | print()
46 | print('=================================================')
47 | print('Iteration:', niter)
48 | print("band gap:", ("%10.4f" % gap))
49 | print("CBM:", ("%10.4f" % cbm))
50 | print("VBM:", ("%10.4f" % vbm))
51 | print("Is the gap direct:", is_direct)
52 | if niter > 1:
53 | old_val = fw_spec["conval"]
54 | new_val = gap
55 | diff = abs(old_val - new_val)
56 | print("Difference:", ("%10.4f" % diff))
57 | print('=================================================')
58 | print()
59 | if diff < tol:
60 | conv = True
61 | return FWAction(update_spec={"ifconv": conv, "conval": gap})
62 |
63 |
64 | @explicit_serialize
65 | class MakeWFilesList(FiretaskBase):
66 |
67 | def run_task(self, fw_spec):
68 | files2copy = glob.glob("W*.tmp")
69 | return FWAction(update_spec={"wfiles": files2copy})
70 |
71 | @explicit_serialize
72 | class SaveNbandsov(FiretaskBase):
73 |
74 | required_params = ["enwinbse"]
75 |
76 | def run_task(self, fw_spec):
77 |
78 | enwinbse = self["enwinbse"]
79 | filename = str(os.getcwd()) + '/vasprun.xml'
80 | vasprun = Vasprun(filename)
81 | qpe=vasprun.eigenvalues
82 | gap, cbm, vbm, is_direct = vasprun.eigenvalue_band_properties
83 | nbandso,nbandsv=get_nbandsov(qpe,vbm,cbm,enwinbse)
84 |
85 | return FWAction(update_spec={"nbandso": nbandso, "nbandsv": nbandsv})
86 |
87 | @explicit_serialize
88 | class SaveConvParams(FiretaskBase):
89 |
90 | required_params = ["nomegagw","encutgw","nbands"]
91 |
92 | def run_task(self, fw_spec):
93 | nomegagw=self["nomegagw"]
94 | encutgw=self["encutgw"]
95 | nbands=self["nbands"]
96 | return FWAction(update_spec={"nomegagw": nomegagw, "encutgw": encutgw, "nbands": nbands})
97 |
98 | @explicit_serialize
99 | class StopIfConverged(FiretaskBase):
100 | """
101 | Your Comments Here
102 | """
103 | def run_task(self, fw_spec):
104 | """
105 | Your Comments Here
106 | """
107 | ifconv = fw_spec["ifconv"]
108 | if ifconv:
109 | return FWAction(exit=True)
110 |
111 |
112 | @explicit_serialize
113 | class PasscalClocsCond(FiretaskBase):
114 | """
115 | Your Comments Here
116 | """
117 | required_params = ["name"]
118 | optional_params = ["filesystem", "path"]
119 |
120 | def run_task(self, fw_spec):
121 | """
122 | Your Comments Here
123 | """
124 | calc_locs = list(fw_spec.get("calc_locs", []))
125 | calc_locs.append({"name": self["name"],
126 | "filesystem": env_chk(self.get('filesystem', None), fw_spec),
127 | "path": self.get("path", os.getcwd())})
128 | ifconv = fw_spec["ifconv"]
129 | if ifconv:
130 | return FWAction(mod_spec=[{'_push_all': {'calc_locs': calc_locs}}])
131 |
132 |
133 | @explicit_serialize
134 | class WriteBSEInput(FiretaskBase):
135 | """
136 | Your Comments Here
137 | """
138 | required_params = ["structure", "reciprocal_density"]
139 |
140 | def run_task(self, fw_spec):
141 | """
142 | Your Comments Here
143 | """
144 | f_incar = str(os.getcwd()) + '/INCAR'
145 | structure = self["structure"]
146 | reciprocal_density = self["reciprocal_density"]
147 | nbandso = fw_spec["nbandso"]
148 | nbandsv = fw_spec["nbandsv"]
149 | prev_incar = Incar.from_file(f_incar)
150 | vis = CreateInputs(structure, mode='BSE', prev_incar=prev_incar, reciprocal_density=reciprocal_density,
151 | nbandso=nbandso, nbandsv=nbandsv)
152 | vis.write_input(".")
153 |
154 |
155 | @explicit_serialize
156 | class WriteGWInput(FiretaskBase):
157 | """
158 | Your Comments Here
159 | """
160 | required_params = ["structure", "reciprocal_density", "nbandsgw", "wannier_fw"]
161 |
162 | def run_task(self, fw_spec):
163 | """
164 | Your Comments Here
165 | """
166 | f_incar = str(os.getcwd()) + '/INCAR'
167 | prev_incar = Incar.from_file(f_incar)
168 | structure = self["structure"]
169 | nbandsgw = self["nbandsgw"]
170 | wannier_fw = self["wannier_fw"]
171 | reciprocal_density = self["reciprocal_density"]
172 | encutgw=fw_spec["encutgw"]
173 | nomegagw=fw_spec["nomegagw"]
174 | nbands=fw_spec["nbands"]
175 | vis = CreateInputs(structure, mode='GW', prev_incar=prev_incar, reciprocal_density=reciprocal_density,
176 | encutgw=encutgw, nomegagw=nomegagw, nbands=nbands, nbandsgw=nbandsgw, wannier_fw=wannier_fw)
177 | vis.write_input(".")
178 |
179 |
180 | def read_emcpyout(fname):
181 | f = open(fname)
182 | contents = f.readlines()
183 | f.close()
184 | ne=0
185 | nh=0
186 | h_res={}
187 | e_res={}
188 | for content in contents:
189 | if "m_h:" in content:
190 | nh=nh+1
191 | lines = str.split(content)
192 | hmass=eval(lines[1])
193 | hibnd=eval(lines[4])
194 | inda=lines.index('->')
195 | if inda==10:
196 | hdir1=lines[9]
197 | hdir2=lines[14]
198 | else:
199 | hdir1='Intermediate'
200 | hdir2=lines[13]
201 |
202 | h_res['mass'+str(nh)+': '+str(hibnd)+', '+hdir1+', '+hdir2]=hmass
203 |
204 | if "m_e:" in content:
205 | ne=ne+1
206 | lines = str.split(content)
207 | emass=eval(lines[1])
208 | eibnd=eval(lines[4])
209 | inda=lines.index('->')
210 | if inda==10:
211 | edir1=lines[9]
212 | edir2=lines[14]
213 | else:
214 | edir1='Intermediate'
215 | edir2=lines[13]
216 |
217 |
218 | e_res['mass'+str(ne)+': '+str(eibnd)+', '+edir1+', '+edir2]=emass
219 |
220 | return h_res, e_res
221 |
222 | def read_epsilon(fname):
223 | vasprun = Vasprun(fname)
224 | try:
225 | epsilon = vasprun.epsilon_static_wolfe
226 | except:
227 | epsilon = None
228 | return epsilon
229 |
230 |
231 | def calc_delta_evac(x,y,n0):
232 | dx1=x[n0+1]-x[n0]
233 | dy1=y[n0+1]-y[n0]
234 | dx2=x[n0]-x[n0-1]
235 | dy2=y[n0]-y[n0-1]
236 | f1=dy1/dx1
237 | f2=dy2/dx2
238 | return (f1+f2)/2
239 |
240 |
241 |
242 | def read_vac_level(locpot_fname,fname):
243 | lpot=Locpot.from_file(locpot_fname)
244 | vrun=Vasprun(fname)
245 | vrun_d=vrun.as_dict()
246 | struct=Structure.from_dict(vrun_d["input"]["crystal"])
247 | latt_c=struct.lattice.c
248 | y=lpot.get_average_along_axis(2)
249 | zarr=lpot.get_axis_grid(2)
250 |
251 | dist_z0=0.
252 | z0=0.
253 |
254 | for n,z in enumerate(zarr):
255 | dist=[]
256 | for site in struct.sites:
257 | pos_z=site.coords[2]
258 | if pos_z<0:
259 | pos_z=pos_z+latt_c
260 | dist.append(abs(pos_z-z))
261 | dist.append(abs(pos_z+latt_c-z))
262 | dist_z=min(dist)
263 | if dist_z>dist_z0:
264 | dist_z0=dist_z
265 | z0=z
266 | n0=n
267 |
268 | evac=y[n0]
269 | zvac=zarr[n0]
270 | delta_evac=calc_delta_evac(zarr,y,n0)
271 |
272 | return zvac,evac,delta_evac
273 |
274 | def get_gap_from_dict(qp_energies):
275 |
276 | tol=1e-5
277 | vbm = -float("inf")
278 | cbm = float("inf")
279 | for spin, d in qp_energies.items():
280 | for k, val in enumerate(d):
281 | for (eigenval, occu) in val:
282 | if occu > tol and eigenval > vbm:
283 | vbm = eigenval
284 | elif occu <= tol and eigenval < cbm:
285 | cbm = eigenval
286 | igap=max(cbm-vbm,0)
287 |
288 | gap = []
289 | filled = 1.0
290 | tol=1e-5
291 | vbm=0
292 | cbm=0
293 | for spin, d in qp_energies.items():
294 | for k, val in enumerate(d):
295 | for (eigenval, occu) in val:
296 | if abs(occu-filled)<=tol:
297 | vbm=eigenval
298 | else:
299 | cbm=eigenval
300 | gap.append(cbm-vbm)
301 | break
302 | dgap=min(gap)
303 | return igap,dgap
304 |
305 | def get_nbandsov(qp_energies,vbm,cbm,enwinbse):
306 |
307 | tol=1e-5
308 | nvb=[]
309 | ncb=[]
310 | for spin, d in qp_energies.items():
311 | for k, val in enumerate(d):
312 | for ibnd,(eigenval, occ) in enumerate(val):
313 | if abs(occ-1.0) 9:
404 | raise ValueError(
405 | "CopyVaspOutputs doesn't properly handle >9 relaxations!")
406 | m = re.search('\.relax\d*', relax_paths[-1])
407 | relax_ext = m.group(0)
408 |
409 | # detect .gz extension if needed - note that monty zpath() did not seem useful here
410 | gz_ext = ""
411 | if not (f + relax_ext) in all_files:
412 | for possible_ext in [".gz", ".GZ"]:
413 | if (f + relax_ext + possible_ext) in all_files:
414 | gz_ext = possible_ext
415 |
416 | if not (f + relax_ext + gz_ext) in all_files:
417 | raise ValueError("Cannot find file: {}".format(f))
418 |
419 | # copy the file (minus the relaxation extension)
420 | self.fileclient.copy(prev_path_full + relax_ext + gz_ext,
421 | dest_path + gz_ext)
422 |
423 | # unzip the .gz if needed
424 | if gz_ext in ['.gz', ".GZ"]:
425 | # unzip dest file
426 | f = gzip.open(dest_path + gz_ext, 'rt')
427 | file_content = f.read()
428 | with open(dest_path, 'w') as f_out:
429 | f_out.writelines(file_content)
430 | f.close()
431 | os.remove(dest_path + gz_ext)
432 |
--------------------------------------------------------------------------------
/pyGWBSE/wannier_tasks.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 |
3 | """
4 | This module defines tasks for WANNIER90 calculation
5 | """
6 |
7 | import os
8 |
9 | import numpy as np
10 | from atomate.utils.utils import get_logger
11 | from fireworks import explicit_serialize, FiretaskBase
12 | from pymatgen.core import Structure
13 | from pymatgen.io.vasp import Vasprun
14 | from pymatgen.io.vasp.inputs import Incar, Potcar, PotcarSingle
15 | from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
16 | from pymatgen.symmetry.bandstructure import HighSymmKpath
17 |
18 | from pyGWBSE.inputset import CreateInputs
19 |
20 | logger = get_logger(__name__)
21 |
22 | __author__ = 'Tathagata Biswas'
23 | __email__ = 'tbiswas3@asu.edu'
24 |
25 |
26 | @explicit_serialize
27 | class WriteWannierInputForGW(FiretaskBase):
28 | """
29 | Your Comments Here
30 | """
31 | required_params = ["structure", "reciprocal_density", "nbandsgw"]
32 |
33 | def run_task(self, fw_spec):
34 | """
35 | Your Comments Here
36 | """
37 | f_incar = str(os.getcwd()) + '/INCAR'
38 | structure = self["structure"]
39 | nbandsgw = self["nbandsgw"]
40 | reciprocal_density = self["reciprocal_density"]
41 | prev_incar = Incar.from_file(f_incar)
42 | wann_inp = str(os.getcwd()) + '/wannier90.win'
43 | vasprunfile = str(os.getcwd()) + '/vasprun.xml'
44 | poscarfile = str(os.getcwd()) + '/POSCAR'
45 | potcarfile = str(os.getcwd()) + '/POTCAR'
46 | vasprun = Vasprun(vasprunfile)
47 | incar = vasprun.incar
48 | nbands = incar["NBANDS"]
49 | elements = read_potcar(potcarfile, poscarfile)
50 | labels, kpts = kpath_finder(poscarfile)
51 | numwan = 0
52 | for element in elements:
53 | numwan = numwan + element[5]
54 | if numwan > nbandsgw:
55 | nbandsgw = numwan
56 | encutgw=fw_spec["encutgw"]
57 | nomegagw=fw_spec["nomegagw"]
58 | nbands=fw_spec["nbands"]
59 | vis = CreateInputs(structure, mode='GW', reciprocal_density=reciprocal_density,
60 | prev_incar=prev_incar, encutgw=encutgw, nomegagw=nomegagw, nbands=nbands, nbandsgw=nbandsgw)
61 | vis.write_input(".")
62 | labels, kpts = kpath_finder(poscarfile)
63 | write_wannier_input(numwan, nbands, labels, kpts, wann_inp, elements,False)
64 |
65 |
66 | @explicit_serialize
67 | class WriteWannierInputForDFT(FiretaskBase):
68 | """
69 | Your Comments Here
70 | """
71 | required_params = ["structure", "reciprocal_density", "ppn", "write_hr"]
72 |
73 | def run_task(self, fw_spec):
74 | """
75 | Your Comments Here
76 | """
77 | f_incar = str(os.getcwd()) + '/INCAR'
78 | structure = self["structure"]
79 | reciprocal_density = self["reciprocal_density"]
80 | ppn = self["ppn"]
81 | write_hr = self["write_hr"]
82 | prev_incar = Incar.from_file(f_incar)
83 | wann_inp = str(os.getcwd()) + '/wannier90.win'
84 | vasprunfile = str(os.getcwd()) + '/vasprun.xml'
85 | poscarfile = str(os.getcwd()) + '/POSCAR'
86 | potcarfile = str(os.getcwd()) + '/POTCAR'
87 | vasprun = Vasprun(vasprunfile)
88 | incar = vasprun.incar
89 | nbands = incar["NBANDS"]
90 | elements = read_potcar(potcarfile, poscarfile)
91 | numwan = 0
92 | for element in elements:
93 | numwan = numwan + element[5]
94 | print(numwan, nbands)
95 | if numwan > nbands:
96 | nbands = (int(numwan / ppn) + 1) * ppn
97 | vis = CreateInputs(structure, mode='STATIC', prev_incar=prev_incar, reciprocal_density=reciprocal_density,
98 | nbands=nbands)
99 | vis.write_input(".")
100 | labels, kpts = kpath_finder(poscarfile)
101 | write_wannier_input(numwan, nbands, labels, kpts, wann_inp, elements,write_hr)
102 |
103 |
104 | @explicit_serialize
105 | class CopyKptsWan2vasp(FiretaskBase):
106 | """
107 | Your Comments Here
108 | """
109 |
110 | def run_task(self, fw_spec):
111 | """
112 | Your Comments Here
113 | """
114 | f_wannkpt = str(os.getcwd()) + '/wannier90_band.kpt'
115 | f_vaspkpt = str(os.getcwd()) + '/KPOINTS'
116 | f = open(f_wannkpt)
117 | contents = f.readlines()
118 | f.close()
119 | lines = str.split(contents[0])
120 | nkpts = eval(lines[0])
121 | f = open(f_vaspkpt, 'w')
122 | f.write('kpoints file generated from wannier90_band.kpt' + '\n')
123 | f.write(str(nkpts) + '\n')
124 | f.write('Reciprocal' + '\n')
125 | for ik in range(nkpts):
126 | f.write(contents[ik + 1])
127 | f.close()
128 |
129 |
130 | def write_wannier_input(numwan, nbands, labels, kpts, wann_inp, elements,write_hr):
131 | """
132 | Your Comments Here
133 | """
134 | if write_hr:
135 | f = open(wann_inp, 'a')
136 | f.write("write_hr = true" + "\n")
137 | f.close()
138 | else:
139 | f = open(wann_inp, 'w')
140 | f.write("num_wann = " + str(numwan) + "\n")
141 | if numwan < nbands:
142 | f.write("exclude_bands " + str(numwan + 1) + "-" + str(nbands) + "\n")
143 | if numwan == nbands - 1:
144 | f.write("exclude_bands " + str(numwan + 1) + "\n")
145 | f.write("bands_plot = true" + "\n")
146 | f.write("begin kpoint_path" + "\n")
147 | for i in range(len(labels)):
148 | for j in range(len(labels[i])-1):
149 | label1=labels[i][j]
150 | label2=labels[i][j+1]
151 | string = write_kpath_lines(kpts[label1], label1, kpts[label2], label2)
152 | f.write(string)
153 | f.write("end kpoint_path" + "\n")
154 | f.write("bands_num_points 40" + "\n")
155 | f.write("bands_plot_format gnuplot" + "\n")
156 | f.write("Begin Projections" + "\n")
157 | f.write("random" + "\n")
158 | for element in elements:
159 | f.write(element[0] + ':')
160 | for l in range(4):
161 | if element[l + 1] > 0:
162 | if l == 0:
163 | f.write('l=' + str(l))
164 | else:
165 | f.write(';' + 'l=' + str(l))
166 | f.write('\n')
167 | f.write("End Projections" + "\n")
168 | f.write("num_iter = 500" + "\n")
169 | f.close()
170 |
171 |
172 | def write_kpath_lines(kpt1, label1, kpt2, label2):
173 | """
174 | Your Comments Here
175 | """
176 | string = label1 + " " + "%10.5f" % kpt1[0] + "%10.5f" % kpt1[1] + "%10.5f" % kpt1[
177 | 2] + " " + label2 + " " + "%10.5f" % kpt2[0] + "%10.5f" % kpt2[1] + "%10.5f" % kpt2[2] + "\n"
178 | return string
179 |
180 |
181 | def kpath_finder(filename):
182 | """
183 | Your Comments Here
184 | """
185 | struct = Structure.from_file(filename)
186 | spcg = SpacegroupAnalyzer(struct)
187 | pstruct = spcg.get_primitive_standard_structure(international_monoclinic=False)
188 | hskp = HighSymmKpath(pstruct)
189 | kpts = hskp.kpath["kpoints"]
190 | labels = hskp.kpath["path"]
191 | return labels, kpts
192 |
193 |
194 | def read_potcar(potcarfile, poscarfile):
195 | """
196 | Your Comments Here
197 | """
198 | struct = Structure.from_file(poscarfile)
199 | potcar = Potcar.from_file(potcarfile)
200 | sites = struct.species
201 | specs = potcar.spec
202 | wan_info = []
203 | for spec in specs:
204 | single = PotcarSingle.from_symbol_and_functional(symbol=spec['symbol'], functional='PBE_54')
205 | orbitals = single.electron_configuration
206 | element = single.element
207 | nat = str(sites).count(single.element)
208 | spdf = []
209 | for orbital in orbitals:
210 | spdf.append(orbital[1])
211 | scnt = spdf.count('s')
212 | pcnt = spdf.count('p')
213 | dcnt = spdf.count('d')
214 | fcnt = spdf.count('f')
215 | numwan = nat * (scnt * 1 + pcnt * 3 + dcnt * 5 + fcnt * 7)
216 | wan_info.append([element, scnt, pcnt, dcnt, fcnt, numwan])
217 | return wan_info
218 |
219 |
220 | def read_vbm(fname):
221 | """
222 | Your Comments Here
223 | """
224 | vasprun = Vasprun(fname, parse_potcar_file=False)
225 | gap, cbm, vbm, is_direct = vasprun.eigenvalue_band_properties
226 | return gap, vbm
227 |
228 |
229 | def read_wannier(fname_band, fname_kpt, vbm):
230 | """
231 | Your Comments Here
232 | """
233 | f = open(fname_band)
234 | contents = f.readlines()
235 | f.close()
236 |
237 | kvals = []
238 | evals = []
239 |
240 | for content in contents:
241 | lines = str.split(content)
242 | if len(lines) != 0:
243 | kvals.append(eval(lines[0]))
244 | evals.append(eval(lines[1]))
245 | with open(fname_kpt) as f:
246 | first_line = f.readline()
247 | nkpt = eval(str.split(first_line)[0])
248 | nband = int(len(evals) / nkpt)
249 | kpts_flat = np.array(kvals)
250 | eigs_flat = np.array(evals) - vbm
251 | kpts = kpts_flat.reshape(nband, nkpt)
252 | eigs = eigs_flat.reshape(nband, nkpt)
253 |
254 | return kpts, eigs
255 |
256 |
257 | def read_vasp(fname, vbm):
258 | """
259 | Your Comments Here
260 | """
261 | vasprun = Vasprun(fname)
262 | eigs = vasprun.eigenvalues
263 | nkpt = len(vasprun.actual_kpoints)
264 | kptvasp = vasprun.actual_kpoints
265 | out = []
266 | for spin, d in eigs.items():
267 | for k, val in enumerate(d):
268 | for n, eigenval in enumerate(val):
269 | out.append(eigenval[0] - vbm)
270 | nbands = int(len(out) / nkpt)
271 | eigvasp = np.reshape(out, (nkpt, nbands))
272 |
273 | return kptvasp, eigvasp
274 |
275 |
276 | def read_special_kpts(fname):
277 | """
278 | Your Comments Here
279 | """
280 | f = open(fname)
281 | contents = f.readlines()
282 | f.close()
283 | spkptl = []
284 | spkptc = []
285 | for content in contents:
286 | if 'set xtics' in content:
287 | lines = str.split(content,sep='"')
288 | for n, words in enumerate(lines):
289 | if n!=0 and n%2!=0:
290 | spkptl.append(words)
291 | elif n!=0:
292 | spkptc.append(eval(words[:9]))
293 |
294 | return spkptl,spkptc
295 |
296 |
--------------------------------------------------------------------------------
/pyGWBSE/wflows.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 |
3 |
4 | """
5 | Defines standardized Fireworks that can be chained easily to perform various
6 | sequences of VASP calculations.
7 | """
8 | import numpy as np
9 | from atomate.common.firetasks.glue_tasks import PassCalcLocs
10 | from atomate.vasp.firetasks.write_inputs import WriteVaspFromIOSet
11 | from fireworks import Firework, Tracker
12 |
13 |
14 | from pyGWBSE.inputset import CreateInputs
15 | from pyGWBSE.out2db import gw2db, bse2db, emc2db, eps2db, Wannier2DB, rpa2db
16 | from pyGWBSE.run_calc import Run_Vasp, Run_Sumo, Run_Wannier
17 | from pyGWBSE.tasks import CopyOutputFiles, CheckBeConv, StopIfConverged, PasscalClocsCond, WriteBSEInput, \
18 | WriteGWInput, MakeWFilesList, SaveNbandsov, SaveConvParams
19 | from pyGWBSE.wannier_tasks import WriteWannierInputForDFT, WriteWannierInputForGW, CopyKptsWan2vasp
20 |
21 |
22 | class ScfFW(Firework):
23 | def __init__(self, mat_name=None, structure=None, nbands=None, kpar=None, reciprocal_density=None,
24 | vasp_input_set=None, vasp_input_params=None,
25 | vasp_cmd="vasp", prev_calc_loc=True, prev_calc_dir=None, db_file=None, wannier_fw=None,
26 | vasptodb_kwargs={}, **kwargs):
27 | """
28 | Your Comments Here
29 | """
30 | t = []
31 | vasp_input_set = CreateInputs(structure, kpar=kpar, reciprocal_density=reciprocal_density, nbands=nbands,
32 | wannier_fw=wannier_fw)
33 | name = 'SCF'
34 | fw_name = "{}-{}".format(mat_name, name)
35 | t.append(WriteVaspFromIOSet(structure=structure,
36 | vasp_input_set=vasp_input_set,
37 | vasp_input_params=vasp_input_params))
38 | t.append(Run_Vasp(vasp_cmd=vasp_cmd))
39 | t.append(eps2db(structure=structure, mat_name=mat_name, db_file=db_file, defuse_unsuccessful=False))
40 | t.append(rpa2db(structure=structure, mat_name=mat_name, task_label=name, db_file=db_file, defuse_unsuccessful=False))
41 | t.append(PassCalcLocs(name=name))
42 | super(ScfFW, self).__init__(t, name=fw_name, **kwargs)
43 |
44 |
45 | class convFW(Firework):
46 |
47 | def __init__(self, mat_name=None, structure=None, tolerence=None, no_conv=None, nbands=None,
48 | nbgwfactor=None, encutgw=None, nomegagw=None, convsteps=None, conviter=None,
49 | kpar=None, nbandsgw=None, reciprocal_density=None, vasp_input_set=None, vasp_input_params=None,
50 | vasp_cmd="vasp", prev_calc_loc=True, prev_calc_dir=None, db_file=None, vasptodb_kwargs={}, parents=None, **kwargs):
51 | t = []
52 | name = "CONV"
53 | fw_name = "{}-{}".format(mat_name, name)
54 | niter = 0
55 | nocc=nbands
56 | convsteps=np.array(convsteps)*0.01
57 | for niter in range(conviter):
58 | niter = niter + 1
59 | files2copy = ['WAVECAR']
60 | task_label = 'Convergence_Iteration: ' + str(niter)
61 |
62 | hviter=np.heaviside((niter-1),0)
63 |
64 | nbgwfactor = nbgwfactor + nbgwfactor*hviter*convsteps[0]
65 | encutgw = encutgw + encutgw*hviter*convsteps[1]
66 | nomegagw = nomegagw + nomegagw*hviter*convsteps[2]
67 |
68 | nbands=round(nocc*nbgwfactor)
69 | encutgw=round(encutgw)
70 | nomegagw=round(nomegagw)
71 |
72 | if no_conv==False:
73 | if hviter==0:
74 | print('Convergence test will be performed using following values')
75 | print('Iteration, NBANDS, ENCUTGW, NOMEGA')
76 | print('%10i' %niter, '%7i' %nbands, '%8i' %encutgw, '%6i' %nomegagw)
77 | else:
78 | if hviter==0:
79 | print('values of follwing parameters will be used')
80 | print('NBANDS, ENCUTGW, NOMEGA')
81 | print('%7i' %nbands, '%8i' %encutgw, '%6i' %nomegagw)
82 |
83 | if prev_calc_dir:
84 | t.append(CopyOutputFiles(additional_files=files2copy, calc_dir=prev_calc_dir, contcar_to_poscar=True))
85 | elif parents:
86 | if prev_calc_loc:
87 | t.append(
88 | CopyOutputFiles(additional_files=files2copy, calc_loc=prev_calc_loc, contcar_to_poscar=True))
89 | vasp_input_set = CreateInputs(structure, mode='DIAG', nbands=nbands, kpar=kpar,
90 | reciprocal_density=reciprocal_density)
91 | t.append(WriteVaspFromIOSet(structure=structure,
92 | vasp_input_set=vasp_input_set,
93 | vasp_input_params=vasp_input_params))
94 | t.append(Run_Vasp(vasp_cmd=vasp_cmd))
95 | vasp_input_set = CreateInputs(structure,mode='CONV',nbands=nbands,encutgw=encutgw,nomegagw=nomegagw,kpar=kpar,reciprocal_density=reciprocal_density,nbandsgw=nbandsgw)
96 | t.append(WriteVaspFromIOSet(structure=structure,
97 | vasp_input_set=vasp_input_set,
98 | vasp_input_params=vasp_input_params))
99 | if no_conv==False:
100 | t.append(Run_Vasp(vasp_cmd=vasp_cmd))
101 | t.append(SaveConvParams(nbands=nbands, encutgw=encutgw, nomegagw=nomegagw))
102 | t.append(CheckBeConv(niter=niter, tolerence=tolerence, no_conv=no_conv))
103 | t.append(PasscalClocsCond(name=name))
104 | if no_conv==False:
105 | t.append(gw2db(structure=structure, mat_name=mat_name, task_label=task_label, db_file=db_file, defuse_unsuccessful=False))
106 | t.append(StopIfConverged())
107 | tracker = Tracker('vasp.log', nlines=100)
108 | super(convFW, self).__init__(t, parents=parents, name=fw_name, spec={"_trackers": [tracker]}, **kwargs)
109 |
110 |
111 | class GwFW(Firework):
112 | def __init__(self, mat_name=None, structure=None, tolerence=None, no_conv=None, reciprocal_density=None,
113 | vasp_input_set=None, vasp_input_params=None, nbandso=None, nbandsv=None, nbandsgw=None,
114 | vasp_cmd="vasp", prev_calc_loc=True, prev_calc_dir=None, db_file=None, wannier_fw=None,
115 | vasptodb_kwargs={}, job_tag=None, parents=None, **kwargs):
116 | """
117 | Your Comments Here
118 | """
119 | t = []
120 | name = "GW"
121 | fw_name = "{}-{}".format(mat_name, name)
122 | files2copy = ['WAVECAR', 'WAVEDER']
123 | if prev_calc_dir:
124 | t.append(CopyOutputFiles(additional_files=files2copy, calc_dir=prev_calc_dir, contcar_to_poscar=True))
125 | elif parents:
126 | if prev_calc_loc:
127 | t.append(CopyOutputFiles(additional_files=files2copy, calc_loc=prev_calc_loc, contcar_to_poscar=True))
128 | t.append(WriteGWInput(structure=structure, reciprocal_density=reciprocal_density, nbandsgw=nbandsgw,
129 | wannier_fw=wannier_fw))
130 | for niter in range(1, 10):
131 | task_label = 'scGW_Iteration: ' + str(niter)
132 | if wannier_fw:
133 | t.append(WriteWannierInputForGW(structure=structure, reciprocal_density=reciprocal_density,nbandsgw=nbandsgw))
134 | t.append(Run_Vasp(vasp_cmd=vasp_cmd))
135 | t.append(CheckBeConv(niter=niter, tolerence=tolerence, no_conv=no_conv))
136 | t.append(PasscalClocsCond(name=name))
137 | t.append(MakeWFilesList())
138 | t.append(
139 | gw2db(structure=structure, mat_name=mat_name, task_label=task_label, job_tag=job_tag, db_file=db_file,
140 | defuse_unsuccessful=False))
141 | t.append(StopIfConverged())
142 | tracker = Tracker('vasp.log', nlines=100)
143 |
144 | super(GwFW, self).__init__(t, parents=parents, name=fw_name, spec={"_trackers": [tracker]}, **kwargs)
145 |
146 |
147 | class BseFW(Firework):
148 | def __init__(self, mat_name=None, structure=None, reciprocal_density=None, vasp_input_set=None,
149 | vasp_input_params=None, enwinbse=None,
150 | vasp_cmd="vasp", prev_calc_loc=True, prev_calc_dir=None, db_file=None, vasptodb_kwargs={},
151 | job_tag=None, parents=None, **kwargs):
152 | """
153 | Your Comments Here
154 | """
155 | t = []
156 | name = "BSE"
157 | fw_name = "{}-{}".format(mat_name, name)
158 | files2copy = ['WAVECAR', 'WAVEDER']
159 | if prev_calc_dir:
160 | t.append(CopyOutputFiles(additional_files=files2copy, calc_dir=prev_calc_dir, contcar_to_poscar=True))
161 | elif parents:
162 | if prev_calc_loc:
163 | t.append(CopyOutputFiles(additional_files=files2copy, calc_loc=prev_calc_loc, contcar_to_poscar=True))
164 | t.append(SaveNbandsov(enwinbse=enwinbse))
165 | t.append(WriteBSEInput(structure=structure, reciprocal_density=reciprocal_density))
166 | t.append(Run_Vasp(vasp_cmd=vasp_cmd))
167 | t.append(bse2db(structure=structure, mat_name=mat_name, task_label=name, job_tag=job_tag, db_file=db_file,
168 | defuse_unsuccessful=False))
169 | tracker = Tracker('vasp.log', nlines=100)
170 |
171 | super(BseFW, self).__init__(t, parents=parents, name=fw_name, state='PAUSED', spec={"_trackers": [tracker]},
172 | **kwargs)
173 |
174 |
175 | class EmcFW(Firework):
176 | def __init__(self, mat_name=None, structure=None, nbands=None, kpar=None, reciprocal_density=None, steps=None,
177 | vasp_input_set=None, vasp_input_params=None,
178 | vasp_cmd="vasp", sumo_cmd='sumo', prev_calc_loc=True, prev_calc_dir=None, db_file=None,
179 | vasptodb_kwargs={}, parents=None, **kwargs):
180 | """
181 | Your Comments Here
182 | """
183 | t = []
184 |
185 | vasp_input_set = CreateInputs(structure, mode='EMC', kpar=kpar, reciprocal_density=reciprocal_density,
186 | nbands=nbands)
187 | name = 'EMC'
188 | fw_name = "{}-{}".format(mat_name, name)
189 | if prev_calc_dir:
190 | t.append(CopyOutputFiles(calc_dir=prev_calc_dir, additional_files=["CHGCAR"]))
191 | elif parents:
192 | t.append(CopyOutputFiles(calc_loc=True, additional_files=["CHGCAR"]))
193 | else:
194 | raise ValueError("Must specify previous calculation for NonScfFW")
195 | t.append(WriteVaspFromIOSet(structure=structure,
196 | vasp_input_set=vasp_input_set,
197 | vasp_input_params=vasp_input_params))
198 | t.append(Run_Vasp(vasp_cmd=vasp_cmd))
199 | t.append(Run_Sumo(sumo_cmd=sumo_cmd))
200 | t.append(emc2db(structure=structure, mat_name=mat_name, db_file=db_file, defuse_unsuccessful=False))
201 | super(EmcFW, self).__init__(t, parents=parents, name=fw_name, **kwargs)
202 |
203 |
204 | class WannierCheckFW(Firework):
205 | def __init__(self, ppn=None, kpar=None, mat_name=None, structure=None, reciprocal_density=None, vasp_input_set=None,
206 | vasp_input_params=None,
207 | vasp_cmd="vasp", wannier_cmd=None, prev_calc_loc=True, prev_calc_dir=None, db_file=None,
208 | vasptodb_kwargs={}, parents=None, **kwargs):
209 | """
210 | Your Comments Here
211 | """
212 | t = []
213 | name = "WANNIER_CHECK"
214 | fw_name = "{}-{}".format(mat_name, name)
215 | t.append(CopyOutputFiles(calc_loc=prev_calc_loc, contcar_to_poscar=True))
216 | t.append(WriteWannierInputForDFT(structure=structure, reciprocal_density=reciprocal_density, ppn=ppn, write_hr=False))
217 | t.append(Run_Vasp(vasp_cmd=vasp_cmd))
218 | t.append(WriteWannierInputForDFT(structure=structure, reciprocal_density=reciprocal_density, ppn=ppn, write_hr=True))
219 | t.append(Run_Wannier(wannier_cmd=wannier_cmd))
220 | vasp_input_set = CreateInputs(structure, mode='EMC', kpar=kpar, reciprocal_density=reciprocal_density)
221 | t.append(WriteVaspFromIOSet(structure=structure,
222 | vasp_input_set=vasp_input_set,
223 | vasp_input_params=vasp_input_params))
224 | t.append(CopyKptsWan2vasp())
225 | t.append(Run_Vasp(vasp_cmd=vasp_cmd))
226 | t.append(Wannier2DB(structure=structure, mat_name=mat_name, task_label='CHECK_WANNIER_INTERPOLATION',
227 | db_file=db_file, compare_vasp=True, defuse_unsuccessful=False))
228 | tracker = Tracker('vasp.log', nlines=100)
229 |
230 | super(WannierCheckFW, self).__init__(t, parents=parents, name=fw_name, spec={"_trackers": [tracker]}, **kwargs)
231 |
232 |
233 | class WannierFW(Firework):
234 | def __init__(self, structure=None, mat_name=None, wannier_cmd=None, prev_calc_loc=True, prev_calc_dir=None,
235 | db_file=None, parents=None, **kwargs):
236 | """
237 | Your Comments Here
238 | """
239 | t = []
240 | name = "WANNIER"
241 | fw_name = "{}-{}".format(mat_name, name)
242 | files2copy = ['wannier90.win', 'wannier90.mmn', 'wannier90.amn', 'wannier90.eig']
243 | t.append(CopyOutputFiles(additional_files=files2copy, calc_loc=prev_calc_loc, contcar_to_poscar=True))
244 | t.append(Run_Wannier(wannier_cmd=wannier_cmd))
245 | t.append(Wannier2DB(structure=structure, mat_name=mat_name, task_label='GW_BANDSTRUCTURE', db_file=db_file,
246 | compare_vasp=False, defuse_unsuccessful=False))
247 | tracker = Tracker('wannier90.wout', nlines=100)
248 |
249 | super(WannierFW, self).__init__(t, parents=parents, name=fw_name, spec={"_trackers": [tracker]}, **kwargs)
250 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | atomate==1.0.3
2 | FireWorks==2.0.3
3 | pymatgen==2022.9.21
4 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup
2 |
3 |
4 | setup(
5 | name='pyGWBSE',
6 | version='1.0',
7 | description='python workflow for GW-BSE calculation',
8 | author='Tathagata Biswas',
9 | author_email='tbiswas3@asu.edu',
10 | packages=['pyGWBSE'],
11 | install_requires=['FireWorks>=2.0.3', 'pymatgen>=2022.9.21',
12 | 'atomate>=1.0.3'],
13 | package_data={"pyGWBSE": ["inputset.yaml"]}
14 |
15 | )
16 |
--------------------------------------------------------------------------------
/sphinx/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = .
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/sphinx/README:
--------------------------------------------------------------------------------
1 | TO INSTALL run the "compile" script
2 | "input.yaml is a sample input file"
3 | Run make_wf.py to crate a workflow based on "input.yaml"
4 |
5 |
6 | You will need wannier90, sumo-bandstats, pymatgen, fireworks and atomate to run the code.
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/sphinx/README.md:
--------------------------------------------------------------------------------
1 | # pyGWBSE
2 | python workflow for GW-BSE calculation
3 |
--------------------------------------------------------------------------------
/sphinx/_static/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cmdlab/pyGWBSE/110d0b47f96d7676ae224fc75a76e7e37c8922bd/sphinx/_static/github.png
--------------------------------------------------------------------------------
/sphinx/_static/orcid.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cmdlab/pyGWBSE/110d0b47f96d7676ae224fc75a76e7e37c8922bd/sphinx/_static/orcid.jpg
--------------------------------------------------------------------------------
/sphinx/clean:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | rm -rf build/ dist/ pyGWBSE.egg-info/ __pycache__/
3 | rm -rf pyGWBSE/__init__.py pyGWBSE/__pycache__/
4 |
--------------------------------------------------------------------------------
/sphinx/compile:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | python setup.py install
3 |
--------------------------------------------------------------------------------
/sphinx/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 | #
3 | # This file only contains a selection of the most common options. For a full
4 | # list see the documentation:
5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html
6 |
7 | # -- Path setup --------------------------------------------------------------
8 |
9 | # If extensions (or modules to document with autodoc) are in another directory,
10 | # add these directories to sys.path here. If the directory is relative to the
11 | # documentation root, use os.path.abspath to make it absolute, like shown here.
12 | #
13 | import os
14 | import sys
15 | sys.path.insert(0, os.path.abspath('.'))
16 | sys.path.insert(0, os.path.abspath('../'))
17 | sys.path.insert(0, os.path.abspath('../gwbse_wf'))
18 |
19 | # -- Project information -----------------------------------------------------
20 |
21 | project = 'WFGWBSE'
22 | copyright = '2021, Tathagata Biswas'
23 | author = 'Tathagata Biswas'
24 |
25 | # The full version, including alpha/beta/rc tags
26 | release = '0.1'
27 |
28 |
29 | # -- General configuration ---------------------------------------------------
30 |
31 | # Add any Sphinx extension module names here, as strings. They can be
32 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
33 | # ones.
34 | extensions = [
35 | 'sphinx.ext.autodoc',
36 | 'sphinx.ext.napoleon'
37 | ]
38 |
39 | # Add any paths that contain templates here, relative to this directory.
40 | templates_path = ['_templates']
41 |
42 | # List of patterns, relative to source directory, that match files and
43 | # directories to ignore when looking for source files.
44 | # This pattern also affects html_static_path and html_extra_path.
45 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
46 |
47 |
48 | # -- Options for HTML output -------------------------------------------------
49 |
50 | # The theme to use for HTML and HTML Help pages. See the documentation for
51 | # a list of builtin themes.
52 |
53 | html_theme = 'sphinx_rtd_theme'
54 | autodoc_member_order = 'bysource'
55 | autodoc_mock_imports = ["fireworks", "atomate", "pymatgen", "monty", "pydash", "pymongo"]
56 | autoclass_content = 'both'
57 | autodoc_default_flags = ['members', 'undoc-members', 'private-members', 'special-members', 'inherited-members', 'show-inheritance']
58 |
59 |
60 | # Add any paths that contain custom static files (such as style sheets) here,
61 | # relative to this directory. They are copied after the builtin static files,
62 | # so a file named "default.css" will overwrite the builtin "default.css".
63 | html_static_path = ['_static']
--------------------------------------------------------------------------------
/sphinx/example/AlN_abs.txt:
--------------------------------------------------------------------------------
1 | 6.15789 0.430108 0 0 0 0
2 | 6.17895 0.55914 0 0 0 0
3 | 6.15789 0.924731 0 0 0 0
4 | 6.17895 1.5914 0 0 0 0
5 | 6.22105 2.04301 0 0 0 0
6 | 6.28421 2.43011 0 0 0 0
7 | 6.32632 2.47312 0 0 0 0
8 | 6.51579 2.34409 0 0 0 0
9 | 6.57895 2.36559 0 0 0 0
10 | 6.74737 2.45161 0 0 0 0
11 | 6.97895 2.66667 0 0 0 0
12 | 7.06316 2.94624 0 0 0 0
13 | 7.14737 3.24731 0 0 0 0
14 | 7.23158 3.5914 0 0 0 0
15 | 7.29474 3.87097 0 0 0 0
16 | 7.33684 4.25806 0 0 0 0
17 | 7.42105 4.7957 0 0 0 0
18 | 7.50526 5.50538 0 0 0 0
19 | 7.54737 6.15054 0 0 0 0
20 | 7.58947 6.7957 0 0 0 0
21 | 7.63158 7.33333 0 0 0 0
22 | 7.65263 7.65591 0 0 0 0
23 | 7.69474 8 0 0 0 0
24 | 7.73684 8.8172 0 0 0 0
25 | 7.75789 9.22581 0 0 0 0
26 | 7.8 9.5914 0 0 0 0
27 | 7.84211 9.97849 0 0 0 0
28 | 7.98947 9.5914 0 0 0 0
29 | 8.07368 9.26882 0 0 0 0
30 | 8.26316 8.88172 0 0 0 0
31 | 8.49474 8.53763 0 0 0 0
32 | 8.6 8.47312 0 0 0 0
33 | 8.74737 8.58065 0 0 0 0
34 | 8.87368 8.62366 0 0 0 0
35 | 9.04211 8.53763 0 0 0 0
36 | 9.14737 8.15054 0 0 0 0
37 | 9.23158 7.87097 0 0 0 0
38 | 9.31579 7.65591 0 0 0 0
39 | 9.42105 7.22581 0 0 0 0
40 | 9.48421 6.90323 0 0 0 0
41 | 9.58947 6.36559 0 0 0 0
42 | 9.67368 5.87097 0 0 0 0
43 | 9.73684 5.52688 0 0 0 0
44 |
--------------------------------------------------------------------------------
/sphinx/example/create_workflow.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "These examples show how to create GW-BSE workflow using $py$GWBSE\n",
8 | "package. We will show how to compute QP bandstructure for wurtzite-AlN\n",
9 | "at the partial self-consistent (GW$_0$) level by obtaining input \n",
10 | "structure from Material Project (MP) database. We will also compute the \n",
11 | "absorption spectra of wurtzite-AlN by solving Bethe-Salpeter equation (BSE)."
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": 1,
17 | "metadata": {},
18 | "outputs": [],
19 | "source": [
20 | "#First let's load the required libraries such as pymatgen and Fireworks\n",
21 | "import sys\n",
22 | "from pyGWBSE.make_wflow import read_input, create_wfs\n",
23 | "from fireworks import LaunchPad\n",
24 | "from pymatgen.ext.matproj import MPRester\n",
25 | "from pymatgen import Structure"
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": 9,
31 | "metadata": {
32 | "scrolled": false
33 | },
34 | "outputs": [
35 | {
36 | "name": "stdout",
37 | "output_type": "stream",
38 | "text": [
39 | "PARAMS:\r\n",
40 | " kpar: 8 \r\n",
41 | " # 'KPAR' tag to be used in VASP simulations\r\n",
42 | " \r\n",
43 | " ppn: 13 \r\n",
44 | " # NPROCS/KPAR ; NPROCS: number of total processors to be used in VASP simulations \r\n",
45 | " \r\n",
46 | " reciprocal_density: 200 \r\n",
47 | " # reciprocal density that determines the k-grid using 'automatic_density_by_vol' method of pymatgen\r\n",
48 | " \r\n",
49 | " encutgw: 100 \r\n",
50 | " # ENCUTGW to be used in VASP simulations\r\n",
51 | " \r\n",
52 | " nbgwfactor: 3 \r\n",
53 | " # NBANDS=nbgwfactor x nocc'; nocc' is the smallest multiple of ppn which is larger than number of occupied bands\r\n",
54 | " \r\n",
55 | " nomegagw: 80 \r\n",
56 | " # NOMEGAGW to be used in VASP simulations\r\n",
57 | " \r\n",
58 | " convparam: NBANDS \r\n",
59 | " # NBANDS/ENCUTGW/NOMEGA parameter to run convergence test for \r\n",
60 | " \r\n",
61 | " convsteps: 2 \r\n",
62 | " # steps to be used for convergence test\r\n",
63 | " \r\n",
64 | " conviter: 5 \r\n",
65 | " # maximum number of iteration in convergence test \r\n",
66 | " \r\n",
67 | " enwinbse: 3.0 \r\n",
68 | " # energy window in BSE calculations\r\n",
69 | "\r\n",
70 | "\r\n",
71 | "\r\n",
72 | "STRUCTURE:\r\n",
73 | " \r\n",
74 | " source: MID \r\n",
75 | " # MID/POSCAR MID:get structure from MP database, POSCAR: structure from a file \r\n",
76 | " \r\n",
77 | " mat_name: NEW_MAT \r\n",
78 | " # unique identifier in the database when source=POSCAR\r\n",
79 | " \r\n",
80 | " material_id: mp-661 \r\n",
81 | " # material_id of the input structure in MP database\r\n",
82 | " \r\n",
83 | " \r\n",
84 | " \r\n",
85 | "WFLOW_DESIGN:\r\n",
86 | " \r\n",
87 | " skip_emc: false \r\n",
88 | " # set true to skip effective mass calculation \r\n",
89 | " \r\n",
90 | " skip_wannier: false \r\n",
91 | " # set true to skip wannier bandstructure interpolation\r\n",
92 | " \r\n",
93 | " skip_conv: false \r\n",
94 | " # set true to skip convergence test\r\n",
95 | " \r\n",
96 | " skip_gw: false \r\n",
97 | " # set true to skip GW calculation\r\n",
98 | " \r\n",
99 | " scgw: true \r\n",
100 | " # set true to perform self-consistent GW instead of G0W0\r\n",
101 | " \r\n",
102 | " skip_bse: false \r\n",
103 | " # set true to skip BSE calculation\r\n"
104 | ]
105 | }
106 | ],
107 | "source": [
108 | "#Now let's check the content of the 'input.yaml' file.\n",
109 | "!cat 'input.yaml'"
110 | ]
111 | },
112 | {
113 | "cell_type": "code",
114 | "execution_count": 3,
115 | "metadata": {},
116 | "outputs": [],
117 | "source": [
118 | "\"\"\"\n",
119 | " 'read_input' function reads input parameters from input.yaml file.\n",
120 | " \n",
121 | " Returns:\n",
122 | " \n",
123 | " structure: pymatgen structure object for the input structure\n",
124 | " input_dict: a dictionary of all the input paramters\n",
125 | " \n",
126 | "\"\"\"\n",
127 | "\n",
128 | "structure, input_dict = read_input()"
129 | ]
130 | },
131 | {
132 | "cell_type": "code",
133 | "execution_count": 4,
134 | "metadata": {
135 | "scrolled": true
136 | },
137 | "outputs": [
138 | {
139 | "name": "stdout",
140 | "output_type": "stream",
141 | "text": [
142 | "-------------------------------------------\n",
143 | "material: mp-661\n",
144 | "Information for efficient parallelization\n",
145 | "You have 8 occupied bands\n",
146 | "You have 76 kpoints\n",
147 | "You have [[12, 12, 7]] k-grid\n",
148 | "Will perform convergence test for: NBANDS\n",
149 | "Values that will be used for convergence test: 39 65 91 117 143 \n",
150 | "KPAR= 8\n",
151 | "reciprocal_density= 200\n",
152 | "BSE calculation will include bands in the energy window (eV)= 3.0\n",
153 | "-------------------------------------------\n"
154 | ]
155 | },
156 | {
157 | "name": "stderr",
158 | "output_type": "stream",
159 | "text": [
160 | "/home/tatha/anaconda3/envs/cms/lib/python3.6/site-packages/pymatgen/io/vasp/sets.py:447: BadInputSetWarning:\n",
161 | "\n",
162 | "Overriding the POTCAR functional is generally not recommended as it significantly affect the results of calculations and compatibility with other calculations done with the same input set. Note that some POTCAR symbols specified in the configuration file may not be available in the selected functional.\n",
163 | "\n"
164 | ]
165 | }
166 | ],
167 | "source": [
168 | "\"\"\"\n",
169 | " 'create_wfs' function creates the GW-BSE workflow based on input specification.\n",
170 | " \n",
171 | " Args:\n",
172 | " \n",
173 | " structure: pymatgen structure object for the input structure\n",
174 | " input_dict: a dictionary of all the input paramters\n",
175 | " \n",
176 | " Returns:\n",
177 | " \n",
178 | " wf_gwbse: GW-BSE workflow as a Fireworks workflow object.\n",
179 | " \n",
180 | "\"\"\"\n",
181 | "\n",
182 | "wf_gwbse=create_wfs(structure, input_dict)"
183 | ]
184 | },
185 | {
186 | "cell_type": "markdown",
187 | "metadata": {},
188 | "source": [
189 | "The error message \"Overriding the POTCAR functional is generally not ...\" is due to changing default POTCAR symbols to GW POTCAR files. One can choose other POTCARs by modifying inputset.yaml file. "
190 | ]
191 | },
192 | {
193 | "cell_type": "code",
194 | "execution_count": 5,
195 | "metadata": {},
196 | "outputs": [],
197 | "source": [
198 | "#Load the Fireworks Launchpad \n",
199 | "lpad = LaunchPad.auto_load() "
200 | ]
201 | },
202 | {
203 | "cell_type": "code",
204 | "execution_count": 6,
205 | "metadata": {},
206 | "outputs": [
207 | {
208 | "name": "stdout",
209 | "output_type": "stream",
210 | "text": [
211 | "2022-09-14 14:27:54,737 INFO Added a workflow. id_map: {-7: 1, -6: 2, -5: 3, -4: 4, -3: 5, -2: 6, -1: 7}\n"
212 | ]
213 | },
214 | {
215 | "data": {
216 | "text/plain": [
217 | "{-7: 1, -6: 2, -5: 3, -4: 4, -3: 5, -2: 6, -1: 7}"
218 | ]
219 | },
220 | "execution_count": 6,
221 | "metadata": {},
222 | "output_type": "execute_result"
223 | }
224 | ],
225 | "source": [
226 | "#Add the workflow you just created\n",
227 | "lpad.add_wf(wf_gwbse)"
228 | ]
229 | },
230 | {
231 | "cell_type": "code",
232 | "execution_count": 7,
233 | "metadata": {
234 | "scrolled": false
235 | },
236 | "outputs": [
237 | {
238 | "name": "stdout",
239 | "output_type": "stream",
240 | "text": [
241 | "/home/tatha/anaconda3/envs/cms/lib/python3.6/site-packages/pymatgen/io/vasp/sets.py:447: BadInputSetWarning:\n",
242 | "\n",
243 | "Overriding the POTCAR functional is generally not recommended as it significantly affect the results of calculations and compatibility with other calculations done with the same input set. Note that some POTCAR symbols specified in the configuration file may not be available in the selected functional.\n",
244 | "\n",
245 | "[\n",
246 | " {\n",
247 | " \"fw_id\": 1,\n",
248 | " \"created_on\": \"2022-09-14T21:27:54.144377\",\n",
249 | " \"updated_on\": \"2022-09-14T21:27:54.144378\",\n",
250 | " \"state\": \"PAUSED\",\n",
251 | " \"name\": \"mp-661-BSE\"\n",
252 | " },\n",
253 | " {\n",
254 | " \"fw_id\": 2,\n",
255 | " \"created_on\": \"2022-09-14T21:27:54.144357\",\n",
256 | " \"updated_on\": \"2022-09-14T21:27:54.144358\",\n",
257 | " \"name\": \"mp-661-WANNIER\",\n",
258 | " \"state\": \"WAITING\"\n",
259 | " },\n",
260 | " {\n",
261 | " \"fw_id\": 3,\n",
262 | " \"created_on\": \"2022-09-14T21:27:54.144341\",\n",
263 | " \"updated_on\": \"2022-09-14T21:27:54.144341\",\n",
264 | " \"name\": \"mp-661-GW\",\n",
265 | " \"state\": \"WAITING\"\n",
266 | " },\n",
267 | " {\n",
268 | " \"fw_id\": 4,\n",
269 | " \"created_on\": \"2022-09-14T21:27:54.144271\",\n",
270 | " \"updated_on\": \"2022-09-14T21:27:54.144272\",\n",
271 | " \"name\": \"mp-661-CONV\",\n",
272 | " \"state\": \"WAITING\"\n",
273 | " },\n",
274 | " {\n",
275 | " \"fw_id\": 5,\n",
276 | " \"created_on\": \"2022-09-14T21:27:54.141887\",\n",
277 | " \"updated_on\": \"2022-09-14T21:27:54.141888\",\n",
278 | " \"name\": \"mp-661-WANNIER_CHECK\",\n",
279 | " \"state\": \"WAITING\"\n",
280 | " },\n",
281 | " {\n",
282 | " \"fw_id\": 6,\n",
283 | " \"created_on\": \"2022-09-14T21:27:54.141655\",\n",
284 | " \"updated_on\": \"2022-09-14T21:27:54.141656\",\n",
285 | " \"name\": \"mp-661-EMC\",\n",
286 | " \"state\": \"WAITING\"\n",
287 | " },\n",
288 | " {\n",
289 | " \"fw_id\": 7,\n",
290 | " \"created_on\": \"2022-09-14T21:27:54.141378\",\n",
291 | " \"updated_on\": \"2022-09-14T21:27:54.531247\",\n",
292 | " \"state\": \"READY\",\n",
293 | " \"name\": \"mp-661-SCF\"\n",
294 | " }\n",
295 | "]\n"
296 | ]
297 | }
298 | ],
299 | "source": [
300 | "#Check the Fireworks loaded to the Launchpad\n",
301 | "lp='lpad get_fws'\n",
302 | "!{lp}"
303 | ]
304 | },
305 | {
306 | "cell_type": "markdown",
307 | "metadata": {},
308 | "source": [
309 | "As you can see there are 7 fireworks with prefix `mp-661` were loaded to the Launchpad. \n",
310 | "Also one should note that the BSE Firework is in a `PAUSED` state by default. This is \n",
311 | "because, the k-point parallelization is not implemented for BSE calculation in VASP. \n",
312 | "Therefore, to make the number of bands in the WAVEDER file a multiple of number of \n",
313 | "processor used (requirement for VASP, otherwise it will change the NBANDS value) we \n",
314 | "need to run the BSE workflow on NPROCS=NPROCS$'$/KPAR, where NPROCS$'$ is the number \n",
315 | "of processors used for the `fw_id: 2-7`. Now that we have all the Fireworks in the \n",
316 | "Launchpad we can run them and use the postprocessing scripts to analyze the results once \n",
317 | "they are `COMPLETED`."
318 | ]
319 | }
320 | ],
321 | "metadata": {
322 | "kernelspec": {
323 | "display_name": "cms",
324 | "language": "python",
325 | "name": "cms"
326 | },
327 | "language_info": {
328 | "codemirror_mode": {
329 | "name": "ipython",
330 | "version": 3
331 | },
332 | "file_extension": ".py",
333 | "mimetype": "text/x-python",
334 | "name": "python",
335 | "nbconvert_exporter": "python",
336 | "pygments_lexer": "ipython3",
337 | "version": "3.6.13"
338 | }
339 | },
340 | "nbformat": 4,
341 | "nbformat_minor": 4
342 | }
343 |
--------------------------------------------------------------------------------
/sphinx/example/input.yaml:
--------------------------------------------------------------------------------
1 | PARAMS:
2 | kpar: 8
3 | # 'KPAR' tag to be used in VASP simulations
4 |
5 | ppn: 13
6 | # NPROCS/KPAR ; NPROCS: number of total processors to be used in VASP simulations
7 |
8 | reciprocal_density: 200
9 | # reciprocal density that determines the k-grid using 'automatic_density_by_vol' method of pymatgen
10 |
11 | encutgw: 100
12 | # ENCUTGW to be used in VASP simulations
13 |
14 | nbgwfactor: 5
15 | # NBANDS=nbgwfactor x nocc'; nocc' is the smallest multiple of ppn which is larger than number of occupied bands
16 |
17 | nomegagw: 80
18 | # NOMEGAGW to be used in VASP simulations
19 |
20 | convparam: NBANDS
21 | # NBANDS/ENCUTGW/NOMEGA parameter to run convergence test for
22 |
23 | convsteps: 2
24 | # steps to be used for convergence test
25 |
26 | conviter: 5
27 | # maximum number of iteration in convergence test
28 |
29 | enwinbse: 3.0
30 | # energy window in BSE calculations
31 |
32 |
33 |
34 | STRUCTURE:
35 |
36 | source: MID
37 | # MID/POSCAR MID:get structure from MP database, POSCAR: structure from a file
38 |
39 | mat_name: NEW_MAT
40 | # unique identifier in the database when source=POSCAR
41 |
42 | material_id: mp-661
43 | # material_id of the input structure in MP database
44 |
45 |
46 |
47 | WFLOW_DESIGN:
48 |
49 | skip_emc: false
50 | # set true to skip effective mass calculation
51 |
52 | skip_wannier: false
53 | # set true to skip wannier bandstructure interpolation
54 |
55 | skip_conv: false
56 | # set true to skip convergence test
57 |
58 | skip_gw: false
59 | # set true to skip GW calculation
60 |
61 | scgw: true
62 | # set true to perform self-consistent GW instead of G0W0
63 |
64 | skip_bse: false
65 | # set true to skip BSE calculation
66 |
--------------------------------------------------------------------------------
/sphinx/index.rst:
--------------------------------------------------------------------------------
1 | .. WFGWBSE documentation master file, created by
2 | sphinx-quickstart on Fri Aug 6 11:21:48 2021.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to WFGWBSE's documentation!
7 | ===================================
8 |
9 | .. toctree::
10 | :maxdepth: 2
11 | :caption: Contents:
12 |
13 | rst/modules
14 |
15 |
16 | Indices and tables
17 | ==================
18 |
19 | * :ref:`genindex`
20 | * :ref:`modindex`
21 | * :ref:`search`
22 |
--------------------------------------------------------------------------------
/sphinx/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=.
11 | set BUILDDIR=_build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/sphinx/pyGWBSE/config.py:
--------------------------------------------------------------------------------
1 | __author__ = 'Tathagata Biswas '
2 |
3 | # TODO: @computron should be able to load from YAML -computron
4 |
5 | VASP_CMD = ">>vasp_cmd<<"
6 | SUMO_CMD = ">>sumo_cmd<<"
7 | WANNIER_CMD = ">>wannier_cmd<<"
8 | DB_FILE = ">>db_file<<"
9 |
10 |
--------------------------------------------------------------------------------
/sphinx/pyGWBSE/inputset.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 | # Copyright (c) Pymatgen Development Team.
3 | # Distributed under the terms of the MIT License.
4 |
5 | import os
6 |
7 | from monty.serialization import loadfn
8 | from pymatgen.io.vasp.inputs import Incar, Kpoints
9 | from pymatgen.io.vasp.sets import DictSet
10 | from pymatgen.symmetry.bandstructure import HighSymmKpath
11 |
12 | MODULE_DIR = os.path.dirname(os.path.abspath(__file__))
13 |
14 | class CreateInputs(DictSet):
15 | """
16 | Your Comments Here
17 | """
18 | CONFIG = loadfn(os.path.join(MODULE_DIR, "inputset.yaml"))
19 |
20 | SUPPORTED_MODES = ("DIAG", "GW", "STATIC", "BSE", "CONV", "EMC")
21 |
22 | def __init__(self, structure, prev_incar=None, nbands=None, nomegagw=None, encutgw=None,
23 | potcar_functional="PBE_54", reciprocal_density=100, kpoints_line_density = 100, kpar=None, nbandsgw=None,
24 | mode="STATIC", copy_wavecar=True, nbands_factor=5, ncores=16,nbandso=None, nbandsv=None, wannier_fw=None,
25 | **kwargs):
26 | super().__init__(structure, CreateInputs.CONFIG, **kwargs)
27 | self.prev_incar = prev_incar
28 | self.nbands = nbands
29 | self.encutgw = encutgw
30 | self.nomegagw = nomegagw
31 | self.potcar_functional = potcar_functional
32 | self.reciprocal_density = reciprocal_density
33 | self.kpoints_line_density = kpoints_line_density
34 | self.mode = mode.upper()
35 | if self.mode not in CreateInputs.SUPPORTED_MODES:
36 | raise ValueError("%s not one of the support modes : %s" %
37 | (self.mode, CreateInputs.SUPPORTED_MODES))
38 | self.kwargs = kwargs
39 | self.copy_wavecar = copy_wavecar
40 | self.nbands_factor = nbands_factor
41 | self.ncores = ncores
42 | self.kpar = kpar
43 | self.nbandsgw = nbandsgw
44 | self.nbandso = nbandso
45 | self.nbandsv = nbandsv
46 | self.wannier_fw = wannier_fw
47 |
48 | @property
49 | def kpoints(self):
50 | """
51 | Generate gamma center k-points mesh grid for GW calc,
52 | which is requested by GW calculation.
53 | """
54 | if self.mode == "EMC":
55 | kpath = HighSymmKpath(self.structure)
56 | frac_k_points, k_points_labels = kpath.get_kpoints(
57 | line_density=self.kpoints_line_density,
58 | coords_are_cartesian=False)
59 | kpoints = Kpoints(
60 | comment="Non SCF run along symmetry lines",
61 | style=Kpoints.supported_modes.Reciprocal,
62 | num_kpts=len(frac_k_points),
63 | kpts=frac_k_points, labels=k_points_labels,
64 | kpts_weights=[1] * len(frac_k_points))
65 |
66 | return kpoints
67 |
68 | else:
69 |
70 | kpoints=Kpoints.automatic_density_by_vol(self.structure,
71 | self.reciprocal_density, force_gamma=True)
72 |
73 | return kpoints
74 |
75 | @property
76 | def incar(self):
77 | """
78 | Your Comments Here
79 | """
80 | parent_incar = super().incar
81 | incar = Incar(self.prev_incar) if self.prev_incar is not None else \
82 | Incar(parent_incar)
83 | if self.wannier_fw == True:
84 | incar.update({
85 | "LWANNIER90": True
86 | })
87 | if self.mode == "EMC":
88 | incar.update({
89 | "IBRION": -1,
90 | "ISMEAR": 0,
91 | "SIGMA": 0.001,
92 | "LCHARG": False,
93 | "LORBIT": 11,
94 | "LWAVE": False,
95 | "NSW": 0,
96 | "ISYM": 0,
97 | "ICHARG": 11
98 | })
99 | incar.pop("LWANNIER90", None)
100 | incar.pop("LEPSILON", None)
101 | if self.mode == "DIAG":
102 | # Default parameters for diagonalization calculation.
103 | incar.update({
104 | "ALGO": "Exact",
105 | "NELM": 1,
106 | "LOPTICS": True,
107 | "LPEAD": True
108 | })
109 | incar.pop("LEPSILON", None)
110 | incar.pop("LWANNIER90", None)
111 | elif self.mode == "GW":
112 | # Default parameters for GW calculation.
113 | incar.update({
114 | "ALGO": "GW",
115 | "NELM": 1,
116 | "NOMEGA": self.nomegagw,
117 | "ENCUTGW": self.encutgw,
118 | "NBANDSGW": self.nbandsgw,
119 | "LWAVE": True
120 | })
121 | if self.wannier_fw == True:
122 | incar.update({
123 | "LWANNIER90": True
124 | })
125 | incar.pop("EDIFF", None)
126 | incar.pop("LOPTICS", None)
127 | incar.pop("LPEAD", None)
128 | incar.pop("LEPSILON", None)
129 | elif self.mode == "CONV":
130 | # Default parameters for GW calculation.
131 | incar.update({
132 | "ALGO": "GW0",
133 | "NELM": 1,
134 | "NOMEGA": self.nomegagw,
135 | "ENCUTGW": self.encutgw,
136 | "NBANDSGW": self.nbandsgw,
137 | "LWAVE": False
138 | })
139 | incar.pop("EDIFF", None)
140 | incar.pop("LOPTICS", None)
141 | incar.pop("LEPSILON", None)
142 | incar.pop("LPEAD", None)
143 | incar.pop("LWANNIER90", None)
144 | elif self.mode == "BSE":
145 | # Default parameters for BSE calculation.
146 | incar.update({
147 | "ALGO": "BSE",
148 | "ANTIRES": 0,
149 | "NBANDSO": self.nbandso,
150 | "NBANDSV": self.nbandsv,
151 | "KPAR": 1,
152 | "CSHIFT": 0.2
153 | })
154 | incar.pop("LEPSILON", None)
155 | incar.pop("LWANNIER90", None)
156 | if self.nbands:
157 | incar["NBANDS"] = self.nbands
158 |
159 | if self.kpar:
160 | incar["KPAR"] = self.kpar
161 |
162 | rd=self.reciprocal_density
163 |
164 | incar["SYSTEM"] = 'reciprocal density: '+str(rd)
165 |
166 | # Respect user set INCAR.
167 | incar.update(self.kwargs.get("user_incar_settings", {}))
168 |
169 | return incar
170 |
171 |
--------------------------------------------------------------------------------
/sphinx/pyGWBSE/inputset.yaml:
--------------------------------------------------------------------------------
1 | # Default VASP settings for GW calculations used by the Materials Virtual Lab.
2 | INCAR:
3 | ALGO: Normal
4 | ENCUT: 500
5 | EDIFF: 1.0e-8
6 | ISMEAR: 0
7 | LREAL: AUTO
8 | ISPIN: 1
9 | LWAVE: true
10 | NELM: 100
11 | PREC: Accurate
12 | SIGMA: 0.01
13 | LEPSILON: true
14 | LVHAR: false
15 | LOPTICS: true
16 | LPEAD: false
17 | LORBIT: 11
18 | KPOINTS:
19 | reciprocal_density: 100
20 | POTCAR:
21 | Ac: Ac
22 | Ag: Ag_sv_GW
23 | Al: Al_GW
24 | Ar: Ar_GW
25 | As: As_GW
26 | At: At_d_GW
27 | Au: Au_sv_GW
28 | B: B_GW
29 | Ba: Ba_sv_GW
30 | Be: Be_sv_GW
31 | Bi: Bi_d_GW
32 | Br: Br_GW
33 | C: C_GW
34 | Ca: Ca_sv_GW
35 | Cd: Cd_sv_GW
36 | Ce: Ce_GW
37 | Cl: Cl_GW
38 | Co: Co_sv_GW
39 | Cr: Cr_sv_GW
40 | Cs: Cs_sv_GW
41 | Cu: Cu_sv_GW
42 | Dy: Dy_3
43 | Er: Er_3
44 | Eu: Eu
45 | F: F_GW
46 | Fe: Fe_sv_GW
47 | Ga: Ga_d_GW
48 | Gd: Gd
49 | Ge: Ge_d_GW
50 | H: H_GW
51 | He: He_GW
52 | Hf: Hf_sv_GW
53 | Hg: Hg_sv_GW
54 | Ho: Ho_3
55 | I: I_GW
56 | In: In_d_GW
57 | Ir: Ir_sv_GW
58 | K: K_sv_GW
59 | Kr: Kr_GW
60 | La: La_GW
61 | Li: Li_sv_GW
62 | Lu: Lu_3
63 | Mg: Mg_sv_GW
64 | Mn: Mn_sv_GW
65 | Mo: Mo_sv_GW
66 | N: N_GW
67 | Na: Na_sv_GW
68 | Nb: Nb_sv_GW
69 | Nd: Nd_3
70 | Ne: Ne_GW
71 | Ni: Ni_sv_GW
72 | Np: Np
73 | O: O_GW
74 | Os: Os_sv_GW
75 | P: P_GW
76 | Pa: Pa
77 | Pb: Pb_d_GW
78 | Pd: Pd_sv_GW
79 | Pm: Pm_3
80 | Po: Po_d_GW
81 | Pr: Pr_3
82 | Pt: Pt_sv_GW
83 | Pu: Pu
84 | Rb: Rb_sv_GW
85 | Re: Re_sv_GW
86 | Rh: Rh_sv_GW
87 | Rn: Rn_d_GW
88 | Ru: Ru_sv_GW
89 | S: S_GW
90 | Sb: Sb_d_GW
91 | Sc: Sc_sv_GW
92 | Se: Se_GW
93 | Si: Si_GW
94 | Sm: Sm_3
95 | Sn: Sn_d_GW
96 | Sr: Sr_sv_GW
97 | Ta: Ta_sv_GW
98 | Tb: Tb_3
99 | Tc: Tc_sv_GW
100 | Te: Te_GW
101 | Th: Th
102 | Ti: Ti_sv_GW
103 | Tl: Tl_d_GW
104 | Tm: Tm_3
105 | U: U
106 | V: V_sv_GW
107 | W: W_sv_GW
108 | Xe: Xe_GW
109 | Y: Y_sv_GW
110 | Yb: Yb_2
111 | Zn: Zn_sv_GW
112 | Zr: Zr_sv_GW
113 |
--------------------------------------------------------------------------------
/sphinx/pyGWBSE/make_wflow.py:
--------------------------------------------------------------------------------
1 | #This code is to create the workflow based on inputs from input.yaml file
2 |
3 | from fireworks import Firework, Workflow
4 | from pyGWBSE.wflows import ScfFW, convFW, BseFW, GwFW, EmcFW, WannierCheckFW, WannierFW
5 | from pyGWBSE.inputset import CreateInputs
6 | from pymatgen import Structure
7 | from fireworks import LaunchPad
8 | from pyGWBSE.config import VASP_CMD, DB_FILE, SUMO_CMD, WANNIER_CMD
9 | from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
10 | from pymatgen.io.vasp.inputs import Kpoints
11 | from pymatgen.ext.matproj import MPRester
12 | import numpy as np
13 | from pymongo import MongoClient
14 | import yaml
15 | import sys
16 |
17 |
18 | #Function to find the kgrid and number of symmtery reduced kpoints based on symmetry of the structure and the reciprocal density
19 | def num_ir_kpts(struct,reciprocal_density):
20 | spg=SpacegroupAnalyzer(struct, symprec=0.01, angle_tolerance=5)
21 | Kpts=Kpoints.automatic_density_by_vol(struct,reciprocal_density,force_gamma=True)
22 | kpts=spg.get_ir_reciprocal_mesh(mesh=Kpts.kpts, is_shift=(0, 0, 0))
23 | return Kpts.kpts,len(kpts)
24 |
25 |
26 | #Function to find the number of occupied bands from the input structure
27 | def num_occ_bands(struct):
28 | vasp_input_set = CreateInputs(struct)
29 | nel=vasp_input_set.nelect
30 | nocc=int(nel/2)
31 | return nocc
32 |
33 |
34 | #Function to read the input.yaml file
35 | def read_input():
36 | yaml_file = open("input.yaml")
37 | input_dict = yaml.load(yaml_file, Loader=yaml.FullLoader)
38 |
39 | struc_src=input_dict["STRUCTURE"]["source"]
40 | if struc_src=='POSCAR':
41 | struct=Structure.from_file('POSCAR')
42 | mat_name=input_dict["STRUCTURE"]["mat_name"]
43 | elif struc_src=='MID':
44 | material_id=input_dict["STRUCTURE"]["material_id"]
45 | mat_name=material_id
46 | with MPRester("b62Ts1xuKP9ahZmX") as m:
47 | struct = m.get_structure_by_material_id(material_id,conventional_unit_cell=False)
48 | else:
49 | sys.exit('Error: use MID/POSCAR as structure source .... Exiting NOW')
50 | input_dict["PARAMS"]["mat_name"]=mat_name
51 | return struct, input_dict
52 |
53 | #Function to create the workflow
54 | def create_wfs(struct, params_dict, vasp_cmd=None, sumo_cmd=None, wannier_cmd=None, db_file=None, c=None):
55 |
56 | c = c or {}
57 | vasp_cmd = c.get("VASP_CMD", VASP_CMD)
58 | sumo_cmd = c.get("SUMO_CMD", SUMO_CMD)
59 | wannier_cmd = c.get("WANNIER_CMD", WANNIER_CMD)
60 | db_file = c.get("DB_FILE", DB_FILE)
61 |
62 | params=params_dict["PARAMS"]
63 | mat_name=params["mat_name"]
64 | nocc=num_occ_bands(struct)
65 | kpar=params["kpar"]
66 | ppn=params["ppn"]
67 | rd=params["reciprocal_density"]
68 | nbgwfactor=params["nbgwfactor"]
69 | encutgw=params["encutgw"]
70 | nomegagw=params["nomegagw"]
71 | convparam=params["convparam"]
72 | convsteps=params["convsteps"]
73 | conviter=params["conviter"]
74 | enwinbse=params["enwinbse"]
75 | skip_emc=params_dict["WFLOW_DESIGN"]["skip_emc"]
76 | skip_wannier=params_dict["WFLOW_DESIGN"]["skip_wannier"]
77 | skip_conv=params_dict["WFLOW_DESIGN"]["skip_conv"]
78 | skip_gw=params_dict["WFLOW_DESIGN"]["skip_gw"]
79 | scgw=params_dict["WFLOW_DESIGN"]["scgw"]
80 | skip_bse=params_dict["WFLOW_DESIGN"]["skip_bse"]
81 |
82 | mesh,nkpt=num_ir_kpts(struct,rd)
83 | nbands=(int(nocc/ppn)+1)*ppn
84 | nbandsgw=nocc+10
85 |
86 | print("-------------------------------------------")
87 | print("material: ",mat_name)
88 | print("Information for efficient parallelization")
89 | print("You have ",nocc,"occupied bands")
90 | print("You have ",nkpt,"kpoints")
91 | print("You have ",mesh,"k-grid")
92 | if not(skip_conv):
93 | print("Will perform convergence test for: ",convparam)
94 | print("Values that will be used for convergence test: ",end='')
95 | if convparam=='NOMEGA':
96 | initparam=nomegagw
97 | if convparam=='NBANDS':
98 | initparam=nbgwfactor
99 | if convparam=='ENCUTGW':
100 | initparam=encutgw
101 | for citer in range(conviter):
102 | if convparam=='NBANDS':
103 | print(nbands*(initparam+citer*convsteps),end=' ')
104 | else:
105 | print(initparam+citer*convsteps,end=' ')
106 | print( )
107 | print("KPAR=",kpar)
108 | print("reciprocal_density=",rd)
109 | if not(skip_bse):
110 | print("BSE calculation will include bands in the energy window (eV)=", enwinbse)
111 | print("-------------------------------------------")
112 |
113 | if scgw==True:
114 | gw_tag='GW0'
115 | else:
116 | gw_tag='G0W0'
117 |
118 | ifw=0
119 |
120 | fws = [ScfFW(structure=struct, mat_name=mat_name, nbands=nbands, vasp_cmd=vasp_cmd,db_file=db_file,kpar=kpar,reciprocal_density=rd,wannier_fw=not(skip_wannier))]
121 |
122 | if skip_emc==False:
123 | ifw=ifw+1
124 | parents = fws[0]
125 | fw = EmcFW(structure=struct, mat_name=mat_name, vasp_cmd=vasp_cmd, sumo_cmd=sumo_cmd, db_file=db_file,kpar=kpar,reciprocal_density=rd, steps=0.001,parents=parents)
126 | fws.append(fw)
127 |
128 | if skip_wannier==False:
129 | ifw=ifw+1
130 | parents = fws[0]
131 | fw = WannierCheckFW(structure=struct, mat_name=mat_name, kpar=kpar, ppn=ppn,vasp_cmd=vasp_cmd,wannier_cmd=wannier_cmd,db_file=db_file,parents=parents,reciprocal_density=rd)
132 | fws.append(fw)
133 |
134 | ifw=ifw+1
135 | parents = fws[0]
136 | fw = convFW(structure=struct, mat_name=mat_name, nbands=nbands, nbgwfactor=nbgwfactor, encutgw=encutgw, nomegagw=nomegagw, convparam=convparam, convsteps=convsteps, conviter=conviter,
137 | tolerence=0.1, no_conv=skip_conv, vasp_cmd=vasp_cmd,db_file=db_file,parents=parents,kpar=kpar,nbandsgw=nbandsgw,reciprocal_density=rd)
138 | fws.append(fw)
139 |
140 | if skip_gw==False:
141 | ifw=ifw+1
142 | parents = fws[ifw-1]
143 | fw = GwFW(structure=struct, mat_name=mat_name, tolerence=0.1, no_conv=not(scgw),
144 | vasp_cmd=vasp_cmd,db_file=db_file,parents=parents,reciprocal_density=rd, nbandsgw=nbandsgw, wannier_fw=not(skip_wannier), job_tag=gw_tag)
145 | fws.append(fw)
146 |
147 | if skip_wannier==False and skip_gw==False:
148 | ifw=ifw+1
149 | parents = fws[ifw-1]
150 | fw = WannierFW(structure=struct,mat_name=mat_name, wannier_cmd=wannier_cmd,db_file=db_file,parents=parents)
151 | fws.append(fw)
152 |
153 | if skip_bse==False and skip_gw==True:
154 | sys.exit('Error: Need QP energies from GW calculation to perform BSE .... Exiting NOW')
155 |
156 | if skip_bse==False and skip_gw==False:
157 | ifw=ifw+1
158 | if skip_wannier==False:
159 | parents = fws[ifw-2]
160 | else:
161 | parents = fws[ifw-1]
162 | fw = BseFW(structure=struct, mat_name=mat_name,
163 | vasp_cmd=vasp_cmd,db_file=db_file,parents=parents,reciprocal_density=rd,enwinbse=enwinbse, job_tag=gw_tag+'-BSE')
164 | fws.append(fw)
165 |
166 |
167 | wf_gwbse = Workflow(fws)
168 |
169 | return wf_gwbse
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/sphinx/pyGWBSE/out2db.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 |
3 | import glob
4 | import os
5 |
6 | from atomate.utils.utils import env_chk
7 | from atomate.vasp.database import VaspCalcDb
8 | from fireworks import explicit_serialize, FiretaskBase, FWAction
9 | from monty.json import jsanitize
10 | from pymatgen.io.vasp.outputs import Vasprun, Outcar
11 |
12 | from pyGWBSE.tasks import read_emcpyout, read_epsilon, get_gap_from_dict, read_vac_level
13 | from pyGWBSE.wannier_tasks import read_vbm, read_wannier, read_vasp, read_special_kpts
14 |
15 |
16 | @explicit_serialize
17 | class gw2db(FiretaskBase):
18 | """
19 | Insert quasi-particle energies into the database for a GW calculation.
20 | """
21 | required_params = ["structure", "task_label", "db_file", "mat_name"]
22 | optional_params = ["job_tag"]
23 |
24 | def run_task(self, fw_spec):
25 | """
26 | Your Comments Here
27 | """
28 | # get adddtional tags to parse the directory for
29 | db_file = env_chk(self.get('db_file'), fw_spec)
30 | mmdb = VaspCalcDb.from_db_file(db_file, admin=True)
31 | ifconv = fw_spec["ifconv"]
32 | structure = self["structure"]
33 | task_label = self["task_label"]
34 | if "job_tag" in self:
35 | job_tag = self["job_tag"]
36 | else:
37 | job_tag = None
38 | mat_name = self["mat_name"]
39 | task_collection = 'QP_Results'
40 | dir_name = os.getcwd()
41 | file = glob.glob('vasprun.xml*')[-1]
42 | vasprun = Vasprun(file)
43 | file = glob.glob('OUTCAR*')[-1]
44 | outcar = Outcar(file)
45 | run_stats=outcar.run_stats
46 | qp_energies = vasprun.eigenvalues
47 | en, eps1, eps2 = vasprun.dielectric
48 | igap, dgap = get_gap_from_dict(qp_energies)
49 | incar = vasprun.incar
50 | parameters = vasprun.parameters
51 | bgap, cbm, vbm, is_band_gap_direct = vasprun.eigenvalue_band_properties
52 | kpts_dict = vasprun.kpoints.as_dict()
53 | # dictionary to update the database with
54 | d = {"structure": structure.as_dict(),
55 | "formula_pretty": structure.composition.reduced_formula,
56 | "material_id": mat_name, "run_stats": run_stats,
57 | "run_directory": dir_name, 'direct_gap': dgap, 'indirect_gap': igap,
58 | "qp_energies": qp_energies, "task_label": task_label,
59 | "frequency": en, "epsilon_1": eps1, "epsilon_2": eps2,
60 | "job_tag": job_tag, "ifconv": ifconv, "vbm": vbm, "cbm": cbm,
61 | "incar": incar, "parameters": parameters, "kpoints": kpts_dict}
62 | d = jsanitize(d)
63 | coll = mmdb.db[task_collection]
64 | coll.insert_one(d)
65 |
66 | return FWAction(update_spec={"gw_gaps": [igap, dgap]})
67 |
68 |
69 | @explicit_serialize
70 | class bse2db(FiretaskBase):
71 | """
72 | Insert exciton energies, oscillator strength and dielectric function into the database for a BSE calculation.
73 | """
74 | required_params = ["structure", "task_label", "db_file", "mat_name"]
75 | optional_params = ["job_tag"]
76 |
77 | def run_task(self, fw_spec):
78 | """
79 | Your Comments Here
80 | """
81 | # get adddtional tags to parse the directory for
82 | db_file = env_chk(self.get('db_file'), fw_spec)
83 | mmdb = VaspCalcDb.from_db_file(db_file, admin=True)
84 | structure = self["structure"]
85 | task_label = self["task_label"]
86 | job_tag = self["job_tag"]
87 | mat_name = self["mat_name"]
88 | igap = fw_spec["gw_gaps"][0]
89 | dgap = fw_spec["gw_gaps"][1]
90 | task_collection = 'BSE_Results'
91 | dir_name = os.getcwd()
92 | filename = glob.glob('vasprun.xml*')[-1]
93 | if "job_tag" in self:
94 | job_tag = self["job_tag"]
95 | else:
96 | job_tag = None
97 | with open(filename, "a") as file:
98 | file.write("")
99 | vasprun = Vasprun(filename)
100 | incar = vasprun.incar
101 | parameters = vasprun.parameters
102 | optical_transition = vasprun.optical_transition
103 | en, eps1, eps2 = vasprun.dielectric
104 | kpts_dict = vasprun.kpoints.as_dict()
105 | file = glob.glob('OUTCAR*')[-1]
106 | outcar = Outcar(file)
107 | run_stats=outcar.run_stats
108 | d = {"structure": structure.as_dict(),
109 | "formula_pretty": structure.composition.reduced_formula,
110 | "material_id": mat_name, "run_directory": dir_name,
111 | "frequency": en, "epsilon_1": eps1, "epsilon_2": eps2,
112 | 'direct_gap': dgap, 'indirect_gap': igap, "run_stats": run_stats,
113 | "optical_transition": optical_transition, "task_label": task_label, "job_tag": job_tag,
114 | "incar": incar, "parameters": parameters, "kpoints": kpts_dict}
115 | d = jsanitize(d)
116 | coll = mmdb.db[task_collection]
117 | coll.insert_one(d)
118 |
119 | @explicit_serialize
120 | class rpa2db(FiretaskBase):
121 | """
122 | Insert exciton energies, oscillator strength and dielectric function into the database for a BSE calculation.
123 | """
124 | required_params = ["structure", "task_label", "db_file", "mat_name"]
125 |
126 | def run_task(self, fw_spec):
127 | """
128 | Your Comments Here
129 | """
130 | # get adddtional tags to parse the directory for
131 | db_file = env_chk(self.get('db_file'), fw_spec)
132 | mmdb = VaspCalcDb.from_db_file(db_file, admin=True)
133 | structure = self["structure"]
134 | task_label = self["task_label"]
135 | mat_name = self["mat_name"]
136 | task_collection = 'RPA_Results'
137 | dir_name = os.getcwd()
138 | filename = glob.glob('vasprun.xml*')[-1]
139 | vasprun = Vasprun(filename)
140 | incar = vasprun.incar
141 | parameters = vasprun.parameters
142 | dft_energies = vasprun.eigenvalues
143 | en, eps1, eps2 = vasprun.dielectric
144 | kpts_dict = vasprun.kpoints.as_dict()
145 | file = glob.glob('OUTCAR*')[-1]
146 | outcar = Outcar(file)
147 | run_stats=outcar.run_stats
148 | d = {"structure": structure.as_dict(),
149 | "formula_pretty": structure.composition.reduced_formula,
150 | "material_id": mat_name, "run_directory": dir_name,
151 | "dft_energies": dft_energies, "run_stats": run_stats,
152 | "frequency": en, "epsilon_1": eps1, "epsilon_2": eps2, "task_label": task_label,
153 | "incar": incar, "parameters": parameters, "kpoints": kpts_dict}
154 | d = jsanitize(d)
155 | coll = mmdb.db[task_collection]
156 | coll.insert_one(d)
157 |
158 | @explicit_serialize
159 | class emc2db(FiretaskBase):
160 | """
161 | Insert effective masses for a SUMO-BANDSTATS calculation.
162 | """
163 | required_params = ["structure", "db_file", "mat_name"]
164 |
165 | def run_task(self, fw_spec):
166 | """
167 | Your Comments Here
168 | """
169 | # get adddtional tags to parse the directory for
170 | db_file = env_chk(self.get('db_file'), fw_spec)
171 | dir_name = os.getcwd()
172 | mmdb = VaspCalcDb.from_db_file(db_file, admin=True)
173 | structure = self["structure"]
174 | mat_name = self["mat_name"]
175 | task_collection = 'EMC_Results'
176 | filename = glob.glob('sumo-bandstats.log*')[-1]
177 | hmass, emass = read_emcpyout(filename)
178 | # dictionary to update the database with
179 | d = {"structure": structure.as_dict(),
180 | "formula_pretty": structure.composition.reduced_formula,
181 | "material_id": mat_name, "run_directory": dir_name,
182 | "hole_effective_mass": hmass, "electron_effective_mass": emass}
183 | d = jsanitize(d)
184 | coll = mmdb.db[task_collection]
185 | coll.insert_one(d)
186 |
187 | @explicit_serialize
188 | class eps2db(FiretaskBase):
189 | """
190 | Insert macroscopic dielectric constants for LEPSILON=TRUE calculation.
191 | """
192 | required_params = ["structure", "db_file", "mat_name"]
193 |
194 | def run_task(self, fw_spec):
195 | """
196 | Your Comments Here
197 | """
198 | # get additional tags to parse the directory for
199 | db_file = env_chk(self.get('db_file'), fw_spec)
200 | mmdb = VaspCalcDb.from_db_file(db_file, admin=True)
201 | dir_name = os.getcwd()
202 | structure = self["structure"]
203 | mat_name = self["mat_name"]
204 | task_collection = 'EPS_Results'
205 | filename = glob.glob('vasprun.xml*')[-1]
206 | try:
207 | locpot_fname = glob.glob('LOCPOT*')[-1]
208 | zvac, evac, delta_evac=read_vac_level(locpot_fname, filename)
209 | ifvac=True
210 | except:
211 | ifvac=False
212 | epsilon = read_epsilon(filename)
213 | vrun = Vasprun(filename, parse_projected_eigen=True)
214 | ks_energies = vrun.eigenvalues
215 | proj_eigs=vrun.projected_eigenvalues
216 | kwgs=vrun.actual_kpoints_weights
217 | file = glob.glob('OUTCAR*')[-1]
218 | outcar = Outcar(file)
219 | run_stats=outcar.run_stats
220 | igap, dgap = get_gap_from_dict(ks_energies)
221 | bgap, cbm, vbm, is_band_gap_direct = vrun.eigenvalue_band_properties
222 | # dictionary to update the database with
223 | d = {"structure": structure.as_dict(),
224 | "formula_pretty": structure.composition.reduced_formula,
225 | "material_id": mat_name, "dielectric constant": epsilon,
226 | "run_stats": run_stats, "run_directory": dir_name,
227 | 'direct_gap': dgap, 'indirect_gap': igap,
228 | "kpoint_weights": kwgs, "cbm": cbm, "vbm": vbm,
229 | "projected_eigs": proj_eigs, "ks_energies": ks_energies}
230 | if ifvac:
231 | d.update({"z_vacuum": zvac, "e_vacuum": evac, "delta_e_vacuum": delta_evac})
232 | d = jsanitize(d)
233 | coll = mmdb.db[task_collection]
234 | coll.insert_one(d)
235 |
236 |
237 |
238 | @explicit_serialize
239 | class Wannier2DB(FiretaskBase):
240 | """
241 | Insert a optical transition and quasi-particle energies
242 | into the database for a GW and BSE calculation.
243 |
244 | Args:
245 | db_file (str): path to file containing the database credentials.
246 | Supports env_chk. Default: write data to JSON file.
247 | task_collection (str): The name of the task collection you
248 | want to push the data to.
249 | wf_name (str): The name of the workflow that this analysis is part of.
250 | """
251 |
252 | required_params = ["structure", "task_label", "db_file", "compare_vasp", "mat_name"]
253 |
254 | def run_task(self, fw_spec):
255 | """
256 | Your Comments Here
257 | """
258 | # get adddtional tags to parse the directory for
259 | db_file = env_chk(self.get('db_file'), fw_spec)
260 | mmdb = VaspCalcDb.from_db_file(db_file, admin=True)
261 | structure = self["structure"]
262 | task_label = self["task_label"]
263 | compare_vasp = self["compare_vasp"]
264 | mat_name = self["mat_name"]
265 | task_collection = 'WANNIER_Results'
266 | dir_name = os.getcwd()
267 | fname_band = glob.glob('wannier90_band.dat*')[-1]
268 | fname_kpt = glob.glob('wannier90_band.kpt*')[-1]
269 | fname_gnu = glob.glob('wannier90_band.gnu*')[-1]
270 | fname_vasp = glob.glob('vasprun.xml*')[-1]
271 | gap, vbm = read_vbm(fname_vasp)
272 | kpts, eigs_wann = read_wannier(fname_band, fname_kpt, vbm)
273 | spkptl, spkptc = read_special_kpts(fname_gnu)
274 | if compare_vasp:
275 | kpt_vasp, eigs_vasp = read_vasp(fname_vasp, vbm)
276 | d = {"structure": structure.as_dict(),
277 | "formula_pretty": structure.composition.reduced_formula,
278 | "material_id": mat_name,
279 | "run_directory": dir_name,
280 | "wannier_kpoints": kpts, "wannier_eigenvalues": eigs_wann,
281 | "actual_kpoints": kpt_vasp, "actual_eigenvalues": eigs_vasp,
282 | "special_kpoint_labels": spkptl,
283 | "special_kpoint_coordinates": spkptc,
284 | "task_label": task_label}
285 | else:
286 | d = {"structure": structure.as_dict(),
287 | "formula_pretty": structure.composition.reduced_formula,
288 | "material_id": mat_name,
289 | "run_directory": dir_name,
290 | "wannier_kpoints": kpts, "wannier_eigenvalues": eigs_wann,
291 | "special_kpoint_labels": spkptl,
292 | "special_kpoint_coordinates": spkptc,
293 | "task_label": task_label}
294 | d = jsanitize(d)
295 | coll = mmdb.db[task_collection]
296 | coll.insert_one(d)
297 |
--------------------------------------------------------------------------------
/sphinx/pyGWBSE/run_calc.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 |
3 | """
4 | This module defines tasks that support running vasp in various ways.
5 | """
6 |
7 | import os
8 | import subprocess
9 |
10 | from atomate.utils.utils import env_chk, get_logger
11 | from fireworks import explicit_serialize, FiretaskBase
12 |
13 | __author__ = 'Anubhav Jain '
14 | __credits__ = 'Shyue Ping Ong '
15 |
16 | logger = get_logger(__name__)
17 |
18 |
19 | @explicit_serialize
20 | class Run_Vasp(FiretaskBase):
21 | """
22 | Execute a command directly (no custodian).
23 |
24 | Args:
25 | cmd (str): the name of the full executable to run. Supports env_chk.
26 |
27 | Other Parameters:
28 | expand_vars (str): Set to true to expand variable names in the cmd.
29 | """
30 |
31 | required_params = ["vasp_cmd"]
32 | optional_params = ["expand_vars"]
33 |
34 | def run_task(self, fw_spec):
35 | """
36 | Your Comments Here
37 | """
38 | cmd = env_chk(self["vasp_cmd"], fw_spec)
39 | if self.get("expand_vars", False):
40 | cmd = os.path.expandvars(cmd)
41 |
42 | logger.info("Running command: {}".format(cmd))
43 | return_code = subprocess.call(cmd, shell=True)
44 | logger.info("Command {} finished running with returncode: {}".format(cmd, return_code))
45 |
46 |
47 | @explicit_serialize
48 | class Run_Sumo(FiretaskBase):
49 | """
50 | Your Comments Here
51 | """
52 | required_params = ["sumo_cmd"]
53 |
54 | def run_task(self, fw_spec):
55 | """
56 | Your Comments Here
57 | """
58 | cmd = env_chk(self["sumo_cmd"], fw_spec)
59 | logger.info("Running command: {}".format(cmd))
60 | return_code = subprocess.call(cmd, shell=True)
61 | logger.info("Command {} finished running with returncode: {}".format(cmd, return_code))
62 |
63 |
64 | @explicit_serialize
65 | class Run_Wannier(FiretaskBase):
66 | """
67 | Your Comments Here
68 | """
69 | required_params = ["wannier_cmd"]
70 |
71 | def run_task(self, fw_spec):
72 | """
73 | Your Comments Here
74 | """
75 | cmd = env_chk(self["wannier_cmd"], fw_spec)
76 | logger.info("Running command: {}".format(cmd))
77 | return_code = subprocess.call(cmd, shell=True)
78 | logger.info("Command {} finished running with returncode: {}".format(cmd, return_code))
79 |
--------------------------------------------------------------------------------
/sphinx/pyGWBSE/tasks.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 |
3 | import glob
4 | import gzip
5 | import os
6 | import re
7 | from atomate.common.firetasks.glue_tasks import CopyFiles, get_calc_loc
8 | from atomate.utils.utils import env_chk, get_logger
9 | from fireworks import explicit_serialize, FiretaskBase, FWAction
10 | from pymatgen.io.vasp import Vasprun, Locpot
11 | from pymatgen.io.vasp.inputs import Incar
12 | from pymatgen.core import Structure
13 |
14 | from pyGWBSE.inputset import CreateInputs
15 |
16 | """
17 | This module defines tasks that acts as a glue between other vasp Firetasks to allow communication
18 | between different Firetasks and Fireworks. This module also contains tasks that affect the control
19 | flow of the workflow, e.g. tasks to check stability or the gap is within a certain range.
20 | """
21 |
22 | logger = get_logger(__name__)
23 |
24 | __author__ = 'Anubhav Jain, Kiran Mathew'
25 | __email__ = 'ajain@lbl.gov, kmathew@lbl.gov'
26 |
27 |
28 | @explicit_serialize
29 | class CheckBeConv(FiretaskBase):
30 | """
31 | Your Comments Here
32 | """
33 | required_params = ["niter", "tolerence", "no_conv"]
34 |
35 | def run_task(self, fw_spec):
36 | """
37 | Your Comments Here
38 | """
39 | niter = self["niter"]
40 | conv = self["no_conv"]
41 | tol = self["tolerence"]
42 | filename = str(os.getcwd()) + '/vasprun.xml'
43 | vasprun = Vasprun(filename)
44 | gap, cbm, vbm, is_direct = vasprun.eigenvalue_band_properties
45 | print()
46 | print('=================================================')
47 | print('Iteration:', niter)
48 | print("band gap:", ("%10.4f" % gap))
49 | print("CBM:", ("%10.4f" % cbm))
50 | print("VBM:", ("%10.4f" % vbm))
51 | print("Is the gap direct:", is_direct)
52 | if niter > 1:
53 | old_val = fw_spec["conval"]
54 | new_val = gap
55 | diff = abs(old_val - new_val)
56 | print("Difference:", ("%10.4f" % diff))
57 | print('=================================================')
58 | print()
59 | if diff < tol:
60 | conv = True
61 | return FWAction(update_spec={"ifconv": conv, "conval": gap})
62 |
63 |
64 | @explicit_serialize
65 | class MakeWFilesList(FiretaskBase):
66 |
67 | def run_task(self, fw_spec):
68 | files2copy = glob.glob("W*.tmp")
69 | return FWAction(update_spec={"wfiles": files2copy})
70 |
71 | @explicit_serialize
72 | class SaveNbandsov(FiretaskBase):
73 |
74 | required_params = ["enwinbse"]
75 |
76 | def run_task(self, fw_spec):
77 |
78 | enwinbse = self["enwinbse"]
79 | filename = str(os.getcwd()) + '/vasprun.xml'
80 | vasprun = Vasprun(filename)
81 | qpe=vasprun.eigenvalues
82 | gap, cbm, vbm, is_direct = vasprun.eigenvalue_band_properties
83 | nbandso,nbandsv=get_nbandsov(qpe,vbm,cbm,enwinbse)
84 |
85 | return FWAction(update_spec={"nbandso": nbandso, "nbandsv": nbandsv})
86 |
87 | @explicit_serialize
88 | class SaveConvParams(FiretaskBase):
89 |
90 | required_params = ["nomegagw","encutgw","nbands"]
91 |
92 | def run_task(self, fw_spec):
93 | nomegagw=self["nomegagw"]
94 | encutgw=self["encutgw"]
95 | nbands=self["nbands"]
96 | return FWAction(update_spec={"nomegagw": nomegagw, "encutgw": encutgw, "nbands": nbands})
97 |
98 | @explicit_serialize
99 | class StopIfConverged(FiretaskBase):
100 | """
101 | Your Comments Here
102 | """
103 | def run_task(self, fw_spec):
104 | """
105 | Your Comments Here
106 | """
107 | ifconv = fw_spec["ifconv"]
108 | if ifconv:
109 | return FWAction(exit=True)
110 |
111 |
112 | @explicit_serialize
113 | class PasscalClocsCond(FiretaskBase):
114 | """
115 | Your Comments Here
116 | """
117 | required_params = ["name"]
118 | optional_params = ["filesystem", "path"]
119 |
120 | def run_task(self, fw_spec):
121 | """
122 | Your Comments Here
123 | """
124 | calc_locs = list(fw_spec.get("calc_locs", []))
125 | calc_locs.append({"name": self["name"],
126 | "filesystem": env_chk(self.get('filesystem', None), fw_spec),
127 | "path": self.get("path", os.getcwd())})
128 | ifconv = fw_spec["ifconv"]
129 | if ifconv:
130 | return FWAction(mod_spec=[{'_push_all': {'calc_locs': calc_locs}}])
131 |
132 |
133 | @explicit_serialize
134 | class WriteBSEInput(FiretaskBase):
135 | """
136 | Your Comments Here
137 | """
138 | required_params = ["structure", "reciprocal_density"]
139 |
140 | def run_task(self, fw_spec):
141 | """
142 | Your Comments Here
143 | """
144 | f_incar = str(os.getcwd()) + '/INCAR'
145 | structure = self["structure"]
146 | reciprocal_density = self["reciprocal_density"]
147 | nbandso = fw_spec["nbandso"]
148 | nbandsv = fw_spec["nbandsv"]
149 | prev_incar = Incar.from_file(f_incar)
150 | vis = CreateInputs(structure, mode='BSE', prev_incar=prev_incar, reciprocal_density=reciprocal_density,
151 | nbandso=nbandso, nbandsv=nbandsv)
152 | vis.write_input(".")
153 |
154 |
155 | @explicit_serialize
156 | class WriteGWInput(FiretaskBase):
157 | """
158 | Your Comments Here
159 | """
160 | required_params = ["structure", "reciprocal_density", "nbandsgw", "wannier_fw"]
161 |
162 | def run_task(self, fw_spec):
163 | """
164 | Your Comments Here
165 | """
166 | f_incar = str(os.getcwd()) + '/INCAR'
167 | prev_incar = Incar.from_file(f_incar)
168 | structure = self["structure"]
169 | nbandsgw = self["nbandsgw"]
170 | wannier_fw = self["wannier_fw"]
171 | reciprocal_density = self["reciprocal_density"]
172 | encutgw=fw_spec["encutgw"]
173 | nomegagw=fw_spec["nomegagw"]
174 | nbands=fw_spec["nbands"]
175 | vis = CreateInputs(structure, mode='GW', prev_incar=prev_incar, reciprocal_density=reciprocal_density,
176 | encutgw=encutgw, nomegagw=nomegagw, nbands=nbands, nbandsgw=nbandsgw, wannier_fw=wannier_fw)
177 | vis.write_input(".")
178 |
179 |
180 | def read_emcpyout(fname):
181 | f = open(fname)
182 | contents = f.readlines()
183 | f.close()
184 | ne=0
185 | nh=0
186 | h_res={}
187 | e_res={}
188 | for content in contents:
189 | if "m_h:" in content:
190 | nh=nh+1
191 | lines = str.split(content)
192 | hmass=eval(lines[1])
193 | hibnd=eval(lines[4])
194 | inda=lines.index('->')
195 | if inda==10:
196 | hdir1=lines[9]
197 | hdir2=lines[14]
198 | else:
199 | hdir1='Intermediate'
200 | hdir2=lines[13]
201 |
202 | h_res['mass'+str(nh)+': '+str(hibnd)+', '+hdir1+', '+hdir2]=hmass
203 |
204 | if "m_e:" in content:
205 | ne=ne+1
206 | lines = str.split(content)
207 | emass=eval(lines[1])
208 | eibnd=eval(lines[4])
209 | inda=lines.index('->')
210 | if inda==10:
211 | edir1=lines[9]
212 | edir2=lines[14]
213 | else:
214 | edir1='Intermediate'
215 | edir2=lines[13]
216 |
217 |
218 | e_res['mass'+str(ne)+': '+str(eibnd)+', '+edir1+', '+edir2]=emass
219 |
220 | return h_res, e_res
221 |
222 | def read_epsilon(fname):
223 | vasprun = Vasprun(fname)
224 | try:
225 | epsilon = vasprun.epsilon_static_wolfe
226 | except:
227 | epsilon = None
228 | return epsilon
229 |
230 |
231 | def calc_delta_evac(x,y,n0):
232 | dx1=x[n0+1]-x[n0]
233 | dy1=y[n0+1]-y[n0]
234 | dx2=x[n0]-x[n0-1]
235 | dy2=y[n0]-y[n0-1]
236 | f1=dy1/dx1
237 | f2=dy2/dx2
238 | return (f1+f2)/2
239 |
240 |
241 |
242 | def read_vac_level(locpot_fname,fname):
243 | lpot=Locpot.from_file(locpot_fname)
244 | vrun=Vasprun(fname)
245 | vrun_d=vrun.as_dict()
246 | struct=Structure.from_dict(vrun_d["input"]["crystal"])
247 | latt_c=struct.lattice.c
248 | y=lpot.get_average_along_axis(2)
249 | zarr=lpot.get_axis_grid(2)
250 |
251 | dist_z0=0.
252 | z0=0.
253 |
254 | for n,z in enumerate(zarr):
255 | dist=[]
256 | for site in struct.sites:
257 | pos_z=site.coords[2]
258 | if pos_z<0:
259 | pos_z=pos_z+latt_c
260 | dist.append(abs(pos_z-z))
261 | dist.append(abs(pos_z+latt_c-z))
262 | dist_z=min(dist)
263 | if dist_z>dist_z0:
264 | dist_z0=dist_z
265 | z0=z
266 | n0=n
267 |
268 | evac=y[n0]
269 | zvac=zarr[n0]
270 | delta_evac=calc_delta_evac(zarr,y,n0)
271 |
272 | return zvac,evac,delta_evac
273 |
274 | def get_gap_from_dict(qp_energies):
275 |
276 | tol=1e-5
277 | vbm = -float("inf")
278 | cbm = float("inf")
279 | for spin, d in qp_energies.items():
280 | for k, val in enumerate(d):
281 | for (eigenval, occu) in val:
282 | if occu > tol and eigenval > vbm:
283 | vbm = eigenval
284 | elif occu <= tol and eigenval < cbm:
285 | cbm = eigenval
286 | igap=max(cbm-vbm,0)
287 |
288 | gap = []
289 | filled = 1.0
290 | tol=1e-5
291 | vbm=0
292 | cbm=0
293 | for spin, d in qp_energies.items():
294 | for k, val in enumerate(d):
295 | for (eigenval, occu) in val:
296 | if abs(occu-filled)<=tol:
297 | vbm=eigenval
298 | else:
299 | cbm=eigenval
300 | gap.append(cbm-vbm)
301 | break
302 | dgap=min(gap)
303 | return igap,dgap
304 |
305 | def get_nbandsov(qp_energies,vbm,cbm,enwinbse):
306 |
307 | tol=1e-5
308 | nvb=[]
309 | ncb=[]
310 | for spin, d in qp_energies.items():
311 | for k, val in enumerate(d):
312 | for ibnd,(eigenval, occ) in enumerate(val):
313 | if abs(occ-1.0) 9:
404 | raise ValueError(
405 | "CopyVaspOutputs doesn't properly handle >9 relaxations!")
406 | m = re.search('\.relax\d*', relax_paths[-1])
407 | relax_ext = m.group(0)
408 |
409 | # detect .gz extension if needed - note that monty zpath() did not seem useful here
410 | gz_ext = ""
411 | if not (f + relax_ext) in all_files:
412 | for possible_ext in [".gz", ".GZ"]:
413 | if (f + relax_ext + possible_ext) in all_files:
414 | gz_ext = possible_ext
415 |
416 | if not (f + relax_ext + gz_ext) in all_files:
417 | raise ValueError("Cannot find file: {}".format(f))
418 |
419 | # copy the file (minus the relaxation extension)
420 | self.fileclient.copy(prev_path_full + relax_ext + gz_ext,
421 | dest_path + gz_ext)
422 |
423 | # unzip the .gz if needed
424 | if gz_ext in ['.gz', ".GZ"]:
425 | # unzip dest file
426 | f = gzip.open(dest_path + gz_ext, 'rt')
427 | file_content = f.read()
428 | with open(dest_path, 'w') as f_out:
429 | f_out.writelines(file_content)
430 | f.close()
431 | os.remove(dest_path + gz_ext)
432 |
--------------------------------------------------------------------------------
/sphinx/pyGWBSE/wannier_tasks.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 |
3 | """
4 | This module defines tasks for WANNIER90 calculation
5 | """
6 |
7 | import os
8 |
9 | import numpy as np
10 | from atomate.utils.utils import get_logger
11 | from fireworks import explicit_serialize, FiretaskBase
12 | from pymatgen import Structure
13 | from pymatgen.io.vasp import Vasprun
14 | from pymatgen.io.vasp.inputs import Incar, Potcar, PotcarSingle
15 | from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
16 | from pymatgen.symmetry.bandstructure import HighSymmKpath
17 |
18 | from pyGWBSE.inputset import CreateInputs
19 |
20 | logger = get_logger(__name__)
21 |
22 | __author__ = 'Tathagata Biswas'
23 | __email__ = 'tbiswas3@asu.edu'
24 |
25 |
26 | @explicit_serialize
27 | class WriteWannierInputForGW(FiretaskBase):
28 | """
29 | Your Comments Here
30 | """
31 | required_params = ["structure", "reciprocal_density", "nbandsgw"]
32 |
33 | def run_task(self, fw_spec):
34 | """
35 | Your Comments Here
36 | """
37 | f_incar = str(os.getcwd()) + '/INCAR'
38 | structure = self["structure"]
39 | nbandsgw = self["nbandsgw"]
40 | reciprocal_density = self["reciprocal_density"]
41 | prev_incar = Incar.from_file(f_incar)
42 | wann_inp = str(os.getcwd()) + '/wannier90.win'
43 | vasprunfile = str(os.getcwd()) + '/vasprun.xml'
44 | poscarfile = str(os.getcwd()) + '/POSCAR'
45 | potcarfile = str(os.getcwd()) + '/POTCAR'
46 | vasprun = Vasprun(vasprunfile)
47 | incar = vasprun.incar
48 | nbands = incar["NBANDS"]
49 | elements = read_potcar(potcarfile, poscarfile)
50 | labels, kpts = kpath_finder(poscarfile)
51 | numwan = 0
52 | for element in elements:
53 | numwan = numwan + element[5]
54 | if numwan > nbandsgw:
55 | nbandsgw = numwan
56 | encutgw=fw_spec["encutgw"]
57 | nomegagw=fw_spec["nomegagw"]
58 | nbands=fw_spec["nbands"]
59 | vis = CreateInputs(structure, mode='GW', reciprocal_density=reciprocal_density,
60 | prev_incar=prev_incar, encutgw=encutgw, nomegagw=nomegagw, nbands=nbands, nbandsgw=nbandsgw)
61 | vis.write_input(".")
62 | labels, kpts = kpath_finder(poscarfile)
63 | write_wannier_input(numwan, nbands, labels, kpts, wann_inp, elements,False)
64 |
65 |
66 | @explicit_serialize
67 | class WriteWannierInputForDFT(FiretaskBase):
68 | """
69 | Your Comments Here
70 | """
71 | required_params = ["structure", "reciprocal_density", "ppn", "write_hr"]
72 |
73 | def run_task(self, fw_spec):
74 | """
75 | Your Comments Here
76 | """
77 | f_incar = str(os.getcwd()) + '/INCAR'
78 | structure = self["structure"]
79 | reciprocal_density = self["reciprocal_density"]
80 | ppn = self["ppn"]
81 | write_hr = self["write_hr"]
82 | prev_incar = Incar.from_file(f_incar)
83 | wann_inp = str(os.getcwd()) + '/wannier90.win'
84 | vasprunfile = str(os.getcwd()) + '/vasprun.xml'
85 | poscarfile = str(os.getcwd()) + '/POSCAR'
86 | potcarfile = str(os.getcwd()) + '/POTCAR'
87 | vasprun = Vasprun(vasprunfile)
88 | incar = vasprun.incar
89 | nbands = incar["NBANDS"]
90 | elements = read_potcar(potcarfile, poscarfile)
91 | numwan = 0
92 | for element in elements:
93 | numwan = numwan + element[5]
94 | print(numwan, nbands)
95 | if numwan > nbands:
96 | nbands = (int(numwan / ppn) + 1) * ppn
97 | vis = CreateInputs(structure, mode='STATIC', prev_incar=prev_incar, reciprocal_density=reciprocal_density,
98 | nbands=nbands)
99 | vis.write_input(".")
100 | labels, kpts = kpath_finder(poscarfile)
101 | write_wannier_input(numwan, nbands, labels, kpts, wann_inp, elements,write_hr)
102 |
103 |
104 | @explicit_serialize
105 | class CopyKptsWan2vasp(FiretaskBase):
106 | """
107 | Your Comments Here
108 | """
109 |
110 | def run_task(self, fw_spec):
111 | """
112 | Your Comments Here
113 | """
114 | f_wannkpt = str(os.getcwd()) + '/wannier90_band.kpt'
115 | f_vaspkpt = str(os.getcwd()) + '/KPOINTS'
116 | f = open(f_wannkpt)
117 | contents = f.readlines()
118 | f.close()
119 | lines = str.split(contents[0])
120 | nkpts = eval(lines[0])
121 | f = open(f_vaspkpt, 'w')
122 | f.write('kpoints file generated from wannier90_band.kpt' + '\n')
123 | f.write(str(nkpts) + '\n')
124 | f.write('Reciprocal' + '\n')
125 | for ik in range(nkpts):
126 | f.write(contents[ik + 1])
127 | f.close()
128 |
129 |
130 | def write_wannier_input(numwan, nbands, labels, kpts, wann_inp, elements,write_hr):
131 | """
132 | Your Comments Here
133 | """
134 | if write_hr:
135 | f = open(wann_inp, 'a')
136 | f.write("write_hr = true" + "\n")
137 | f.close()
138 | else:
139 | f = open(wann_inp, 'w')
140 | f.write("num_wann = " + str(numwan) + "\n")
141 | if numwan < nbands:
142 | f.write("exclude_bands " + str(numwan + 1) + "-" + str(nbands) + "\n")
143 | if numwan == nbands - 1:
144 | f.write("exclude_bands " + str(numwan + 1) + "\n")
145 | f.write("bands_plot = true" + "\n")
146 | f.write("begin kpoint_path" + "\n")
147 | for i in range(len(labels)):
148 | for j in range(len(labels[i])-1):
149 | label1=labels[i][j]
150 | label2=labels[i][j+1]
151 | string = write_kpath_lines(kpts[label1], label1, kpts[label2], label2)
152 | f.write(string)
153 | f.write("end kpoint_path" + "\n")
154 | f.write("bands_num_points 40" + "\n")
155 | f.write("bands_plot_format gnuplot" + "\n")
156 | f.write("Begin Projections" + "\n")
157 | f.write("random" + "\n")
158 | for element in elements:
159 | f.write(element[0] + ':')
160 | for l in range(4):
161 | if element[l + 1] > 0:
162 | if l == 0:
163 | f.write('l=' + str(l))
164 | else:
165 | f.write(';' + 'l=' + str(l))
166 | f.write('\n')
167 | f.write("End Projections" + "\n")
168 | f.write("num_iter = 500" + "\n")
169 | f.close()
170 |
171 |
172 | def write_kpath_lines(kpt1, label1, kpt2, label2):
173 | """
174 | Your Comments Here
175 | """
176 | string = label1 + " " + "%10.5f" % kpt1[0] + "%10.5f" % kpt1[1] + "%10.5f" % kpt1[
177 | 2] + " " + label2 + " " + "%10.5f" % kpt2[0] + "%10.5f" % kpt2[1] + "%10.5f" % kpt2[2] + "\n"
178 | return string
179 |
180 |
181 | def kpath_finder(filename):
182 | """
183 | Your Comments Here
184 | """
185 | struct = Structure.from_file(filename)
186 | spcg = SpacegroupAnalyzer(struct)
187 | pstruct = spcg.get_primitive_standard_structure(international_monoclinic=False)
188 | hskp = HighSymmKpath(pstruct)
189 | kpts = hskp.kpath["kpoints"]
190 | labels = hskp.kpath["path"]
191 | return labels, kpts
192 |
193 |
194 | def read_potcar(potcarfile, poscarfile):
195 | """
196 | Your Comments Here
197 | """
198 | struct = Structure.from_file(poscarfile)
199 | potcar = Potcar.from_file(potcarfile)
200 | sites = struct.species
201 | specs = potcar.spec
202 | wan_info = []
203 | for spec in specs:
204 | single = PotcarSingle.from_symbol_and_functional(symbol=spec['symbol'], functional='PBE_54')
205 | orbitals = single.electron_configuration
206 | element = single.element
207 | nat = str(sites).count(single.element)
208 | spdf = []
209 | for orbital in orbitals:
210 | spdf.append(orbital[1])
211 | scnt = spdf.count('s')
212 | pcnt = spdf.count('p')
213 | dcnt = spdf.count('d')
214 | fcnt = spdf.count('f')
215 | numwan = nat * (scnt * 1 + pcnt * 3 + dcnt * 5 + fcnt * 7)
216 | wan_info.append([element, scnt, pcnt, dcnt, fcnt, numwan])
217 | return wan_info
218 |
219 |
220 | def read_vbm(fname):
221 | """
222 | Your Comments Here
223 | """
224 | vasprun = Vasprun(fname, parse_potcar_file=False)
225 | gap, cbm, vbm, is_direct = vasprun.eigenvalue_band_properties
226 | return gap, vbm
227 |
228 |
229 | def read_wannier(fname_band, fname_kpt, vbm):
230 | """
231 | Your Comments Here
232 | """
233 | f = open(fname_band)
234 | contents = f.readlines()
235 | f.close()
236 |
237 | kvals = []
238 | evals = []
239 |
240 | for content in contents:
241 | lines = str.split(content)
242 | if len(lines) != 0:
243 | kvals.append(eval(lines[0]))
244 | evals.append(eval(lines[1]))
245 | with open(fname_kpt) as f:
246 | first_line = f.readline()
247 | nkpt = eval(str.split(first_line)[0])
248 | nband = int(len(evals) / nkpt)
249 | kpts_flat = np.array(kvals)
250 | eigs_flat = np.array(evals) - vbm
251 | kpts = kpts_flat.reshape(nband, nkpt)
252 | eigs = eigs_flat.reshape(nband, nkpt)
253 |
254 | return kpts, eigs
255 |
256 |
257 | def read_vasp(fname, vbm):
258 | """
259 | Your Comments Here
260 | """
261 | vasprun = Vasprun(fname)
262 | eigs = vasprun.eigenvalues
263 | nkpt = len(vasprun.actual_kpoints)
264 | kptvasp = vasprun.actual_kpoints
265 | out = []
266 | for spin, d in eigs.items():
267 | for k, val in enumerate(d):
268 | for n, eigenval in enumerate(val):
269 | out.append(eigenval[0] - vbm)
270 | nbands = int(len(out) / nkpt)
271 | eigvasp = np.reshape(out, (nkpt, nbands))
272 |
273 | return kptvasp, eigvasp
274 |
275 |
276 | def read_special_kpts(fname):
277 | """
278 | Your Comments Here
279 | """
280 | f = open(fname)
281 | contents = f.readlines()
282 | f.close()
283 | spkptl = []
284 | spkptc = []
285 | for content in contents:
286 | if 'set xtics' in content:
287 | lines = str.split(content,sep='"')
288 | for n, words in enumerate(lines):
289 | if n!=0 and n%2!=0:
290 | spkptl.append(words)
291 | elif n!=0:
292 | spkptc.append(eval(words[:9]))
293 |
294 | return spkptl,spkptc
295 |
296 |
--------------------------------------------------------------------------------
/sphinx/pyGWBSE/wflows.py:
--------------------------------------------------------------------------------
1 | # coding: utf-8
2 |
3 |
4 | """
5 | Defines standardized Fireworks that can be chained easily to perform various
6 | sequences of VASP calculations.
7 | """
8 |
9 | from atomate.common.firetasks.glue_tasks import PassCalcLocs
10 | from atomate.vasp.firetasks.write_inputs import WriteVaspFromIOSet
11 | from fireworks import Firework, Tracker
12 |
13 |
14 | from pyGWBSE.inputset import CreateInputs
15 | from pyGWBSE.out2db import gw2db, bse2db, emc2db, eps2db, Wannier2DB, rpa2db
16 | from pyGWBSE.run_calc import Run_Vasp, Run_Sumo, Run_Wannier
17 | from pyGWBSE.tasks import CopyOutputFiles, CheckBeConv, StopIfConverged, PasscalClocsCond, WriteBSEInput, \
18 | WriteGWInput, MakeWFilesList, SaveNbandsov, SaveConvParams
19 | from pyGWBSE.wannier_tasks import WriteWannierInputForDFT, WriteWannierInputForGW, CopyKptsWan2vasp
20 |
21 |
22 | class ScfFW(Firework):
23 | def __init__(self, mat_name=None, structure=None, nbands=None, kpar=None, reciprocal_density=None,
24 | vasp_input_set=None, vasp_input_set_params=None,
25 | vasp_cmd="vasp", prev_calc_loc=True, prev_calc_dir=None, db_file=None, wannier_fw=None,
26 | vasptodb_kwargs={}, **kwargs):
27 | """
28 | Your Comments Here
29 | """
30 | t = []
31 | vasp_input_set = CreateInputs(structure, kpar=kpar, reciprocal_density=reciprocal_density, nbands=nbands,
32 | wannier_fw=wannier_fw)
33 | name = 'SCF'
34 | fw_name = "{}-{}".format(mat_name, name)
35 | t.append(WriteVaspFromIOSet(structure=structure,
36 | vasp_input_set=vasp_input_set,
37 | vasp_input_set_params=vasp_input_set_params))
38 | t.append(Run_Vasp(vasp_cmd=vasp_cmd, auto_npar=">>auto_npar<<"))
39 | t.append(eps2db(structure=structure, mat_name=mat_name, db_file=db_file, defuse_unsuccessful=False))
40 | t.append(rpa2db(structure=structure, mat_name=mat_name, task_label=name, db_file=db_file, defuse_unsuccessful=False))
41 | t.append(PassCalcLocs(name=name))
42 | super(ScfFW, self).__init__(t, name=fw_name, **kwargs)
43 |
44 |
45 | class convFW(Firework):
46 |
47 | def __init__(self, mat_name=None, structure=None, tolerence=None, no_conv=None, nbands=None,
48 | nbgwfactor=None, encutgw=None, nomegagw=None, convparam=None, convsteps=None, conviter=None,
49 | kpar=None, nbandsgw=None, reciprocal_density=None, vasp_input_set=None, vasp_input_set_params=None,
50 | vasp_cmd="vasp",
51 | prev_calc_loc=True, prev_calc_dir=None, db_file=None, vasptodb_kwargs={}, parents=None, **kwargs):
52 | t = []
53 | name = "CONV"
54 | fw_name = "{}-{}".format(mat_name, name)
55 | niter = 0
56 | for niter in range(conviter):
57 | niter = niter + 1
58 | files2copy = ['WAVECAR']
59 | task_label = 'Convergence_Iteration: ' + str(niter)
60 | if convparam == 'NBANDS':
61 | nbgwfactor = nbgwfactor + (niter - 1) * convsteps
62 | if convparam == 'ENCUTGW':
63 | encutgw = encutgw + (niter - 1) * convsteps
64 | if convparam == 'NOMEGA':
65 | nomegagw = nomegagw + (niter - 1) * convsteps
66 | if prev_calc_dir:
67 | t.append(CopyOutputFiles(additional_files=files2copy, calc_dir=prev_calc_dir, contcar_to_poscar=True))
68 | elif parents:
69 | if prev_calc_loc:
70 | t.append(
71 | CopyOutputFiles(additional_files=files2copy, calc_loc=prev_calc_loc, contcar_to_poscar=True))
72 | vasp_input_set = CreateInputs(structure, mode='DIAG', nbands=nbands * nbgwfactor, kpar=kpar,
73 | reciprocal_density=reciprocal_density)
74 | t.append(WriteVaspFromIOSet(structure=structure,
75 | vasp_input_set=vasp_input_set,
76 | vasp_input_set_params=vasp_input_set_params))
77 | t.append(Run_Vasp(vasp_cmd=vasp_cmd, auto_npar=">>auto_npar<<"))
78 | vasp_input_set = CreateInputs(structure,mode='CONV',nbands=nbands*nbgwfactor,encutgw=encutgw,nomegagw=nomegagw,kpar=kpar,reciprocal_density=reciprocal_density,nbandsgw=nbandsgw)
79 | t.append(WriteVaspFromIOSet(structure=structure,
80 | vasp_input_set=vasp_input_set,
81 | vasp_input_set_params=vasp_input_set_params))
82 | if no_conv==False:
83 | t.append(Run_Vasp(vasp_cmd=vasp_cmd, auto_npar=">>auto_npar<<"))
84 | t.append(SaveConvParams(nbands=nbands*nbgwfactor, encutgw=encutgw, nomegagw=nomegagw))
85 | t.append(CheckBeConv(niter=niter, tolerence=tolerence, no_conv=no_conv))
86 | t.append(PasscalClocsCond(name=name))
87 | if no_conv==False:
88 | t.append(gw2db(structure=structure, mat_name=mat_name, task_label=task_label, db_file=db_file,
89 | defuse_unsuccessful=False))
90 | t.append(StopIfConverged())
91 | tracker = Tracker('vasp.log', nlines=100)
92 | super(convFW, self).__init__(t, parents=parents, name=fw_name, spec={"_trackers": [tracker]}, **kwargs)
93 |
94 |
95 | class GwFW(Firework):
96 | def __init__(self, mat_name=None, structure=None, tolerence=None, no_conv=None, reciprocal_density=None,
97 | vasp_input_set=None, vasp_input_set_params=None, nbandso=None, nbandsv=None, nbandsgw=None,
98 | vasp_cmd="vasp", prev_calc_loc=True, prev_calc_dir=None, db_file=None, wannier_fw=None,
99 | vasptodb_kwargs={}, job_tag=None, parents=None, **kwargs):
100 | """
101 | Your Comments Here
102 | """
103 | t = []
104 | name = "GW"
105 | fw_name = "{}-{}".format(mat_name, name)
106 | files2copy = ['WAVECAR', 'WAVEDER']
107 | if prev_calc_dir:
108 | t.append(CopyOutputFiles(additional_files=files2copy, calc_dir=prev_calc_dir, contcar_to_poscar=True))
109 | elif parents:
110 | if prev_calc_loc:
111 | t.append(CopyOutputFiles(additional_files=files2copy, calc_loc=prev_calc_loc, contcar_to_poscar=True))
112 | t.append(WriteGWInput(structure=structure, reciprocal_density=reciprocal_density, nbandsgw=nbandsgw,
113 | wannier_fw=wannier_fw))
114 | for niter in range(1, 10):
115 | task_label = 'scGW_Iteration: ' + str(niter)
116 | if wannier_fw:
117 | t.append(WriteWannierInputForGW(structure=structure, reciprocal_density=reciprocal_density,nbandsgw=nbandsgw))
118 | t.append(Run_Vasp(vasp_cmd=vasp_cmd, auto_npar=">>auto_npar<<"))
119 | t.append(CheckBeConv(niter=niter, tolerence=tolerence, no_conv=no_conv))
120 | t.append(PasscalClocsCond(name=name))
121 | t.append(MakeWFilesList())
122 | t.append(
123 | gw2db(structure=structure, mat_name=mat_name, task_label=task_label, job_tag=job_tag, db_file=db_file,
124 | defuse_unsuccessful=False))
125 | t.append(StopIfConverged())
126 | tracker = Tracker('vasp.log', nlines=100)
127 |
128 | super(GwFW, self).__init__(t, parents=parents, name=fw_name, spec={"_trackers": [tracker]}, **kwargs)
129 |
130 |
131 | class BseFW(Firework):
132 | def __init__(self, mat_name=None, structure=None, reciprocal_density=None, vasp_input_set=None,
133 | vasp_input_set_params=None, enwinbse=None,
134 | vasp_cmd="vasp", prev_calc_loc=True, prev_calc_dir=None, db_file=None, vasptodb_kwargs={},
135 | job_tag=None, parents=None, **kwargs):
136 | """
137 | Your Comments Here
138 | """
139 | t = []
140 | name = "BSE"
141 | fw_name = "{}-{}".format(mat_name, name)
142 | files2copy = ['WAVECAR', 'WAVEDER']
143 | if prev_calc_dir:
144 | t.append(CopyOutputFiles(additional_files=files2copy, calc_dir=prev_calc_dir, contcar_to_poscar=True))
145 | elif parents:
146 | if prev_calc_loc:
147 | t.append(CopyOutputFiles(additional_files=files2copy, calc_loc=prev_calc_loc, contcar_to_poscar=True))
148 | t.append(SaveNbandsov(enwinbse=enwinbse))
149 | t.append(WriteBSEInput(structure=structure, reciprocal_density=reciprocal_density))
150 | t.append(Run_Vasp(vasp_cmd=vasp_cmd, auto_npar=">>auto_npar<<"))
151 | t.append(bse2db(structure=structure, mat_name=mat_name, task_label=name, job_tag=job_tag, db_file=db_file,
152 | defuse_unsuccessful=False))
153 | tracker = Tracker('vasp.log', nlines=100)
154 |
155 | super(BseFW, self).__init__(t, parents=parents, name=fw_name, state='PAUSED', spec={"_trackers": [tracker]},
156 | **kwargs)
157 |
158 |
159 | class EmcFW(Firework):
160 | def __init__(self, mat_name=None, structure=None, nbands=None, kpar=None, reciprocal_density=None, steps=None,
161 | vasp_input_set=None, vasp_input_set_params=None,
162 | vasp_cmd="vasp", sumo_cmd='sumo', prev_calc_loc=True, prev_calc_dir=None, db_file=None,
163 | vasptodb_kwargs={}, parents=None, **kwargs):
164 | """
165 | Your Comments Here
166 | """
167 | t = []
168 |
169 | vasp_input_set = CreateInputs(structure, mode='EMC', kpar=kpar, reciprocal_density=reciprocal_density,
170 | nbands=nbands)
171 | name = 'EMC'
172 | fw_name = "{}-{}".format(mat_name, name)
173 | if prev_calc_dir:
174 | t.append(CopyOutputFiles(calc_dir=prev_calc_dir, additional_files=["CHGCAR"]))
175 | elif parents:
176 | t.append(CopyOutputFiles(calc_loc=True, additional_files=["CHGCAR"]))
177 | else:
178 | raise ValueError("Must specify previous calculation for NonScfFW")
179 | t.append(WriteVaspFromIOSet(structure=structure,
180 | vasp_input_set=vasp_input_set,
181 | vasp_input_set_params=vasp_input_set_params))
182 | t.append(Run_Vasp(vasp_cmd=vasp_cmd, auto_npar=">>auto_npar<<"))
183 | t.append(Run_Sumo(sumo_cmd=sumo_cmd))
184 | t.append(emc2db(structure=structure, mat_name=mat_name, db_file=db_file, defuse_unsuccessful=False))
185 | super(EmcFW, self).__init__(t, parents=parents, name=fw_name, **kwargs)
186 |
187 |
188 | class WannierCheckFW(Firework):
189 | def __init__(self, ppn=None, kpar=None, mat_name=None, structure=None, reciprocal_density=None, vasp_input_set=None,
190 | vasp_input_set_params=None,
191 | vasp_cmd="vasp", wannier_cmd=None, prev_calc_loc=True, prev_calc_dir=None, db_file=None,
192 | vasptodb_kwargs={}, parents=None, **kwargs):
193 | """
194 | Your Comments Here
195 | """
196 | t = []
197 | name = "WANNIER_CHECK"
198 | fw_name = "{}-{}".format(mat_name, name)
199 | t.append(CopyOutputFiles(calc_loc=prev_calc_loc, contcar_to_poscar=True))
200 | t.append(WriteWannierInputForDFT(structure=structure, reciprocal_density=reciprocal_density, ppn=ppn, write_hr=False))
201 | t.append(Run_Vasp(vasp_cmd=vasp_cmd, auto_npar=">>auto_npar<<"))
202 | t.append(WriteWannierInputForDFT(structure=structure, reciprocal_density=reciprocal_density, ppn=ppn, write_hr=True))
203 | t.append(Run_Wannier(wannier_cmd=wannier_cmd))
204 | vasp_input_set = CreateInputs(structure, mode='EMC', kpar=kpar, reciprocal_density=reciprocal_density)
205 | t.append(WriteVaspFromIOSet(structure=structure,
206 | vasp_input_set=vasp_input_set,
207 | vasp_input_set_params=vasp_input_set_params))
208 | t.append(CopyKptsWan2vasp())
209 | t.append(Run_Vasp(vasp_cmd=vasp_cmd, auto_npar=">>auto_npar<<"))
210 | t.append(Wannier2DB(structure=structure, mat_name=mat_name, task_label='CHECK_WANNIER_INTERPOLATION',
211 | db_file=db_file, compare_vasp=True, defuse_unsuccessful=False))
212 | tracker = Tracker('vasp.log', nlines=100)
213 |
214 | super(WannierCheckFW, self).__init__(t, parents=parents, name=fw_name, spec={"_trackers": [tracker]}, **kwargs)
215 |
216 |
217 | class WannierFW(Firework):
218 | def __init__(self, structure=None, mat_name=None, wannier_cmd=None, prev_calc_loc=True, prev_calc_dir=None,
219 | db_file=None, parents=None, **kwargs):
220 | """
221 | Your Comments Here
222 | """
223 | t = []
224 | name = "WANNIER"
225 | fw_name = "{}-{}".format(mat_name, name)
226 | files2copy = ['wannier90.win', 'wannier90.mmn', 'wannier90.amn', 'wannier90.eig']
227 | t.append(CopyOutputFiles(additional_files=files2copy, calc_loc=prev_calc_loc, contcar_to_poscar=True))
228 | t.append(Run_Wannier(wannier_cmd=wannier_cmd))
229 | t.append(Wannier2DB(structure=structure, mat_name=mat_name, task_label='GW_BANDSTRUCTURE', db_file=db_file,
230 | compare_vasp=False, defuse_unsuccessful=False))
231 | tracker = Tracker('wannier90.wout', nlines=100)
232 |
233 | super(WannierFW, self).__init__(t, parents=parents, name=fw_name, spec={"_trackers": [tracker]}, **kwargs)
234 |
--------------------------------------------------------------------------------
/sphinx/requirement.txt:
--------------------------------------------------------------------------------
1 | numpy==1.16.0
2 | FireWorks==1.8.1
3 | pymatgen==2018.11.30
4 | atomate==0.8.4
5 | monty==1.0.3
6 | sphinx==3.0.1
7 | sphinx-rtd-theme==0.5.2
8 | setuptools==57.4.0
9 | pybtex==0.24.0
--------------------------------------------------------------------------------
/sphinx/rst/modules.rst:
--------------------------------------------------------------------------------
1 | WFGWBSE
2 | =======
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | project_intro/modules
8 | Documentation
9 |
--------------------------------------------------------------------------------
/sphinx/rst/project/gwbse_wf/getfromdb.rst:
--------------------------------------------------------------------------------
1 | getfromdb module
2 | ================
3 |
4 | .. automodule:: getfromdb
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/sphinx/rst/project/gwbse_wf/inputset.rst:
--------------------------------------------------------------------------------
1 | inputset module
2 | ===============
3 |
4 | .. automodule:: inputset
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/sphinx/rst/project/gwbse_wf/modules.rst:
--------------------------------------------------------------------------------
1 | gwbse_wf
2 | ========
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | getfromdb
8 | inputset
9 | out2db
10 | run_calc
11 | tasks
12 | wannier_tasks
13 | wflows
14 |
--------------------------------------------------------------------------------
/sphinx/rst/project/gwbse_wf/out2db.rst:
--------------------------------------------------------------------------------
1 | out2db module
2 | =============
3 |
4 | .. automodule:: out2db
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/sphinx/rst/project/gwbse_wf/run_calc.rst:
--------------------------------------------------------------------------------
1 | run\_calc module
2 | ================
3 |
4 | .. automodule:: run_calc
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/sphinx/rst/project/gwbse_wf/tasks.rst:
--------------------------------------------------------------------------------
1 | tasks module
2 | ============
3 |
4 | .. automodule:: tasks
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/sphinx/rst/project/gwbse_wf/wannier_tasks.rst:
--------------------------------------------------------------------------------
1 | wannier\_tasks module
2 | =====================
3 |
4 | .. automodule:: wannier_tasks
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/sphinx/rst/project/gwbse_wf/wflows.rst:
--------------------------------------------------------------------------------
1 | wflows module
2 | =============
3 |
4 | .. automodule:: wflows
5 | :members:
6 | :undoc-members:
7 | :special-members: '__init__'
8 | :show-inheritance:
9 |
--------------------------------------------------------------------------------
/sphinx/rst/project/make_wf.rst:
--------------------------------------------------------------------------------
1 | make\_wf module
2 | ===============
3 |
4 | .. automodule:: make_wf
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/sphinx/rst/project/modules.rst:
--------------------------------------------------------------------------------
1 | WFGWBSE
2 | =======
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | make_wf
8 | gwbse_wf/modules
--------------------------------------------------------------------------------
/sphinx/rst/project_intro/installation.rst:
--------------------------------------------------------------------------------
1 | Installing WFGWBSE
2 | ==================
3 |
4 | ""Your Comments Here""
5 |
6 |
--------------------------------------------------------------------------------
/sphinx/rst/project_intro/introduction.rst:
--------------------------------------------------------------------------------
1 | ============
2 | Introduction
3 | ============
4 |
5 | ""Your Comments Here""
6 |
7 | Package Description
8 | ===================
9 |
10 | ""Your Comments Here""
11 |
12 | Examples
13 | ========
14 |
15 | ""Your Comments Here""
16 |
17 | How to cite 2dSynth
18 | ===================
19 |
20 | If you use 2dSynth in your research, please consider citing the following work:
21 |
22 | **add later**
23 |
24 | License
25 | =======
26 |
27 | ""Your Comments Here""
28 |
29 | About the Team
30 | ==============
31 |
32 | ""Your Comments Here""
33 |
34 | Copyright Policy
35 | ================
36 |
37 | ""Your Comments Here""
38 |
39 | # Copyright (c) CMD Lab Development Team.
40 | # Distributed under the terms of the GNU License.
--------------------------------------------------------------------------------
/sphinx/rst/project_intro/modules.rst:
--------------------------------------------------------------------------------
1 | Project Intro
2 | =============
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | introduction
8 | installation
9 | team
10 | references
11 |
--------------------------------------------------------------------------------
/sphinx/rst/project_intro/references.rst:
--------------------------------------------------------------------------------
1 | References
2 | ==========
3 |
4 | ""Your Comments Here""
--------------------------------------------------------------------------------
/sphinx/rst/project_intro/team.rst:
--------------------------------------------------------------------------------
1 | ================
2 | Development Team
3 | ================
4 |
5 | Lead Maintainers
6 | ================
7 |
8 | | **Arunima K. Singh** |as2362| |0000-0002-7212-6310|
9 | | Assistant Professor, Department of Physics
10 | | Arizona State University, Tempe
11 |
12 | .. |as2362| image:: ../../_static/github.png
13 | :target: https://github.com/as2362
14 | :width: 26
15 | :height: 26
16 | :alt: GitHub profile for as2362
17 |
18 | .. |0000-0002-7212-6310| image:: ../../_static/orcid.jpg
19 | :target: https://orcid.org/0000-0002-7212-6310
20 | :width: 26
21 | :height: 26
22 | :alt: ORCID profile for 0000-0002-7212-6310
23 |
24 | | Tathagata Biswas
25 | | XYZ
26 | | Arizona State University, Tempe
27 |
28 | List of Developers (A-Z)
29 | ========================
30 |
31 |
32 |
--------------------------------------------------------------------------------
/sphinx/setup.py:
--------------------------------------------------------------------------------
1 | from setuptools import setup
2 |
3 |
4 | setup(
5 | name='pyGWBSE',
6 | version='1.0',
7 | description='python workflow for GW-BSE calculation',
8 | author='Tathagata Biswas',
9 | author_email='tbiswas3@asu.edu',
10 | packages=['pyGWBSE'],
11 | install_requires=['FireWorks>=1.4.0', 'pymatgen>=2018.6.11',
12 | 'monty>=1.0.2', 'atomate>=0.8.4'],
13 | package_data={"pyGWBSE": ["inputset.yaml"]}
14 |
15 | )
16 |
--------------------------------------------------------------------------------