Arcane  4.2.1.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
MeshUtils.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/* MeshUtils.cc (C) 2000-2026 */
9/* */
10/* Fonctions diverses sur les éléments du maillage. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/CheckedConvert.h"
15#include "arcane/utils/List.h"
16#include "arcane/utils/ScopedPtr.h"
17#include "arcane/utils/OStringStream.h"
18#include "arcane/utils/StringBuilder.h"
19#include "arcane/utils/ITraceMng.h"
20#include "arcane/utils/JSONWriter.h"
21#include "arcane/utils/IHashAlgorithm.h"
22
24#include "arcane/core/IVariableMng.h"
25#include "arcane/core/VariableTypes.h"
26#include "arcane/core/ISubDomain.h"
27#include "arcane/core/StdNum.h"
28#include "arcane/core/MeshVariableInfo.h"
29#include "arcane/core/Variable.h"
30#include "arcane/core/IMesh.h"
31#include "arcane/core/IMeshSubMeshTransition.h"
33#include "arcane/core/ItemGroup.h"
34#include "arcane/core/Item.h"
35#include "arcane/core/ItemCompare.h"
36#include "arcane/core/ItemPrinter.h"
38#include "arcane/core/XmlNode.h"
39#include "arcane/core/XmlNodeList.h"
40#include "arcane/core/IParallelMng.h"
41#include "arcane/core/IIOMng.h"
42#include "arcane/core/IXmlDocumentHolder.h"
43#include "arcane/core/IItemFamily.h"
44#include "arcane/core/VariableCollection.h"
45#include "arcane/core/ITiedInterface.h"
46#include "arcane/core/SharedVariable.h"
47#include "arcane/core/MeshVisitor.h"
48#include "arcane/core/IMeshUtilities.h"
49#include "arcane/core/IVariableSynchronizer.h"
50#include "arcane/core/UnstructuredMeshConnectivity.h"
51#include "arcane/core/datatype/DataAllocationInfo.h"
52
54
55#include <algorithm>
56#include <map>
57
58/*---------------------------------------------------------------------------*/
59/*---------------------------------------------------------------------------*/
60
61namespace Arcane
62{
63using impl::ItemBase;
64
65/*---------------------------------------------------------------------------*/
66/*---------------------------------------------------------------------------*/
67
68// #define ARCANE_DEBUG_MESH
69
70/*---------------------------------------------------------------------------*/
71/*---------------------------------------------------------------------------*/
72
73template <class ValueType> inline void
74_writeValue(ITraceMng* trace, const String& name, ValueType v)
75{
76 Integer wl = CheckedConvert::toInteger(65 - name.length());
77 trace->pinfo() << name << Trace::Width(wl) << v;
78}
79
80template <> inline void
81_writeValue(ITraceMng* trace, const String& name, Real3 v)
82{
83 Integer wl = CheckedConvert::toInteger(63 - name.length());
84 trace->pinfo() << name << ".x" << Trace::Width(wl) << v.x;
85 trace->pinfo() << name << ".y" << Trace::Width(wl) << v.y;
86 trace->pinfo() << name << ".z" << Trace::Width(wl) << v.z;
87}
88
89template <> inline void
90_writeValue(ITraceMng* trace, const String& name, Real3x3 v)
91{
92 Integer wl = CheckedConvert::toInteger(62 - name.length());
93 trace->pinfo() << name << ".xx" << Trace::Width(wl) << v.x.x;
94 trace->pinfo() << name << ".xy" << Trace::Width(wl) << v.x.y;
95 trace->pinfo() << name << ".xz" << Trace::Width(wl) << v.x.z;
96
97 trace->pinfo() << name << ".yx" << Trace::Width(wl) << v.y.x;
98 trace->pinfo() << name << ".yy" << Trace::Width(wl) << v.y.y;
99 trace->pinfo() << name << ".yz" << Trace::Width(wl) << v.y.z;
100
101 trace->pinfo() << name << ".zx" << Trace::Width(wl) << v.z.x;
102 trace->pinfo() << name << ".zy" << Trace::Width(wl) << v.z.y;
103 trace->pinfo() << name << ".zz" << Trace::Width(wl) << v.z.z;
104}
105
106template <class ItemType, class ValueType> inline void
107_writeInfo(ISubDomain* mng, const VariableCollection& variables, const ItemType& item)
108{
109 typedef typename MeshVariableInfoT<ItemType, ValueType, 0>::PrivateType VariableScalarTrueType;
110 typedef typename MeshVariableInfoT<ItemType, ValueType, 1>::PrivateType VariableArrayTrueType;
111
112 ITraceMng* trace = mng->traceMng();
114
115 for (VariableCollection::Enumerator i(variables); ++i;) {
116 IVariable* vp = *i;
117 // Pour l'instant, n'affiche pas les variables partielles
118 if (vp->isPartial())
119 continue;
120 // Vérifie qu'il s'agit bien d'une variable du maillage et du bon genre
121 ItemGroup group = vp->itemGroup();
122 if (group.itemKind() != item_kind)
123 continue;
124
125 const String& name = vp->name();
126 auto* v = dynamic_cast<VariableScalarTrueType*>(vp);
127 if (v) {
128 ConstArrayView<ValueType> values = v->valueView();
129 if (values.size() < item.localId()) {
130 trace->error() << "Dimensions invalides pour la variable '" << name << "' "
131 << "(taille=" << values.size() << " index=" << item.localId();
132 continue;
133 }
134 _writeValue(trace, name, values[item.localId()]);
135 }
136
137 auto* v2 = dynamic_cast<VariableArrayTrueType*>(vp);
138 if (v2) {
139 Array2View<ValueType> values = v2->valueView();
140 Integer lid = item.localId();
141 if (values.dim1Size() < lid) {
142 trace->error() << "Dimensions invalides pour la variable '" << name << "' "
143 << "(taille=" << values.dim1Size() << " index=" << lid;
144 continue;
145 }
146 Integer n = values[lid].size();
147 for (Integer z = 0; z < n; ++z) {
148 _writeValue(trace, name + "[" + z + "]", values[lid][z]);
149 }
150 }
151 }
152}
153
154/*---------------------------------------------------------------------------*/
155/*---------------------------------------------------------------------------*/
156
157void MeshUtils::
158writeMeshItemInfo(ISubDomain* sd, Cell cell, bool depend_info)
159{
160 ITraceMng* trace = sd->traceMng();
161 Integer sid = sd->subDomainId();
162 StringBuilder buf("Info-");
163 buf += sid;
164 Trace::Setter mci(trace, buf.toString());
165
166 VariableCollection variables(sd->variableMng()->usedVariables());
167
168 Integer nb_node = cell.nbNode();
169 Integer nb_edge = cell.nbEdge();
170 Integer nb_face = cell.nbFace();
171
172 trace->pinfo() << "** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- **";
173 trace->pinfo() << "** -- Affichage des informations pour la maille " << cell.uniqueId();
174 trace->pinfo() << "** -- Structure:";
175 trace->pinfo() << "id unique: " << Trace::Width(5) << cell.uniqueId();
176 trace->pinfo() << "id local: " << Trace::Width(5) << cell.localId();
177 trace->pinfo() << "propriétaire: " << Trace::Width(5) << cell.owner();
178 trace->pinfo() << "type: " << Trace::Width(5) << cell.typeInfo()->typeName();
179
180 trace->pinfo() << "nombre de nœuds: " << Trace::Width(5) << nb_node;
181 for (Integer i = 0; i < nb_node; ++i)
182 trace->pinfo() << "id unique du nœud " << Trace::Width(2)
183 << i << " : " << Trace::Width(5) << cell.node(i).uniqueId();
185 trace->pinfo() << "nombre d'arêtes: " << Trace::Width(5) << nb_edge;
186 for (Integer i = 0; i < nb_edge; ++i)
187 trace->pinfo() << "id unique de l'arête " << Trace::Width(2)
188 << i << " : " << Trace::Width(5) << cell.edge(i).uniqueId();
189
190 trace->pinfo() << "nombre de faces: " << Trace::Width(5) << nb_face;
191 for (Integer i = 0; i < nb_face; ++i)
192 trace->pinfo() << "id local de la face " << Trace::Width(2)
193 << i << " : " << Trace::Width(5) << cell.face(i).localId();
194
195 trace->pinfo() << "** -- Variables:";
196 _writeInfo<Cell, Real>(sd, variables, cell);
197 _writeInfo<Cell, Real2>(sd, variables, cell);
198 _writeInfo<Cell, Real3>(sd, variables, cell);
199 _writeInfo<Cell, Real2x2>(sd, variables, cell);
200 _writeInfo<Cell, Real3x3>(sd, variables, cell);
201 _writeInfo<Cell, Int32>(sd, variables, cell);
202 _writeInfo<Cell, Int64>(sd, variables, cell);
203
204 trace->pinfo() << "** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- **";
205
206 if (depend_info) {
207 for (Integer i = 0; i < nb_node; ++i)
208 writeMeshItemInfo(sd, cell.node(i), false);
209 for (Integer i = 0; i < nb_edge; ++i)
210 writeMeshItemInfo(sd, cell.edge(i), false);
211 for (Integer i = 0; i < nb_face; ++i)
212 writeMeshItemInfo(sd, cell.face(i), false);
213 }
214}
215
216/*---------------------------------------------------------------------------*/
217/*---------------------------------------------------------------------------*/
219void MeshUtils::
220writeMeshItemInfo(ISubDomain* sd, Node node, bool depend_info)
221{
222 ITraceMng* trace = sd->traceMng();
223 Integer sid = sd->subDomainId();
224 StringBuilder buf("Info-");
225 buf += sid;
226 Trace::Setter mci(trace, buf.toString());
227
228 VariableCollection variables(sd->variableMng()->usedVariables());
230 Integer nb_cell = node.nbCell();
231 Integer nb_edge = node.nbEdge();
232 Integer nb_face = node.nbFace();
234 trace->pinfo() << "** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- **";
235 trace->pinfo() << "** -- Affichage des informations pour le nœud " << node.uniqueId();
236 trace->pinfo() << "** -- Structure:";
237 trace->pinfo() << "id unique: " << Trace::Width(5) << node.uniqueId();
238 trace->pinfo() << "id local: " << Trace::Width(5) << node.localId();
239 trace->pinfo() << "propriétaire: " << Trace::Width(5) << node.owner();
240
241 trace->pinfo() << "nombre de mailles: " << Trace::Width(5) << nb_cell;
242 for (Integer i = 0; i < nb_cell; ++i)
243 trace->pinfo() << "id unique de la maille " << Trace::Width(2)
244 << i << " : " << Trace::Width(5) << node.cell(i).uniqueId();
245
246 trace->pinfo() << "nombre de faces: " << Trace::Width(5) << nb_face;
247 for (Integer i = 0; i < nb_face; ++i)
248 trace->pinfo() << "id local de la face " << Trace::Width(2)
249 << i << " : " << Trace::Width(5) << node.face(i).localId();
250
251 trace->pinfo() << "** -- Variables:";
252 _writeInfo<Node, Real>(sd, variables, node);
253 _writeInfo<Node, Real2>(sd, variables, node);
254 _writeInfo<Node, Real3>(sd, variables, node);
255 _writeInfo<Node, Real2x2>(sd, variables, node);
256 _writeInfo<Node, Real3x3>(sd, variables, node);
257 _writeInfo<Node, Int32>(sd, variables, node);
258 _writeInfo<Node, Int64>(sd, variables, node);
259
260 if (depend_info) {
261 for (Integer i = 0; i < nb_cell; ++i)
262 writeMeshItemInfo(sd, node.cell(i), false);
263 for (Integer i = 0; i < nb_edge; ++i)
264 writeMeshItemInfo(sd, node.edge(i), false);
265 for (Integer i = 0; i < nb_face; ++i)
266 writeMeshItemInfo(sd, node.face(i), false);
267 }
268}
269
270/*---------------------------------------------------------------------------*/
271/*---------------------------------------------------------------------------*/
272
273void MeshUtils::
274writeMeshItemInfo(ISubDomain* sd, Edge edge, bool depend_info)
275{
276 ITraceMng* trace = sd->traceMng();
277 Integer sid = sd->subDomainId();
278 StringBuilder buf("Info-");
279 buf += sid;
280 Trace::Setter mci(trace, buf.toString());
281
282 VariableCollection variables(sd->variableMng()->usedVariables());
283
284 Integer nb_cell = edge.nbCell();
285 Integer nb_face = edge.nbFace();
286 Integer nb_node = edge.nbNode();
287
288 trace->pinfo() << "** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- **";
289 trace->pinfo() << "** -- Affichage des informations pour l'arête " << edge.localId() << " (localid)";
290 trace->pinfo() << "** -- Structure:";
291 trace->pinfo() << "id unique: " << Trace::Width(5) << "None";
292 trace->pinfo() << "id local: " << Trace::Width(5) << edge.localId();
293 trace->pinfo() << "propriétaire: " << Trace::Width(5) << edge.owner();
294
295 trace->pinfo() << "nombre de nœuds: " << Trace::Width(5) << nb_node;
296 for (Integer i = 0; i < nb_node; ++i)
297 trace->pinfo() << "id unique du nœud " << Trace::Width(2)
298 << i << " : " << Trace::Width(5) << edge.node(i).uniqueId();
299
300 trace->pinfo() << "nombre de mailles: " << Trace::Width(5) << nb_cell;
301 for (Integer i = 0; i < nb_cell; ++i)
302 trace->pinfo() << "id unique de la maille " << Trace::Width(2)
303 << i << " : " << Trace::Width(5) << edge.cell(i).uniqueId();
304
305 trace->pinfo() << "** -- Variables:";
306 _writeInfo<Edge, Real>(sd, variables, edge);
307 _writeInfo<Edge, Real2>(sd, variables, edge);
308 _writeInfo<Edge, Real3>(sd, variables, edge);
309 _writeInfo<Edge, Real2x2>(sd, variables, edge);
310 _writeInfo<Edge, Real3x3>(sd, variables, edge);
311 _writeInfo<Edge, Int32>(sd, variables, edge);
312 _writeInfo<Edge, Int64>(sd, variables, edge);
313
314 if (depend_info) {
315 for (Integer i = 0; i < nb_node; ++i)
316 writeMeshItemInfo(sd, edge.node(i), false);
317 for (Integer i = 0; i < nb_face; ++i)
318 writeMeshItemInfo(sd, edge.face(i), false);
319 for (Integer i = 0; i < nb_cell; ++i)
320 writeMeshItemInfo(sd, edge.cell(i), false);
321 }
322}
323
324/*---------------------------------------------------------------------------*/
325/*---------------------------------------------------------------------------*/
326
327void MeshUtils::
328writeMeshItemInfo(ISubDomain* sd, Face face, bool depend_info)
329{
330 ITraceMng* trace = sd->traceMng();
331 Integer sid = sd->subDomainId();
332 StringBuilder buf("Info-");
333 buf += sid;
334 Trace::Setter mci(trace, buf.toString());
335
336 VariableCollection variables(sd->variableMng()->usedVariables());
337
338 Integer nb_cell = face.nbCell();
339 Integer nb_edge = face.nbEdge();
340 Integer nb_node = face.nbNode();
341
342 trace->pinfo() << "** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- ** -- **";
343 trace->pinfo() << "** -- Affichage des informations pour la face " << face.localId() << " (localid)";
344 trace->pinfo() << "** -- Structure:";
345 trace->pinfo() << "id unique: " << Trace::Width(5) << "None";
346 trace->pinfo() << "id local: " << Trace::Width(5) << face.localId();
347 trace->pinfo() << "propriétaire: " << Trace::Width(5) << face.owner();
348
349 trace->pinfo() << "nombre de nœuds: " << Trace::Width(5) << nb_node;
350 for (Integer i = 0; i < nb_node; ++i)
351 trace->pinfo() << "id unique du nœud " << Trace::Width(2)
352 << i << " : " << Trace::Width(5) << face.node(i).uniqueId();
353
354 trace->pinfo() << "nombre de mailles: " << Trace::Width(5) << nb_cell;
355 for (Integer i = 0; i < nb_cell; ++i)
356 trace->pinfo() << "id unique de la maille " << Trace::Width(2)
357 << i << " : " << Trace::Width(5) << face.cell(i).uniqueId();
358
359 trace->pinfo() << "** -- Variables:";
360 _writeInfo<Face, Real>(sd, variables, face);
361 _writeInfo<Face, Real2>(sd, variables, face);
362 _writeInfo<Face, Real3>(sd, variables, face);
363 _writeInfo<Face, Real2x2>(sd, variables, face);
364 _writeInfo<Face, Real3x3>(sd, variables, face);
365 _writeInfo<Face, Int32>(sd, variables, face);
366 _writeInfo<Face, Int64>(sd, variables, face);
367
368 if (depend_info) {
369 for (Integer i = 0; i < nb_node; ++i)
370 writeMeshItemInfo(sd, face.node(i), false);
371 for (Integer i = 0; i < nb_edge; ++i)
372 writeMeshItemInfo(sd, face.edge(i), false);
373 for (Integer i = 0; i < nb_cell; ++i)
374 writeMeshItemInfo(sd, face.cell(i), false);
375 }
376}
377
378/*---------------------------------------------------------------------------*/
379/*---------------------------------------------------------------------------*/
380
381class _CompareNodes
382{
383 public:
384
385 bool operator()(const Node& node1, const Node& node2)
386 {
387 const Real3& r1 = m_coords[node1];
388 const Real3& r2 = m_coords[node2];
389 return r1 < r2;
390 }
391
392 public:
393
394 _CompareNodes(IMesh* mesh, const SharedVariableNodeReal3& coords)
395 : m_items(mesh->itemsInternal(IK_Node))
396 , m_coords(coords)
397 {
398 }
399 ItemInternalList m_items;
400 const SharedVariableNodeReal3& m_coords;
401};
402
403class _CompareItemWithNodes
404{
405 public:
406
407 bool operator()(const ItemWithNodes& cell1, const ItemWithNodes& cell2)
408 {
409 Integer nb1 = cell1.nbNode();
410 Integer nb2 = cell2.nbNode();
411 if (nb1 < nb2)
412 return true;
413 if (nb2 < nb1)
414 return false;
415 Integer n = nb1;
416 for (Integer i = 0; i < n; ++i) {
417 Integer n1 = m_nodes_sorted_id[cell1.node(i).localId()];
418 Integer n2 = m_nodes_sorted_id[cell2.node(i).localId()];
419 if (n1 != n2)
420 return n1 < n2;
421 }
422 return false;
423 //return n1<n2;
424 }
425
426 public:
427
428 _CompareItemWithNodes(IMesh* mesh, eItemKind ik, Int32ConstArrayView nodes_sorted_id)
429 : m_items(mesh->itemsInternal(ik))
430 , m_nodes_sorted_id(nodes_sorted_id)
431 {
432 }
433 ItemInternalList m_items;
434 Int32ConstArrayView m_nodes_sorted_id;
435};
436
437/*---------------------------------------------------------------------------*/
438/*---------------------------------------------------------------------------*/
439
440void _writeItems(std::ostream& ofile, const String& name, Int32ConstArrayView ids)
441{
442 Integer nb_sub_item = ids.size();
443 ofile << " " << name << " " << nb_sub_item << " (";
444 for (Integer i = 0; i < nb_sub_item; ++i)
445 ofile << ' ' << ids[i];
446 ofile << " )";
447}
448
450{
451 public:
452
453 virtual ~IItemFiller() {}
454
455 public:
456
457 virtual Integer nbItem(ItemBase item) const = 0;
458 virtual void fillLocalIds(ItemBase item, Int32ArrayView ids) const = 0;
459};
460
462: public IItemFiller
463{
464 Integer nbItem(ItemBase item) const override { return item.nbEdge(); }
465 void fillLocalIds(ItemBase item, Int32ArrayView ids) const override
466 {
467 Integer nb_edge = ids.size();
468 for (Integer i = 0; i < nb_edge; ++i)
469 ids[i] = item.edgeId(i);
470 }
471};
472
474: public IItemFiller
475{
476 Int32 nbItem(ItemBase item) const override { return item.nbCell(); }
477 void fillLocalIds(ItemBase item, Int32ArrayView ids) const override
478 {
479 Integer nb_cell = ids.size();
480 for (Integer i = 0; i < nb_cell; ++i)
481 ids[i] = item.cellId(i);
482 }
483};
484
486: public IItemFiller
487{
488 Int32 nbItem(ItemBase item) const override { return item.nbFace(); }
489 void fillLocalIds(ItemBase item, Int32ArrayView ids) const override
490 {
491 Integer nb_face = ids.size();
492 for (Integer i = 0; i < nb_face; ++i)
493 ids[i] = item.faceId(i);
494 }
495};
496
498: public IItemFiller
499{
500 virtual Int32 nbItem(ItemBase item) const { return item.nbNode(); }
501 virtual void fillLocalIds(ItemBase item, Int32ArrayView ids) const
502 {
503 Integer nb_node = ids.size();
504 for (Integer i = 0; i < nb_node; ++i)
505 ids[i] = item.nodeId(i);
506 }
507};
508
509void _fillSorted(Item titem, Int32Array& local_ids, Int32ConstArrayView sorted_ids, const IItemFiller& filler)
510{
511 ItemBase item = titem.itemBase();
512 Integer n = filler.nbItem(item);
513 local_ids.resize(n);
514 filler.fillLocalIds(item, local_ids);
515 for (Integer i = 0; i < n; ++i)
516 local_ids[i] = sorted_ids[local_ids[i]];
517}
518
519/*---------------------------------------------------------------------------*/
520/*---------------------------------------------------------------------------*/
521
522void MeshUtils::
523writeMeshInfosSorted(IMesh* mesh, const String& file_name)
524{
525 if (!mesh)
526 return;
527 std::ofstream ofile(file_name.localstr());
528 ofile.precision(FloatInfo<Real>::maxDigit() + 1);
529 Integer nb_node = mesh->nbNode();
530 Integer nb_edge = mesh->nbEdge();
531 Integer nb_face = mesh->nbFace();
532 Integer nb_cell = mesh->nbCell();
533 ofile << "** Maillage Trié --> "
534 << " Nœuds " << nb_node
535 << " Arêtes " << nb_edge
536 << " Faces " << nb_face
537 << " Mailles " << nb_cell
538 << "\n";
539 UniqueArray<Node> sorted_nodes(nb_node);
540 UniqueArray<Edge> sorted_edges(nb_edge);
541 UniqueArray<Face> sorted_faces(nb_face);
542 UniqueArray<Cell> sorted_cells(nb_cell);
543
544 Int32UniqueArray nodes_sorted_id(nb_node);
545 Int32UniqueArray edges_sorted_id(nb_edge);
546 Int32UniqueArray faces_sorted_id(nb_face);
547 Int32UniqueArray cells_sorted_id(nb_cell);
548 {
549 // Trie les noeuds par ordre croissant de leur coordonnées
550 NodeInfoListView nodes(mesh->nodeFamily());
551 for (Integer i = 0; i < nb_node; ++i)
552 sorted_nodes[i] = nodes[i];
553 {
554 SharedVariableNodeReal3 shared_coords(mesh->sharedNodesCoordinates());
555 _CompareNodes compare_nodes(mesh, shared_coords);
556 std::sort(std::begin(sorted_nodes), std::end(sorted_nodes), compare_nodes);
557 }
558 for (Integer i = 0; i < nb_node; ++i)
559 nodes_sorted_id[sorted_nodes[i].localId()] = i;
560
561 // Trie les arêtes
562 EdgeInfoListView edges(mesh->edgeFamily());
563 for (Integer i = 0; i < nb_edge; ++i)
564 sorted_edges[i] = edges[i];
565 {
566 _CompareItemWithNodes compare_edges(mesh, IK_Edge, nodes_sorted_id);
567 std::sort(std::begin(sorted_edges), std::end(sorted_edges), compare_edges);
568 }
569 for (Integer i = 0; i < nb_edge; ++i)
570 edges_sorted_id[sorted_edges[i].localId()] = i;
571
572 // Trie les faces
573 FaceInfoListView faces(mesh->faceFamily());
574 for (Integer i = 0; i < nb_face; ++i)
575 sorted_faces[i] = faces[i];
576 {
577 _CompareItemWithNodes compare_faces(mesh, IK_Face, nodes_sorted_id);
578 std::sort(std::begin(sorted_faces), std::end(sorted_faces), compare_faces);
579 }
580 for (Integer i = 0; i < nb_face; ++i)
581 faces_sorted_id[sorted_faces[i].localId()] = i;
582
583 // Trie les mailles
584 CellInfoListView cells(mesh->cellFamily());
585 for (Integer i = 0; i < nb_cell; ++i)
586 sorted_cells[i] = cells[i];
587 {
588 _CompareItemWithNodes compare_cells(mesh, IK_Cell, nodes_sorted_id);
589 std::sort(std::begin(sorted_cells), std::end(sorted_cells), compare_cells);
590 }
591 for (Integer i = 0; i < nb_cell; ++i)
592 cells_sorted_id[sorted_cells[i].localId()] = i;
593
594 SharedVariableNodeReal3 coords(mesh->sharedNodesCoordinates());
595
596 ofile << "** Nœuds\n";
597 Int32UniqueArray lids;
598 for (Integer i = 0; i < nb_node; ++i) {
599 const Node& node = sorted_nodes[i];
600 ofile << "Nœud: " << i << " Coordonnée: " << coords[node];
601
602 _fillSorted(node, lids, edges_sorted_id, EdgeFiller());
603 std::sort(std::begin(lids), std::end(lids));
604 _writeItems(ofile, "Arêtes", lids);
605
606 _fillSorted(node, lids, faces_sorted_id, FaceFiller());
607 std::sort(std::begin(lids), std::end(lids));
608 _writeItems(ofile, "Faces", lids);
609
610 _fillSorted(node, lids, cells_sorted_id, CellFiller());
611 std::sort(std::begin(lids), std::end(lids));
612 _writeItems(ofile, "Mailles", lids);
613
614 ofile << '\n';
615 }
616
617 ofile << "** Arêtes\n";
618 for (Integer i = 0; i < nb_edge; ++i) {
619 Edge edge = sorted_edges[i];
620 Integer edge_nb_node = edge.nbNode();
621 Integer edge_nb_face = edge.nbFace();
622 Integer edge_nb_cell = edge.nbCell();
623 ofile << "Arête: " << i
624 << " Nœuds " << edge_nb_node << " (";
625 for (Integer i_node = 0; i_node < edge_nb_node; ++i_node)
626 ofile << ' ' << nodes_sorted_id[edge.node(i_node).localId()];
627 ofile << " )";
628 ofile << " Faces " << edge_nb_face << " (";
629 for (Integer i_face = 0; i_face < edge_nb_face; ++i_face)
630 ofile << ' ' << faces_sorted_id[edge.face(i_face).localId()];
631 ofile << " )";
632 ofile << " Mailles " << edge_nb_cell << " (";
633 for (Integer i_cell = 0; i_cell < edge_nb_cell; ++i_cell)
634 ofile << ' ' << cells_sorted_id[edge.cell(i_cell).localId()];
635 ofile << " )";
636 ofile << '\n';
637 }
638
639 ofile << "** Faces\n";
640 for (Integer i = 0; i < nb_face; ++i) {
641 Face face = sorted_faces[i];
642 Integer face_nb_node = face.nbNode();
643 Integer face_nb_edge = face.nbEdge();
644 Integer face_nb_cell = face.nbCell();
645 ofile << "Face: " << i;
646 ofile << " Nœuds " << face.nbNode() << " (";
647 for (Integer i_node = 0; i_node < face_nb_node; ++i_node)
648 ofile << ' ' << nodes_sorted_id[face.node(i_node).localId()];
649 ofile << " )";
650
651 ofile << " Arêtes " << face_nb_edge << " (";
652 for (Integer i_edge = 0; i_edge < face_nb_edge; ++i_edge)
653 ofile << ' ' << edges_sorted_id[face.edge(i_edge).localId()];
654 ofile << " )";
655
656 ofile << " Mailles " << face_nb_cell << " (";
657 for (Integer i_cell = 0; i_cell < face_nb_cell; ++i_cell)
658 ofile << ' ' << cells_sorted_id[face.cell(i_cell).localId()];
659
660 const Cell& back_cell = face.backCell();
661 if (!back_cell.null())
662 ofile << " Arrière " << cells_sorted_id[back_cell.localId()];
663
664 const Cell& front_cell = face.frontCell();
665 if (!front_cell.null())
666 ofile << " Avant " << cells_sorted_id[front_cell.localId()];
667
668 ofile << " )";
669 ofile << '\n';
670 }
671
672 ofile << "** Mailles\n";
673 for (Integer i = 0; i < nb_cell; ++i) {
674 Cell cell = sorted_cells[i];
675 //Integer cell_nb_node = cell.nbNode();
676 ofile << "Maille: " << i;
677
678 _fillSorted(cell, lids, nodes_sorted_id, NodeFiller());
679 _writeItems(ofile, "Nodes", lids);
680 _fillSorted(cell, lids, edges_sorted_id, EdgeFiller());
681 _writeItems(ofile, "Edges", lids);
682 _fillSorted(cell, lids, faces_sorted_id, FaceFiller());
683 _writeItems(ofile, "Faces", lids);
684 ofile << '\n';
685 }
686 }
687}
688
689/*---------------------------------------------------------------------------*/
690/*---------------------------------------------------------------------------*/
691
692void MeshUtils::
693writeMeshInfos(IMesh* mesh, const String& file_name)
694{
695 if (!mesh)
696 return;
697 std::ofstream ofile(file_name.localstr());
698 ofile.precision(FloatInfo<Real>::maxDigit() + 1);
699 Integer nb_node = mesh->nbNode();
700 Integer nb_edge = mesh->nbEdge();
701 Integer nb_face = mesh->nbFace();
702 Integer nb_cell = mesh->nbCell();
703 ofile << "** Maillage --> "
704 << " Nœuds " << nb_node
705 << " Arêtes " << nb_edge
706 << " Faces " << nb_face
707 << " Mailles " << nb_cell
708 << "\n";
709
710 NodeInfoListView nodes(mesh->nodeFamily());
711 FaceInfoListView faces(mesh->faceFamily());
712 CellInfoListView cells(mesh->cellFamily());
713 //TODO pouvoir afficher les infos même si on n'est pas un maillage primaire
714 VariableNodeReal3& coords(mesh->toPrimaryMesh()->nodesCoordinates());
715
716 ofile << "** Nœuds\n";
717 for (Integer i = 0; i < nb_node; ++i) {
718 Node node = nodes[i];
719 Integer node_nb_face = node.nbFace();
720 Integer node_nb_cell = node.nbCell();
721 ofile << "Nœud: " << i << " Coordonnée: " << coords[node];
722 ofile << " Faces " << node_nb_face << " (";
723 for (Integer i_face = 0; i_face < node_nb_face; ++i_face)
724 ofile << ' ' << node.face(i_face).localId();
725 ofile << " )";
726 ofile << " Mailles " << node_nb_cell << " (";
727 for (Integer i_cell = 0; i_cell < node_nb_cell; ++i_cell)
728 ofile << ' ' << node.cell(i_cell).localId();
729 ofile << " )";
730 ofile << '\n';
731 }
732
733 ofile << "** Faces\n";
734 for (Integer i = 0; i < nb_face; ++i) {
735 Face face = faces[i];
736 Integer face_nb_node = face.nbNode();
737 Integer face_nb_cell = face.nbCell();
738 ofile << "Face: " << i
739 << " Nœuds " << face_nb_node << " (";
740 for (Integer i_node = 0; i_node < face_nb_node; ++i_node)
741 ofile << ' ' << face.node(i_node).localId();
742 ofile << " )";
743 ofile << " Mailles " << face_nb_cell << " (";
744
745 for (Integer i_cell = 0; i_cell < face_nb_cell; ++i_cell)
746 ofile << ' ' << face.cell(i_cell).localId();
747
748 const Cell& back_cell = face.backCell();
749 if (!back_cell.null())
750 ofile << " Arrière " << back_cell.localId();
751
752 const Cell& front_cell = face.frontCell();
753 if (!front_cell.null())
754 ofile << " Avant " << front_cell.localId();
755
756 ofile << " )";
757 ofile << '\n';
758 }
759
760 ofile << "** Mailles\n";
761 for (Integer i = 0; i < nb_cell; ++i) {
762 Cell cell = cells[i];
763 Integer cell_nb_node = cell.nbNode();
764 Integer cell_nb_face = cell.nbFace();
765 ofile << "Maille: " << i
766 << " Nœuds " << cell_nb_node << " (";
767 for (Integer i_node = 0; i_node < cell_nb_node; ++i_node)
768 ofile << ' ' << cell.node(i_node).localId();
769 ofile << " )";
770 ofile << " Faces " << cell_nb_face << " (";
771 for (Integer i_face = 0; i_face < cell_nb_face; ++i_face)
772 ofile << ' ' << cell.face(i_face).localId();
773 ofile << " )";
774 ofile << '\n';
775 }
776}
777
778/*---------------------------------------------------------------------------*/
779/*---------------------------------------------------------------------------*/
780
781namespace
782{
783 template <typename ItemType> void
784 _sortByUniqueIds(IMesh* mesh, eItemKind ik, Array<ItemType>& items)
785 {
786 ItemGroup all_items(mesh->itemFamily(ik)->allItems());
787 items.resize(all_items.size());
788
789 Integer index = 0;
790 ENUMERATE_ (ItemType, i, all_items) {
791 ItemType item = *i;
792 items[index] = item;
793 ++index;
794 }
795 std::sort(std::begin(items), std::end(items), ItemCompare());
796 }
797
798 void
799 _stringToIds(const String& str, Int64Array& ids)
800 {
801 ids.clear();
802 std::istringstream istr(str.localstr());
803 Integer z = 0;
804 while (istr.good()) {
805 istr >> z;
806 if (!istr)
807 break;
808 ids.add(z);
809 }
810 }
811
812 template <typename SubItemType> void
813 _writeSubItems(std::ostream& ofile, const char* item_name, ItemConnectedListViewT<SubItemType> sub_list)
814 {
815 Int32 n = sub_list.size();
816 if (n == 0)
817 return;
818 ofile << "<" << item_name << " count='" << n << "'>";
819 for (SubItemType sub_item : sub_list)
820 ofile << ' ' << sub_item.uniqueId();
821 ofile << "</" << item_name << ">";
822 }
823} // namespace
824
825/*---------------------------------------------------------------------------*/
826/*---------------------------------------------------------------------------*/
827
828void MeshUtils::
829writeMeshConnectivity(IMesh* mesh, const String& file_name)
830{
831 std::ofstream ofile(file_name.localstr());
832 ofile.precision(FloatInfo<Real>::maxDigit() + 1);
833 if (!mesh)
834 return;
835
836 ITraceMng* trace = mesh->traceMng();
837
838 trace->info() << "Écriture de la connectivité du maillage dans '" << file_name << "'";
839
840 ofile << "<?xml version='1.0' ?>\n";
841 ofile << "<mesh-connectivity>\n";
842 UniqueArray<Node> nodes;
843 UniqueArray<Edge> edges;
844 UniqueArray<Face> faces;
845 UniqueArray<Cell> cells;
846
847 _sortByUniqueIds(mesh, IK_Node, nodes);
848 _sortByUniqueIds(mesh, IK_Edge, edges);
849 _sortByUniqueIds(mesh, IK_Face, faces);
850 _sortByUniqueIds(mesh, IK_Cell, cells);
851
852 // Écrit les noeuds
853 {
854 ofile << "<nodes count='" << nodes.size() << "'>\n";
855 for (Node item : nodes) {
856 ofile << " <node uid='" << item.uniqueId() << "' owner='" << item.owner() << "'>";
857 _writeSubItems(ofile, "cells", item.cells());
858 _writeSubItems(ofile, "faces", item.faces());
859 _writeSubItems(ofile, "edges", item.edges());
860 ofile << "</node>\n";
861 }
862 ofile << "</nodes>\n";
863 }
864
865 // Écrit les arêtes
866 {
867 ofile << "<edges count='" << edges.size() << "'>\n";
868 for (Edge edge : edges) {
869 ofile << " <edge uid='" << edge.uniqueId() << "' owner='" << edge.owner() << "'>";
870 _writeSubItems(ofile, "nodes", edge.nodes());
871 _writeSubItems(ofile, "cells", edge.cells());
872 _writeSubItems(ofile, "faces", edge.faces());
873 ofile << "</edge>\n";
874 }
875 ofile << "</edges>\n";
876 }
877
878 // Écrit les faces
879 {
880 ofile << "<faces count='" << faces.size() << "'>\n";
881 for (Face face : faces) {
882 // Integer item_nb_face = item.nbFace();
883 ofile << " <face uid='" << face.uniqueId()
884 << "' typeid='" << face.type()
885 << "' owner='" << face.owner() << "'>";
886 _writeSubItems(ofile, "nodes", face.nodes());
887 _writeSubItems(ofile, "edges", face.edges());
888 {
889 // Infos sur les mailles
890 ofile << "<cells";
891 Cell back_cell = face.backCell();
892 if (!back_cell.null())
893 ofile << " back='" << back_cell.uniqueId() << "'";
894 Cell front_cell = face.frontCell();
895 if (!front_cell.null())
896 ofile << " front='" << front_cell.uniqueId() << "'";
897 ofile << "/>";
898 }
899
900 // Infos sur les maitres/esclaves
901 if (face.isSlaveFace())
902 _writeSubItems(ofile, "slave-faces", face.slaveFaces());
903 if (face.isMasterFace()) {
904 ofile << "<faces count='1'>";
905 ofile << ' ' << face.masterFace().uniqueId();
906 ofile << "</faces>";
907 }
908
909 ofile << "</face>\n";
910 }
911 ofile << "</faces>\n";
912 }
913
914 // Écrit les mailles
915 {
916 ofile << "<cells count='" << cells.size() << "'>\n";
917 // Pour les mailles autour d'une maille.
918 // Une maille est autour d'une autre si elle est connectée par
919 // au moins un nœud
920 Int64UniqueArray ghost_cells_layer1;
921 ghost_cells_layer1.reserve(100);
922 for (Cell cell : cells) {
923 ofile << " <cell uid='" << cell.uniqueId()
924 << "' typeid='" << cell.type()
925 << "' owner='" << cell.owner() << "'>";
926 _writeSubItems(ofile, "nodes", cell.nodes());
927 _writeSubItems(ofile, "edges", cell.edges());
928 _writeSubItems(ofile, "faces", cell.faces());
929 if (mesh->isAmrActivated()) {
930 ofile << "<amr level='" << cell.level() << "'>";
931 // {
932 // ofile << "<parent count='" << item.nbHParent() << "'>";
933 // trace->info() << "Truc : " << item.nbHParent();
934 // for (Integer j = 0; j < item.nbHParent(); ++j) {
935 // ofile << ' ' << item.parent(j).uniqueId();
936 // }
937 // ofile << "</parent>";
938 // }
939 {
940 ofile << "<child count='" << cell.nbHChildren() << "'>";
941 for (Integer j = 0; j < cell.nbHChildren(); ++j) {
942 ofile << ' ' << cell.hChild(j).uniqueId();
943 }
944 ofile << "</child>";
945 }
946 ofile << "</amr>";
947 }
948 {
949 ghost_cells_layer1.clear();
950 for (Node node : cell.nodes()) {
951 for (Cell sub_cell : node.cells()) {
952 ghost_cells_layer1.add(sub_cell.uniqueId().asInt64());
953 }
954 }
955
956 {
957 // Trie la liste des mailles fantômes et retire les doublons.
958 std::sort(std::begin(ghost_cells_layer1), std::end(ghost_cells_layer1));
959 auto new_end = std::unique(std::begin(ghost_cells_layer1), std::end(ghost_cells_layer1));
960 ghost_cells_layer1.resize(arcaneCheckArraySize(new_end - std::begin(ghost_cells_layer1)));
961 ofile << "<ghost1 count='" << ghost_cells_layer1.size() << "'>";
962 for (auto j : ghost_cells_layer1)
963 ofile << ' ' << j;
964 ofile << "</ghost1>\n";
965 }
966 }
967 ofile << "</cell>\n";
968 }
969 ofile << "</cells>\n";
970 }
971
972 // Sauve les groupes
973
974 {
975 ofile << "<groups>\n";
976 // Trie les groupes par ordre alphabétique pour être certains qu'ils sont
977 // toujours écrits dans le même ordre.
978 std::map<String, ItemGroup> sorted_groups;
979 for (ItemGroupCollection::Enumerator i_group(mesh->groups()); ++i_group;) {
980 const ItemGroup& group = *i_group;
981 if (group.isLocalToSubDomain())
982 continue;
983 sorted_groups.insert(std::make_pair(group.name(), group));
984 }
985 for (const auto& [name, group] : sorted_groups) {
986 ofile << "<group name='" << group.name()
987 << "' kind='" << itemKindName(group.itemKind())
988 << "' count='" << group.size() << "'>\n";
989 ENUMERATE_ (Item, i_item, group) {
990 ofile << ' ' << i_item->uniqueId();
991 }
992 ofile << "\n</group>\n";
993 }
994 ofile << "</groups>\n";
995 }
996
997 // Sauve les interfaces liées
998 {
999 ofile << "<tied-interfaces>\n";
1000 TiedInterfaceCollection tied_interfaces(mesh->tiedInterfaces());
1001 for (TiedInterfaceCollection::Enumerator itied(tied_interfaces); ++itied;) {
1002 ITiedInterface* interface = *itied;
1003 FaceGroup slave_group = interface->slaveInterface();
1004 FaceGroup master_group = interface->masterInterface();
1005 ofile << "<tied-interface master_name='" << master_group.name()
1006 << "' slave_name='" << slave_group.name() << "'>\n";
1007 TiedInterfaceNodeList tied_nodes(interface->tiedNodes());
1008 TiedInterfaceFaceList tied_faces(interface->tiedFaces());
1009 ENUMERATE_FACE (iface, master_group) {
1010 Face face = *iface;
1011 //FaceVectorView slave_faces = face.slaveFaces();
1012 ofile << "<master-face uid='" << face.uniqueId() << "'>\n";
1013 for (Integer zz = 0, zs = tied_nodes[iface.index()].size(); zz < zs; ++zz) {
1014 TiedNode tn = tied_nodes[iface.index()][zz];
1015 ofile << "<node uid='" << tn.node().uniqueId() << "' iso='" << tn.isoCoordinates() << "' />\n";
1016 }
1017 for (Integer zz = 0, zs = tied_faces[iface.index()].size(); zz < zs; ++zz) {
1018 TiedFace tf = tied_faces[iface.index()][zz];
1019 ofile << "<face uid='" << tf.face().uniqueId() << "'/>\n";
1020 }
1021 ofile << "</master-face>\n";
1022 }
1023 ofile << "</tied-interface>\n";
1024 }
1025 ofile << "</tied-interfaces>\n";
1026 }
1027 ofile << "</mesh-connectivity>\n";
1028}
1029
1030/*---------------------------------------------------------------------------*/
1031/*---------------------------------------------------------------------------*/
1032
1033/*---------------------------------------------------------------------------*/
1034/*---------------------------------------------------------------------------*/
1035
1036class MeshUtilsCheckConnectivity
1037{
1038 public:
1039
1040 class ItemInternalXml
1041 {
1042 public:
1043
1044 ItemInternalXml() {}
1045 explicit ItemInternalXml(Item item)
1046 : m_item(item)
1047 {}
1048
1049 public:
1050
1051 bool operator<(const ItemInternalXml& i2) const
1052 {
1053 return m_item.uniqueId() < i2.m_item.uniqueId();
1054 }
1055 bool operator<(Int64 uid) const
1056 {
1057 return m_item.uniqueId() < uid;
1058 }
1059
1060 public:
1061
1062 Item m_item;
1063 XmlNode m_element;
1064 };
1065 typedef std::map<Int64, ItemInternalXml> ItemInternalXmlMap;
1066
1067 public:
1068
1069 MeshUtilsCheckConnectivity(IMesh* mesh, const XmlNode& doc_node, bool check_sub_domain)
1070 : m_mesh(mesh)
1071 , m_doc_node(doc_node)
1072 , m_has_error(false)
1073 , m_check_sub_domain(check_sub_domain)
1074 {
1075 }
1076
1077 public:
1078
1079 void doCheck();
1080
1081 public:
1082
1083 IMesh* m_mesh;
1084 XmlNode m_doc_node;
1085 bool m_has_error;
1086 bool m_check_sub_domain;
1087 ItemInternalXmlMap m_nodes_internal;
1088 ItemInternalXmlMap m_edges_internal;
1089 ItemInternalXmlMap m_faces_internal;
1090 ItemInternalXmlMap m_cells_internal;
1091 Int64UniqueArray m_items_unique_id;
1092
1093 private:
1094
1095 /*void _sortByUniqueIds(eItemKind ik,Array<ItemInternalXml>& items_internal)
1096 {
1097 ItemGroup all_items(m_mesh->allItems(ik));
1098 items_internal.resize(all_items.size());
1099
1100 Integer index = 0;
1101 ENUMERATE_ITEM(i,all_items){
1102 const Item& item = *i;
1103 items_internal[index].m_item = item.internal();
1104 ++index;
1105 }
1106 std::sort(items_internal.begin(),items_internal.end());
1107 }*/
1108 void _read(eItemKind ik, ItemInternalXmlMap& items_internal,
1109 XmlNode root_node, const String& lower_case_kind_name);
1110
1111 /*ItemInternalXml* _find(Array<ItemInternalXml>& items_internal,Integer uid)
1112 {
1113 ItemInternalXmlIterator z = std::lower_bound(items_internal.begin(),items_internal.end(),uid);
1114 if (z==items_internal.end())
1115 return 0;
1116 ItemInternalXml* ixml = &(*z);
1117 if (ixml->m_item->uniqueId()!=uid)
1118 return 0;
1119 return ixml;
1120 //cout << "NOT IMPLEMENTED!\n";
1121 //return 0;
1122 }*/
1123};
1124
1125/*---------------------------------------------------------------------------*/
1126/*---------------------------------------------------------------------------*/
1127
1128void MeshUtils::
1129checkMeshConnectivity(IMesh* mesh, const XmlNode& doc_node, bool check_sub_domain)
1130{
1131 if (!mesh)
1132 return;
1133 MeshUtilsCheckConnectivity v(mesh, doc_node, check_sub_domain);
1134 v.doCheck();
1135}
1136
1137void MeshUtils::
1138checkMeshConnectivity(IMesh* mesh, const String& file_name, bool check_sub_domain)
1139{
1140 ITraceMng* tm = mesh->traceMng();
1142 //IXmlDocumentHolder* doc = io_mng->parseXmlFile(file_name);
1143 XmlNode root = doc->documentNode();
1144 checkMeshConnectivity(mesh, root, check_sub_domain);
1145}
1146
1147void MeshUtilsCheckConnectivity::
1148_read(eItemKind ik, ItemInternalXmlMap& items_internal, XmlNode root_node,
1149 const String& lower_case_kind_name)
1150{
1151 ITraceMng* trace = m_mesh->traceMng();
1152
1153 //_sortByUniqueIds(ik,items_internal);
1154
1155 String ustr_uid("uid");
1156 String ustr_cells("cells");
1157 String ustr_count("count");
1158 String ustr_nodes("nodes");
1159 String ustr_ghost1("ghost1");
1160
1161 String kind_name(itemKindName(ik));
1162
1163 ENUMERATE_ITEM (iitem, m_mesh->itemFamily(ik)->allItems()) {
1164 Item item = *iitem;
1165 ItemInternalXml ixml(item);
1166 items_internal.insert(ItemInternalXmlMap::value_type(item.uniqueId().asInt64(), ixml));
1167 }
1168
1169#ifdef ARCANE_DEBUG_MESH
1170 for (Integer i = 0; i < items_internal.size(); ++i) {
1171 const ItemInternalXml& item_xml = items_internal[i];
1172 trace->info() << "Item " << kind_name << ":" << item_xml.m_item->uniqueId()
1173 << ' ' << i << ' ' << item_xml.m_item;
1174 }
1175#endif
1176
1177 XmlNodeList xml_items(root_node.children(lower_case_kind_name));
1178 for (const auto& xml_node : xml_items) {
1179 Integer uid = xml_node.attr(ustr_uid).valueAsInteger();
1180 ItemInternalXmlMap::iterator iixml = items_internal.find(uid);
1181 if (iixml != items_internal.end()) {
1182 iixml->second.m_element = xml_node;
1183 }
1184#if 0
1185 ItemInternalXml* ixml = _find(items_internal,uid);
1186 if (ixml){
1187 ixml->m_element = xml_node;
1188#ifdef ARCANE_DEBUG_MESH
1189 trace->info() << "FOUND " << uid << ' ' << z->m_item->uniqueId() << ' ' << z->m_element.name()
1190 << ' ' << z->m_item;
1191#endif
1192 }
1193#ifdef ARCANE_DEBUG_MESH
1194 else
1195 trace->info() << "FOUND " << uid << " NOT HERE";
1196#endif
1197#endif
1198 }
1199
1200 Int32UniqueArray local_ids;
1201 local_ids.reserve(100);
1202 for (ItemInternalXmlMap::const_iterator i(items_internal.begin()); i != items_internal.end(); ++i) {
1203 const ItemInternalXml& item_xml = i->second;
1204 Item item = item_xml.m_item;
1205 const XmlNode& xitem = item_xml.m_element;
1206 if (xitem.null()) {
1207 trace->error() << "Item " << kind_name << ":" << item.uniqueId()
1208 << "inconnu dans le maillage de référence";
1209 m_has_error = true;
1210 continue;
1211 }
1212 if (ik != IK_Node) {
1213 ItemWithNodes item_with_node(item);
1214 XmlNode xitem_node = xitem.child(ustr_nodes);
1215 Integer ref_nb_node = xitem_node.attr(ustr_count).valueAsInteger();
1216 Integer nb_node = item_with_node.nbNode();
1217 if (ref_nb_node != nb_node) {
1218 trace->error() << "Item " << kind_name << ":" << item.uniqueId()
1219 << ": nombre de nœuds (" << nb_node << ") "
1220 << "différent du référentiel (" << ref_nb_node << ")";
1221 m_has_error = true;
1222 continue;
1223 }
1224
1225 m_items_unique_id.reserve(ref_nb_node);
1226 String s = xitem_node.value();
1227 _stringToIds(s, m_items_unique_id);
1228 bool is_bad = false;
1229 for (NodeEnumerator i_node(item_with_node.nodes()); i_node(); ++i_node) {
1230 if (m_items_unique_id[i_node.index()] != i_node->uniqueId()) {
1231 is_bad = true;
1232 break;
1233 }
1234 }
1235 if (is_bad) {
1236 m_has_error = true;
1237 OStringStream ostr;
1238 ostr() << "Item " << kind_name << ":" << item.uniqueId()
1239 << ": nœuds (";
1240 for (NodeEnumerator i_node(item_with_node.nodes()); i_node(); ++i_node) {
1241 ostr() << ' ' << i_node->uniqueId();
1242 }
1243 ostr() << ") différents du référentiel (" << s << ")";
1244 trace->error() << ostr.str();
1245 }
1246 }
1247 if (item.isOwn()) {
1248 // Si c'est une maille, vérifier si les mailles qui devraient être
1249 // des fantômes sont présentes dans le maillage.
1250 // Si c'est un nœud, vérifier si les mailles autour de ce nœud
1251 // sont présentes dans le maillage.
1252 XmlNode elem;
1253 if (ik == IK_Cell)
1254 elem = xitem.child(ustr_ghost1);
1255 else if (ik == IK_Node)
1256 elem = xitem.child(ustr_cells);
1257 if (!elem.null()) {
1258 _stringToIds(elem.value(), m_items_unique_id);
1259 local_ids.resize(m_items_unique_id.size());
1260 m_mesh->cellFamily()->itemsUniqueIdToLocalId(local_ids, m_items_unique_id, false);
1261 StringBuilder not_found;
1262 bool has_not_found = false;
1263 for (Integer uui = 0, uuis = m_items_unique_id.size(); uui < uuis; ++uui) {
1264 if (local_ids[uui] == NULL_ITEM_ID) {
1265 not_found += " ";
1266 not_found += m_items_unique_id[uui];
1267 m_has_error = true;
1268 has_not_found = true;
1269 }
1270 }
1271 if (has_not_found) {
1272 if (ik == IK_Cell)
1273 trace->info() << "ERREUR : Une ou plusieurs mailles fantômes de la maille "
1274 << ItemPrinter(item) << " ne sont pas dans le sous-domaine"
1275 << " ref='" << elem.value() << "' not_found='" << not_found << '\'';
1276 else if (ik == IK_Node) {
1277 trace->info() << "ERREUR : Une ou plusieurs mailles avec le nœud "
1278 << ItemPrinter(item) << " ne sont pas dans le sous-domaine"
1279 << " ref='" << elem.value() << "' not_found='" << not_found << '\'';
1280 }
1281 }
1282 }
1283 }
1284 }
1285}
1286
1287/*---------------------------------------------------------------------------*/
1288/*---------------------------------------------------------------------------*/
1289
1290/*---------------------------------------------------------------------------*/
1291/*---------------------------------------------------------------------------*/
1292
1293void MeshUtilsCheckConnectivity::
1294doCheck()
1295{
1296 ITraceMng* trace = m_mesh->traceMng();
1297
1298 trace->info() << "Vérification de la connectivité du maillage checkMeshConnectivity()";
1299
1300 XmlNode root_node = m_doc_node.child(String("mesh-connectivity"));
1301 if (!root_node) {
1302 trace->warning() << "Fichier de connectivité incorrect";
1303 return;
1304 }
1305 XmlNode nodes_root = root_node.child("nodes");
1306 XmlNode faces_root = root_node.child("faces");
1307 XmlNode cells_root = root_node.child("cells");
1308
1309 _read(IK_Node, m_nodes_internal, nodes_root, "node");
1310 _read(IK_Face, m_faces_internal, faces_root, "face");
1311 _read(IK_Cell, m_cells_internal, cells_root, "cell");
1312
1313 String ustr_groups("groups");
1314 String ustr_group("group");
1315 String ustr_count("count");
1316
1317 XmlNode groups_root = root_node.child(ustr_groups);
1318 for (ItemGroupCollection::Enumerator i_group(m_mesh->groups()); ++i_group;) {
1319 const ItemGroup& group = *i_group;
1320 if (group.isLocalToSubDomain() || group.isOwn())
1321 continue;
1322 XmlNode group_elem = groups_root.childWithNameAttr(ustr_group, String(group.name()));
1323 if (group_elem.null()) {
1324 m_has_error = true;
1325 trace->error() << "Unable to find group <" << group.name()
1326 << "> in reference file";
1327 continue;
1328 }
1329 Integer size = group_elem.attr(ustr_count).valueAsInteger();
1330 m_items_unique_id.reserve(size);
1331 _stringToIds(group_elem.value(), m_items_unique_id);
1332 Integer ref_size = m_items_unique_id.size();
1333 if (ref_size != size) {
1334 trace->error() << "Number of items in group <" << group.name()
1335 << "> (" << size << " different than reference (" << ref_size;
1336 }
1337 // TODO: vérifier que les toutes les entités du groupe dans le maillage
1338 // de référence sont aussi dans le groupe correspondant de ce maillage.
1339 }
1340
1341 if (m_has_error) {
1342 trace->fatal() << "Error(s) while checking mesh";
1343 }
1344}
1345
1346/*---------------------------------------------------------------------------*/
1347/*---------------------------------------------------------------------------*/
1348
1349/*---------------------------------------------------------------------------*/
1350/*---------------------------------------------------------------------------*/
1351
1352void MeshUtils::
1353checkMeshProperties(IMesh* mesh, bool is_sorted, bool has_no_hole, bool check_faces)
1354{
1355 if (!mesh)
1356 return;
1357 if (has_no_hole)
1358 throw NotImplementedException(A_FUNCINFO, "Has no hole");
1359
1360 ITraceMng* trace = mesh->traceMng();
1361 bool has_error = false;
1362 if (is_sorted) {
1363 //for( Integer iki=0; iki<NB_ITEM_KIND; ++iki ){
1364 // eItemKind ik = static_cast<eItemKind>(iki);
1365 for (IItemFamilyCollection::Enumerator i(mesh->itemFamilies()); ++i;) {
1366 eItemKind ik = (*i)->itemKind();
1367 if (!check_faces && ik == IK_Face)
1368 continue;
1369 // Il est normal que les particules ne soient pas triées
1370 if (ik == IK_Particle)
1371 continue;
1372 //ItemGroup all_items = mesh->itemFamily(ik)->allItems();
1373 ItemGroup all_items = (*i)->allItems();
1374 Item last_item;
1375 ENUMERATE_ITEM (iitem, all_items) {
1376 Item item = *iitem;
1377
1378 if (!last_item.null() && (last_item.uniqueId() >= item.uniqueId() || last_item.localId() >= item.localId())) {
1379 trace->error() << "Item not sorted " << ItemPrinter(item, ik)
1380 << " Last item " << ItemPrinter(last_item, ik);
1381 has_error = true;
1382 }
1383 last_item = item;
1384 }
1385 }
1386 }
1387 if (has_error) {
1388 ARCANE_FATAL("Missing required mesh properties (sorted and/or no hole)");
1389 }
1390}
1391
1392/*---------------------------------------------------------------------------*/
1393/*---------------------------------------------------------------------------*/
1394
1395void MeshUtils::
1396printItems(std::ostream& ostr, const String& name, ItemGroup item_group)
1397{
1398 ostr << " ------- " << name << '\n';
1399 ENUMERATE_ITEM (iitem, item_group) {
1400 ostr << FullItemPrinter((*iitem)) << "\n";
1401 }
1402}
1403
1404/*---------------------------------------------------------------------------*/
1405/*---------------------------------------------------------------------------*/
1406
1407bool MeshUtils::
1408reorderNodesOfFace(Int64ConstArrayView before_ids, Int64ArrayView after_ids)
1409{
1410 // \a true s'il faut réorienter les faces pour que leur orientation
1411 // soit indépendante du partitionnement du maillage initial.
1412 bool need_swap_orientation = false;
1413 Integer min_node_index = 0;
1414 Integer nb_node = before_ids.size();
1415
1416 // Traite directement le cas des arêtes
1417 if (nb_node == 2) {
1418 if (before_ids[0] < before_ids[1]) {
1419 after_ids[0] = before_ids[0];
1420 after_ids[1] = before_ids[1];
1421 return false;
1422 }
1423 after_ids[0] = before_ids[1];
1424 after_ids[1] = before_ids[0];
1425 return true;
1426 }
1427
1428 // L'algorithme suivant oriente les faces en tenant compte uniquement
1429 // de l'ordre de la numérotation de ces noeuds. Si cet ordre est
1430 // conservé lors du partitionnement, alors l'orientation des faces
1431 // sera aussi conservée.
1432
1433 // L'algorithme est le suivant :
1434 // - Recherche le noeud n de plus petit indice.
1435 // - Recherche n-1 et n+1 les indices de ses 2 noeuds voisins.
1436 // - Si (n+1) est inférieur à (n-1), l'orientation n'est pas modifiée.
1437 // - Si (n+1) est supérieur à (n-1), l'orientation est inversée.
1438
1439 // Recherche le noeud de plus petit indice
1440
1441 Int64 min_node = INT64_MAX;
1442 for (Integer k = 0; k < nb_node; ++k) {
1443 Int64 id = before_ids[k];
1444 if (id < min_node) {
1445 min_node = id;
1446 min_node_index = k;
1447 }
1448 }
1449 Int64 next_node = before_ids[(min_node_index + 1) % nb_node];
1450 Int64 prev_node = before_ids[(min_node_index + (nb_node - 1)) % nb_node];
1451 Integer incr = 0;
1452 Integer incr2 = 0;
1453 if (next_node == min_node) {
1454 next_node = before_ids[(min_node_index + (nb_node + 2)) % nb_node];
1455 incr = 1;
1456 }
1457 if (prev_node == min_node) {
1458 prev_node = before_ids[(min_node_index + (nb_node - 2)) % nb_node];
1459 incr2 = nb_node - 1;
1460 }
1461 if (next_node > prev_node)
1462 need_swap_orientation = true;
1463 if (need_swap_orientation) {
1464 for (Integer k = 0; k < nb_node; ++k) {
1465 Integer index = (nb_node - k + min_node_index + incr) % nb_node;
1466 after_ids[k] = before_ids[index];
1467 }
1468 }
1469 else {
1470 for (Integer k = 0; k < nb_node; ++k) {
1471 Integer index = (k + min_node_index + incr2) % nb_node;
1472 after_ids[k] = before_ids[index];
1473 }
1474 }
1475 return need_swap_orientation;
1476}
1477
1478/*---------------------------------------------------------------------------*/
1479/*---------------------------------------------------------------------------*/
1480
1481bool MeshUtils::
1482reorderNodesOfFace2(Int64ConstArrayView nodes_unique_id, IntegerArrayView new_index)
1483{
1484 // \a true s'il faut réorienter les faces pour que leur orientation
1485 // soit indépendante du partitionnement du maillage initial.
1486 bool need_swap_orientation = false;
1487 Integer min_node_index = 0;
1488 Integer nb_node = nodes_unique_id.size();
1489
1490 // Traite directement le cas des arêtes
1491 if (nb_node == 2) {
1492 if (nodes_unique_id[0] < nodes_unique_id[1]) {
1493 new_index[0] = 0;
1494 new_index[1] = 1;
1495 return false;
1496 }
1497 new_index[0] = 1;
1498 new_index[1] = 0;
1499 return true;
1500 }
1501
1502 // L'algorithme suivant oriente les faces en tenant compte uniquement
1503 // de l'ordre de la numérotation de ces noeuds. Si cet ordre est
1504 // conservé lors du partitionnement, alors l'orientation des faces
1505 // sera aussi conservée.
1506
1507 // L'algorithme est le suivant :
1508 // - Recherche le noeud n de plus petit indice.
1509 // - Recherche n-1 et n+1 les indices de ses 2 noeuds voisins.
1510 // - Si (n+1) est inférieur à (n-1), l'orientation n'est pas modifiée.
1511 // - Si (n+1) est supérieur à (n-1), l'orientation est inversée.
1512
1513 // Recherche le noeud de plus petit indice
1514
1515 Int64 min_node = INT64_MAX;
1516 for (Integer k = 0; k < nb_node; ++k) {
1517 Int64 id = nodes_unique_id[k];
1518 if (id < min_node) {
1519 min_node = id;
1520 min_node_index = k;
1521 }
1522 }
1523 Int64 next_node = nodes_unique_id[(min_node_index + 1) % nb_node];
1524 Int64 prev_node = nodes_unique_id[(min_node_index + (nb_node - 1)) % nb_node];
1525 Integer incr = 0;
1526 Integer incr2 = 0;
1527 if (next_node == min_node) {
1528 next_node = nodes_unique_id[(min_node_index + 2) % nb_node];
1529 incr = 1;
1530 }
1531 if (prev_node == min_node) {
1532 prev_node = nodes_unique_id[(min_node_index + (nb_node - 2)) % nb_node];
1533 incr2 = nb_node - 1;
1534 }
1535 if (next_node > prev_node)
1536 need_swap_orientation = true;
1537 if (need_swap_orientation) {
1538 for (Integer k = 0; k < nb_node; ++k) {
1539 Integer index = (nb_node - k + min_node_index + incr) % nb_node;
1540 new_index[k] = index;
1541 }
1542 }
1543 else {
1544 for (Integer k = 0; k < nb_node; ++k) {
1545 Integer index = (k + min_node_index + incr2) % nb_node;
1546 new_index[k] = index;
1547 }
1548 }
1549 return need_swap_orientation;
1550}
1551
1552/*---------------------------------------------------------------------------*/
1553/*---------------------------------------------------------------------------*/
1554
1555Face MeshUtils::
1556getFaceFromNodesLocalId(Node node, Int32ConstArrayView face_nodes_local_id)
1557{
1558 Integer n = face_nodes_local_id.size();
1559 for (Integer i = 0, s = node.nbFace(); i < s; ++i) {
1560 Face f(node.face(i));
1561 Integer fn = f.nbNode();
1562 if (fn == n) {
1563 bool same_face = true;
1564 for (Integer zz = 0; zz < n; ++zz)
1565 if (f.node(zz).localId() != face_nodes_local_id[zz]) {
1566 same_face = false;
1567 break;
1568 }
1569 if (same_face)
1570 return f;
1571 }
1572 }
1573 return Face();
1574}
1575
1576/*---------------------------------------------------------------------------*/
1577/*---------------------------------------------------------------------------*/
1578
1579Face MeshUtils::
1580getFaceFromNodesUniqueId(Node node, Int64ConstArrayView face_nodes_unique_id)
1581{
1582 Integer n = face_nodes_unique_id.size();
1583 for (Integer i = 0, s = node.nbFace(); i < s; ++i) {
1584 Face f(node.face(i));
1585 Integer fn = f.nbNode();
1586 if (fn == n) {
1587 bool same_face = true;
1588 for (Integer zz = 0; zz < n; ++zz)
1589 if (f.node(zz).uniqueId() != face_nodes_unique_id[zz]) {
1590 same_face = false;
1591 break;
1592 }
1593 if (same_face)
1594 return f;
1595 }
1596 }
1597 return Face();
1598}
1599
1600/*---------------------------------------------------------------------------*/
1601/*---------------------------------------------------------------------------*/
1602
1603void MeshUtils::
1604removeItemAndKeepOrder(Int32ArrayView items, Int32 local_id)
1605{
1606 Integer n = items.size();
1607 if (n <= 0)
1608 ARCANE_FATAL("Can not remove item lid={0} because list is empty", local_id);
1609
1610 --n;
1611 if (n == 0) {
1612 if (items[0] == local_id)
1613 return;
1614 }
1615 else {
1616 // Si l'élément est le dernier, ne fait rien.
1617 if (items[n] == local_id)
1618 return;
1619 for (Integer i = 0; i < n; ++i) {
1620 if (items[i] == local_id) {
1621 for (Integer z = i; z < n; ++z)
1622 items[z] = items[z + 1];
1623 return;
1624 }
1625 }
1626 }
1627 // TODO: Il faut activer cela mais pour l'instant cela fait planter un test.
1628 //ARCANE_FATAL("No entity with local_id={0} found in list {1}",local_id,items);
1629}
1630
1631/*---------------------------------------------------------------------------*/
1632/*---------------------------------------------------------------------------*/
1633
1634void MeshUtils::
1635shrinkMeshGroups(IMesh* mesh)
1636{
1637 auto f = [&](ItemGroup& group) {
1638 group.internal()->shrinkMemory();
1639 };
1640 meshvisitor::visitGroups(mesh, f);
1641}
1642
1643/*---------------------------------------------------------------------------*/
1644/*---------------------------------------------------------------------------*/
1645
1646Int64 MeshUtils::
1647printMeshGroupsMemoryUsage(IMesh* mesh, Int32 print_level)
1648{
1649 ITraceMng* tm = mesh->traceMng();
1650 Int64 total_capacity = 0;
1651 Int64 total_computed_capacity = 0;
1652 auto f = [&](ItemGroup& group) {
1653 ItemGroupImpl* p = group.internal();
1654 // Attention à bien prendre la taille du groupe via \a p
1655 // car sinon pour un groupe calculé on le reconstruit.
1656 Int64 c = p->capacity();
1657 bool is_computed = p->hasComputeFunctor();
1658 total_capacity += c;
1659 if (is_computed)
1660 total_computed_capacity += c;
1661 if (print_level >= 1)
1662 tm->info() << "GROUP Name=" << group.name() << " computed?=" << p->hasComputeFunctor()
1663 << " nb_ref=" << p->nbRef() << " size=" << p->size()
1664 << " capacity=" << c;
1665 };
1666 meshvisitor::visitGroups(mesh, f);
1667 tm->info() << "MeshGroupsMemoryUsage: capacity = " << total_capacity
1668 << " computed_capacity=" << total_computed_capacity;
1669 return total_capacity * sizeof(Int32);
1670}
1671
1672/*---------------------------------------------------------------------------*/
1673/*---------------------------------------------------------------------------*/
1674
1675void MeshUtils::
1676dumpSynchronizerTopologyJSON(IVariableSynchronizer* var_syncer, const String& filename)
1677{
1678 IParallelMng* pm = var_syncer->parallelMng();
1679 ITraceMng* tm = pm->traceMng();
1680 Int32 nb_rank = pm->commSize();
1681 Int32 my_rank = pm->commRank();
1682 Int32ConstArrayView comm_ranks = var_syncer->communicatingRanks();
1683
1684 tm->info(4) << "Dumping VariableSynchronizerTopology filename=" << filename;
1685 Int32 nb_comm_rank = comm_ranks.size();
1686
1687 UniqueArray<Int32> nb_items_by_rank(nb_comm_rank);
1688 for (Integer i = 0; i < nb_comm_rank; ++i)
1689 nb_items_by_rank[i] = var_syncer->sharedItems(i).size();
1690
1691 JSONWriter json_writer(JSONWriter::FormatFlags::None);
1692 json_writer.beginObject();
1693
1694 if (my_rank == 0) {
1695 UniqueArray<Int32> all_nb_comm_ranks(nb_rank);
1696 pm->gather(Int32ConstArrayView(1, &nb_comm_rank), all_nb_comm_ranks, 0);
1697 json_writer.write("NbNeighbor", all_nb_comm_ranks);
1698
1699 {
1700 UniqueArray<Int32> all_neighbor_ranks;
1701 pm->gatherVariable(comm_ranks, all_neighbor_ranks, 0);
1702 json_writer.write("NeighborsRank", all_neighbor_ranks);
1703 }
1704 {
1705 UniqueArray<Int32> all_nb_items_by_rank;
1706 pm->gatherVariable(nb_items_by_rank, all_nb_items_by_rank, 0);
1707 json_writer.write("NeighborsSize", all_nb_items_by_rank);
1708 }
1709 }
1710 else {
1711 pm->gather(Int32ConstArrayView(1, &nb_comm_rank), {}, 0);
1712 UniqueArray<Int32> empty_array;
1713 pm->gatherVariable(comm_ranks, empty_array, 0);
1714 pm->gatherVariable(nb_items_by_rank, empty_array, 0);
1715 }
1716
1717 json_writer.endObject();
1718
1719 if (my_rank == 0) {
1720 std::ofstream ofile(filename.localstr());
1721 auto bytes = json_writer.getBuffer().bytes();
1722 ofile.write(reinterpret_cast<const char*>(bytes.data()), bytes.size());
1723 }
1724}
1725
1726/*---------------------------------------------------------------------------*/
1727/*---------------------------------------------------------------------------*/
1728
1729namespace
1730{
1731 class MyIdsToTest
1732 {
1733 public:
1734
1735 friend bool operator<(const MyIdsToTest& a, const MyIdsToTest& b)
1736 {
1737 return a.ids < b.ids;
1738 }
1739 static constexpr int MAX_SIZE = 16;
1740
1741 public:
1742
1743 std::array<Int32, MAX_SIZE> ids = {};
1744 };
1745
1746 void _computePatternOccurence(const ItemGroup& items, const String& message,
1748 {
1749 std::map<MyIdsToTest, Int32> occurence_map;
1750 Int32 nb_skipped = 0;
1751 ENUMERATE_ (Item, iitem, items) {
1752 Item item = *iitem;
1753 MyIdsToTest diff_ids;
1754
1755 Int32 index = 0;
1756 Int32 lid0 = 0;
1757 bool is_skipped = false;
1758 for (ItemLocalId sub_item : cty.items(item)) {
1759 if (index >= MyIdsToTest::MAX_SIZE) {
1760 is_skipped = true;
1761 break;
1762 }
1763 if (index == 0)
1764 lid0 = sub_item.localId();
1765 diff_ids.ids[index] = sub_item.localId() - lid0;
1766 //info() << " Cell lid=" << item.localId() << " I=" << index << " diff_lid=" << diff_ids.ids[index];
1767 ++index;
1768 }
1769 if (is_skipped)
1770 ++nb_skipped;
1771 else
1772 ++occurence_map[diff_ids];
1773 }
1774 ITraceMng* tm = items.mesh()->traceMng();
1775 tm->info() << "Occurence: " << message << " group=" << items.name()
1776 << " nb=" << items.size() << " map_size=" << occurence_map.size()
1777 << " nb_skipped=" << nb_skipped;
1778 }
1779} // namespace
1780
1781void MeshUtils::
1782computeConnectivityPatternOccurence(IMesh* mesh)
1783{
1785
1787
1788 _computePatternOccurence(mesh->allNodes(), "NodeCells", cty.nodeCell());
1789 _computePatternOccurence(mesh->allNodes(), "NodeFaces", cty.nodeFace());
1790 _computePatternOccurence(mesh->allFaces(), "FaceCells", cty.faceCell());
1791 _computePatternOccurence(mesh->allFaces(), "FaceNodes", cty.faceNode());
1792 _computePatternOccurence(mesh->allCells(), "CellNodes", cty.cellNode());
1793 _computePatternOccurence(mesh->allCells(), "CellFaces", cty.cellFace());
1794}
1795
1796/*---------------------------------------------------------------------------*/
1797/*---------------------------------------------------------------------------*/
1798
1799void MeshUtils::
1800markMeshConnectivitiesAsMostlyReadOnly(IMesh* mesh, RunQueue* queue, bool do_prefetch)
1801{
1802 if (!mesh)
1803 return;
1804 IVariableMng* vm = mesh->variableMng();
1805 VariableCollection used_variables = vm->usedVariables();
1806 const String tag_name = "ArcaneConnectivity";
1808
1809 // Les variables associées à la connectivité ont le tag 'ArcaneConnectivity'.
1810 for (VariableCollection::Enumerator iv(used_variables); ++iv;) {
1811 IVariable* v = *iv;
1812 if (!v->hasTag(tag_name))
1813 continue;
1814 if (v->meshHandle().meshOrNull() == mesh) {
1815 v->setAllocationInfo(alloc_info);
1816 if (do_prefetch)
1818 }
1819 }
1820}
1821
1822/*---------------------------------------------------------------------------*/
1823/*---------------------------------------------------------------------------*/
1824
1825impl::ItemBase MeshUtils::
1826findOneItem(IItemFamily* family, Int64 unique_id)
1827{
1828 ItemInternal* v = family->findOneItem(unique_id);
1829 if (v)
1830 return { v };
1831 return {};
1832}
1833
1834/*---------------------------------------------------------------------------*/
1835/*---------------------------------------------------------------------------*/
1836
1837impl::ItemBase MeshUtils::
1838findOneItem(IItemFamily* family, ItemUniqueId unique_id)
1839{
1840 ItemInternal* v = family->findOneItem(unique_id);
1841 if (v)
1842 return { v };
1843 return {};
1844}
1845
1846/*---------------------------------------------------------------------------*/
1847/*---------------------------------------------------------------------------*/
1848
1849namespace MeshUtils::impl
1850{
1851 //! Retourne le max des uniqueId() des entités de \a group
1852 Int64 _getMaxUniqueId(const ItemGroup& group, Int64 max_uid)
1853 {
1854 ENUMERATE_ (Item, iitem, group) {
1855 Item item = *iitem;
1856 if (max_uid < item.uniqueId())
1857 max_uid = item.uniqueId();
1858 }
1859 return max_uid;
1860 }
1861} // namespace MeshUtils::impl
1862
1863/*---------------------------------------------------------------------------*/
1864/*---------------------------------------------------------------------------*/
1865
1866ItemUniqueId MeshUtils::
1867getMaxItemUniqueIdCollective(IMesh* mesh)
1868{
1869 Int64 max_uid = NULL_ITEM_UNIQUE_ID;
1870 max_uid = impl::_getMaxUniqueId(mesh->allNodes(), max_uid);
1871 max_uid = impl::_getMaxUniqueId(mesh->allEdges(), max_uid);
1872 max_uid = impl::_getMaxUniqueId(mesh->allCells(), max_uid);
1873 max_uid = impl::_getMaxUniqueId(mesh->allFaces(), max_uid);
1874 Int64 global_max = mesh->parallelMng()->reduce(Parallel::ReduceMax, max_uid);
1875 return ItemUniqueId(global_max);
1876}
1877
1878/*---------------------------------------------------------------------------*/
1879/*---------------------------------------------------------------------------*/
1880
1881void MeshUtils::
1882checkUniqueIdsHashCollective(IItemFamily* family, IHashAlgorithm* hash_algo,
1883 const String& expected_hash, bool print_hash,
1884 bool include_ghost)
1885{
1886 ARCANE_CHECK_POINTER(family);
1887 ARCANE_CHECK_POINTER(hash_algo);
1888
1889 IParallelMng* pm = family->parallelMng();
1890 ITraceMng* tm = family->traceMng();
1891
1892 UniqueArray<Int64> own_items_uid;
1893 ItemGroup own_items_group = (include_ghost ? family->allItems() : family->allItems().own());
1894 ENUMERATE_ (Item, iitem, own_items_group) {
1895 Item item{ *iitem };
1896 own_items_uid.add(item.uniqueId());
1897 }
1898 UniqueArray<Int64> global_items_uid;
1899 pm->allGatherVariable(own_items_uid, global_items_uid);
1900 std::sort(global_items_uid.begin(), global_items_uid.end());
1901
1902 UniqueArray<Byte> hash_result;
1903 hash_algo->computeHash64(asBytes(global_items_uid.constSpan()), hash_result);
1904 String hash_str = Convert::toHexaString(hash_result);
1905 if (print_hash)
1906 tm->info() << "HASH_RESULT family=" << family->name()
1907 << " v=" << hash_str << " expected=" << expected_hash;
1908 if (!expected_hash.empty() && hash_str != expected_hash)
1909 ARCANE_FATAL("Bad hash for uniqueId() for family '{0}' v='{1}' expected='{2}'",
1910 family->fullName(), hash_str, expected_hash);
1911}
1912
1913/*---------------------------------------------------------------------------*/
1914/*---------------------------------------------------------------------------*/
1915
1916void MeshUtils::
1917fillUniqueIds(ItemVectorView items, Array<Int64>& uids)
1918{
1919 Integer nb_item = items.size();
1920 uids.resize(nb_item);
1921 ENUMERATE_ITEM (iitem, items)
1922 uids[iitem.index()] = iitem->uniqueId();
1923}
1924
1925/*---------------------------------------------------------------------------*/
1926/*---------------------------------------------------------------------------*/
1927
1928Int64 MeshUtils::
1929generateHashUniqueId(SmallSpan<const Int64> nodes_unique_id)
1930{
1931 // Tout les bits sont formées avec la fonction de hash.
1932 // Le uniqueId() généré doit toujours être positif
1933 // sauf pour l'entité nulle.
1934 Int32 nb_node = nodes_unique_id.size();
1935 if (nb_node == 0)
1936 return -1;
1937 using Hasher = IntegerHashFunctionT<Int64>;
1938 Int64 uid0 = nodes_unique_id[0];
1939 Int64 hash = Hasher::hashfunc(uid0);
1940 for (Int32 i = 1; i < nb_node; ++i) {
1941 Int64 next_hash = Hasher::hashfunc(nodes_unique_id[i]);
1942 hash ^= next_hash + 0x9e3779b9 + (hash << 6) + (hash >> 2);
1943 }
1944 Int64 new_uid = math::abs(hash);
1945 ARCANE_ASSERT(new_uid >= 0, ("UniqueId is not >= 0"));
1946 return new_uid;
1947}
1948
1949/*---------------------------------------------------------------------------*/
1950/*---------------------------------------------------------------------------*/
1951
1952void MeshUtils::
1953computeAndSetOwnerForNodes(IMesh* mesh)
1954{
1956 mesh->utilities()->computeAndSetOwnersForNodes();
1957}
1958
1959/*---------------------------------------------------------------------------*/
1960/*---------------------------------------------------------------------------*/
1961
1962void MeshUtils::
1963computeAndSetOwnerForEdges(IMesh* mesh)
1964{
1966 mesh->utilities()->computeAndSetOwnersForEdges();
1967}
1968
1969/*---------------------------------------------------------------------------*/
1970/*---------------------------------------------------------------------------*/
1971
1972void MeshUtils::
1973computeAndSetOwnerForFaces(IMesh* mesh)
1974{
1976 mesh->utilities()->computeAndSetOwnersForFaces();
1977}
1978
1979/*---------------------------------------------------------------------------*/
1980/*---------------------------------------------------------------------------*/
1981
1982} // End namespace Arcane
1983
1984/*---------------------------------------------------------------------------*/
1985/*---------------------------------------------------------------------------*/
#define ARCANE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Types et macros pour itérer sur les entités du maillage.
#define ENUMERATE_FACE(name, group)
Enumérateur générique d'un groupe de faces.
#define ENUMERATE_(type, name, group)
Enumérateur générique d'un groupe d'entité
#define ENUMERATE_ITEM(name, group)
Enumérateur générique d'un groupe de noeuds.
Fonctions mathématiques diverses.
Fonctions utilitaires sur le maillage.
Fonctions utilitaires sur les variables.
void prefetchVariableAsync(IVariable *var, const RunQueue *queue_or_null)
Pré-copie la mémoire associée à la variable var.
Integer size() const
Nombre d'éléments du vecteur.
Vue modifiable pour un tableau 2D.
constexpr Integer size() const noexcept
Retourne la taille du tableau.
Classe de base des vecteurs 1D de données.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void clear()
Supprime les éléments du tableau.
iterator begin()
Itérateur sur le premier élément du tableau.
void add(ConstReferenceType val)
Ajoute l'élément val à la fin du tableau.
Span< const T > constSpan() const
Vue constante sur ce tableau.
void reserve(Int64 new_capacity)
Réserve le mémoire pour new_capacity éléments.
iterator end()
Itérateur sur le premier élément après la fin du tableau.
Vue sur les informations des mailles.
Maille d'un maillage.
Definition Item.h:1214
Vue constante d'un tableau de type T.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
ARCANE_DEPRECATED_122 Int32 size() const
Nombre d'éléments de la première dimension.
Informations sur l'allocation d'une donnée.
Vue sur les informations des arêtes.
Arête d'une maille.
Definition Item.h:826
Cell cell(Int32 i) const
i-ème maille de l'arête
Definition Item.h:1631
Face face(Int32 i) const
i-ème face de l'arête
Definition Item.h:1625
Int32 nbFace() const
Nombre de faces connectées à l'arête.
Definition Item.h:907
Int32 nbNode() const
Nombre de sommets de l'arête.
Definition Item.h:904
Int32 nbCell() const
Nombre de mailles connectées à l'arête.
Definition Item.h:910
Vue sur les informations des faces.
Face d'une maille.
Definition Item.h:964
Cell frontCell() const
Maille devant la face (maille nulle si aucune).
Definition Item.h:1652
Cell cell(Int32 i) const
i-ème maille de la face
Definition Item.h:1665
Int32 nbCell() const
Nombre de mailles de la face (1 ou 2).
Definition Item.h:1042
Edge edge(Int32 i) const
i-ème arête de la face
Definition Item.h:1156
Int32 nbEdge() const
Nombre d'arêtes de la face.
Definition Item.h:1153
Cell backCell() const
Maille derrière la face (maille nulle si aucune).
Definition Item.h:1646
Informations sur le type à virgule flottante.
Definition FloatInfo.h:35
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
Interface d'un algorithme de hashage.
virtual void computeHash64(Span< const Byte > input, ByteArray &output)
Calcule la valeur du hash pour le tableau input.
Interface d'une famille d'entités.
Definition IItemFamily.h:84
virtual ItemGroup allItems() const =0
Groupe de toutes les entités.
virtual ItemInternal * findOneItem(Int64 unique_id)=0
Entité de numéro unique unique_id.
virtual IParallelMng * parallelMng() const =0
Gestionnaire de parallélisme associé
virtual String name() const =0
Nom de la famille.
virtual ITraceMng * traceMng() const =0
Gestionnaire de trace associé
virtual String fullName() const =0
Nom complet de la famille (avec celui du maillage).
Interface du gestionnaire de parallélisme pour un sous-domaine.
virtual void gatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf, Int32 rank)=0
Effectue un regroupement sur tous les processeurs.
virtual ITraceMng * traceMng() const =0
Gestionnaire de traces.
virtual Int32 commRank() const =0
Rang de cette instance dans le communicateur.
virtual void allGatherVariable(ConstArrayView< char > send_buf, Array< char > &recv_buf)=0
Effectue un regroupement sur tous les processeurs.
virtual Int32 commSize() const =0
Nombre d'instance dans le communicateur.
virtual void gather(ConstArrayView< char > send_buf, ArrayView< char > recv_buf, Int32 rank)=0
Effectue un regroupement sur un processeurs. Il s'agit d'une opération collective....
Interface du gestionnaire d'un sous-domaine.
Definition ISubDomain.h:74
virtual Int32 subDomainId() const =0
Numéro du sous-domaine associé à ce gestionnaire.
virtual IVariableMng * variableMng()=0
Retourne le gestionnaire de variables.
Interface d'un classe gérant une semi-conformité du maillage.
Interface du gestionnaire de traces.
virtual TraceMessage pinfo()=0
Flot pour un message d'information parallèle.
virtual TraceMessage error()=0
Flot pour un message d'erreur.
virtual TraceMessage info()=0
Flot pour un message d'information.
Interface du gestionnaire de variables.
virtual VariableCollection usedVariables()=0
Liste des variables utilisées.
Interface d'un service de synchronisation de variable.
virtual Int32ConstArrayView communicatingRanks()=0
Rangs des sous-domaines avec lesquels on communique.
virtual IParallelMng * parallelMng()=0
Gestionnaire parallèle associé
virtual Int32ConstArrayView sharedItems(Int32 index)=0
Liste des ids locaux des entités partagées avec un sous-domaine.
Interface d'une variable.
Definition IVariable.h:39
virtual bool hasTag(const String &tagname)=0
true si la variable possède le tag tagname
virtual void setAllocationInfo(const DataAllocationInfo &v)=0
Positionne les informations sur l'allocation.
virtual MeshHandle meshHandle() const =0
Maillage auquel est associé la variable.
static IXmlDocumentHolder * loadFromFile(const String &filename, ITraceMng *tm)
Charge un document XML.
Definition DomUtils.cc:445
Classe de base d'une vue sur une connectivité non structurée.
Classe de base pour les entités du maillage.
Integer nbEdge() const
Nombre d'arêtes de l'entité ou nombre d'arêtes connectés à l'entités (pour les noeuds).
ItemUniqueId uniqueId() const
Numéro unique de l'entité
Integer nbCell() const
Nombre de mailles connectées à l'entité (pour les noeuds, arêtes et faces).
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Integer nbFace() const
Nombre de faces de l'entité ou nombre de faces connectés à l'entités (pour les noeuds et arêtes).
Integer nbNode() const
Nombre de noeuds de l'entité
Vue sur une liste d'entités connectées à une autre.
virtual Integer nbRef() const
Nombre de références sur le groupe.
Integer size() const
Nombre d'entités du groupe.
Int64 capacity() const
Nombre d'éléments alloués.
bool hasComputeFunctor() const
Indique si le groupe est calculé
Groupe d'entités de maillage.
Definition ItemGroup.h:49
const String & name() const
Nom du groupe.
Definition ItemGroup.h:76
bool isLocalToSubDomain() const
Vrai si le groupe est local au sous-domaine.
Definition ItemGroup.h:225
ItemGroup own() const
Groupe équivalent à celui-ci mais contenant uniquement les éléments propres au sous-domaine.
Definition ItemGroup.cc:190
Index d'un Item dans une variable.
Definition ItemLocalId.h:41
Classe utilitaire pour imprimer les infos sur une entité.
Definition ItemPrinter.h:34
static eItemKind kind()
Genre de l'entité
Definition ItemTypes.h:624
Identifiant unique d'une entité.
Vue sur un vecteur d'entités.
Int32 size() const
Nombre d'éléments du vecteur.
Elément de maillage s'appuyant sur des noeuds (Edge,Face,Cell).
Definition Item.h:736
Node node(Int32 i) const
i-ème noeud de l'entité
Definition Item.h:791
Int32 nbNode() const
Nombre de noeuds de l'entité
Definition Item.h:788
Classe de base d'un élément de maillage.
Definition Item.h:83
constexpr Int32 localId() const
Identifiant local de l'entité dans le sous-domaine du processeur.
Definition Item.h:219
Int32 owner() const
Numéro du sous-domaine propriétaire de l'entité
Definition Item.h:238
ItemUniqueId uniqueId() const
Identifiant unique sur tous les domaines.
Definition Item.h:225
constexpr bool null() const
true si l'entité est nul (i.e. non connecté au maillage)
Definition Item.h:216
impl::ItemBase itemBase() const
Partie interne de l'entité.
Definition Item.h:369
IMesh * meshOrNull() const
Retourne le maillage associé à cette instance.
Informations générique sur les types d'une variable du maillage.
Vue sur les informations des noeuds.
Noeud d'un maillage.
Definition Item.h:582
Cell cell(Int32 i) const
i-ème maille du noeud
Definition Item.h:1616
CellConnectedListViewType cells() const
Liste des mailles du noeud.
Definition Item.h:692
constexpr Int32 nbFace() const
Nombre de faces connectées au noeud.
Definition Item.h:662
constexpr Int32 nbEdge() const
Nombre d'arêtes connectées au noeud.
Definition Item.h:659
Face face(Int32 i) const
i-ème face du noeud
Definition Item.h:1610
Edge edge(Int32 i) const
i-ème arête du noeud
Definition Item.h:1604
Int32 nbCell() const
Nombre de mailles connectées au noeud.
Definition Item.h:665
Classe gérant un vecteur réel de 3 dimensions.
Encapsulation d'un pointeur qui se détruit automatiquement.
Definition ScopedPtr.h:44
Vue d'un tableau d'éléments de type T.
Definition Span.h:802
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Definition Span.h:325
Constructeur de chaîne de caractère unicode.
String toString() const
Retourne la chaîne de caractères construite.
constexpr Span< const Byte > bytes() const ARCCORE_NOEXCEPT
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition StringView.h:96
Chaîne de caractères unicode.
Int64 length() const
Retourne la longueur de la chaîne.
Definition String.cc:339
const char * localstr() const
Retourne la conversion de l'instance dans l'encodage UTF-8.
Definition String.cc:228
bool empty() const
Vrai si la chaîne est vide (nulle ou "").
Definition String.cc:316
Face semi-conforme du maillage.
Definition TiedFace.h:34
Face face() const
Face soudée.
Definition TiedFace.h:51
Noeud semi-conforme du maillage.
Definition TiedNode.h:39
Node node() const
Noeud lié
Definition TiedNode.h:58
Real2 isoCoordinates() const
Coordonnées iso-barycentriques du noeud.
Definition TiedNode.h:61
Positionne une classe de message.
Formattage du flot en longueur.
Vecteur 1D de données avec sémantique par valeur (style STL).
Vue sur les connectivités standards d'un maillage non structuré.
Collection de variables.
Noeud d'un arbre DOM.
Definition XmlNode.h:51
ItemGroupT< Face > FaceGroup
Groupe de faces.
Definition ItemTypes.h:178
ItemEnumeratorT< Node > NodeEnumerator
Enumérateurs sur des noeuds.
Definition ItemTypes.h:254
MeshVariableScalarRefT< Node, Real3 > VariableNodeReal3
Grandeur au noeud de type coordonnées.
String toHexaString(ByteConstArrayView input)
Converti un tableau d'octet en sa représentation hexadécimale.
@ ReduceMax
Maximum des valeurs.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Array< Int64 > Int64Array
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:119
ArrayView< Int64 > Int64ArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:449
Integer arcaneCheckArraySize(unsigned long long size)
Vérifie que size peut être converti dans un 'Integer' pour servir de taille à un tableau....
UniqueArray< Int64 > Int64UniqueArray
Tableau dynamique à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:337
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:480
ArrayView< Integer > IntegerArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:455
bool operator<(const Item &item1, const Item &item2)
Compare deux entités.
Definition Item.h:551
ConstArrayView< ItemInternal * > ItemInternalList
Type de la liste interne des entités.
Definition ItemTypes.h:466
ConstArrayView< Int64 > Int64ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 64 bits.
Definition UtilsTypes.h:478
@ HostAndDeviceMostlyRead
Indique que la donnée sera utilisée à la fois sur accélérateur et sur CPU et qu'elle ne sera pas souv...
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:339
ArrayView< Int32 > Int32ArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:451
SharedMeshVariableScalarRefT< Node, Real3 > SharedVariableNodeReal3
Grandeur au noeud de type coordonnées.
eItemKind
Genre d'entité de maillage.
@ IK_Particle
Entité de maillage de genre particule.
@ IK_Node
Entité de maillage de genre noeud.
@ IK_Cell
Entité de maillage de genre maille.
@ IK_Face
Entité de maillage de genre face.
@ IK_Edge
Entité de maillage de genre arête.
const char * itemKindName(eItemKind kind)
Nom du genre d'entité.
Impl::SpanTypeFromSize< conststd::byte, SizeType >::SpanType asBytes(const SpanImpl< DataType, SizeType, Extent > &s)
Convertit la vue en un tableau d'octets non modifiables.
Definition Span.h:1028
Array< Int32 > Int32Array
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:121
@ Cell
Le maillage est AMR par maille.
Definition MeshKind.h:52
Collection< ITiedInterface * > TiedInterfaceCollection
Collection d'interfaces liées.
std::int32_t Int32
Type entier signé sur 32 bits.
Real y
deuxième composante du triplet
Real z
troisième composante du triplet
Real x
première composante du triplet