Merge pull request #262 from jtkrogel/dev

nexus: better guard for structure file and internal consistency
This commit is contained in:
Mark Dewing 2017-06-12 16:03:55 -05:00 committed by GitHub
commit ef1451cac5
5 changed files with 155 additions and 29 deletions

View File

@ -154,13 +154,11 @@ def morse_reduced_mass(m1,m2=None):
m1 = ptable[m1].atomic_weight.me
#end if
if m2 is None:
m = m1
else:
if isinstance(m2,str):
m2 = ptable[m2].atomic_weight.me
#end if
m = 1./(1./m1+1./m2) # reduced mass
m2 = m1
elif isinstance(m2,str):
m2 = ptable[m2].atomic_weight.me
#end if
m = 1./(1./m1+1./m2) # reduced mass
return m
#end def morse_reduced_mass

View File

@ -396,18 +396,50 @@ class PhysicalSystem(Matter):
#end def pseudize
def check_folded_system(self):
def check_folded_system(self,exit=True,message=False):
msg = ''
sys_folded = self.folded_system!=None
struct_folded = self.structure.folded_structure!=None
if sys_folded!=struct_folded:
self.error('folding of physical system and structure is not consistent\n system folded: {0}\n structure folded: {1}'.format(sys_folded,struct_folded))
msg+='folding of physical system and structure is not consistent\nsystem folded: {0}\nstructure folded: {1}\n'.format(sys_folded,struct_folded)
#end if
if sys_folded and id(self.structure.folded_structure)!=id(self.folded_system.structure):
self.error('structure of folded system and folded structure are distinct\n this is not allowed and may be a developer error')
msg+='structure of folded system and folded structure are distinct\nthis is not allowed and may be a developer error'
#end if
success = len(msg)==0
if not success and exit:
self.error(msg)
#end if
if not message:
return success
else:
return success,msg
#end if
#end def check_folded_system
def check_consistent(self,tol=1e-8,exit=True,message=False):
fs,fm = self.check_folded_system(exit=False,message=True)
cs,cm = self.structure.check_consistent(tol,exit=False,message=True)
msg = ''
if not fs:
msg += fm+'\n'
#end if
if not cs:
msg += cm+'\n'
#end if
consistent = len(msg)==0
if not consistent and exit:
self.error(msg)
#end if
if not message:
return consistent
else:
return consistent,msg
#end if
#end def check_consistent
def change_units(self,units):
self.structure.change_units(units,folded=False)
if self.folded_system!=None:
@ -623,14 +655,27 @@ def generate_physical_system(**kwargs):
if 'structure' in kwargs:
s = kwargs['structure']
is_str = isinstance(s,str)
if is_str and os.path.exists(s):# and '.' in os.path.split(s)[1]:
if 'elem' in kwargs:
kwargs['structure'] = read_structure(s,elem=kwargs['elem'])
if is_str:
if os.path.exists(s):
if 'elem' in kwargs:
kwargs['structure'] = read_structure(s,elem=kwargs['elem'])
else:
kwargs['structure'] = read_structure(s)
#end if
else:
kwargs['structure'] = read_structure(s)
slow = s.lower()
format = None
if '.' in slow:
format = slow.rsplit('.')[1]
elif 'poscar' in slow:
format = 'poscar'
#end if
is_path = '/' in s
is_file = format in set('xyz xsf poscar cif fhi-aims'.split())
if is_path or is_file:
PhysicalSystem.class_error('user provided structure file does not exist\nstructure file path: '+s,'generate_physical_system')
#end if
#end if
elif is_str and '/' in s:
PhysicalSystem.class_error('path provided for structure file does not exist: '+s,'generate_physical_system')
#end if
#end if

View File

