// -------------------------------------------------------------------------- // // void Test_Configuration::testMatchLists() { // Setup a configuration. std::vector< std::vector<double> > basis(3, std::vector<double>(3,0.0)); basis[1][0] = 0.25; basis[1][1] = 0.25; basis[1][2] = 0.25; basis[2][0] = 0.75; basis[2][1] = 0.75; basis[2][2] = 0.75; std::vector<int> basis_sites(3); basis_sites[0] = 0; basis_sites[1] = 1; basis_sites[2] = 2; std::vector<std::string> basis_elements(3); basis_elements[0] = "A"; basis_elements[1] = "B"; basis_elements[2] = "B"; // Make a 37x18x19 structure. const int nI = 37; const int nJ = 18; const int nK = 19; const int nB = 3; // Coordinates and elements. std::vector<std::vector<double> > coordinates; std::vector<std::string> elements; for (int i = 0; i < nI; ++i) { for (int j = 0; j < nJ; ++j) { for (int k = 0; k < nK; ++k) { for (int b = 0; b < nB; ++b) { std::vector<double> c(3); c[0] = i + basis[b][0]; c[1] = j + basis[b][1]; c[2] = k + basis[b][2]; coordinates.push_back(c); elements.push_back(basis_elements[b]); } } } } elements[0] = "V"; elements[216] = "V"; elements[1434] = "V"; elements[2101] = "V"; // Possible types. std::map<std::string, int> possible_types; possible_types["*"] = 0; possible_types["A"] = 1; possible_types["B"] = 2; possible_types["V"] = 3; // Setup the configuration. Configuration configuration(coordinates, elements, possible_types); // Setup the lattice map. std::vector<int> repetitions(3); repetitions[0] = nI; repetitions[1] = nJ; repetitions[2] = nK; std::vector<bool> periodicity(3, true); LatticeMap lattice_map(nB, repetitions, periodicity); // Try to access the match lists before initialization. They should be // empty. CPPUNIT_ASSERT( configuration.minimalMatchList(10).empty() ); CPPUNIT_ASSERT( configuration.minimalMatchList(2101).empty() ); CPPUNIT_ASSERT( configuration.minimalMatchList(1434).empty() ); // Init the match lists. configuration.initMatchLists(lattice_map, 1); // This did something. CPPUNIT_ASSERT( !configuration.minimalMatchList(10).empty() ); CPPUNIT_ASSERT( !configuration.minimalMatchList(2101).empty() ); CPPUNIT_ASSERT( !configuration.minimalMatchList(1434).empty() ); // Get the match list the hard way. const std::vector<MinimalMatchListEntry> ref_1434 = \ configuration.minimalMatchList( 1434, lattice_map.neighbourIndices(1434), lattice_map); // Check the size. CPPUNIT_ASSERT_EQUAL( static_cast<int>(ref_1434.size()), static_cast<int>(configuration.minimalMatchList(1434).size()) ); // Check the values. for (size_t i = 0; i < ref_1434.size(); ++i) { CPPUNIT_ASSERT_EQUAL( ref_1434[i].match_type, configuration.minimalMatchList(1434)[i].match_type ); CPPUNIT_ASSERT_EQUAL( ref_1434[i].update_type, configuration.minimalMatchList(1434)[i].update_type ); CPPUNIT_ASSERT_EQUAL( ref_1434[i].index, configuration.minimalMatchList(1434)[i].index ); CPPUNIT_ASSERT_DOUBLES_EQUAL( ref_1434[i].distance, configuration.minimalMatchList(1434)[i].distance, 1.0e-14 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( ref_1434[i].coordinate.x(), configuration.minimalMatchList(1434)[i].coordinate.x(), 1.0e-14 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( ref_1434[i].coordinate.y(), configuration.minimalMatchList(1434)[i].coordinate.y(), 1.0e-14 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( ref_1434[i].coordinate.z(), configuration.minimalMatchList(1434)[i].coordinate.z(), 1.0e-14 ); } // Setup a process that changes V to B. // Get a process that finds a V between two B and turns one of // the Bs into an A. std::vector<std::string> process_elements1(3); process_elements1[0] = "V"; process_elements1[1] = "B"; process_elements1[2] = "B"; std::vector<std::string> process_elements2(3); process_elements2[0] = "B"; process_elements2[1] = "A"; process_elements2[2] = "B"; std::vector<std::vector<double> > process_coordinates(3, std::vector<double>(3, 0.0)); process_coordinates[1][0] = -0.25; process_coordinates[1][1] = -0.25; process_coordinates[1][2] = -0.25; process_coordinates[2][0] = 0.25; process_coordinates[2][1] = 0.25; process_coordinates[2][2] = 0.25; const double rate = 13.7; Configuration c1(process_coordinates, process_elements1, possible_types); Configuration c2(process_coordinates, process_elements2, possible_types); Process p(c1, c2, rate, basis_sites); // Now, add index 1434 to the process. // We know by construction that these match. p.addSite(1434, 0.0); // For site 1434 // 350 changes from 1 to 0 // 1434 changes from 2 to 1 // All other must remain unchanged. CPPUNIT_ASSERT_EQUAL( configuration.types()[1434], 3 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[350], 2 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[1433], 2 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[349], 2 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[351], 1 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[2517], 1 ); // Peform the process. configuration.performProcess(p, 1434); // Check that the types were correctly updated. CPPUNIT_ASSERT_EQUAL( configuration.types()[1434], 2 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[350], 1 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[1433], 2 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[349], 2 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[351], 1 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[2517], 1 ); // Check that updating the matchlist gets us the correct values. configuration.updateMatchList(1434); // Reference. const std::vector<MinimalMatchListEntry> ref2_1434 = \ configuration.minimalMatchList( 1434, lattice_map.neighbourIndices(1434), lattice_map); // Check the size. CPPUNIT_ASSERT_EQUAL( static_cast<int>(ref2_1434.size()), static_cast<int>(configuration.minimalMatchList(1434).size()) ); // Check the values. for (size_t i = 0; i < ref2_1434.size(); ++i) { CPPUNIT_ASSERT_EQUAL( ref2_1434[i].match_type, configuration.minimalMatchList(1434)[i].match_type ); CPPUNIT_ASSERT_EQUAL( ref2_1434[i].update_type, configuration.minimalMatchList(1434)[i].update_type ); CPPUNIT_ASSERT_EQUAL( ref2_1434[i].index, configuration.minimalMatchList(1434)[i].index ); CPPUNIT_ASSERT_DOUBLES_EQUAL( ref2_1434[i].distance, configuration.minimalMatchList(1434)[i].distance, 1.0e-14 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( ref2_1434[i].coordinate.x(), configuration.minimalMatchList(1434)[i].coordinate.x(), 1.0e-14 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( ref2_1434[i].coordinate.y(), configuration.minimalMatchList(1434)[i].coordinate.y(), 1.0e-14 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( ref2_1434[i].coordinate.z(), configuration.minimalMatchList(1434)[i].coordinate.z(), 1.0e-14 ); } }
// -------------------------------------------------------------------------- // // void Test_Configuration::testPerformProcess() { // Setup a realistic system. std::vector< std::vector<double> > basis(3, std::vector<double>(3,0.0)); basis[1][0] = 0.25; basis[1][1] = 0.25; basis[1][2] = 0.25; basis[2][0] = 0.75; basis[2][1] = 0.75; basis[2][2] = 0.75; std::vector<int> basis_sites(3); basis_sites[0] = 0; basis_sites[1] = 1; basis_sites[2] = 2; std::vector<std::string> basis_elements(3); basis_elements[0] = "A"; basis_elements[1] = "B"; basis_elements[2] = "B"; // Make a 37x18x19 structure. const int nI = 37; const int nJ = 18; const int nK = 19; const int nB = 3; // Coordinates and elements. std::vector<std::vector<double> > coordinates; std::vector<std::string> elements; for (int i = 0; i < nI; ++i) { for (int j = 0; j < nJ; ++j) { for (int k = 0; k < nK; ++k) { for (int b = 0; b < nB; ++b) { std::vector<double> c(3); c[0] = i + basis[b][0]; c[1] = j + basis[b][1]; c[2] = k + basis[b][2]; coordinates.push_back(c); elements.push_back(basis_elements[b]); } } } } elements[0] = "V"; elements[216] = "V"; // These affects process 0,1 and 3 elements[1434] = "V"; elements[2101] = "V"; // This affects process 0,1 and 2 // Possible types. std::map<std::string, int> possible_types; possible_types["*"] = 0; possible_types["A"] = 1; possible_types["B"] = 2; possible_types["V"] = 3; // Setup the configuration. Configuration configuration(coordinates, elements, possible_types); // Setup the lattice map. std::vector<int> repetitions(3); repetitions[0] = nI; repetitions[1] = nJ; repetitions[2] = nK; std::vector<bool> periodicity(3, true); LatticeMap lattice_map(nB, repetitions, periodicity); // Init the match lists. configuration.initMatchLists(lattice_map, 1); // Get a process that finds a V between two B and turns one of // the Bs into an A. std::vector<std::string> process_elements1(3); process_elements1[0] = "V"; process_elements1[1] = "B"; process_elements1[2] = "B"; std::vector<std::string> process_elements2(3); process_elements2[0] = "B"; process_elements2[1] = "A"; process_elements2[2] = "B"; std::vector<std::vector<double> > process_coordinates(3, std::vector<double>(3, 0.0)); process_coordinates[1][0] = -0.25; process_coordinates[1][1] = -0.25; process_coordinates[1][2] = -0.25; process_coordinates[2][0] = 0.25; process_coordinates[2][1] = 0.25; process_coordinates[2][2] = 0.25; const double rate = 13.7; Configuration c1(process_coordinates, process_elements1, possible_types); Configuration c2(process_coordinates, process_elements2, possible_types); Process p(c1, c2, rate, basis_sites); // Now, add index 1434 to the process. // We know by construction that these match. p.addSite(1434, 0.0); // For site 1434 // 350 changes from 1 to 0 // 1434 changes from 2 to 1 // All other must remain unchanged. CPPUNIT_ASSERT_EQUAL( configuration.types()[1434], 3 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[350], 2 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[1433], 2 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[349], 2 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[351], 1 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[2517], 1 ); // Peform the process. configuration.performProcess(p, 1434); // Check that the types were correctly updated. CPPUNIT_ASSERT_EQUAL( configuration.types()[1434], 2 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[350], 1 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[1433], 2 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[349], 2 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[351], 1 ); CPPUNIT_ASSERT_EQUAL( configuration.types()[2517], 1 ); // Check that the correct indices were added to the list of affected. const std::vector<int> affected = p.affectedIndices(); CPPUNIT_ASSERT_EQUAL( affected[0], 1434 ); CPPUNIT_ASSERT_EQUAL( affected[1], 350 ); }
// -------------------------------------------------------------------------- // // void Test_Interactions::testUpdateProcessIDMoves() { // Setup two valid processes. std::vector<Process> processes; std::vector<std::string> process_elements1(3); process_elements1[0] = "A"; process_elements1[1] = "B"; process_elements1[2] = "V"; std::vector<std::string> process_elements2(3); process_elements2[0] = "B"; process_elements2[1] = "A"; process_elements2[2] = "A"; std::vector<std::vector<double> > process_coordinates1(3, std::vector<double>(3, 0.0)); process_coordinates1[1][0] = -1.0; process_coordinates1[1][1] = 0.0; process_coordinates1[1][2] = 0.0; process_coordinates1[2][0] = 0.3; process_coordinates1[2][1] = 0.3; process_coordinates1[2][2] = 0.3; std::vector<int> move_origins; move_origins.push_back(0); move_origins.push_back(1); std::vector<Coordinate> move_vectors; move_vectors.push_back( Coordinate(-1.0, 0.0, 0.0) ); move_vectors.push_back( Coordinate( 1.0, 0.0, 0.0) ); // Possible types. std::map<std::string, int> possible_types; possible_types["*"] = 0; possible_types["A"] = 1; possible_types["B"] = 2; possible_types["V"] = 3; const double rate = 13.7; const Configuration c1(process_coordinates1, process_elements1, possible_types); const Configuration c2(process_coordinates1, process_elements2, possible_types); // Let this process be valid at site 0. processes.push_back(Process(c1,c2,rate,std::vector<int>(1,0), move_origins, move_vectors)); // Let this process be valid at sites 0 and 2. std::vector<int> sites_vector(2,0); sites_vector[1] = 2; processes.push_back(Process(c1,c2,rate,sites_vector, move_origins, move_vectors)); std::vector<std::vector<double> > process_coordinates2(3, std::vector<double>(3, 0.0)); process_coordinates2[1][0] = 0.7; process_coordinates2[1][1] = 0.7; process_coordinates2[1][2] = -0.3; process_coordinates2[2][0] = 1.0; process_coordinates2[2][1] = 1.0; process_coordinates2[2][2] = 1.0; move_vectors[0] = Coordinate( 0.7, 0.7, -0.3); move_vectors[1] = Coordinate(-0.7,-0.7, 0.3); const Configuration c3(process_coordinates2, process_elements1, possible_types); const Configuration c4(process_coordinates2, process_elements2, possible_types); // Let the process be valid at site 1. processes.push_back(Process(c3,c4,rate,std::vector<int>(1,1), move_origins, move_vectors)); Interactions interactions(processes, true); // Generate a corresponding configuration. std::vector<std::vector<double> > config_coordinates; std::vector<std::string> elements; for (int i = 0; i < 5; ++i) { for (int j = 0; j < 5; ++j) { for (int k = 0; k < 5; ++k) { std::vector<double> coord(3); coord[0] = 0.0 + i*1.0; coord[1] = 0.0 + j*1.0; coord[2] = 0.0 + k*1.0; config_coordinates.push_back(coord); elements.push_back("V"); coord[0] = 0.3 + i*1.0; coord[1] = 0.3 + j*1.0; coord[2] = 0.3 + k*1.0; elements.push_back("B"); config_coordinates.push_back(coord); } } } // Get the config and lattice map. Configuration config(config_coordinates, elements, possible_types); const LatticeMap lattice_map(2, std::vector<int>(3,5), std::vector<bool>(3,true)); // Now, setup the matchlists in the configuration. config.initMatchLists(lattice_map, interactions.maxRange()); // Check the process match lists before we start. CPPUNIT_ASSERT_EQUAL(static_cast<int>(interactions.processes()[0]->minimalMatchList().size()), 3); CPPUNIT_ASSERT_EQUAL(static_cast<int>(interactions.processes()[1]->minimalMatchList().size()), 3); CPPUNIT_ASSERT_EQUAL(static_cast<int>(interactions.processes()[2]->minimalMatchList().size()), 3); // Check the id moves before update. { const std::vector< std::pair<int, int> > & id_moves = interactions.processes()[0]->idMoves(); CPPUNIT_ASSERT_EQUAL( static_cast<int>(id_moves.size()), 2 ); CPPUNIT_ASSERT_EQUAL( id_moves[0].first, 0 ); CPPUNIT_ASSERT_EQUAL( id_moves[0].second, 2 ); CPPUNIT_ASSERT_EQUAL( id_moves[1].first, 2 ); CPPUNIT_ASSERT_EQUAL( id_moves[1].second, 0 ); } // Update the interactions according to the configuration match lists. // This also updates the id moves on the processes. interactions.updateProcessMatchLists(config, lattice_map); // Check the id moves after update. { const std::vector<MinimalMatchListEntry> & match = interactions.processes()[0]->minimalMatchList(); CPPUNIT_ASSERT_EQUAL( static_cast<int>(match.size()), 6 ); const std::vector< std::pair<int, int> > & id_moves = interactions.processes()[0]->idMoves(); CPPUNIT_ASSERT_EQUAL( static_cast<int>(id_moves.size()), 2 ); CPPUNIT_ASSERT_EQUAL( id_moves[0].first, 0 ); CPPUNIT_ASSERT_EQUAL( id_moves[0].second, 5 ); CPPUNIT_ASSERT_EQUAL( id_moves[1].first, 5 ); CPPUNIT_ASSERT_EQUAL( id_moves[1].second, 0 ); // Wildcards are now added. CPPUNIT_ASSERT_EQUAL( match[0].match_type, 1 ); CPPUNIT_ASSERT_EQUAL( match[1].match_type, 3 ); CPPUNIT_ASSERT_EQUAL( match[2].match_type, 0 ); CPPUNIT_ASSERT_EQUAL( match[3].match_type, 0 ); CPPUNIT_ASSERT_EQUAL( match[4].match_type, 0 ); CPPUNIT_ASSERT_EQUAL( match[5].match_type, 2 ); } }
// -------------------------------------------------------------------------- // // void Test_Interactions::testUpdateProcessMatchLists() { // Setup two valid processes. std::vector<Process> processes; std::vector<std::string> process_elements1(3); process_elements1[0] = "A"; process_elements1[1] = "B"; process_elements1[2] = "V"; std::vector<std::string> process_elements2(3); process_elements2[0] = "B"; process_elements2[1] = "A"; process_elements2[2] = "A"; std::vector<std::vector<double> > process_coordinates1(3, std::vector<double>(3, 0.0)); process_coordinates1[1][0] = -1.0; process_coordinates1[1][1] = 0.0; process_coordinates1[1][2] = 0.0; process_coordinates1[2][0] = 0.3; process_coordinates1[2][1] = 0.3; process_coordinates1[2][2] = 0.3; // Possible types. std::map<std::string, int> possible_types; possible_types["*"] = 0; possible_types["A"] = 1; possible_types["B"] = 2; possible_types["V"] = 3; const double rate = 13.7; const Configuration c1(process_coordinates1, process_elements1, possible_types); const Configuration c2(process_coordinates1, process_elements2, possible_types); // Let this process be valid at site 0. processes.push_back(Process(c1,c2,rate,std::vector<int>(1,0))); // Let this process be valid at sites 0 and 2. std::vector<int> sites_vector(2,0); sites_vector[1] = 2; processes.push_back(Process(c1,c2,rate,sites_vector)); std::vector<std::vector<double> > process_coordinates2(3, std::vector<double>(3, 0.0)); process_coordinates2[1][0] = 0.7; process_coordinates2[1][1] = 0.7; process_coordinates2[1][2] = -0.3; process_coordinates2[2][0] = 1.0; process_coordinates2[2][1] = 1.0; process_coordinates2[2][2] = 1.0; const Configuration c3(process_coordinates2, process_elements1, possible_types); const Configuration c4(process_coordinates2, process_elements2, possible_types); // Let the process be valid at site 1. processes.push_back(Process(c3,c4,rate,std::vector<int>(1,1))); Interactions interactions(processes, true); // Generate a corresponding configuration. std::vector<std::vector<double> > config_coordinates; std::vector<std::string> elements; for (int i = 0; i < 5; ++i) { for (int j = 0; j < 5; ++j) { for (int k = 0; k < 5; ++k) { std::vector<double> coord(3); coord[0] = 0.0 + i*1.0; coord[1] = 0.0 + j*1.0; coord[2] = 0.0 + k*1.0; config_coordinates.push_back(coord); elements.push_back("V"); coord[0] = 0.3 + i*1.0; coord[1] = 0.3 + j*1.0; coord[2] = 0.3 + k*1.0; elements.push_back("B"); config_coordinates.push_back(coord); } } } // Get the config and lattice map. Configuration config(config_coordinates, elements, possible_types); // Make sure we do this on a non-periodic lattice map, to make sure // the most central cell is choosen for determining wildcard positions. const LatticeMap lattice_map(2, std::vector<int>(3,5), std::vector<bool>(3,false)); // Now, setup the matchlists in the configuration. config.initMatchLists(lattice_map, interactions.maxRange()); // Check the process match lists before we start. CPPUNIT_ASSERT_EQUAL(static_cast<int>(interactions.processes()[0]->minimalMatchList().size()), 3); CPPUNIT_ASSERT_EQUAL(static_cast<int>(interactions.processes()[1]->minimalMatchList().size()), 3); CPPUNIT_ASSERT_EQUAL(static_cast<int>(interactions.processes()[2]->minimalMatchList().size()), 3); // Update the interactions according to the configuration match lists. interactions.updateProcessMatchLists(config, lattice_map); // Check a few coordinates and match types. { const std::vector<MinimalMatchListEntry> & match = interactions.processes()[0]->minimalMatchList(); CPPUNIT_ASSERT_EQUAL( static_cast<int>(match.size()), 6 ); // Wildcards are now added. CPPUNIT_ASSERT_EQUAL( match[0].match_type, 1 ); CPPUNIT_ASSERT_EQUAL( match[1].match_type, 3 ); CPPUNIT_ASSERT_EQUAL( match[2].match_type, 0 ); CPPUNIT_ASSERT_EQUAL( match[3].match_type, 0 ); CPPUNIT_ASSERT_EQUAL( match[4].match_type, 0 ); CPPUNIT_ASSERT_EQUAL( match[5].match_type, 2 ); // These are not changed - but sorted. CPPUNIT_ASSERT_DOUBLES_EQUAL( match[0].coordinate.x(), process_coordinates1[0][0], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[0].coordinate.y(), process_coordinates1[0][1], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[0].coordinate.z(), process_coordinates1[0][2], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[1].coordinate.x(), process_coordinates1[2][0], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[1].coordinate.y(), process_coordinates1[2][1], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[1].coordinate.z(), process_coordinates1[2][2], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[5].coordinate.x(), process_coordinates1[1][0], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[5].coordinate.y(), process_coordinates1[1][1], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[5].coordinate.z(), process_coordinates1[1][2], 1.0e-10 ); // Here are the added wildcards. CPPUNIT_ASSERT_DOUBLES_EQUAL( match[2].coordinate.x(), -0.7, 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[2].coordinate.y(), 0.3, 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[2].coordinate.z(), 0.3, 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[3].coordinate.x(), 0.3, 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[3].coordinate.y(), -0.7, 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[3].coordinate.z(), 0.3, 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[4].coordinate.x(), 0.3, 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[4].coordinate.y(), 0.3, 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[4].coordinate.z(), -0.7, 1.0e-10 ); } { // This one is not changed, since it was applicable to more than one basis site. const std::vector<MinimalMatchListEntry> & match = interactions.processes()[1]->minimalMatchList(); CPPUNIT_ASSERT_EQUAL( static_cast<int>(match.size()), 3 ); // Not changed - but sorted. CPPUNIT_ASSERT_DOUBLES_EQUAL( match[0].coordinate.x(), process_coordinates1[0][0], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[0].coordinate.y(), process_coordinates1[0][1], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[0].coordinate.z(), process_coordinates1[0][2], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[1].coordinate.x(), process_coordinates1[2][0], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[1].coordinate.y(), process_coordinates1[2][1], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[1].coordinate.z(), process_coordinates1[2][2], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[2].coordinate.x(), process_coordinates1[1][0], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[2].coordinate.y(), process_coordinates1[1][1], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[2].coordinate.z(), process_coordinates1[1][2], 1.0e-10 ); } { const std::vector<MinimalMatchListEntry> & match = interactions.processes()[2]->minimalMatchList(); CPPUNIT_ASSERT_EQUAL( static_cast<int>(match.size()), 47 ); // Not changed. CPPUNIT_ASSERT_DOUBLES_EQUAL( match[0].coordinate.x(), process_coordinates2[0][0], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[0].coordinate.y(), process_coordinates2[0][1], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[0].coordinate.z(), process_coordinates2[0][2], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[13].coordinate.x(), process_coordinates2[1][0], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[13].coordinate.y(), process_coordinates2[1][1], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[13].coordinate.z(), process_coordinates2[1][2], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[46].coordinate.x(), process_coordinates2[2][0], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[46].coordinate.y(), process_coordinates2[2][1], 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[46].coordinate.z(), process_coordinates2[2][2], 1.0e-10 ); // These are the added wildcards. for (int i = 0; i < 47; ++i) { if (i != 0 && i != 13 && i != 46) { CPPUNIT_ASSERT_EQUAL( match[i].match_type, 0 ); } } // Check one coordinate. CPPUNIT_ASSERT_DOUBLES_EQUAL( match[17].coordinate.x(),-0.3, 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[17].coordinate.y(),-0.3, 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[17].coordinate.z(),-1.3, 1.0e-10 ); // Check another one. CPPUNIT_ASSERT_DOUBLES_EQUAL( match[18].coordinate.x(),-1.0, 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[18].coordinate.y(),-1.0, 1.0e-10 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( match[18].coordinate.z(), 0.0, 1.0e-10 ); } }
// -------------------------------------------------------------------------- // // void Test_Interactions::testMaxRange() { // Setup two valid processes. std::vector<Process> processes; std::vector<std::string> process_elements1(3); process_elements1[0] = "A"; process_elements1[1] = "A"; process_elements1[2] = "A"; std::vector<std::string> process_elements2(3); process_elements2[0] = "B"; process_elements2[1] = "A"; process_elements2[2] = "A"; std::vector<std::vector<double> > process_coordinates(3, std::vector<double>(3, 0.0)); process_coordinates[1][0] = -0.1; process_coordinates[1][1] = -0.1; process_coordinates[1][2] = -0.1; // Possible types. std::map<std::string, int> possible_types; possible_types["A"] = 0; possible_types["B"] = 1; possible_types["V"] = 2; const double rate = 13.7; const Configuration c1(process_coordinates, process_elements1, possible_types); const Configuration c2(process_coordinates, process_elements2, possible_types); std::vector<int> sites_vector(0); processes.push_back(Process(c1,c2,rate,sites_vector)); processes.push_back(Process(c1,c2,rate,sites_vector)); // Setup the interactions object. const Interactions interactions(processes, true); // This should have the max range 1. CPPUNIT_ASSERT_EQUAL( interactions.maxRange(), 1 ); // Adding a process with a -1.1 site should make the max range become 2. process_coordinates[1][0] = 0.0; process_coordinates[1][1] = 0.0; process_coordinates[1][2] = -1.1; const Configuration c3(process_coordinates, process_elements1, possible_types); const Configuration c4(process_coordinates, process_elements2, possible_types); processes.push_back(Process(c3,c4,rate,sites_vector)); // This should have the max range 2. const Interactions interactions2(processes, true); CPPUNIT_ASSERT_EQUAL( interactions2.maxRange(), 2 ); // Check the same thing in y. process_coordinates[1][0] = 0.0; process_coordinates[1][1] = -2.1; process_coordinates[1][2] = 0.0; const Configuration c5(process_coordinates, process_elements1, possible_types); const Configuration c6(process_coordinates, process_elements2, possible_types); processes[2] = Process(c5,c6,rate,sites_vector); // This should have the max range 3. const Interactions interactions3(processes, true); CPPUNIT_ASSERT_EQUAL( interactions3.maxRange(), 3 ); // And in x. process_coordinates[1][0] = -3.1; process_coordinates[1][1] = 0.0; process_coordinates[1][2] = 0.0; const Configuration c7(process_coordinates, process_elements1, possible_types); const Configuration c8(process_coordinates, process_elements2, possible_types); processes[2] = Process(c7,c8,rate,sites_vector); // This should have the max range 4. const Interactions interactions4(processes, true); CPPUNIT_ASSERT_EQUAL( interactions4.maxRange(), 4 ); // And in the positive direction. // Adding a process with a 5.1 site should make the max range become 5. process_coordinates[1][0] = 0.0; process_coordinates[1][1] = 0.0; process_coordinates[1][2] = 5.1; const Configuration c9(process_coordinates, process_elements1, possible_types); const Configuration c10(process_coordinates, process_elements2, possible_types); processes[2] = Process(c9,c10,rate,sites_vector); // This should have the max range 5. const Interactions interactions5(processes, true); CPPUNIT_ASSERT_EQUAL( interactions5.maxRange(), 5 ); // Check the same thing in y. process_coordinates[1][0] = 0.0; process_coordinates[1][1] = 2.1; process_coordinates[1][2] = 0.0; const Configuration c11(process_coordinates, process_elements1, possible_types); const Configuration c12(process_coordinates, process_elements2, possible_types); processes[2] = Process(c11,c12,rate,sites_vector); // This should have the max range 2. const Interactions interactions6(processes, true); CPPUNIT_ASSERT_EQUAL( interactions6.maxRange(), 2 ); // And in x. process_coordinates[1][0] = 4.1; process_coordinates[1][1] = 0.0; process_coordinates[1][2] = 0.0; const Configuration c13(process_coordinates, process_elements1, possible_types); const Configuration c14(process_coordinates, process_elements2, possible_types); processes[2] = Process(c13,c14,rate,sites_vector); // This should have the max range 4. const Interactions interactions7(processes, true); CPPUNIT_ASSERT_EQUAL( interactions7.maxRange(), 4 ); }
// -------------------------------------------------------------------------- // // void Test_Interactions::testQuery() { // Setup two valid processes. std::vector<Process> processes; // Possible types. std::map<std::string, int> possible_types; possible_types["A"] = 0; possible_types["B"] = 1; possible_types["V"] = 2; // A process that independent of local environment swaps a "B" to "V" { const std::vector<std::string> process_elements1(1,"B"); const std::vector<std::string> process_elements2(1,"V"); const std::vector<std::vector<double> > process_coordinates(1, std::vector<double>(3, 0.0)); const double rate = 1.234; Configuration c1(process_coordinates, process_elements1, possible_types); Configuration c2(process_coordinates, process_elements2, possible_types); Process p(c1, c2, rate, std::vector<int>(1,0)); // Store twize. processes.push_back(p); processes.push_back(p); } // A process that finds an A between two B's in the 1,1,1 direction // and swap the A and the first B. { std::vector<std::string> process_elements1(3); process_elements1[0] = "A"; process_elements1[1] = "B"; process_elements1[2] = "B"; std::vector<std::string> process_elements2(3); process_elements2[0] = "B"; process_elements2[1] = "A"; process_elements2[2] = "B"; std::vector<std::vector<double> > process_coordinates(3, std::vector<double>(3, 0.0)); process_coordinates[1][0] = -0.25; process_coordinates[1][1] = -0.25; process_coordinates[1][2] = -0.25; process_coordinates[2][0] = 0.25; process_coordinates[2][1] = 0.25; process_coordinates[2][2] = 0.25; const double rate = 13.7; Configuration c1(process_coordinates, process_elements1, possible_types); Configuration c2(process_coordinates, process_elements2, possible_types); Process p(c1, c2, rate, std::vector<int>(1,0)); processes.push_back(p); } // Setup the interactions object. Interactions interactions(processes, false); // Query for the processes. const std::vector<Process*> & queried_processes = interactions.processes(); // Check the length of the list of processes. CPPUNIT_ASSERT_EQUAL( static_cast<int>(queried_processes.size()), 3 ); // Get the types in the queried processes and check. CPPUNIT_ASSERT_EQUAL( queried_processes[0]->minimalMatchList()[0].match_type, 1 ); CPPUNIT_ASSERT_EQUAL( queried_processes[0]->minimalMatchList()[0].update_type, 2 ); CPPUNIT_ASSERT_EQUAL( queried_processes[2]->minimalMatchList()[2].match_type, 1 ); CPPUNIT_ASSERT_EQUAL( queried_processes[2]->minimalMatchList()[2].update_type, 1 ); // Query for the total number of available sites. This is zero since no sites are added to // the processes. CPPUNIT_ASSERT_EQUAL( interactions.totalAvailableSites(), 0 ); // Add sites to the processes and see that we get the correct number out. interactions.processes()[0]->addSite(12); interactions.processes()[0]->addSite(143); interactions.processes()[0]->addSite(1654); interactions.processes()[0]->addSite(177777); interactions.processes()[1]->addSite(12); interactions.processes()[1]->addSite(143); interactions.processes()[2]->addSite(1654); interactions.processes()[2]->addSite(177777); interactions.processes()[2]->addSite(177777); CPPUNIT_ASSERT_EQUAL( interactions.totalAvailableSites(), 9 ); // Query for the rate calculator. const RateCalculator & rc = interactions.rateCalculator(); CPPUNIT_ASSERT( &rc != NULL ); }
// -------------------------------------------------------------------------- // // void Test_Interactions::testUpdateAndPickCustom() { // Setup a list of custom rate processes. std::vector<CustomRateProcess> processes; // Setup a vector of dummy processes. std::vector<std::string> process_elements1(1); process_elements1[0] = "A"; std::vector<std::string> process_elements2(1); process_elements2[0] = "B"; std::vector<std::vector<double> > process_coordinates(1, std::vector<double>(3, 0.0)); // Possible types. std::map<std::string, int> possible_types; possible_types["A"] = 0; possible_types["B"] = 1; possible_types["V"] = 2; const double rate = 1.0/13.7; Configuration c1(process_coordinates, process_elements1, possible_types); Configuration c2(process_coordinates, process_elements2, possible_types); std::vector<int> sites_vector(1,0); processes.push_back(CustomRateProcess(c1,c2,rate,sites_vector, 1.0)); processes.push_back(CustomRateProcess(c1,c2,rate,sites_vector, 1.0)); processes.push_back(CustomRateProcess(c1,c2,rate/2.0,sites_vector, 1.0)); processes.push_back(CustomRateProcess(c1,c2,rate,sites_vector, 1.0)); processes.push_back(CustomRateProcess(c1,c2,rate,sites_vector, 1.0)); processes.push_back(CustomRateProcess(c1,c2,rate,sites_vector, 1.0)); // Fake a matching by adding sites to the processes. // First process, 3 sites, total rate 12 processes[0].addSite(12, 4.0); processes[0].addSite(123, 7.0); processes[0].addSite(332, 1.0); // Second process, 2 sites, total rate 4 processes[1].addSite(19, 1.0); processes[1].addSite(12, 3.0); // Third process, 4 sites, total rate 3 processes[2].addSite(19, 1.0/4.0); processes[2].addSite(12, 5.0/4.0); processes[2].addSite(234, 2.0/4.0); processes[2].addSite(991, 4.0/4.0); // The sixth process, one site, total rate 12. processes[5].addSite(992, 12.0); // Setup the interactions object. RateCalculator rc; Interactions interactions(processes, true, rc); // Update the probability table. interactions.updateProbabilityTable(); // Check the values of the probability table. const std::vector<std::pair<double, int> > & probability_table = \ interactions.probabilityTable(); CPPUNIT_ASSERT_EQUAL( static_cast<int>(probability_table.size()), static_cast<int>(processes.size()) ); CPPUNIT_ASSERT_DOUBLES_EQUAL( probability_table[0].first, 12.0, 1.0e-14 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( probability_table[1].first, 16.0, 1.0e-14 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( probability_table[2].first, 19.0, 1.0e-14 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( probability_table[3].first, 19.0, 1.0e-14 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( probability_table[4].first, 19.0, 1.0e-14 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( probability_table[5].first, 31.0, 1.0e-14 ); CPPUNIT_ASSERT_EQUAL( probability_table[0].second, 3 ); CPPUNIT_ASSERT_EQUAL( probability_table[1].second, 2 ); CPPUNIT_ASSERT_EQUAL( probability_table[2].second, 4 ); CPPUNIT_ASSERT_EQUAL( probability_table[3].second, 0 ); CPPUNIT_ASSERT_EQUAL( probability_table[4].second, 0 ); CPPUNIT_ASSERT_EQUAL( probability_table[5].second, 1 ); // Make sure to seed the random number generator before we test any // random dependent stuff. seedRandom(false, 131); // Pick processes from this table with enough statistics should give // the distribution proportional to the number of available sites, // but with the double rate for the third process should halve // this entry. std::vector<int> picked(6,0); const int n_loop = 1000000; for (int i = 0; i < n_loop; ++i) { const int p = interactions.pickProcessIndex(); // Make sure the picked process is not negative or too large. CPPUNIT_ASSERT( p >= 0 ); CPPUNIT_ASSERT( p < static_cast<int>(probability_table.size()) ); ++picked[p]; } CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0*picked[0]/n_loop, 12.0/31.0, 1.0e-2 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0*picked[1]/n_loop, 4.0/31.0, 1.0e-2 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0*picked[2]/n_loop, 3.0/31.0, 1.0e-2 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0*picked[3]/n_loop, 0.0/31.0, 1.0e-2 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0*picked[4]/n_loop, 0.0/31.0, 1.0e-2 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0*picked[5]/n_loop, 12.0/31.0, 1.0e-2 ); // Check that picking the process twice with two different access methods and // a seed reset inbetween gives a reference to the same object. seedRandom(false, 87); const int p = interactions.pickProcessIndex(); const Process & proc1 = (*interactions.processes()[p]); seedRandom(false, 87); const Process & proc2 = (*interactions.pickProcess()); CPPUNIT_ASSERT_EQUAL( &proc1, &proc2 ); // Alter the total rate in one of the processes and re-run the picking. interactions.processes()[5]->removeSite(992); interactions.processes()[5]->addSite(992, 24.0); // Update the probability table. interactions.updateProbabilityTable(); std::vector<int> picked2(6,0); for (int i = 0; i < n_loop; ++i) { const int p = interactions.pickProcessIndex(); // Make sure the picked process is not negative or too large. CPPUNIT_ASSERT( p >= 0 ); CPPUNIT_ASSERT( p < static_cast<int>(probability_table.size()) ); ++picked2[p]; } CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0*picked2[0]/n_loop, 12.0/43.0, 1.0e-2 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0*picked2[1]/n_loop, 4.0/43.0, 1.0e-2 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0*picked2[2]/n_loop, 3.0/43.0, 1.0e-2 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0*picked2[3]/n_loop, 0.0/43.0, 1.0e-2 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0*picked2[4]/n_loop, 0.0/43.0, 1.0e-2 ); CPPUNIT_ASSERT_DOUBLES_EQUAL( 1.0*picked2[5]/n_loop, 24.0/43.0, 1.0e-2 ); // DONE }