mirror of https://github.com/QMCPACK/qmcpack.git
291 lines
12 KiB
Python
291 lines
12 KiB
Python
##################################################################
|
|
## (c) Copyright 2015- by Jaron T. Krogel ##
|
|
##################################################################
|
|
|
|
|
|
#====================================================================#
|
|
# gamess.py #
|
|
# Nexus interface to the GAMESS simulation code. #
|
|
# #
|
|
# Content summary: #
|
|
# GamessInput #
|
|
# Input class for the GAMESS code. #
|
|
# Capable of reading/writing arbitrary GAMESS input files. #
|
|
# #
|
|
# generate_gamess_input #
|
|
# User function to create arbitrary GAMESS input. #
|
|
# #
|
|
# KeywordGroup #
|
|
# Represents an arbitrary keyword group in the input file. #
|
|
# #
|
|
# KeywordSpecGroup #
|
|
# Base class for specialized keyword groups. #
|
|
# Derived classes enforce the keyword specification. #
|
|
# See ContrlGroup, SystemGroup, GuessGroup, ScfGroup, #
|
|
# McscfGroup, DftGroup, GugdiaGroup, DrtGroup, CidrtGroup, #
|
|
# and DetGroup #
|
|
# #
|
|
# FormattedGroup #
|
|
# Represents strict machine-formatted input groups. #
|
|
# #
|
|
#====================================================================#
|
|
|
|
|
|
import os
|
|
import numpy as np
|
|
from numpy import array,ndarray,abs
|
|
from generic import obj
|
|
from developer import DevBase
|
|
from debug import *
|
|
from simulation import Simulation
|
|
from gamess_input import GamessInput,generate_gamess_input,FormattedGroup,KeywordGroup,GuessGroup,GIarray
|
|
from gamess_analyzer import GamessAnalyzer
|
|
|
|
|
|
|
|
class Gamess(Simulation):
|
|
input_type = GamessInput
|
|
analyzer_type = GamessAnalyzer
|
|
generic_identifier = 'gamess'
|
|
application = 'gamess.x'
|
|
infile_extension = '.inp'
|
|
application_properties = set(['serial','mpi'])
|
|
application_results = set(['orbitals'])
|
|
|
|
ericfmt = None
|
|
mcppath = None
|
|
|
|
@staticmethod
|
|
def settings(ericfmt=None,mcppath=None):
|
|
Gamess.ericfmt = ericfmt
|
|
Gamess.mcppath = mcppath
|
|
#end def settings
|
|
|
|
@staticmethod
|
|
def restore_default_settings():
|
|
Gamess.ericfmt = None
|
|
Gamess.mcppath = None
|
|
#end def restore_default_settings
|
|
|
|
|
|
def __init__(self,**kwargs):
|
|
self.mo_reorder = None
|
|
mo_reorder = kwargs.pop('mo_reorder',None)
|
|
if mo_reorder is not None:
|
|
self.mo_reorder = [s.lower() for s in mo_reorder]
|
|
#end if
|
|
Simulation.__init__(self,**kwargs)
|
|
#end def __init__
|
|
|
|
|
|
def init_job_extra(self):
|
|
# gamess seems to need lots of environment variables to run properly
|
|
# nearly all of these are names of output/work files
|
|
# setup the environment to run gamess
|
|
if not isinstance(self.ericfmt,str):
|
|
self.error('you must set ericfmt with settings() or Gamess.settings()')
|
|
#end if
|
|
env = obj()
|
|
for file,unit in GamessInput.file_units.items():
|
|
env[file] = '{0}.F{1}'.format(self.identifier,str(unit).zfill(2))
|
|
#end for
|
|
env.INPUT = self.infile
|
|
env.ERICFMT = self.ericfmt
|
|
env.MCPPATH = self.mcppath
|
|
self.job.set_environment(**env)
|
|
#end def init_job_extra
|
|
|
|
|
|
def check_result(self,result_name,sim):
|
|
input = self.input
|
|
if result_name=='orbitals':
|
|
calculating_result = 'contrl' in input and 'scftyp' in input.contrl and input.contrl.scftyp.lower() in ('rhf','rohf','uhf','mcscf','none')
|
|
else:
|
|
calculating_result = False
|
|
#end if
|
|
return calculating_result
|
|
#end def check_result
|
|
|
|
|
|
def get_result(self,result_name,sim):
|
|
result = obj()
|
|
input = self.input
|
|
analyzer = self.load_analyzer_image()
|
|
if result_name=='orbitals':
|
|
result.location = os.path.join(self.locdir,self.outfile)
|
|
result.outfile = result.location
|
|
result.vec = None # vec from punch
|
|
result.norbitals = 0 # orbital count in punch
|
|
result.mos = 0 # orbital count (MO's) from log file
|
|
result.scftyp = input.contrl.scftyp.lower()
|
|
if 'counts' in analyzer and 'mos' in analyzer.counts:
|
|
result.mos = analyzer.counts.mos
|
|
#end if
|
|
if 'punch' in analyzer and 'vec' in analyzer.punch:
|
|
result.norbitals = analyzer.punch.norbitals
|
|
result.vec = analyzer.punch.vec
|
|
#end if
|
|
if 'orbitals' in analyzer:
|
|
result.orbitals = analyzer.orbitals
|
|
#end if
|
|
else:
|
|
self.error('ability to get result '+result_name+' has not been implemented')
|
|
#end if
|
|
return result
|
|
#end def get_result
|
|
|
|
|
|
def incorporate_result(self,result_name,result,sim):
|
|
input = self.input
|
|
if result_name=='orbitals':
|
|
if result.vec is None or result.norbitals<1:
|
|
self.error('could not obtain orbitals from previous GAMESS run')
|
|
#end if
|
|
if not 'guess' in input:
|
|
input.guess = GuessGroup()
|
|
#end if
|
|
if 'norb' in input.guess: # user provided norb
|
|
norb = input.guess.norb
|
|
else:
|
|
norb = result.norbitals
|
|
#end if
|
|
if 'norder' not in input.guess:
|
|
input.guess.clear()
|
|
#end if
|
|
if self.mo_reorder is not None:
|
|
if 'orbitals' not in result:
|
|
self.error('Orbital information from prior calculation "{}" located at {} cannot be found. You requested orbital reordering via the "mo_reorder" input keyword. Due to missing information, this operation cannot be performed. The current simulation "{}" is located at {}.'.format(sim.identifier,sim.locdir,self.identifier,self.locdir))
|
|
self.block()
|
|
#end if
|
|
guess_inputs = obj()
|
|
ecounts = self.system.particles.electron_counts()
|
|
orbs = result.orbitals
|
|
order_map = obj(up='iorder',down='jorder')
|
|
nelec_map = obj(up=ecounts[0],down=ecounts[1])
|
|
for spin,vname in order_map.items():
|
|
nelec = nelec_map[spin]
|
|
if len(self.mo_reorder)<nelec:
|
|
self.error('Too few symmetries provided in "mo_reorder" for spin "{0}".\nNumber of electrons with spin "{0}": {1}\nNumber of entries in "mo_reorder": {2}\nContents of "mo_reorder": {3}\nSimulation identifier: {4}\nSimulation location: {5}'.format(spin,nelec,len(self.mo_reorder),self.mo_reorder,self.identifier,self.locdir))
|
|
#end if
|
|
symmetries = [s.lower() for s in orbs[spin].symmetry]
|
|
missing = set(self.mo_reorder)-set(symmetries)
|
|
if len(missing)>0:
|
|
self.error('Symmetries provided by "mo_reorder" keyword are not found in the outputted MOs.\nSet of symmetries provided in "mo_reorder": {}\nSet of symmetries present in MOs: {}\nContents of "mo_reorder": {}\nSimulation identifier: {}\nSimulation location: {}'.format(sorted(set(self.mo_reorder)),sorted(set(symmetries)),self.mo_reorder,self.identifier,self.locdir))
|
|
#end if
|
|
occ = np.zeros(len(symmetries),dtype=bool)
|
|
for symm in self.mo_reorder[:nelec]:
|
|
for i,(s,o) in enumerate(zip(symmetries,occ)):
|
|
if not o and symm==s:
|
|
occ[i] = True
|
|
break
|
|
#end if
|
|
#end for
|
|
#end for
|
|
if occ.sum()<nelec:
|
|
self.error('Too few orbitals occupied based on "mo_reorder" request.\nNumber of orbitals occupied: {}\nNumber of spin "{}" electrons: {}\nContents of "mo_reorder": {}\nSimulation identifier: {}\nSimulation location: {}'.format(occ.sum(),spin,nelec,self.mo_reorder,self.identifier,self.locdir))
|
|
#end if
|
|
indices = np.arange(len(symmetries),dtype=int)[occ]+1
|
|
start = 0
|
|
found = False
|
|
for i in range(len(indices)):
|
|
start = i
|
|
if indices[i]!=i+1:
|
|
found = True
|
|
break
|
|
#end if
|
|
#end if
|
|
if found:
|
|
reduced_indices = indices[start:]
|
|
start+=1
|
|
else:
|
|
reduced_indices = []
|
|
#end if
|
|
if len(reduced_indices)>0:
|
|
guess_inputs.norder = 1
|
|
guess_inputs[vname] = GIarray({start:reduced_indices})
|
|
#end if
|
|
#end for
|
|
input.guess.set(**guess_inputs)
|
|
#end if
|
|
input.guess.set(
|
|
guess = 'moread',
|
|
norb = norb,
|
|
prtmo = True,
|
|
)
|
|
input.vec = FormattedGroup(result.vec)
|
|
else:
|
|
self.error('ability to incorporate result '+result_name+' has not been implemented')
|
|
#end if
|
|
#end def incorporate_result
|
|
|
|
|
|
def app_command(self):
|
|
if self.app_name == 'rungms':
|
|
return 'rungms '+self.infile
|
|
else:
|
|
return self.app_name+' '+self.infile.replace('.inp','')
|
|
#end if
|
|
#end def app_command
|
|
|
|
|
|
def check_sim_status(self):
|
|
output = open(os.path.join(self.locdir,self.outfile),'r').read()
|
|
#errors = open(os.path.join(self.locdir,self.errfile),'r').read()
|
|
|
|
self.failed = 'EXECUTION OF GAMESS TERMINATED -ABNORMALLY-' in output
|
|
self.finished = self.failed or 'EXECUTION OF GAMESS TERMINATED NORMALLY' in output
|
|
#end def check_sim_status
|
|
|
|
|
|
def get_output_files(self):
|
|
output_files = []
|
|
return output_files
|
|
#end def get_output_files
|
|
|
|
|
|
def output_filename(self,name):
|
|
name = name.upper()
|
|
if name not in GamessInput.file_units:
|
|
self.error('gamess does not produce a file matching the requested description: {0}'.format(name))
|
|
#end if
|
|
unit = GamessInput.file_units[name]
|
|
filename = '{0}.F{1}'.format(self.identifier,str(unit).zfill(2))
|
|
return filename
|
|
#end def output_filename
|
|
|
|
|
|
def output_filepath(self,name):
|
|
filename = self.output_filename(name)
|
|
filepath = os.path.join(self.locdir,filename)
|
|
filepath = os.path.abspath(filepath)
|
|
return filepath
|
|
#end def
|
|
#end class Gamess
|
|
|
|
|
|
|
|
def generate_gamess(**kwargs):
|
|
sim_args,inp_args = Gamess.separate_inputs(kwargs,copy_pseudos=False,sim_kw=['mo_reorder'])
|
|
|
|
if not 'input' in sim_args:
|
|
sim_args.input = generate_gamess_input(**inp_args)
|
|
#end if
|
|
gamess = Gamess(**sim_args)
|
|
|
|
return gamess
|
|
#end def generate_gamess
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|