You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SF_4p_server.cc 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /**********************************************************
  2. This software is part of J.-S. Caux's C++ library.
  3. Copyright (c) J.-S. Caux.
  4. -----------------------------------------------------------
  5. File: SF_4p_server.cc
  6. Purpose: 4 spinon contrib to S(k, omega) for XXX_h0, parallel code using MPICH.
  7. Server part.
  8. ***********************************************************/
  9. #include "mpi.h"
  10. #include "ABACUS.h"
  11. namespace ABACUS {
  12. void SF_4p_opt_server (MPI_Comm comm, int N, DP omegamax, int Nomega, DP req_prec, int Npts_K, int Npts_W, I_table Itable,
  13. int Max_Secs, bool refine)
  14. {
  15. double Start_Time_MPI = MPI_Wtime();
  16. Heis_Write_Kfull_File (N);
  17. Heis_Write_w_File (Nomega, omegamax);
  18. stringstream SF_stringstream;
  19. string SF_string;
  20. SF_stringstream << "SF_4p_N_" << N << "_No_" << Nomega << "_omax_" << omegamax
  21. << "_prec_" << req_prec << "_Npts_K_" << Npts_K << "_Npts_W_" << Npts_W << ".dat";
  22. SF_string = SF_stringstream.str();
  23. const char* SF_Cstr = SF_string.c_str();
  24. fstream SF_outfile;
  25. if (!refine) SF_outfile.open(SF_Cstr, fstream::out | fstream::trunc);
  26. else SF_outfile.open(SF_Cstr, fstream::in | fstream::out);
  27. if (SF_outfile.fail()) ABACUSerror("Could not open SF_outfile... ");
  28. SF_outfile.precision(10);
  29. int dim_k = N/2 + 1;
  30. DP* SF_4p = new DP[dim_k * Nomega];
  31. // Initialize to zero to be sure:
  32. for (int i = 0; i < Nomega * dim_k; ++i) SF_4p[i] = 0.0;
  33. // If refining, load SF from existing file
  34. int total_nr_req = 0;
  35. DP buff;
  36. if (refine) {
  37. for (int iomega = 0; iomega < Nomega; ++iomega) {
  38. for (int ik = 0; ik < dim_k; ++ik) {
  39. SF_outfile >> SF_4p[dim_k * iomega + ik];
  40. if (SF_4p[dim_k * iomega + ik] == 0.0) total_nr_req++;
  41. // We only load the LHS of the BZ, so we load N/2 empty values...
  42. }
  43. for (int ibuff = 0; ibuff < N/2; ++ibuff) SF_outfile >> buff;
  44. }
  45. }
  46. else if (!refine) total_nr_req = dim_k * Nomega;
  47. // List iomega and ik which need to be computed:
  48. int* needed_ik = new int[total_nr_req];
  49. int* needed_iomega = new int[total_nr_req];
  50. int index = 0;
  51. for (int iomega = 0; iomega < Nomega; ++iomega)
  52. for (int ik = 0; ik < dim_k; ++ik) {
  53. if (SF_4p[dim_k * iomega + ik] == 0) {
  54. needed_ik[index] = ik;
  55. needed_iomega[index] = iomega;
  56. index++;
  57. }
  58. }
  59. cout << total_nr_req << " points required." << endl;
  60. if (index != total_nr_req) {
  61. cout << total_nr_req << "\t" << index << endl;
  62. ABACUSerror("Not counting total_nr_req correctly in SF_4p_opt_server");
  63. }
  64. int nr_machines;
  65. MPI_Comm_size (comm, &nr_machines);
  66. int nr_clients = nr_machines - 1; // one for the server
  67. int client_request_size = 7;
  68. DP client_request[client_request_size];
  69. // this is:
  70. // ik
  71. // iomega
  72. // k
  73. // omega
  74. // req_prec
  75. // Npts_K
  76. // Npts_W
  77. int client_result_size = 8;
  78. DP client_result[client_result_size]; // same, plus SF_4p
  79. MPI_Status status;
  80. int scanning = 1;
  81. int nr_sent_out = 0;
  82. int nr_returned = 0;
  83. for (int i = 1; i <= nr_clients && i <= total_nr_req; ++i) {
  84. // Send request to client i, in the form of the req_id_array vector
  85. client_request[0] = DP(needed_ik[nr_sent_out]);
  86. client_request[1] = DP(needed_iomega[nr_sent_out]);
  87. client_request[2] = (twoPI * needed_ik[nr_sent_out])/N;
  88. client_request[3] = (needed_iomega[nr_sent_out] + 0.5) * omegamax/Nomega;
  89. client_request[4] = req_prec;
  90. client_request[5] = DP(Npts_K);
  91. client_request[6] = DP(Npts_W);
  92. MPI_Send(client_request, client_request_size, MPI_DOUBLE, i, scanning, comm);
  93. nr_sent_out++;
  94. }
  95. DP Actual_Time_MPI = MPI_Wtime();
  96. while (nr_returned < nr_sent_out) {
  97. MPI_Recv (client_result, client_result_size, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, comm, &status);
  98. nr_returned++;
  99. // unbuffer result
  100. SF_4p[dim_k * int(client_result[1]) + int(client_result[0])] = client_result[7];
  101. Actual_Time_MPI = MPI_Wtime();
  102. // Send out new request if needed and time available
  103. if (nr_sent_out < total_nr_req && Actual_Time_MPI - Start_Time_MPI < Max_Secs) {
  104. client_request[0] = needed_ik[nr_sent_out];
  105. client_request[1] = needed_iomega[nr_sent_out];
  106. client_request[2] = (twoPI * needed_ik[nr_sent_out])/N;
  107. client_request[3] = (needed_iomega[nr_sent_out] + 0.5) * omegamax/Nomega;
  108. MPI_Send (client_request, client_request_size, MPI_DOUBLE, status.MPI_SOURCE, scanning, comm);
  109. nr_sent_out++;
  110. }
  111. } // while (nr_returned < total_nr_req)
  112. // Output all data: double up to full [0, 2pi] interval in k with symmetry
  113. SF_outfile.seekp(0);
  114. for (int iomega = 0; iomega < Nomega; ++iomega) {
  115. for (int ik = 0; ik < dim_k; ++ik) SF_outfile << SF_4p[dim_k * iomega + ik] << "\t";
  116. for (int ik = 2; ik <= dim_k; ++ik) SF_outfile << SF_4p[dim_k * iomega + dim_k - ik] << "\t";
  117. SF_outfile << endl;
  118. }
  119. SF_outfile.close();
  120. cout << endl << "Done !" << endl;
  121. // Send term signal to clients
  122. int scanning_completed = 0;
  123. for (int i = 1; i <= nr_clients; ++i)
  124. MPI_Send (client_request, client_request_size, MPI_DOUBLE, i, scanning_completed, comm);
  125. return;
  126. }
  127. } // namespace ABACUS