Implements Saves for Last Successful Run
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -12,4 +12,5 @@ __pycache__/
|
||||
simfiles/*
|
||||
|
||||
.vscode/*
|
||||
.idea/*
|
||||
.idea/*
|
||||
*.pkl
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
player.read_potentials()
|
||||
|
||||
except Exception as err:
|
||||
sys.exit(err)
|
||||
|
||||
player = Player(args.infile)
|
||||
player.create_simulation_dir()
|
||||
|
||||
player.print_keywords()
|
||||
|
||||
player.create_simulation_dir()
|
||||
|
||||
player.read_potentials()
|
||||
player.print_potentials()
|
||||
|
||||
player.prepare_system()
|
||||
|
||||
@@ -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.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)
|
||||
|
||||
@@ -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="")()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user