def numpy2DArrayToStdVectorStdVectorDouble(array): """ Convert a 2D numpy array to a std::vector<std::vector<double> > representation. :param array: The array to convert. :returns: A corresponding std::vector<std::vector<double> > object. """ # Get the shape of the array. shape = numpy.shape(array) nI = shape[0] nJ = shape[1] # Setup the c++ object. cpp_2D_vector = Backend.StdVectorStdVectorDouble(nI) # Copy the values over. for i in range(nI): cpp_vector = Backend.StdVectorDouble(nJ) for j in range(nJ): cpp_vector[j] = array[i][j] cpp_2D_vector[i] = cpp_vector # Done. return cpp_2D_vector
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)
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)