Finishes DiceInterface Refactoring and Continues Tests Implementation

This commit is contained in:
2023-04-24 12:15:51 -03:00
parent b869ee74fb
commit 9202331852
19 changed files with 629 additions and 190 deletions

View File

@@ -1,21 +1,22 @@
diceplayer: diceplayer:
maxcyc: 3 maxcyc: 3
opt: no opt: no
ncores: 4
nprocs: 4 nprocs: 4
qmprog: 'g16' qmprog: 'g16'
lps: no lps: no
ghosts: no ghosts: no
altsteps: 20000
altsteps: 20000
dice: dice:
ncores: 3
nmol: [1, 50] nmol: [1, 50]
dens: 0.75 dens: 0.75
nstep: [2000, 3000] nstep: [2000, 3000, 4000]
isave: 1000 isave: 1000
outname: 'phb' outname: 'phb'
progname: '~/.local/bin/dice'
ljname: 'phb.ljc' ljname: 'phb.ljc'
randominit: 'always' randominit: 'first'
gaussian: gaussian:
qmprog: 'g16' qmprog: 'g16'

View File

@@ -1,4 +1,4 @@
from diceplayer.shared.external.dice import Dice from diceplayer.shared.interface.dice_interface import DiceInterface
from diceplayer.player import Player from diceplayer.player import Player
from pathlib import Path from pathlib import Path
@@ -7,7 +7,6 @@ import logging
import pickle import pickle
import sys import sys
__VERSION = "v0.0.1" __VERSION = "v0.0.1"
@@ -51,7 +50,7 @@ def main():
output_path = Path(args.outfile) output_path = Path(args.outfile)
if output_path.exists(): if output_path.exists():
output_path.rename(str(output_path)+".backup") output_path.rename(str(output_path) + ".backup")
except Exception as err: except Exception as err:
sys.exit(err) sys.exit(err)
@@ -66,5 +65,6 @@ def main():
player.start() player.start()
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@@ -1,3 +1,4 @@
from diceplayer.shared.config.step_dto import StepDTO
from diceplayer.shared.environment.atom import Atom from diceplayer.shared.environment.atom import Atom
from diceplayer.shared.utils.dataclass_protocol import Dataclass from diceplayer.shared.utils.dataclass_protocol import Dataclass
from diceplayer.shared.config.gaussian_dto import GaussianDTO from diceplayer.shared.config.gaussian_dto import GaussianDTO
@@ -5,9 +6,9 @@ from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.environment.system import System from diceplayer.shared.environment.system import System
from diceplayer.shared.utils.misc import weekday_date_time from diceplayer.shared.utils.misc import weekday_date_time
from diceplayer.shared.config.player_dto import PlayerDTO from diceplayer.shared.config.player_dto import PlayerDTO
from diceplayer.shared.external.gaussian import Gaussian from diceplayer.shared.interface.gaussian_interface import GaussianInterface
from diceplayer.shared.config.dice_dto import DiceDTO from diceplayer.shared.config.dice_dto import DiceDTO
from diceplayer.shared.external.dice import Dice from diceplayer.shared.interface.dice_interface import DiceInterface
from dataclasses import fields from dataclasses import fields
from pathlib import Path from pathlib import Path
@@ -39,8 +40,8 @@ class Player:
config_data.get("diceplayer") config_data.get("diceplayer")
) )
self.gaussian = Gaussian(config_data.get("gaussian")) self.gaussian = GaussianInterface(config_data.get("gaussian"))
self.dice = Dice(config_data.get("dice")) self.dice = DiceInterface(config_data.get("dice"))
def start(self): def start(self):
self.print_keywords() self.print_keywords()
@@ -50,6 +51,9 @@ class Player:
self.read_potentials() self.read_potentials()
# self.print_potentials() # self.print_potentials()
self.dice_start(1)
self.dice_start(2)
def create_simulation_dir(self): def create_simulation_dir(self):
simulation_dir_path = Path(self.config.simulation_dir) simulation_dir_path = Path(self.config.simulation_dir)
if simulation_dir_path.exists(): if simulation_dir_path.exists():
@@ -140,7 +144,7 @@ class Player:
self.dice.config.ljname self.dice.config.ljname
) )
) )
self.dice.combrule = combrule self.dice.config.combrule = combrule
ntypes = ljdata.pop(0).split()[0] ntypes = ljdata.pop(0).split()[0]
if not ntypes.isdigit(): if not ntypes.isdigit():
@@ -184,8 +188,21 @@ class Player:
Atom(**self.validate_atom_dict(i, j, new_atom)) Atom(**self.validate_atom_dict(i, j, new_atom))
) )
def dice_start(self): def dice_start(self, cycle: int):
self.dice.start() self.dice.configure(
StepDTO(
ncores=self.config.ncores,
nprocs=self.config.nprocs,
simulation_dir=self.config.simulation_dir,
altsteps=self.config.altsteps,
molecule=self.system.molecule,
nmol=self.system.nmols,
)
)
self.dice.start(cycle)
self.dice.reset()
def gaussian_start(self): def gaussian_start(self):
self.gaussian.start() self.gaussian.start()

