def __init__(self, trajectory_filename, configuration, max_buffer_size=None, max_buffer_time=None): """ Constructor for the XYZTrajectory. :param trajectory_filename: The file name to write trajectory information to. :type trajectory_filename: str :param sites: The lattice sites of the configuration as an Nx3 list. :param max_buffer_size: The max size of the the buffer in memory before writing to file. :type max_buffer_size: int :param max_buffer_time: The max time limit between dumps to file. :type max_buffer_time: float """ # Call the base class constructor. Trajectory.__init__(self, trajectory_filename, max_buffer_size, max_buffer_time) # Init the member data. self.__atom_id_types = [] self.__atom_id_coordinates = [] self.__time = [] self.__step = [] # Write the header. self.__writeHeader(configuration)
def __init__(self, trajectory_filename, configuration, max_buffer_size=None, max_buffer_time=None): """ Constructor for the Trajectory. :param trajectory_filename: The file name to write trajectory information to. :type trajectory_filename: str :param sites: The lattice sites of the configuration as an Nx3 list. :param max_buffer_size: The max size of the the buffer in memory before writing to file. :type max_buffer_size: int :param max_buffer_time: The max time limit between dumps to file. :type max_buffer_time: float """ # Call the base class constructor. Trajectory.__init__(self, trajectory_filename, max_buffer_size, max_buffer_time) # Init the member data. self.__types_buffer = [] self.__simulation_time_buffer = [] self.__step_buffer = [] # Write the header. self.__writeHeader(configuration.sites())
def testAppendAndFlushBufferSize(self): """ Test that the append function flushes when the buffer size is large. """ # Setup data. simulation_time = 12.3 step = 14 class Config: def __init__(self): pass configuration = Config() # Instantiate a trajectory. t = Trajectory(trajectory_filename="filename") # Add the needed functions. def storeData(*args, **kwargs): pass t._storeData = storeData ret_buffer = 10.0 def bufferSize(*args, **kwargs): return ret_buffer t._bufferSize = bufferSize class Dummy: self.fc = False d = Dummy() def flush(): d.fc = True t.flush = flush # Append. t.append(simulation_time, step, configuration) # The first time allways flushes. self.assertTrue(d.fc) # Append again. d.fc = False t.append(simulation_time, step, configuration) self.assertFalse(d.fc) # Change the value of the buffer size so that flush() gets called. ret_buffer = t._Trajectory__max_buffer_size + 1 # Append. t.append(simulation_time, step, configuration) # Check. self.assertTrue(d.fc)
def testAppendInterface(self): """ Test that the append function can not be called directly from the baseclass. """ # Setup data. simulation_time = 12.3 step = 14 class Config: def __init__(self): pass configuration = Config() # Instantiate a trajectory. t = Trajectory(trajectory_filename="filename") # Call append. self.assertRaises( AttributeError, lambda: t.append(simulation_time, step, configuration)) # Add the missing function. def storeData(*args, **kwargs): pass t._storeData = storeData self.assertRaises( AttributeError, lambda: t.append(simulation_time, step, configuration)) # Add the missing function. def bufferSize(*args, **kwargs): pass t._bufferSize = bufferSize self.assertRaises( AttributeError, lambda: t.append(simulation_time, step, configuration)) # Add the missing function. def flush(*args, **kwargs): pass t.flush = flush # Now it works. t.append(simulation_time, step, configuration)
def testDefaultConstruction(self): """ Test default construction. """ t = Trajectory(trajectory_filename="filename") # Check the member data. self.assertEqual(t._trajectory_filename, "filename") self.assertEqual(t._Trajectory__max_buffer_size, 10485760) # 10 MB self.assertEqual(t._Trajectory__max_buffer_time, 1800.0) # 30 min
def testConstruction(self): """ Test that we can instantiate the Trajectory base class. """ t = Trajectory(trajectory_filename="filename", max_buffer_size=100, max_buffer_time=30.0) # Check the member data. self.assertEqual(t._trajectory_filename, "filename") self.assertEqual(t._Trajectory__max_buffer_size, 100) self.assertEqual(t._Trajectory__max_buffer_time, 30.0)
def testAppendInterface(self): """ Test that the append function can not be called directly from the baseclass. """ # Setup data. simulation_time = 12.3 step = 14 class Config: def __init__(self): pass configuration = Config() # Instantiate a trajectory. t = Trajectory(trajectory_filename="filename") # Call append. self.assertRaises(AttributeError, lambda: t.append(simulation_time, step, configuration)) # Add the missing function. def storeData(*args, **kwargs): pass t._storeData = storeData self.assertRaises(AttributeError, lambda: t.append(simulation_time, step, configuration)) # Add the missing function. def bufferSize(*args, **kwargs): pass t._bufferSize = bufferSize self.assertRaises(AttributeError, lambda: t.append(simulation_time, step, configuration)) # Add the missing function. def flush(*args, **kwargs): pass t.flush = flush # Now it works. t.append(simulation_time, step, configuration)
def testAppendTimeUpdate(self): """ Test that the append function updates the time only when it flushes. """ # Setup data. simulation_time = 12.3 step = 14 class Config: def __init__(self): pass configuration = Config() # Instantiate a trajectory. t = Trajectory(trajectory_filename="filename") # Add the needed functions. def storeData(*args, **kwargs): pass t._storeData = storeData ret_buffer = 10.0 def bufferSize(*args, **kwargs): return ret_buffer t._bufferSize = bufferSize class Dummy: self.fc = False d = Dummy() def flush(): d.fc = True t.flush = flush # Append. t.append(simulation_time, step, configuration) # The first time allways flushes. self.assertTrue(d.fc) # This updates the time last dump variable. ref_time_last_dump = t._Trajectory__time_last_dump # Sleep 10 ms. time.sleep(0.01) # Append again. d.fc = False t.append(simulation_time, step, configuration) self.assertFalse(d.fc) # This does not update the time last dump. self.assertAlmostEqual(ref_time_last_dump, t._Trajectory__time_last_dump, 10) # Change the value of the max buffer time so that flush() gets called. t._Trajectory__max_buffer_time = 0.0 # Sleep 10 ms. time.sleep(0.01) # Append. t.append(simulation_time, step, configuration) # Check. self.assertTrue(d.fc) # The time last dump should have been updated. self.assertTrue( (t._Trajectory__time_last_dump - ref_time_last_dump) > 0.0001 )
def run(self, control_parameters=None, trajectory_filename=None): """ Run the KMC lattice model simulation with specified parameters. :param control_paramters: An instance of KMCControlParameters specifying number of steps to run etc. :param trajectory_filename: The filename of the trajectory. If not given no trajectory will be saved. """ # Check the input. if not isinstance(control_parameters, KMCControlParameters): msg =""" The 'control_parameters' input to the KMCLatticeModel run funtion must be an instance of type KMCControlParameters.""" raise Error(msg) # Check the trajectory filename. use_trajectory = True if trajectory_filename is None: use_trajectory = False msg =""" KMCLib: WARNING: No trajectory filename given -> no trajectory will be saved.""" prettyPrint(msg) elif not isinstance(trajectory_filename, str): msg = """ The 'trajectory_filename' input to the KMCLattice model run function must be given as string.""" raise Error(msg) # Construct the C++ lattice model. prettyPrint(" KMCLib: setting up the backend C++ object.") cpp_model = self._backend() # Print the initial matching information if above the verbosity threshold. if self.__verbosity_level > 9: self._printMatchInfo(cpp_model) # Check that we have at least one available process to run the KMC simulation. if cpp_model.interactions().totalAvailableSites() == 0: raise Error("No available processes. None of the processes you have defined as input match any position in the configuration. Change your initial configuration or processes to run KMC.") # Setup a trajectory object. if use_trajectory: trajectory = Trajectory(trajectory_filename=trajectory_filename, sites=self.__configuration.sites()) # Add the first step. trajectory.append(simulation_time = self.__cpp_timer.simulationTime(), step = 0, types = self.__configuration.types()) # Get the needed parameters. n_steps = control_parameters.numberOfSteps() n_dump = control_parameters.dumpInterval() prettyPrint(" KMCLib: Runing for %i steps, starting from time: %f\n"%(n_steps,self.__cpp_timer.simulationTime())) # Run the KMC simulation. try: # Loop over the steps. for s in range(n_steps): step = s+1 # Check if it is possible to take a step. nP = cpp_model.interactions().totalAvailableSites() if nP == 0: raise Error("No more available processes.") # Take a step. cpp_model.singleStep() if ((step)%n_dump == 0): prettyPrint(" KMCLib: %i steps executed. time: %f "%(step, self.__cpp_timer.simulationTime())) # Perform IO using the trajectory object. if use_trajectory: trajectory.append(simulation_time = self.__cpp_timer.simulationTime(), step = step, types = self.__configuration.types()) finally: # Flush the buffers when done. if use_trajectory: trajectory.flush()
def testFlush(self): """ Make sure we can flush the buffer as expected. """ # Get a filename. name = os.path.abspath(os.path.dirname(__file__)) name = os.path.join(name, "..", "..") name = os.path.join(name, "TestUtilities", "Scratch") trajectory_filename = os.path.join(name, "tmp_trajectory_file.py") self.__files_to_remove.append(trajectory_filename) # Construct the trajecctory object. sites = [[0.0,1.0,2.3], [1.0,0.0,2.3], [1.0,1.0,0.3], [1.0,1.0,2.3], [3.4,4.5,4.3], [3.4,4.3,4.3], [3.4,5.5,4.3], [3.7,7.5,6.5]] # Construct. t = Trajectory(trajectory_filename, sites) # Check that the file is created but only with meta information. global_dict = {} local_dict = {} execfile(trajectory_filename, global_dict, local_dict) empty_list = [] ret_types = local_dict['types'] self.assertEqual( ret_types, empty_list ) ret_times = local_dict['times'] self.assertEqual( ret_times, empty_list ) ret_steps = local_dict['steps'] self.assertEqual( ret_steps, empty_list ) # Fill the buffers. t._Trajectory__types_buffer = [["ABC", "123"],["123", "ABC"]] t._Trajectory__simulation_time_buffer = [1.234, 5.678] t._Trajectory__step_buffer = [1, 99] # Flush the buffers. t.flush() # Check that the buffers are empty. self.assertEqual( t._Trajectory__types_buffer, empty_list ) self.assertEqual( t._Trajectory__simulation_time_buffer, empty_list ) self.assertEqual( t._Trajectory__step_buffer, empty_list ) # Check that the file has the flushed values. global_dict = {} local_dict = {} execfile(trajectory_filename, global_dict, local_dict) ret_types = local_dict['types'] self.assertEqual( ret_types, [["ABC", "123"],["123", "ABC"]] ) ret_times = local_dict['times'] self.assertAlmostEqual( ret_times, [1.234, 5.678], 10 ) ret_steps = local_dict['steps'] self.assertEqual( ret_steps, [1, 99] )
def testAppend(self): """ Test appending to the trajectory. """ # Setup input. sites = [[0.0,1.0,2.3], [1.0,0.0,2.3], [1.0,1.0,0.3], [1.0,1.0,2.3], [3.4,4.5,4.3], [3.4,4.3,4.3], [3.4,5.5,4.3], [3.7,7.5,6.5]] name = os.path.abspath(os.path.dirname(__file__)) name = os.path.join(name, "..", "..") name = os.path.join(name, "TestUtilities", "Scratch") trajectory_filename = os.path.join(name, "tmp_trajectory_file.py") self.__files_to_remove.append(trajectory_filename) # Construct. t = Trajectory(trajectory_filename, sites) # Append times, steps and typers. t.append(1.10045, 12, ["A", "A", "A", "A", "A", "A"] ) # Since this was the first time it should have triggered a dump to file. global_dict = {} local_dict = {} execfile(trajectory_filename, global_dict, local_dict) # Needed to prevent test failure. MPICommons.barrier() # Check the types. ret_types = local_dict['types'] ref_types = [["A", "A", "A", "A", "A", "A"]] self.assertEqual( ret_types, ref_types ) # Check the steps. ret_steps = local_dict['steps'] ref_steps = [12] self.assertEqual( ret_steps, ref_steps ) # Check the times. ret_times = local_dict['times'] ref_times = [1.10045] self.assertEqual( ret_times, ref_times ) # Appending again directly makes no dump. t.append(1.1993, 14, ["B", "B", "B", "B", "B", "B"] ) global_dict = {} local_dict = {} execfile(trajectory_filename, global_dict, local_dict) # Needed to prevent test failure. MPICommons.barrier() # Check. ret_types = local_dict['types'] self.assertEqual( ret_types, ref_types ) ret_steps = local_dict['steps'] self.assertEqual( ret_steps, ref_steps ) ret_times = local_dict['times'] self.assertEqual( ret_times, ref_times ) # But if we dump again and set the time limit to zero we will trigger a dump. t._Trajectory__max_buffer_time = 0.0 t.append(1.199, 19, ["C", "C", "C", "C", "C", "C"] ) # Reset the time to some thing large. t._Trajectory__max_buffer_time = 100000000000.0 global_dict = {} local_dict = {} execfile(trajectory_filename, global_dict, local_dict) # Check the types. ret_types = local_dict['types'] ref_types = [["A","A","A","A","A","A"], ["B","B","B","B","B","B"], ["C","C","C","C","C","C"]] # Needed to prevent test failure. MPICommons.barrier() self.assertEqual( ret_types, ref_types ) # Check the steps. ret_steps = local_dict['steps'] ref_steps = [12,14,19] self.assertEqual( ret_steps, ref_steps ) # Check the times. ret_times = local_dict['times'] ref_times = [1.10045, 1.1993, 1.199] self.assertEqual( ret_times, ref_times ) # The buffers are reset after each dump. If we make the # max size limit smaller than the size of the appended types # list this must trigger a dump. types = ["A","A","A","A","A","B"] size = sys.getsizeof(types) t._Trajectory__max_buffer_size = size # Append. t.append(1.1995, 43, types ) # Check. global_dict = {} local_dict = {} execfile(trajectory_filename, global_dict, local_dict) ret_types = local_dict['types'] ref_types = [["A","A","A","A","A","A"], ["B","B","B","B","B","B"], ["C","C","C","C","C","C"]] # Needed to prevent test failure. MPICommons.barrier() self.assertEqual( ret_types, ref_types ) # Append. t.append(1.1995, 43, types ) t.append(1.1995, 43, types ) t.append(1.1995, 43, types ) # This last one triggers the dump. t.append(1.1995, 43, types ) # Check. global_dict = {} local_dict = {} execfile(trajectory_filename, global_dict, local_dict) ret_types = local_dict['types'] ref_types = [["A","A","A","A","A","A"], ["B","B","B","B","B","B"], ["C","C","C","C","C","C"], ["A","A","A","A","A","B"], ["A","A","A","A","A","B"], ["A","A","A","A","A","B"], ["A","A","A","A","A","B"], ["A","A","A","A","A","B"]] # Needed to prevent test failure. MPICommons.barrier() self.assertEqual( ret_types, ref_types )
def testWriteToFile(self): """ Test writing the buffers to file. """ # Setup input. sites = [[0.0,1.0,2.3], [1.0,0.0,2.3], [1.0,1.0,0.3], [1.0,1.0,2.3], [3.4,4.5,4.3], [3.4,4.3,4.3], [3.4,5.5,4.3], [3.7,7.5,6.5]] name = os.path.abspath(os.path.dirname(__file__)) name = os.path.join(name, "..", "..") name = os.path.join(name, "TestUtilities", "Scratch") trajectory_filename = os.path.join(name, "tmp_trajectory_file.py") self.__files_to_remove.append(trajectory_filename) # Construct. t = Trajectory(trajectory_filename, sites) # Write times, steps and typers. times = [1.10045, 2.334156, 3.4516410] steps = [12, 25, 52] types = [["ThisIsTheLongestTypeNameIHaveEverEncounteredPerhaps", "here", "is", "Next", "Long", "List", "Offffffff", "Names", "now", "this", "one", "is", "longer", "still"], ["A", "B", "C", "D", "E", "F", "G", "H"], ["1", "2", "4", "5", "6", "5" ,"43", "243r2424"]] # Needed to prevent test failure. MPICommons.barrier() # Check that the time is zero before we start. self.assertAlmostEqual( t._Trajectory__time_last_dump, 0.0, 10 ) t._Trajectory__writeToFile(times, steps, types) # Needed to prevent test failure. MPICommons.barrier() # Check that the time stamp was updated. self.assertTrue( 1357651850 < t._Trajectory__time_last_dump ) last_time = t._Trajectory__time_last_dump # Check the info stored in the file. global_dict = {} local_dict = {} execfile(trajectory_filename, global_dict, local_dict) # Check the types. ret_types = local_dict['types'] ref_types = [['ThisIsTheLongestTypeNameIHaveEverEncounteredPerhaps', 'here', 'is', 'Next', 'Long', 'List', 'Offffffff', 'Names', 'now', 'this', 'one', 'is', 'longer', 'still'], ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'], ['1', '2', '4', '5', '6', '5', '43', '243r2424']] # Needed to prevent test failure. MPICommons.barrier() self.assertEqual( ret_types, ref_types ) # Check the steps. ret_steps = local_dict['steps'] ref_steps = [12, 25, 52] self.assertEqual( ret_steps, ref_steps ) # Check the times. ret_times = local_dict['times'] ref_times = [1.10045, 2.334156, 3.451641] self.assertEqual( ret_times, ref_times ) # Sleep for two seconds before we add again. time.sleep(1) t._Trajectory__writeToFile(times, steps, types) # Check the time. self.assertTrue( (t._Trajectory__time_last_dump - last_time > 1) ) # Now, check the file again. global_dict = {} local_dict = {} execfile(trajectory_filename, global_dict, local_dict) # Check the types. ret_types = local_dict['types'] ref_types = [['ThisIsTheLongestTypeNameIHaveEverEncounteredPerhaps', 'here', 'is', 'Next', 'Long', 'List', 'Offffffff', 'Names', 'now', 'this', 'one', 'is', 'longer', 'still'], ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'], ['1', '2', '4', '5', '6', '5', '43', '243r2424'], ['ThisIsTheLongestTypeNameIHaveEverEncounteredPerhaps', 'here', 'is', 'Next', 'Long', 'List', 'Offffffff', 'Names', 'now', 'this', 'one', 'is', 'longer', 'still'], ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'], ['1', '2', '4', '5', '6', '5', '43', '243r2424']] # Needed to prevent test failure. MPICommons.barrier() self.assertEqual( ret_types, ref_types ) # Check the steps. ret_steps = local_dict['steps'] ref_steps = [12, 25, 52, 12, 25, 52] self.assertEqual( ret_steps, ref_steps ) # Check the times. ret_times = local_dict['times'] ref_times = [1.10045, 2.334156, 3.451641, 1.10045, 2.334156, 3.451641] self.assertEqual( ret_times, ref_times )
def testAppendTimeUpdate(self): """ Test that the append function updates the time only when it flushes. """ # Setup data. simulation_time = 12.3 step = 14 class Config: def __init__(self): pass configuration = Config() # Instantiate a trajectory. t = Trajectory(trajectory_filename="filename") # Add the needed functions. def storeData(*args, **kwargs): pass t._storeData = storeData ret_buffer = 10.0 def bufferSize(*args, **kwargs): return ret_buffer t._bufferSize = bufferSize class Dummy: self.fc = False d = Dummy() def flush(): d.fc = True t.flush = flush # Append. t.append(simulation_time, step, configuration) # The first time allways flushes. self.assertTrue(d.fc) # This updates the time last dump variable. ref_time_last_dump = t._Trajectory__time_last_dump # Sleep 10 ms. time.sleep(0.01) # Append again. d.fc = False t.append(simulation_time, step, configuration) self.assertFalse(d.fc) # This does not update the time last dump. self.assertAlmostEqual(ref_time_last_dump, t._Trajectory__time_last_dump, 10) # Change the value of the max buffer time so that flush() gets called. t._Trajectory__max_buffer_time = 0.0 # Sleep 10 ms. time.sleep(0.01) # Append. t.append(simulation_time, step, configuration) # Check. self.assertTrue(d.fc) # The time last dump should have been updated. self.assertTrue( (t._Trajectory__time_last_dump - ref_time_last_dump) > 0.0001)