Guest User

Untitled

a guest
Apr 25th, 2018
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.45 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <cmath>
  4. #include <chrono>
  5. #include <omp.h>
  6. #include <cstring>
  7. #include <mpi.h>
  8. #include <fstream>
  9.  
  10. #define EPS 1E-7
  11. #define PI 3.14159265358979323846
  12.  
  13. using namespace std;
  14.  
  15. bool CheckSphereIn(const double& R, const double& x, const double& y){
  16. return x*x + y*y - R*R <= EPS;
  17. }
  18.  
  19. int MakeSpherePointsField(const double& R, const double& h, vector<double>& X, vector<double>& Y,
  20. const double& start_x=0.f, const double& start_y=0.f){ // 0.f - это преобразование 0 к double(чтобы было 0.0)
  21. if (abs(R) < EPS)
  22. return EXIT_FAILURE;
  23. if (abs(h) < EPS)
  24. return EXIT_FAILURE;
  25.  
  26. const auto n = static_cast<long>(R / h);
  27.  
  28. X.clear();
  29. Y.clear();
  30.  
  31. for (auto i = 0; i < n; ++i)
  32. for (auto j = 0; j < n; ++j)
  33. if (CheckSphereIn(R, h*i, h*j)){
  34. X.emplace_back(h*i + start_x);
  35. Y.emplace_back(h*j + start_y);
  36. }
  37.  
  38. return EXIT_SUCCESS;
  39. }
  40.  
  41. double RKF(const double& y, const double& f, const double& h){
  42. return y + h*f;
  43. }
  44.  
  45. int set_tasks(const int n, const int k, vector<int>& left, vector<int>& right){
  46. left.clear();
  47. right.clear();
  48.  
  49. for (int i = 0; i < k; ++i){
  50. left.push_back((int) (((long)i * n) / k));
  51. right.push_back((int) (((long) (i + 1) * n) / k - 1));
  52. }
  53. return 0;
  54. }
  55.  
  56. vector<int> left_indexes, right_indexes;
  57.  
  58. // добавить омега
  59. int ToNextStepMPI(double* X, double* Y, const unsigned long n, const double& h, const int& id, const int& comm_size){
  60. if (abs(h) < EPS)
  61. return EXIT_FAILURE;
  62.  
  63. double *oldX = new double[n], *oldY = new double[n];
  64. memcpy(oldX, X, sizeof(double)*n);
  65. memcpy(oldY, Y, sizeof(double)*n);
  66.  
  67. #pragma omp parallel for
  68. for (auto i = left_indexes[id]; i < right_indexes[id]; ++i){
  69. double k1_x, k2_x, k3_x, k4_x;
  70. double k1_y, k2_y, k3_y, k4_y;
  71. double sum_x = 0, sum_y = 0;
  72. for (auto j = 0; j < n; ++j){
  73. if (i == j)
  74. continue;
  75. double d = pow(oldX[i] - oldX[j], 2) + pow(oldY[i] - oldY[j], 2); //расстояние между двумя точками
  76. sum_x += (oldY[i] - oldY[j]) / d;
  77. sum_y += (oldX[i] - oldX[j]) / d;
  78. }
  79.  
  80. k1_x = sum_x/-2/PI;
  81. k1_y = sum_y/2/PI;
  82.  
  83. double c_x = k1_x*h/2;
  84. double c_y = k1_y*h/2;
  85. for (auto j = 0; j < n; ++j){
  86. if (i == j)
  87. continue;
  88. double d = pow(oldX[i]+c_x - oldX[j]+c_x, 2) + pow(oldY[i]+c_y - oldY[j]+c_y, 2); //расстояние между двумя точками
  89. sum_x += (oldY[i]+c_y - oldY[j]+c_y) / d;
  90. sum_y += (oldX[i]+c_x - oldX[j]+c_x) / d;
  91. }
  92. k2_x = sum_x/-2/PI;
  93. k2_y = sum_y/-2/PI;
  94.  
  95. c_x = k2_x*h/2;
  96. c_y = k2_y*h/2;
  97. for (auto j = 0; j < n; ++j){
  98. if (i == j)
  99. continue;
  100. double d = pow(oldX[i]+c_x - oldX[j]+c_x, 2) + pow(oldY[i]+c_y - oldY[j]+c_y, 2); //расстояние между двумя точками
  101. sum_x += (oldY[i]+c_y - oldY[j]+c_y) / d;
  102. sum_y += (oldX[i]+c_x - oldX[j]+c_x) / d;
  103. }
  104. k3_x = sum_x/-2/PI;
  105. k3_y = sum_y/2/PI;
  106.  
  107. c_x = k3_x*h;
  108. c_y = k3_y*h;
  109. for (auto j = 0; j < n; ++j){
  110. if (i == j)
  111. continue;
  112. double d = pow(oldX[i] - oldX[j], 2) + pow(oldY[i] - oldY[j], 2); //расстояние между двумя точками
  113. sum_x += (oldY[i] - oldY[j]) / d;
  114. sum_y += (oldX[i] - oldX[j]) / d;
  115. }
  116. k4_x = sum_x/-2/PI;
  117. k4_x = sum_y/2/PI;
  118.  
  119. X[i] = X[i] + (k1_x + 2*k2_x + 2*k3_x + k4_x)*h/6;
  120. Y[i] = Y[i] + (k1_y+ 2*k2_y + 2*k3_y + k4_y)*h/6;
  121. }
  122.  
  123. // всеобщее обновление массивов X и Y
  124. for (auto i = 0; i < comm_size; ++i){
  125. MPI_Bcast(X + left_indexes[i], right_indexes[i] - left_indexes[i], MPI_DOUBLE, i, MPI_COMM_WORLD);
  126. MPI_Bcast(Y + left_indexes[i], right_indexes[i] - left_indexes[i], MPI_DOUBLE, i, MPI_COMM_WORLD);
  127. }
  128.  
  129. delete[] oldX;
  130. delete[] oldY;
  131.  
  132. return EXIT_SUCCESS;
  133. }
  134.  
  135. int get_default_max_threads_num(){
  136. int res = 0;
  137. #pragma omp parallel
  138. {
  139. #pragma omp single
  140. res = omp_get_num_threads();
  141. }
  142. return res;
  143. }
  144.  
  145. void check_err(string err_str, const int err){
  146. if (err)
  147. cout << err_str << " " << err << endl;
  148. }
  149.  
  150. int main(int argc, char** argv) {
  151.  
  152.  
  153. check_err("MPI_Init", MPI_Init(&argc, &argv));
  154. int id, cores;
  155.  
  156. MPI_Comm_rank(MPI_COMM_WORLD, &id);
  157. MPI_Comm_size(MPI_COMM_WORLD, &cores);
  158.  
  159.  
  160. vector<double> Xv, Yv;
  161. MakeSpherePointsField(1, 0.2, Xv, Yv); // вычисление точек, которые попадают в сферу с радиусом 5; шаг 0.05; Xv, Yv координаты этих точек
  162.  
  163. // перенос данных из векторов в обычные массивы, чтобы вставлять часть массива в другой была O(1)
  164. double *X = new double[Xv.size()], *Y = new double[Yv.size()];
  165. int n = Xv.size();
  166. cout << "n?: " << n << endl;
  167.  
  168. memcpy(X, Xv.data(), sizeof(double)*n);
  169. Xv.clear();
  170. memcpy(Y, Yv.data(), sizeof(double)*n);
  171. Yv.clear();
  172.  
  173. if (id == 0) {
  174. cout << "Cores count: " << cores << endl;
  175. cout << "Threads count: " << get_default_max_threads_num() << endl;
  176. cout << "Points count: " << n << endl;
  177. }
  178.  
  179. // создает два массива, в которых указаны индексы начала и конца точек которые будут обрабатываться в каждом узле
  180. set_tasks(static_cast<const int>(n), cores, left_indexes, right_indexes);
  181.  
  182. const unsigned long steps = 100;
  183. const double h = 0.1;
  184. chrono::duration<double> timer;
  185.  
  186.  
  187. FILE* file = fopen("points.txt", "w");
  188. fprintf(file, "%d\n", n);
  189. int i;
  190.  
  191. auto start_time = chrono::steady_clock::now();
  192. for (auto i = 0; i < steps; ++i)
  193. {
  194. if (id == 0) {
  195. for (i = 0; i < n; ++i)
  196. fprintf(file, "%f %f\n", X[i], Y[i]);
  197.  
  198. }
  199. ToNextStepMPI(X, Y, n, h, id, cores);
  200. }
  201. fclose(file);
  202. timer = chrono::steady_clock::now() - start_time;
  203.  
  204.  
  205. MPI_Barrier(MPI_COMM_WORLD);
  206.  
  207. if (id == 0)
  208. cout << "Time: " << timer.count() << " sec" << endl;
  209.  
  210. delete[] X;
  211. delete[] Y;
  212.  
  213. MPI_Finalize();
  214.  
  215. return EXIT_SUCCESS;
  216. }
Add Comment
Please, Sign In to add comment