Initial Folder Rework Implementation
Adds the Environment, External, Utils folder inside de DPpack. All classes are going to be implemented there
This commit is contained in:
830
diceplayer/DPpack/Player.py
Normal file
830
diceplayer/DPpack/Player.py
Normal file
@@ -0,0 +1,830 @@
|
||||
from diceplayer.DPpack.Utils.Validations import NotNull
|
||||
from diceplayer.DPpack.Utils.PTable import *
|
||||
from diceplayer.DPpack.Utils.Misc import *
|
||||
|
||||
from diceplayer.DPpack.External.Gaussian import Gaussian
|
||||
from diceplayer.DPpack.External.Dice import Dice
|
||||
|
||||
from diceplayer.DPpack.Environment.System import System
|
||||
from diceplayer.DPpack.Environment.Molecule import Molecule
|
||||
from diceplayer.DPpack.Environment.Atom import Atom
|
||||
|
||||
from typing import TextIO
|
||||
|
||||
import os
|
||||
import sys
|
||||
import shutil
|
||||
import textwrap
|
||||
import types
|
||||
import yaml
|
||||
|
||||
|
||||
env = ["OMP_STACKSIZE"]
|
||||
|
||||
|
||||
class Player:
|
||||
def __init__(self, infile: TextIO, outfile: TextIO) -> None:
|
||||
|
||||
self.infile = infile
|
||||
self.outfile = outfile
|
||||
|
||||
self.continued: bool = None
|
||||
|
||||
self.system = System()
|
||||
|
||||
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 = Dice(infile, outfile)
|
||||
self.dice_keywords = [
|
||||
a
|
||||
for a in dir(self.dice)
|
||||
if not a.startswith("__") and not callable(getattr(self.dice, a))
|
||||
]
|
||||
|
||||
self.gaussian = Gaussian()
|
||||
self.gaussian_keywords = [
|
||||
a
|
||||
for a in dir(self.gaussian)
|
||||
if not a.startswith("__") and not callable(getattr(self.gaussian, a))
|
||||
]
|
||||
|
||||
self.TOL_RMS_FORCE = 3e-4
|
||||
self.TOL_MAX_FORCE = 4.5e-4
|
||||
self.TOL_RMS_STEP = 1.2e-3
|
||||
self.TOL_MAX_SET = 1.8e-3
|
||||
self.TRUST_RADIUS = None
|
||||
|
||||
self.combrule = None
|
||||
|
||||
|
||||
@NotNull(requiredArgs=["maxcyc", "opt", "nprocs", "qmprog", "lps", "ghosts", "altsteps"])
|
||||
def updateKeywords(self, **data):
|
||||
self.__dict__.update(data)
|
||||
|
||||
def read_keywords(self) -> None:
|
||||
|
||||
with self.infile as f:
|
||||
data = yaml.load(f, Loader=yaml.SafeLoader)
|
||||
|
||||
self.updateKeywords(data.get("diceplayer"))
|
||||
self.dice.updateKeywords(data.get("dice"))
|
||||
self.gaussian.updateKeywords(data.get("gaussian"))
|
||||
|
||||
def check_keywords(self) -> None:
|
||||
|
||||
min_steps = 20000
|
||||
|
||||
if self.dice.ljname == None:
|
||||
sys.exit(
|
||||
"Error: 'ljname' keyword not specified in file {}".format(self.infile)
|
||||
)
|
||||
|
||||
if self.dice.outname == None:
|
||||
sys.exit(
|
||||
"Error: 'outname' keyword not specified in file {}".format(self.infile)
|
||||
)
|
||||
|
||||
if self.dice.dens == None:
|
||||
sys.exit(
|
||||
"Error: 'dens' keyword not specified in file {}".format(self.infile)
|
||||
)
|
||||
|
||||
if self.dice.nmol == 0:
|
||||
sys.exit(
|
||||
"Error: 'nmol' keyword not defined appropriately in file {}".format(
|
||||
self.infile
|
||||
)
|
||||
)
|
||||
|
||||
if self.dice.nstep == 0:
|
||||
sys.exit(
|
||||
"Error: 'nstep' keyword not defined appropriately in file {}".format(
|
||||
self.infile
|
||||
)
|
||||
)
|
||||
|
||||
# Check only if QM program is Gaussian:
|
||||
if self.player.qmprog in ("g03", "g09", "g16"):
|
||||
|
||||
if self.gaussian.level == None:
|
||||
sys.exit(
|
||||
"Error: 'level' keyword not specified in file {}".format(
|
||||
self.infile
|
||||
)
|
||||
)
|
||||
|
||||
if self.gaussian.gmiddle != None:
|
||||
if not os.path.isfile(self.gaussian.gmiddle):
|
||||
sys.exit("Error: file {} not found".format(self.gaussian.gmiddle))
|
||||
|
||||
if self.gaussian.gbottom != None:
|
||||
if not os.path.isfile(self.gaussian.gbottom):
|
||||
sys.exit("Error: file {} not found".format(self.gaussian.gbottom))
|
||||
|
||||
if self.gaussian.pop != "chelpg" and (
|
||||
self.player.ghosts == "yes" or self.player.lps == "yes"
|
||||
):
|
||||
sys.exit(
|
||||
"Error: ghost atoms or lone pairs only available with 'pop = chelpg')"
|
||||
)
|
||||
|
||||
# Check only if QM program is Molcas:
|
||||
# if self.player.qmprog == "molcas":
|
||||
|
||||
# if self.molcas.mbottom == None:
|
||||
# sys.exit("Error: 'mbottom' keyword not specified in file {}".format(self.infile))
|
||||
# else:
|
||||
# if not os.path.isfile(self.molcas.mbottom):
|
||||
# sys.exit("Error: file {} not found".format(self.molcas.mbottom))
|
||||
|
||||
# if self.molcas.basis == None:
|
||||
# sys.exit("Error: 'basis' keyword not specified in file {}".format(self.infile))
|
||||
|
||||
if self.player.altsteps != 0:
|
||||
|
||||
# Verifica se tem mais de 1 molecula QM
|
||||
# (No futuro usar o RMSD fit para poder substituir todas as moleculas QM
|
||||
# no arquivo outname.xy - Need to change the __make_init_file!!)
|
||||
if self.dice.nmol[0] > 1:
|
||||
sys.exit(
|
||||
"Error: altsteps > 0 only possible with 1 QM molecule (nmol = 1 n2 n3 n4)"
|
||||
)
|
||||
|
||||
# if not zero, altsteps cannot be less than min_steps
|
||||
self.player.altsteps = max(min_steps, self.player.altsteps)
|
||||
# altsteps value is always the nearest multiple of 1000
|
||||
self.player.altsteps = round(self.player.altsteps / 1000) * 1000
|
||||
|
||||
for i in range(len(self.dice.nstep)):
|
||||
# nstep can never be less than min_steps
|
||||
self.dice.nstep[i] = max(min_steps, self.dice.nstep[i])
|
||||
# nstep values are always the nearest multiple of 1000
|
||||
self.dice.nstep[i] = round(self.dice.nstep[i] / 1000) * 1000
|
||||
|
||||
# isave must be between 100 and 2000
|
||||
self.dice.isave = max(100, self.dice.isave)
|
||||
self.dice.isave = min(2000, self.dice.isave)
|
||||
# isave value is always the nearest multiple of 100
|
||||
self.dice.isave = round(self.dice.isave / 100) * 100
|
||||
|
||||
def print_keywords(self) -> None:
|
||||
|
||||
self.outfile.write(
|
||||
"##########################################################################################\n"
|
||||
"############# Welcome to DICEPLAYER version 1.0 #############\n"
|
||||
"##########################################################################################\n"
|
||||
"\n"
|
||||
)
|
||||
self.outfile.write("Your python version is {}\n".format(sys.version))
|
||||
self.outfile.write("\n")
|
||||
self.outfile.write("Program started on {}\n".format(weekday_date_time()))
|
||||
self.outfile.write("\n")
|
||||
self.outfile.write("Environment variables:\n")
|
||||
for var in env:
|
||||
self.outfile.write(
|
||||
"{} = {}\n".format(
|
||||
var, (os.environ[var] if var in os.environ else "Not set")
|
||||
)
|
||||
)
|
||||
|
||||
self.outfile.write(
|
||||
"\n==========================================================================================\n"
|
||||
" CONTROL variables being used in this run:\n"
|
||||
"------------------------------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
)
|
||||
|
||||
for key in sorted(self.player_keywords):
|
||||
if getattr(self.player, key) != None:
|
||||
if isinstance(getattr(self.player, key), list):
|
||||
string = " ".join(str(x) for x in getattr(self.player, key))
|
||||
self.outfile.write("{} = {}\n".format(key, string))
|
||||
else:
|
||||
self.outfile.write(
|
||||
"{} = {}\n".format(key, getattr(self.player, key))
|
||||
)
|
||||
|
||||
self.outfile.write("\n")
|
||||
|
||||
self.outfile.write(
|
||||
"------------------------------------------------------------------------------------------\n"
|
||||
" DICE variables being used in this run:\n"
|
||||
"------------------------------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
)
|
||||
|
||||
for key in sorted(self.dice_keywords):
|
||||
if getattr(self.dice, key) != None:
|
||||
if isinstance(getattr(self.dice, key), list):
|
||||
string = " ".join(str(x) for x in getattr(self.dice, key))
|
||||
self.outfile.write("{} = {}\n".format(key, string))
|
||||
else:
|
||||
self.outfile.write("{} = {}\n".format(key, getattr(self.dice, key)))
|
||||
|
||||
self.outfile.write("\n")
|
||||
|
||||
if self.player.qmprog in ("g03", "g09", "g16"):
|
||||
|
||||
self.outfile.write(
|
||||
"------------------------------------------------------------------------------------------\n"
|
||||
" GAUSSIAN variables being used in this run:\n"
|
||||
"------------------------------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
)
|
||||
|
||||
for key in sorted(self.gaussian_keywords):
|
||||
if getattr(self.gaussian, key) != None:
|
||||
if isinstance(getattr(self.gaussian, key), list):
|
||||
string = " ".join(str(x) for x in getattr(self.gaussian, key))
|
||||
self.outfile.write("{} = {}\n".format(key, string))
|
||||
else:
|
||||
self.outfile.write(
|
||||
"{} = {}\n".format(key, getattr(self.gaussian, key))
|
||||
)
|
||||
|
||||
self.outfile.write("\n")
|
||||
|
||||
# elif self.player.qmprog == "molcas":
|
||||
|
||||
# self.outfile.write("------------------------------------------------------------------------------------------\n"
|
||||
# " MOLCAS variables being used in this run:\n"
|
||||
# "------------------------------------------------------------------------------------------\n"
|
||||
# "\n")
|
||||
|
||||
# for key in sorted(molcas):
|
||||
# if molcas[key] != None:
|
||||
# if isinstance(molcas[key], list):
|
||||
# string = " ".join(str(x) for x in molcas[key])
|
||||
# self.outfile.write("{} = {}\n".format(key, string))
|
||||
# else:
|
||||
# self.outfile.write("{} = {}\n".format(key, molcas[key]))
|
||||
|
||||
# self.outfile.write("\n")
|
||||
|
||||
def read_potential(self) -> None: # Deve ser atualizado para o uso de
|
||||
|
||||
try:
|
||||
with open(self.dice.ljname) as file:
|
||||
ljfile = file.readlines()
|
||||
except EnvironmentError as err:
|
||||
sys.exit(err)
|
||||
|
||||
combrule = ljfile.pop(0).split()[0]
|
||||
if combrule not in ("*", "+"):
|
||||
sys.exit(
|
||||
"Error: expected a '*' or a '+' sign in 1st line of file {}".format(
|
||||
self.dice.ljname
|
||||
)
|
||||
)
|
||||
self.dice.combrule = combrule
|
||||
|
||||
ntypes = ljfile.pop(0).split()[0]
|
||||
if not ntypes.isdigit():
|
||||
sys.exit(
|
||||
"Error: expected an integer in the 2nd line of file {}".format(
|
||||
self.dice.ljname
|
||||
)
|
||||
)
|
||||
ntypes = int(ntypes)
|
||||
|
||||
if ntypes != len(self.dice.nmol):
|
||||
sys.exit(
|
||||
"Error: number of molecule types in file {} must match that of 'nmol' keyword in file {}".format(
|
||||
self.dice.ljname, self.infile
|
||||
)
|
||||
)
|
||||
line = 2
|
||||
for i in range(ntypes):
|
||||
|
||||
line += 1
|
||||
nsites, molname = ljfile.pop(0).split()[:2]
|
||||
|
||||
if not nsites.isdigit():
|
||||
sys.exit(
|
||||
"Error: expected an integer in line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
|
||||
if molname is None:
|
||||
sys.exit(
|
||||
"Error: expected a molecule name in line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
|
||||
nsites = int(nsites)
|
||||
|
||||
self.system.add_type(nsites, Molecule(molname))
|
||||
|
||||
for j in range(nsites):
|
||||
|
||||
line += 1
|
||||
new_atom = ljfile.pop(0).split()
|
||||
|
||||
if len(new_atom) < 8:
|
||||
sys.exit(
|
||||
"Error: expected at least 8 fields in line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
|
||||
if not new_atom[0].isdigit():
|
||||
sys.exit(
|
||||
"Error: expected an integer in field 1, line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
lbl = int(new_atom[0])
|
||||
|
||||
if not new_atom[1].isdigit():
|
||||
sys.exit(
|
||||
"Error: expected an integer in field 2, line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
|
||||
atnumber = int(new_atom[1])
|
||||
if (
|
||||
atnumber == ghost_number and i == 0
|
||||
): # Ghost atom not allowed in the QM molecule
|
||||
sys.exit(
|
||||
"Error: found a ghost atom in line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
na = atnumber
|
||||
|
||||
try:
|
||||
rx = float(new_atom[2])
|
||||
except:
|
||||
sys.exit(
|
||||
"Error: expected a float in field 3, line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
ry = float(new_atom[3])
|
||||
except:
|
||||
sys.exit(
|
||||
"Error: expected a float in field 4, line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
rz = float(new_atom[4])
|
||||
except:
|
||||
sys.exit(
|
||||
"Error: expected a float in field 5, line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
chg = float(new_atom[5])
|
||||
except:
|
||||
sys.exit(
|
||||
"Error: expected a float in field 6, line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
eps = float(new_atom[6])
|
||||
except:
|
||||
sys.exit(
|
||||
"Error: expected a float in field 7, line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
sig = float(new_atom[7])
|
||||
except:
|
||||
sys.exit(
|
||||
"Error: expected a float in field 8, line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
|
||||
mass = atommass[na]
|
||||
|
||||
if len(new_atom) > 8:
|
||||
masskey, mass = new_atom[8].partition("=")[::2]
|
||||
if masskey.lower() == "mass" and len(mass) != 0:
|
||||
try:
|
||||
new_mass = float(mass)
|
||||
if new_mass > 0:
|
||||
mass = new_mass
|
||||
except:
|
||||
sys.exit(
|
||||
"Error: expected a positive float after 'mass=' in field 9, line {} of file {}".format(
|
||||
line, self.dice.ljname
|
||||
)
|
||||
)
|
||||
|
||||
self.system.molecule[i].add_atom(
|
||||
Atom(lbl, na, rx, ry, rz, chg, eps, sig)
|
||||
)
|
||||
|
||||
to_delete = ["lbl", "na", "rx", "ry", "rz", "chg", "eps", "sig", "mass"]
|
||||
for _var in to_delete:
|
||||
if _var in locals() or _var in globals():
|
||||
exec(f"del {_var}")
|
||||
|
||||
def print_potential(self) -> None:
|
||||
|
||||
formatstr = "{:<3d} {:>3d} {:>10.5f} {:>10.5f} {:>10.5f} {:>10.6f} {:>9.5f} {:>7.4f} {:>9.4f}\n"
|
||||
self.outfile.write(
|
||||
"\n"
|
||||
"==========================================================================================\n"
|
||||
)
|
||||
self.outfile.write(
|
||||
" Potential parameters from file {}:\n".format(
|
||||
self.dice.ljname
|
||||
)
|
||||
)
|
||||
self.outfile.write(
|
||||
"------------------------------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
)
|
||||
|
||||
self.outfile.write("Combination rule: {}\n".format(self.dice.combrule))
|
||||
self.outfile.write(
|
||||
"Types of molecules: {}\n\n".format(len(self.system.molecule))
|
||||
)
|
||||
|
||||
i = 0
|
||||
for mol in self.system.molecule:
|
||||
i += 1
|
||||
self.outfile.write(
|
||||
"{} atoms in molecule type {}:\n".format(len(mol.atom), i)
|
||||
)
|
||||
self.outfile.write(
|
||||
"---------------------------------------------------------------------------------\n"
|
||||
"Lbl AN X Y Z Charge Epsilon Sigma Mass\n"
|
||||
)
|
||||
self.outfile.write(
|
||||
"---------------------------------------------------------------------------------\n"
|
||||
)
|
||||
|
||||
for atom in mol.atom:
|
||||
|
||||
self.outfile.write(
|
||||
formatstr.format(
|
||||
atom.lbl,
|
||||
atom.na,
|
||||
atom.rx,
|
||||
atom.ry,
|
||||
atom.rz,
|
||||
atom.chg,
|
||||
atom.eps,
|
||||
atom.sig,
|
||||
atom.mass,
|
||||
)
|
||||
)
|
||||
|
||||
self.outfile.write("\n")
|
||||
|
||||
if self.player.ghosts == "yes" or self.player.lps == "yes":
|
||||
self.outfile.write(
|
||||
"\n"
|
||||
"------------------------------------------------------------------------------------------\n"
|
||||
" Aditional potential parameters:\n"
|
||||
"------------------------------------------------------------------------------------------\n"
|
||||
)
|
||||
|
||||
# if player['ghosts'] == "yes":
|
||||
|
||||
# self.outfile.write("\n")
|
||||
# self.outfile.write("{} ghost atoms appended to molecule type 1 at:\n".format(len(ghost_types)))
|
||||
# self.outfile.write("---------------------------------------------------------------------------------\n")
|
||||
|
||||
# atoms_string = ""
|
||||
# for ghost in ghost_types:
|
||||
# for atom in ghost['numbers']:
|
||||
# atom_sym = atomsymb[ molecules[0][atom - 1]['na'] ].strip()
|
||||
# atoms_string += "{}{} ".format(atom_sym,atom)
|
||||
|
||||
# if ghost['type'] == "g":
|
||||
# self.outfile.write(textwrap.fill("* Geometric center of atoms {}".format(atoms_string), 80))
|
||||
# elif ghost['type'] == "m":
|
||||
# self.outfile.write(textwrap.fill("* Center of mass of atoms {}".format(atoms_string), 80))
|
||||
# elif ghost['type'] == "z":
|
||||
# self.outfile.write(textwrap.fill("* Center of atomic number of atoms {}".format(atoms_string), 80))
|
||||
|
||||
# self.outfile.write("\n")
|
||||
|
||||
# if player['lps'] == 'yes':
|
||||
|
||||
# self.outfile.write("\n")
|
||||
# self.outfile.write("{} lone pairs appended to molecule type 1:\n".format(len(lp_types)))
|
||||
# self.outfile.write("---------------------------------------------------------------------------------\n")
|
||||
|
||||
# for lp in lp_types:
|
||||
# # LP type 1 or 2
|
||||
# if lp['type'] in (1, 2):
|
||||
# atom1_num = lp['numbers'][0]
|
||||
# atom1_sym = atomsymb[ molecules[0][atom1_num - 1]['na'] ].strip()
|
||||
# atom2_num = lp['numbers'][1]
|
||||
# atom2_sym = atomsymb[ molecules[0][atom2_num - 1]['na'] ].strip()
|
||||
# atom3_num = lp['numbers'][2]
|
||||
# atom3_sym = atomsymb[ molecules[0][atom3_num - 1]['na'] ].strip()
|
||||
|
||||
# self.outfile.write(textwrap.fill(
|
||||
# "* Type {} on atom {}{} with {}{} {}{}. Alpha = {:<5.1f} Deg and D = {:<4.2f} Angs".format(
|
||||
# lp['type'], atom1_sym, atom1_num, atom2_sym, atom2_num, atom3_sym, atom3_num, lp['alpha'],
|
||||
# lp['dist']), 86))
|
||||
# self.outfile.write("\n")
|
||||
|
||||
# # Other LP types
|
||||
|
||||
self.outfile.write(
|
||||
"\n"
|
||||
"==========================================================================================\n"
|
||||
)
|
||||
|
||||
def check_executables(self) -> None:
|
||||
|
||||
self.outfile.write("\n")
|
||||
self.outfile.write(90 * "=")
|
||||
self.outfile.write("\n\n")
|
||||
|
||||
dice_path = shutil.which(self.dice.progname)
|
||||
if dice_path != None:
|
||||
self.outfile.write(
|
||||
"Program {} found at {}\n".format(self.dice.progname, dice_path)
|
||||
)
|
||||
self.dice.path = dice_path
|
||||
else:
|
||||
sys.exit("Error: cannot find dice executable")
|
||||
|
||||
qmprog_path = shutil.which(self.gaussian.qmprog)
|
||||
if qmprog_path != None:
|
||||
self.outfile.write(
|
||||
"Program {} found at {}\n".format(self.gaussian.qmprog, qmprog_path)
|
||||
)
|
||||
self.gaussian.path = qmprog_path
|
||||
else:
|
||||
sys.exit("Error: cannot find {} executable".format(self.gaussian.qmprog))
|
||||
|
||||
if self.gaussian.qmprog in ("g03", "g09", "g16"):
|
||||
formchk_path = shutil.which("formchk")
|
||||
if formchk_path != None:
|
||||
self.outfile.write("Program formchk found at {}\n".format(formchk_path))
|
||||
else:
|
||||
sys.exit("Error: cannot find formchk executable")
|
||||
|
||||
def dice_start(self, cycle: int):
|
||||
|
||||
self.dice.configure(
|
||||
self.player.initcyc,
|
||||
self.player.nprocs,
|
||||
self.player.altsteps,
|
||||
self.system.nmols,
|
||||
self.system.molecule,
|
||||
)
|
||||
|
||||
self.dice.start(cycle)
|
||||
|
||||
self.dice.reset()
|
||||
|
||||
def gaussian_start(self, cycle: int, geomsfh: TextIO):
|
||||
|
||||
self.gaussian.configure(
|
||||
self.player.initcyc,
|
||||
self.player.nprocs,
|
||||
self.dice.ncores,
|
||||
self.player.altsteps,
|
||||
self.player.switchcyc,
|
||||
self.player.opt,
|
||||
self.system.nmols,
|
||||
self.system.molecule,
|
||||
)
|
||||
|
||||
position = self.gaussian.start(cycle, self.outfile, self.player.readhessian)
|
||||
|
||||
## Update the geometry of the reference molecule
|
||||
self.system.update_molecule(position, self.outfile)
|
||||
|
||||
## Print new geometry in geoms.xyz
|
||||
self.system.print_geom(cycle, geomsfh)
|
||||
|
||||
self.gaussian.reset()
|
||||
|
||||
# I still have to talk with Herbet about this function
|
||||
def populate_asec_vdw(self, cycle):
|
||||
|
||||
# Both asec_charges and vdw_meanfield will utilize the Molecule() class and Atoms() with some None elements
|
||||
|
||||
asec_charges = Molecule(
|
||||
"ASEC_CHARGES"
|
||||
) # (lbl=None, na=None, rx, ry, rz, chg, eps=None, sig=None)
|
||||
# vdw_meanfield = (
|
||||
# Molecule()
|
||||
# ) # (lbl=None, na=None, rx, ry, rz, chg=None, eps, sig)
|
||||
|
||||
if self.dice.nstep[-1] % self.dice.isave == 0:
|
||||
nconfigs = round(self.dice.nstep[-1] / self.dice.isave)
|
||||
else:
|
||||
nconfigs = int(self.dice.nstep[-1] / self.dice.isave)
|
||||
|
||||
norm_factor = nconfigs * self.player.nprocs
|
||||
|
||||
nsitesref = len(self.system.molecule[0].atom)
|
||||
# nsitesref = (
|
||||
# len(self.system.molecule[0].atom)
|
||||
# + len(self.system.molecule[0].ghost_atoms)
|
||||
# + len(self.system.molecule[0].lp_atoms)
|
||||
# )
|
||||
|
||||
nsites_total = self.dice.nmol[0] * nsitesref
|
||||
for i in range(1, len(self.dice.nmol)):
|
||||
nsites_total += self.dice.nmol[i] * len(self.system.molecule[i].atom)
|
||||
|
||||
thickness = []
|
||||
picked_mols = []
|
||||
|
||||
for proc in range(1, self.player.nprocs + 1): # Run over folders
|
||||
|
||||
simdir = "simfiles"
|
||||
path = (
|
||||
simdir
|
||||
+ os.sep
|
||||
+ "step{:02d}".format(cycle)
|
||||
+ os.sep
|
||||
+ "p{:02d}".format(proc)
|
||||
)
|
||||
file = path + os.sep + self.dice.outname + ".xyz"
|
||||
if not os.path.isfile(file):
|
||||
sys.exit("Error: cannot find file {}".format(file))
|
||||
try:
|
||||
with open(file) as xyzfh:
|
||||
xyzfile = xyzfh.readlines()
|
||||
except:
|
||||
sys.exit("Error: cannot open file {}".format(file))
|
||||
|
||||
for config in range(nconfigs): # Run over configs in a folder
|
||||
|
||||
if int(xyzfile.pop(0).split()[0]) != nsites_total:
|
||||
sys.exit("Error: wrong number of sites in file {}".format(file))
|
||||
|
||||
box = xyzfile.pop(0).split()[-3:]
|
||||
box = [float(box[0]), float(box[1]), float(box[2])]
|
||||
sizes = self.system.molecule[0].sizes_of_molecule()
|
||||
thickness.append(
|
||||
min(
|
||||
[
|
||||
(box[0] - sizes[0]) / 2,
|
||||
(box[1] - sizes[1]) / 2,
|
||||
(box[2] - sizes[2]) / 2,
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
# Skip the first (reference) molecule
|
||||
xyzfile = xyzfile[nsitesref:]
|
||||
mol_count = 0
|
||||
for type in range(len(self.dice.nmol)): # Run over types of molecules
|
||||
|
||||
if type == 0:
|
||||
nmols = self.dice.nmol[0] - 1
|
||||
else:
|
||||
nmols = self.dice.nmol[type]
|
||||
|
||||
for mol in range(nmols): # Run over molecules of each type
|
||||
|
||||
new_molecule = Molecule(self.system.molecule[type].molname)
|
||||
# Run over sites of each molecule
|
||||
for site in range(len(self.system.molecule[types].atom)):
|
||||
|
||||
# new_molecule.append({})
|
||||
line = xyzfile.pop(0).split()
|
||||
|
||||
if (
|
||||
line[0].title()
|
||||
!= atomsymb[
|
||||
self.system.molecule[type].atom[site].na.strip()
|
||||
]
|
||||
):
|
||||
sys.exit("Error reading file {}".format(file))
|
||||
|
||||
new_molecule.add_atom(
|
||||
Atom(
|
||||
self.system.molecule[type].atom[site].lbl,
|
||||
self.system.molecule[type].atom[site].na,
|
||||
self.system.molecule[type]
|
||||
.atom[site]
|
||||
.float(line[1]),
|
||||
self.system.molecule[type]
|
||||
.atom[site]
|
||||
.float(line[2]),
|
||||
self.system.molecule[type]
|
||||
.atom[site]
|
||||
.float(line[3]),
|
||||
self.system.molecule[type].atom[site].chg,
|
||||
self.system.molecule[type].atom[site].eps,
|
||||
self.system.molecule[type].atom[site].sig,
|
||||
)
|
||||
)
|
||||
|
||||
dist = self.system.molecule[0].minimum_distance(new_molecule)
|
||||
if dist < thickness[-1]:
|
||||
mol_count += 1
|
||||
for atom in new_molecule.atom:
|
||||
asec_charges.append({})
|
||||
# vdw_meanfield.append({})
|
||||
|
||||
asec_charges[-1]["rx"] = atom.rx
|
||||
asec_charges[-1]["ry"] = atom.ry
|
||||
asec_charges[-1]["rz"] = atom.rz
|
||||
asec_charges[-1]["chg"] = atom.chg / norm_factor
|
||||
|
||||
# if self.player.vdwforces == "yes":
|
||||
# vdw_meanfield[-1]["rx"] = atom["rx"]
|
||||
# vdw_meanfield[-1]["ry"] = atom["ry"]
|
||||
# vdw_meanfield[-1]["rz"] = atom["rz"]
|
||||
# vdw_meanfield[-1]["eps"] = atom["eps"]
|
||||
# vdw_meanfield[-1]["sig"] = atom["sig"]
|
||||
|
||||
# #### Read lines with ghosts or lps in molecules of type 0 (reference)
|
||||
# #### and, if dist < thickness, appends to asec
|
||||
# if type == 0:
|
||||
# for ghost in ghost_atoms:
|
||||
# line = xyzfile.pop(0).split()
|
||||
# if line[0] != dice_ghost_label:
|
||||
# sys.exit("Error reading file {}".format(file))
|
||||
# if dist < thickness[-1]:
|
||||
# asec_charges.append({})
|
||||
# asec_charges[-1]['rx'] = float(line[1])
|
||||
# asec_charges[-1]['ry'] = float(line[2])
|
||||
# asec_charges[-1]['rz'] = float(line[3])
|
||||
# asec_charges[-1]['chg'] = ghost['chg'] / norm_factor
|
||||
|
||||
# for lp in lp_atoms:
|
||||
# line = xyzfile.pop(0).split()
|
||||
# if line[0] != dice_ghost_label:
|
||||
# sys.exit("Error reading file {}".format(file))
|
||||
# if dist < thickness[-1]:
|
||||
# asec_charges.append({})
|
||||
# asec_charges[-1]['rx'] = float(line[1])
|
||||
# asec_charges[-1]['ry'] = float(line[2])
|
||||
# asec_charges[-1]['rz'] = float(line[3])
|
||||
# asec_charges[-1]['chg'] = lp['chg'] / norm_factor
|
||||
|
||||
picked_mols.append(mol_count)
|
||||
|
||||
self.outfile.write("Done\n")
|
||||
|
||||
string = "In average, {:^7.2f} molecules ".format(
|
||||
sum(picked_mols) / norm_factor
|
||||
)
|
||||
string += "were selected from each of the {} configurations ".format(
|
||||
len(picked_mols)
|
||||
)
|
||||
string += (
|
||||
"of the production simulations to form the ASEC, comprising a shell with "
|
||||
)
|
||||
string += "minimum thickness of {:>6.2f} Angstrom\n".format(
|
||||
sum(thickness) / norm_factor
|
||||
)
|
||||
|
||||
self.outfile.write(textwrap.fill(string, 86))
|
||||
self.outfile.write("\n")
|
||||
|
||||
otherfh = open("ASEC.dat", "w")
|
||||
for charge in asec_charges:
|
||||
otherfh.write(
|
||||
"{:>10.5f} {:>10.5f} {:>10.5f} {:>11.8f}\n".format(
|
||||
charge["rx"], charge["ry"], charge["rz"], charge["chg"]
|
||||
)
|
||||
)
|
||||
otherfh.close()
|
||||
|
||||
return asec_charges
|
||||
|
||||
class Player:
|
||||
def __init__(self) -> None:
|
||||
|
||||
self.maxcyc = None
|
||||
self.nprocs = 1
|
||||
self.switchcyc = 3
|
||||
self.altsteps = 20000
|
||||
self.maxstep = 0.3
|
||||
self.opt = "yes"
|
||||
self.freq = "no"
|
||||
self.readhessian = "no"
|
||||
self.lps = "no"
|
||||
self.ghosts = "no"
|
||||
self.vdwforces = "no"
|
||||
self.tol_factor = 1.2
|
||||
self.qmprog = "g16"
|
||||
|
||||
self.initcyc = 1
|
||||
Reference in New Issue
Block a user