diff --git a/diceplayer/DPpack/External/Dice.py b/diceplayer/DPpack/External/Dice.py index db6e259..cbf570a 100644 --- a/diceplayer/DPpack/External/Dice.py +++ b/diceplayer/DPpack/External/Dice.py @@ -1,24 +1,16 @@ -from dataclasses import dataclass -from diceplayer.DPpack.Utils.PTable import * -from diceplayer.DPpack.Utils.Misc import * - -from diceplayer.DPpack.Environment.Molecule import Molecule -from diceplayer.DPpack.Environment.Atom import Atom - -from typing import IO, Final, Tuple, List, TextIO, Union - -from numpy.core.numeric import partition -from numpy import random - -from multiprocessing import Process, connection -import subprocess -import setproctitle import os -import sys import shutil +import subprocess +import sys +from multiprocessing import Process, connection +from typing import Final, List, TextIO +import setproctitle +from diceplayer.DPpack.Utils.Misc import * +from diceplayer.DPpack.Utils.PTable import * +from diceplayer.DPpack.Utils.StepDTO import StepDTO from diceplayer.DPpack.Utils.Validations import NotNull - +from numpy import random DICE_END_FLAG: Final[str] = "End of simulation" DICE_FLAG_LINE: Final[int] = -2 @@ -26,18 +18,17 @@ UMAANG3_TO_GCM3: Final[float] = 1.6605 MAX_SEED: Final[int] = 4294967295 + class Dice: title = "Diceplayer run" progname = "dice" - - path = None - + nprocs: int = None randominit = "first" combrule = "*" ncores = 1 - + temp = 300.0 press = 1.0 isave = 1000 @@ -53,14 +44,7 @@ class Dice: self.infile = infile self.outfile = outfile - @NotNull(requiredArgs = [ - "ncores", - "nmol", - "dens", - "nstep", - "ljname", - "outname" - ]) + @NotNull(requiredArgs=["ncores", "nmol", "dens", "nstep", "ljname", "outname"]) def updateKeywords(self, **data): self.__dict__.update(data) @@ -86,9 +70,9 @@ class Dice: volume = float(box[-3]) * float(box[-2]) * float(box[-1]) total_mass = 0 - for i in range(len(self.molecule)): + for i in range(len(self.step.molecule)): - total_mass += self.molecule[i].total_mass * self.nmol[i] + total_mass += self.step.molecule[i].total_mass * self.step.nmol[i] density = (total_mass / volume) * UMAANG3_TO_GCM3 @@ -109,9 +93,9 @@ class Dice: except: sys.exit("Error: cannot open file {}".format(file)) - nsites = len(self.molecule[0].atom) * self.nmol[0] - for i in range(1, len(self.nmol)): - nsites += self.nmol[i] * len(self.molecule[i].atom) + nsites = len(self.step.molecule[0].atom) * self.step.nmol[0] + for i in range(1, len(self.step.nmol)): + nsites += self.step.nmol[i] * len(self.step.molecule[i].atom) nsites += 2 @@ -132,11 +116,11 @@ class Dice: num = time.time() num = (num - int(num)) * 1e6 - + num = int((num - int(num)) * 1e6) random.seed((os.getpid() * num) % (MAX_SEED + 1)) - if self.randominit == "first" and cycle > self.initcyc: + if self.randominit == "first" and cycle > self.step.initcyc: last_step_dir = "step{:02d}".format(cycle - 1) last_path = sim_dir + os.sep + last_step_dir + os.sep + proc_dir xyzfile = last_path + os.sep + "last.xyz" @@ -149,7 +133,7 @@ class Dice: elif len(self.nstep) == 3: - if self.randominit == "first" and cycle > self.initcyc: + if self.randominit == "first" and cycle > self.step.initcyc: self.dens = self.__new_density(cycle, proc) else: self.__make_nvt_ter(cycle, path) @@ -175,15 +159,15 @@ class Dice: fh.write("ljname = {}\n".format(self.ljname)) fh.write("outname = {}\n".format(self.outname)) - string = " ".join(str(x) for x in self.nmol) + string = " ".join(str(x) for x in self.step.nmol) fh.write("nmol = {}\n".format(string)) fh.write("dens = {}\n".format(self.dens)) fh.write("temp = {}\n".format(self.temp)) - if self.randominit == "first" and cycle > self.initcyc: + if self.randominit == "first" and cycle > self.step.initcyc: fh.write("init = yesreadxyz\n") - fh.write("nstep = {}\n".format(self.altsteps)) + fh.write("nstep = {}\n".format(self.step.altsteps)) else: fh.write("init = yes\n") fh.write("nstep = {}\n".format(self.nstep[0])) @@ -214,7 +198,7 @@ class Dice: fh.write("ljname = {}\n".format(self.ljname)) fh.write("outname = {}\n".format(self.outname)) - string = " ".join(str(x) for x in self.nmol) + string = " ".join(str(x) for x in self.step.nmol) fh.write("nmol = {}\n".format(string)) fh.write("dens = {}\n".format(self.dens)) @@ -226,7 +210,7 @@ class Dice: fh.write("accum = no\n") fh.write("iprint = 1\n") fh.write("isave = {}\n".format(self.isave)) - fh.write("irdf = {}\n".format(10 * self.nprocs)) + fh.write("irdf = {}\n".format(10 * self.step.nprocs)) seed = int(1e6 * random.random()) fh.write("seed = {}\n".format(seed)) @@ -246,16 +230,16 @@ class Dice: fh.write("ljname = {}\n".format(self.ljname)) fh.write("outname = {}\n".format(self.outname)) - string = " ".join(str(x) for x in self.nmol) + string = " ".join(str(x) for x in self.step.nmol) fh.write("nmol = {}\n".format(string)) fh.write("press = {}\n".format(self.press)) fh.write("temp = {}\n".format(self.temp)) - if self.randominit == "first" and cycle > self.initcyc: + if self.randominit == "first" and cycle > self.step.initcyc: fh.write("init = yesreadxyz\n") fh.write("dens = {:<8.4f}\n".format(self.dens)) - fh.write("vstep = {}\n".format(int(self.altsteps / 5))) + fh.write("vstep = {}\n".format(int(self.step.altsteps / 5))) else: fh.write("init = no\n") fh.write("vstep = {}\n".format(int(self.nstep[1] / 5))) @@ -285,7 +269,7 @@ class Dice: fh.write("ljname = {}\n".format(self.ljname)) fh.write("outname = {}\n".format(self.outname)) - string = " ".join(str(x) for x in self.nmol) + string = " ".join(str(x) for x in self.step.nmol) fh.write("nmol = {}\n".format(string)) fh.write("press = {}\n".format(self.press)) @@ -299,7 +283,7 @@ class Dice: fh.write("accum = no\n") fh.write("iprint = 1\n") fh.write("isave = {}\n".format(self.isave)) - fh.write("irdf = {}\n".format(10 * self.nprocs)) + fh.write("irdf = {}\n".format(10 * self.step.nprocs)) seed = int(1e6 * random.random()) fh.write("seed = {}\n".format(seed)) @@ -319,11 +303,11 @@ class Dice: sys.exit("Error: cannot open file {}".format(file)) nsites_mm = 0 - for i in range(1, len(self.nmol)): - nsites_mm += self.nmol[i] * len(self.molecule[i].atom) + for i in range(1, len(self.step.nmol)): + nsites_mm += self.step.nmol[i] * len(self.step.molecule[i].atom) nsites_mm *= -1 - + xyzfile = xyzfile[nsites_mm:] file = path + os.sep + self.outname + ".xy" @@ -333,7 +317,7 @@ class Dice: except: sys.exit("Error: cannot open file {}".format(file)) - for atom in self.molecule[0].atom: + for atom in self.step.molecule[0].atom: fh.write( "{:>10.6f} {:>10.6f} {:>10.6f}\n".format(atom.rx, atom.ry, atom.rz) ) @@ -360,16 +344,16 @@ class Dice: sys.exit("Error: cannot open file {}".format(file)) fh.write("{}\n".format(self.combrule)) - fh.write("{}\n".format(len(self.nmol))) + fh.write("{}\n".format(len(self.step.nmol))) nsites_qm = ( - len(self.molecule[0].atom) - + len(self.molecule[0].ghost_atoms) - + len(self.molecule[0].lp_atoms) + len(self.step.molecule[0].atom) + + len(self.step.molecule[0].ghost_atoms) + + len(self.step.molecule[0].lp_atoms) ) - fh.write("{} {}\n".format(nsites_qm, self.molecule[0].molname)) - for atom in self.molecule[0].atom: + fh.write("{} {}\n".format(nsites_qm, self.step.molecule[0].molname)) + for atom in self.step.molecule[0].atom: fh.write( fstr.format( atom.lbl, @@ -383,23 +367,23 @@ class Dice: ) ) - ghost_label = self.molecule[0].atom[-1].lbl + 1 - for i in self.molecule[0].ghost_atoms: + ghost_label = self.step.molecule[0].atom[-1].lbl + 1 + for i in self.step.molecule[0].ghost_atoms: fh.write( fstr.format( ghost_label, ghost_number, - self.molecule[0].atom[i].rx, - self.molecule[0].atom[i].ry, - self.molecule[0].atom[i].rz, - self.molecule[0].atom[i].chg, + self.step.molecule[0].atom[i].rx, + self.step.molecule[0].atom[i].ry, + self.step.molecule[0].atom[i].rz, + self.step.molecule[0].atom[i].chg, 0, 0, ) ) ghost_label += 1 - for lp in self.molecule[0].lp_atoms: + for lp in self.step.molecule[0].lp_atoms: fh.write( fstr.format( ghost_label, @@ -413,7 +397,7 @@ class Dice: ) ) - for mol in self.molecule[1:]: + for mol in self.step.molecule[1:]: fh.write("{} {}\n".format(len(mol.atom), mol.molname)) for atom in mol.atom: fh.write( @@ -462,7 +446,7 @@ class Dice: if len(self.nstep) == 2: - if self.randominit == "first" and cycle > self.initcyc: + if self.randominit == "first" and cycle > self.step.initcyc: string_tmp = "previous" else: string_tmp = "random" @@ -620,7 +604,7 @@ class Dice: ) if not self.randominit == "always" or ( - (self.randominit == "first" and cycle > self.initcyc) + (self.randominit == "first" and cycle > self.step.initcyc) ): string = " (from previous configuration) " else: @@ -735,28 +719,15 @@ class Dice: except Exception as err: sys.exit(err) - def configure( - self, - initcyc: int, - nprocs: int, - altsteps: int, - nmol: List[int], - molecule: List[Molecule], - ): - - self.initcyc = initcyc - - self.nprocs = nprocs - self.altsteps = altsteps - self.nmol = nmol - self.molecule = molecule + def configure(self, step: StepDTO): + self.step = step def start(self, cycle: int) -> None: procs = [] sentinels = [] - for proc in range(1, self.nprocs + 1): + for proc in range(1, self.step.nprocs + 1): p = Process(target=self.__simulation_process, args=(cycle, proc)) p.start() @@ -776,11 +747,8 @@ class Dice: p.terminate() sys.exit(status) - for proc in range(1, self.nprocs + 1): + for proc in range(1, self.step.nprocs + 1): self.__print_last_config(cycle, proc) def reset(self): - - del self.nprocs - del self.altsteps - del self.molecule + del self.step diff --git a/diceplayer/DPpack/External/Gaussian.py b/diceplayer/DPpack/External/Gaussian.py index 84e11e6..d589197 100644 --- a/diceplayer/DPpack/External/Gaussian.py +++ b/diceplayer/DPpack/External/Gaussian.py @@ -1,29 +1,23 @@ -from turtle import position -from diceplayer.DPpack.Environment.Atom import * -from diceplayer.DPpack.Utils.PTable import * -from diceplayer.DPpack.Utils.Misc import * - -from diceplayer.DPpack.External.Dice import * - -from diceplayer.DPpack.Environment.Molecule import Molecule -from diceplayer.DPpack.Environment.Atom import Atom - -from typing import IO, List, TextIO +import os +import shutil +import subprocess +import sys +import textwrap +from typing import TextIO import numpy as np -import subprocess -import os -import sys -import shutil -import textwrap -import types +from diceplayer.DPpack.Environment.Atom import Atom +from diceplayer.DPpack.Environment.Molecule import Molecule +from diceplayer.DPpack.Utils.Misc import * +from diceplayer.DPpack.Utils.PTable import * +from diceplayer.DPpack.Utils.StepDTO import StepDTO +from diceplayer.DPpack.Utils.Validations import NotNull class Gaussian: qmprog = "g09" - path = None mem = None keywords = None chgmult = [0, 1] @@ -35,9 +29,7 @@ class Gaussian: def __init__(self) -> None: pass - @NotNull(requiredArgs = [ - "level" - ]) + @NotNull(requiredArgs=["level"]) def updateKeywords(self, **data): self.__dict__.update(data) @@ -71,7 +63,7 @@ class Gaussian: while start.find("Cartesian Gradient") != 0: # expression in begining of line start = fchkfile.pop(0).strip() - degrees = 3 * len(self.molecule[0].atom) + degrees = 3 * len(self.step.molecule[0].atom) count = 0 while len(forces) < degrees: values = fchkfile.pop(0).split() @@ -90,11 +82,11 @@ class Gaussian: "Number Number X Y Z\n" "-----------------------------------------------------------------------\n" ) - for i in range(len(self.molecule[0].atom)): + for i in range(len(self.step.molecule[0].atom)): fh.write( " {:>5d} {:>3d} {:>14.9f} {:>14.9f} {:>14.9f}\n".format( i + 1, - self.molecule[0].atom[i].na, + self.step.molecule[0].atom[i].na, forces.pop(0), forces.pop(0), forces.pop(0), @@ -129,7 +121,7 @@ class Gaussian: while start.find("Cartesian Force Constants") != 0: start = fchkfile.pop(0).strip() - degrees = 3 * len(self.molecule[0].atom) + degrees = 3 * len(self.step.molecule[0].atom) last = round(degrees * (degrees + 1) / 2) count = 0 @@ -167,7 +159,7 @@ class Gaussian: while start.find("The second derivative matrix:") != 0: start = logfile.pop(0).strip() - degrees = 3 * len(self.molecule[0].atom) + degrees = 3 * len(self.step.molecule[0].atom) hessian = np.zeros((degrees, degrees)) k = 0 @@ -193,7 +185,7 @@ class Gaussian: fh.write("Optimization cycle: {}\n".format(cycle)) fh.write("Cartesian Gradient\n") - degrees = 3 * len(self.molecule[0].atom) + degrees = 3 * len(self.step.molecule[0].atom) for i in range(degrees): fh.write(" {:>11.8g}".format(cur_gradient[i])) if (i + 1) % 5 == 0 or i == degrees - 1: @@ -229,14 +221,14 @@ class Gaussian: fh.write("%Chk=asec.chk\n") if self.mem != None: fh.write("%Mem={}MB\n".format(self.mem)) - fh.write("%Nprocs={}\n".format(self.nprocs * self.ncores)) + fh.write("%Nprocs={}\n".format(self.step.nprocs * self.step.ncores)) kword_line = "#P " + str(self.level) if self.keywords != None: kword_line += " " + self.keywords - if self.opt == "yes": + if self.step.opt == "yes": kword_line += " Force" # kword_line += " Charge" @@ -253,7 +245,7 @@ class Gaussian: fh.write("\n") fh.write("{},{}\n".format(self.chgmult[0], self.chgmult[1])) - for atom in self.molecule[0].atom: + for atom in self.step.molecule[0].atom: symbol = atomsymb[atom.na] fh.write( "{:<2s} {:>10.5f} {:>10.5f} {:>10.5f}\n".format( @@ -330,7 +322,7 @@ class Gaussian: fh.write("\nAtomic charges:\n") fh.write("------------------------------------\n") - for atom in self.molecule[0].atom: + for atom in self.step.molecule[0].atom: line = glogfile.pop(0).split() atom_str = line[1] charge = float(line[2]) @@ -466,28 +458,9 @@ class Gaussian: # return step + def configure(self, step: StepDTO): - def configure( - self, - initcyc: int, - nprocs: int, - ncores: int, - altsteps: int, - switchcyc: int, - opt: str, - nmol: List[int], - molecule: List[Molecule], - ): - - self.initcyc = initcyc - - self.nprocs = nprocs - self.ncores = ncores - self.altsteps = altsteps - self.switchcyc = switchcyc - self.opt = opt - - self.molecule = molecule + self.step = step def start(self, cycle: int, outfile: TextIO, readhessian: str) -> np.ndarray: @@ -569,10 +542,8 @@ class Gaussian: # From 2nd step on, update the hessian else: - outfile.write( - "\nUpdating the hessian matrix using the BFGS method... " - ) - hessian = self.molecule[0].update_hessian( + outfile.write("\nUpdating the hessian matrix using the BFGS method... ") + hessian = self.step.molecule[0].update_hessian( step, gradient, old_gradient, hessian ) outfile.write("Done\n") @@ -586,7 +557,7 @@ class Gaussian: position += step ## If needed, calculate the charges - if cycle < self.switchcyc: + if cycle < self.step.switchcyc: # internal.gaussian.make_charge_input(cycle, asec_charges) self.run_gaussian(cycle, "charge", outfile) @@ -615,7 +586,7 @@ class Gaussian: ## Print new info for molecule[0] self.outfile.write("\nNew values for molecule type 1:\n\n") - self.molecule[0].print_mol_info(outfile) + self.step.molecule[0].print_mol_info(outfile) ## ## Molcas block @@ -683,6 +654,4 @@ class Gaussian: def reset(self): - del self.nprocs - del self.altsteps - del self.molecule + del self.step diff --git a/diceplayer/DPpack/Player.py b/diceplayer/DPpack/Player.py index 9aeb8d0..106a9e4 100644 --- a/diceplayer/DPpack/Player.py +++ b/diceplayer/DPpack/Player.py @@ -1,23 +1,21 @@ -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 sys import textwrap import types +from typing import TextIO + import yaml +from diceplayer.DPpack.Environment.Atom import Atom +from diceplayer.DPpack.Environment.Molecule import Molecule +from diceplayer.DPpack.Environment.System import System +from diceplayer.DPpack.External.Dice import Dice +from diceplayer.DPpack.External.Gaussian import Gaussian +from diceplayer.DPpack.Utils.Misc import * +from diceplayer.DPpack.Utils.PTable import * +from diceplayer.DPpack.Utils.StepDTO import StepDTO +from diceplayer.DPpack.Utils.Validations import NotNull env = ["OMP_STACKSIZE"] @@ -61,8 +59,9 @@ class Player: self.combrule = None - - @NotNull(requiredArgs=["maxcyc", "opt", "nprocs", "qmprog", "lps", "ghosts", "altsteps"]) + @NotNull( + requiredArgs=["maxcyc", "opt", "nprocs", "qmprog", "lps", "ghosts", "altsteps"] + ) def updateKeywords(self, **data): self.__dict__.update(data) @@ -585,11 +584,13 @@ class Player: def dice_start(self, cycle: int): self.dice.configure( - self.player.initcyc, - self.player.nprocs, - self.player.altsteps, - self.system.nmols, - self.system.molecule, + StepDTO( + self.player.initcyc, + self.player.nprocs, + self.player.altsteps, + self.system.nmols, + self.system.molecule, + ) ) self.dice.start(cycle) diff --git a/diceplayer/DPpack/Utils/StepDTO.py b/diceplayer/DPpack/Utils/StepDTO.py new file mode 100644 index 0000000..255a997 --- /dev/null +++ b/diceplayer/DPpack/Utils/StepDTO.py @@ -0,0 +1,17 @@ +from dataclasses import dataclass +from typing import List + +from diceplayer.DPpack.Environment.Molecule import Molecule + + +@dataclass +class StepDTO: + + initcyc: int + nprocs: int + ncores: int + altsteps: int + switchcyc: int + opt: str + nmol: List[int] + molecule: List[Molecule] \ No newline at end of file diff --git a/diceplayer/DPpack/Utils/Validations.py b/diceplayer/DPpack/Utils/Validations.py index 5381863..a25257c 100644 --- a/diceplayer/DPpack/Utils/Validations.py +++ b/diceplayer/DPpack/Utils/Validations.py @@ -12,4 +12,4 @@ def NotNull(requiredArgs=[]): return wrapper - return _NotNull + return _NotNull \ No newline at end of file diff --git a/diceplayer/__main__.py b/diceplayer/__main__.py index ae0e82b..e97041f 100644 --- a/diceplayer/__main__.py +++ b/diceplayer/__main__.py @@ -1,19 +1,21 @@ #!/usr/bin/python3 -from multiprocessing import Process, connection -import os, sys, time, signal -import setproctitle -import numpy as np import argparse -import shutil +import os import pickle +import shutil +import signal +import sys +import time +from multiprocessing import Process, connection -from diceplayer.DPpack.Utils.Misc import * +import numpy as np +import setproctitle -from diceplayer.DPpack.Player import Player - -from diceplayer.DPpack.Environment.Molecule import Molecule from diceplayer.DPpack.Environment.Atom import Atom +from diceplayer.DPpack.Environment.Molecule import Molecule +from diceplayer.DPpack.Player import Player +from diceplayer.DPpack.Utils.Misc import * __version = "dev" setproctitle.setproctitle("diceplayer-{}".format(__version))