def run(self): if self.model is None: self.model = KMC_Model(self.queue, self.parameter_queue, self.signal_queue, steps_per_frame=self.steps_per_frame) self.model.run()
class KMC_ModelProxy(multiprocessing.Process): """This is a proxy class handling the communication with the Model process. This proxy was necessary because Windows does not support fork() and thus the model process cannot be split-off directly. As a workaround multiprocessing tries to pickle the memory of the current process, however it does not know how to pickle the fortran objects. """ def __init__(self, *args, **kwargs): super(KMC_ModelProxy, self).__init__() self.steps_per_frame = kwargs.get('steps_per_frame', 50000) self.model = kwargs.get( 'model', None, ) self.kwargs = kwargs self.signal_queue = self.kwargs.get('signal_queue') self.parameter_queue = self.kwargs.get('parameter_queue') self.queue = self.kwargs.get('queue') def run(self): if self.model is None: self.model = KMC_Model(self.queue, self.parameter_queue, self.signal_queue, steps_per_frame=self.steps_per_frame) self.model.run() def join(self): self.signal_queue.put('JOIN') super(KMC_ModelProxy, self).join() def terminate(self): self.signal_queue.put('STOP') super(KMC_ModelProxy, self).terminate()
def run(point): """Run function""" T, p_COgas, p_O2gas = point kmc_settings.simulation_size = 1 with KMC_Model(print_rates=False, banner=False) as model: # Write header to data file if not os.path.isfile(DATA_FILENAME): with file(DATA_FILENAME, 'w') as datafile: datafile.write( "#T p_CO p_O2 kmc_time %s %s\n" % (model.get_tof_header(), model.get_occupation_header())) datafile.write(str(model)) # Set experimental parameters model.parameters.p_COgas = p_COgas model.parameters.p_O2gas = p_O2gas model.parameters.T = T # Run simulation last_time = 0. for double_step in range(3): last_time = model.base.get_kmc_time() model.double() model.base.set_kmc_time(last_time) print(model.size) while not model.base.get_kmc_time() > INITIAL_TIME + last_time: model.do_steps(INITIAL_STEPS) atoms = model.get_atoms(geometry=False) occupation = [] tof = [] delta_ts = [] for i in range(SAMPLES): model.do_steps() atoms = model.get_atoms(geometry=False) occupation.append(atoms.occupation.flatten()) tof.append(atoms.tof_data) delta_ts.append(atoms.delta_t) occupation = np.average(occupation, axis=0, weights=delta_ts) tof = np.average(tof, axis=0, weights=delta_ts) kmc_time = sum(delta_ts) with file(DATA_FILENAME, 'a') as datafile: outdata = tuple([T, p_COgas, p_O2gas, kmc_time] + list(tof) + list(occupation)) datafile.write( (' '.join(['%.3e'] * len(outdata)) + '\n') % outdata)
def main(args=None): """The CLI main entry point function. The optional argument args, can be used to directly supply command line argument like $ kmcos <args> otherwise args will be taken from STDIN. """ from glob import glob options, args, parser = get_options(args, get_parser=True) global model, pt, np, cm_model if not args[0] in list(usage.keys()): args[0] = match_keys(args[0], usage, parser) if args[0] == 'benchmark': from sys import path path.append(os.path.abspath(os.curdir)) nsteps = 1000000 from time import time from kmcos.run import KMC_Model model = KMC_Model(print_rates=False, banner=False) accelerated = model.can_accelerate if not accelerated: time0 = time() try: model.proclist.do_kmc_steps(nsteps) except: # kmos < 0.3 had no model.proclist.do_kmc_steps model.do_steps(nsteps) needed_time = time() - time0 print('Using the [%s] backend.' % model.get_backend()) print('%s steps took %.2f seconds' % (nsteps, needed_time)) print('Or %.2e steps/s' % (1e6 / needed_time)) model.deallocate() else: time0 = time() model.do_steps(nsteps) needed_time = time() - time0 print('Using the [%s] backend.' % model.get_backend()) print('Using the temporal acceleration scheme') print('%s normal steps took %.2f seconds' % (nsteps, needed_time)) print('Or %.2e steps/s' % (1e6 / needed_time)) print('') model.deallocate() model = KMC_Model(print_rates=False, banner=False) time0 = time() model.do_acc_steps(nsteps) needed_time = time() - time0 print('%s accelerated steps took %.2f seconds' % (nsteps, needed_time)) print('Or %.2e steps/s' % (1e6 / needed_time)) model.deallocate() elif args[0] == 'build': from kmcos.utils import build build(options) elif args[0] == 'edit': from kmcos import gui gui.main() elif args[0] == 'settings-export': import kmcos.types import kmcos.io from kmcos.io import ProcListWriter if len(args) < 2: parser.error('XML file and export path expected.') if len(args) < 3: out_dir = '%s_%s' % (os.path.splitext(args[1])[0], options.backend) print('No export path provided. Exporting to %s' % out_dir) args.append(out_dir) xml_file = args[1] export_dir = args[2] project = kmcos.types.Project() project.import_file(xml_file) writer = ProcListWriter(project, export_dir) writer.write_settings() elif args[0] == 'export': import kmcos.types import kmcos.io from kmcos.utils import build if len(args) < 2: parser.error('XML file and export path expected.') if len(args) < 3: out_dir = '%s_%s' % (os.path.splitext(args[1])[0], options.backend) print('No export path provided. Exporting to %s' % out_dir) args.append(out_dir) xml_file = args[1] export_dir = os.path.join(args[2], 'src') project = kmcos.types.Project() project.import_file(xml_file) project.shorten_names(max_length=options.variable_length) kmcos.io.export_source(project, export_dir, options=options, accelerated=options.temp_acc) if ((os.name == 'posix' and os.uname()[0] in ['Linux', 'Darwin']) or os.name == 'nt') \ and not options.source_only: os.chdir(export_dir) build(options) for out in glob('kmc_*'): if os.path.exists('../%s' % out) : if options.overwrite : overwrite = 'y' else: overwrite = input(('Should I overwrite existing %s ?' '[y/N] ') % out).lower() if overwrite.startswith('y') : print('Overwriting {out}'.format(**locals())) os.remove('../%s' % out) shutil.move(out, '..') else : print('Skipping {out}'.format(**locals())) else: shutil.move(out, '..') elif args[0] == 'settings-export': import kmcos.io pt = kmcos.io.import_file(args[1]) if len(args) < 3: out_dir = os.path.splitext(args[1])[0] print('No export path provided. Exporting kmc_settings.py to %s' % out_dir) args.append(out_dir) if not os.path.exists(args[2]): os.mkdir(args[2]) elif not os.path.isdir(args[2]): raise UserWarning("Cannot overwrite %s; Exiting;" % args[2]) writer = kmcos.io.ProcListWriter(pt, args[2]) writer.write_settings() elif args[0] == 'help': if len(args) < 2: parser.error('Which help do you want?') if args[1] == 'all': for command in sorted(usage): print(usage[command]) elif args[1] in usage: print('Usage: %s\n' % usage[args[1]]) else: arg = match_keys(args[1], usage, parser) print('Usage: %s\n' % usage[arg]) elif args[0] == 'import': import kmcos.io if not len(args) >= 2: raise UserWarning('XML file name expected.') pt = kmcos.io.import_xml_file(args[1]) if len(args) == 2: sh(banner='Note: pt = kmcos.io.import_xml(\'%s\')' % args[1]) elif len(args) == 3: # if optional 3rd argument is given, store model there and exit pt.save(args[2]) elif args[0] == 'rebuild': from time import sleep print('Will rebuild model from kmc_settings.py in current directory') print('Please do not interrupt,' ' build process, as you will most likely') print('loose the current model files.') sleep(2.) from sys import path path.append(os.path.abspath(os.curdir)) from tempfile import mktemp if not os.path.exists('kmc_model.so') \ and not os.path.exists('kmc_model.pyd'): raise Exception('No kmc_model.so found.') if not os.path.exists('kmc_settings.py'): raise Exception('No kmc_settings.py found.') from kmcos.run import KMC_Model model = KMC_Model(print_rates=False, banner=False) tempfile = mktemp() f = file(tempfile, 'w') f.write(model.xml()) f.close() for kmc_model in glob('kmc_model.*'): os.remove(kmc_model) os.remove('kmc_settings.py') main('export %s -b %s .' % (tempfile, options.backend)) os.remove(tempfile) model.deallocate() elif args[0] in ['run', 'shell']: from sys import path path.append(os.path.abspath(os.curdir)) from kmcos.run import KMC_Model # useful to have in interactive mode import numpy as np try: from matplotlib import pyplot as plt except: plt = None if options.catmap: import catmap import catmap.cli.kmc_runner seed = catmap.cli.kmc_runner.get_seed_from_path('.') cm_model = catmap.ReactionModel(setup_file='{seed}.mkm'.format(**locals())) catmap_message = '\nSide-loaded catmap_model {seed}.mkm into cm_model = ReactionModel(setup_file="{seed}.mkm")'.format(**locals()) else: catmap_message = '' try: model = KMC_Model(print_rates=False) except: print("Warning: could not import kmc_model!" " Please make sure you are in the right directory") sh(banner='Note: model = KMC_Model(print_rates=False){catmap_message}'.format(**locals())) try: model.deallocate() except: print("Warning: could not deallocate model. Was is allocated?") elif args[0] == 'version': from kmcos import VERSION print(VERSION) elif args[0] == 'view': from sys import path path.append(os.path.abspath(os.curdir)) from kmcos import view view.main(steps_per_frame=options.steps_per_frame) elif args[0] == 'xml': from sys import path path.append(os.path.abspath(os.curdir)) from kmcos.run import KMC_Model model = KMC_Model(banner=False, print_rates=False) print(model.xml()) else: parser.error('Command "%s" not understood.' % args[0])
import pickle from kmcos.run import KMC_Model model = KMC_Model() NSTEPS = 1e6 model.do_steps(NSTEPS) model.pickle_export_atoms("MyFirstDiffusion_atoms_" + str(NSTEPS) + ".pkl")
def import_model(sim_size, random_seed): model = KMC_Model(print_rates=False, banner=False, size=sim_size, random_seed=random_seed) return model
def simulate_tpd(Tinitial, Tfinal, beta, cov, species, element, maxstp, minstp): #******************************Initiating & opening******************************* # In this section, the files to be exported to are created and opened. Then, some of the initial conditions and headers are exported to files. The size and number of sites of the model are calculated. Then, the initial coverage is produced using the random seed and coverage that was set in the main() function. path = 'tpd_info_{0}_{1}'.format(cov, element) prefix = "*****" + str(path) + "***** " print(prefix, "Starting run of", cov, species, "coverage at", Tinitial, "Kelvin...") os.mkdir(path) cov1 = open(path + '/site_coverages.txt', 'w') des = open(path + '/desorptions.txt', 'w') representation = open(path + '/representation.txt', 'w') cov2 = open(path + '/total_coverages.txt', 'w') info = open(path + '/info.txt', 'w') info.write( "Starting temperature = {0} \nFinal temperature = {1} \nHeating rate = {2}\n" .format(Tinitial, Tfinal, beta)) info.write("Initial coverage = {0} of {1}\n".format(cov, species)) info.write("Pseudo-random generator seed = {0}\n".format(element)) cov1.write( "Temperature[K]\tTime[s]\tDesorption_events\tSite_coverage_filled\tSite_coverage_empty\tDesorption_TOF\n" ) cov2.write( "Temperature[K]\tTime[s]\tDesorption_events\tTotal_sitecoverage_filled\tTotal_sitecoverage_empty\n" ) model = KMC_Model(print_rates=False, banner=False) kmc_settings.random_seed = element #set the random seed to the seed that was generated model.parameters.T = Tinitial #the temperature parameter is set so that the processes' rate contstants reflect the temperature changes representation.write(str(model.__repr__) + '\n') representation.close() des.write("Temperature[K]\tTime[s]\tDesorption_events" + '\n') nsites = model.lattice.spuck #sets the number of sites per cell vol = model.base.get_volume( ) #sets the volume of the model(num of sites * num of cells) # dictionary of {species_name : corresponding int} reps = {} for i, spec in enumerate(sorted(kmc_settings.representations)): reps[spec] = i # initial coverage: print(prefix, "Producing initial coverage...") nadsorbed = 0 nads = int(round(cov * vol)) #changed this temporarily(cov) X, Y, Z = model.lattice.system_size sites = [ [x, y, z, n + 1] for (x, y, z, n) in product(list(range(X)), list(range( Y)), list(range(Z)), list(range(nsites))) ] # for loop to populate an array with every possible cell/site combination in the model; the range function excludes the last #number; for x,y,z the indices work out but for n, 1 has to be added for it to be correct random.seed(element) #sets the random seed to the random seed passed in for i in range( nads ): #for loop for producing the coverage that was set previously while True: site = random.choice(sites) if model.lattice.get_species(site) == reps['empty']: model._put(site, model.proclist.co) nadsorbed += 1 break model._adjust_database() info.write('Initial number of CO atoms = {0} (total of {1} sites)'.format( nadsorbed, vol)) info.close() config = model._get_configuration() #*******************************Start******************************* #The initial temperature, min and max steps are set. The initial temperature is set according the the number passed into the simulate_tpd function. The min and max steps are set according to user input information. Then the model does a set number of steps to 'warm' the model up. Then, a for loop is entered until the final temperature is reached or the number desorbed is equal to the number adsorbed. In this loop, the model does steps and increments the temperature between snapshots. Then, it exports information if a molecule has been desorbed print(prefix, "Starting TPD...\n") atoms = model.get_atoms(geometry=True) write(path + '/initial.traj', atoms) ################################################################## User Set Parameters 2 of 2 #################################################################### ndesorbed = 0 maxsteps = maxstp # max number of steps that should be in a snapshot minsteps = minstp # min number of steps that should be in a snap shot steps = minsteps max_covChange = 0.5 # max percent of coverage change that should occur min_covChange = 0.0001 # min percent of coverage change that should occur covForDecSteps = .03 # percent coverage left, used for slowing the model down towards the end of the sim cov_final = .01 # the lowest amount of coverage before the simulation needs to stop curr_cov = (atoms.occupation[0])[0] # the current amount of coverage prev_cov = curr_cov # the previous coverage, used for determining coverage change T = Tinitial # the starting temperature prev_T = T # the previous temperature, used in exporting data maxDeltaTpersnapshot = 5 # max number the temperature can increase by between snapshots prev_config = model._get_configuration( ) # previous configuration, used for reseting the model prev_t = atoms.kmc_time # previous kmc_time, used for reseting the model ################################################################################################################################################################## while T < Tfinal and ndesorbed < nadsorbed and curr_cov > cov_final: #while the temperature hasn't reached the final temp, and all the molecules haven't desorbed desorbed = False model.parameters.T = T model.do_steps(steps) atoms = model.get_atoms(geometry=False) t = atoms.kmc_time curr_cov = (atoms.occupation[0])[0] prev_T = T Tincr = beta * ( t - prev_t ) # calculate the value to increment the temperature by(if it passes all the checks) T_incremented = T + Tincr cov_change = ( prev_cov - curr_cov ) # coverage change, used to see if any molecules have desorbed if Tincr > maxDeltaTpersnapshot: # if the value to increment the temperature is too large, reset the model and decrease the steps by half model._set_configuration(prev_config) model.base.set_kmc_time(prev_t) model._adjust_database() steps = steps / 2 successfulresolution = False if ndesorbed == 0: T = T + maxDeltaTpersnapshot atoms = model.get_atoms(geometry=False) elif cov_change > max_covChange: # if the coverage change is too large, reset the model and decrease the steps by half model._set_configuration(prev_config) model.base.set_kmc_time(prev_t) model._adjust_database() steps = steps / 2 successfulresolution = False atoms = model.get_atoms(geometry=False) elif cov_change < min_covChange: # if the coverage change is too small, double the steps successfulresolution = True T = T_incremented steps = steps * 2 prev_cov = curr_cov prev_t = atoms.kmc_time else: # if the checks have been passed, increment the temperature using the calculated T_incremented value successfulresolution = True T = T_incremented prev_cov = curr_cov prev_t = atoms.kmc_time if curr_cov < covForDecSteps: # if the current coverage is lower than the set amount, decrease the steps by half and set minsteps to 1. This prevents the simulation crashing from too many steps minsteps = 1 steps = steps / 2 if successfulresolution: # if the snapshot passed all of the tests desorbed = False avg_T = (T + prev_T) / 2 print(prefix, "Avg Temp:", avg_T, "Time:", t, "\nSteps per update:", steps, "Coverage change:", cov_change, "Tincr:", Tincr, '\n') if cov_change != 0: # if the coverage change was zero, no molecules desorbed, don't export the data desorbed = True recentdesorbed = cov_change * vol ndesorbed += recentdesorbed #counter for total number desorbed if desorbed: # if a molecule did desorb, export the data entry = str(avg_T) + '\t' + str(t) + '\t' + str( recentdesorbed ) + '\t' #temp could be exported by linear fitting the tof calculations and picking whether to export curr or prev temp based on those calcs print(prefix, "DESORBED", ndesorbed, 'out of', nadsorbed, "Total sites:", model.base.get_volume(), '\n') des.write(entry + '\n') cov1.write(entry) cov2.write(entry) for spec in atoms.occupation: tot = 0.0 for site in range(nsites): cov1.write(str(spec[site]) + '\t') tot += spec[site] cov2.write(str(tot / nsites) + '\t') cov1.write(str(atoms.tof_integ[0]) + '\t') cov1.write('\n') cov2.write('\n') if steps < minsteps: steps = minsteps # if the steps are lower than the min amount of steps, set equal to the minsteps elif steps > maxsteps: steps = maxsteps # if the steps are higher than the max amount of steps, set equal to the maxsteps prev_config = model._get_configuration() sys.stdout.flush() cov1.close() cov2.close() des.close() #*************************Finalize******************************* model.deallocate() print(prefix, "Finished!") status.close() return
'''This file is made to run with MyFirstDiffusion. This file does steps 1 by 1 and records the site occupations for each step at each site. ''' import os import math import pdb from kmcos.run import KMC_Model from kmc_settings import * model = KMC_Model() atoms = model.get_atoms(geometry=False) # represents the full directory path name that the kmcos directory is in with directory name last, have to add the _ or we cannot retrieve the last character dirpath_name = os.getcwd() + '_' simulation_size = model.size[0] # model.size gives you the size of the arrays which would be [3,3] for a model totalsites = simulation_size*simulation_size#with a sim_size of 3. spt = 20 # total number of steps sps = 1 # total number of steps per "snapshot" SNI = int(spt/sps) # number of s iterations Step = 0 SimulationName = 'MyFirstDiffusion' # Change to current simulation name for each run filename1 = '%s_OccupationPopulations.csv' %(SimulationName) with open(filename1, 'a') as f1: # headers for file1 f1.write('Step;') f1.write('Time;') f1.write('SiteA_SiteOccupation;') f1.write('SiteB_SiteOccupation;') f1.write('SiteC_SiteOccupation\n') for s in range(0,SNI+1): # snapshot iterations plus 1 because range always excludes the last number