Arcane  4.1.12.0
Developer documentation
Loading...
Searching...
No Matches
ItemFamilyVariableSerializer.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/* ItemFamilyVariableSerializer.cc (C) 2000-2024 */
9/* */
10/* Manages the serialization/deserialization of variables for a family. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/NotSupportedException.h"
15#include "arcane/utils/HashTableMap.h"
16#include "arcane/utils/Collection.h"
17
18#include "arcane/core/VariableTypes.h"
20#include "arcane/core/ItemPrinter.h"
21#include "arcane/core/ISerializer.h"
22#include "arcane/core/IItemFamily.h"
23#include "arcane/core/ItemVector.h"
24#include "arcane/core/MeshToMeshTransposer.h"
25#include "arcane/core/ItemFamilySerializeArgs.h"
26#include "arcane/core/IParallelMng.h"
27// TODO: a supprimer
28#include "arcane/core/IMesh.h"
29#include "arcane/core/IVariableMng.h"
30#include "arcane/core/ISubDomain.h"
31
32#include "arcane/mesh/ItemFamilyVariableSerializer.h"
33
34#include <set>
35
36/*
37 * NOTE:
38 * Instead of one instance of this class managing the serialization of variables
39 * for the parent family and all child families, an instance per family would be necessary.
40 */
41/*---------------------------------------------------------------------------*/
42/*---------------------------------------------------------------------------*/
43
44namespace Arcane
45{
46class ItemFamilyExchange;
47}
48
49/*---------------------------------------------------------------------------*/
50/*---------------------------------------------------------------------------*/
51
52namespace Arcane::mesh
53{
54
55namespace
56{
57 const Integer VARIABLE_MAGIC_NUMBER = 0x3a9e4324;
58}
59/*---------------------------------------------------------------------------*/
60/*---------------------------------------------------------------------------*/
61
62ItemFamilyVariableSerializer::
63ItemFamilyVariableSerializer(IItemFamily* family)
64: TraceAccessor(family->traceMng())
65, m_item_family(family)
66{
67}
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
71
72ItemFamilyVariableSerializer::
73~ItemFamilyVariableSerializer()
74{
75}
76
77/*---------------------------------------------------------------------------*/
78/*---------------------------------------------------------------------------*/
79
80void ItemFamilyVariableSerializer::
81initialize()
82{
83 // Determines the list of variables to exchange
84 // It also includes variables from child families
85 // TODO: it would be necessary to retrieve the variables of each
86 // family via IItemFamily::usedVariables(), but this method does not guarantee
87 // alphabetical order of transmission. By thinking with an std::map, we
88 // should be able to manage it.
89 IVariableMng* vm = m_item_family->mesh()->variableMng();
90 VariableCollection used_vars(vm->usedVariables());
91
92 UniqueArray<IItemFamily*> family_to_exchange;
93 family_to_exchange.add(m_item_family); // The current family
94 IItemFamilyCollection child_families = m_item_family->childFamilies();
95 for (IItemFamily* child_family : child_families)
96 family_to_exchange.add(child_family);
97
98 for (Integer i = 0; i < family_to_exchange.size(); ++i) {
99 IItemFamily* current_family = family_to_exchange[i];
100 info(4) << " Serializing family " << current_family->fullName();
101
102 // TODO: retrieve the variables used by the family
103 // via ItemFamily::usedVariables
104 for (VariableCollection::Enumerator i_var(used_vars); ++i_var;) {
105 IVariable* var = *i_var;
106 // TODO: check if all variables need to be exchanged.
107 // Should PNoDump variables be sent?
108 // TODO: call the writeObservable of IVariableMng or make
109 // a specific one for balancing
110 // TODO: check that all sub-domains have the same values
111 // for m_variables_to_exchange with the variables in the same order.
112 bool no_exchange = (var->property() & IVariable::PNoExchange);
113 if (no_exchange)
114 continue;
115 IItemFamily* var_family = var->itemFamily();
116 if (var_family == current_family) {
117 debug(Trace::High) << "Add variable " << var->fullName() << " to serialize";
119 }
120 }
121 }
122 debug() << "Number of variables to serialize: " << m_variables_to_exchange.size();
123}
124
125/*---------------------------------------------------------------------------*/
126/*---------------------------------------------------------------------------*/
131void ItemFamilyVariableSerializer::
132_checkSerialization(ISerializer* sbuf, Int32ConstArrayView local_ids)
133{
134 switch (sbuf->mode()) {
135 case ISerializer::ModeReserve:
136 // Reserves for the uniqueId() list of transferred entities
137 sbuf->reserveInteger(1); // Magic number for readVariables();
138 sbuf->reserveInteger(1); // Number of serialized entities.
139 break;
141 // Serializes the number of transferred entities
142 sbuf->put(VARIABLE_MAGIC_NUMBER);
143 sbuf->put(local_ids.size());
144 break;
146 // Checks for serialization errors.
147 Integer magic_number = sbuf->getInteger();
148 if (magic_number != VARIABLE_MAGIC_NUMBER)
149 ARCANE_FATAL("Internal error: bad magic number expected={0} found={1}",
150 VARIABLE_MAGIC_NUMBER, magic_number);
151
152 // Retrieves the number of transferred entities for verification
153 Integer nb_item = sbuf->getInteger();
154 if (local_ids.size() != nb_item) {
155 // Since Arcane 2.4.0, 'm_family_serializer' is responsible for
156 // retrieving the localId() of the sent entities. The array
157 // m_receive_local_ids[i] must therefore always be correct.
158 ARCANE_FATAL("Bad value for received_items family={0} n={1} expected={2}",
159 m_item_family->name(), local_ids, nb_item);
160 }
161 break;
162 }
163}
164
165/*---------------------------------------------------------------------------*/
166/*---------------------------------------------------------------------------*/
171void ItemFamilyVariableSerializer::
172_checkSerializationVariable(ISerializer* sbuf, IVariable* var)
173{
174 String var_full_name = var->fullName();
175 switch (sbuf->mode()) {
176 case ISerializer::ModeReserve:
177 // Reserves for the variable name
178 sbuf->reserve(var_full_name);
179 break;
181 sbuf->put(var_full_name);
182 break;
184 String expected_name;
185 sbuf->get(expected_name);
186 if (expected_name != var_full_name)
187 ARCANE_FATAL("Incoherent variable var={0} expected={1}",
188 var_full_name, expected_name);
189 } break;
190 }
191}
192
193/*---------------------------------------------------------------------------*/
194/*---------------------------------------------------------------------------*/
200void ItemFamilyVariableSerializer::
201serialize(const ItemFamilySerializeArgs& args)
202{
203 ISerializer* sbuf = args.serializer();
204 Int32ConstArrayView local_ids = args.localIds();
205
206 bool is_recv = (sbuf->mode() == ISerializer::ModeGet);
207 String mode_str = (is_recv) ? "recv" : "send";
208 const bool is_debug = arcaneIsDebug();
209
210 Int32 owner_rank = (is_recv) ? m_item_family->parallelMng()->commRank() : args.rank();
211
212 _checkSerialization(sbuf, local_ids);
213
215 info(4) << "-- Serializing variable " << var->fullName()
216 << " group=" << var->itemGroup().name()
217 << " (n=" << var->itemGroup().size() << ")"
218 << " mode=" << (int)sbuf->mode()
219 << " target_rank=" << args.rank();
220
222
223 if (is_debug) {
224 ENUMERATE_ITEM (iitem, m_item_family->view(local_ids)) {
225 debug(Trace::Highest) << "To " << mode_str << " : " << ItemPrinter(*iitem);
226 }
227 debug(Trace::High) << "To " << mode_str << " count = " << local_ids.size();
228 }
229
230 if (var->itemFamily() != m_item_family) {
231 IItemFamily* var_family = var->itemFamily();
232 ItemVector dest_items = MeshToMeshTransposer::transpose(m_item_family,
233 var_family,
234 m_item_family->view(local_ids),
235 false);
236 Int32UniqueArray dest_lids;
237 dest_lids.reserve(dest_items.size());
238 ENUMERATE_ITEM (iitem, dest_items) {
239 Int32 lid = iitem.localId();
240 if (lid != NULL_ITEM_LOCAL_ID && iitem->owner() == owner_rank) {
241 dest_lids.add(lid);
242 }
243 }
244 debug(Trace::High) << "Serializing " << dest_lids.size() << " sub-items";
245
246 if (var->isPartial())
247 _serializePartialVariable(var, sbuf, dest_lids);
248 else
249 var->serialize(sbuf, dest_lids);
250 }
251 else {
252 if (var->isPartial())
253 _serializePartialVariable(var, sbuf, local_ids);
254 else
255 var->serialize(sbuf, local_ids);
256 }
257 }
258}
259
260/*---------------------------------------------------------------------------*/
261/*---------------------------------------------------------------------------*/
280void ItemFamilyVariableSerializer::
281_serializePartialVariable(IVariable* var, ISerializer* sbuf, Int32ConstArrayView local_ids)
282{
283 String var_full_name = var->fullName();
284
285 ItemGroup group = var->itemGroup();
286 ISerializer::eMode mode = sbuf->mode();
287 switch (mode) {
288 case ISerializer::ModeReserve:
290 Int32UniqueArray indexes_to_send;
291 Int64UniqueArray unique_ids_to_send;
292 std::set<Int32> items_to_send;
293 for (Integer i = 0, n = local_ids.size(); i < n; ++i) {
294 items_to_send.insert(local_ids[i]);
295 }
296 ENUMERATE_ITEM (iitem, group) {
297 if (items_to_send.find(iitem.itemLocalId()) != items_to_send.end()) {
298 indexes_to_send.add(iitem.index());
299 unique_ids_to_send.add((*iitem).uniqueId());
300 }
301 }
302 Integer nb_item_to_send = indexes_to_send.size();
303 if (mode == ISerializer::ModeReserve) {
304 // Reserves for the number of elements and for each element
305 sbuf->reserveInt64(1);
306 sbuf->reserveSpan(eBasicDataType::Int64, nb_item_to_send);
307 }
308 else {
309 sbuf->putInt64(nb_item_to_send);
310 sbuf->putSpan(unique_ids_to_send);
311 }
312 var->serialize(sbuf, indexes_to_send);
313 } break;
315 Int32UniqueArray indexes;
316 Int64UniqueArray unique_ids;
317 String expected_name;
318 //sbuf->get(expected_name);
319 //if (expected_name!=var_full_name)
320 //ARCANE_FATAL("Incoherent variable var={0} expected={1}",
321 //var_full_name,expected_name);
322 Int64 nb_item = sbuf->getInt64();
323 unique_ids.resize(nb_item);
324 sbuf->getSpan(unique_ids);
325 Integer nb_item_in_variable = group.size();
326 HashTableMapT<Int64, Int32> unique_ids_to_index(nb_item_in_variable, true);
327 ENUMERATE_ITEM (iitem, group) {
328 unique_ids_to_index.nocheckAdd((*iitem).uniqueId(), iitem.index());
329 }
330 indexes.resize(nb_item);
331 for (Integer i = 0; i < nb_item; ++i) {
332 // Checks that the entity is present. This is normally the case unless
333 // \a group is not consistent between the PE (that is, for example an
334 // entity \a x present on 2 PE but which is in \a group only for one
335 // of the two PE).
336 HashTableMapT<Int64, Int32>::Data* data = unique_ids_to_index.lookup(unique_ids[i]);
337 if (!data)
338 ARCANE_FATAL("Can not find item with unique_id={0} index={1}", unique_ids[i], i);
339 indexes[i] = data->value();
340 }
341
342 var->serialize(sbuf, indexes);
343 } break;
344 }
345}
346
347/*---------------------------------------------------------------------------*/
348/*---------------------------------------------------------------------------*/
349
350} // End namespace Arcane::mesh
351
352/*---------------------------------------------------------------------------*/
353/*---------------------------------------------------------------------------*/
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
Types and macros for iterating over mesh entities.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
Integer size() const
Number of elements in the vector.
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.
void reserve(Int64 new_capacity)
Reserves memory for new_capacity elements.
constexpr Integer size() const noexcept
Number of elements in the array.
Hash table for associative arrays.
void nocheckAdd(KeyTypeConstRef id, const ValueType &value)
Adds the value value corresponding to the key id.
Data * lookup(KeyTypeConstRef id)
Searches for the value corresponding to key id.
Interface of an entity family.
Definition IItemFamily.h:83
virtual String fullName() const =0
Full family name (with the mesh's name).
virtual ItemVectorView view(Int32ConstArrayView local_ids)=0
View on the entities.
virtual void reserve(eBasicDataType dt, Int64 n)=0
Reserves memory for n objects of type dt.
virtual Integer getInteger()=0
Retrieve a size.
virtual Int64 getInt64()=0
Retrieve a size.
virtual void put(Span< const Real > values)=0
Add the array values.
virtual void putSpan(Span< const Real > values)
Add the array values.
virtual eMode mode() const =0
Current operating mode.
virtual void getSpan(Span< Real > values)
Retrieve the array values.
virtual void get(ArrayView< Real > values)=0
Retrieve the array values.
virtual void reserveSpan(eBasicDataType dt, Int64 n)=0
Reserves memory for n values of dt.
virtual void putInt64(Int64 value)=0
Add the integer value.
Variable manager interface.
virtual VariableCollection usedVariables()=0
List of used variables.
Interface of a variable.
Definition IVariable.h:40
virtual String fullName() const =0
Full variable name (with family prefix).
@ PNoExchange
Indicates that the variable should not be exchanged.
Definition IVariable.h:130
virtual int property() const =0
Returns the properties of the variable.
virtual ItemGroup itemGroup() const =0
Associated mesh group.
virtual void serialize(ISerializer *sbuffer, IDataOperation *operation=0)=0
virtual IItemFamily * itemFamily() const =0
Associated entity family.
Arguments for the serialization callbacks of entity families.
Int32 rank() const
Rank of the source or destination.
Int32ConstArrayView localIds() const
Local indices of the entities. During serialization, these are the local indices of the entities sent...
ISerializer * serializer() const
Associated serializer.
Mesh entity group.
Definition ItemGroup.h:51
Integer size() const
Number of elements in the group.
Definition ItemGroup.h:93
Utility class for printing information about an entity.
Definition ItemPrinter.h:35
Entity vector.
Definition ItemVector.h:60
Int32 size() const
Number of elements in the vector.
Definition ItemVector.h:106
static ItemVector transpose(IMesh *meshA, IMesh *meshB, ItemVectorView itemsA, bool do_fatal=false)
Transpose itemsA from meshB to items on meshB.
TraceMessageDbg debug(Trace::eDebugLevel=Trace::Medium) const
Flow for a debug message.
TraceMessage info() const
Flow for an information message.
1D data vector with value semantics (STL style).
void _serializePartialVariable(IVariable *var, ISerializer *sbuf, Int32ConstArrayView local_ids)
Serialise une variable partielle.
void _checkSerializationVariable(ISerializer *sbuf, IVariable *var)
Serializes the variable name to verify that deserialization is correct.
void _checkSerialization(ISerializer *sbuf, Int32ConstArrayView local_ids)
Serializes a magic number and the number of entities to verify that deserialization is correct.
UniqueArray< IVariable * > m_variables_to_exchange
List of variables to exchange.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
UniqueArray< Int64 > Int64UniqueArray
Dynamic 1D array of 64-bit integers.
Definition UtilsTypes.h:339
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:482
Collection< IItemFamily * > IItemFamilyCollection
Collection of item families.
bool arcaneIsDebug()
True if the ARCANE_DEBUG macro is defined.
Definition Misc.cc:76
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:341
std::int32_t Int32
Signed integer type of 32 bits.