11#define sc_int64 static_cast<int64_t>
19 std::vector<int64_t>& nodal_nnz_in_diag,
20 std::vector<int64_t>& nodal_nnz_off_diag,
29 const int64_t local_block_start = 0;
30 const int64_t local_block_end = 0;
31 const std::vector<uint64_t>& locI_block_addr;
33 DOFHandler(int64_t block_start,
35 const std::vector<uint64_t>& in_locJ_block_address)
36 : local_block_start(block_start),
37 local_block_end(block_end),
38 locI_block_addr(in_locJ_block_address)
42 bool IsMapLocal(int64_t ir)
const
44 return (ir >= local_block_start and ir < local_block_end);
47 int64_t MapIRLocal(int64_t ir)
const {
return ir - local_block_start; }
49 int64_t GetLocFromIR(int64_t ir)
52 std::upper_bound(locI_block_addr.begin(), locI_block_addr.end(), ir) -
53 locI_block_addr.begin() - 1;
62 auto IR_MAP_ERROR = []()
69 auto JR_MAP_ERROR = []()
76 auto IS_VALUE_IN_VECTOR = [](
const std::vector<int64_t>& vec, int64_t val)
78 bool already_there =
false;
79 for (
auto check_val : vec)
94 nodal_nnz_in_diag.clear();
95 nodal_nnz_off_diag.clear();
103 for (
unsigned int i = 0; i < cell_mapping.NumNodes(); ++i)
105 const int64_t ir =
MapDOF(cell, i);
106 if (ir < 0) IR_MAP_ERROR();
108 if (dof_handler.IsMapLocal(ir))
110 const int64_t il = dof_handler.MapIRLocal(ir);
111 std::vector<int64_t>& node_links = nodal_connections[il];
113 for (
unsigned int j = 0; j < cell_mapping.NumNodes(); ++j)
115 const int64_t jr =
MapDOF(cell, j);
116 if (jr < 0) JR_MAP_ERROR();
118 if (IS_VALUE_IN_VECTOR(node_links, jr))
continue;
120 node_links.push_back(jr);
121 if (dof_handler.IsMapLocal(jr)) nodal_nnz_in_diag[il] += 1;
123 nodal_nnz_off_diag[il] += 1;
136 typedef std::pair<int64_t, std::vector<int64_t>> ROWJLINKS;
137 std::vector<ROWJLINKS> ir_links;
143 for (
unsigned int i = 0; i < cell_mapping.NumNodes(); ++i)
145 const int64_t ir =
MapDOF(cell, i);
146 if (ir < 0) IR_MAP_ERROR();
148 if (not dof_handler.IsMapLocal(ir))
150 ROWJLINKS new_ir_link;
151 ROWJLINKS* cur_ir_link = &new_ir_link;
154 bool ir_already_there =
false;
155 for (
auto& ir_link : ir_links)
156 if (ir == ir_link.first)
158 ir_already_there =
true;
159 cur_ir_link = &ir_link;
164 auto& node_links = cur_ir_link->second;
165 for (
unsigned int j = 0; j < cell_mapping.NumNodes(); ++j)
167 const int64_t jr =
MapDOF(cell, j);
168 if (jr < 0) JR_MAP_ERROR();
170 if (IS_VALUE_IN_VECTOR(node_links, jr))
continue;
172 node_links.push_back(jr);
176 if (not ir_already_there)
178 cur_ir_link->first = ir;
179 ir_links.push_back(*cur_ir_link);
191 std::vector<std::vector<int64_t>> locI_serialized(
Chi::mpi.process_count);
193 for (
const auto& ir_linkage : ir_links)
195 const int64_t locI = dof_handler.GetLocFromIR(ir_linkage.first);
197 locI_serialized[locI].push_back(
198 sc_int64(ir_linkage.second.size()));
199 locI_serialized[locI].push_back(
sc_int64(ir_linkage.first));
200 for (int64_t jr : ir_linkage.second)
201 locI_serialized[locI].push_back(jr);
208 std::vector<int> sendcount(
Chi::mpi.process_count, 0);
209 std::vector<int> recvcount(
Chi::mpi.process_count, 0);
211 for (
const auto& locI_data : locI_serialized)
213 sendcount[locI] =
static_cast<int>(locI_data.size());
217 <<
"To send to " << locI <<
" = " << sendcount[locI];
223 sendcount.data(), 1, MPI_INT, recvcount.data(), 1, MPI_INT,
Chi::mpi.
comm);
228 std::vector<int> send_displs(
Chi::mpi.process_count, 0);
229 std::vector<int> recv_displs(
Chi::mpi.process_count, 0);
231 int send_displ_c = 0;
232 int recv_displ_c = 0;
235 for (
int send_count : sendcount)
237 send_displs[c++] = send_displ_c;
238 send_displ_c += send_count;
241 for (
int recv_count : recvcount)
243 recv_displs[c++] = recv_displ_c;
244 recv_displ_c += recv_count;
252 std::vector<int64_t> sendbuf;
253 std::vector<int64_t> recvbuf;
255 sendbuf.reserve(send_displ_c);
256 recvbuf.resize(recv_displ_c, 0);
258 for (
const auto& serial_block : locI_serialized)
259 for (int64_t data_val : serial_block)
260 sendbuf.push_back(data_val);
262 MPI_Alltoallv(sendbuf.data(),
275 std::vector<ROWJLINKS> foreign_ir_links;
277 for (
size_t k = 0; k < recvbuf.size();)
279 const int64_t num_values = recvbuf[k++];
280 const int64_t ir = recvbuf[k++];
283 new_links.first = ir;
284 new_links.second.reserve(num_values);
285 for (
int i = 0; i < num_values; ++i)
286 new_links.second.push_back(recvbuf[k++]);
288 foreign_ir_links.push_back(std::move(new_links));
292 for (
const auto& ir_linkage : foreign_ir_links)
294 const int64_t ir = ir_linkage.first;
296 if (not dof_handler.IsMapLocal(ir)) IR_MAP_ERROR();
298 int64_t il = dof_handler.MapIRLocal(ir);
299 std::vector<int64_t>& node_links = nodal_connections[il];
301 for (int64_t jr : ir_linkage.second)
303 if (IS_VALUE_IN_VECTOR(node_links, jr))
continue;
305 node_links.push_back(jr);
306 if (dof_handler.IsMapLocal(jr)) nodal_nnz_in_diag[il] += 1;
308 nodal_nnz_off_diag[il] += 1;
316 auto backup_nnz_in_diag = nodal_nnz_in_diag;
317 auto backup_nnz_off_diag = nodal_nnz_off_diag;
321 nodal_nnz_in_diag.clear();
322 nodal_nnz_off_diag.clear();
332 for (
int j = 0; j < N; ++j)
335 nodal_nnz_in_diag[ir] = backup_nnz_in_diag[i];
336 nodal_nnz_off_diag[ir] = backup_nnz_off_diag[i];
344 for (
int j = 0; j < N; ++j)
349 nodal_nnz_in_diag[ir] = backup_nnz_in_diag[i];
350 nodal_nnz_off_diag[ir] = backup_nnz_off_diag[i];
static void Exit(int error_code)
static chi::MPI_Info & mpi
LogStream LogAllVerbose1()
const MPI_Comm & comm
MPI communicator.
const CellMapping & GetCellMapping(const chi_mesh::Cell &cell) const
uint64_t local_base_block_size_
uint64_t local_block_address_
std::vector< uint64_t > locJ_block_address_
const chi_mesh::MeshContinuum & ref_grid_
UnknownStorageType dof_storage_type_
unsigned int GetTotalUnknownStructureSize() const
void BuildSparsityPattern(std::vector< int64_t > &nodal_nnz_in_diag, std::vector< int64_t > &nodal_nnz_off_diag, const UnknownManager &unknown_manager) const override
int64_t MapDOF(const chi_mesh::Cell &cell, unsigned int node, const UnknownManager &unknown_manager, unsigned int unknown_id, unsigned int component) const override
LocalCellHandler local_cells