Arcane  4.2.3.0
Developer documentation
Loading...
Searching...
No Matches
VariableSynchronizerComputeList.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* VariableSynchronizerComputeList.cc (C) 2000-2024 */
9/* */
10/* Calculation of the list of entities to synchronize. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/impl/internal/VariableSynchronizerComputeList.h"
15
16#include "arcane/utils/ITraceMng.h"
17#include "arcane/utils/FatalErrorException.h"
18#include "arcane/utils/PlatformUtils.h"
19#include "arcane/utils/OStringStream.h"
20#include "arcane/utils/ValueConvert.h"
21
22#include "arcane/core/IParallelMng.h"
23#include "arcane/core/IItemFamily.h"
24#include "arcane/core/ItemPrinter.h"
25
26#include "arcane/impl/DataSynchronizeInfo.h"
27#include "arcane/impl/internal/VariableSynchronizer.h"
28
29#include <algorithm>
30
31/*---------------------------------------------------------------------------*/
32/*---------------------------------------------------------------------------*/
33
34namespace Arcane
35{
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
40VariableSynchronizerComputeList::
41VariableSynchronizerComputeList(VariableSynchronizer* var_sync)
42: TraceAccessor(var_sync->traceMng())
43, m_synchronizer(var_sync)
44, m_parallel_mng(var_sync->m_parallel_mng)
45, m_item_group(var_sync->m_item_group)
46, m_is_verbose(var_sync->m_is_verbose)
47{
48 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ARCANE_DEBUG_VARIABLESYNCHRONIZERCOMPUTELIST", true))
49 m_is_debug = (v.value() != 0);
50}
51
52/*---------------------------------------------------------------------------*/
53/*---------------------------------------------------------------------------*/
54
74void VariableSynchronizerComputeList::
75compute()
76{
77 const bool is_debug = m_is_debug;
78 IItemFamily* item_family = m_item_group.itemFamily();
79 Int32 my_rank = m_parallel_mng->commRank();
80 Int32 nb_rank = m_parallel_mng->commSize();
81
82 m_is_verbose = traceMng()->verbosityLevel() >= 4;
83
84 UniqueArray<SharedArray<Int32>> boundary_items(nb_rank);
85
86 if(m_is_verbose) {
87 info() << "Compute synchronize informations group=" << m_item_group.name()
88 << " family=" << item_family->fullName()
89 << " group size=" << m_item_group.size();
90 }
91
92 {
93 Integer nb_error = 0;
94 Int64UniqueArray bad_items_uid;
95 ENUMERATE_ITEM (i, m_item_group) {
96 Item item = *i;
97 impl::ItemBase item_internal = item.itemBase();
98 Int32 owner = item_internal.owner();
99 if (owner == my_rank)
100 continue;
101 Int64 uid = item_internal.uniqueId().asInt64();
102 if (owner == A_NULL_RANK || owner >= nb_rank) {
103 ++nb_error;
104 if (nb_error < 10)
105 bad_items_uid.add(uid);
106 continue;
107 }
108 if (is_debug) {
109 info() << "Add entity uid=" << uid
110 << " lid=" << item_internal.localId() << " to the subdomain " << owner;
111 }
112 boundary_items[owner].add(item_internal.localId());
113 }
114 if (nb_error != 0) {
115 for (Int64 uid : bad_items_uid) {
116 info() << "ERROR: The entity uid=" << uid
117 << " group=" << m_item_group.name() << " doesn't belong to "
118 << "any subdomain or belong to an invalid subdomain";
119 }
120 ARCANE_FATAL("Error while creating synchronization information nb_error={0}", nb_error);
121 }
122 }
123
124 _createList(boundary_items);
125
126 if (is_debug)
127 _printSyncList();
128
129 if(m_is_verbose) {
130 info() << "End compute synchronize information group=" << m_item_group.name()
131 << " Date=" << platform::getCurrentDateTime();
132 }
133}
134
135/*---------------------------------------------------------------------------*/
136/*---------------------------------------------------------------------------*/
137
138void VariableSynchronizerComputeList::
139_createList(UniqueArray<SharedArray<Int32>>& boundary_items)
140{
141 const bool is_debug = m_is_debug;
142 DataSynchronizeInfo* sync_info = m_synchronizer->m_sync_info.get();
143
144 sync_info->clear();
145
146 IItemFamily* item_family = m_item_group.itemFamily();
147 IParallelMng* pm = m_parallel_mng;
148 Int32 my_rank = pm->commRank();
149 Int32 nb_rank = pm->commSize();
150 info(4) << "VariableSynchronizer::createList() begin for group=" << m_item_group.name();
151
152 Real time_begin = platform::getRealTime();
153 Real time_before_all_gather = 0.0;
154 Real time_after_all_gather = 0.0;
155 Real time_before_sendrecv = 0.0;
156 Real time_after_sendrecv = 0.0;
157 Real time_after_sendrecv_wait = 0.0;
158
159 // Table of neighborhood known by ghost items.
160 // This is not necessarily the final list for sync_info->communicatingRanks() in the case
161 // of non-symmetric ghost/shared relationship between processors (if one of them is 0)
162 // The complementary processing appears after the "Communication Reciprocity" section
163 Int32UniqueArray communicating_ghost_ranks;
164 for (Integer i = 0; i < nb_rank; ++i) {
165 if (boundary_items[i].empty())
166 continue;
167 communicating_ghost_ranks.add(i);
168 if (is_debug) {
169 ItemInfoListView items_internal(item_family);
170 for (Integer z = 0, zs = boundary_items[i].size(); z < zs; ++z) {
171 Item item = items_internal[boundary_items[i][z]];
172 info() << "Item uid=" << item.uniqueId() << ",lid=" << item.localId();
173 }
174 }
175 }
176
177 Integer nb_comm_rank = communicating_ghost_ranks.size();
178
179 Int32UniqueArray nb_ghost(nb_rank);
180 Int32UniqueArray nb_share(nb_rank);
181 nb_ghost.fill(0);
182
183 // Maximum number of connected subdomains. Used to dimension
184 // the arrays for the allGather()
185 Integer max_comm_rank = pm->reduce(Parallel::ReduceMax, nb_comm_rank);
186 debug() << "communicating sub domains my=" << nb_comm_rank
187 << " max=" << max_comm_rank;
188
189 // List of ghost cell groups.
190 UniqueArray<SharedArray<Int32>> ghost_group_list(boundary_items.size());
191
192 // Retrieves the lists of ghost entities.
193 for (Integer i = 0; i < nb_comm_rank; ++i) {
194 Int32 current_rank = communicating_ghost_ranks[i];
195 SharedArray<Int32>& ghost_grp = boundary_items[current_rank];
196 ghost_group_list[i] = ghost_grp;
197 nb_ghost[current_rank] = ghost_grp.size();
198 }
199
200 UniqueArray<ShareRankInfo> share_rank_info;
201 UniqueArray<GhostRankInfo> ghost_rank_info;
202 {
203 Integer gather_size = 1 + (max_comm_rank * 2);
204 Int32UniqueArray global_ghost_info(gather_size * nb_rank);
205 {
206 // Each subdomain constructs an array indicating for
207 // each group of ghost elements, the concerned processor and
208 // the number of elements in this group.
209 // This array will then be gathered across all subdomains
210 // (by an allGather()) so that each subdomain can iterate through it
211 // and then know who owns its shared cells.
212 Int32UniqueArray local_ghost_info(gather_size);
213 Integer pos = 0;
214 local_ghost_info[pos++] = nb_comm_rank; // Indicates the number of elements in the array
215 debug() << "Send local info " << nb_comm_rank;
216 for (Integer index = 0, s = communicating_ghost_ranks.size(); index < s; ++index) {
217 local_ghost_info[pos++] = communicating_ghost_ranks[index];
218 local_ghost_info[pos++] = ghost_group_list[index].size();
219 debug() << "Send local info i=" << index << " target=" << communicating_ghost_ranks[index]
220 << " nb=" << ghost_group_list[index].size();
221 }
222 time_before_all_gather = platform::getRealTime();
223 if (m_is_verbose) {
224 info() << "AllGather size() " << local_ghost_info.size()
225 << ' ' << global_ghost_info.size()
226 << " begin_date=" << platform::getCurrentDateTime();
227 }
228 pm->allGather(local_ghost_info, global_ghost_info);
229 time_after_all_gather = platform::getRealTime();
230 if (m_is_verbose) {
231 info() << "AllGather end_date=" << platform::getCurrentDateTime();
232 }
233 }
234 {
235 for (Integer index = 0, s = nb_rank; index < s; ++index) {
236 Integer pos = gather_size * index;
237 Integer sub_size = global_ghost_info[pos++];
238 for (Integer sub_index = 0; sub_index < sub_size; ++sub_index) {
239 Integer proc_id = global_ghost_info[pos++];
240 Integer nb_elem = global_ghost_info[pos++];
241 if (proc_id == my_rank) {
242 if (is_debug) {
243 info() << "Get for share group " << index << ' ' << nb_elem;
244 }
245 share_rank_info.add(ShareRankInfo(index, nb_elem));
246 }
247 }
248 }
249 }
250
251 {
252 // Created the infos concerning the ghost cells
253 Integer nb_send = communicating_ghost_ranks.size();
254 ghost_rank_info.resize(nb_send);
255 for (Integer i = 0; i < nb_send; ++i) {
256 SharedArray<Int32> gr = ghost_group_list[i];
257 ghost_rank_info[i].setInfos(communicating_ghost_ranks[i], gr);
258 }
259 }
260 }
261 //pm->barrier();
262 ItemInfoListView items_internal(item_family);
263 {
264 {
265 // Communication Reciprocity
266 // For synchronizations to work correctly, it is necessary that
267 // 'share_rank_info' and 'ghost_rank_info' have
268 // the same number of elements. If this is not the case, it means
269 // that a processor 'n' owns shared cells with proc 'm'
270 // without this being reciprocal. If this is the case, we add
271 // a reference to this subdomain in 'share_rank_info'
272 // with no elements to send.
273 Integer nb_recv = share_rank_info.size();
274 Integer nb_send = ghost_rank_info.size();
275
276 if (is_debug) {
277 info() << "Infos before auto add: send " << nb_send << " recv " << nb_recv;
278 for (Integer i = 0; i < ghost_rank_info.size(); ++i) {
279 const GhostRankInfo& asdi = ghost_rank_info[i];
280 info() << "Ghost: " << i << asdi.nbItem() << ' ' << asdi.rank();
281 }
282 for (Integer i = 0; i < share_rank_info.size(); ++i) {
283 const ShareRankInfo& asdi = share_rank_info[i];
284 info() << "Shared: " << i << ' ' << asdi.nbItem() << ' ' << asdi.rank();
285 }
286 }
287
288 for (Integer i = 0; i < nb_send; ++i) {
289 Integer proc_id = ghost_rank_info[i].rank();
290 Integer z = 0;
291 for (; z < nb_recv; ++z)
292 if (share_rank_info[z].rank() == proc_id)
293 break;
294 debug(Trace::Highest) << "CHECKS " << proc_id << ' ' << z << ' ' << nb_recv;
295 if (z == nb_recv) {
296 debug() << "Add communication with the subdomain " << proc_id;
297 share_rank_info.add(ShareRankInfo(proc_id));
298 }
299 }
300
301 for (Integer i = 0; i < nb_recv; ++i) {
302 Integer proc_id = share_rank_info[i].rank();
303 Integer z = 0;
304 for (; z < nb_send; ++z)
305 if (ghost_rank_info[z].rank() == proc_id)
306 break;
307 debug(Trace::Highest) << "CHECKR " << proc_id << ' ' << z << ' ' << nb_send;
308 if (z == nb_send) {
309 debug() << "Add communication with subdomain " << proc_id;
310 ghost_rank_info.add(GhostRankInfo(proc_id));
311 }
312 }
313
314 if (ghost_rank_info.size() != share_rank_info.size()) {
315 ARCANE_FATAL("Problem with the number of subdomain shared ({0}) and ghosts ({1})",
316 share_rank_info.size(), ghost_rank_info.size());
317 }
318 // Sort the array by increasing subdomain number.
319 std::sort(std::begin(share_rank_info), std::end(share_rank_info));
320 std::sort(std::begin(ghost_rank_info), std::end(ghost_rank_info));
321 }
322
323 // OK, now we know the list of subdomains that possess
324 // the shared cells of this subdomain and conversely, the list of
325 // subdomains interested in the own cells of this subdomain.
326 // All that remains is to send and receive the corresponding information.
327 // To do this, and to avoid deadlocks, we first send the info
328 // for the subdomains whose number is less than this subdomain.
329 Integer nb_comm_proc = ghost_rank_info.size();
330 info(4) << "Number of communicating processors: " << nb_comm_proc;
332 time_before_sendrecv = platform::getRealTime();
333 {
334 //Integer nb_recv = share_rank_info.size();
335
336 // Sort the array by increasing subdomain number.
337 for (Integer i = 0; i < ghost_rank_info.size(); ++i) {
338 const GhostRankInfo& asdi = ghost_rank_info[i];
339 debug() << "Ghost: " << i << " " << asdi.nbItem() << ' ' << asdi.rank();
340 }
341 for (Integer i = 0; i < share_rank_info.size(); ++i) {
342 const ShareRankInfo& asdi = share_rank_info[i];
343 debug() << "Shared: " << i << " " << asdi.nbItem() << ' ' << asdi.rank();
344 }
345 Integer current_send_index = 0;
346 Integer current_recv_index = 0;
347 for (Integer i = 0; i < nb_comm_proc * 2; ++i) {
348 Integer send_proc = nb_rank;
349 Integer recv_proc = nb_rank;
350 if (current_send_index != nb_comm_proc)
351 send_proc = ghost_rank_info[current_send_index].rank();
352 if (current_recv_index != nb_comm_proc)
353 recv_proc = ghost_rank_info[current_recv_index].rank();
354 bool do_send = true;
355 if (send_proc == recv_proc) {
356 if (send_proc < my_rank)
357 do_send = true;
358 else
359 do_send = false;
360 }
361 else if (send_proc < recv_proc)
362 do_send = true;
363 else
364 do_send = false;
365 if (do_send) {
366 GhostRankInfo& asdi = ghost_rank_info[current_send_index];
367 asdi.resize();
368 Int64ArrayView uids = asdi.uniqueIds();
369 Int32ConstArrayView asdi_local_ids = asdi.localIds();
370 //Integer zindex = 0;
371 Integer nb_local = asdi_local_ids.size();
372 for (Integer z = 0, zs = nb_local; z < zs; ++z) {
373 //for( ItemGroup::const_iter z(asdi.group()); z.hasNext(); ++z, ++zindex ){
374 const Item& elem = items_internal[asdi_local_ids[z]];
375 uids[z] = elem.uniqueId().asInt64();
376 }
377 if (is_debug) {
378 info() << "Number of elements that will be sent to the subdomain " << send_proc
379 << " " << nb_local << " elements";
380 for (Integer z = 0; z < nb_local; ++z) {
381 info() << "Unique id " << uids[z];
382 }
383 }
384 debug() << "Send proc " << send_proc;
385 if (!uids.empty())
386 requests.add(pm->send(uids, send_proc, false));
387 ++current_send_index;
388 }
389 else {
390 ShareRankInfo& asdi = share_rank_info[current_recv_index];
391 asdi.resize();
392 Int64ArrayView items_unique_id = asdi.uniqueIds();
393 debug() << "Recv proc " << recv_proc;
394 //TODO use non-blocking.
395 if (!items_unique_id.empty())
396 pm->recv(items_unique_id, recv_proc);
397 //String group_name(share_name);
398 //group_name += recv_proc;
399
400 SharedArray<Int32> items_local_id(items_unique_id.size());
401 item_family->itemsUniqueIdToLocalId(items_local_id, items_unique_id);
402 SharedArray<Int32> share_group = items_local_id;
403 debug() << "Creating shared entities for the subdomain " << recv_proc
404 << " with " << items_local_id.size() << " entities";
405 //ItemGroup share_group = mesh->itemFamily(item_kind)->createGroup(group_name,items_local_id,true);
406 //share_group.setLocalToSubDomain(true);
407 asdi.setLocalIds(share_group);
408 if (is_debug) {
409 for (Integer z = 0, zs = share_group.size(); z < zs; ++z) {
410 const Item& item = items_internal[share_group[z]];
411 info() << "Item uid=" << item.uniqueId() << ",lid=" << item.localId();
412 }
413 }
414 ++current_recv_index;
415 }
416 }
417 time_after_sendrecv = platform::getRealTime();
418 if (m_is_verbose) {
419 info() << "Wait requests n=" << requests.size()
420 << " begin_date=" << platform::getCurrentDateTime();
421 }
422 pm->waitAllRequests(requests);
423 time_after_sendrecv_wait = platform::getRealTime();
424 if (m_is_verbose) {
425 info() << "Wait requests end_date=" << platform::getCurrentDateTime();
426 }
427 }
428 }
429 _checkValid(ghost_rank_info, share_rank_info);
430 sync_info->recompute();
431
432 // Verify that all ghosts have been found
433 for (Integer i = 0, n = sync_info->size(); i < n; ++i) {
434 Int32 target_rank = sync_info->targetRank(i);
435 if (sync_info->receiveInfo().nbItem(i) != boundary_items[target_rank].size())
436 ARCANE_FATAL("Inconsistent ghost count");
437 }
438
439 info(4) << "VariableSynchronize:: end compute list group=" << m_item_group.name()
440 << " t_init=" << Trace::Precision(4, time_before_all_gather - time_begin, true)
441 << " t_allgather=" << Trace::Precision(4, time_after_all_gather - time_before_all_gather, true)
442 << " t_sendrecv=" << Trace::Precision(4, time_after_sendrecv_wait - time_before_sendrecv, true)
443 << " t_wait=" << Trace::Precision(4, time_after_sendrecv_wait - time_after_sendrecv, true);
444}
445
446/*---------------------------------------------------------------------------*/
447/*---------------------------------------------------------------------------*/
448
449void VariableSynchronizerComputeList::
450_checkValid(ArrayView<GhostRankInfo> ghost_rank_info,
451 ArrayView<ShareRankInfo> share_rank_info)
452{
453 const bool is_debug = m_is_debug;
454 Integer nb_comm_proc = ghost_rank_info.size();
455 Integer nb_error = 0;
456 bool has_error = false;
457 const Integer max_error = 10; // Max number of errors displayed.
458 Int32 my_rank = m_parallel_mng->commRank();
459 IItemFamily* item_family = m_item_group.itemFamily();
460 ItemInfoListView items_internal(item_family);
461
462 // Array used to mark elements that are either
463 // owned by the subdomain or ghost.
464 // Normally, if the data is consistent, this should mark
465 // all elements.
466 // NOTE: this is only useful if \a itemGroup() equals allItems()
467 UniqueArray<bool> marked_elem(item_family->maxLocalId());
468 marked_elem.fill(false);
469 // Mark elements owned by the subdomain
470 ENUMERATE_ITEM (i_item, m_item_group) {
471 Item item = *i_item;
472 if (item.isOwn()) {
473 marked_elem[item.localId()] = true;
474 if (is_debug) {
475 info() << "Own Item " << ItemPrinter(item);
476 }
477 }
478 }
479
480 for (Integer i_comm = 0; i_comm < nb_comm_proc; ++i_comm) {
481 GhostRankInfo& ghost_info = ghost_rank_info[i_comm];
482 ShareRankInfo& share_info = share_rank_info[i_comm];
483 if (ghost_info.rank() != share_info.rank()) {
484 ARCANE_FATAL("Inconsistency between the subdomain numbers ghost_rank={0} share_rank={1}",
485 ghost_info.rank(), share_info.rank());
486 }
487 Integer current_proc = ghost_info.rank();
488 Int32ConstArrayView ghost_grp = ghost_info.localIds();
489 Int32ConstArrayView share_grp = share_info.localIds();
490
491 if (share_grp.empty() && ghost_grp.empty()) {
492 error() << "Shared and ghosts groups null for the subdomain " << current_proc;
493 has_error = true;
494 continue;
495 }
496 if (current_proc == my_rank) {
497 error() << "Error in the communication pattern: "
498 << "the processor can't communicate with itself";
499 has_error = true;
500 continue;
501 }
502
503 // Mark elements of the shared group
504 for (Integer z = 0, zs = ghost_grp.size(); z < zs; ++z) {
505 const Item& elem = items_internal[ghost_grp[z]];
506 bool is_marked = marked_elem[elem.localId()];
507 if (is_marked) {
508 // The element should not already be marked.
509 if (nb_error < max_error)
510 error() << "The entity " << ItemPrinter(elem) << " belongs to another ghost group "
511 << "or is owned by the subdomain.";
512 ++nb_error;
513 continue;
514 }
515 marked_elem[elem.localId()] = true;
516 }
517
518 m_synchronizer->m_sync_info->add(VariableSyncInfo(share_grp, ghost_grp, current_proc));
519 }
520
521 // Verify that all elements are marked
522 ENUMERATE_ITEM (i, m_item_group) {
523 Item item = *i;
524 if (!marked_elem[item.localId()]) {
525 if (nb_error < max_error) {
526 error() << "The entity " << ItemPrinter(item)
527 << " doesn't belong to the subdomain or any ghost group.";
528 }
529 ++nb_error;
530 }
531 }
532
533 // If there is an error, we stop.
534 if (nb_error != 0) {
535 has_error = true;
536 if (nb_error >= max_error)
537 error() << nb_error << " total elements are incorrectly dealt with";
538 }
539 if (has_error)
540 ARCANE_FATAL("Error while creating the exchange structures of the family={0}",
541 item_family->fullName());
542}
543
544/*---------------------------------------------------------------------------*/
545/*---------------------------------------------------------------------------*/
546
547void VariableSynchronizerComputeList::
548_printSyncList()
549{
550 DataSynchronizeInfo* sync_info = m_synchronizer->m_sync_info.get();
551 Integer nb_comm = sync_info->size();
552 info() << "SYNC LIST FOR GROUP : " << m_item_group.fullName() << " N=" << nb_comm;
553 OStringStream ostr;
554 IItemFamily* item_family = m_item_group.itemFamily();
555 ItemInfoListView items_internal(item_family);
556 for (Integer i = 0; i < nb_comm; ++i) {
557 Int32 target_rank = sync_info->targetRank(i);
558 ostr() << " TARGET=" << target_rank << '\n';
559 Int32ConstArrayView share_ids = sync_info->sendInfo().localIds(i);
560 ostr() << "\t\tSHARE(lid,uid) n=" << share_ids.size() << " :";
561 for (Integer z = 0, zs = share_ids.size(); z < zs; ++z) {
562 Item item = items_internal[share_ids[z]];
563 ostr() << " (" << item.localId() << "," << item.uniqueId() << ")";
564 }
565 ostr() << "\n";
566 Int32ConstArrayView ghost_ids = sync_info->receiveInfo().localIds(i);
567 ostr() << "\t\tGHOST(lid,uid) n=" << ghost_ids.size() << " :";
568 for (Integer z = 0, zs = ghost_ids.size(); z < zs; ++z) {
569 Item item = items_internal[ghost_ids[z]];
570 ostr() << " (" << item.localId() << "," << item.uniqueId() << ")";
571 }
572 ostr() << "\n";
573 }
574 info() << ostr.str();
575}
576
577/*---------------------------------------------------------------------------*/
578/*---------------------------------------------------------------------------*/
579
580} // namespace Arcane
581
582/*---------------------------------------------------------------------------*/
583/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
Integer size() const
Number of elements in the vector.
Modifiable view of an array of type T.
constexpr Integer size() const noexcept
Returns the size of the array.
constexpr bool empty() const noexcept
Returns true if the array is empty (zero dimension).
void fill(ConstReferenceType value)
Fills the array with the value value.
void resize(Int64 s)
Changes the number of elements in the array to s.
void add(ConstReferenceType val)
Adds element val to the end of the array.
constexpr Integer size() const noexcept
Number of elements in the array.
Int32 nbItem(Int32 index) const
Number of entities for rank index.
Information necessary to synchronize entities across a group.
Int32 targetRank(Int32 index) const
Rank of the index-th target.
void recompute()
Notifies the instance that the values have changed.
const DataSynchronizeBufferInfoList & receiveInfo() const
Receive (ghost) information.
Interface of an entity family.
Definition IItemFamily.h:85
virtual Int32 maxLocalId() const =0
virtual String fullName() const =0
Full family name (with the mesh's name).
virtual void itemsUniqueIdToLocalId(Int32ArrayView local_ids, Int64ConstArrayView unique_ids, bool do_fatal=true) const =0
Converts an array of unique numbers to local numbers.
Interface of the parallelism manager for a subdomain.
virtual Int32 commRank() const =0
Rank of this instance in the communicator.
virtual void recv(ArrayView< char > values, Int32 rank)=0
virtual Int32 commSize() const =0
Number of instances in the communicator.
virtual void allGather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf)=0
Performs an all-gather operation across all processors. This is a collective operation....
virtual void waitAllRequests(ArrayView< Request > rvalues)=0
Blocks while waiting for the rvalues requests to complete.
virtual char reduce(eReduceType rt, char v)=0
Performs a reduction of type rt on the real v and returns the value.
ItemUniqueId uniqueId() const
Unique number of the entity.
Int32 owner() const
Number of the owning subdomain of the entity.
Int32 localId() const
Local number (in the subdomain) of the entity.
View of a list to obtain information about entities.
Utility class for printing information about an entity.
Definition ItemPrinter.h:35
Base class for a mesh element.
Definition Item.h:84
constexpr Int32 localId() const
Local identifier of the entity in the processor subdomain.
Definition Item.h:233
ItemUniqueId uniqueId() const
Unique identifier across all domains.
Definition Item.h:239
constexpr bool isOwn() const
true if the entity belongs to the subdomain
Definition Item.h:267
impl::ItemBase itemBase() const
Internal part of the entity.
Definition Item.h:383
1D vector of data with reference semantics.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
Formatting real numbers with a given precision.
1D data vector with value semantics (STL style).
void _createList(UniqueArray< SharedArray< Int32 > > &boundary_items)
Interface of a variable synchronization service.
@ ReduceMax
Maximum of values.
Real getRealTime()
Real time used in seconds.
String getCurrentDateTime()
Current date and time in ISO 8601 format.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
ArrayView< Int64 > Int64ArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:445
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:333
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
Definition UtilsTypes.h:476
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:335
double Real
Type representing a real number.
std::int32_t Int32
Signed integer type of 32 bits.