|
1 | 1 | #include "write_HS_R.h" |
2 | 2 |
|
| 3 | +#include "module_base/parallel_reduce.h" |
3 | 4 | #include "module_parameter/parameter.h" |
4 | 5 | #include "module_base/timer.h" |
5 | 6 | #include "module_hamilt_lcao/hamilt_lcaodft/LCAO_HS_arrays.hpp" |
|
8 | 9 | #include "module_hamilt_lcao/hamilt_lcaodft/spar_st.h" |
9 | 10 | #include "write_HS_sparse.h" |
10 | 11 |
|
| 12 | +#ifdef __MPI |
| 13 | +#include <mpi.h> |
| 14 | +#endif |
| 15 | + |
| 16 | +#include <algorithm> |
| 17 | +#include <cstdio> |
| 18 | +#include <fstream> |
| 19 | +#include <iomanip> |
| 20 | +#include <numeric> |
| 21 | +#include <sstream> |
| 22 | +#include <vector> |
| 23 | + |
| 24 | +namespace |
| 25 | +{ |
| 26 | +template <typename T> |
| 27 | +struct GetSEntry |
| 28 | +{ |
| 29 | + size_t row; |
| 30 | + size_t col; |
| 31 | + T value; |
| 32 | +}; |
| 33 | + |
| 34 | +void write_gets_data(std::ofstream& ofs, const double& data) |
| 35 | +{ |
| 36 | + ofs << " " << std::fixed << std::scientific << std::setprecision(8) << data; |
| 37 | +} |
| 38 | + |
| 39 | +void write_gets_data(std::ofstream& ofs, const std::complex<double>& data) |
| 40 | +{ |
| 41 | + ofs << " (" << std::fixed << std::scientific << std::setprecision(8) << data.real() << "," |
| 42 | + << std::fixed << std::scientific << std::setprecision(8) << data.imag() << ")"; |
| 43 | +} |
| 44 | + |
| 45 | +template <typename Tdata> |
| 46 | +void save_gets_sparse_fast( |
| 47 | + const std::map<Abfs::Vector3_Order<int>, std::map<size_t, std::map<size_t, Tdata>>>& smat, |
| 48 | + const std::set<Abfs::Vector3_Order<int>>& all_R_coor, |
| 49 | + const double& sparse_thr, |
| 50 | + const std::string& filename, |
| 51 | + const std::string& label, |
| 52 | + const int& istep) |
| 53 | +{ |
| 54 | + const int nlocal = PARAM.globalv.nlocal; |
| 55 | + const int total_R_num = all_R_coor.size(); |
| 56 | + |
| 57 | + std::vector<int> nonzero_num(total_R_num, 0); |
| 58 | + int count = 0; |
| 59 | + for (const auto& R_coor : all_R_coor) |
| 60 | + { |
| 61 | + auto iter = smat.find(R_coor); |
| 62 | + if (iter != smat.end()) |
| 63 | + { |
| 64 | + for (const auto& row_loop : iter->second) |
| 65 | + { |
| 66 | + for (const auto& value : row_loop.second) |
| 67 | + { |
| 68 | + if (std::abs(value.second) > sparse_thr) |
| 69 | + { |
| 70 | + ++nonzero_num[count]; |
| 71 | + } |
| 72 | + } |
| 73 | + } |
| 74 | + } |
| 75 | + ++count; |
| 76 | + } |
| 77 | +#ifdef __MPI |
| 78 | + Parallel_Reduce::reduce_all(nonzero_num.data(), total_R_num); |
| 79 | +#endif |
| 80 | + |
| 81 | + int output_R_number = 0; |
| 82 | + for (const int nnz : nonzero_num) |
| 83 | + { |
| 84 | + if (nnz != 0) |
| 85 | + { |
| 86 | + ++output_R_number; |
| 87 | + } |
| 88 | + } |
| 89 | + |
| 90 | + int myrank = 0; |
| 91 | + int nprocs = 1; |
| 92 | +#ifdef __MPI |
| 93 | + MPI_Comm_rank(MPI_COMM_WORLD, &myrank); |
| 94 | + MPI_Comm_size(MPI_COMM_WORLD, &nprocs); |
| 95 | +#endif |
| 96 | + |
| 97 | + std::ofstream ofs; |
| 98 | + if (myrank == 0) |
| 99 | + { |
| 100 | + ofs.open(filename.c_str()); |
| 101 | + ofs << "STEP: " << std::max(istep, 0) << std::endl; |
| 102 | + ofs << "Matrix Dimension of " + label + "(R): " << nlocal << std::endl; |
| 103 | + ofs << "Matrix number of " + label + "(R): " << output_R_number << std::endl; |
| 104 | + } |
| 105 | + |
| 106 | + count = 0; |
| 107 | + for (const auto& R_coor : all_R_coor) |
| 108 | + { |
| 109 | + if (nonzero_num[count] == 0) |
| 110 | + { |
| 111 | + ++count; |
| 112 | + continue; |
| 113 | + } |
| 114 | + |
| 115 | + std::ofstream ofs_indices; |
| 116 | + std::ifstream ifs_indices; |
| 117 | + std::stringstream indices_filename; |
| 118 | + indices_filename << PARAM.globalv.global_out_dir << std::to_string(myrank) << "temp_gets_sparse_indices.dat"; |
| 119 | + |
| 120 | + std::vector<int> indptr; |
| 121 | + if (myrank == 0) |
| 122 | + { |
| 123 | + ofs << R_coor.x << " " << R_coor.y << " " << R_coor.z << " " |
| 124 | + << nonzero_num[count] << std::endl; |
| 125 | + ofs_indices.open(indices_filename.str().c_str()); |
| 126 | + indptr.reserve(nlocal + 1); |
| 127 | + indptr.push_back(0); |
| 128 | + } |
| 129 | + |
| 130 | + const int row_block_size = 4096; |
| 131 | + for (int row_begin = 0; row_begin < nlocal; row_begin += row_block_size) |
| 132 | + { |
| 133 | + const int row_end = std::min(row_begin + row_block_size, nlocal); |
| 134 | + |
| 135 | + std::vector<GetSEntry<Tdata>> local_entries; |
| 136 | + auto iter = smat.find(R_coor); |
| 137 | + if (iter != smat.end()) |
| 138 | + { |
| 139 | + auto row_iter = iter->second.lower_bound(static_cast<size_t>(row_begin)); |
| 140 | + while (row_iter != iter->second.end() && row_iter->first < static_cast<size_t>(row_end)) |
| 141 | + { |
| 142 | + for (const auto& value : row_iter->second) |
| 143 | + { |
| 144 | + if (std::abs(value.second) > sparse_thr) |
| 145 | + { |
| 146 | + local_entries.push_back({row_iter->first, value.first, value.second}); |
| 147 | + } |
| 148 | + } |
| 149 | + ++row_iter; |
| 150 | + } |
| 151 | + } |
| 152 | + |
| 153 | + std::vector<GetSEntry<Tdata>> entries; |
| 154 | +#ifdef __MPI |
| 155 | + const int local_bytes = static_cast<int>(local_entries.size() * sizeof(GetSEntry<Tdata>)); |
| 156 | + std::vector<int> recv_counts(nprocs, 0); |
| 157 | + MPI_Gather(&local_bytes, 1, MPI_INT, recv_counts.data(), 1, MPI_INT, 0, MPI_COMM_WORLD); |
| 158 | + |
| 159 | + std::vector<int> displs; |
| 160 | + int total_bytes = 0; |
| 161 | + if (myrank == 0) |
| 162 | + { |
| 163 | + displs.resize(nprocs, 0); |
| 164 | + for (int ip = 1; ip < nprocs; ++ip) |
| 165 | + { |
| 166 | + displs[ip] = displs[ip - 1] + recv_counts[ip - 1]; |
| 167 | + } |
| 168 | + total_bytes = std::accumulate(recv_counts.begin(), recv_counts.end(), 0); |
| 169 | + entries.resize(total_bytes / sizeof(GetSEntry<Tdata>)); |
| 170 | + } |
| 171 | + |
| 172 | + MPI_Gatherv(local_entries.empty() ? nullptr : local_entries.data(), |
| 173 | + local_bytes, |
| 174 | + MPI_BYTE, |
| 175 | + entries.empty() ? nullptr : entries.data(), |
| 176 | + recv_counts.empty() ? nullptr : recv_counts.data(), |
| 177 | + displs.empty() ? nullptr : displs.data(), |
| 178 | + MPI_BYTE, |
| 179 | + 0, |
| 180 | + MPI_COMM_WORLD); |
| 181 | +#else |
| 182 | + entries.swap(local_entries); |
| 183 | +#endif |
| 184 | + |
| 185 | + if (myrank == 0) |
| 186 | + { |
| 187 | + std::sort(entries.begin(), entries.end(), [](const auto& lhs, const auto& rhs) { |
| 188 | + return lhs.row == rhs.row ? lhs.col < rhs.col : lhs.row < rhs.row; |
| 189 | + }); |
| 190 | + |
| 191 | + std::vector<GetSEntry<Tdata>> merged_entries; |
| 192 | + merged_entries.reserve(entries.size()); |
| 193 | + for (size_t i = 0; i < entries.size();) |
| 194 | + { |
| 195 | + GetSEntry<Tdata> merged = entries[i]; |
| 196 | + ++i; |
| 197 | + while (i < entries.size() && entries[i].row == merged.row && entries[i].col == merged.col) |
| 198 | + { |
| 199 | + merged.value += entries[i].value; |
| 200 | + ++i; |
| 201 | + } |
| 202 | + if (std::abs(merged.value) > sparse_thr) |
| 203 | + { |
| 204 | + merged_entries.push_back(merged); |
| 205 | + } |
| 206 | + } |
| 207 | + |
| 208 | + size_t entry_index = 0; |
| 209 | + for (int row = row_begin; row < row_end; ++row) |
| 210 | + { |
| 211 | + int row_nnz = 0; |
| 212 | + while (entry_index < merged_entries.size() |
| 213 | + && merged_entries[entry_index].row == static_cast<size_t>(row)) |
| 214 | + { |
| 215 | + write_gets_data(ofs, merged_entries[entry_index].value); |
| 216 | + ofs_indices << " " << merged_entries[entry_index].col; |
| 217 | + ++row_nnz; |
| 218 | + ++entry_index; |
| 219 | + } |
| 220 | + indptr.push_back(indptr.back() + row_nnz); |
| 221 | + } |
| 222 | + } |
| 223 | + } |
| 224 | + |
| 225 | + if (myrank == 0) |
| 226 | + { |
| 227 | + ofs << std::endl; |
| 228 | + |
| 229 | + ofs_indices << std::endl; |
| 230 | + ofs_indices.close(); |
| 231 | + ifs_indices.open(indices_filename.str().c_str()); |
| 232 | + ofs << ifs_indices.rdbuf(); |
| 233 | + ifs_indices.close(); |
| 234 | + |
| 235 | + for (const auto& pointer : indptr) |
| 236 | + { |
| 237 | + ofs << " " << pointer; |
| 238 | + } |
| 239 | + ofs << std::endl; |
| 240 | + |
| 241 | + std::remove(indices_filename.str().c_str()); |
| 242 | + } |
| 243 | + |
| 244 | + ++count; |
| 245 | + } |
| 246 | + |
| 247 | + if (myrank == 0) |
| 248 | + { |
| 249 | + ofs.close(); |
| 250 | + } |
| 251 | +} |
| 252 | +} // namespace |
| 253 | + |
11 | 254 | // if 'binary=true', output binary file. |
12 | 255 | // The 'sparse_thr' is the accuracy of the sparse matrix. |
13 | 256 | // If the absolute value of the matrix element is less than or equal to the |
@@ -178,25 +421,49 @@ void ModuleIO::output_SR(Parallel_Orbitals& pv, |
178 | 421 |
|
179 | 422 | if (PARAM.inp.nspin == 4) |
180 | 423 | { |
181 | | - ModuleIO::save_sparse(HS_Arrays.SR_soc_sparse, |
182 | | - HS_Arrays.all_R_coor, |
183 | | - sparse_thr, |
184 | | - binary, |
185 | | - SR_filename, |
186 | | - pv, |
187 | | - "S", |
188 | | - istep); |
| 424 | + if (PARAM.inp.calculation == "get_S" && !binary) |
| 425 | + { |
| 426 | + save_gets_sparse_fast(HS_Arrays.SR_soc_sparse, |
| 427 | + HS_Arrays.all_R_coor, |
| 428 | + sparse_thr, |
| 429 | + SR_filename, |
| 430 | + "S", |
| 431 | + istep); |
| 432 | + } |
| 433 | + else |
| 434 | + { |
| 435 | + ModuleIO::save_sparse(HS_Arrays.SR_soc_sparse, |
| 436 | + HS_Arrays.all_R_coor, |
| 437 | + sparse_thr, |
| 438 | + binary, |
| 439 | + SR_filename, |
| 440 | + pv, |
| 441 | + "S", |
| 442 | + istep); |
| 443 | + } |
189 | 444 | } |
190 | 445 | else |
191 | 446 | { |
192 | | - ModuleIO::save_sparse(HS_Arrays.SR_sparse, |
193 | | - HS_Arrays.all_R_coor, |
194 | | - sparse_thr, |
195 | | - binary, |
196 | | - SR_filename, |
197 | | - pv, |
198 | | - "S", |
199 | | - istep); |
| 447 | + if (PARAM.inp.calculation == "get_S" && !binary) |
| 448 | + { |
| 449 | + save_gets_sparse_fast(HS_Arrays.SR_sparse, |
| 450 | + HS_Arrays.all_R_coor, |
| 451 | + sparse_thr, |
| 452 | + SR_filename, |
| 453 | + "S", |
| 454 | + istep); |
| 455 | + } |
| 456 | + else |
| 457 | + { |
| 458 | + ModuleIO::save_sparse(HS_Arrays.SR_sparse, |
| 459 | + HS_Arrays.all_R_coor, |
| 460 | + sparse_thr, |
| 461 | + binary, |
| 462 | + SR_filename, |
| 463 | + pv, |
| 464 | + "S", |
| 465 | + istep); |
| 466 | + } |
200 | 467 | } |
201 | 468 |
|
202 | 469 | sparse_format::destroy_HS_R_sparse(HS_Arrays); |
|
0 commit comments