int main(int argc, char* argv[]) { if (MPI_Init(&argc, &argv) != MPI_SUCCESS) { cerr << "Coudln't initialize MPI." << endl; abort(); } MPI_Comm comm = MPI_COMM_WORLD; int rank = 0, comm_size = 0; MPI_Comm_rank(comm, &rank); MPI_Comm_size(comm, &comm_size); float zoltan_version; if (Zoltan_Initialize(argc, argv, &zoltan_version) != ZOLTAN_OK) { cout << "Zoltan_Initialize failed" << endl; abort(); } Dccrg<std::array<int, 2>> grid; const std::array<uint64_t, 3> grid_length = {{18, 18, 1}}; grid .set_initial_length(grid_length) .set_neighborhood_length(2) .set_maximum_refinement_level(0) .set_periodic(true, true, true) .set_load_balancing_method("RANDOM") .initialize(comm); /* Use a neighborhood like this in the z plane: O.O.O ..... O.X.O ..... O.O.O and play 4 interlaced games simultaneously. */ typedef dccrg::Types<3>::neighborhood_item_t neigh_t; const std::vector<neigh_t> neighborhood{ {-2, -2, 0}, {-2, 0, 0}, {-2, 2, 0}, { 0, -2, 0}, { 0, 2, 0}, { 2, -2, 0}, { 2, 0, 0}, { 2, 2, 0} }; const int neighborhood_id = 1; if (!grid.add_neighborhood(neighborhood_id, neighborhood)) { std::cerr << __FILE__ << ":" << __LINE__ << " Couldn't set neighborhood" << std::endl; abort(); } // initial condition const std::unordered_set<uint64_t> live_cells = get_live_cells(grid_length[0], 0); for (const uint64_t cell: live_cells) { auto* const cell_data = grid[cell]; if (cell_data != nullptr) { (*cell_data)[0] = 1; } } // every process outputs the game state into its own file ostringstream basename, suffix(".vtk"); basename << "tests/user_neighborhood/general_neighborhood_" << rank << "_"; ofstream outfile, visit_file; // visualize the game with visit -o game_of_life_test.visit if (rank == 0) { visit_file.open("tests/user_neighborhood/general_neighborhood.visit"); visit_file << "!NBLOCKS " << comm_size << endl; } #define TIME_STEPS 36 for (int step = 0; step < TIME_STEPS; step++) { grid.balance_load(); grid.update_copies_of_remote_neighbors(neighborhood_id); // check that the result is correct if (step % 4 == 0) { const std::unordered_set<uint64_t> live_cells = get_live_cells(grid_length[0], step); for (const auto& cell: grid.local_cells(neighborhood_id)) { if ((*cell.data)[0] == 0) { if (live_cells.count(cell.id) > 0) { std::cerr << __FILE__ << ":" << __LINE__ << " Cell " << cell.id << " shouldn't be alive on step " << step << endl; abort(); } } else { if (live_cells.count(cell.id) == 0) { std::cerr << __FILE__ << ":" << __LINE__ << " Cell " << cell.id << " should be alive on step " << step << endl; abort(); } } } } // write the game state into a file named according to the current time step string current_output_name(""); ostringstream step_string; step_string.fill('0'); step_string.width(5); step_string << step; current_output_name += basename.str(); current_output_name += step_string.str(); current_output_name += suffix.str(); // visualize the game with visit -o game_of_life_test.visit if (rank == 0) { for (int process = 0; process < comm_size; process++) { visit_file << "general_neighborhood_" << process << "_" << step_string.str() << suffix.str() << endl; } } // write the grid into a file vector<uint64_t> cells = grid.get_cells(); sort(cells.begin(), cells.end()); grid.write_vtk_file(current_output_name.c_str()); // prepare to write the game data into the same file outfile.open(current_output_name.c_str(), ofstream::app); outfile << "CELL_DATA " << cells.size() << endl; // go through the grids cells and write their state into the file outfile << "SCALARS is_alive float 1" << endl; outfile << "LOOKUP_TABLE default" << endl; for (const uint64_t cell: cells) { const auto* const cell_data = grid[cell]; if ((*cell_data)[0] == 1) { // color live cells of interlaced games differently const Types<3>::indices_t indices = grid.mapping.get_indices(cell); outfile << 1 + indices[0] % 2 + (indices[1] % 2) * 2; } else { outfile << 0; } outfile << endl; } // write each cells live neighbor count outfile << "SCALARS live_neighbor_count float 1" << endl; outfile << "LOOKUP_TABLE default" << endl; for (const uint64_t cell: cells) { const auto* const cell_data = grid[cell]; outfile << (*cell_data)[1] << endl; } // write each cells neighbor count outfile << "SCALARS neighbors int 1" << endl; outfile << "LOOKUP_TABLE default" << endl; for (const uint64_t cell: cells) { const auto* const neighbors = grid.get_neighbors_of(cell); outfile << neighbors->size() << endl; } // write each cells process outfile << "SCALARS process int 1" << endl; outfile << "LOOKUP_TABLE default" << endl; for (size_t i = 0; i < cells.size(); i++) { outfile << rank << endl; } // write each cells id outfile << "SCALARS id int 1" << endl; outfile << "LOOKUP_TABLE default" << endl; for (const uint64_t cell: cells) { outfile << cell << endl; } outfile.close(); // get live neighbor counts for (const auto& cell: grid.local_cells(neighborhood_id)) { (*cell.data)[1] = 0; for (const auto& neighbor: cell.neighbors_of) { if ((*neighbor.data)[0] == 1) { (*cell.data)[1]++; } } } // calculate the next turn for (const auto& cell: grid.local_cells(neighborhood_id)) { if ((*cell.data)[1] == 3) { (*cell.data)[0] = 1; } else if ((*cell.data)[1] != 2) { (*cell.data)[0] = 0; } } } MPI_Finalize(); return EXIT_SUCCESS; }
int main(int argc, char* argv[]) { if (MPI_Init(&argc, &argv) != MPI_SUCCESS) { cerr << "Coudln't initialize MPI." << endl; abort(); } MPI_Comm comm = MPI_COMM_WORLD; int rank = 0, comm_size = 0; MPI_Comm_rank(comm, &rank); MPI_Comm_size(comm, &comm_size); float zoltan_version; if (Zoltan_Initialize(argc, argv, &zoltan_version) != ZOLTAN_OK) { cout << "Zoltan_Initialize failed" << endl; exit(EXIT_FAILURE); } Dccrg<Cell, Stretched_Cartesian_Geometry> grid; constexpr size_t GRID_SIZE = 2; constexpr unsigned int NEIGHBORHOOD_SIZE = 1; grid .set_initial_length({GRID_SIZE, 1, 1}) .set_neighborhood_length(NEIGHBORHOOD_SIZE) .set_maximum_refinement_level(-1) .set_load_balancing_method("RANDOM") .initialize(comm); constexpr double CELL_SIZE = 1.0 / GRID_SIZE; Stretched_Cartesian_Geometry::Parameters geom_params; for (size_t i = 0; i <= GRID_SIZE; i++) { geom_params.coordinates[0].push_back(i * CELL_SIZE); } geom_params.coordinates[1].push_back(0); geom_params.coordinates[1].push_back(0.5); geom_params.coordinates[2].push_back(0); geom_params.coordinates[2].push_back(0.5); grid.set_geometry(geom_params); // every process outputs the game state into its own file ostringstream basename, suffix(".vtk"); basename << "refine_simple_" << rank << "_"; ofstream outfile, visit_file; // visualize the game with visit -o game_of_life_test.visit if (rank == 0) { visit_file.open("tests/refine/refine_simple.visit"); visit_file << "!NBLOCKS " << comm_size << endl; } constexpr size_t TIME_STEPS = 3; for (size_t step = 0; step < TIME_STEPS; step++) { // refine the smallest cell that is closest to the starting corner const std::array<double, 3> refine_coord{ 0.000001 * CELL_SIZE, 0.000001 * CELL_SIZE, 0.000001 * CELL_SIZE }; grid.refine_completely_at(refine_coord); grid.stop_refining(); grid.balance_load(); auto cells = grid.get_cells(); sort(cells.begin(), cells.end()); for (const auto& cell: cells) { const auto ref_lvl = grid.get_refinement_level(cell); for (const auto& neighbor: *grid.get_neighbors_of(cell)) { if (neighbor.first == error_cell) { continue; } const auto neigh_ref_lvl = grid.get_refinement_level(neighbor.first); if (abs(ref_lvl - neigh_ref_lvl) > 1) { std::cerr << "Refinement level difference between " << cell << " and " << neighbor.first << " too large" << std::endl; abort(); } } } // write the game state into a file named according to the current time step string current_output_name("tests/refine/"); ostringstream step_string; step_string.fill('0'); step_string.width(5); step_string << step; current_output_name += basename.str(); current_output_name += step_string.str(); current_output_name += suffix.str(); // visualize the game with visit -o game_of_life_test.visit if (rank == 0) { for (int process = 0; process < comm_size; process++) { visit_file << "refine_simple_" << process << "_" << step_string.str() << suffix.str() << endl; } } // write the grid into a file grid.write_vtk_file(current_output_name.c_str()); // prepare to write the game data into the same file outfile.open(current_output_name.c_str(), ofstream::app); outfile << "CELL_DATA " << cells.size() << endl; // write each cells neighbor count outfile << "SCALARS neighbors int 1" << endl; outfile << "LOOKUP_TABLE default" << endl; for (const auto& cell: cells) { const auto* const neighbors = grid.get_neighbors_of(cell); outfile << neighbors->size() << endl; } // write each cells process outfile << "SCALARS process int 1" << endl; outfile << "LOOKUP_TABLE default" << endl; for (size_t i = 0; i < cells.size(); i++) { outfile << rank << endl; } // write each cells id outfile << "SCALARS id int 1" << endl; outfile << "LOOKUP_TABLE default" << endl; for (const auto& cell: cells) { outfile << cell << endl; } outfile.close(); } if (rank == 0) { visit_file.close(); } MPI_Finalize(); return EXIT_SUCCESS; }