View File

@@ -7,10 +7,11 @@ from typing import List
@dataclass @dataclass
class DiceDTO(Dataclass): class DiceDTO(Dataclass):
"""
Data Transfer Object for the Dice configuration.
"""
ljname: str ljname: str
outname: str outname: str
ncores: int
dens: float dens: float
nmol: List[int] nmol: List[int]
nstep: List[int] nstep: List[int]
@@ -20,6 +21,7 @@ class DiceDTO(Dataclass):
isave: int = 1000 isave: int = 1000
press: float = 1.0 press: float = 1.0
temp: float = 300.0 temp: float = 300.0
progname: str = "dice"
randominit: str = 'first' randominit: str = 'first'
def __post_init__(self): def __post_init__(self):
@@ -44,7 +46,7 @@ class DiceDTO(Dataclass):
"Error: 'nmol' keyword not defined appropriately in config file" "Error: 'nmol' keyword not defined appropriately in config file"
) )
if not isinstance(self.nstep, list): if not isinstance(self.nstep, list) or len(self.nstep) not in (2, 3):
raise ValueError( raise ValueError(
"Error: 'nstep' keyword not defined appropriately in config file" "Error: 'nstep' keyword not defined appropriately in config file"
) )

View File

@@ -6,6 +6,9 @@ from dacite import from_dict
@dataclass @dataclass
class GaussianDTO(Dataclass): class GaussianDTO(Dataclass):
"""
Data Transfer Object for the Gaussian configuration.
"""
level: str level: str
qmprog: str qmprog: str
keywords: str keywords: str

View File

@@ -6,9 +6,13 @@ from dacite import from_dict
@dataclass @dataclass
class PlayerDTO(Dataclass): class PlayerDTO(Dataclass):
"""
Data Transfer Object for the player configuration.
"""
opt: bool opt: bool
maxcyc: int maxcyc: int
nprocs: int nprocs: int
ncores: int
qmprog: str = 'g16' qmprog: str = 'g16'
altsteps: int = 20000 altsteps: int = 20000

View File

@@ -1,4 +1,5 @@
from diceplayer.shared.environment.molecule import Molecule from diceplayer.shared.environment.molecule import Molecule
from diceplayer.shared.config.player_dto import PlayerDTO
from dataclasses import dataclass from dataclasses import dataclass
from typing import List from typing import List
@@ -6,13 +7,16 @@ from typing import List
@dataclass @dataclass
class StepDTO: class StepDTO:
nprocs: int = None """
ncores: int = None Data Transfer Object for the step configuration.
altsteps: int = None """
switchcyc: int = None ncores: int
opt: str = None nprocs: int
simulation_dir: str
altsteps: int
nmol: List[int] = None nmol: List[int] = None
molecule: List[Molecule] = None molecule: List[Molecule] = None
charges: List[float] = None charges: List[float] = None
position: List[float] = None position: List[float] = None

View File

@@ -1 +0,0 @@
from .__external import External

View File

@@ -1,53 +0,0 @@
from diceplayer.shared.config.dice_dto import DiceDTO
from diceplayer.shared.external import External
from multiprocessing import Process, connection
from setproctitle import setproctitle
import sys
class Dice(External):
__slots__ = ['config', 'step']
def __init__(self, data: dict):
self.config: DiceDTO = self.set_config(data)
@staticmethod
def set_config(data: dict) -> DiceDTO:
return DiceDTO.from_dict(data)
def configure(self, step: any):
self.step = step
def start(self, cycle: int):
procs = [
Process(target=self._simulation_process, args=(cycle, proc))
for proc in range(1, self.config.ncores+1)
]
for proc in procs:
proc.start()
connection.wait(p.sentinel for p in procs)
def reset(self):
del self.step
def _simulation_process(self, cycle: int, proc: int):
setproctitle(f"diceplayer-step{cycle:0d}-p{proc:0d}")
try:
self._make_proc_dir(cycle, proc)
self._make_dice_inputs(cycle, proc)
self._run_dice(cycle, proc)
except Exception as err:
sys.exit(err)
def _make_proc_dir(self, cycle, proc):
raise NotImplementedError
def _make_dice_inputs(self, cycle, proc):
raise NotImplementedError
def _run_dice(self, cycle, proc):
raise NotImplementedError

