def testCreateInitialState(self): sg_ratio = 0.75 monomer_draw = [0.48772, 0.15174, 0.7886] initial_monomers = create_initial_monomers(sg_ratio, monomer_draw) initial_events = create_initial_events(initial_monomers, DEF_RXN_RATES) initial_state = create_initial_state(initial_events, initial_monomers) self.assertTrue(len(initial_state) == 3) self.assertTrue(str(initial_monomers[0]) == str(initial_state[0][MONOMER]))
def testCreate3Monomers(self): initial_monomers = create_initial_monomers(0.75, [0.48772, 0.15174, 0.7886]) self.assertTrue(len(initial_monomers) == 3) self.assertTrue(initial_monomers[0].type == S) self.assertTrue(initial_monomers[1].type == S) self.assertTrue(initial_monomers[2].type == G) self.assertTrue(initial_monomers[1] < initial_monomers[2]) self.assertFalse(initial_monomers[0] == initial_monomers[1])
def testFindScaling(self): test_scaling = False if test_scaling: # To test scaling: replicate batch runs with different numbers of monomers # Here, we are testing with equal amount of S and G (no C) times = [] sg_ratio = 1 pct_s = sg_ratio / (1 + sg_ratio) test_vals = np.linspace(50, 150, num=3, dtype='int32') num_repeats = 5 for num_monos in test_vals: print(f"Starting batch simulation with {num_monos} monomers") times.append([]) for i in range(num_repeats): random_seed = 8 + i np.random.seed(random_seed) print(f" Starting repeat", i) # Generate the initial monomers and events (oxidation) monomer_draw = np.random.rand(num_monos) initial_monomers = create_initial_monomers( pct_s, monomer_draw) initial_events = create_initial_events( initial_monomers, DEF_RXN_RATES) # Set the state and add the option to join initial monomers initial_state = create_initial_state( initial_events, initial_monomers) # Start timing the actual KMC part # noinspection PyUnboundLocalVariable start = time.time() run_kmc(DEF_RXN_RATES, initial_state, initial_events, sg_ratio=sg_ratio, random_seed=random_seed) end = time.time() times[-1].append(end - start) print( f'Average time to complete simulation with {num_monos:5n} monomers: ' f'{np.sum(times[-1]) / num_repeats:7.2f} seconds') # Now we want to fit the times that we just calculated to a generic power law expression $t = aN^b$ to find the # scaling of our algorithm. meas_t = [np.mean(one_time) for one_time in times] # sdev_t = [np.sqrt(np.var(one_time)) for one_time in times] meas_n = test_vals sim_t = lambda p, n: p[0] * np.power(n, p[1]) loss = lambda p: np.linalg.norm(sim_t(p, meas_n) - meas_t) results = optimize.minimize(loss, np.asarray([1e-5, 2.5]), bounds=[[0, 1], [0, 10]], options={'disp': True}) opt_p = results.x scaling_formula = f'$t = {opt_p[0]:3.1e}N^{{ {opt_p[1]:4.2f} }}$' print(f'Scaling: {scaling_formula}')
def testMissingRequiredSGRatio(self): # set up variable to allow running run_kmc without specifying sg_ratio initial_sg_ratio = 0.75 num_initial_monos = 3 monomer_draw = np.around(np.random.rand(num_initial_monos), MAX_NUM_DECIMAL) # these are tested separately initial_monomers = create_initial_monomers(initial_sg_ratio, monomer_draw) initial_events = create_initial_events(initial_monomers, DEF_RXN_RATES) initial_state = create_initial_state(initial_events, initial_monomers) events = {initial_events[i] for i in range(num_initial_monos)} events.add(Event(GROW, [], rate=1e4)) try: run_kmc(DEF_RXN_RATES, initial_state, sorted(events), n_max=20, t_max=1, random_seed=10) self.assertFalse("Should not arrive here; An error should have be raised") except InvalidDataError as e: self.assertTrue("A numeric sg_ratio" in e.args[0])
def generate_lignin(num_monomers: int = 1) -> Chem.Mol: """Generates lignin molecule. parameters ---------- num_monomers : int Number of monomers in lignin molecule. """ # Set the percentage of S sg_ratio = 0 pct_s = sg_ratio / (1 + sg_ratio) # Set the initial and maximum number of monomers to be modeled. ini_num_monos = 1 max_num_monos = num_monomers # Maximum time to simulate, in seconds t_max = 1 # seconds mono_add_rate = 1e4 # monomers/second # Use a random number and the given sg_ratio to determine the monolignol types to be initially modeled monomer_draw = np.random.rand(ini_num_monos) initial_monomers = create_initial_monomers(pct_s, monomer_draw) # Initially allow only oxidation events. After they are used to determine the initial state, add # GROW to the events, which allows additional monomers to be added to the reaction at the # specified rate and with the specified ratio initial_events = create_initial_events(initial_monomers, rxn_rates) initial_state = create_initial_state(initial_events, initial_monomers) initial_events.append(Event(GROW, [], rate=mono_add_rate)) # simulate lignin creation result = run_kmc(rxn_rates, initial_state, initial_events, n_max=max_num_monos, t_max=t_max, sg_ratio=sg_ratio) # using RDKit nodes = result[MONO_LIST] adj = result[ADJ_MATRIX] block = generate_mol(adj, nodes) mol = MolFromMolBlock(block) mol = Chem.AddHs(mol) return mol
def create_sample_kmc_result(max_time=1., num_initial_monos=3, max_monos=10, sg_ratio=0.75, seed=10): # The set lists are to minimize randomness in testing (adding while debugging source of randomness in some tests; # leaving because it doesn't hurt a thing; also leaving option to make a monomer_draw of arbitrary length # using a seed, but rounding those numbers because the machine precision differences in floats was the bug np.random.seed(seed) if num_initial_monos == 3: monomer_draw = MONO_DRAW_3 elif num_initial_monos == 20: monomer_draw = [0.77132064, 0.02075195, 0.63364823, 0.74880388, 0.49850701, 0.22479665, 0.19806286, 0.76053071, 0.16911084, 0.08833981, 0.68535982, 0.95339335, 0.00394827, 0.51219226, 0.81262096, 0.61252607, 0.72175532, 0.29187607, 0.91777412, 0.71457578] else: monomer_draw = np.around(np.random.rand(num_initial_monos), MAX_NUM_DECIMAL) # these are tested separately elsewhere initial_monomers = create_initial_monomers(sg_ratio, monomer_draw) initial_events = create_initial_events(initial_monomers, DEF_RXN_RATES) initial_state = OrderedDict(create_initial_state(initial_events, initial_monomers)) initial_events.append(Event(GROW, [], rate=1e4)) result = run_kmc(DEF_RXN_RATES, initial_state, initial_events, n_max=max_monos, t_max=max_time, random_seed=10, sg_ratio=sg_ratio) return result
# Set the percentage of S sg_ratio = 1 pct_s = sg_ratio / (1 + sg_ratio) # Set the initial and maximum number of monomers to be modeled. ini_num_monos = 2 max_num_monos = 10 # Maximum time to simulate, in seconds t_max = 1 # seconds mono_add_rate = 1e4 # monomers/second # Use a random number and the given sg_ratio to determine the monolignol types to be initially modeled monomer_draw = np.random.rand(ini_num_monos) initial_monomers = create_initial_monomers(pct_s, monomer_draw) # Initially allow only oxidation events. After they are used to determine the initial state, add # GROW to the events, which allows additional monomers to be added to the reaction at the # specified rate and with the specified ratio initial_events = create_initial_events(initial_monomers, rxn_rates) initial_state = create_initial_state(initial_events, initial_monomers) initial_events.append(Event(GROW, [], rate=mono_add_rate)) result = run_kmc(rxn_rates, initial_state, initial_events, n_max=max_num_monos, t_max=t_max, sg_ratio=sg_ratio)