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/* .vscode/*
.idea/* .idea/*
*.pkl

View File

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

View File

@@ -43,23 +43,17 @@ def main():
# Open OUTFILE for writing and print keywords and initial info # Open OUTFILE for writing and print keywords and initial info
logger.set_logger(args.outfile, logging.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") player.read_potentials()
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.create_simulation_dir() player.create_simulation_dir()
player.read_potentials() player.print_keywords()
player.print_potentials() player.print_potentials()
player.prepare_system() player.prepare_system()

View File

@@ -1,3 +1,5 @@
import pickle
from diceplayer.shared.interface.gaussian_interface import GaussianInterface from diceplayer.shared.interface.gaussian_interface import GaussianInterface
from diceplayer.shared.interface.dice_interface import DiceInterface from diceplayer.shared.interface.dice_interface import DiceInterface
from diceplayer.shared.utils.dataclass_protocol import Dataclass from diceplayer.shared.utils.dataclass_protocol import Dataclass
@@ -11,38 +13,54 @@ from diceplayer.shared.environment.atom import Atom
from diceplayer import logger from diceplayer import logger
from dataclasses import fields from dataclasses import fields
from typing import Type, Tuple
from pathlib import Path from pathlib import Path
from typing import Type, List
import logging
import yaml import yaml
import sys import sys
import os import os
ENV = ["OMP_STACKSIZE"] ENV = ["OMP_STACKSIZE"]
class Player: class Player:
def __init__(self, infile: str): def __init__(self, infile: str = None, optimization: bool = False):
config_data = self.read_keywords(infile) 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( self.config = self.set_config(
config_data.get("diceplayer") 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.dice_interface = DiceInterface()
self.gaussian_interface = GaussianInterface() self.gaussian_interface = GaussianInterface()
def start(self, initial_cycle: int = 1): def start(self):
logger.info( logger.info(
"==========================================================================================\n" "==========================================================================================\n"
"Starting the iterative process.\n" "Starting the iterative process.\n"
"==========================================================================================\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( logger.info(
f"------------------------------------------------------------------------------------------\n" f"------------------------------------------------------------------------------------------\n"
@@ -54,9 +72,12 @@ class Player:
try: try:
self.gaussian_start(cycle) self.gaussian_start(cycle)
pass
except StopIteration as e: except StopIteration as e:
break break
self.save_run_in_pickle(cycle)
def prepare_system(self): def prepare_system(self):
for i, mol in enumerate(self.system.molecule): for i, mol in enumerate(self.system.molecule):
logger.info( logger.info(
@@ -75,7 +96,6 @@ class Player:
logger.info("\n") logger.info("\n")
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():
@@ -390,6 +410,31 @@ class Player:
logger.info("\n") 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 @staticmethod
def set_config(data: dict) -> PlayerConfig: def set_config(data: dict) -> PlayerConfig:
return PlayerConfig.from_dict(data) return PlayerConfig.from_dict(data)
@@ -398,3 +443,11 @@ class Player:
def read_keywords(infile) -> dict: def read_keywords(infile) -> dict:
with open(infile, 'r') as yml_file: with open(infile, 'r') as yml_file:
return yaml.load(yml_file, Loader=yaml.SafeLoader) 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.nsites.ljc": get_potentials_error_nsites(),
"phb.error.molname.ljc": get_potentials_error_molname(), "phb.error.molname.ljc": get_potentials_error_molname(),
} }
mock_file = mock.mock_open(read_data=values[file]) if file in values:
return mock_file() 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 = DiceInterface()
dice.configure(self.config, System()) dice.configure(self.config, System())
dice._make_nvt_eq('test') dice._make_nvt_eq(1, 'test')
mock_handler = mock_open() mock_handler = mock_open()
calls = mock_handler.write.call_args_list calls = mock_handler.write.call_args_list

View File

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