123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- /**********************************************************
-
- This software is part of J.-S. Caux's C++ library.
-
- Copyright (c) J.-S. Caux.
-
- -----------------------------------------------------------
-
- File: SF_4p_server.cc
-
- Purpose: 4 spinon contrib to S(k, omega) for XXX_h0, parallel code using MPICH.
- Server part.
-
- ***********************************************************/
-
- #include "mpi.h"
- #include "ABACUS.h"
-
- namespace ABACUS {
-
-
- 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,
- int Max_Secs, bool refine)
- {
- double Start_Time_MPI = MPI_Wtime();
-
- Heis_Write_Kfull_File (N);
- Heis_Write_w_File (Nomega, omegamax);
-
- stringstream SF_stringstream;
- string SF_string;
- SF_stringstream << "SF_4p_N_" << N << "_No_" << Nomega << "_omax_" << omegamax
- << "_prec_" << req_prec << "_Npts_K_" << Npts_K << "_Npts_W_" << Npts_W << ".dat";
- SF_string = SF_stringstream.str();
- const char* SF_Cstr = SF_string.c_str();
-
- fstream SF_outfile;
- if (!refine) SF_outfile.open(SF_Cstr, fstream::out | fstream::trunc);
- else SF_outfile.open(SF_Cstr, fstream::in | fstream::out);
- if (SF_outfile.fail()) ABACUSerror("Could not open SF_outfile... ");
-
- SF_outfile.precision(10);
-
- int dim_k = N/2 + 1;
-
- DP* SF_4p = new DP[dim_k * Nomega];
-
- // Initialize to zero to be sure:
- for (int i = 0; i < Nomega * dim_k; ++i) SF_4p[i] = 0.0;
-
- // If refining, load SF from existing file
-
- int total_nr_req = 0;
- DP buff;
- if (refine) {
- for (int iomega = 0; iomega < Nomega; ++iomega) {
- for (int ik = 0; ik < dim_k; ++ik) {
- SF_outfile >> SF_4p[dim_k * iomega + ik];
- if (SF_4p[dim_k * iomega + ik] == 0.0) total_nr_req++;
-
- // We only load the LHS of the BZ, so we load N/2 empty values...
- }
- for (int ibuff = 0; ibuff < N/2; ++ibuff) SF_outfile >> buff;
- }
- }
- else if (!refine) total_nr_req = dim_k * Nomega;
-
- // List iomega and ik which need to be computed:
-
- int* needed_ik = new int[total_nr_req];
- int* needed_iomega = new int[total_nr_req];
-
- int index = 0;
- for (int iomega = 0; iomega < Nomega; ++iomega)
- for (int ik = 0; ik < dim_k; ++ik) {
- if (SF_4p[dim_k * iomega + ik] == 0) {
- needed_ik[index] = ik;
- needed_iomega[index] = iomega;
- index++;
- }
- }
-
- cout << total_nr_req << " points required." << endl;
-
- if (index != total_nr_req) {
- cout << total_nr_req << "\t" << index << endl;
- ABACUSerror("Not counting total_nr_req correctly in SF_4p_opt_server");
- }
-
- int nr_machines;
- MPI_Comm_size (comm, &nr_machines);
- int nr_clients = nr_machines - 1; // one for the server
-
- int client_request_size = 7;
- DP client_request[client_request_size];
- // this is:
- // ik
- // iomega
- // k
- // omega
- // req_prec
- // Npts_K
- // Npts_W
- int client_result_size = 8;
- DP client_result[client_result_size]; // same, plus SF_4p
-
- MPI_Status status;
-
- int scanning = 1;
-
- int nr_sent_out = 0;
- int nr_returned = 0;
-
- for (int i = 1; i <= nr_clients && i <= total_nr_req; ++i) {
-
- // Send request to client i, in the form of the req_id_array vector
- client_request[0] = DP(needed_ik[nr_sent_out]);
- client_request[1] = DP(needed_iomega[nr_sent_out]);
- client_request[2] = (twoPI * needed_ik[nr_sent_out])/N;
- client_request[3] = (needed_iomega[nr_sent_out] + 0.5) * omegamax/Nomega;
- client_request[4] = req_prec;
- client_request[5] = DP(Npts_K);
- client_request[6] = DP(Npts_W);
-
- MPI_Send(client_request, client_request_size, MPI_DOUBLE, i, scanning, comm);
- nr_sent_out++;
- }
-
- DP Actual_Time_MPI = MPI_Wtime();
-
- while (nr_returned < nr_sent_out) {
-
- MPI_Recv (client_result, client_result_size, MPI_DOUBLE, MPI_ANY_SOURCE, MPI_ANY_TAG, comm, &status);
- nr_returned++;
-
- // unbuffer result
- SF_4p[dim_k * int(client_result[1]) + int(client_result[0])] = client_result[7];
-
- Actual_Time_MPI = MPI_Wtime();
-
- // Send out new request if needed and time available
- if (nr_sent_out < total_nr_req && Actual_Time_MPI - Start_Time_MPI < Max_Secs) {
- client_request[0] = needed_ik[nr_sent_out];
- client_request[1] = needed_iomega[nr_sent_out];
- client_request[2] = (twoPI * needed_ik[nr_sent_out])/N;
- client_request[3] = (needed_iomega[nr_sent_out] + 0.5) * omegamax/Nomega;
- MPI_Send (client_request, client_request_size, MPI_DOUBLE, status.MPI_SOURCE, scanning, comm);
- nr_sent_out++;
- }
-
- } // while (nr_returned < total_nr_req)
-
- // Output all data: double up to full [0, 2pi] interval in k with symmetry
- SF_outfile.seekp(0);
- for (int iomega = 0; iomega < Nomega; ++iomega) {
- for (int ik = 0; ik < dim_k; ++ik) SF_outfile << SF_4p[dim_k * iomega + ik] << "\t";
- for (int ik = 2; ik <= dim_k; ++ik) SF_outfile << SF_4p[dim_k * iomega + dim_k - ik] << "\t";
- SF_outfile << endl;
- }
-
- SF_outfile.close();
-
- cout << endl << "Done !" << endl;
-
- // Send term signal to clients
- int scanning_completed = 0;
- for (int i = 1; i <= nr_clients; ++i)
- MPI_Send (client_request, client_request_size, MPI_DOUBLE, i, scanning_completed, comm);
-
- return;
- }
-
-
- } // namespace ABACUS
|