View File

@@ -0,0 +1 @@
from .__interface import Interface

View File

@@ -3,7 +3,7 @@ from diceplayer.shared.utils.dataclass_protocol import Dataclass
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
class External(ABC): class Interface(ABC):
__slots__ = [ __slots__ = [
'config' 'config'
] ]

View File

@@ -0,0 +1,388 @@
from __future__ import annotations
from diceplayer.shared.config.dice_dto import DiceDTO
from diceplayer.shared.config.step_dto import StepDTO
from diceplayer.shared.interface import Interface
from multiprocessing import Process, connection
from setproctitle import setproctitle
from typing import Final, TextIO
from pathlib import Path
import subprocess
import shutil
import random
import time
import sys
import os
DICE_END_FLAG: Final[str] = "End of simulation"
DICE_FLAG_LINE: Final[int] = -2
UMAANG3_TO_GCM3: Final[float] = 1.6605
MAX_SEED: Final[int] = 4294967295
class DiceInterface(Interface):
__slots__ = ['config', 'step']
title = "Diceplayer run"
def __init__(self, data: dict):
self.config: DiceDTO = self.set_config(data)
self.step: StepDTO | None = None
@staticmethod
def set_config(data: dict) -> DiceDTO:
return DiceDTO.from_dict(data)
def configure(self, step: any):
self.step = step
def start(self, cycle: int):
procs = []
sentinels = []
for proc in range(1, self.step.nprocs + 1):
p = Process(target=self._simulation_process, args=(cycle, proc))
p.start()
procs.append(p)
sentinels.append(p.sentinel)
while procs:
finished = connection.wait(sentinels)
for proc_sentinel in finished:
i = sentinels.index(proc_sentinel)
status = procs[i].exitcode
procs.pop(i)
sentinels.pop(i)
if status != 0:
for p in procs:
p.terminate()
sys.exit(status)
def reset(self):
del self.step
def _simulation_process(self, cycle: int, proc: int):
setproctitle(f"diceplayer-step{cycle:0d}-p{proc:0d}")
try:
self._make_proc_dir(cycle, proc)
self._make_dice_inputs(cycle, proc)
self._run_dice(cycle, proc)
except Exception as err:
sys.exit(err)
def _make_proc_dir(self, cycle, proc):
simulation_dir = Path(self.step.simulation_dir)
if not simulation_dir.exists():
simulation_dir.mkdir(parents=True)
proc_dir = Path(
simulation_dir,
f"step{cycle:02d}",
f"p{proc:02d}"
)
proc_dir.mkdir(parents=True, exist_ok=True)
def _make_dice_inputs(self, cycle, proc):
proc_dir = Path(
self.step.simulation_dir,
f"step{cycle:02d}",
f"p{proc:02d}"
)
self._make_potentials(proc_dir)
random.seed(self._make_dice_seed())
# This is logic is used to make the initial configuration file
# for the next cycle using the last.xyz file from the previous cycle.
if self.config.randominit == 'first' and cycle > 1:
last_xyz = Path(
self.step.simulation_dir,
f"step{(cycle - 1):02d}",
f"p{proc:02d}",
"last.xyz"
)
if not last_xyz.exists():
raise FileNotFoundError(f"File {last_xyz} not found.")
with open(last_xyz, 'r') as last_xyz_file:
self._make_init_file(proc_dir, last_xyz_file)
last_xyz_file.seek(0)
self.config.dens = self._new_density(last_xyz_file)
else:
self._make_nvt_ter(cycle, proc_dir)
if len(self.config.nstep) == 2:
self._make_nvt_eq(proc_dir)
elif len(self.config.nstep) == 3:
self._make_npt_ter(cycle, proc_dir)
self._make_npt_eq(proc_dir)
def _run_dice(self, cycle: int, proc: int):
working_dir = os.getcwd()
proc_dir = Path(
self.step.simulation_dir,
f"step{cycle:02d}",
f"p{proc:02d}"
)
os.chdir(proc_dir)
if not (self.config.randominit == 'first' and cycle > 1):
self.run_dice_file(cycle, proc, "NVT.ter")
if len(self.config.nstep) == 2:
self.run_dice_file(cycle, proc, "NVT.eq")
elif len(self.config.nstep) == 3:
self.run_dice_file(cycle, proc, "NPT.ter")
self.run_dice_file(cycle, proc, "NPT.eq")
os.chdir(working_dir)
xyz_file = Path(proc_dir, "phb.xyz")
last_xyz_file = Path(proc_dir, "last.xyz")
if xyz_file.exists():
shutil.copy(xyz_file, last_xyz_file)
else:
raise FileNotFoundError(f"File {xyz_file} not found.")
@staticmethod
def _make_dice_seed() -> int:
num = time.time()
num = (num - int(num)) * 1e6
num = int((num - int(num)) * 1e6)
return (os.getpid() * num) % (MAX_SEED + 1)
def _make_init_file(self, proc_dir: Path, last_xyz_file: TextIO):
xyz_lines = last_xyz_file.readlines()
nsites_mm = 0
for i in range(len(self.step.nmol)):
nsites_mm += self.step.nmol[i] * len(self.step.molecule[i].atom)
xyz_lines = xyz_lines[-nsites_mm:]
input_file = Path(proc_dir, self.config.outname + ".xy")
with open(input_file, 'w') as f:
for atom in self.step.molecule[0].atom:
f.write(
f"{atom.rx:>10.6f} {atom.ry:>10.6f} {atom.rz:>10.6f}\n"
)
for line in xyz_lines:
atom = line.split()
rx = float(atom[1])
ry = float(atom[2])
rz = float(atom[3])
f.write(f"{rx:>10.6f} {ry:>10.6f} {rz:>10.6f}\n")
f.write("$end")
def _new_density(self, last_xyz_file: TextIO):
last_xyz_lines = last_xyz_file.readlines()
box = last_xyz_lines[1].split()
volume = float(box[-3]) * float(box[-2]) * float(box[-1])
total_mass = 0
for i in range(len(self.step.molecule)):
total_mass += self.step.molecule[i].total_mass * self.step.nmol[i]
density = (total_mass / volume) * UMAANG3_TO_GCM3
return density
def _make_nvt_ter(self, cycle, proc_dir):
file = Path(proc_dir, "NVT.ter")
with open(file, 'w') as f:
f.write(f"title = {self.title} - NVT Thermalization\n")
f.write(f"ncores = {self.step.ncores}\n")
f.write(f"ljname = {self.config.ljname}\n")
f.write(f"outname = {self.config.outname}\n")
mol_string = " ".join(str(x) for x in self.config.nmol)
f.write(f"nmol = {mol_string}\n")
f.write(f"dens = {self.config.dens}\n")
f.write(f"temp = {self.config.temp}\n")
if self.config.randominit == "first" and cycle > 1:
f.write(f"init = yesreadxyz\n")
f.write(f"nstep = {self.step.altsteps}\n")
else:
f.write(f"init = yes\n")
f.write(f"nstep = {self.config.nstep[0]}\n")
f.write("vstep = 0\n")
f.write("mstop = 1\n")
f.write("accum = no\n")
f.write("iprint = 1\n")
f.write("isave = 0\n")
f.write("irdf = 0\n")
seed = int(1e6 * random.random())
f.write(f"seed = {seed}\n")
f.write(f"upbuf = {self.config.upbuf}")
def _make_nvt_eq(self, proc_dir):
file = Path(proc_dir, "NVT.eq")
with open(file, 'w') as f:
f.write(f"title = {self.title} - NVT Production\n")
f.write(f"ncores = {self.step.ncores}\n")
f.write(f"ljname = {self.config.ljname}\n")
f.write(f"outname = {self.config.outname}\n")
mol_string = " ".join(str(x) for x in self.config.nmol)
f.write(f"nmol = {mol_string}\n")
f.write(f"dens = {self.config.dens}\n")
f.write(f"temp = {self.config.temp}\n")
f.write("init = no\n")
f.write(f"nstep = {self.config.nstep[1]}\n")
f.write("vstep = 0\n")
f.write("mstop = 1\n")
f.write("accum = no\n")
f.write("iprint = 1\n")
f.write(f"isave = {self.config.isave}\n")
f.write(f"irdf = {10 * self.step.nprocs}\n")
seed = int(1e6 * random.random())
f.write("seed = {}\n".format(seed))
def _make_npt_ter(self, cycle, proc_dir):
file = Path(proc_dir, "NPT.ter")
with open(file, 'w') as f:
f.write(f"title = {self.title} - NPT Thermalization\n")
f.write(f"ncores = {self.step.ncores}\n")
f.write(f"ljname = {self.config.ljname}\n")
f.write(f"outname = {self.config.outname}\n")
mol_string = " ".join(str(x) for x in self.config.nmol)
f.write(f"nmol = {mol_string}\n")
f.write(f"press = {self.config.press}\n")
f.write(f"temp = {self.config.temp}\n")
if self.config.randominit == "first" and cycle > 1:
f.write("init = yesreadxyz\n")
f.write(f"dens = {self.config.dens:<8.4f}\n")
f.write(f"vstep = {int(self.step.altsteps / 5)}\n")
else:
f.write("init = no\n")
f.write(f"vstep = {int(self.config.nstep[1] / 5)}\n")
f.write("nstep = 5\n")
f.write("mstop = 1\n")
f.write("accum = no\n")
f.write("iprint = 1\n")
f.write("isave = 0\n")
f.write("irdf = 0\n")
seed = int(1e6 * random.random())
f.write(f"seed = {seed}\n")
def _make_npt_eq(self, proc_dir):
file = Path(proc_dir, "NPT.eq")
with open(file, 'w') as f:
f.write(f"title = {self.title} - NPT Production\n")
f.write(f"ncores = {self.step.ncores}\n")
f.write(f"ljname = {self.config.ljname}\n")
f.write(f"outname = {self.config.outname}\n")
mol_string = " ".join(str(x) for x in self.config.nmol)
f.write(f"nmol = {mol_string}\n")
f.write(f"press = {self.config.press}\n")
f.write(f"temp = {self.config.temp}\n")
f.write(f"nstep = 5\n")
f.write(f"vstep = {int(self.config.nstep[2] / 5)}\n")
f.write("init = no\n")
f.write("mstop = 1\n")
f.write("accum = no\n")
f.write("iprint = 1\n")
f.write(f"isave = {self.config.isave}\n")
f.write(f"irdf = {10 * self.step.nprocs}\n")
seed = int(1e6 * random.random())
f.write(f"seed = {seed}\n")
def _make_potentials(self, proc_dir):
fstr = "{:<3d} {:>3d} {:>10.5f} {:>10.5f} {:>10.5f} {:>10.6f} {:>9.5f} {:>7.4f}\n"
file = Path(proc_dir, self.config.ljname)
with open(file, 'w') as f:
f.write(f"{self.config.combrule}\n")
f.write(f"{len(self.step.nmol)}\n")
nsites_qm = len(self.step.molecule[0].atom)
f.write(f"{nsites_qm} {self.step.molecule[0].molname}\n")
for atom in self.step.molecule[0].atom:
f.write(
fstr.format(
atom.lbl,
atom.na,
atom.rx,
atom.ry,
atom.rz,
atom.chg,
atom.eps,
atom.sig,
)
)
for mol in self.step.molecule[1:]:
f.write(f"{len(mol.atom)} {mol.molname}\n")
for atom in mol.atom:
f.write(
fstr.format(
atom.lbl,
atom.na,
atom.rx,
atom.ry,
atom.rz,
atom.chg,
atom.eps,
atom.sig,
)
)
def run_dice_file(self, cycle: int, proc: int, file_name: str):
with open(Path(file_name), 'r') as infile, open(Path(file_name + ".out"), 'w') as outfile:
if shutil.which("bash") is not None:
exit_status = subprocess.call(
[
"bash",
"-c",
f"exec -a dice-step{cycle}-p{proc} {self.config.progname} < {infile.name} > {outfile.name}",
]
)
else:
exit_status = subprocess.call(
self.config.progname, stdin=infile, stdout=outfile
)
if exit_status != 0:
raise Exception(f"Dice process step{cycle:02d}-p{proc:02d} did not exit properly")
with open(Path(file_name + ".out"), 'r') as outfile:
flag = outfile.readlines()[DICE_FLAG_LINE].strip()
if flag != DICE_END_FLAG:
raise Exception(f"Dice process step{cycle:02d}-p{proc:02d} did not exit properly")

