Exemplo n.º 1
0
    def testBackendWithCustomRates(self):
        """ Test that we can construct the backend object with custom rates. """
        # A first process.
        coords = [[1.0, 2.0, 3.4], [1.1, 1.2, 1.3]]
        types0 = ["A", "B"]
        types1 = ["B", "A"]
        rate_0_1 = 3.5
        process_0 = KMCProcess(coords,
                               types0,
                               types1,
                               basis_sites=[0],
                               rate_constant=rate_0_1)

        # A second process.
        types0 = ["A", "C"]
        types1 = ["C", "A"]
        rate_0_1 = 1.5
        process_1 = KMCProcess(coords,
                               types0,
                               types1,
                               basis_sites=[0],
                               rate_constant=rate_0_1)

        processes = [process_0, process_1]

        # Set the custom rates class to use.
        custom_rates_class = CustomRateCalculator

        # Set the rate function on the custom rates calculator for testing.
        ref_rnd = numpy.random.uniform(0.0, 1.0)

        def testRateFunction(obj, coords, types_before, types_after,
                             rate_const, process_number, global_coordinate):
            return ref_rnd

        # Store the original.
        custom_rate_function = custom_rates_class.rate
        try:
            custom_rates_class.rate = testRateFunction

            # Construct the interactions object.
            kmc_interactions = KMCInteractions(processes=processes,
                                               implicit_wildcards=False)

            # Setup a dict with the possible types.
            possible_types = {
                "A": 13,
                "D": 2,
                "B": 3,
                "J": 4,
                "C": 5,
            }

            # Use a dummy argument for the configuration.
            config = "DummyConfig"

            # Test that it fails if the rate calculator is of wrong class.
            kmc_interactions.setRateCalculator(rate_calculator=Error)
            self.assertRaises(
                Error,
                lambda: kmc_interactions._backend(possible_types, 2, config))

            # Test that it fails if the rate calculator is the base class.
            kmc_interactions.setRateCalculator(
                rate_calculator=KMCRateCalculatorPlugin)
            self.assertRaises(
                Error,
                lambda: kmc_interactions._backend(possible_types, 2, config))

            # But this should work.
            kmc_interactions.setRateCalculator(
                rate_calculator=custom_rates_class)

            # Construct the backend.
            cpp_interactions = kmc_interactions._backend(
                possible_types, 2, config)

            # Test that the configuration on the custom rate class is the one given.
            self.assertTrue(
                kmc_interactions._KMCInteractions__rate_calculator.
                configuration == config)  #  <-  Check by reference.

            # Get the rate calculator reference out of the C++ object and
            # check that a call from C++ calls the Python extension.
            cpp_coords = Backend.StdVectorDouble()
            cpp_types1 = Backend.StdVectorString()
            cpp_types2 = Backend.StdVectorString()
            rate_constant = 543.2211
            process_number = 33
            coordinate = (1.2, 3.4, 5.6)

            self.assertAlmostEqual(
                cpp_interactions.rateCalculator().backendRateCallback(
                    cpp_coords,
                    cpp_coords.size() / 3, cpp_types1, cpp_types2,
                    rate_constant, process_number, coordinate[0],
                    coordinate[1], coordinate[2]), ref_rnd, 12)
            self.assertAlmostEqual(
                kmc_interactions._KMCInteractions__rate_calculator.
                backendRateCallback(cpp_coords,
                                    cpp_coords.size() / 3, cpp_types1,
                                    cpp_types2, rate_constant, process_number,
                                    coordinate[0], coordinate[1],
                                    coordinate[2]), ref_rnd, 12)

        finally:
            # Reset the class.
            custom_rates_class.rate = custom_rate_function

        # Construct a C++ RateCalculator object directly and check that this object
        # returns the rate given to it.
        cpp_rate_calculator = Backend.RateCalculator()
        self.assertAlmostEqual(
            cpp_rate_calculator.backendRateCallback(
                cpp_coords,
                cpp_coords.size() / 3, cpp_types1, cpp_types2, rate_constant,
                process_number, coordinate[0], coordinate[1], coordinate[2]),
            rate_constant, 12)
Exemplo n.º 2
0
    def testBackendWithCustomRates(self):
        """ Test that we can construct the backend object with custom rates. """
        # A first process.
        coords = [[1.0, 2.0, 3.4], [1.1, 1.2, 1.3]]
        types0 = ["A", "B"]
        types1 = ["B", "A"]
        rate_0_1 = 3.5
        process_0 = KMCProcess(coords,
                               types0,
                               types1,
                               basis_sites=[0],
                               rate_constant=rate_0_1)

        # A second process.
        types0 = ["A", "C"]
        types1 = ["C", "A"]
        rate_0_1 = 1.5
        process_1 = KMCProcess(coords,
                               types0,
                               types1,
                               basis_sites=[0],
                               rate_constant=rate_0_1)

        processes = [process_0, process_1]

        # Set the custom rates class to use.
        custom_rates_class = CustomRateCalculator

        # Construct the interactions object.
        kmc_interactions = KMCInteractions(processes=processes,
                                           implicit_wildcards=False)
        kmc_interactions.setRateCalculator(rate_calculator=custom_rates_class)

        # Set the rate function on the custom rates calculator for testing.
        ref_rnd = numpy.random.uniform(0.0, 1.0)

        def testRateFunction(coords, types_before, types_after, rate_const,
                             process_number, global_coordinate):
            return ref_rnd

        kmc_interactions._KMCInteractions__rate_calculator.rate = testRateFunction

        # Setup a dict with the possible types.
        possible_types = {
            "A": 13,
            "D": 2,
            "B": 3,
            "J": 4,
            "C": 5,
        }

        # Construct the backend.
        cpp_interactions = kmc_interactions._backend(possible_types, 2)

        # Get the rate calculator reference out of the C++ object and
        # check that a call from C++ calls the Python extension.
        cpp_coords = Backend.StdVectorDouble()
        cpp_types1 = Backend.StdVectorString()
        cpp_types2 = Backend.StdVectorString()
        rate_constant = 543.2211
        process_number = 33
        coordinate = (1.2, 3.4, 5.6)

        self.assertAlmostEqual(
            cpp_interactions.rateCalculator().backendRateCallback(
                cpp_coords,
                cpp_coords.size() / 3, cpp_types1, cpp_types2, rate_constant,
                process_number, coordinate[0], coordinate[1], coordinate[2]),
            ref_rnd, 12)
        self.assertAlmostEqual(
            kmc_interactions._KMCInteractions__rate_calculator.
            backendRateCallback(cpp_coords,
                                cpp_coords.size() / 3, cpp_types1, cpp_types2,
                                rate_constant, process_number, coordinate[0],
                                coordinate[1], coordinate[2]), ref_rnd, 12)

        # Construct a C++ RateCalculator object directly and check that this object
        # returns the rate given to it.
        cpp_rate_calculator = Backend.RateCalculator()
        self.assertAlmostEqual(
            cpp_rate_calculator.backendRateCallback(
                cpp_coords,
                cpp_coords.size() / 3, cpp_types1, cpp_types2, rate_constant,
                process_number, coordinate[0], coordinate[1], coordinate[2]),
            rate_constant, 12)