ABACUS/src/XXX_VOA/SF_4p_server.cc

175 lines
5.2 KiB
C++
Executable File

/**********************************************************
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