This method reads the keywords from a given initial file and saves it for future use, each in their separate class Signed-off-by: Vitor Hideyoshi <vitor.h.n.batista@gmail.com>
272 lines
8.2 KiB
Python
272 lines
8.2 KiB
Python
import os, sys
|
|
import shutil
|
|
import textwrap
|
|
|
|
from DPpack.PTable import *
|
|
from DPpack.Misc import *
|
|
|
|
class Internal:
|
|
|
|
def __init__(self, infile):
|
|
|
|
self.infile = infile
|
|
|
|
self.player = self.Player()
|
|
self.player_keywords = [a for a in dir(self.player) if not a.startswith('__') and not callable(getattr(self.player, a))]
|
|
|
|
self.dice = self.Dice()
|
|
self.dice_keywords = [a for a in dir(self.dice) if not a.startswith('__') and not callable(getattr(self.dice, a))]
|
|
|
|
self.gaussian = self.Gaussian()
|
|
self.gaussian_keywords = [a for a in dir(self.gaussian) if not a.startswith('__') and not callable(getattr(self.gaussian, a))]
|
|
|
|
self.molcas = self.Molcas()
|
|
self.molcas_keywords = [a for a in dir(self.molcas) if not a.startswith('__') and not callable(getattr(self.molcas, a))]
|
|
|
|
## Constanst that shall be set for global use
|
|
|
|
self.tol_rms_force = 3e-4 # Hartree/Bohr
|
|
self.tol_max_force = 4.5e-4 # Hartree/Bohr
|
|
self.tol_rms_step = 1.2e-3 # Bohr
|
|
self.tol_max_step = 1.8e-3 # Bohr
|
|
self.trust_radius = None
|
|
|
|
## Dice:
|
|
self.combrule = None
|
|
self.randominit = None
|
|
|
|
def read_keywords(self):
|
|
|
|
try:
|
|
with open(self.infile) as fh:
|
|
controlfile = fh.readlines()
|
|
except EnvironmentError:
|
|
sys.exit("Error: cannot open file {}".format(self.infile))
|
|
|
|
for line in controlfile:
|
|
|
|
key, value = line.partition("=")[::2] # Discards the '='
|
|
key = key.strip().lower()
|
|
if key in ('title', 'keywords'):
|
|
value = value.strip()
|
|
else:
|
|
value = value.split()
|
|
|
|
#### Read the Diceplayer related keywords
|
|
if key in self.player_keywords and len(value) != 0: ## 'value' is not empty!
|
|
|
|
if key == 'qmprog' and value[0].lower() in ("g03", "g09", "g16", "molcas"):
|
|
setattr(self.player, key, value[0].lower())
|
|
|
|
elif key == 'opt' and value[0].lower() in ("yes", "no", "ts"):
|
|
setattr(self.player, key, value[0].lower())
|
|
|
|
#elif key == 'zipprog' and value[0].lower() in ("zip", "gzip", "bzip"):
|
|
#player[key] = value[0].lower()
|
|
|
|
elif key in ('lps', 'ghosts') and value[0].lower() in ("yes", "no"):
|
|
setattr(self.player, key, value[0].lower())
|
|
|
|
elif key in ('readhessian', 'vdwforces') and value[0].lower() in ("yes", "no"):
|
|
setattr(self.player, key, value[0].lower())
|
|
|
|
elif key in ('maxcyc', 'initcyc', 'nprocs', 'altsteps', 'switchcyc'):
|
|
err = "Error: expected a positive integer for keyword {} in file {}".format(key, self.infile)
|
|
try:
|
|
new_value = int(value[0])
|
|
if new_value >= 1:
|
|
setattr(self.player, key, new_value)
|
|
elif key == 'altsteps' and new_value == 0:
|
|
setattr(self.player, key, 0)
|
|
except ValueError:
|
|
sys.exit(err)
|
|
|
|
elif key == 'maxstep': # Cannot be less than 0.01
|
|
err = "Error: expected a float greater than 0.01 for keyword {} in file {}".format(key, self.infile)
|
|
try:
|
|
new_value = float(value[0])
|
|
if new_value < 0.01:
|
|
sys.exit(err)
|
|
else:
|
|
setattr(self.player, key).append(new_value)
|
|
except ValueError:
|
|
sys.exit(err)
|
|
|
|
#### Read the Dice related keywords
|
|
elif key in self.dice_keywords and len(value) != 0: ## 'value' is not empty!
|
|
|
|
if key == 'title':
|
|
setattr(self.dice, key, value)
|
|
|
|
elif key in ('ljname', 'outname', 'progname'):
|
|
setattr(self.dice, key, value[0])
|
|
|
|
elif key in ('ncores', 'isave'):
|
|
err = "Error: expected a positive integer for keyword {} in file {}".format(key, self.infile)
|
|
if not value[0].isdigit():
|
|
sys.exit(err)
|
|
new_value = int(value[0])
|
|
if new_value >= 1:
|
|
setattr(self.dice, key, new_value)
|
|
|
|
elif key in ('temp', 'press', 'dens'): # Cannot be less than 1e-10
|
|
err = "Error: expected a positive float for keyword {} in file {}".format(key, self.infile)
|
|
try:
|
|
new_value = float(value[0])
|
|
if new_value < 1e-10:
|
|
sys.exit(err)
|
|
else:
|
|
setattr(self.dice, key, new_value)
|
|
except ValueError:
|
|
sys.exit(err)
|
|
|
|
elif key == 'nmol': # If defined, must be well defined (only positive integer values)
|
|
err = "Error: expected 1 to 4 positive integers for keyword {} in file {}".format(key, self.infile)
|
|
args = min(4, len(value))
|
|
for i in range(args):
|
|
if value[i].isdigit():
|
|
new_value = int(value[i])
|
|
if new_value < 1:
|
|
sys.exit(err)
|
|
else:
|
|
setattr(self.dice, key, new_value)
|
|
elif i == 0:
|
|
sys.exit(err)
|
|
else:
|
|
break
|
|
|
|
elif key == 'nstep': # If defined, must be well defined (only positive integer values)
|
|
err = "Error: expected 2 or 3 positive integers for keyword {} in file {}".format(key, self.infile)
|
|
if len(value) < 2:
|
|
sys.exit(err)
|
|
args = min(3, len(value))
|
|
for i in range(args):
|
|
if value[i].isdigit():
|
|
new_value = int(value[i])
|
|
if new_value < 1:
|
|
sys.exit(err)
|
|
else:
|
|
setattr(self.dice, key, new_value)
|
|
elif i < 2:
|
|
sys.exit(err)
|
|
else:
|
|
break
|
|
|
|
#### Read the Gaussian related keywords
|
|
elif key in self.gaussian_keywords and len(value) != 0: ## 'value' is not empty!
|
|
|
|
if key == 'mem': # Memory in MB (minimum of 100)
|
|
err = "Error: expected a positive integer for keyword {} in file {}".format(key, self.infile)
|
|
if not value[0].isdigit():
|
|
sys.exit(err)
|
|
new_value = int(value[0])
|
|
if new_value >= 100:
|
|
setattr(self.gaussian, key, new_value)
|
|
|
|
elif key == 'keywords':
|
|
setattr(self.gaussian, key, value)
|
|
|
|
elif key == 'chgmult': # If defined, must be well defined (2 integer values)
|
|
err = "Error: expected 2 integers for keyword {} in file {}".format(key, self.infile)
|
|
if len(value) < 2:
|
|
sys.exit(err)
|
|
for i in range (2):
|
|
try:
|
|
setattr(self.gaussian, key)[i] = int(value[i])
|
|
except ValueError:
|
|
sys.exit(err)
|
|
|
|
elif key in ('level', 'chglevel'):
|
|
setattr(self.gaussian, key, value[0])
|
|
|
|
elif key in ('gmiddle', 'gbottom'):
|
|
setattr(self.gaussian, key, value[0])
|
|
|
|
elif key == 'pop' and value[0].lower() in ("chelpg", "mk", "nbo"):
|
|
setattr(self.gaussian, key, value[0].lower())
|
|
|
|
#### Read the Molcas related keywords
|
|
elif key in self.molcas_keywords and len(value) != 0: ## 'value' is not empty!
|
|
|
|
if key == 'root': # If defined, must be well defined (only positive integer values)
|
|
err = "Error: expected a positive integer for keyword {} in file {}".format(key, infile)
|
|
if not value[0].isdigit():
|
|
sys.exit(err)
|
|
new_value = int(value[0])
|
|
if new_value >= 1:
|
|
setattr(self.molcas, key, new_value)
|
|
|
|
elif key in ('mbottom', 'orbfile'):
|
|
setattr(self.molcas, key, value[0])
|
|
|
|
elif key == 'basis':
|
|
setattr(self.molcas ,key, value[0])
|
|
|
|
#### End
|
|
|
|
class Player:
|
|
|
|
def __init__(self):
|
|
|
|
self.maxcyc = None
|
|
self.initcyc = 1
|
|
self.nprocs = 1
|
|
self.switchcyc = 3
|
|
self.altsteps = 20000
|
|
self.maxstep = .3
|
|
self.qmprog = "g09"
|
|
self.opt = "yes"
|
|
self.freq = "no"
|
|
self.readhessian = "no"
|
|
self.lps = "no"
|
|
self.ghosts = "no"
|
|
self.vdwforces = "no"
|
|
self.tol_factor = 1.2
|
|
|
|
|
|
|
|
class Dice:
|
|
|
|
def __init__(self):
|
|
|
|
self.title = "Diceplayer run"
|
|
self.progname = "dice"
|
|
self.temp = 300.0
|
|
self.press = 1.0
|
|
self.isave = 1000 # ASEC construction will take this into account
|
|
self.ncores = 1
|
|
|
|
self.dens = None # Investigate the possibility of using 'box = Lx Ly Lz' instead.
|
|
#dice['box'] = None # So 'geom' would be set by diceplayer and 'cutoff' would be
|
|
# switched off. One of them must be given.
|
|
self.ljname = None
|
|
self.outname = None
|
|
self.nmol = [] # Up to 4 integer values related to up to 4 molecule types
|
|
self.nstep = [] # 2 or 3 integer values related to 2 or 3 simulations
|
|
# (NVT th + NVT eq) or (NVT th + NPT th + NPT eq).
|
|
# This will control the 'nstep' keyword of Dice
|
|
|
|
|
|
class Gaussian:
|
|
|
|
def __init__(self):
|
|
|
|
self.mem = None
|
|
self.keywords = None
|
|
self.chgmult = [0, 1]
|
|
self.gmiddle = None # In each case, if a filename is given, its content will be
|
|
self.gbottom = None # inserted in the gaussian input
|
|
self.pop = "chelpg"
|
|
self.chglevel = None
|
|
|
|
self.level = None
|
|
|
|
class Molcas:
|
|
|
|
def __init(self):
|
|
|
|
self.orbfile = "input.exporb"
|
|
self.root = 1
|
|
|
|
self.mbottom = None
|
|
self.basis = None |