Arcane  4.2.3.0
User documentation
Loading...
Searching...
No Matches
MeshStats.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/* MeshStats.cc (C) 2000-2026 */
9/* */
10/* Mesh statistics. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "IMeshStats.h"
16#include "arcane/utils/StringBuilder.h"
17#include "arcane/utils/Collection.h"
18
19#include "arcane/core/MeshStats.h"
20#include "arcane/core/Item.h"
21#include "arcane/core/ItemGroup.h"
23#include "arcane/core/IMesh.h"
24#include "arcane/core/IItemFamily.h"
25#include "arcane/core/IParallelMng.h"
26#include "arcane/core/IVariable.h"
27#include "arcane/core/IVariableMng.h"
28#include "arcane/core/ISubDomain.h"
29#include "arcane/core/StringDictionary.h"
30#include "arcane/core/VariableCollection.h"
31#include "arcane/core/IVariableSynchronizer.h"
32#include "arcane/core/MeshHandle.h"
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36
37namespace Arcane
38{
39
40/*---------------------------------------------------------------------------*/
41/*---------------------------------------------------------------------------*/
42
43IMeshStats* IMeshStats::
44create(ITraceMng* trace, IMesh* mesh, IParallelMng* pm)
45{
46 return new MeshStats(trace, mesh, pm);
47}
48
49/*---------------------------------------------------------------------------*/
50/*---------------------------------------------------------------------------*/
51
52Ref<IMeshStats> IMeshStats::
53create(ITraceMng* tm, IMesh* mesh)
54{
55 return makeRef<IMeshStats>(new MeshStats(tm,mesh));
56}
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60
61MeshStats::
62MeshStats(ITraceMng* trace, IMesh* mesh, IParallelMng* pm)
63: TraceAccessor(trace)
64, m_mesh(mesh)
65, m_parallel_mng(pm)
66{
67}
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
71
72MeshStats::
73MeshStats(ITraceMng* tm, IMesh* mesh)
74: TraceAccessor(tm)
75, m_mesh(mesh)
76, m_parallel_mng(mesh->parallelMng())
77{
78}
79/*---------------------------------------------------------------------------*/
80/*---------------------------------------------------------------------------*/
81
84{
85 // Mesh statistics display
86 _dumpStats<IMesh>();
87}
88
89/*---------------------------------------------------------------------------*/
90/*---------------------------------------------------------------------------*/
91
94{
95 _dumpStats<IMesh>();
96}
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
100
101template <> void MeshStats::
102_computeElementsOnGroup<IMesh>(ArrayView<Int64> nb_type, Int64ArrayView nb_kind, Integer istat)
103{
104 _computeElementsOnGroup(nb_type, nb_kind, m_mesh->allNodes(), istat);
105 _computeElementsOnGroup(nb_type, nb_kind, m_mesh->allEdges(), istat);
106 _computeElementsOnGroup(nb_type, nb_kind, m_mesh->allFaces(), istat);
107 _computeElementsOnGroup(nb_type, nb_kind, m_mesh->allCells(), istat);
108}
109
110/*---------------------------------------------------------------------------*/
111/*---------------------------------------------------------------------------*/
112
113template <> void MeshStats::
114_statLabel<IMesh>(const String& name)
115{
116 info() << " -- MESH STATISTICS " << Trace::Width(8) << name
117 << " FOR " << m_mesh->name();
118}
119
120/*---------------------------------------------------------------------------*/
121/*---------------------------------------------------------------------------*/
122
123template <typename T> void MeshStats::
124_dumpStats()
125{
126 Trace::Setter setter(traceMng(), "Mesh");
127
128 const Integer nb_type = m_mesh->itemTypeMng()->types().size();
129 const Integer nb_kind = NB_ITEM_KIND;
130
131 const char* name[3] = { "(All)", "(Own)", "(Ghost)" };
132
133 // To handle Own and Ghost only in parallel
134 const Integer nstat = (m_parallel_mng->isParallel()) ? 3 : 1;
135
136 // We group all data into the same communication
137 const Integer data_by_stat = nb_type + nb_kind;
138 const Integer all_data_count = nstat * data_by_stat;
139 Int64UniqueArray nb_data(all_data_count, 0);
140
141 // We now fill the entire array block by block
142 for (Integer istat = 0; istat < nstat; ++istat) {
143 const Integer first_type = istat * data_by_stat;
144 const Integer first_kind = first_type + nb_type;
145 // Number of elements of each type on this subdomain.
146 Int64ArrayView nb_local_type = nb_data.view().subView(first_type, nb_type);
147 // Number of elements of each kind on a subdomain
148 Int64ArrayView nb_local_kind = nb_data.view().subView(first_kind, nb_kind);
149 _computeElementsOnGroup<T>(nb_local_type, nb_local_kind, istat);
150 }
151
152 // Summary result table
153 Int64UniqueArray nb_data_min(all_data_count, 0);
154 Int64UniqueArray nb_data_max(all_data_count, 0);
155 Int64UniqueArray nb_data_sum(all_data_count, 0);
156 Int32UniqueArray min_data_rank(all_data_count, 0);
157 Int32UniqueArray max_data_rank(all_data_count, 0);
158 m_parallel_mng->computeMinMaxSum(nb_data,
159 nb_data_min,
160 nb_data_max,
161 nb_data_sum,
162 min_data_rank,
163 max_data_rank);
164
165 // We check if there is anything to display
166 {
167 bool is_empty = true;
168 for (Integer istat = 0; istat < nstat; ++istat) {
169 const Integer first_type = istat * data_by_stat;
170 Int64ConstArrayView nb_global_type = nb_data_sum.subConstView(first_type, nb_type);
171 for (Integer i = 0; i < nb_global_type.size(); ++i)
172 if (nb_global_type[i] != 0) {
173 is_empty = false;
174 break;
175 }
176 if (!is_empty)
177 break;
178 }
179 if (is_empty)
180 return;
181 }
182
183 ItemTypeMng* type_mng = m_mesh->itemTypeMng();
184
185 // We now produce the stats display
186 const Integer nb_rank = m_parallel_mng->commSize();
187 for (Integer istat = 0; istat < nstat; ++istat) {
188 // Construction of decompressed working views
189 // (reusing variable names from the previous version)
190 const Integer first_type = istat * data_by_stat;
191 const Integer first_kind = first_type + nb_type;
192
193 Int64ConstArrayView nb_local_type = nb_data.subConstView(first_type, nb_type);
194 Int64ConstArrayView nb_local_min_type = nb_data_min.subConstView(first_type, nb_type);
195 Int64ConstArrayView nb_local_max_type = nb_data_max.subConstView(first_type, nb_type);
196 Int64ConstArrayView nb_global_type = nb_data_sum.subConstView(first_type, nb_type);
197 Int32ConstArrayView min_rank_type = min_data_rank.subConstView(first_type, nb_type);
198 Int32ConstArrayView max_rank_type = max_data_rank.subConstView(first_type, nb_type);
199
200 Int64ConstArrayView nb_local_kind = nb_data.subConstView(first_kind, nb_kind);
201 Int64ConstArrayView nb_local_min_kind = nb_data_min.subConstView(first_kind, nb_kind);
202 Int64ConstArrayView nb_local_max_kind = nb_data_max.subConstView(first_kind, nb_kind);
203 Int64ConstArrayView nb_global_kind = nb_data_sum.subConstView(first_kind, nb_kind);
204 Int32ConstArrayView min_rank_kind = min_data_rank.subConstView(first_kind, nb_kind);
205 Int32ConstArrayView max_rank_kind = max_data_rank.subConstView(first_kind, nb_kind);
206
207 info() << " -------------------------------------------";
208 _statLabel<T>(name[istat]);
209
210 info() << Trace::Width(18) << "Item"
211 << Trace::Width(10) << "Myself"
212 << Trace::Width(10) << "Min"
213 << Trace::Width(8) << "Rank"
214 << Trace::Width(10) << "Max"
215 << Trace::Width(8) << "Rank"
216 << Trace::Width(10) << "Average"
217 << Trace::Width(10) << "Bal"
218 << Trace::Width(12) << "Total";
219
220 info() << " ";
221 for (Integer i = 0, s = nb_kind; i < s; ++i) {
222 eItemKind kt = static_cast<eItemKind>(i);
223 _printInfo(itemKindName(kt), nb_local_kind[i],
224 nb_local_min_kind[i], min_rank_kind[i],
225 nb_local_max_kind[i], max_rank_kind[i],
226 nb_global_kind[i], nb_rank);
227 // if (nb_global_kind[i]!=0) {
228 // pinfo() << "MeshStats ("<< m_parallel_mng->commRank() <<") : " << name[istat]
229 // << " kind=" << itemKindName(kt)
230 // << " n=" << nb_local_kind[i];
231 // plog() << "MeshStats ("<< m_parallel_mng->commRank() <<") : " << name[istat]
232 // << " kind=" << itemKindName(kt)
233 // << " n=" << nb_local_kind[i];
234 // }
235 }
236 info() << " ";
237 for (Integer i = 0, s = nb_type; i < s; ++i) {
238 _printInfo(type_mng->typeName(i), nb_local_type[i],
239 nb_local_min_type[i], min_rank_type[i],
240 nb_local_max_type[i], max_rank_type[i],
241 nb_global_type[i], nb_rank);
242 // if (nb_global_type[i]!=0)
243 // pinfo() << "MeshStats ("<< m_parallel_mng->commRank() <<") : " << name[istat]
244 // << " type=" << Item::typeName(i)
245 // << " n=" << nb_local_type[i];
246 }
247 info() << " ";
248 info() << " -------------------------------------------";
249 }
250 // _computeNeighboorsComm();
251
252 _dumpCommunicatingRanks();
253 _dumpLegacyConnectivityMemoryUsage();
254 _dumpIncrementalConnectivityMemoryUsage();
255}
256
257/*---------------------------------------------------------------------------*/
258/*---------------------------------------------------------------------------*/
259
260void MeshStats::
261_dumpLegacyConnectivityMemoryUsage()
262{
263 // This list of names comes from mesh/ItemFamily.cc
264 UniqueArray<String> var_names = { "FamilyItemsData", "FamilyItemsShared" };
265 IVariableMng* vm = m_mesh->variableMng();
266 Real total_memory = 0.0;
267 for (IItemFamily* family : m_mesh->itemFamilies()) {
268 String name = family->name();
269 Real family_memory = 0.0;
270 info(4) << "Family name=" << family->name();
271 for (const String& s : var_names) {
272 IVariable* v = vm->findMeshVariable(m_mesh, name + s);
273 if (v) {
274 Real v_memory = v->allocatedMemory();
275 family_memory += v_memory;
276 info(4) << "Allocated Memory n=" << s << " v=" << v_memory;
277 }
278 }
279 info(4) << "Memory for family name=" << name << " mem=" << family_memory;
280 total_memory += family_memory;
281 }
282 info() << "Total memory for legacy connectivities mem=" << total_memory;
283}
284
285/*---------------------------------------------------------------------------*/
286/*---------------------------------------------------------------------------*/
287
288void MeshStats::
289_dumpIncrementalConnectivityMemoryUsage()
290{
291 IVariableMng* vm = m_mesh->variableMng();
292 Real total_memory = 0.0;
293 VariableCollection used_variables = vm->usedVariables();
294 const String tag_name = "ArcaneConnectivity";
295 for (VariableCollection::Enumerator iv(used_variables); ++iv;) {
296 IVariable* v = *iv;
297 if (!v->hasTag(tag_name))
298 continue;
299 if (v->meshHandle().meshOrNull() == m_mesh) {
300 Real v_memory = v->allocatedMemory();
301 info(4) << "Allocated Memory n=" << v->name() << " v=" << v_memory;
302 total_memory += v_memory;
303 }
304 }
305 info() << "Total memory for incremental connectivities mem=" << total_memory;
306}
307
308/*---------------------------------------------------------------------------*/
309/*---------------------------------------------------------------------------*/
310
311void MeshStats::
312_printInfo(const String& name, Int64 nb_local,
313 Int64 nb_local_min, Integer min_rank,
314 Int64 nb_local_max, Integer max_rank,
315 Int64 nb_global, Integer nb_rank)
316{
317 if (nb_global == 0 && nb_local == 0)
318 return;
319
320 Int64 average = nb_global;
321 if (nb_rank != 0)
322 average /= nb_rank;
323 Real bal1 = (Real)(nb_local_max - average);
324 if (average != 0)
325 bal1 = bal1 / (Real)average;
326 Int64 bal = static_cast<Int64>(bal1 * 1000);
327 info() << Trace::Width(18) << name
328 << Trace::Width(10) << nb_local
329 << Trace::Width(10) << nb_local_min
330 << Trace::Width(8) << min_rank
331 << Trace::Width(10) << nb_local_max
332 << Trace::Width(8) << max_rank
333 << Trace::Width(10) << average
334 << Trace::Width(10) << bal
335 << Trace::Width(12) << nb_global;
336}
337
338/*---------------------------------------------------------------------------*/
339/*---------------------------------------------------------------------------*/
340
341void MeshStats::
342_computeElementsOnGroup(Int64ArrayView nb_type, Int64ArrayView nb_kind,
343 ItemGroup group, Integer istat)
344{
345 Int32 ik = static_cast<Int32>(group.itemKind());
346 ENUMERATE_ITEM (i, group) {
347 Item item = *i;
348 Int16 type = item.type();
349 if (istat == 0 || (istat == 1 && item.isOwn()) || (istat == 2 && !item.isOwn())) {
350 ++nb_kind[ik];
351 ++nb_type[type];
352 }
353 }
354}
355
356/*---------------------------------------------------------------------------*/
357/*---------------------------------------------------------------------------*/
358
359void MeshStats::
360_computeNeighboorsComm()
361{
362 Integer nb_proc = m_parallel_mng->commSize();
363 Int64UniqueArray vol_comm_out(nb_proc);
364 StringBuilder out = "";
365 vol_comm_out.fill(0);
366
367 ENUMERATE_ITEM (i, m_mesh->allCells()) {
368 Item item = *i;
369 if (item.isOwn())
370 continue;
371 vol_comm_out[item.owner()]++;
372 }
373
374 for (Integer i = 0; i < nb_proc; ++i) {
375 out += " ";
376 out += vol_comm_out[i];
377 }
378 pinfo() << "Comm Proc " << m_parallel_mng->commRank() << " : " << out;
379}
380
381/*---------------------------------------------------------------------------*/
382/*---------------------------------------------------------------------------*/
383
384void MeshStats::
385_dumpCommunicatingRanks()
386{
387 // Displays statistics on the number of subdomains we communicate with.
388 // We take neighbors from the cell list.
389 IItemFamily* cell_family = m_mesh->cellFamily();
390 IVariableSynchronizer* sync_info = cell_family->allItemsSynchronizer();
391 Int64 nb_comm_local = sync_info->communicatingRanks().size();
392 Int32 nb_comm_min_rank = 0;
393 Int32 nb_comm_max_rank = 0;
394 Int64 nb_comm_max = 0;
395 Int64 nb_comm_min = 0;
396 Int64 nb_comm_sum = 0;
397 IParallelMng* pm = m_parallel_mng;
398 pm->computeMinMaxSum(nb_comm_local, nb_comm_min, nb_comm_max, nb_comm_sum,
399 nb_comm_min_rank, nb_comm_max_rank);
400 Int64 average = nb_comm_sum / pm->commSize();
401 info() << String::format("CommunicatingSubDomains: local={0}, min={1}, max={2}"
402 " average={3} min_rank={4} max_rank={5}",
403 nb_comm_local, nb_comm_min, nb_comm_max, average,
404 nb_comm_min_rank, nb_comm_max_rank);
405}
406
407/*---------------------------------------------------------------------------*/
408/*---------------------------------------------------------------------------*/
409
410} // namespace Arcane
411
412/*---------------------------------------------------------------------------*/
413/*---------------------------------------------------------------------------*/
Declarations of Arcane's general types.
Types and macros for iterating over mesh entities.
#define ENUMERATE_ITEM(name, group)
Generic enumerator for a node group.
Modifiable view of an array of type T.
constexpr ArrayView< T > subView(Integer abegin, Integer asize) noexcept
Sub-view starting from element abegin and containing asize elements.
constexpr ConstArrayView< T > subConstView(Integer abegin, Integer asize) const noexcept
Sub-view (constant) starting from element abegin and containing asize elements.
virtual String name() const =0
Mesh name.
virtual FaceGroup allFaces()=0
Group of all faces.
virtual NodeGroup allNodes()=0
Group of all nodes.
virtual CellGroup allCells()=0
Group of all cells.
virtual EdgeGroup allEdges()=0
Group of all edges.
Interface of a class providing mesh information.
Definition IMeshStats.h:31
Interface of the parallelism manager for a subdomain.
Mesh entity group.
Definition ItemGroup.h:51
Display informations abour a mesh.
Definition MeshStats.h:45
void dumpStats() override
Prints mesh information.
Definition MeshStats.cc:83
void dumpGraphStats() override
Prints mesh graph information.
Definition MeshStats.cc:93
Reference to an instance.
TraceMessage pinfo() const
Flow for a parallel information message.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
-- 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
ConstArrayView< Int64 > Int64ConstArrayView
C equivalent of a 1D array of 64-bit integers.
Definition UtilsTypes.h:474
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
Definition UtilsTypes.h:335
eItemKind
Mesh entity type.
std::int16_t Int16
Signed integer type of 16 bits.
const char * itemKindName(eItemKind kind)
Entity kind name.
double Real
Type representing a real number.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
std::int32_t Int32
Signed integer type of 32 bits.