Implements Saves for Last Successful Run
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -12,4 +12,5 @@ __pycache__/
|
|||||||
simfiles/*
|
simfiles/*
|
||||||
|
|
||||||
.vscode/*
|
.vscode/*
|
||||||
.idea/*
|
.idea/*
|
||||||
|
*.pkl
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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:
|
player.create_simulation_dir()
|
||||||
sys.exit(err)
|
|
||||||
|
|
||||||
player = Player(args.infile)
|
|
||||||
|
|
||||||
player.print_keywords()
|
player.print_keywords()
|
||||||
|
|
||||||
player.create_simulation_dir()
|
|
||||||
|
|
||||||
player.read_potentials()
|
|
||||||
player.print_potentials()
|
player.print_potentials()
|
||||||
|
|
||||||
player.prepare_system()
|
player.prepare_system()
|
||||||
|
|||||||
@@ -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():
|
||||||
@@ -169,12 +189,12 @@ class Player:
|
|||||||
nsites, molname = ljc_data.pop(0).split()[:2]
|
nsites, molname = ljc_data.pop(0).split()[:2]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise 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():
|
if not nsites.isdigit():
|
||||||
raise ValueError(
|
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)
|
nsites = int(nsites)
|
||||||
@@ -271,7 +291,7 @@ class Player:
|
|||||||
'Charges optimization failed. No charges found in result.'
|
'Charges optimization failed. No charges found in result.'
|
||||||
)
|
)
|
||||||
|
|
||||||
diff = self.system.molecule[0]\
|
diff = self.system.molecule[0] \
|
||||||
.update_charges(result['charges'])
|
.update_charges(result['charges'])
|
||||||
|
|
||||||
self.system.print_charges_and_dipole(cycle)
|
self.system.print_charges_and_dipole(cycle)
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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="")()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user