View File

@@ -1,8 +1,8 @@
from diceplayer.shared.config.gaussian_dto import GaussianDTO from diceplayer.shared.config.gaussian_dto import GaussianDTO
from diceplayer.shared.external import External from diceplayer.shared.interface import Interface
class Gaussian(External): class GaussianInterface(Interface):
def __init__(self, data: dict): def __init__(self, data: dict):
self.config: GaussianDTO = self.set_config(data) self.config: GaussianDTO = self.set_config(data)

View File

@@ -1,62 +0,0 @@
import argparse
from distutils.command.clean import clean
import os
import shutil
import sys
import PyInstaller.__main__
name = "diceplayer"
parser = argparse.ArgumentParser(prog="Diceplayer Setup")
parser.add_argument(
"-b", "--build",
dest="build",
default=False,
action="store_true",
help="Builds the Diceplayer Binary",
)
parser.add_argument(
"-c", "--clean",
dest="clean",
default=False,
action="store_true",
help="Cleans the Development Environment"
)
args = parser.parse_args()
def __build():
PyInstaller.__main__.run(
["diceplayer/__main__.py", "--onefile", "-n{}".format(name)]
)
def __clean():
try:
shutil.rmtree("build")
shutil.rmtree("dist")
os.remove("diceplayer.spec")
except:
print("Workspace clean.")
if __name__ == "__main__":
if args.build:
__build()
elif args.clean:
__clean()
else:
parser.print_help(sys.stderr)
sys.exit(1)

