Skip to content

Commit

Permalink
Merge pull request #154 from pyscal/add_qe
Browse files Browse the repository at this point in the history
Add qe
  • Loading branch information
srmnitc authored Jul 26, 2024
2 parents abfe5ce + a3482ff commit e8f77a1
Show file tree
Hide file tree
Showing 24 changed files with 20,073 additions and 2,808 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.9.8
current_version = 0.9.9
commit = True
tag = False

Expand Down
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ url: 'https://atomrdf.pyscal.org'
license: "MIT"
repository-code: https://github.com/pyscal/atomRDF
type: software
version: 0.9.8
version: 0.9.9
42 changes: 16 additions & 26 deletions atomrdf/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -1278,11 +1278,10 @@ def get_system_from_sample(self, sample):
sys._name = sample.toPython().split('sample:')[-1]
return sys

def to_file(self, sample, filename=None, format="poscar", add_sample_id=True,
input_data=None, pseudopotentials=None,
kspacing=None, kpts=None,
koffset=(0, 0, 0),
crystal_coordinates=False):
def to_file(self, sample, filename=None, format="poscar",
add_sample_id=True,
copy_from=None,
pseudo_files=None):
"""
Save a given sample to a file
Expand All @@ -1297,24 +1296,13 @@ def to_file(self, sample, filename=None, format="poscar", add_sample_id=True,
format: string, {"lammps-dump","lammps-data", "poscar", 'cif', 'quantum-espresso'}
or any format supported by ase
input_data : str, optional
Additional input data to include in the output file. Defaults to None.
Only valid for quantum-espresso format. See ASE write docs for more information.
pseudopotentials : str, optional
The path to the pseudopotentials file. Defaults to None.
Only valid for quantum-espresso format. See ASE write docs for more information.
kspacing : float, optional
The k-spacing value to include in the output file. Defaults to None.
Only valid for quantum-espresso format. See ASE write docs for more information.
kpts : list, optional
A list of k-points to include in the output file. Defaults to None.
Only valid for quantum-espresso format. See ASE write docs for more information.
koffset : tuple, optional
The k-offset values to include in the output file. Defaults to (0, 0, 0).
Only valid for quantum-espresso format. See ASE write docs for more information.
crystal_coordinates : bool, optional
Whether to include crystal coordinates in the output file. Defaults to False.
Only valid for quantum-espresso format. See ASE write docs for more information.
copy_from : str, optional
If provided, input options for quantum-espresso format will be copied from
the given file. Structure specific information will be replaced.
Note that the validity of input file is not checked.
pseudo_files : list, optional
if provided, add the pseudopotential filenames to file.
Should be in alphabetical order of chemical species symbols.
Returns
-------
Expand All @@ -1325,9 +1313,11 @@ def to_file(self, sample, filename=None, format="poscar", add_sample_id=True,
filename = os.path.join(os.getcwd(), "out")

sys = self.get_system_from_sample(sample)
sys.to_file(filename=filename, format=format, add_sample_id=add_sample_id, input_data=input_data,
pseudopotentials=pseudopotentials, kspacing=kspacing,
kpts=kpts, koffset=koffset, crystal_coordinates=crystal_coordinates)
sys.to_file(filename=filename,
format=format,
add_sample_id=add_sample_id,
copy_from=copy_from,
pseudo_files=pseudo_files)

def enable_workflow(self, workflow_object, workflow_environment=None, workflow_module=None):
self.workflow.inform_graph(workflow_object,
Expand Down
117 changes: 117 additions & 0 deletions atomrdf/io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import mendeleev
import numpy as np
from ase.io.espresso import read_fortran_namelist
import os
import warnings

def _convert_tab_to_dict(tab):
keywords = ["ATOMIC_SPECIES",
"ATOMIC_POSITIONS",
"K_POINTS",
"CELL_PARAMETERS",
"OCCUPATIONS",
"CONSTRAINTS",
"ATOMIC_VELOCITIES",
"ATOMIC_FORCES",
"ADDITIONAL_K_POINTS",
"SOLVENTS",
"HUBBARD"]

tabdict = {}
for line in tab:
firstword = line.split()[0]
secondword = " ".join(line.split()[1:])

if firstword in keywords:
tabdict[firstword] = {}
tabdict[firstword]['value'] = []
tabdict[firstword]['extra'] = secondword
tabarr = tabdict[firstword]['value']
else:
tabarr.append(line.strip())
return tabdict

def write_espresso(s, inputfile, copy_from=None, pseudo_files=None):
data = None
tab = None

if copy_from is not None:
if os.path.exists(copy_from):
try:
with open(copy_from, 'r') as fin:
data, tab = read_fortran_namelist(fin)
except:
warnings.warn(f'Error reading {copy_from}, a clean file will be written')
copy=True

if tab is not None:
tab = _convert_tab_to_dict(tab)
else:
tab = {}

if data is None:
data = {}
data['system'] = {}
data['control'] = {}

tab['CELL_PARAMETERS'] = {}
tab['CELL_PARAMETERS']['extra'] = 'angstrom'
tab['CELL_PARAMETERS']['value'] = []

for vec in s.box:
tab['CELL_PARAMETERS']['value'].append(' '.join([str(x) for x in vec]))

cds = s.direct_coordinates
species = s.atoms.species

unique_species = np.unique(species)
if pseudo_files is not None:
if not len(pseudo_files) == len(unique_species):
raise ValueError('Number of pseudo files must match number of unique species')
pseudo_dirs = [os.path.dirname(os.path.abspath(pseudo_file)) for pseudo_file in pseudo_files]
if not len(np.unique(pseudo_dirs)) == 1:
raise ValueError('All pseudo files must be in the same directory')
data['control']['pseudo_dir'] = pseudo_dirs[0]
else:
pseudo_files = ['None' for x in range(len(unique_species))]

tab['ATOMIC_SPECIES'] = {}
tab['ATOMIC_SPECIES']['extra'] = ''
tab['ATOMIC_SPECIES']['value'] = []

for count, us in enumerate(unique_species):
chem = mendeleev.element(us)
tab['ATOMIC_SPECIES']['value'].append(f'{us} {chem.atomic_weight} {os.path.basename(pseudo_files[count])}')

tab['ATOMIC_POSITIONS'] = {}
tab['ATOMIC_POSITIONS']['extra'] = 'crystal'
tab['ATOMIC_POSITIONS']['value'] = []

for cd, sp in zip(cds, species):
tab['ATOMIC_POSITIONS']['value'].append(f'{sp} {cd[0]} {cd[1]} {cd[2]}')

data['system']['ibrav'] = 0
data['system']['nat'] = len(species)
data['system']['ntyp'] = len(unique_species)

with open(inputfile, 'w') as fout:
if s.sample is not None:
fout.write(f'! {s.sample.toPython()}\n\n')

for key, val in data.items():
fout.write(f'&{key.upper()}\n')
for k, v in val.items():
if isinstance(v, str):
fout.write(f' {k} = \'{v}\',\n')
else:
fout.write(f' {k} = {v},\n')
fout.write('/\n')
fout.write('\n')

for key, val in tab.items():
fout.write(f'{key} {val["extra"]}\n')
fout.write('\n')
for v in val['value']:
fout.write(v)
fout.write('\n')
fout.write('\n')
53 changes: 14 additions & 39 deletions atomrdf/structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import atomrdf.json_io as json_io
import atomrdf.properties as prp
from atomrdf.sample import Property
import atomrdf.io as aio

from rdflib import Graph, Namespace, XSD, RDF, RDFS, BNode, URIRef
from atomrdf.namespace import CMSO, LDO, PLDO, PODO, UNSAFEASMO, UNSAFECMSO, PROV, Literal, ASMO
Expand Down Expand Up @@ -784,6 +785,7 @@ def __init__(
mapdict = {}
mapdict['ase'] = update_wrapper(partial(self.to_file, format='ase'), self.to_file)
mapdict['pyiron'] = update_wrapper(partial(self.to_file, format='pyiron'), self.to_file)
mapdict['quantum_espresso'] = update_wrapper(partial(self.to_file, format='quantum-espresso'), self.to_file)
mapdict['file'] = self.to_file
self.write._add_attribute(mapdict)

Expand Down Expand Up @@ -1466,22 +1468,11 @@ def write_poscar_id(self, outfile):
for line in lines:
fout.write(line)

def write_quatum_espresso_id(self, outfile):
lines = []
lines.append(f"! {self.sample.toPython()}\n")
with open(outfile, "r") as fin:
for line in fin:
lines.append(line)
with open(outfile, "w") as fout:
for line in lines:
fout.write(line)

def to_file(self, filename=None, format='lammps-dump', customkeys=None, customvals=None,
def to_file(self, filename=None,
format='lammps-dump',
customkeys=None, customvals=None,
compressed=False, timestep=0, species=None, add_sample_id=True,
input_data=None, pseudopotentials=None,
kspacing=None, kpts=None,
koffset=(0, 0, 0),
crystal_coordinates=False):
copy_from=None, pseudo_files=None):
"""
Write the structure to a file in the specified format.
Expand All @@ -1508,24 +1499,13 @@ def to_file(self, filename=None, format='lammps-dump', customkeys=None, customva
add_sample_id : bool, optional
Whether to add a sample ID to the output file. Defaults to True.
Only valid for poscar and quantum-espresso formats.
input_data : str, optional
Additional input data to include in the output file. Defaults to None.
Only valid for quantum-espresso format. See ASE write docs for more information.
pseudopotentials : str, optional
The path to the pseudopotentials file. Defaults to None.
Only valid for quantum-espresso format. See ASE write docs for more information.
kspacing : float, optional
The k-spacing value to include in the output file. Defaults to None.
Only valid for quantum-espresso format. See ASE write docs for more information.
kpts : list, optional
A list of k-points to include in the output file. Defaults to None.
Only valid for quantum-espresso format. See ASE write docs for more information.
koffset : tuple, optional
The k-offset values to include in the output file. Defaults to (0, 0, 0).
Only valid for quantum-espresso format. See ASE write docs for more information.
crystal_coordinates : bool, optional
Whether to include crystal coordinates in the output file. Defaults to False.
Only valid for quantum-espresso format. See ASE write docs for more information.
copy_from : str, optional
If provided, input options for quantum-espresso format will be copied from
the given file. Structure specific information will be replaced.
Note that the validity of input file is not checked.
pseudo_files : list, optional
if provided, add the pseudopotential filenames to file.
Should be in alphabetical order of chemical species symbols.
Returns
-------
Expand Down Expand Up @@ -1565,12 +1545,7 @@ def to_file(self, filename=None, format='lammps-dump', customkeys=None, customva
write(outfile, asesys, format='lammps-data', atom_style='atomic')

elif format == "quantum-espresso":
asesys = convert_snap(self)
write(outfile, asesys, format='espresso-in', input_data=input_data,
pseudopotentials=pseudopotentials, kspacing=kspacing,
kpts=kpts, koffset=koffset, crystal_coordinates=crystal_coordinates)
if add_sample_id and (self.sample is not None):
self.write_quatum_espresso_id(outfile)
aio.write_espresso(self, filename, copy_from=copy_from, pseudo_files=pseudo_files)

else:
asesys = convert_snap(self)
Expand Down
Empty file added atomrdf/workflow/qe/__init__.py
Empty file.
Loading

0 comments on commit e8f77a1

Please sign in to comment.