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])
예제 #3
0
    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
예제 #7
0
# 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)