Implements Saves for Last Successful Run

This commit is contained in:
2023-06-05 19:01:36 -03:00
parent 33612f2d7b
commit d0be244d3c
7 changed files with 116 additions and 57 deletions

1
.gitignore vendored
View File

@@ -13,3 +13,4 @@ simfiles/*
.vscode/*
.idea/*
*.pkl

View File

@@ -1,16 +1,16 @@
diceplayer:
opt: no
mem: 24
maxcyc: 10
maxcyc: 5
ncores: 5
nprocs: 4
qmprog: 'g16'
lps: no
ghosts: no
altsteps: 20000
altsteps: 2000
dice:
nmol: [1, 1000]
nmol: [1, 100]
dens: 1.0
nstep: [2000, 3000]
isave: 1000

View File

@@ -43,23 +43,17 @@ def main():
# Open OUTFILE for writing and print keywords and initial info
logger.set_logger(args.outfile, logging.INFO)
try:
if args.opt_continue:
player = Player.from_save()
else:
player = Player.from_file(args.infile)
pickle_path = Path("latest-step.pkl")
if args.opt_continue and pickle_path.exists():
with open(pickle_path) as pickle_file:
save = pickle.load(pickle_file)
except Exception as err:
sys.exit(err)
player = Player(args.infile)
player.print_keywords()
player.read_potentials()
player.create_simulation_dir()
player.read_potentials()
player.print_keywords()
player.print_potentials()
player.prepare_system()

View File

@@ -1,3 +1,5 @@
import pickle
from diceplayer.shared.interface.gaussian_interface import GaussianInterface
from diceplayer.shared.interface.dice_interface import DiceInterface
from diceplayer.shared.utils.dataclass_protocol import Dataclass
@@ -11,38 +13,54 @@ from diceplayer.shared.environment.atom import Atom
from diceplayer import logger
from dataclasses import fields
from typing import Type, Tuple
from pathlib import Path
from typing import Type, List
import logging
import yaml
import sys
import os
ENV = ["OMP_STACKSIZE"]
class Player:
def __init__(self, infile: str):
config_data = self.read_keywords(infile)
def __init__(self, infile: str = None, optimization: bool = False):
if infile is None and optimization is False:
raise ValueError("Must specify either infile or optimization")
self.system = System()
elif infile is not None:
config_data = self.read_keywords(infile)
self.config = self.set_config(
config_data.get("diceplayer")
)
self.system = System()
self.initial_cycle = 1
elif optimization is True:
save = self.load_run_from_pickle()
self.config = save[0]
self.system = save[1]
self.initial_cycle = save[2]
else:
raise ValueError("Must specify either infile or config")
self.dice_interface = DiceInterface()
self.gaussian_interface = GaussianInterface()
def start(self, initial_cycle: int = 1):
def start(self):
logger.info(
"==========================================================================================\n"
"Starting the iterative process.\n"
"==========================================================================================\n"
)
for cycle in range(initial_cycle, self.config.maxcyc + 1):
for cycle in range(self.initial_cycle, self.config.maxcyc + 1):
logger.info(
f"------------------------------------------------------------------------------------------\n"
@@ -54,9 +72,12 @@ class Player:
try:
self.gaussian_start(cycle)
pass
except StopIteration as e:
break
self.save_run_in_pickle(cycle)
def prepare_system(self):
for i, mol in enumerate(self.system.molecule):
logger.info(
@@ -75,7 +96,6 @@ class Player:
logger.info("\n")
def create_simulation_dir(self):
simulation_dir_path = Path(self.config.simulation_dir)
if simulation_dir_path.exists():
@@ -169,12 +189,12 @@ class Player:
nsites, molname = ljc_data.pop(0).split()[:2]
except ValueError:
raise ValueError(
f"Error: expected nsites and molname for the molecule type {i+1}"
f"Error: expected nsites and molname for the molecule type {i + 1}"
)
if not nsites.isdigit():
raise ValueError(
f"Error: expected nsites to be an integer for molecule type {i+1}"
f"Error: expected nsites to be an integer for molecule type {i + 1}"
)
nsites = int(nsites)
@@ -271,7 +291,7 @@ class Player:
'Charges optimization failed. No charges found in result.'
)
diff = self.system.molecule[0]\
diff = self.system.molecule[0] \
.update_charges(result['charges'])
self.system.print_charges_and_dipole(cycle)
@@ -390,6 +410,31 @@ class Player:
logger.info("\n")
def save_run_in_pickle(self, cycle):
try:
with open('latest-step.pkl', 'wb') as pickle_file:
pickle.dump(
(self.config, self.system, cycle),
pickle_file
)
except Exception:
raise RuntimeError(
f'Could not save pickle file latest-step.pkl.'
)
@staticmethod
def load_run_from_pickle() -> Tuple[PlayerConfig, System, int]:
pickle_path = Path("latest-step.pkl")
try:
with open(pickle_path, 'rb') as pickle_file:
save = pickle.load(pickle_file)
return save[0], save[1], save[2] + 1
except Exception:
raise RuntimeError(
f'Could not load pickle file {pickle_path}.'
)
@staticmethod
def set_config(data: dict) -> PlayerConfig:
return PlayerConfig.from_dict(data)
@@ -398,3 +443,11 @@ class Player:
def read_keywords(infile) -> dict:
with open(infile, 'r') as yml_file:
return yaml.load(yml_file, Loader=yaml.SafeLoader)
@classmethod
def from_file(cls, infile: str) -> 'Player':
return cls(infile=infile)
@classmethod
def from_save(cls):
return cls(optimization=True)

View File

@@ -107,5 +107,7 @@ def mock_open(file, *args, **kwargs):
"phb.error.nsites.ljc": get_potentials_error_nsites(),
"phb.error.molname.ljc": get_potentials_error_molname(),
}
mock_file = mock.mock_open(read_data=values[file])
return mock_file()
if file in values:
return mock.mock_open(read_data=values[file])()
return mock.mock_open(read_data="")()

View File

@@ -417,7 +417,7 @@ class TestDiceInterface(unittest.TestCase):
dice = DiceInterface()
dice.configure(self.config, System())
dice._make_nvt_eq('test')
dice._make_nvt_eq(1, 'test')
mock_handler = mock_open()
calls = mock_handler.write.call_args_list

View File

@@ -27,7 +27,7 @@ class TestPlayer(unittest.TestCase):
player.gaussian_start = mock.MagicMock()
player.dice_start = mock.MagicMock()
player.start(1)
player.start()
self.assertEqual(player.dice_start.call_count, 3)
self.assertEqual(player.gaussian_start.call_count, 3)
@@ -66,21 +66,30 @@ class TestPlayer(unittest.TestCase):
player.print_keywords()
expected_output = [
'INFO:diceplayer:##########################################################################################\n############# Welcome to DICEPLAYER version 1.0 #############\n##########################################################################################\n\n',
'INFO:diceplayer:Your python version is TEST\n', 'INFO:diceplayer:\n',
'INFO:diceplayer:Program started on 00 Test 0000 at 00:00:00\n', 'INFO:diceplayer:\n',
'INFO:diceplayer:Environment variables:\n', 'INFO:diceplayer:OMP_STACKSIZE = Not set\n',
'INFO:diceplayer:\n==========================================================================================\n CONTROL variables being used in this run:\n------------------------------------------------------------------------------------------\n\n',
'INFO:diceplayer:\n',
'INFO:diceplayer:------------------------------------------------------------------------------------------\n DICE variables being used in this run:\n------------------------------------------------------------------------------------------\n\n',
'INFO:diceplayer:dens = 0.75', 'INFO:diceplayer:isave = 1000', 'INFO:diceplayer:ljname = phb.ljc',
'INFO:diceplayer:nmol = [ 1 50 ]', 'INFO:diceplayer:nstep = [ 2000 3000 4000 ]',
'INFO:diceplayer:outname = phb', 'INFO:diceplayer:press = 1.0',
'INFO:diceplayer:progname = ~/.local/bin/dice', 'INFO:diceplayer:randominit = first',
'INFO:diceplayer:temp = 300.0', 'INFO:diceplayer:\n',
'INFO:diceplayer:------------------------------------------------------------------------------------------\n GAUSSIAN variables being used in this run:\n------------------------------------------------------------------------------------------\n\n',
'INFO:diceplayer:keywords = freq', 'INFO:diceplayer:level = MP2/aug-cc-pVDZ',
'INFO:diceplayer:pop = chelpg', 'INFO:diceplayer:qmprog = g16', 'INFO:diceplayer:\n']
'INFO:diceplayer:##########################################################################################\n############# Welcome to DICEPLAYER version 1.0 #############\n##########################################################################################\n',
'INFO:diceplayer:Your python version is TEST\n',
'INFO:diceplayer:Program started on 00 Test 0000 at 00:00:00\n',
'INFO:diceplayer:Environment variables:',
'INFO:diceplayer:OMP_STACKSIZE = Not set\n',
'INFO:diceplayer:------------------------------------------------------------------------------------------\n DICE variables being used in this run:\n------------------------------------------------------------------------------------------\n',
'INFO:diceplayer:dens = 0.75',
'INFO:diceplayer:isave = 1000',
'INFO:diceplayer:ljname = phb.ljc',
'INFO:diceplayer:nmol = [ 1 50 ]',
'INFO:diceplayer:nstep = [ 2000 3000 4000 ]',
'INFO:diceplayer:outname = phb',
'INFO:diceplayer:press = 1.0',
'INFO:diceplayer:progname = ~/.local/bin/dice',
'INFO:diceplayer:randominit = first',
'INFO:diceplayer:temp = 300.0',
'INFO:diceplayer:------------------------------------------------------------------------------------------\n GAUSSIAN variables being used in this run:\n------------------------------------------------------------------------------------------\n',
'INFO:diceplayer:chg_tol = 0.01',
'INFO:diceplayer:keywords = freq',
'INFO:diceplayer:level = MP2/aug-cc-pVDZ',
'INFO:diceplayer:pop = chelpg',
'INFO:diceplayer:qmprog = g16',
'INFO:diceplayer:\n'
]
self.assertEqual(cm.output, expected_output)
@@ -294,22 +303,22 @@ class TestPlayer(unittest.TestCase):
player.print_potentials()
expected_output = [
'INFO:diceplayer:==========================================================================================\n',
'INFO:diceplayer: Potential parameters from file phb.ljc:',
'INFO:diceplayer:------------------------------------------------------------------------------------------\n',
'INFO:diceplayer:Combination rule: *', 'INFO:diceplayer:Types of molecules: 2\n',
'INFO:diceplayer:==========================================================================================\n Potential parameters from file phb.ljc:\n------------------------------------------------------------------------------------------\n',
'INFO:diceplayer:Combination rule: *',
'INFO:diceplayer:Types of molecules: 2\n',
'INFO:diceplayer:1 atoms in molecule type 1:',
'INFO:diceplayer:---------------------------------------------------------------------------------',
'INFO:diceplayer:Lbl AN X Y Z Charge Epsilon Sigma Mass',
'INFO:diceplayer:---------------------------------------------------------------------------------',
'INFO:diceplayer:1 1 0.00000 0.00000 0.00000 0.000000 0.00000 0.0000 1.0079',
'INFO:diceplayer:\n', 'INFO:diceplayer:1 atoms in molecule type 2:',
'INFO:diceplayer:\n',
'INFO:diceplayer:1 atoms in molecule type 2:',
'INFO:diceplayer:---------------------------------------------------------------------------------',
'INFO:diceplayer:Lbl AN X Y Z Charge Epsilon Sigma Mass',
'INFO:diceplayer:---------------------------------------------------------------------------------',
'INFO:diceplayer:1 1 0.00000 0.00000 0.00000 0.000000 0.00000 0.0000 1.0079',
'INFO:diceplayer:\n',
'INFO:diceplayer:==========================================================================================']
'INFO:diceplayer:\n'
]
self.assertEqual(
context.output,