View File

@@ -8,10 +8,9 @@ class TestDiceDto(unittest.TestCase):
dice_dto = DiceDTO( dice_dto = DiceDTO(
ljname='test', ljname='test',
outname='test', outname='test',
ncores=1,
dens=1.0, dens=1.0,
nmol=[1], nmol=[1],
nstep=[1], nstep=[1, 1],
) )
self.assertIsInstance(dice_dto, DiceDTO) self.assertIsInstance(dice_dto, DiceDTO)
@@ -21,10 +20,9 @@ class TestDiceDto(unittest.TestCase):
DiceDTO( DiceDTO(
ljname=None, ljname=None,
outname='test', outname='test',
ncores=1,
dens=1.0, dens=1.0,
nmol=[1], nmol=[1],
nstep=[1], nstep=[1, 1],
) )
self.assertEqual(ex.exception, "Error: 'ljname' keyword not specified in config file") self.assertEqual(ex.exception, "Error: 'ljname' keyword not specified in config file")
@@ -33,10 +31,9 @@ class TestDiceDto(unittest.TestCase):
DiceDTO( DiceDTO(
ljname='test', ljname='test',
outname=None, outname=None,
ncores=1,
dens=1.0, dens=1.0,
nmol=[1], nmol=[1],
nstep=[1], nstep=[1, 1],
) )
self.assertEqual(ex.exception, "Error: 'outname' keyword not specified in config file") self.assertEqual(ex.exception, "Error: 'outname' keyword not specified in config file")
@@ -45,10 +42,9 @@ class TestDiceDto(unittest.TestCase):
DiceDTO( DiceDTO(
ljname='test', ljname='test',
outname='test', outname='test',
ncores=1,
dens=None, dens=None,
nmol=[1], nmol=[1],
nstep=[1], nstep=[1, 1],
) )
self.assertEqual(ex.exception, "Error: 'dens' keyword not specified in config file") self.assertEqual(ex.exception, "Error: 'dens' keyword not specified in config file")
@@ -57,10 +53,9 @@ class TestDiceDto(unittest.TestCase):
DiceDTO( DiceDTO(
ljname='test', ljname='test',
outname='test', outname='test',
ncores=1,
dens=1.0, dens=1.0,
nmol=0, nmol=0,
nstep=[1], nstep=[1, 1],
) )
self.assertEqual(ex.exception, "Error: 'nmol' keyword not defined appropriately in config file") self.assertEqual(ex.exception, "Error: 'nmol' keyword not defined appropriately in config file")
@@ -69,7 +64,6 @@ class TestDiceDto(unittest.TestCase):
DiceDTO( DiceDTO(
ljname='test', ljname='test',
outname='test', outname='test',
ncores=1,
dens=1.0, dens=1.0,
nmol=[1], nmol=[1],
nstep=0, nstep=0,
@@ -80,10 +74,9 @@ class TestDiceDto(unittest.TestCase):
dice_dto = DiceDTO.from_dict({ dice_dto = DiceDTO.from_dict({
'ljname': 'test', 'ljname': 'test',
'outname': 'test', 'outname': 'test',
'ncores': 1,
'dens': 1.0, 'dens': 1.0,
'nmol': [1], 'nmol': [1],
'nstep': [1], 'nstep': [1, 1],
}) })
self.assertIsInstance(dice_dto, DiceDTO) self.assertIsInstance(dice_dto, DiceDTO)

View File

@@ -0,0 +1,45 @@
from diceplayer.shared.config.gaussian_dto import GaussianDTO
import unittest
class TestGaussianDTO(unittest.TestCase):
def test_class_instantiation(self):
gaussian_dto = GaussianDTO(
level='test',
qmprog='g16',
keywords='test',
)
self.assertIsInstance(gaussian_dto, GaussianDTO)
def test_is_valid_qmprog(self):
with self.assertRaises(ValueError):
gaussian_dto = GaussianDTO(
level='test',
qmprog='test',
keywords='test',
)
def test_is_valid_level(self):
with self.assertRaises(ValueError):
gaussian_dto = GaussianDTO(
level=None,
qmprog='g16',
keywords='test',
)
def test_from_dict(self):
gaussian_dto = GaussianDTO.from_dict(
{
'level': 'test',
'qmprog': 'g16',
'keywords': 'test',
}
)
self.assertIsInstance(gaussian_dto, GaussianDTO)
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,28 @@
from diceplayer.shared.config.player_dto import PlayerDTO
import unittest
class TestPlayerDTO(unittest.TestCase):
def test_class_instantiation(self):
player_dto = PlayerDTO(opt=True, maxcyc=100, nprocs=4)
self.assertIsInstance(player_dto, PlayerDTO)
def test_min_altsteps(self):
player_dto = PlayerDTO(opt=True, maxcyc=100, nprocs=4, altsteps=100)
self.assertEqual(player_dto.altsteps, 20000)
def test_from_dict(self):
player_dto = PlayerDTO.from_dict({
'opt': True,
'maxcyc': 100,
'nprocs': 4
})
self.assertIsInstance(player_dto, PlayerDTO)
if __name__ == '__main__':
unittest.main()

View File

@@ -26,25 +26,6 @@ class TestSystem(unittest.TestCase):
system.add_type('test', Molecule('test')) system.add_type('test', Molecule('test'))
self.assertEqual(ex.exception, 'Error: nmols is not an integer') self.assertEqual(ex.exception, 'Error: nmols is not an integer')
def test_center_of_mass_distance(self):
system = System()
a = Molecule('test')
a.add_atom(
Atom(lbl=0, na=1, rx=0, ry=0, rz=0, chg=0, eps=0, sig=0)
)
system.add_type(1, a)
b = Molecule('test')
b.add_atom(
Atom(lbl=0, na=1, rx=0, ry=0, rz=0, chg=0, eps=0, sig=0)
)
system.add_type(1, b)
self.assertIsInstance(system.center_of_mass_distance(0, 1), float)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@@ -1,4 +1,5 @@
from diceplayer.shared.external.dice import Dice from diceplayer.shared.config.step_dto import StepDTO
from diceplayer.shared.interface.dice_interface import DiceInterface
from unittest import mock from unittest import mock
import unittest import unittest
@@ -6,28 +7,28 @@ import unittest
class TestDice(unittest.TestCase): class TestDice(unittest.TestCase):
def test_class_instantiation(self): def test_class_instantiation(self):
dice = Dice( dice = DiceInterface(
{ {
'ljname': 'test', 'ljname': 'test',
'outname': 'test', 'outname': 'test',
'ncores': 1, 'ncores': 1,
'dens': 1.0, 'dens': 1.0,
'nmol': [1], 'nmol': [1],
'nstep': [1], 'nstep': [1, 1],
} }
) )
self.assertIsInstance(dice, Dice) self.assertIsInstance(dice, DiceInterface)
def test_configure(self): def test_configure(self):
dice = Dice( dice = DiceInterface(
{ {
'ljname': 'test', 'ljname': 'test',
'outname': 'test', 'outname': 'test',
'ncores': 1, 'ncores': 1,
'dens': 1.0, 'dens': 1.0,
'nmol': [1], 'nmol': [1],
'nstep': [1], 'nstep': [1, 1],
} }
) )
@@ -38,14 +39,14 @@ class TestDice(unittest.TestCase):
self.assertTrue(hasattr(dice, 'step')) self.assertTrue(hasattr(dice, 'step'))
def test_reset(self): def test_reset(self):
dice = Dice( dice = DiceInterface(
{ {
'ljname': 'test', 'ljname': 'test',
'outname': 'test', 'outname': 'test',
'ncores': 1, 'ncores': 1,
'dens': 1.0, 'dens': 1.0,
'nmol': [1], 'nmol': [1],
'nstep': [1], 'nstep': [1, 1],
} }
) )
@@ -60,30 +61,41 @@ class TestDice(unittest.TestCase):
@mock.patch('diceplayer.shared.external.dice.connection') @mock.patch('diceplayer.shared.external.dice.connection')
@mock.patch('diceplayer.shared.external.dice.Process') @mock.patch('diceplayer.shared.external.dice.Process')
def test_start(self, mock_process, mock_connection): def test_start(self, mock_process, mock_connection):
dice = Dice( dice = DiceInterface(
{ {
'ljname': 'test', 'ljname': 'test',
'outname': 'test', 'outname': 'test',
'ncores': 1, 'ncores': 1,
'dens': 1.0, 'dens': 1.0,
'nmol': [1], 'nmol': [1],
'nstep': [1], 'nstep': [1, 1],
} }
) )
dice.configure(
StepDTO(
ncores=1,
nprocs=1,
simulation_dir='test',
altsteps=1,
molecule=[],
nmol=[],
)
)
dice.start(1) dice.start(1)
self.assertTrue(mock_process.called) self.assertTrue(mock_process.called)
self.assertTrue(mock_connection.wait.called) self.assertTrue(mock_connection.wait.called)
def test_simulation_process_raises_exception(self): def test_simulation_process_raises_exception(self):
dice = Dice( dice = DiceInterface(
{ {
'ljname': 'test', 'ljname': 'test',
'outname': 'test', 'outname': 'test',
'ncores': 1, 'ncores': 1,
'dens': 1.0, 'dens': 1.0,
'nmol': [1], 'nmol': [1],
'nstep': [1], 'nstep': [1, 1],
} }
) )
@@ -94,14 +106,14 @@ class TestDice(unittest.TestCase):
@mock.patch('diceplayer.shared.external.dice.Dice._make_dice_inputs') @mock.patch('diceplayer.shared.external.dice.Dice._make_dice_inputs')
@mock.patch('diceplayer.shared.external.dice.Dice._run_dice') @mock.patch('diceplayer.shared.external.dice.Dice._run_dice')
def test_simulation_process(self, mock_run_dice, mock_make_dice_inputs, mock_make_proc_dir): def test_simulation_process(self, mock_run_dice, mock_make_dice_inputs, mock_make_proc_dir):
dice = Dice( dice = DiceInterface(
{ {
'ljname': 'test', 'ljname': 'test',
'outname': 'test', 'outname': 'test',
'ncores': 1, 'ncores': 1,
'dens': 1.0, 'dens': 1.0,
'nmol': [1], 'nmol': [1],
'nstep': [1], 'nstep': [1, 1],
} }
) )
@@ -111,6 +123,82 @@ class TestDice(unittest.TestCase):
self.assertTrue(dice._make_dice_inputs.called) self.assertTrue(dice._make_dice_inputs.called)
self.assertTrue(dice._run_dice.called) self.assertTrue(dice._run_dice.called)
@mock.patch('diceplayer.shared.external.dice.Path.mkdir')
@mock.patch('diceplayer.shared.external.dice.Path.exists')
def test_make_proc_dir_if_simdir_exists(self, mock_path_exists, mock_path_mkdir):
dice = DiceInterface(
{
'ljname': 'test',
'outname': 'test',
'ncores': 1,
'dens': 1.0,
'nmol': [1],
'nstep': [1, 1],
}
)
dice.configure(
StepDTO(
ncores=1,
nprocs=1,
simulation_dir='test',
altsteps=1,
molecule=[],
nmol=[],
)
)
mock_path_exists.return_value = False
dice._make_proc_dir(1, 1)
self.assertEqual(mock_path_mkdir.call_count, 2)
@mock.patch('diceplayer.shared.external.dice.Path.mkdir')
@mock.patch('diceplayer.shared.external.dice.Path.exists')
def test_make_proc_dir_if_simdir_doesnt_exists(self, mock_path_exists, mock_path_mkdir):
dice = DiceInterface(
{
'ljname': 'test',
'outname': 'test',
'ncores': 1,
'dens': 1.0,
'nmol': [1],
'nstep': [1, 1],
}
)
dice.configure(
StepDTO(
ncores=1,
nprocs=1,
simulation_dir='test',
altsteps=1,
molecule=[],
nmol=[],
)
)
mock_path_exists.return_value = False
dice._make_proc_dir(1, 1)
self.assertEqual(mock_path_mkdir.call_count, 2)
def test_make_dice_seed(self):
dice = DiceInterface(
{
'ljname': 'test',
'outname': 'test',
'ncores': 1,
'dens': 1.0,
'nmol': [1],
'nstep': [1, 1],
}
)
seed = dice._make_dice_seed()
self.assertIsInstance(seed, int)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()