@ -29,6 +29,57 @@ from execute import execute
from debug import ci
unique_vdw_functionals = [
'optb86b-vdw',
'vdw-df3', # optB88+vdW
'vdw-df',
'vdw-df2',
'rev-vdw-df2',
'vdw-df-c09',
'vdw-df2-c09',
'rvv10',
]
repeat_vdw_functionals = [
'vdw-df4', # 'optB86b-vdW'
]
unique_functionals = [
'revpbe',
'pw86pbe',
'b86bpbe',
'pbe0',
'hse',
'gaup',
'pbesol',
'pbeq2d',
'optbk88',
'optb86b',
'pbe',
'wc',
'b3lyp',
'pbc',
'bp',
'pw91',
'hcth',
'olyp',
'tpss',
'oep',
'hf',
'blyp',
'lda',
'sogga',
'm06l',
'ev93',
]+unique_vdw_functionals
repeat_functionals = [
'q2d', # pbeq2d
'pz', # lda
]+repeat_vdw_functionals
vdw_functionals = set(unique_vdw_functionals+repeat_vdw_functionals)
allowed_functionals = set(unique_functionals+repeat_functionals)
class Pwscf(Simulation):
input_type = PwscfInput
analyzer_type = PwscfAnalyzer
@ -41,11 +92,11 @@ class Pwscf(Simulation):
vdw_table = None
@staticmethod
def settings(vdw_table=None):
# van der Waals family of functional require the vdW table generated by
# generate_vdW_kernel_table.x: specify 'vdw_table' in settings
Pwscf.vdw_table = vdw_table
@staticmethod
def settings(vdw_table=None):
# van der Waals family of functional require the vdW table generated by
# generate_vdW_kernel_table.x: specify 'vdw_table' in settings
Pwscf.vdw_table = vdw_table
#end def settings
#def propagate_identifier(self):
@ -75,16 +126,20 @@ class Pwscf(Simulation):
if not os.path.exists(outdir):
os.makedirs(outdir)
#end if
#copy over vdw_table for vdW-DF functional
#copy over vdw_table for vdW-DF functional
if self.path_exists('input/system/input_dft'):
if self.input.system.input_dft.lower().startswith('vdw-df'):
functional = self.input.system.input_dft.lower()
if '+' not in functional and functional not in allowed_functionals:
self.warn('functional "{0}" is unknown to pwscf'.format(functional))
#end if
if functional in vdw_functionals:
if self.vdw_table is None:
self.error('attempting to run vdW-DF functional, but vdw_table is missing\nplease provide path to table file via "vdw_table" parameter in settings')
self.error('attempting to run vdW functional "{0}", but vdw_table is missing\nplease provide path to table file via "vdw_table" parameter in settings'.format(functional))
#end if
cd_rel = os.path.relpath(self.vdw_table,self.locdir)
# copy instead of link to vdw_table to avoid file-lock from multiple pw.x instances
cp_cmd = 'cd '+self.locdir+';cp '+cd_rel+' .'
os.system(cp_cmd)
cd_rel = os.path.relpath(self.vdw_table,self.locdir)
# copy instead of link to vdw_table to avoid file-lock from multiple pw.x instances
cp_cmd = 'cd '+self.locdir+';cp '+cd_rel+' .'
os.system(cp_cmd)
#end if
#end if
#end def write_prep

View File

@ -474,6 +474,11 @@ class Simulation(NexusCore):
#end if
if isinstance(self.system,PhysicalSystem):
self.system = self.system.copy()
consistent,msg = self.system.check_consistent(exit=False,message=True)
if not consistent:
locdir = os.path.join(nexus_core.local_directory,nexus_core.runs,self.path)
self.error('user provided physical system is not internally consistent\nsimulation identifier: {0}\nlocal directory: {1}\nmore details on the user error are given below\n\n{2}'.format(self.identifier,locdir,msg))
#end if
elif self.system!=None:
self.error('system must be a PhysicalSystem object\nyou provided an object of type: {0}'.format(self.system.__class__.__name__))
#end if

View File

@ -766,6 +766,26 @@ class Structure(Sobj):
#end def __init__
def check_consistent(self,tol=1e-8,exit=True,message=False):
msg = ''
if self.has_axes():
kaxes = 2*pi*inv(self.axes).T
abs_diff = abs(self.kaxes-kaxes).sum()
if abs_diff>tol:
msg += 'direct and reciprocal space axes are not consistent\naxes present:\n{0}\nkaxes present:\n{1}\nconsistent kaxes:\n{2}\nabsolute difference: {3}\n'.format(self.axes,self.kaxes,kaxes,abs_diff)
#end if
#end if
consistent = len(msg)==0
if not consistent and exit:
self.error(msg)
#end if
if not message:
return consistent
else:
return consistent,msg
#end if
#end def check_consistent
def set_axes(self,axes):
self.reset_axes(axes)
@ -3181,8 +3201,11 @@ class Structure(Sobj):
#end def add_kmesh
def kpoints_unit(self):
return dot(self.kpoints,inv(self.kaxes))
def kpoints_unit(self,kpoints=None):
if kpoints is None:
kpoints = self.kpoints
#end if
return dot(kpoints,inv(self.kaxes))
#end def kpoints_unit